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.injectors;
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.ComponentFactory;
019 import org.picocontainer.DefaultPicoContainer;
020 import org.picocontainer.lifecycle.NullLifecycleStrategy;
021 import org.picocontainer.parameters.ConstantParameter;
022 import org.picocontainer.monitors.AbstractComponentMonitor;
023 import org.picocontainer.monitors.NullComponentMonitor;
024 import static org.picocontainer.parameters.ComponentParameter.*;
025 import org.picocontainer.behaviors.CachingBehaviorFactory;
026 import org.picocontainer.tck.AbstractComponentAdapterTestCase;
027 import org.picocontainer.testmodel.NullLifecycle;
028 import org.picocontainer.testmodel.PersonBean;
029 import org.picocontainer.testmodel.PurseBean;
030 import org.picocontainer.testmodel.SimpleTouchable;
031 import org.picocontainer.testmodel.Touchable;
032
033
034 public class SetterInjectorTestCase
035 extends AbstractComponentAdapterTestCase {
036
037 protected Class getComponentAdapterType() {
038 return SetterInjector.class;
039 }
040
041 protected ComponentFactory createDefaultComponentAdapterFactory() {
042 return new CachingBehaviorFactory().forThis(new SetterInjectionFactory());
043 }
044
045 protected ComponentAdapter prepDEF_verifyWithoutDependencyWorks(MutablePicoContainer picoContainer) {
046 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {new ConstantParameter(
047 "Pico Container")}, new NullComponentMonitor(), new NullLifecycleStrategy());
048 }
049
050 protected ComponentAdapter prepDEF_verifyDoesNotInstantiate(MutablePicoContainer picoContainer) {
051 picoContainer.addComponent("Pico Container");
052 return new SetterInjector(DeadBody.class, DeadBody.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
053 }
054
055 protected ComponentAdapter prepDEF_visitable() {
056 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {new ConstantParameter(
057 "Pico Container")}, new NullComponentMonitor(), new NullLifecycleStrategy());
058
059 }
060
061 protected ComponentAdapter prepSER_isSerializable(MutablePicoContainer picoContainer) {
062 picoContainer.addComponent("Pico Container");
063 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
064 }
065
066 protected ComponentAdapter prepSER_isXStreamSerializable(MutablePicoContainer picoContainer) {
067 return prepSER_isSerializable(picoContainer);
068 }
069
070 protected ComponentAdapter prepDEF_isAbleToTakeParameters(MutablePicoContainer picoContainer) {
071 picoContainer.addComponent("Pico Container");
072 picoContainer.addComponent(PersonBean.class);
073 SetterInjector componentAdapter = new SetterInjector(
074 PurseBean.class, MoneyPurse.class, new Parameter[] {DEFAULT, new ConstantParameter(100.0)}, new NullComponentMonitor(), new NullLifecycleStrategy());
075 return picoContainer.addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, null);
076 }
077
078 public static class MoneyPurse
079 extends PurseBean {
080 double money;
081
082 public double getMoney() {
083 return money;
084 }
085
086 public void setMoney(double money) {
087 this.money = money;
088 }
089 }
090
091 protected ComponentAdapter prepVER_verificationFails(MutablePicoContainer picoContainer) {
092 picoContainer.addComponent("Pico Container");
093 picoContainer.addComponent(PersonBean.class);
094 SetterInjector componentAdapter = new SetterInjector(
095 PurseBean.class, MoneyPurse.class, new Parameter[] {DEFAULT},new NullComponentMonitor(), new NullLifecycleStrategy());
096 return picoContainer.addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, null);
097 }
098
099 protected ComponentAdapter prepINS_createsNewInstances(MutablePicoContainer picoContainer) {
100 picoContainer.addComponent("Pico Container");
101 return new SetterInjector(PersonBean.class, PersonBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
102 }
103
104 public static class Ghost
105 extends PersonBean {
106 public Ghost() {
107 throw new VerifyError("test");
108 }
109 }
110
111 protected ComponentAdapter prepINS_errorIsRethrown(MutablePicoContainer picoContainer) {
112 picoContainer.addComponent("Pico Container");
113 return new SetterInjector(Ghost.class, Ghost.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
114 }
115
116 public static class DeadBody
117 extends PersonBean {
118 public DeadBody() {
119 throw new RuntimeException("test");
120 }
121 }
122
123 protected ComponentAdapter prepINS_runtimeExceptionIsRethrown(MutablePicoContainer picoContainer) {
124 picoContainer.addComponent("Pico Container");
125 return new SetterInjector(DeadBody.class, DeadBody.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
126 }
127
128 public static class HidingPersion
129 extends PersonBean {
130 public HidingPersion() throws Exception {
131 throw new Exception("test");
132 }
133 }
134
135 protected ComponentAdapter prepINS_normalExceptionIsRethrownInsidePicoInitializationException(
136 MutablePicoContainer picoContainer) {
137 picoContainer.addComponent("Pico Container");
138 return new SetterInjector(
139 HidingPersion.class, HidingPersion.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
140 }
141
142 protected ComponentAdapter prepRES_dependenciesAreResolved(MutablePicoContainer picoContainer) {
143 picoContainer.addComponent("Pico Container");
144 picoContainer.addComponent(PersonBean.class);
145 return new SetterInjector(PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
146 }
147
148 public static class WealthyPerson
149 extends PersonBean {
150 PurseBean purse;
151
152 public PurseBean getPurse() {
153 return purse;
154 }
155
156 public void setPurse(PurseBean purse) {
157 this.purse = purse;
158 }
159 }
160
161 protected ComponentAdapter prepRES_failingVerificationWithCyclicDependencyException(MutablePicoContainer picoContainer) {
162 picoContainer.addComponent("Pico Container");
163 picoContainer.addComponent(PersonBean.class, WealthyPerson.class);
164 SetterInjector componentAdapter = new SetterInjector(
165 PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
166 return picoContainer.addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, null);
167 }
168
169 protected ComponentAdapter prepRES_failingInstantiationWithCyclicDependencyException(MutablePicoContainer picoContainer) {
170 picoContainer.addComponent("Pico Container");
171 picoContainer.addComponent(PersonBean.class, WealthyPerson.class);
172 SetterInjector componentAdapter = new SetterInjector(
173 PurseBean.class, PurseBean.class, new Parameter[] {DEFAULT}, new NullComponentMonitor(), new NullLifecycleStrategy());
174 return picoContainer.addAdapter(componentAdapter).getComponentAdapter(PurseBean.class, null);
175 }
176
177 public static class A {
178 private B b;
179 private String string;
180 private List list;
181
182 public void setB(B b) {
183 this.b = b;
184 }
185
186 public B getB() {
187 return b;
188 }
189
190 public String getString() {
191 return string;
192 }
193
194 public void setString(String string) {
195 this.string = string;
196 }
197
198 public List getList() {
199 return list;
200 }
201
202 public void setList(List list) {
203 this.list = list;
204 }
205 }
206
207 public static class A2 {
208 private B b;
209 private String string;
210 private List list;
211
212 public void injectB(B b) {
213 this.b = b;
214 }
215
216 public B getB() {
217 return b;
218 }
219
220 public String getString() {
221 return string;
222 }
223
224 public void injectString(String string) {
225 this.string = string;
226 }
227
228 public List getList() {
229 return list;
230 }
231
232 public void injectList(List list) {
233 this.list = list;
234 }
235 }
236
237
238 public static class B {
239 }
240
241 public void testAllUnsatisfiableDependenciesAreSignalled() {
242 SetterInjector aAdapter = new SetterInjector("a", A.class, Parameter.DEFAULT, new NullComponentMonitor(), new NullLifecycleStrategy());
243 SetterInjector bAdapter = new SetterInjector("b", B.class, Parameter.DEFAULT, new NullComponentMonitor(), new NullLifecycleStrategy());
244
245 MutablePicoContainer pico = new DefaultPicoContainer();
246 pico.addAdapter(bAdapter);
247 pico.addAdapter(aAdapter);
248
249 try {
250 aAdapter.getComponentInstance(pico);
251 } catch (AbstractInjector.UnsatisfiableDependenciesException e) {
252 assertTrue(e.getUnsatisfiableDependencies().contains(List.class));
253 assertTrue(e.getUnsatisfiableDependencies().contains(String.class));
254 }
255 }
256
257 public void testAllUnsatisfiableDependenciesAreSignalled2() {
258 SetterInjector aAdapter = new SetterInjector(A2.class, A2.class, null, new NullComponentMonitor(), new NullLifecycleStrategy());
259 SetterInjector bAdapter = new SetterInjector("b", B.class, null, new NullComponentMonitor(), new NullLifecycleStrategy());
260
261 MutablePicoContainer pico = new DefaultPicoContainer();
262 pico.addComponent(List.class, ArrayList.class)
263 .addComponent(String.class, "foo")
264 .addAdapter(bAdapter)
265 .addAdapter(aAdapter);
266
267 aAdapter.getComponentInstance(pico);
268
269 assertNotNull(aAdapter);
270
271 A2 a = pico.getComponent(A2.class);
272 assertTrue(a.getList() == null);
273 assertTrue(a.getString() == null);
274 }
275
276 public static class InitBurp {
277
278 private Wind wind;
279
280 public void initWind(Wind wind) {
281 this.wind = wind;
282 }
283 }
284
285 public static class SetterBurp {
286
287 private Wind wind;
288
289 public void setWind(Wind wind) {
290 this.wind = wind;
291 }
292 }
293
294 public static class Wind {
295
296 }
297
298 public void testSetterMethodInjectionToContrastWithThatBelow() {
299
300 MutablePicoContainer pico = new DefaultPicoContainer();
301 pico.addAdapter(new SetterInjector(SetterBurp.class, SetterBurp.class, Parameter.DEFAULT, new NullComponentMonitor(), new NullLifecycleStrategy()));
302 pico.addComponent(Wind.class, new Wind());
303 SetterBurp burp = pico.getComponent(SetterBurp.class);
304 assertNotNull(burp);
305 assertNotNull(burp.wind);
306 }
307
308 public void testNonSetterMethodInjection() {
309 MutablePicoContainer pico = new DefaultPicoContainer();
310 pico.addAdapter(new SetterInjector(InitBurp.class, InitBurp.class, Parameter.DEFAULT, new NullComponentMonitor(), new NullLifecycleStrategy()) {
311 protected String getInjectorPrefix() {
312 return "init";
313 }
314 });
315 pico.addComponent(Wind.class, new Wind());
316 InitBurp burp = pico.getComponent(InitBurp.class);
317 assertNotNull(burp);
318 assertNotNull(burp.wind);
319 }
320
321 public void testNonSetterMethodInjectionWithoutOverridingSetterPrefix() {
322 MutablePicoContainer pico = new DefaultPicoContainer();
323 pico.addAdapter(new SetterInjector(InitBurp.class, InitBurp.class, Parameter.ZERO, new NullComponentMonitor(), new NullLifecycleStrategy()));
324 pico.addComponent(Wind.class, new Wind());
325 InitBurp burp = pico.getComponent(InitBurp.class);
326 assertNotNull(burp);
327 assertTrue(burp.wind == null);
328 }
329
330
331 public static class C {
332 private B b;
333 private List l;
334 private final boolean asBean;
335
336 public C() {
337 asBean = true;
338 }
339
340 public C(B b) {
341 this.l = new ArrayList();
342 this.b = b;
343 asBean = false;
344 }
345
346 public void setB(B b) {
347 this.b = b;
348 }
349
350 public B getB() {
351 return b;
352 }
353
354 public void setList(List l) {
355 this.l = l;
356 }
357
358 public List getList() {
359 return l;
360 }
361
362 public boolean instantiatedAsBean() {
363 return asBean;
364 }
365 }
366
367 public void testHybridBeans() {
368 SetterInjector bAdapter = new SetterInjector("b", B.class, (Parameter[])null, new NullComponentMonitor(), new NullLifecycleStrategy());
369 SetterInjector cAdapter = new SetterInjector("c", C.class, (Parameter[])null, new NullComponentMonitor(), new NullLifecycleStrategy());
370 SetterInjector cNullAdapter = new SetterInjector("c0", C.class, (Parameter[])null, new NullComponentMonitor(), new NullLifecycleStrategy());
371
372 MutablePicoContainer pico = new DefaultPicoContainer();
373 pico.addAdapter(bAdapter);
374 pico.addAdapter(cAdapter);
375 pico.addAdapter(cNullAdapter);
376 pico.addComponent(ArrayList.class);
377
378 C c = (C) cAdapter.getComponentInstance(pico);
379 assertTrue(c.instantiatedAsBean());
380 C c0 = (C) cNullAdapter.getComponentInstance(pico);
381 assertTrue(c0.instantiatedAsBean());
382 }
383
384 public static class Yin {
385 private Yang yang;
386
387 public void setYin(Yang yang) {
388 this.yang = yang;
389 }
390
391 public Yang getYang() {
392 return yang;
393 }
394 }
395
396 public static class Yang {
397 private Yin yin;
398
399 public void setYang(Yin yin) {
400 this.yin = yin;
401 }
402
403 public Yin getYin() {
404 return yin;
405 }
406 }
407
408 // TODO PICO-188
409 // http://jira.codehaus.org/browse/PICO-188
410 public void FIXME_testShouldBeAbleToHandleMutualDependenciesWithSetterInjection() {
411 MutablePicoContainer pico = new DefaultPicoContainer(new CachingBehaviorFactory().forThis(new SetterInjectionFactory()));
412
413 pico.addComponent(Yin.class);
414 pico.addComponent(Yang.class);
415
416 Yin yin = pico.getComponent(Yin.class);
417 Yang yang = pico.getComponent(Yang.class);
418
419 assertSame(yin, yang.getYin());
420 assertSame(yang, yin.getYang());
421 }
422
423 public void testCustomLifecycleCanBeInjected() throws NoSuchMethodException {
424 RecordingLifecycleStrategy strategy = new RecordingLifecycleStrategy(new StringBuffer());
425 SetterInjector sica = new SetterInjector(
426 NullLifecycle.class, NullLifecycle.class, new Parameter[0],
427 new AbstractComponentMonitor(), strategy);
428 Touchable touchable = new SimpleTouchable();
429 sica.start(touchable);
430 sica.stop(touchable);
431 sica.dispose(touchable);
432 assertEquals("<start<stop<dispose", strategy.recording());
433 }
434
435 }