KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > tck > AbstractPicoContainerTestCase


1 /*****************************************************************************
2  * Copyright (C) PicoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by *
9  *****************************************************************************/

10 package org.picocontainer.tck;
11
12 import java.io.ByteArrayInputStream JavaDoc;
13 import java.io.ByteArrayOutputStream JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.ObjectInputStream JavaDoc;
16 import java.io.ObjectOutputStream JavaDoc;
17 import java.io.Serializable JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Arrays JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.LinkedList JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import junit.framework.Assert;
29
30 import org.picocontainer.ComponentAdapter;
31 import org.picocontainer.Disposable;
32 import org.picocontainer.LifecycleManager;
33 import org.picocontainer.MutablePicoContainer;
34 import org.picocontainer.Parameter;
35 import org.picocontainer.PicoContainer;
36 import org.picocontainer.PicoException;
37 import org.picocontainer.PicoInitializationException;
38 import org.picocontainer.PicoIntrospectionException;
39 import org.picocontainer.PicoRegistrationException;
40 import org.picocontainer.PicoVerificationException;
41 import org.picocontainer.PicoVisitor;
42 import org.picocontainer.Startable;
43 import org.picocontainer.defaults.AbstractPicoVisitor;
44 import org.picocontainer.defaults.AmbiguousComponentResolutionException;
45 import org.picocontainer.defaults.AssignabilityRegistrationException;
46 import org.picocontainer.defaults.BasicComponentParameter;
47 import org.picocontainer.defaults.ConstantParameter;
48 import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
49 import org.picocontainer.defaults.CyclicDependencyException;
50 import org.picocontainer.defaults.DefaultPicoContainer;
51 import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
52 import org.picocontainer.defaults.InstanceComponentAdapter;
53 import org.picocontainer.defaults.NotConcreteRegistrationException;
54 import org.picocontainer.defaults.UnsatisfiableDependenciesException;
55 import org.picocontainer.defaults.VerifyingVisitor;
56 import org.picocontainer.testmodel.DependsOnTouchable;
57 import org.picocontainer.testmodel.SimpleTouchable;
58 import org.picocontainer.testmodel.Touchable;
59 import org.picocontainer.testmodel.Washable;
60 import org.picocontainer.testmodel.WashableTouchable;
61
62 import org.jmock.MockObjectTestCase;
63
64 /**
65  * This test tests (at least it should) all the methods in MutablePicoContainer.
66  */

67 public abstract class AbstractPicoContainerTestCase extends MockObjectTestCase {
68
69     protected abstract MutablePicoContainer createPicoContainer(PicoContainer parent);
70
71     protected final MutablePicoContainer createPicoContainerWithDependsOnTouchableOnly() throws
72             PicoRegistrationException, PicoIntrospectionException {
73         MutablePicoContainer pico = createPicoContainer(null);
74         pico.registerComponentImplementation(DependsOnTouchable.class);
75         return pico;
76
77     }
78
79     protected final MutablePicoContainer createPicoContainerWithTouchableAndDependsOnTouchable() throws
80             PicoRegistrationException, PicoIntrospectionException {
81         MutablePicoContainer pico = createPicoContainerWithDependsOnTouchableOnly();
82         pico.registerComponentImplementation(Touchable.class, SimpleTouchable.class);
83         return pico;
84     }
85
86     public void testBasicInstantiationAndContainment() throws PicoException, PicoRegistrationException {
87         PicoContainer pico = createPicoContainerWithTouchableAndDependsOnTouchable();
88         assertTrue("Component should be instance of Touchable", Touchable.class.isAssignableFrom(pico.getComponentAdapterOfType(Touchable.class).getComponentImplementation()));
89     }
90
91     public void testRegisteredComponentsExistAndAreTheCorrectTypes() throws PicoException, PicoRegistrationException {
92         PicoContainer pico = createPicoContainerWithTouchableAndDependsOnTouchable();
93         assertNotNull("Container should have Touchable component",
94                 pico.getComponentAdapter(Touchable.class));
95         assertNotNull("Container should have DependsOnTouchable component",
96                 pico.getComponentAdapter(DependsOnTouchable.class));
97         assertTrue("Component should be instance of Touchable",
98                 pico.getComponentInstance(Touchable.class) instanceof Touchable);
99         assertTrue("Component should be instance of DependsOnTouchable",
100                 pico.getComponentInstance(DependsOnTouchable.class) instanceof DependsOnTouchable);
101         assertNull("should not have non existent component", pico.getComponentAdapter(Map JavaDoc.class));
102     }
103
104     public void testRegistersSingleInstance() throws PicoException, PicoInitializationException {
105         MutablePicoContainer pico = createPicoContainer(null);
106         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
107         pico.registerComponentInstance(sb);
108         assertSame(sb, pico.getComponentInstance(StringBuffer JavaDoc.class));
109     }
110
111     public void testContainerIsSerializable() throws PicoException, PicoInitializationException,
112             IOException JavaDoc, ClassNotFoundException JavaDoc {
113
114         getTouchableFromSerializedContainer();
115
116     }
117
118     private Touchable getTouchableFromSerializedContainer() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
119         MutablePicoContainer pico = createPicoContainerWithTouchableAndDependsOnTouchable();
120         // Add a list too, using a constant parameter
121
pico.registerComponentImplementation("list", ArrayList JavaDoc.class, new Parameter[]{new ConstantParameter(new Integer JavaDoc(10))});
122
123         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
124         ObjectOutputStream JavaDoc oos = new ObjectOutputStream JavaDoc(baos);
125
126         oos.writeObject(pico);
127         ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(baos.toByteArray()));
128
129         pico = (MutablePicoContainer) ois.readObject();
130
131         DependsOnTouchable dependsOnTouchable = (DependsOnTouchable) pico.getComponentInstance(DependsOnTouchable.class);
132         assertNotNull(dependsOnTouchable);
133         return (Touchable) pico.getComponentInstance(Touchable.class);
134     }
135
136     public void testSerializedContainerCanRetrieveImplementation() throws PicoException, PicoInitializationException,
137             IOException JavaDoc, ClassNotFoundException JavaDoc {
138
139         Touchable touchable = getTouchableFromSerializedContainer();
140
141         SimpleTouchable simpleTouchable = (SimpleTouchable) touchable;
142
143         assertTrue(simpleTouchable.wasTouched);
144     }
145
146
147     public void testGettingComponentWithMissingDependencyFails() throws PicoException, PicoRegistrationException {
148         PicoContainer picoContainer = createPicoContainerWithDependsOnTouchableOnly();
149         try {
150             picoContainer.getComponentInstance(DependsOnTouchable.class);
151             fail("should need a Touchable");
152         } catch (UnsatisfiableDependenciesException e) {
153             assertSame(picoContainer.getComponentAdapterOfType(DependsOnTouchable.class).getComponentImplementation(), e.getUnsatisfiableComponentAdapter().getComponentImplementation());
154             final Set JavaDoc unsatisfiableDependencies = e.getUnsatisfiableDependencies();
155             assertEquals(1, unsatisfiableDependencies.size());
156
157             // Touchable.class is now inside a List (the list of unsatisfied parameters) -- mparaz
158
List JavaDoc unsatisfied = (List JavaDoc) unsatisfiableDependencies.iterator().next();
159             assertEquals(1, unsatisfied.size());
160             assertEquals(Touchable.class, unsatisfied.get(0));
161         }
162     }
163
164     public void testDuplicateRegistration() throws Exception JavaDoc {
165         try {
166             MutablePicoContainer pico = createPicoContainer(null);
167             pico.registerComponentImplementation(Object JavaDoc.class);
168             pico.registerComponentImplementation(Object JavaDoc.class);
169             fail("Should have failed with duplicate registration");
170         } catch (DuplicateComponentKeyRegistrationException e) {
171             assertTrue("Wrong key", e.getDuplicateKey() == Object JavaDoc.class);
172         }
173     }
174
175     public void testExternallyInstantiatedObjectsCanBeRegistgeredAndLookedUp() throws PicoException, PicoInitializationException {
176         MutablePicoContainer pico = createPicoContainer(null);
177         final HashMap JavaDoc map = new HashMap JavaDoc();
178         pico.registerComponentInstance(Map JavaDoc.class, map);
179         assertSame(map, pico.getComponentInstance(Map JavaDoc.class));
180     }
181
182     public void testAmbiguousResolution() throws PicoRegistrationException, PicoInitializationException {
183         MutablePicoContainer pico = createPicoContainer(null);
184         pico.registerComponentImplementation("ping", String JavaDoc.class);
185         pico.registerComponentInstance("pong", "pang");
186         try {
187             pico.getComponentInstance(String JavaDoc.class);
188         } catch (AmbiguousComponentResolutionException e) {
189             assertTrue(e.getMessage().indexOf("java.lang.String") != -1);
190         }
191     }
192
193     public void testLookupWithUnregisteredKeyReturnsNull() throws PicoIntrospectionException, PicoInitializationException, AssignabilityRegistrationException, NotConcreteRegistrationException {
194         MutablePicoContainer pico = createPicoContainer(null);
195         assertNull(pico.getComponentInstance(String JavaDoc.class));
196     }
197
198     public void testLookupWithUnregisteredTypeReturnsNull() throws PicoIntrospectionException, PicoInitializationException, AssignabilityRegistrationException, NotConcreteRegistrationException {
199         MutablePicoContainer pico = createPicoContainer(null);
200         assertNull(pico.getComponentInstanceOfType(String JavaDoc.class));
201     }
202
203     public static class ListAdder {
204         public ListAdder(Collection JavaDoc list) {
205             list.add("something");
206         }
207     }
208
209     public void testUnsatisfiableDependenciesExceptionGivesVerboseEnoughErrorMessage() {
210         MutablePicoContainer pico = createPicoContainer(null);
211         pico.registerComponentImplementation(ComponentD.class);
212
213         try {
214             pico.getComponentInstance(ComponentD.class);
215         } catch (UnsatisfiableDependenciesException e) {
216             Set JavaDoc unsatisfiableDependencies = e.getUnsatisfiableDependencies();
217             assertEquals(1, unsatisfiableDependencies.size());
218
219             List JavaDoc list = (List JavaDoc) unsatisfiableDependencies.iterator().next();
220
221             final List JavaDoc expectedList = new ArrayList JavaDoc(2);
222             expectedList.add(ComponentE.class);
223             expectedList.add(ComponentB.class);
224
225             assertEquals(expectedList, list);
226         }
227     }
228
229     public void testUnsatisfiableDependenciesExceptionGivesUnsatisfiedDependencyTypes() {
230         MutablePicoContainer pico = createPicoContainer(null);
231         // D depends on E and B
232
pico.registerComponentImplementation(ComponentD.class);
233
234         // first - do not register any dependency
235
// should yield first unsatisfied dependency
236
try {
237             pico.getComponentInstance(ComponentD.class);
238         } catch (UnsatisfiableDependenciesException e) {
239             Set JavaDoc unsatisfiableDependencies = e.getUnsatisfiableDependencies();
240             assertEquals(1, unsatisfiableDependencies.size());
241             List JavaDoc list = (List JavaDoc) unsatisfiableDependencies.iterator().next();
242             final List JavaDoc expectedList = new ArrayList JavaDoc(2);
243             expectedList.add(ComponentE.class);
244             expectedList.add(ComponentB.class);
245             assertEquals(expectedList, list);
246
247             Class JavaDoc unsatisfiedDependencyType = e.getUnsatisfiedDependencyType();
248             assertNotNull(unsatisfiedDependencyType);
249             assertEquals(ComponentE.class, unsatisfiedDependencyType);
250         }
251         
252         // now register only first dependency
253
// should yield second unsatisfied dependency
254
pico.registerComponentImplementation(ComponentE.class);
255         try {
256             pico.getComponentInstance(ComponentD.class);
257         } catch (UnsatisfiableDependenciesException e) {
258             Set JavaDoc unsatisfiableDependencies = e.getUnsatisfiableDependencies();
259             assertEquals(1, unsatisfiableDependencies.size());
260             List JavaDoc list = (List JavaDoc) unsatisfiableDependencies.iterator().next();
261             final List JavaDoc expectedList = new ArrayList JavaDoc(2);
262             expectedList.add(ComponentE.class);
263             expectedList.add(ComponentB.class);
264             assertEquals(expectedList, list);
265
266             Class JavaDoc unsatisfiedDependencyType = e.getUnsatisfiedDependencyType();
267             assertNotNull(unsatisfiedDependencyType);
268             assertEquals(ComponentB.class, unsatisfiedDependencyType);
269         }
270     }
271     
272     public void testCyclicDependencyThrowsCyclicDependencyException() {
273         assertCyclicDependencyThrowsCyclicDependencyException(createPicoContainer(null));
274     }
275
276     private static void assertCyclicDependencyThrowsCyclicDependencyException(MutablePicoContainer pico) {
277         pico.registerComponentImplementation(ComponentB.class);
278         pico.registerComponentImplementation(ComponentD.class);
279         pico.registerComponentImplementation(ComponentE.class);
280
281         try {
282             pico.getComponentInstance(ComponentD.class);
283             fail("CyclicDependencyException expected");
284         } catch (CyclicDependencyException e) {
285             // CyclicDependencyException reports now the stack.
286
//final List dependencies = Arrays.asList(ComponentD.class.getConstructors()[0].getParameterTypes());
287
final List JavaDoc dependencies = Arrays.asList(new Class JavaDoc[]{ComponentD.class, ComponentE.class, ComponentD.class});
288             final List JavaDoc reportedDependencies = Arrays.asList(e.getDependencies());
289             assertEquals(dependencies, reportedDependencies);
290         } catch (StackOverflowError JavaDoc e) {
291             fail();
292         }
293     }
294
295     public void testCyclicDependencyThrowsCyclicDependencyExceptionWithParentContainer() {
296         MutablePicoContainer pico = createPicoContainer(createPicoContainer(null));
297         assertCyclicDependencyThrowsCyclicDependencyException(pico);
298     }
299
300     public void testRemovalNonRegisteredComponentAdapterWorksAndReturnsNull() {
301         final MutablePicoContainer picoContainer = createPicoContainer(null);
302         assertNull(picoContainer.unregisterComponent("COMPONENT DOES NOT EXIST"));
303     }
304
305     /**
306      * Important! Nanning really, really depends on this!
307      */

308     public void testComponentAdapterRegistrationOrderIsMaintained() {
309
310         ConstructorInjectionComponentAdapter c1 = new ConstructorInjectionComponentAdapter("1", Object JavaDoc.class);
311         ConstructorInjectionComponentAdapter c2 = new ConstructorInjectionComponentAdapter("2", String JavaDoc.class);
312
313         MutablePicoContainer picoContainer = createPicoContainer(null);
314         picoContainer.registerComponent(c1);
315         picoContainer.registerComponent(c2);
316         assertEquals("registration order should be maintained",
317                 Arrays.asList(new Object JavaDoc[]{c1, c2}), picoContainer.getComponentAdapters());
318
319         picoContainer.getComponentInstances(); // create all the instances at once
320
assertFalse("instances should be created in same order as adapters are created",
321                 picoContainer.getComponentInstances().get(0) instanceof String JavaDoc);
322         assertTrue("instances should be created in same order as adapters are created",
323                 picoContainer.getComponentInstances().get(1) instanceof String JavaDoc);
324
325         MutablePicoContainer reversedPicoContainer = createPicoContainer(null);
326         reversedPicoContainer.registerComponent(c2);
327         reversedPicoContainer.registerComponent(c1);
328         assertEquals("registration order should be maintained",
329                 Arrays.asList(new Object JavaDoc[]{c2, c1}), reversedPicoContainer.getComponentAdapters());
330
331         reversedPicoContainer.getComponentInstances(); // create all the instances at once
332
assertTrue("instances should be created in same order as adapters are created",
333                 reversedPicoContainer.getComponentInstances().get(0) instanceof String JavaDoc);
334         assertFalse("instances should be created in same order as adapters are created",
335                 reversedPicoContainer.getComponentInstances().get(1) instanceof String JavaDoc);
336     }
337
338     public static class NeedsTouchable {
339         public Touchable touchable;
340
341         public NeedsTouchable(Touchable touchable) {
342             this.touchable = touchable;
343         }
344     }
345
346     public static class NeedsWashable {
347         public Washable washable;
348
349         public NeedsWashable(Washable washable) {
350             this.washable = washable;
351         }
352     }
353
354     public void testSameInstanceCanBeUsedAsDifferentTypeWhenCaching() {
355         MutablePicoContainer pico = createPicoContainer(null);
356         pico.registerComponentImplementation("wt", WashableTouchable.class);
357         pico.registerComponentImplementation("nw", NeedsWashable.class);
358         pico.registerComponentImplementation("nt", NeedsTouchable.class);
359
360         NeedsWashable nw = (NeedsWashable) pico.getComponentInstance("nw");
361         NeedsTouchable nt = (NeedsTouchable) pico.getComponentInstance("nt");
362         assertSame(nw.washable, nt.touchable);
363     }
364
365     public void testRegisterComponentWithObjectBadType() throws PicoIntrospectionException {
366         MutablePicoContainer pico = createPicoContainer(null);
367
368         try {
369             pico.registerComponentInstance(Serializable JavaDoc.class, new Object JavaDoc());
370             fail("Shouldn't be able to register an Object.class as Serializable because it is not, " +
371                     "it does not implement it, Object.class does not implement much.");
372         } catch (AssignabilityRegistrationException e) {
373         }
374
375     }
376
377     public static class JMSService {
378         public final String JavaDoc serverid;
379         public final String JavaDoc path;
380
381         public JMSService(String JavaDoc serverid, String JavaDoc path) {
382             this.serverid = serverid;
383             this.path = path;
384         }
385     }
386
387     // http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-52
388
public void testPico52() {
389         MutablePicoContainer pico = createPicoContainer(null);
390
391         pico.registerComponentImplementation("foo", JMSService.class, new Parameter[]{
392             new ConstantParameter("0"),
393             new ConstantParameter("something"),
394         });
395         JMSService jms = (JMSService) pico.getComponentInstance("foo");
396         assertEquals("0", jms.serverid);
397         assertEquals("something", jms.path);
398     }
399
400     public static class ComponentA {
401         public ComponentA(ComponentB b, ComponentC c) {
402             Assert.assertNotNull(b);
403             Assert.assertNotNull(c);
404         }
405     }
406
407     public static class ComponentB {
408     }
409
410     public static class ComponentC {
411     }
412
413     public static class ComponentD {
414         public ComponentD(ComponentE e, ComponentB b) {
415             Assert.assertNotNull(e);
416             Assert.assertNotNull(b);
417         }
418     }
419
420     public static class ComponentE {
421         public ComponentE(ComponentD d) {
422             Assert.assertNotNull(d);
423         }
424     }
425
426     public static class ComponentF {
427         public ComponentF(ComponentA a) {
428             Assert.assertNotNull(a);
429         }
430     }
431
432     public void testAggregatedVerificationException() {
433         MutablePicoContainer pico = createPicoContainer(null);
434         pico.registerComponentImplementation(ComponentA.class);
435         pico.registerComponentImplementation(ComponentE.class);
436         try {
437             new VerifyingVisitor().traverse(pico);
438             fail("we expect a PicoVerificationException");
439         } catch (PicoVerificationException e) {
440             List JavaDoc nested = e.getNestedExceptions();
441             assertEquals(2, nested.size());
442             assertTrue(-1 != e.getMessage().indexOf(ComponentA.class.getName()));
443             assertTrue(-1 != e.getMessage().indexOf(ComponentE.class.getName()));
444         }
445     }
446
447     // An adapter has no longer a hosting container.
448

449 // public void testRegistrationOfAdapterSetsHostingContainerAsSelf() {
450
// final InstanceComponentAdapter componentAdapter = new InstanceComponentAdapter("", new Object());
451
// final MutablePicoContainer picoContainer = createPicoContainer(null);
452
// picoContainer.registerComponent(componentAdapter);
453
// assertSame(picoContainer, componentAdapter.getContainer());
454
// }
455

456     public static class ContainerDependency {
457         public ContainerDependency(PicoContainer container) {
458             assertNotNull(container);
459         }
460     }
461
462     // ImplicitPicoContainer injection is bad. It is an open door for hackers. Developers with
463
// special PicoContainer needs should specifically register() a comtainer they want components to
464
// be able to pick up on.
465

466 // public void testImplicitPicoContainerInjection() {
467
// MutablePicoContainer pico = createPicoContainer(null);
468
// pico.registerComponentImplementation(ContainerDependency.class);
469
// ContainerDependency dep = (ContainerDependency) pico.getComponentInstance(ContainerDependency.class);
470
// assertSame(pico, dep.pico);
471
// }
472

473     public void testShouldReturnNullWhenUnregistereingUnmanagedComponent() {
474         final MutablePicoContainer pico = createPicoContainer(null);
475         assertNull(pico.unregisterComponentByInstance("yo"));
476     }
477
478     public void testShouldReturnNullForComponentAdapterOfUnregisteredType() {
479         final MutablePicoContainer pico = createPicoContainer(null);
480         assertNull(pico.getComponentInstanceOfType(List JavaDoc.class));
481     }
482
483     public void testShouldReturnNonMutableParent() {
484         DefaultPicoContainer parent = new DefaultPicoContainer();
485         final MutablePicoContainer picoContainer = createPicoContainer(parent);
486         assertNotSame(parent, picoContainer.getParent());
487         assertFalse(picoContainer.getParent() instanceof MutablePicoContainer);
488     }
489
490     class Foo implements Startable, Disposable {
491         public boolean started;
492         public boolean stopped;
493         public boolean disposed;
494
495         public void start() {
496             started = true;
497         }
498
499         public void stop() {
500             stopped = true;
501         }
502
503         public void dispose() {
504             disposed = true;
505         }
506
507     }
508
509     public void testContainerCascadesDefaultLifecycle() {
510         final MutablePicoContainer picoContainer = createPicoContainer(null);
511         Foo foo = new Foo();
512         picoContainer.registerComponentInstance(foo);
513         picoContainer.start();
514         assertEquals(true, foo.started);
515         picoContainer.stop();
516         assertEquals(true, foo.stopped);
517         picoContainer.dispose();
518         assertEquals(true, foo.disposed);
519     }
520
521     public void testComponentInstancesFromParentsAreNotDirectlyAccessible2() {
522         final MutablePicoContainer a = createPicoContainer(null);
523         final MutablePicoContainer b = createPicoContainer(a);
524         final MutablePicoContainer c = createPicoContainer(b);
525
526         Object JavaDoc ao = new Object JavaDoc();
527         Object JavaDoc bo = new Object JavaDoc();
528         Object JavaDoc co = new Object JavaDoc();
529
530         a.registerComponentInstance("a", ao);
531         b.registerComponentInstance("b", bo);
532         c.registerComponentInstance("c", co);
533
534         assertEquals(1, a.getComponentInstances().size());
535         assertEquals(1, b.getComponentInstances().size());
536         assertEquals(1, c.getComponentInstances().size());
537     }
538
539     public void testStartStopAndDisposeCascadedtoChildren() {
540         final MutablePicoContainer parent = createPicoContainer(null);
541         parent.registerComponentInstance(new StringBuffer JavaDoc());
542         final MutablePicoContainer child = createPicoContainer(parent);
543         parent.addChildContainer(child);
544         child.registerComponentImplementation(LifeCycleMonitoring.class);
545         parent.start();
546         try {
547             child.start();
548             fail("IllegalStateException expected");
549         } catch (IllegalStateException JavaDoc e) {
550             assertEquals("child already started", "Already started", e.getMessage());
551         }
552         parent.stop();
553         try {
554             child.stop();
555             fail("IllegalStateException expected");
556         } catch (IllegalStateException JavaDoc e) {
557             assertEquals("child not started", "Not started", e.getMessage());
558         }
559         parent.dispose();
560         try {
561             child.dispose();
562             fail("IllegalStateException expected");
563         } catch (IllegalStateException JavaDoc e) {
564             assertEquals("child already disposed", "Already disposed", e.getMessage());
565         }
566
567     }
568
569     public void testMakingOfChildContainer() {
570         final MutablePicoContainer parent = createPicoContainer(null);
571         MutablePicoContainer child = parent.makeChildContainer();
572         assertNotNull(child);
573     }
574
575     public void testMakingOfChildContainerPercolatesLifecycleManager() {
576         final MutablePicoContainer parent = createPicoContainer(null);
577         parent.registerComponentImplementation("one", TestLifecycleComponent.class);
578         MutablePicoContainer child = parent.makeChildContainer();
579         assertNotNull(child);
580         child.registerComponentImplementation("two", TestLifecycleComponent.class);
581         parent.start();
582         try {
583             child.start();
584         } catch (IllegalStateException JavaDoc e) {
585             assertEquals("child already started", "Already started", e.getMessage());
586         }
587         //TODO - The LifecycleManager reference in child containers is not used. Thus is is almost pointless
588
// The reason is because DefaultPicoContainer's accept() method visits child containers' on its own.
589
// This may be file for visiting components in a tree for general cases, but for lifecycle, we
590
// should hand to each LifecycleManager's start(..) at each appropriate node. See mail-list discussion.
591
}
592
593     public static class TestLifecycleManager implements LifecycleManager {
594         public ArrayList JavaDoc started = new ArrayList JavaDoc();
595         public void start(PicoContainer node) {
596             started.add(node);
597         }
598
599         public void stop(PicoContainer node) {
600         }
601
602         public void dispose(PicoContainer node) {
603         }
604
605         public boolean hasLifecycle() {
606             return true;
607         }
608     }
609
610     public static class TestLifecycleComponent implements Startable {
611         public boolean started;
612         public void start() {
613             started = true;
614         }
615         public void stop() {
616         }
617     }
618
619     public void testStartStopAndDisposeNotCascadedtoRemovedChildren() {
620         final MutablePicoContainer parent = createPicoContainer(null);
621         parent.registerComponentInstance(new StringBuffer JavaDoc());
622         StringBuffer JavaDoc sb = (StringBuffer JavaDoc) parent.getComponentInstancesOfType(StringBuffer JavaDoc.class).get(0);
623
624         final MutablePicoContainer child = createPicoContainer(parent);
625         assertTrue(parent.addChildContainer(child));
626         child.registerComponentImplementation(LifeCycleMonitoring.class);
627         assertTrue(parent.removeChildContainer(child));
628         parent.start();
629         assertTrue(sb.toString().indexOf("-started") == -1);
630         parent.stop();
631         assertTrue(sb.toString().indexOf("-stopped") == -1);
632         parent.dispose();
633         assertTrue(sb.toString().indexOf("-disposed") == -1);
634     }
635
636     public void testShouldCascadeStartStopAndDisposeToChild() {
637
638         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
639         final MutablePicoContainer parent = createPicoContainer(null);
640         parent.registerComponentInstance(sb);
641         parent.registerComponentImplementation(Map JavaDoc.class, HashMap JavaDoc.class);
642
643         final MutablePicoContainer child = parent.makeChildContainer();
644         child.registerComponentImplementation(LifeCycleMonitoring.class);
645
646         Map JavaDoc map = (Map JavaDoc) parent.getComponentInstance(Map JavaDoc.class);
647         assertNotNull(map);
648         parent.start();
649         try {
650             child.start();
651             fail("IllegalStateException expected");
652         } catch (IllegalStateException JavaDoc e) {
653             assertEquals("child already started", "Already started", e.getMessage());
654         }
655         parent.stop();
656         try {
657             child.stop();
658             fail("IllegalStateException expected");
659         } catch (IllegalStateException JavaDoc e) {
660             assertEquals("child not started", "Not started", e.getMessage());
661         }
662         parent.dispose();
663         try {
664             child.dispose();
665             fail("IllegalStateException expected");
666         } catch (IllegalStateException JavaDoc e) {
667             assertEquals("child already disposed", "Already disposed", e.getMessage());
668         }
669     }
670
671     public static class LifeCycleMonitoring implements Startable, Disposable {
672         StringBuffer JavaDoc sb;
673
674         public LifeCycleMonitoring(StringBuffer JavaDoc sb) {
675             this.sb = sb;
676             sb.append("-instantiated");
677         }
678
679         public void start() {
680             sb.append("-started");
681         }
682
683         public void stop() {
684             sb.append("-stopped");
685         }
686
687         public void dispose() {
688             sb.append("-disposed");
689         }
690     }
691
692     public static class RecordingStrategyVisitor extends AbstractPicoVisitor {
693
694         private final List JavaDoc list;
695
696         public RecordingStrategyVisitor(List JavaDoc list) {
697             this.list = list;
698         }
699
700         public void visitContainer(PicoContainer pico) {
701             list.add(pico);
702         }
703
704         public void visitComponentAdapter(ComponentAdapter componentAdapter) {
705             list.add(componentAdapter);
706         }
707
708         public void visitParameter(Parameter parameter) {
709             list.add(parameter);
710         }
711
712     }
713
714     public void testAcceptImplementsBreadthFirstStrategy() {
715         final MutablePicoContainer parent = createPicoContainer(null);
716         final MutablePicoContainer child = parent.makeChildContainer();
717         ComponentAdapter hashMapAdapter = parent.registerComponent(new ConstructorInjectionComponentAdapter(HashMap JavaDoc.class, HashMap JavaDoc.class));
718         ComponentAdapter hashSetAdapter = parent.registerComponent(new ConstructorInjectionComponentAdapter(HashSet JavaDoc.class, HashSet JavaDoc.class));
719         ComponentAdapter stringAdapter = parent.registerComponent(new InstanceComponentAdapter(String JavaDoc.class, "foo"));
720         ComponentAdapter arrayListAdapter = child.registerComponent(new ConstructorInjectionComponentAdapter(ArrayList JavaDoc.class, ArrayList JavaDoc.class));
721         Parameter componentParameter = BasicComponentParameter.BASIC_DEFAULT;
722         Parameter throwableParameter = new ConstantParameter(new Throwable JavaDoc("bar"));
723         ComponentAdapter exceptionAdapter = child.registerComponent(new ConstructorInjectionComponentAdapter(Exception JavaDoc.class, Exception JavaDoc.class, new Parameter[]{
724             componentParameter,
725             throwableParameter
726         }));
727
728         List JavaDoc expectedList = Arrays.asList(new Object JavaDoc[]{
729             parent,
730             hashMapAdapter,
731             hashSetAdapter,
732             stringAdapter,
733             child,
734             arrayListAdapter,
735             exceptionAdapter,
736             componentParameter,
737             throwableParameter
738         });
739         List JavaDoc visitedList = new LinkedList JavaDoc();
740         PicoVisitor visitor = new RecordingStrategyVisitor(visitedList);
741         visitor.traverse(parent);
742         assertEquals(expectedList, visitedList);
743     }
744
745     public void testAmbiguousDependencies() throws PicoRegistrationException, PicoInitializationException {
746
747         MutablePicoContainer pico = this.createPicoContainer(null);
748
749         // Register two Touchables that Fred will be confused about
750
pico.registerComponentImplementation(SimpleTouchable.class);
751         pico.registerComponentImplementation(DerivedTouchable.class);
752
753         // Register a confused DependsOnTouchable
754
pico.registerComponentImplementation(DependsOnTouchable.class);
755
756         try {
757             pico.getComponentInstance(DependsOnTouchable.class);
758             fail("DependsOnTouchable should have been confused about the two Touchables");
759         } catch (AmbiguousComponentResolutionException e) {
760             List JavaDoc componentImplementations = Arrays.asList(e.getAmbiguousComponentKeys());
761             assertTrue(componentImplementations.contains(DerivedTouchable.class));
762             assertTrue(componentImplementations.contains(SimpleTouchable.class));
763
764             assertTrue(e.getMessage().indexOf(DerivedTouchable.class.getName()) != -1);
765         }
766     }
767
768
769     public static class DerivedTouchable extends SimpleTouchable {
770         public DerivedTouchable() {
771         }
772     }
773
774 }
775
Popular Tags