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 *****************************************************************************/
009 package org.picocontainer.injectors;
010
011 import org.junit.Test;
012 import org.picocontainer.DefaultPicoContainer;
013 import org.picocontainer.MutablePicoContainer;
014 import org.picocontainer.PicoCompositionException;
015 import org.picocontainer.PicoContainer;
016 import org.picocontainer.annotations.Inject;
017
018 import java.lang.reflect.Type;
019 import java.util.Map;
020
021 import static org.junit.Assert.assertEquals;
022 import static org.junit.Assert.assertNotNull;
023 import static org.junit.Assert.assertNotSame;
024
025 public class FactoryInjectorTestCase {
026
027 public static interface Swede {
028 }
029
030 public static class Turnip2 {
031 Swede swede;
032 private final String foo;
033 public Turnip2(String foo, Swede swede) {
034 this.foo = foo;
035 assertNotNull(swede);
036 this.swede = swede;
037 }
038 public Swede getSwede() {
039 return swede;
040 }
041
042 public String getFoo() {
043 return foo;
044 }
045 }
046
047 public static class Turnip {
048 @Inject
049 Swede swede;
050 private final String foo;
051
052 public Turnip(String foo) {
053 this.foo = foo;
054 }
055
056 public Swede getSwede() {
057 return swede;
058 }
059
060 public String getFoo() {
061 return foo;
062 }
063 }
064
065 @Test
066 public void testThatComponentCanHaveAProvidedDependency() {
067 MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
068 container.addComponent(String.class, "foo");
069 container.addComponent(Turnip.class);
070 container.addAdapter(new SwedeFactoryInjector());
071 Turnip t = container.getComponent(Turnip.class);
072 assertNotNull(t);
073 assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
074 assertEquals("foo", t.getFoo());
075
076 }
077
078 @Test
079 public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector() {
080 MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
081 container.addComponent(String.class, "foo");
082 container.addComponent(Turnip.class);
083 container.addAdapter(new FactoryInjector<Swede>() {
084 public Swede getComponentInstance(PicoContainer container, final Type into) {
085 return new Swede() {
086 public String toString() {
087 return "Swede for " + ((InjectInto) into).getIntoClass().getName();
088 }
089 };
090 }
091 });
092 Turnip t = container.getComponent(Turnip.class);
093 assertNotNull(t);
094 assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
095 assertEquals("foo", t.getFoo());
096
097 }
098
099 @Test
100 public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector2() {
101 MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
102 container.addComponent(String.class, "foo");
103 container.addComponent(Turnip.class);
104 container.addAdapter(new FactoryInjector(Swede.class) {
105 public Swede getComponentInstance(PicoContainer container, final Type into) {
106 return new Swede() {
107 public String toString() {
108 return "Swede for " + ((InjectInto) into).getIntoClass().getName();
109 }
110 };
111 }
112 });
113 Turnip t = container.getComponent(Turnip.class);
114 assertNotNull(t);
115 assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
116 assertEquals("foo", t.getFoo());
117
118 }
119
120 @Test
121 public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector3() {
122 MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
123 container.addComponent(String.class, "foo");
124 container.addComponent(Turnip.class);
125 container.addAdapter(new FactoryInjector(Swede.class) {
126 public Swede getComponentInstance(PicoContainer container, final Type into) {
127 return new Swede() {
128 public String toString() {
129 return "Swede for " + ((InjectInto) into).getIntoClass().getName();
130 }
131 };
132 }
133 });
134 Turnip t = container.getComponent(Turnip.class);
135 assertNotNull(t);
136 assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
137 assertEquals("foo", t.getFoo());
138
139 }
140
141
142 @Test
143 public void testThatComponentCanHaveAProvidedDependencyViaConstructor() {
144 MutablePicoContainer container = new DefaultPicoContainer();
145 container.addComponent(String.class, "foo");
146 container.addComponent(Turnip2.class);
147 container.addAdapter(new SwedeFactoryInjector());
148 Turnip2 t = container.getComponent(Turnip2.class);
149 assertNotNull(t);
150 assertEquals("Swede for " + Turnip2.class.getName(), t.getSwede().toString());
151 assertEquals("foo", t.getFoo());
152
153 }
154
155 @Test
156 public void testThatComponentCanHaveAProvidedDependencyViaConstructorADifferentWay() {
157 MutablePicoContainer container = new DefaultPicoContainer();
158 container.addComponent(String.class, "foo");
159 container.addComponent(Turnip2.class);
160 container.addAdapter(new Swede2FactoryInjector()); // this injector defines Swede2 as key in its ctor
161 Turnip2 t = container.getComponent(Turnip2.class);
162 assertNotNull(t);
163 assertEquals("Swede for " + Turnip2.class.getName(), t.getSwede().toString());
164 assertEquals("foo", t.getFoo());
165
166 }
167
168 private static class SwedeFactoryInjector extends FactoryInjector<Swede> {
169 public Swede getComponentInstance(PicoContainer container, final Type into) throws PicoCompositionException {
170 // Mauro: you can do anything in here by way of startegy for injecting a specific logger :-)
171 return new Swede() {
172 public String toString() {
173 return "Swede for " + ((InjectInto) into).getIntoClass().getName();
174 }
175 };
176 }
177 }
178
179 private static class Swede2FactoryInjector extends FactoryInjector {
180 private Swede2FactoryInjector() {
181 super(Swede.class);
182 }
183
184 public Swede getComponentInstance(PicoContainer container, final Type into) throws PicoCompositionException {
185 // Mauro: you can do anything in here by way of startegy for injecting a specific logger :-)
186 return new Swede() {
187 public String toString() {
188 return "Swede for " + ((InjectInto) into).getIntoClass().getName();
189 }
190 };
191 }
192 }
193
194 private abstract class Footle<T> {
195 private class ServiceConnectionInjector extends FactoryInjector<T> {
196 public T getComponentInstance(PicoContainer container, Type into) {
197 System.out.println("**** injector called for " + into);
198 return null;
199 }
200 }
201
202 private void addAdapter(MutablePicoContainer mpc) {
203 mpc.addAdapter(new ServiceConnectionInjector());
204 }
205 }
206
207 public static interface Tree {
208 String leafColor();
209 }
210 public static class OakTree implements Tree {
211 private String leafColor;
212
213 public OakTree(String leafColor) {
214 this.leafColor = leafColor;
215 }
216
217 public String leafColor() {
218 return leafColor;
219 }
220 }
221
222 @Test public void ensureSophistcatedFactorInjectorCaseIsPossible() {
223
224 DefaultPicoContainer pico = new DefaultPicoContainer();
225 pico.addConfig("leafColor", "green");
226 pico.addComponent(Tree.class, OakTree.class);
227
228 Footle<Map> ft = new Footle<Map>(){};
229
230 ft.addAdapter(pico);
231
232 Tree tree = pico.getComponent(Tree.class);
233 }
234
235 private static class KeyAwareSwedeFactoryInjector extends FactoryInjector<Swede> {
236
237 public Swede getComponentInstance(PicoContainer container, final Type into) throws PicoCompositionException {
238 return new Swede() {
239 public String toString() {
240 InjectInto intoType = (InjectInto) into;
241 return "Swede for " + intoType.getIntoClass().getName() + " " + intoType.getIntoKey();
242 }
243 };
244 }
245 }
246
247 @Test
248 public void testThatFactoryCanUseTargetComponentKey() {
249 MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
250 container.addComponent(String.class, "foo");
251 container.addComponent("turnip1", Turnip.class);
252 container.addComponent("turnip2", Turnip.class);
253 container.addAdapter(new KeyAwareSwedeFactoryInjector());
254 Turnip turnip1 = (Turnip)container.getComponent("turnip1");
255 Turnip turnip2 = (Turnip)container.getComponent("turnip2");
256 assertNotNull(turnip1);
257 assertNotNull(turnip2);
258 assertNotSame(turnip1, turnip2);
259 assertNotSame(turnip1.getSwede(), turnip2.getSwede());
260 assertEquals("Swede for " + Turnip.class.getName() + " turnip1", turnip1.getSwede().toString());
261 assertEquals("Swede for " + Turnip.class.getName() + " turnip2", turnip2.getSwede().toString());
262 }
263
264 @Test
265 public void brendansNullTypeCase() {
266 MutablePicoContainer pico = new DefaultPicoContainer();
267 pico.addComponent(BrendansComponent.class);
268 pico.addAdapter(new BrendansLoggerInjector());
269
270 BrendansComponent bc = pico.getComponent(BrendansComponent.class);
271 assertEquals("org.picocontainer.injectors.InjectInto", bc.logger.canonicalName);
272 }
273
274 public static class BrendansLogger {
275 private String canonicalName;
276
277 public BrendansLogger(String canonicalName) {
278 this.canonicalName = canonicalName;
279 }
280
281 public static BrendansLogger getLogger(String canonicalName) {
282 return new BrendansLogger(canonicalName);
283 }
284 }
285
286 public static class BrendansComponent {
287 BrendansLogger logger;
288
289 public BrendansComponent(BrendansLogger logger) {
290 this.logger = logger;
291 }
292 }
293
294 public static class BrendansLoggerInjector extends FactoryInjector<BrendansLogger> {
295
296 @Override
297 public BrendansLogger getComponentInstance(PicoContainer arg0, final Type arg1)
298 throws PicoCompositionException {
299 return BrendansLogger.getLogger(arg1.getClass().getCanonicalName());
300 }
301
302 }
303
304 }