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 }