KickJava   Java API By Example, From Geeks To Geeks.

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


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 Joerg Schaible *
9  *****************************************************************************/

10 package org.picocontainer.tck;
11
12 import com.thoughtworks.xstream.XStream;
13 import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
14 import com.thoughtworks.xstream.io.xml.XppDriver;
15
16 import junit.framework.Assert;
17 import junit.framework.AssertionFailedError;
18
19 import org.picocontainer.ComponentAdapter;
20 import org.picocontainer.MutablePicoContainer;
21 import org.picocontainer.Parameter;
22 import org.picocontainer.PicoContainer;
23 import org.picocontainer.PicoInitializationException;
24 import org.picocontainer.PicoIntrospectionException;
25 import org.picocontainer.defaults.AbstractPicoVisitor;
26 import org.picocontainer.defaults.ComponentAdapterFactory;
27 import org.picocontainer.defaults.ConstantParameter;
28 import org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory;
29 import org.picocontainer.defaults.CyclicDependencyException;
30 import org.picocontainer.defaults.DecoratingComponentAdapter;
31 import org.picocontainer.defaults.DefaultComponentAdapterFactory;
32 import org.picocontainer.defaults.DefaultPicoContainer;
33 import org.picocontainer.defaults.LifecycleStrategy;
34 import org.picocontainer.defaults.ObjectReference;
35 import org.picocontainer.defaults.PicoInvocationTargetInitializationException;
36 import org.picocontainer.defaults.SimpleReference;
37
38 import org.jmock.MockObjectTestCase;
39
40 import java.io.ByteArrayInputStream JavaDoc;
41 import java.io.ByteArrayOutputStream JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.io.ObjectInputStream JavaDoc;
44 import java.io.ObjectOutputStream JavaDoc;
45 import java.lang.reflect.Constructor JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.Collection JavaDoc;
48 import java.util.HashSet JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.LinkedList JavaDoc;
51 import java.util.List JavaDoc;
52 import java.util.Set JavaDoc;
53
54
55 /**
56  * Test suite for a ComponentAdapter implementation.
57  *
58  * @author Jörg Schaible
59  * @since 1.1
60  */

61 public abstract class AbstractComponentAdapterTestCase extends MockObjectTestCase {
62
63     public static int SERIALIZABLE = 1;
64     public static int VERIFYING = 2;
65     public static int INSTANTIATING = 4;
66     public static int RESOLVING = 8;
67
68     protected abstract Class JavaDoc getComponentAdapterType();
69
70     protected int getComponentAdapterNature() {
71         return SERIALIZABLE | VERIFYING | INSTANTIATING | RESOLVING;
72     }
73
74     protected ComponentAdapterFactory createDefaultComponentAdapterFactory() {
75         return new DefaultComponentAdapterFactory();
76     }
77
78     // ============================================
79
// Default
80
// ============================================
81

82     /**
83      * Prepare the test <em>verifyWithoutDependencyWorks</em>.
84      *
85      * @param picoContainer container, may probably not be used.
86      * @return a ComponentAdapter of the type to test for a component without dependencies. Registration in the pico is
87      * not necessary.
88      */

89     protected abstract ComponentAdapter prepDEF_verifyWithoutDependencyWorks(MutablePicoContainer picoContainer);
90
91     final public void testDEF_verifyWithoutDependencyWorks() {
92         final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
93         final ComponentAdapter componentAdapter = prepDEF_verifyWithoutDependencyWorks(picoContainer);
94         assertSame(getComponentAdapterType(), componentAdapter.getClass());
95         componentAdapter.verify(picoContainer);
96     }
97
98     /**
99      * Prepare the test <em>verifyDoesNotInstantiate</em>.
100      *
101      * @param picoContainer container, may probably not be used.
102      * @return a ComponentAdapter of the type to test for a component that may throw on instantiation. Registration in
103      * the pico is not necessary.
104      */

105     protected abstract ComponentAdapter prepDEF_verifyDoesNotInstantiate(MutablePicoContainer picoContainer);
106
107     final public void testDEF_verifyDoesNotInstantiate() {
108         final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
109         final ComponentAdapter componentAdapter = prepDEF_verifyDoesNotInstantiate(picoContainer);
110         assertSame(getComponentAdapterType(), componentAdapter.getClass());
111         final ComponentAdapter notInstantiatablecomponentAdapter = new NotInstantiatableComponentAdapter(
112                 componentAdapter);
113         final PicoContainer wrappedPicoContainer = wrapComponentInstances(
114                 NotInstantiatableComponentAdapter.class, picoContainer, null);
115         notInstantiatablecomponentAdapter.verify(wrappedPicoContainer);
116     }
117
118     /**
119      * Prepare the test <em>visitable</em>.
120      *
121      * @return a ComponentAdapter of the type to test. If the ComponentAdapter supports {@link Parameter}, you have to
122      * select a component, that have some.
123      */

124     protected abstract ComponentAdapter prepDEF_visitable();
125
126     final public void testDEF_visitable() {
127         final ComponentAdapter componentAdapter = prepDEF_visitable();
128         final Class JavaDoc type = getComponentAdapterType();
129         assertSame(type, componentAdapter.getClass());
130         boolean hasParameters = supportsParameters(type);
131         final RecordingVisitor visitor = new RecordingVisitor();
132         visitor.traverse(componentAdapter);
133         final List JavaDoc visitedElements = new ArrayList JavaDoc(visitor.getVisitedElements());
134         assertSame(componentAdapter, visitedElements.get(0));
135         if (hasParameters) {
136             hasParameters = false;
137             for (final Iterator JavaDoc iter = visitedElements.iterator(); iter.hasNext() && !hasParameters;) {
138                 hasParameters = Parameter.class.isAssignableFrom(iter.next().getClass());
139             }
140             assertTrue("ComponentAdapter " + type + " supports parameters, provide some", hasParameters);
141         }
142     }
143
144     /**
145      * Prepare the test <em>isAbleToTakeParameters</em>. Overload this function, if the ComponentAdapter to test
146      * supports {@link Parameter}.
147      *
148      * @param picoContainer container, may probably not be used.
149      * @return a ComponentAdapter of the type to test. Select a component, that has some parameters. Registration in the
150      * pico is not necessary.
151      */

152     protected ComponentAdapter prepDEF_isAbleToTakeParameters(MutablePicoContainer picoContainer) {
153         final Class JavaDoc type = getComponentAdapterType();
154         boolean hasParameters = supportsParameters(type);
155         if (hasParameters) {
156             fail("You have to overwrite this method for a useful test");
157         }
158         return null;
159     }
160
161     final public void testDEF_isAbleToTakeParameters() {
162         final Class JavaDoc type = getComponentAdapterType();
163         boolean hasParameters = supportsParameters(type);
164         if (hasParameters) {
165             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
166             final ComponentAdapter componentAdapter = prepDEF_isAbleToTakeParameters(picoContainer);
167             assertSame(getComponentAdapterType(), componentAdapter.getClass());
168             final RecordingVisitor visitor = new RecordingVisitor();
169             visitor.traverse(componentAdapter);
170             final List JavaDoc visitedElements = visitor.getVisitedElements();
171             if (hasParameters) {
172                 hasParameters = false;
173                 for (final Iterator JavaDoc iter = visitedElements.iterator(); iter.hasNext() && !hasParameters;) {
174                     hasParameters = Parameter.class.isAssignableFrom(iter.next().getClass());
175                 }
176                 assertTrue("ComponentAdapter " + type + " supports parameters, provide some", hasParameters);
177             }
178             final Object JavaDoc instance = componentAdapter.getComponentInstance(picoContainer);
179             assertNotNull(instance);
180         }
181     }
182
183     // ============================================
184
// Serializable
185
// ============================================
186

187     /**
188      * Prepare the test <em>isSerializable</em>. Overload this function, if the ComponentAdapter supports
189      * serialization.
190      *
191      * @param picoContainer container, may probably not be used.
192      * @return a ComponentAdapter of the type to test. Registration in the pico is not necessary.
193      */

194     protected ComponentAdapter prepSER_isSerializable(MutablePicoContainer picoContainer) {
195         throw new AssertionFailedError("You have to overwrite this method for a useful test");
196     }
197
198     final public void testSER_isSerializable() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
199         if ((getComponentAdapterNature() & SERIALIZABLE) > 0) {
200             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
201             final ComponentAdapter componentAdapter = prepSER_isSerializable(picoContainer);
202             assertSame(getComponentAdapterType(), componentAdapter.getClass());
203             final Object JavaDoc instance = componentAdapter.getComponentInstance(picoContainer);
204             assertNotNull(instance);
205             final ByteArrayOutputStream JavaDoc byteArrayOutputStream = new ByteArrayOutputStream JavaDoc();
206             final ObjectOutputStream JavaDoc outputStream = new ObjectOutputStream JavaDoc(byteArrayOutputStream);
207             outputStream.writeObject(componentAdapter);
208             outputStream.close();
209             final ObjectInputStream JavaDoc inputStream = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(byteArrayOutputStream
210                     .toByteArray()));
211             final ComponentAdapter serializedComponentAdapter = (ComponentAdapter)inputStream.readObject();
212             inputStream.close();
213             assertEquals(componentAdapter.getComponentKey(), serializedComponentAdapter.getComponentKey());
214             final Object JavaDoc instanceAfterSerialization = serializedComponentAdapter.getComponentInstance(picoContainer);
215             assertNotNull(instanceAfterSerialization);
216             assertSame(instance.getClass(), instanceAfterSerialization.getClass());
217         }
218     }
219
220     /**
221      * Prepare the test <em>isXStreamSerializable</em>. Overload this function, if the ComponentAdapter supports
222      * serialization.
223      *
224      * @param picoContainer container, may probably not be used.
225      * @return a ComponentAdapter of the type to test. Registration in the pico is not necessary.
226      */

227     protected ComponentAdapter prepSER_isXStreamSerializable(MutablePicoContainer picoContainer) {
228         throw new AssertionFailedError("You have to overwrite this method for a useful test");
229     }
230
231     final public void testSER_isXStreamSerializableWithPureReflection() {
232         if ((getComponentAdapterNature() & SERIALIZABLE) > 0) {
233             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
234             final ComponentAdapter componentAdapter = prepSER_isXStreamSerializable(picoContainer);
235             assertSame(getComponentAdapterType(), componentAdapter.getClass());
236             final Object JavaDoc instance = componentAdapter.getComponentInstance(picoContainer);
237             assertNotNull(instance);
238             final XStream xstream = new XStream(new PureJavaReflectionProvider(), new XppDriver());
239             final String JavaDoc xml = xstream.toXML(componentAdapter);
240             final ComponentAdapter serializedComponentAdapter = (ComponentAdapter)xstream.fromXML(xml);
241             assertEquals(componentAdapter.getComponentKey(), serializedComponentAdapter.getComponentKey());
242             final Object JavaDoc instanceAfterSerialization = serializedComponentAdapter.getComponentInstance(picoContainer);
243             assertNotNull(instanceAfterSerialization);
244             assertSame(instance.getClass(), instanceAfterSerialization.getClass());
245         }
246     }
247
248     final public void testSER_isXStreamSerializable() {
249         if ((getComponentAdapterNature() & SERIALIZABLE) > 0) {
250             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
251             final ComponentAdapter componentAdapter = prepSER_isXStreamSerializable(picoContainer);
252             assertSame(getComponentAdapterType(), componentAdapter.getClass());
253             final Object JavaDoc instance = componentAdapter.getComponentInstance(picoContainer);
254             assertNotNull(instance);
255             final XStream xstream = new XStream(new XppDriver());
256             final String JavaDoc xml = xstream.toXML(componentAdapter);
257             final ComponentAdapter serializedComponentAdapter = (ComponentAdapter)xstream.fromXML(xml);
258             assertEquals(componentAdapter.getComponentKey(), serializedComponentAdapter.getComponentKey());
259             final Object JavaDoc instanceAfterSerialization = serializedComponentAdapter.getComponentInstance(picoContainer);
260             assertNotNull(instanceAfterSerialization);
261             assertSame(instance.getClass(), instanceAfterSerialization.getClass());
262         }
263     }
264
265     // ============================================
266
// Verifying
267
// ============================================
268

269     /**
270      * Prepare the test <em>verificationFailsWithUnsatisfiedDependency</em>. Overload this function, if the
271      * ComponentAdapter's verification can fail e.g. due to an unresolved dependency.
272      *
273      * @param picoContainer container, may probably not be used.
274      * @return a ComponentAdapter of the type to test, that fails for the verification, e.g. because of a compoennt with
275      * missing dependencies. Registration in the pico is not necessary.
276      */

277     protected ComponentAdapter prepVER_verificationFails(MutablePicoContainer picoContainer) {
278         throw new AssertionFailedError("You have to overwrite this method for a useful test");
279     }
280
281     final public void testVER_verificationFails() {
282         if ((getComponentAdapterNature() & VERIFYING) > 0) {
283             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
284             final ComponentAdapter componentAdapter = prepVER_verificationFails(picoContainer);
285             assertSame(getComponentAdapterType(), componentAdapter.getClass());
286             try {
287                 componentAdapter.verify(picoContainer);
288                 fail("PicoIntrospectionException expected");
289             } catch (PicoIntrospectionException e) {
290             } catch (Exception JavaDoc e) {
291                 fail("PicoIntrospectionException expected, but got " + e.getClass().getName());
292             }
293             try {
294                 componentAdapter.getComponentInstance(picoContainer);
295                 fail("PicoInitializationException or PicoIntrospectionException expected");
296             } catch (PicoInitializationException e) {
297             } catch (PicoIntrospectionException e) {
298             } catch (Exception JavaDoc e) {
299                 fail("PicoInitializationException or PicoIntrospectionException expected, but got "
300                         + e.getClass().getName());
301             }
302         }
303     }
304
305     // ============================================
306
// Instantiating
307
// ============================================
308

309     /**
310      * Prepare the test <em>createsNewInstances</em>. Overload this function, if the ComponentAdapter is
311      * instantiating. It should create a new instance with every call.
312      *
313      * @param picoContainer container, may probably not be used.
314      * @return a ComponentAdapter of the type to test. Registration in the pico is not necessary.
315      */

316     protected ComponentAdapter prepINS_createsNewInstances(MutablePicoContainer picoContainer) {
317         throw new AssertionFailedError("You have to overwrite this method for a useful test");
318     }
319
320     final public void testINS_createsNewInstances() {
321         if ((getComponentAdapterNature() & INSTANTIATING) > 0) {
322             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
323             final ComponentAdapter componentAdapter = prepINS_createsNewInstances(picoContainer);
324             assertSame(getComponentAdapterType(), componentAdapter.getClass());
325             final Object JavaDoc instance = componentAdapter.getComponentInstance(picoContainer);
326             assertNotNull(instance);
327             assertNotSame(instance, componentAdapter.getComponentInstance(picoContainer));
328             assertSame(instance.getClass(), componentAdapter.getComponentInstance(picoContainer).getClass());
329         }
330     }
331
332     /**
333      * Prepare the test <em>errorIsRethrown</em>. Overload this function, if the ComponentAdapter is instantiating.
334      *
335      * @param picoContainer container, may probably not be used.
336      * @return a ComponentAdapter of the type to test with a component that fails with an {@link Error} at
337      * instantiation. Registration in the pico is not necessary.
338      */

339     protected ComponentAdapter prepINS_errorIsRethrown(MutablePicoContainer picoContainer) {
340         throw new AssertionFailedError("You have to overwrite this method for a useful test");
341     }
342
343     final public void testINS_errorIsRethrown() {
344         if ((getComponentAdapterNature() & INSTANTIATING) > 0) {
345             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
346             final ComponentAdapter componentAdapter = prepINS_errorIsRethrown(picoContainer);
347             assertSame(getComponentAdapterType(), componentAdapter.getClass());
348             try {
349                 componentAdapter.getComponentInstance(picoContainer);
350                 fail("Thrown Error excpected");
351             } catch (final Error JavaDoc e) {
352                 assertEquals("test", e.getMessage());
353             }
354         }
355     }
356
357     /**
358      * Prepare the test <em>runtimeExceptionIsRethrown</em>. Overload this function, if the ComponentAdapter is
359      * instantiating.
360      *
361      * @param picoContainer container, may probably not be used.
362      * @return a ComponentAdapter of the type to test with a component that fails with a {@link RuntimeException} at
363      * instantiation. Registration in the pico is not necessary.
364      */

365     protected ComponentAdapter prepINS_runtimeExceptionIsRethrown(MutablePicoContainer picoContainer) {
366         throw new AssertionFailedError("You have to overwrite this method for a useful test");
367     }
368
369     final public void testINS_runtimeExceptionIsRethrown() {
370         if ((getComponentAdapterNature() & INSTANTIATING) > 0) {
371             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
372             final ComponentAdapter componentAdapter = prepINS_runtimeExceptionIsRethrown(picoContainer);
373             assertSame(getComponentAdapterType(), componentAdapter.getClass());
374             try {
375                 componentAdapter.getComponentInstance(picoContainer);
376                 fail("Thrown RuntimeException excpected");
377             } catch (final RuntimeException JavaDoc e) {
378                 assertEquals("test", e.getMessage());
379             }
380         }
381     }
382
383     /**
384      * Prepare the test <em>normalExceptionIsRethrownInsidePicoInvocationTargetInitializationException</em>. Overload
385      * this function, if the ComponentAdapter is instantiating.
386      *
387      * @param picoContainer container, may probably not be used.
388      * @return a ComponentAdapter of the type to test with a component that fails with a
389      * {@link PicoInvocationTargetInitializationException} at instantiation. Registration in the pico is not
390      * necessary.
391      */

392     protected ComponentAdapter prepINS_normalExceptionIsRethrownInsidePicoInvocationTargetInitializationException(
393             MutablePicoContainer picoContainer) {
394         throw new AssertionFailedError("You have to overwrite this method for a useful test");
395     }
396
397     final public void testINS_normalExceptionIsRethrownInsidePicoInvocationTargetInitializationException() {
398         if ((getComponentAdapterNature() & INSTANTIATING) > 0) {
399             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
400             final ComponentAdapter componentAdapter = prepINS_normalExceptionIsRethrownInsidePicoInvocationTargetInitializationException(picoContainer);
401             assertSame(getComponentAdapterType(), componentAdapter.getClass());
402             try {
403                 componentAdapter.getComponentInstance(picoContainer);
404                 fail("Thrown PicoInvocationTargetInitializationException excpected");
405             } catch (final PicoInvocationTargetInitializationException e) {
406                 assertTrue(e.getMessage().endsWith("test"));
407                 assertTrue(e.getCause() instanceof Exception JavaDoc);
408             }
409         }
410     }
411
412     // ============================================
413
// Resolving
414
// ============================================
415

416     /**
417      * Prepare the test <em>dependenciesAreResolved</em>. Overload this function, if the ComponentAdapter is resolves
418      * dependencies.
419      *
420      * @param picoContainer container, used to register dependencies.
421      * @return a ComponentAdapter of the type to test with a component that has dependencies. Registration in the pico
422      * is not necessary.
423      */

424     protected ComponentAdapter prepRES_dependenciesAreResolved(MutablePicoContainer picoContainer) {
425         throw new AssertionFailedError("You have to overwrite this method for a useful test");
426     }
427
428     final public void testRES_dependenciesAreResolved() {
429         if ((getComponentAdapterNature() & RESOLVING) > 0) {
430             final List JavaDoc dependencies = new LinkedList JavaDoc();
431             final Object JavaDoc[] wrapperDependencies = new Object JavaDoc[]{dependencies};
432             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
433             final ComponentAdapter componentAdapter = prepRES_dependenciesAreResolved(picoContainer);
434             assertSame(getComponentAdapterType(), componentAdapter.getClass());
435             assertFalse(picoContainer.getComponentAdapters().contains(componentAdapter));
436             final PicoContainer wrappedPicoContainer = wrapComponentInstances(
437                     CollectingComponentAdapter.class, picoContainer, wrapperDependencies);
438             final Object JavaDoc instance = componentAdapter.getComponentInstance(wrappedPicoContainer);
439             assertNotNull(instance);
440             assertTrue(dependencies.size() > 0);
441         }
442     }
443
444     /**
445      * Prepare the test <em>failingVerificationWithCyclicDependencyException</em>. Overload this function, if the
446      * ComponentAdapter is resolves dependencies.
447      *
448      * @param picoContainer container, used to register dependencies.
449      * @return a ComponentAdapter of the type to test with a component that has cyclic dependencies. You have to
450      * register the component itself in the pico.
451      */

452     protected ComponentAdapter prepRES_failingVerificationWithCyclicDependencyException(
453             MutablePicoContainer picoContainer) {
454         throw new AssertionFailedError("You have to overwrite this method for a useful test");
455     }
456
457     final public void testRES_failingVerificationWithCyclicDependencyException() {
458         if ((getComponentAdapterNature() & RESOLVING) > 0) {
459             final Set JavaDoc cycleInstances = new HashSet JavaDoc();
460             final ObjectReference cycleCheck = new SimpleReference();
461             final Object JavaDoc[] wrapperDependencies = new Object JavaDoc[]{cycleInstances, cycleCheck};
462             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
463             final ComponentAdapter componentAdapter = prepRES_failingVerificationWithCyclicDependencyException(picoContainer);
464             assertSame(getComponentAdapterType(), componentAdapter.getClass());
465             assertTrue(picoContainer.getComponentAdapters().contains(componentAdapter));
466             final PicoContainer wrappedPicoContainer = wrapComponentInstances(
467                     CycleDetectorComponentAdapter.class, picoContainer, wrapperDependencies);
468             try {
469                 componentAdapter.verify(wrappedPicoContainer);
470                 fail("Thrown PicoVerificationException excpected");
471             } catch (final CyclicDependencyException cycle) {
472                 final Class JavaDoc[] dependencies = cycle.getDependencies();
473                 assertSame(dependencies[0], dependencies[dependencies.length - 1]);
474             }
475         }
476     }
477
478     /**
479      * Prepare the test <em>failingInstantiationWithCyclicDependencyException</em>. Overload this function, if the
480      * ComponentAdapter is resolves dependencies.
481      *
482      * @param picoContainer container, used to register dependencies.
483      * @return a ComponentAdapter of the type to test with a component that has cyclic dependencies. You have to
484      * register the component itself in the pico.
485      */

486     protected ComponentAdapter prepRES_failingInstantiationWithCyclicDependencyException(
487             MutablePicoContainer picoContainer) {
488         throw new AssertionFailedError("You have to overwrite this method for a useful test");
489     }
490
491     final public void testRES_failingInstantiationWithCyclicDependencyException() {
492         if ((getComponentAdapterNature() & RESOLVING) > 0) {
493             final Set JavaDoc cycleInstances = new HashSet JavaDoc();
494             final ObjectReference cycleCheck = new SimpleReference();
495             final Object JavaDoc[] wrapperDependencies = new Object JavaDoc[]{cycleInstances, cycleCheck};
496             final MutablePicoContainer picoContainer = new DefaultPicoContainer(createDefaultComponentAdapterFactory());
497             final ComponentAdapter componentAdapter = prepRES_failingInstantiationWithCyclicDependencyException(picoContainer);
498             assertSame(getComponentAdapterType(), componentAdapter.getClass());
499             assertTrue(picoContainer.getComponentAdapters().contains(componentAdapter));
500             final PicoContainer wrappedPicoContainer = wrapComponentInstances(
501                     CycleDetectorComponentAdapter.class, picoContainer, wrapperDependencies);
502             try {
503                 componentAdapter.getComponentInstance(wrappedPicoContainer);
504                 fail("Thrown CyclicDependencyException excpected");
505             } catch (final CyclicDependencyException e) {
506                 final Class JavaDoc[] dependencies = e.getDependencies();
507                 assertSame(dependencies[0], dependencies[dependencies.length - 1]);
508             }
509         }
510     }
511
512     // ============================================
513
// Model & Helpers
514
// ============================================
515

516     static class RecordingVisitor extends AbstractPicoVisitor {
517         private final List JavaDoc visitedElements = new LinkedList JavaDoc();
518
519         public void visitContainer(PicoContainer pico) {
520             visitedElements.add(pico);
521         }
522
523         public void visitComponentAdapter(ComponentAdapter componentAdapter) {
524             visitedElements.add(componentAdapter);
525         }
526
527         public void visitParameter(Parameter parameter) {
528             visitedElements.add(parameter);
529         }
530
531         List JavaDoc getVisitedElements() {
532             return visitedElements;
533         }
534     }
535
536     static public class NotInstantiatableComponentAdapter extends DecoratingComponentAdapter {
537         public NotInstantiatableComponentAdapter(final ComponentAdapter delegate) {
538             super(delegate);
539         }
540
541         public Object JavaDoc getComponentInstance(final PicoContainer container) {
542             Assert.fail("Not instantiatable");
543             return null;
544         }
545     }
546
547     static public class CollectingComponentAdapter extends DecoratingComponentAdapter {
548         final List JavaDoc list;
549
550         public CollectingComponentAdapter(final ComponentAdapter delegate, final List JavaDoc list) {
551             super(delegate);
552             this.list = list;
553         }
554
555         public Object JavaDoc getComponentInstance(final PicoContainer container) {
556             final Object JavaDoc result = super.getComponentInstance(container);
557             list.add(result);
558             return result;
559         }
560     }
561
562     static public class CycleDetectorComponentAdapter extends DecoratingComponentAdapter {
563         private final Set JavaDoc set;
564         private final ObjectReference reference;
565
566         public CycleDetectorComponentAdapter(
567                 final ComponentAdapter delegate, final Set JavaDoc set, final ObjectReference reference) {
568             super(delegate);
569             this.set = set;
570             this.reference = reference;
571         }
572
573         public Object JavaDoc getComponentInstance(final PicoContainer container) {
574             if (set.contains(this)) {
575                 reference.set(this);
576             } else {
577                 set.add(this);
578             }
579             return super.getComponentInstance(container);
580         }
581     }
582
583     public static class RecordingLifecycleStrategy implements LifecycleStrategy {
584         private StringBuffer JavaDoc recorder;
585         
586         public RecordingLifecycleStrategy(StringBuffer JavaDoc recorder) {
587             this.recorder = recorder;
588         }
589     
590         public void start(Object JavaDoc component) {
591             recorder.append("<start");
592         }
593     
594         public void stop(Object JavaDoc component) {
595             recorder.append("<stop");
596         }
597     
598         public void dispose(Object JavaDoc component) {
599             recorder.append("<dispose");
600         }
601         
602         public boolean hasLifecycle(Class JavaDoc type) {
603             return true;
604         }
605         
606         public String JavaDoc recording() {
607             return recorder.toString();
608         }
609     }
610
611     final protected PicoContainer wrapComponentInstances(
612             final Class JavaDoc decoratingComponentAdapterClass, final PicoContainer picoContainer,
613             final Object JavaDoc[] wrapperDependencies) {
614         assertTrue(DecoratingComponentAdapter.class.isAssignableFrom(decoratingComponentAdapterClass));
615         final MutablePicoContainer mutablePicoContainer = new DefaultPicoContainer();
616         final int size = (wrapperDependencies != null ? wrapperDependencies.length : 0) + 1;
617         final Collection JavaDoc allComponentAdapters = picoContainer.getComponentAdapters();
618         for (final Iterator JavaDoc iter = allComponentAdapters.iterator(); iter.hasNext();) {
619             final Parameter[] parameters = new Parameter[size];
620             parameters[0] = new ConstantParameter(iter.next());
621             for (int i = 1; i < parameters.length; i++) {
622                 parameters[i] = new ConstantParameter(wrapperDependencies[i - 1]);
623             }
624             final MutablePicoContainer instantiatingPicoContainer = new DefaultPicoContainer(
625                     new ConstructorInjectionComponentAdapterFactory());
626             instantiatingPicoContainer.registerComponentImplementation(
627                     "decorator", decoratingComponentAdapterClass, parameters);
628             mutablePicoContainer.registerComponent((ComponentAdapter)instantiatingPicoContainer
629                     .getComponentInstance("decorator"));
630         }
631         return mutablePicoContainer;
632     }
633
634     private boolean supportsParameters(final Class JavaDoc type) {
635         boolean hasParameters = false;
636         final Constructor JavaDoc[] constructors = type.getConstructors();
637         for (int i = 0; i < constructors.length && !hasParameters; i++) {
638             final Constructor JavaDoc constructor = constructors[i];
639             final Class JavaDoc[] parameterTypes = constructor.getParameterTypes();
640             for (int j = 0; j < parameterTypes.length; j++) {
641                 final Class JavaDoc parameterType = parameterTypes[j];
642                 if (Parameter.class.isAssignableFrom(parameterType)
643                         || (parameterType.isArray() && Parameter.class.isAssignableFrom(parameterType
644                                 .getComponentType()))) {
645                     hasParameters = true;
646                     break;
647                 }
648             }
649         }
650         return hasParameters;
651     }
652 }
Popular Tags