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 *****************************************************************************/ 009package org.picocontainer.injectors; 010 011import org.junit.Test; 012import org.picocontainer.DefaultPicoContainer; 013import org.picocontainer.MutablePicoContainer; 014import org.picocontainer.PicoCompositionException; 015import org.picocontainer.PicoContainer; 016import org.picocontainer.annotations.Inject; 017 018import java.lang.reflect.Type; 019import java.util.Map; 020 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertNotSame; 024 025public 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}