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