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    package org.picocontainer.defaults;
009    
010    import java.io.FileNotFoundException;
011    
012    import org.jmock.MockObjectTestCase;
013    import org.picocontainer.MutablePicoContainer;
014    import org.picocontainer.Parameter;
015    import org.picocontainer.PicoIntrospectionException;
016    
017    
018    /**
019     * @author Aslak Hellesøy
020     * @author Jörg Schaible
021     * @version $Revision: 2291 $
022     */
023    public class LifecycleVisitorTestCase extends MockObjectTestCase {
024    
025        public abstract static class RecordingLifecycle {
026            private final StringBuffer recording;
027    
028            protected RecordingLifecycle(StringBuffer recording) {
029                this.recording = recording;
030            }
031    
032            public void demarrer() {
033                recording.append("<" + code());
034            }
035    
036            public void arreter() {
037                recording.append(code() + ">");
038            }
039    
040            public void ecraser() {
041                recording.append("!" + code());
042            }
043    
044            private String code() {
045                String name = getClass().getName();
046                return name.substring(name.indexOf('$') + 1);
047            }
048    
049            public void uncallableByVisitor(final String s) {
050            }
051    
052            public void throwsAtVisit() throws FileNotFoundException {
053                throw new FileNotFoundException();
054            }
055    
056            private void callMe() {
057            }
058        }
059    
060        public static class One extends RecordingLifecycle {
061            public One(StringBuffer sb) {
062                super(sb);
063            }
064        }
065    
066        public static class Two extends RecordingLifecycle {
067            public Two(StringBuffer sb, One one) {
068                super(sb);
069                assertNotNull(one);
070            }
071        }
072    
073        public static class Three extends RecordingLifecycle {
074            public Three(StringBuffer sb, One one, Two two) {
075                super(sb);
076                assertNotNull(one);
077                assertNotNull(two);
078            }
079        }
080    
081        public static class Four extends RecordingLifecycle {
082            public Four(StringBuffer sb, Two two, Three three, One one) {
083                super(sb);
084                assertNotNull(one);
085                assertNotNull(two);
086                assertNotNull(three);
087            }
088        }
089    
090        public void testShouldAllowCustomLifecycle() throws NoSuchMethodException {
091            LifecycleVisitor starter = new LifecycleVisitor(
092                    RecordingLifecycle.class.getMethod("demarrer", null), RecordingLifecycle.class, true);
093            LifecycleVisitor stopper = new LifecycleVisitor(
094                    RecordingLifecycle.class.getMethod("arreter", null), RecordingLifecycle.class, false);
095            LifecycleVisitor disposer = new LifecycleVisitor(
096                    RecordingLifecycle.class.getMethod("ecraser", null), RecordingLifecycle.class, false);
097    
098            MutablePicoContainer parent = new DefaultPicoContainer();
099            MutablePicoContainer child = parent.makeChildContainer();
100            parent.registerComponentImplementation("recording", StringBuffer.class);
101            child.registerComponentImplementation(Four.class);
102            parent.registerComponentImplementation(Two.class);
103            parent.registerComponentImplementation(One.class, One.class, new Parameter[]{ComponentParameter.DEFAULT});
104            child.registerComponentImplementation(Three.class);
105    
106            starter.traverse(parent);
107            stopper.traverse(parent);
108            disposer.traverse(parent);
109    
110            assertEquals("<One<Two<Three<FourFour>Three>Two>One>!Four!Three!Two!One", parent.getComponentInstance(
111                    "recording").toString());
112        }
113    
114        public void testPicoIntrospectionExceptionForInvalidMethod() throws NoSuchMethodException {
115            LifecycleVisitor visitor = new LifecycleVisitor(RecordingLifecycle.class.getMethod(
116                    "uncallableByVisitor", new Class[]{String.class}), RecordingLifecycle.class, true);
117            MutablePicoContainer pico = new DefaultPicoContainer();
118            pico.registerComponentImplementation(StringBuffer.class);
119            pico.registerComponentImplementation(One.class);
120            try {
121                visitor.traverse(pico);
122                fail("PicoIntrospectionException expected");
123            } catch (PicoIntrospectionException e) {
124                assertTrue(e.getCause() instanceof IllegalArgumentException);
125            }
126        }
127    
128        public void testPicoIntrospectionExceptionForThrownException() throws NoSuchMethodException {
129            LifecycleVisitor visitor = new LifecycleVisitor(
130                    RecordingLifecycle.class.getMethod("throwsAtVisit", null), RecordingLifecycle.class, true);
131            MutablePicoContainer pico = new DefaultPicoContainer();
132            pico.registerComponentImplementation(StringBuffer.class);
133            pico.registerComponentImplementation(One.class);
134            try {
135                visitor.traverse(pico);
136                fail("PicoIntrospectionException expected");
137            } catch (PicoIntrospectionException e) {
138                assertTrue(e.getCause() instanceof FileNotFoundException);
139            }
140        }
141    
142        public void testPicoIntrospectionExceptionForInaccessibleMethod() throws NoSuchMethodException {
143            LifecycleVisitor visitor = new LifecycleVisitor(
144                    RecordingLifecycle.class.getDeclaredMethod("callMe", null), RecordingLifecycle.class, true);
145            MutablePicoContainer pico = new DefaultPicoContainer();
146            pico.registerComponentImplementation(StringBuffer.class);
147            pico.registerComponentImplementation(One.class);
148            try {
149                visitor.traverse(pico);
150                fail("PicoIntrospectionException expected");
151            } catch (PicoIntrospectionException e) {
152                assertTrue(e.getCause() instanceof IllegalAccessException);
153            }
154        }
155    }