1 10 package org.picocontainer.defaults; 11 12 import org.picocontainer.ComponentAdapter; 13 import org.picocontainer.ComponentMonitor; 14 import org.picocontainer.MutablePicoContainer; 15 import org.picocontainer.Parameter; 16 import org.picocontainer.PicoContainer; 17 import org.picocontainer.PicoInitializationException; 18 import org.picocontainer.PicoIntrospectionException; 19 import org.picocontainer.PicoVisitor; 20 import org.picocontainer.Startable; 21 import org.picocontainer.alternatives.EmptyPicoContainer; 22 import org.picocontainer.monitors.DefaultComponentMonitor; 23 import org.picocontainer.monitors.WriterComponentMonitor; 24 import org.picocontainer.tck.AbstractPicoContainerTestCase; 25 import org.picocontainer.testmodel.DecoratedTouchable; 26 import org.picocontainer.testmodel.DependsOnTouchable; 27 import org.picocontainer.testmodel.SimpleTouchable; 28 import org.picocontainer.testmodel.Touchable; 29 30 import java.io.Serializable ; 31 import java.io.StringWriter ; 32 import java.lang.reflect.Method ; 33 import java.util.ArrayList ; 34 import java.util.Collection ; 35 import java.util.HashMap ; 36 import java.util.LinkedList ; 37 import java.util.List ; 38 39 46 public class DefaultPicoContainerTestCase extends AbstractPicoContainerTestCase { 47 protected MutablePicoContainer createPicoContainer(PicoContainer parent) { 48 return new DefaultPicoContainer(parent); 49 } 50 51 public void testInstantiationWithNullComponentAdapterFactory(){ 52 try { 53 new DefaultPicoContainer((ComponentAdapterFactory)null, (PicoContainer)null); 54 fail("NPE expected"); 55 } catch (NullPointerException e) { 56 } 58 } 59 public void testUpDownDependenciesCannotBeFollowed() { 60 MutablePicoContainer parent = createPicoContainer(null); 61 MutablePicoContainer child = createPicoContainer(parent); 62 63 child.registerComponentImplementation(ComponentF.class); 65 parent.registerComponentImplementation(ComponentA.class); 66 child.registerComponentImplementation(ComponentB.class); 67 child.registerComponentImplementation(ComponentC.class); 68 69 try { 70 child.getComponentInstance(ComponentF.class); 71 fail("Thrown " + UnsatisfiableDependenciesException.class.getName() + " expected"); 72 } catch (final UnsatisfiableDependenciesException e) { 73 assertEquals(ComponentB.class, e.getUnsatisfiedDependencyType()); 74 } 75 } 76 77 public void testComponentsCanBeRemovedByInstance() { 78 MutablePicoContainer pico = createPicoContainer(null); 79 pico.registerComponentImplementation(HashMap .class); 80 pico.registerComponentImplementation(ArrayList .class); 81 List list = (List ) pico.getComponentInstanceOfType(List .class); 82 pico.unregisterComponentByInstance(list); 83 assertEquals(1, pico.getComponentAdapters().size()); 84 assertEquals(1, pico.getComponentInstances().size()); 85 assertEquals(HashMap .class, pico.getComponentInstanceOfType(Serializable .class).getClass()); 86 } 87 88 public void testComponentInstancesListIsReturnedForNullType(){ 89 MutablePicoContainer pico = createPicoContainer(null); 90 List componentInstances = pico.getComponentInstancesOfType(null); 91 assertNotNull(componentInstances); 92 assertEquals(0, componentInstances.size()); 93 } 94 95 public void testComponentsWithCommonSupertypeWhichIsAConstructorArgumentCanBeLookedUpByConcreteType() { 96 MutablePicoContainer pico = createPicoContainer(null); 97 pico.registerComponentImplementation(LinkedList .class, LinkedList .class, new Parameter[0]); 98 pico.registerComponentImplementation(ArrayList .class); 99 assertEquals(ArrayList .class, pico.getComponentInstanceOfType(ArrayList .class).getClass()); 100 } 101 102 110 public void testUnambiguouSelfDependency() { 111 MutablePicoContainer pico = createPicoContainer(null); 112 pico.registerComponentImplementation(SimpleTouchable.class); 113 pico.registerComponentImplementation(DecoratedTouchable.class); 114 Touchable t = (Touchable) pico.getComponentInstance(DecoratedTouchable.class); 115 assertNotNull(t); 116 } 117 118 public static class Thingie { 119 public Thingie(List c) { 120 assertNotNull(c); 121 } 122 } 123 124 public void testThangCanBeInstantiatedWithArrayList() { 125 MutablePicoContainer pico = new DefaultPicoContainer(); 126 pico.registerComponentImplementation(Thingie.class); 127 pico.registerComponentImplementation(ArrayList .class); 128 assertNotNull(pico.getComponentInstance(Thingie.class)); 129 } 130 131 public void testGetComponentAdaptersOfTypeNullReturnsEmptyList() { 132 DefaultPicoContainer pico = new DefaultPicoContainer(); 133 List adapters = pico.getComponentAdaptersOfType(null); 134 assertNotNull(adapters); 135 assertEquals(0, adapters.size()); 136 } 137 138 139 public static class Service { 140 } 141 142 public static class TransientComponent { 143 private Service service; 144 145 public TransientComponent(Service service) { 146 this.service = service; 147 } 148 } 149 150 public void testDefaultPicoContainerReturnsNewInstanceForEachCallWhenUsingTransientComponentAdapter() { 151 DefaultPicoContainer picoContainer = new DefaultPicoContainer(); 152 picoContainer.registerComponentImplementation(Service.class); 153 picoContainer.registerComponent(new ConstructorInjectionComponentAdapter(TransientComponent.class, TransientComponent.class)); 154 TransientComponent c1 = (TransientComponent) picoContainer.getComponentInstance(TransientComponent.class); 155 TransientComponent c2 = (TransientComponent) picoContainer.getComponentInstance(TransientComponent.class); 156 assertNotSame(c1, c2); 157 assertSame(c1.service, c2.service); 158 } 159 160 public static class DependsOnCollection { 161 public DependsOnCollection(Collection c) { 162 } 163 } 164 165 public void testShouldProvideInfoAboutDependingWhenAmbiguityHappens() { 166 MutablePicoContainer pico = this.createPicoContainer(null); 167 pico.registerComponentInstance(new ArrayList ()); 168 pico.registerComponentInstance(new LinkedList ()); 169 pico.registerComponentImplementation(DependsOnCollection.class); 170 try { 171 pico.getComponentInstanceOfType(DependsOnCollection.class); 172 fail(); 173 } catch (AmbiguousComponentResolutionException expected) { 174 String doc = DependsOnCollection.class.getName(); 175 assertEquals("class " + doc + " has ambiguous dependency on interface java.util.Collection, resolves to multiple classes: [class java.util.ArrayList, class java.util.LinkedList]", expected.getMessage()); 176 } 177 } 178 179 public void testInstantiationWithMonitorAndParent() { 180 StringWriter writer = new StringWriter (); 181 ComponentMonitor monitor = new WriterComponentMonitor(writer); 182 DefaultPicoContainer parent = new DefaultPicoContainer(); 183 DefaultPicoContainer child = new DefaultPicoContainer(monitor, parent); 184 parent.registerComponentImplementation("st", SimpleTouchable.class); 185 child.registerComponentImplementation("dot", DependsOnTouchable.class); 186 DependsOnTouchable dot = (DependsOnTouchable) child.getComponentInstance("dot"); 187 assertNotNull(dot); 188 assertTrue("writer not empty", writer.toString().length() > 0); 189 } 190 191 public void testStartCapturedByMonitor() { 192 final StringBuffer sb = new StringBuffer (); 193 DefaultPicoContainer dpc = new DefaultPicoContainer(new DefaultComponentMonitor() { 194 public void invoking(Method method, Object instance) { 195 sb.append(method.toString()); 196 } 197 }); 198 dpc.registerComponentImplementation(DefaultPicoContainer.class); 199 dpc.start(); 200 assertEquals("ComponentMonitor should have been notified that the component had been started", 201 "public abstract void org.picocontainer.Startable.start()", sb.toString()); 202 } 203 204 public void testCanChangeMonitor() { 205 StringWriter writer1 = new StringWriter (); 206 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1); 207 DefaultPicoContainer pico = new DefaultPicoContainer(monitor1); 208 pico.registerComponentImplementation("t1", SimpleTouchable.class); 209 pico.registerComponentImplementation("t3", SimpleTouchable.class); 210 Touchable t1 = (Touchable) pico.getComponentInstance("t1"); 211 assertNotNull(t1); 212 assertTrue("writer not empty", writer1.toString().length() > 0); 213 StringWriter writer2 = new StringWriter (); 214 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2); 215 pico.changeMonitor(monitor2); 216 pico.registerComponentImplementation("t2", SimpleTouchable.class); 217 Touchable t2 = (Touchable) pico.getComponentInstance("t2"); 218 assertNotNull(t2); 219 assertTrue("writer not empty", writer2.toString().length() > 0); 220 assertTrue("writers of same length", writer1.toString().length() == writer2.toString().length()); 221 Touchable t3 = (Touchable) pico.getComponentInstance("t3"); 222 assertNotNull(t3); 223 assertTrue("old writer was used", writer1.toString().length() < writer2.toString().length()); 224 } 225 226 public void testCanChangeMonitorOfChildContainers() { 227 StringWriter writer1 = new StringWriter (); 228 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1); 229 DefaultPicoContainer parent = new DefaultPicoContainer(); 230 DefaultPicoContainer child = new DefaultPicoContainer(monitor1); 231 parent.addChildContainer(child); 232 child.registerComponentImplementation("t1", SimpleTouchable.class); 233 child.registerComponentImplementation("t3", SimpleTouchable.class); 234 Touchable t1 = (Touchable) child.getComponentInstance("t1"); 235 assertNotNull(t1); 236 assertTrue("writer not empty", writer1.toString().length() > 0); 237 StringWriter writer2 = new StringWriter (); 238 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2); 239 parent.changeMonitor(monitor2); 240 child.registerComponentImplementation("t2", SimpleTouchable.class); 241 Touchable t2 = (Touchable) child.getComponentInstance("t2"); 242 assertNotNull(t2); 243 assertTrue("writer not empty", writer2.toString().length() > 0); 244 String s1 = writer1.toString(); 245 String s2 = writer2.toString(); 246 assertTrue("writers of same length", s1.length() == s2.length()); 247 Touchable t3 = (Touchable) child.getComponentInstance("t3"); 248 assertNotNull(t3); 249 assertTrue("old writer was used", writer1.toString().length() < writer2.toString().length()); 250 } 251 252 public void testChangeMonitorIsIgnoredIfNotSupportingStrategy(){ 253 StringWriter writer = new StringWriter (); 254 ComponentMonitor monitor = new WriterComponentMonitor(writer); 255 DefaultPicoContainer parent = new DefaultPicoContainer(new ComponentAdapterFactoryWithNoMonitor(new ComponentAdapterWithNoMonitor(new SimpleTouchable()))); 256 parent.addChildContainer(new EmptyPicoContainer()); 257 parent.registerComponentImplementation("t1", SimpleTouchable.class); 258 parent.changeMonitor(monitor); 259 assertTrue("writer empty", writer.toString().length() == 0); 260 } 261 262 public void testCanReturnCurrentMonitorFromComponentAdapterFactory() { 263 StringWriter writer1 = new StringWriter (); 264 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1); 265 DefaultPicoContainer pico = new DefaultPicoContainer(monitor1); 266 assertEquals(monitor1, pico.currentMonitor()); 267 StringWriter writer2 = new StringWriter (); 268 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2); 269 pico.changeMonitor(monitor2); 270 assertEquals(monitor2, pico.currentMonitor()); 271 } 272 273 public void testCanReturnCurrentMonitorFromComponentAdapter() { 274 StringWriter writer1 = new StringWriter (); 275 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1); 276 InstanceComponentAdapter adapterWithMonitor = new InstanceComponentAdapter(SimpleTouchable.class.getName(), new SimpleTouchable()); 277 adapterWithMonitor.changeMonitor(monitor1); 278 DefaultPicoContainer pico = new DefaultPicoContainer(new ComponentAdapterFactoryWithNoMonitor(adapterWithMonitor)); 279 pico.registerComponentImplementation("t1", SimpleTouchable.class); 280 assertEquals(monitor1, pico.currentMonitor()); 281 StringWriter writer2 = new StringWriter (); 282 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2); 283 pico.changeMonitor(monitor2); 284 assertEquals(monitor2, pico.currentMonitor()); 285 } 286 287 public void testCanReturnCurrentMonitorFromChildContainer() { 288 StringWriter writer1 = new StringWriter (); 289 ComponentMonitor monitor1 = new WriterComponentMonitor(writer1); 290 DefaultPicoContainer pico = new DefaultPicoContainer(new ComponentAdapterFactoryWithNoMonitor(new ComponentAdapterWithNoMonitor(new SimpleTouchable()))); 291 pico.registerComponentImplementation("t1", SimpleTouchable.class); 292 pico.addChildContainer(new EmptyPicoContainer()); 294 pico.addChildContainer(new DefaultPicoContainer(monitor1)); 296 assertEquals(monitor1, pico.currentMonitor()); 297 StringWriter writer2 = new StringWriter (); 298 ComponentMonitor monitor2 = new WriterComponentMonitor(writer2); 299 pico.changeMonitor(monitor2); 300 assertEquals(monitor2, pico.currentMonitor()); 301 } 302 303 public void testCannotReturnCurrentMonitor() { 304 DefaultPicoContainer pico = new DefaultPicoContainer(new ComponentAdapterFactoryWithNoMonitor(null)); 305 try { 306 pico.currentMonitor(); 307 fail("PicoIntrospectionException expected"); 308 } catch (PicoIntrospectionException e) { 309 assertEquals("No component monitor found in container or its children", e.getMessage()); 310 } 311 } 312 313 private static class ComponentAdapterFactoryWithNoMonitor implements ComponentAdapterFactory { 314 private ComponentAdapter adapter; 315 public ComponentAdapterFactoryWithNoMonitor(ComponentAdapter adapter){ 316 this.adapter = adapter; 317 } 318 public ComponentAdapter createComponentAdapter(Object componentKey, Class componentImplementation, Parameter[] parameters) throws PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException { 319 return adapter; 320 } 321 } 322 323 private static class ComponentAdapterWithNoMonitor implements ComponentAdapter { 324 private Object instance; 325 public ComponentAdapterWithNoMonitor(Object instance){ 326 this.instance = instance; 327 } 328 public Object getComponentKey() { 329 return instance.getClass(); 330 } 331 public Class getComponentImplementation() { 332 return instance.getClass(); 333 } 334 public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException { 335 return instance; 336 } 337 public void verify(PicoContainer container) throws PicoIntrospectionException { 338 } 339 public void accept(PicoVisitor visitor) { 340 } 341 } 342 343 public void testMakeChildContainer() { 344 MutablePicoContainer parent = new DefaultPicoContainer(); 345 parent.registerComponentImplementation("t1", SimpleTouchable.class); 346 MutablePicoContainer child = parent.makeChildContainer(); 347 Object t1 = child.getParent().getComponentInstance("t1"); 348 assertNotNull(t1); 349 assertTrue(t1 instanceof SimpleTouchable); 350 } 351 352 public void testCanUseCustomLifecycleStrategyForClassRegistrations() { 353 DefaultPicoContainer dpc = new DefaultPicoContainer(new FailingLifecycleStrategy(), null); 354 dpc.registerComponentImplementation(Startable.class, MyStartable.class); 355 try { 356 dpc.start(); 357 fail("should have barfed"); 358 } catch (RuntimeException e) { 359 assertEquals("foo", e.getMessage()); 360 } 361 } 362 363 public void testCanUseCustomLifecycleStrategyForInstanceRegistrations() { 364 DefaultPicoContainer dpc = new DefaultPicoContainer(new FailingLifecycleStrategy(), null); 365 Startable myStartable = new MyStartable(); 366 dpc.registerComponentInstance(Startable.class, myStartable); 367 try { 368 dpc.start(); 369 fail("should have barfed"); 370 } catch (RuntimeException e) { 371 assertEquals("foo", e.getMessage()); 372 } 373 } 374 375 public static class FailingLifecycleStrategy implements LifecycleStrategy { 376 public void start(Object component) { 377 throw new RuntimeException ("foo"); 378 } 379 380 public void stop(Object component) { 381 } 382 383 public void dispose(Object component) { 384 } 385 386 public boolean hasLifecycle(Class type) { 387 return true; 388 } 389 390 } 391 public static class MyStartable implements Startable { 392 public MyStartable() { 393 } 394 395 public void start() { 396 } 397 398 public void stop() { 399 } 400 } 401 402 public static interface A { 403 404 } 405 406 public static class SimpleA implements A 407 { 408 409 } 410 411 public static class WrappingA implements A 412 { 413 private final A wrapped; 414 415 public WrappingA(A wrapped) { 416 this.wrapped = wrapped; 417 } 418 } 419 420 public void testCanRegisterTwoComponentsImplementingSameInterfaceOneWithInterfaceAsKey() throws Exception { 421 MutablePicoContainer container = createPicoContainer(null); 422 423 container.registerComponentImplementation(SimpleA.class); 424 container.registerComponentImplementation(A.class, WrappingA.class); 425 426 container.start(); 427 428 assertEquals(WrappingA.class, container.getComponentInstance(A.class).getClass()); 429 } 430 431 public void testCanRegisterTwoComponentsWithSameImplementionAndDifferentKey() throws Exception { 432 MutablePicoContainer container = createPicoContainer(null); 433 434 container.registerComponentImplementation(SimpleA.class); 435 container.registerComponentImplementation("A", SimpleA.class); 436 437 container.start(); 438 439 assertNotNull(container.getComponentInstance("A")); 440 assertNotNull(container.getComponentInstance(SimpleA.class)); 441 assertNotSame(container.getComponentInstance("A"), container.getComponentInstance(SimpleA.class)); 442 } 443 444 public static class MyPicoContainer extends DefaultPicoContainer { 445 446 public ComponentAdapter registerComponent(ComponentAdapter componentAdapter) { 447 return super.registerComponent(new SynchronizedComponentAdapter(componentAdapter)); 448 } 449 450 } 451 452 public void testDerivedPicoContainerCanOverloadRegisterComponentForAllCreatedComponentAdapters() { 453 MutablePicoContainer mpc = new MyPicoContainer(); 454 assertEquals(SynchronizedComponentAdapter.class, mpc.registerComponent(new InstanceComponentAdapter("foo", "bar")).getClass()); 455 assertEquals(SynchronizedComponentAdapter.class, mpc.registerComponentInstance("foobar").getClass()); 456 assertEquals(SynchronizedComponentAdapter.class, mpc.registerComponentImplementation(SimpleA.class).getClass()); 457 } 458 } | Popular Tags |