001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by * 009 *****************************************************************************/ 010 package org.picocontainer.defaults; 011 012 import java.util.ArrayList; 013 import java.util.List; 014 015 import org.picocontainer.ComponentAdapter; 016 import org.picocontainer.MutablePicoContainer; 017 import org.picocontainer.Parameter; 018 import org.picocontainer.tck.AbstractComponentAdapterTestCase; 019 import org.picocontainer.testmodel.NullLifecycle; 020 import org.picocontainer.testmodel.PersonBean; 021 import org.picocontainer.testmodel.PurseBean; 022 import org.picocontainer.testmodel.SimpleTouchable; 023 import org.picocontainer.testmodel.Touchable; 024 025 026 public class SetterInjectionComponentAdapterTestCase 027 extends AbstractComponentAdapterTestCase { 028 029 protected Class getComponentAdapterType() { 030 return SetterInjectionComponentAdapter.class; 031 } 032 033 protected ComponentAdapterFactory createDefaultComponentAdapterFactory() { 034 return new CachingComponentAdapterFactory(new SetterInjectionComponentAdapterFactory()); 035 } 036 037 protected ComponentAdapter prepDEF_verifyWithoutDependencyWorks(MutablePicoContainer picoContainer) { 038 return new SetterInjectionComponentAdapter(PersonBean.class, PersonBean.class, new Parameter[]{new ConstantParameter( 039 "Pico Container")}); 040 } 041 042 protected ComponentAdapter prepDEF_verifyDoesNotInstantiate(MutablePicoContainer picoContainer) { 043 picoContainer.registerComponentInstance("Pico Container"); 044 return new SetterInjectionComponentAdapter(DeadBody.class, DeadBody.class, new Parameter[]{ComponentParameter.DEFAULT}); 045 } 046 047 protected ComponentAdapter prepDEF_visitable() { 048 return new SetterInjectionComponentAdapter(PersonBean.class, PersonBean.class, new Parameter[]{new ConstantParameter( 049 "Pico Container")}); 050 } 051 052 protected ComponentAdapter prepSER_isSerializable(MutablePicoContainer picoContainer) { 053 picoContainer.registerComponentInstance("Pico Container"); 054 return new SetterInjectionComponentAdapter(PersonBean.class, PersonBean.class, new Parameter[]{ComponentParameter.DEFAULT}); 055 } 056 057 protected ComponentAdapter prepSER_isXStreamSerializable(MutablePicoContainer picoContainer) { 058 return prepSER_isSerializable(picoContainer); 059 } 060 061 protected ComponentAdapter prepDEF_isAbleToTakeParameters(MutablePicoContainer picoContainer) { 062 picoContainer.registerComponentInstance("Pico Container"); 063 picoContainer.registerComponentImplementation(PersonBean.class); 064 return picoContainer.registerComponent(new SetterInjectionComponentAdapter( 065 PurseBean.class, MoneyPurse.class, new Parameter[]{ 066 ComponentParameter.DEFAULT, new ConstantParameter(new Double(100.0))})); 067 } 068 069 public static class MoneyPurse 070 extends PurseBean { 071 double money; 072 073 public double getMoney() { 074 return money; 075 } 076 077 public void setMoney(double money) { 078 this.money = money; 079 } 080 } 081 082 protected ComponentAdapter prepVER_verificationFails(MutablePicoContainer picoContainer) { 083 picoContainer.registerComponentInstance("Pico Container"); 084 picoContainer.registerComponentImplementation(PersonBean.class); 085 return picoContainer.registerComponent(new SetterInjectionComponentAdapter( 086 PurseBean.class, MoneyPurse.class, new Parameter[]{ComponentParameter.DEFAULT})); 087 } 088 089 protected ComponentAdapter prepINS_createsNewInstances(MutablePicoContainer picoContainer) { 090 picoContainer.registerComponentInstance("Pico Container"); 091 return new SetterInjectionComponentAdapter(PersonBean.class, PersonBean.class, new Parameter[]{ComponentParameter.DEFAULT}); 092 } 093 094 public static class Ghost 095 extends PersonBean { 096 public Ghost() { 097 throw new VerifyError("test"); 098 } 099 } 100 101 protected ComponentAdapter prepINS_errorIsRethrown(MutablePicoContainer picoContainer) { 102 picoContainer.registerComponentInstance("Pico Container"); 103 return new SetterInjectionComponentAdapter(Ghost.class, Ghost.class, new Parameter[]{ComponentParameter.DEFAULT}); 104 } 105 106 public static class DeadBody 107 extends PersonBean { 108 public DeadBody() throws Exception { 109 throw new RuntimeException("test"); 110 } 111 } 112 113 protected ComponentAdapter prepINS_runtimeExceptionIsRethrown(MutablePicoContainer picoContainer) { 114 picoContainer.registerComponentInstance("Pico Container"); 115 return new SetterInjectionComponentAdapter(DeadBody.class, DeadBody.class, new Parameter[]{ComponentParameter.DEFAULT}); 116 } 117 118 public static class HidingPersion 119 extends PersonBean { 120 public HidingPersion() throws Exception { 121 throw new Exception("test"); 122 } 123 } 124 125 protected ComponentAdapter prepINS_normalExceptionIsRethrownInsidePicoInvocationTargetInitializationException( 126 MutablePicoContainer picoContainer) { 127 picoContainer.registerComponentInstance("Pico Container"); 128 return new SetterInjectionComponentAdapter( 129 HidingPersion.class, HidingPersion.class, new Parameter[]{ComponentParameter.DEFAULT}); 130 } 131 132 protected ComponentAdapter prepRES_dependenciesAreResolved(MutablePicoContainer picoContainer) { 133 picoContainer.registerComponentInstance("Pico Container"); 134 picoContainer.registerComponentImplementation(PersonBean.class); 135 return new SetterInjectionComponentAdapter(PurseBean.class, PurseBean.class, new Parameter[]{ComponentParameter.DEFAULT}); 136 } 137 138 public static class WealthyPerson 139 extends PersonBean { 140 PurseBean purse; 141 142 public PurseBean getPurse() { 143 return purse; 144 } 145 146 public void setPurse(PurseBean purse) { 147 this.purse = purse; 148 } 149 } 150 151 protected ComponentAdapter prepRES_failingVerificationWithCyclicDependencyException(MutablePicoContainer picoContainer) { 152 picoContainer.registerComponentInstance("Pico Container"); 153 picoContainer.registerComponentImplementation(PersonBean.class, WealthyPerson.class); 154 return picoContainer.registerComponent(new SetterInjectionComponentAdapter( 155 PurseBean.class, PurseBean.class, new Parameter[]{ComponentParameter.DEFAULT})); 156 } 157 158 protected ComponentAdapter prepRES_failingInstantiationWithCyclicDependencyException(MutablePicoContainer picoContainer) { 159 picoContainer.registerComponentInstance("Pico Container"); 160 picoContainer.registerComponentImplementation(PersonBean.class, WealthyPerson.class); 161 return picoContainer.registerComponent(new SetterInjectionComponentAdapter( 162 PurseBean.class, PurseBean.class, new Parameter[]{ComponentParameter.DEFAULT})); 163 } 164 165 public static class A { 166 private B b; 167 private String string; 168 private List list; 169 170 public void setB(B b) { 171 this.b = b; 172 } 173 174 public B getB() { 175 return b; 176 } 177 178 public String getString() { 179 return string; 180 } 181 182 public void setString(String string) { 183 this.string = string; 184 } 185 186 public List getList() { 187 return list; 188 } 189 190 public void setList(List list) { 191 this.list = list; 192 } 193 } 194 195 public static class B { 196 } 197 198 public void testAllUnsatisfiableDependenciesAreSignalled() { 199 SetterInjectionComponentAdapter aAdapter = new SetterInjectionComponentAdapter("a", A.class, null); 200 SetterInjectionComponentAdapter bAdapter = new SetterInjectionComponentAdapter("b", B.class, null); 201 202 MutablePicoContainer pico = new DefaultPicoContainer(); 203 pico.registerComponent(bAdapter); 204 pico.registerComponent(aAdapter); 205 206 try { 207 aAdapter.getComponentInstance(pico); 208 } catch (UnsatisfiableDependenciesException e) { 209 assertTrue(e.getUnsatisfiableDependencies().contains(List.class)); 210 assertTrue(e.getUnsatisfiableDependencies().contains(String.class)); 211 } 212 } 213 214 public static class C { 215 private B b; 216 private List l; 217 private final boolean asBean; 218 219 public C() { 220 asBean = true; 221 } 222 223 public C(B b) { 224 this.l = new ArrayList(); 225 this.b = b; 226 asBean = false; 227 } 228 229 public void setB(B b) { 230 this.b = b; 231 } 232 233 public B getB() { 234 return b; 235 } 236 237 public void setList(List l) { 238 this.l = l; 239 } 240 241 public List getList() { 242 return l; 243 } 244 245 public boolean instantiatedAsBean() { 246 return asBean; 247 } 248 } 249 250 public void testHybridBeans() { 251 SetterInjectionComponentAdapter bAdapter = new SetterInjectionComponentAdapter("b", B.class, null); 252 SetterInjectionComponentAdapter cAdapter = new SetterInjectionComponentAdapter("c", C.class, null); 253 SetterInjectionComponentAdapter cNullAdapter = new SetterInjectionComponentAdapter("c0", C.class, null); 254 255 MutablePicoContainer pico = new DefaultPicoContainer(); 256 pico.registerComponent(bAdapter); 257 pico.registerComponent(cAdapter); 258 pico.registerComponent(cNullAdapter); 259 pico.registerComponentImplementation(ArrayList.class); 260 261 C c = (C) cAdapter.getComponentInstance(pico); 262 assertTrue(c.instantiatedAsBean()); 263 C c0 = (C) cNullAdapter.getComponentInstance(pico); 264 assertTrue(c0.instantiatedAsBean()); 265 } 266 267 public static class Yin { 268 private Yang yang; 269 270 public void setYin(Yang yang) { 271 this.yang = yang; 272 } 273 274 public Yang getYang() { 275 return yang; 276 } 277 } 278 279 public static class Yang { 280 private Yin yin; 281 282 public void setYang(Yin yin) { 283 this.yin = yin; 284 } 285 286 public Yin getYin() { 287 return yin; 288 } 289 } 290 291 // TODO PICO-188 292 // http://jira.codehaus.org/browse/PICO-188 293 public void FIXME_testShouldBeAbleToHandleMutualDependenciesWithSetterInjection() { 294 MutablePicoContainer pico = new DefaultPicoContainer(new CachingComponentAdapterFactory( 295 new SetterInjectionComponentAdapterFactory())); 296 297 pico.registerComponentImplementation(Yin.class); 298 pico.registerComponentImplementation(Yang.class); 299 300 Yin yin = (Yin) pico.getComponentInstance(Yin.class); 301 Yang yang = (Yang) pico.getComponentInstance(Yang.class); 302 303 assertSame(yin, yang.getYin()); 304 assertSame(yang, yin.getYang()); 305 } 306 307 public void testCustomLifecycleCanBeInjected() throws NoSuchMethodException { 308 RecordingLifecycleStrategy strategy = new RecordingLifecycleStrategy(new StringBuffer()); 309 SetterInjectionComponentAdapter sica = new SetterInjectionComponentAdapter( 310 NullLifecycle.class, NullLifecycle.class, new Parameter[0], false, 311 new DelegatingComponentMonitor(), strategy); 312 Touchable touchable = new SimpleTouchable(); 313 sica.start(touchable); 314 sica.stop(touchable); 315 sica.dispose(touchable); 316 assertEquals("<start<stop<dispose", strategy.recording()); 317 } 318 319 }