001    /*****************************************************************************
002     * Copyright (C) NanoContainer 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     * Original code by Aslak Hellesoy and Paul Hammant                          *
009     *****************************************************************************/
010    
011    package org.nanocontainer.reflection;
012    
013    import junit.framework.TestCase;
014    import org.nanocontainer.DefaultNanoContainer;
015    import org.nanocontainer.NanoContainer;
016    import org.nanocontainer.testmodel.ThingThatTakesParamsInConstructor;
017    import org.nanocontainer.testmodel.WebServerImpl;
018    import org.picocontainer.*;
019    import org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer;
020    
021    import java.io.File;
022    import java.net.MalformedURLException;
023    import java.util.Vector;
024    import java.util.HashMap;
025    import java.util.ArrayList;
026    
027    public class DefaultNanoContainerTestCase extends TestCase {
028    
029        public void testBasic() throws PicoRegistrationException, PicoInitializationException, ClassNotFoundException {
030            NanoContainer nanoContainer = new DefaultNanoContainer();
031            nanoContainer.registerComponentImplementation("org.nanocontainer.testmodel.DefaultWebServerConfig");
032            nanoContainer.registerComponentImplementation("org.nanocontainer.testmodel.WebServer", "org.nanocontainer.testmodel.WebServerImpl");
033        }
034    
035        public void testProvision() throws PicoException, PicoInitializationException, ClassNotFoundException {
036            NanoContainer nanoContainer = new DefaultNanoContainer();
037            nanoContainer.registerComponentImplementation("org.nanocontainer.testmodel.DefaultWebServerConfig");
038            nanoContainer.registerComponentImplementation("org.nanocontainer.testmodel.WebServerImpl");
039    
040            assertNotNull("WebServerImpl should exist", nanoContainer.getPico().getComponentInstance(WebServerImpl.class));
041            assertTrue("WebServerImpl should exist", nanoContainer.getPico().getComponentInstance(WebServerImpl.class) instanceof WebServerImpl);
042        }
043    
044        public void testNoGenerationRegistration() throws PicoRegistrationException, PicoIntrospectionException {
045            NanoContainer nanoContainer = new DefaultNanoContainer();
046            try {
047                nanoContainer.registerComponentImplementation("Ping");
048                fail("should have failed");
049            } catch (ClassNotFoundException e) {
050                // expected
051            }
052        }
053    
054        public void testParametersCanBePassedInStringForm() throws ClassNotFoundException, PicoException, PicoInitializationException {
055            NanoContainer nanoContainer = new DefaultNanoContainer();
056            String className = ThingThatTakesParamsInConstructor.class.getName();
057    
058            nanoContainer.registerComponentImplementation("thing",
059                    className,
060                    new String[]{
061                        "java.lang.String",
062                        "java.lang.Integer"
063                    },
064                    new String[]{
065                        "hello",
066                        "22"
067                    });
068    
069            ThingThatTakesParamsInConstructor thing =
070                    (ThingThatTakesParamsInConstructor) nanoContainer.getPico().getComponentInstance("thing");
071            assertNotNull("component not present", thing);
072            assertEquals("hello22", thing.getValue());
073        }
074    
075        public void testThatTestCompIsNotNaturallyInTheClassPathForTesting() {
076    
077            // the following tests try to load the jar containing TestComp - it
078            // won't do to have the class already available in the classpath
079    
080            try {
081                DefaultNanoContainer dfca = new DefaultNanoContainer();
082                dfca.registerComponentImplementation("foo", "TestComp");
083                Object o = dfca.getPico().getComponentInstance("foo");
084                System.out.println("");
085                fail("Should have failed. Class was loaded from " + o.getClass().getProtectionDomain().getCodeSource().getLocation());
086            } catch (ClassNotFoundException expected) {
087            }
088    
089        }
090    
091        public void testChildContainerAdapterCanRelyOnParentContainerAdapter() throws MalformedURLException, ClassNotFoundException {
092    
093            String testcompJarFileName = System.getProperty("testcomp.jar", "src/test-comp/TestComp.jar");
094            // Paul's path to TestComp. PLEASE do not take out.
095            //testcompJarFileName = "D:/OSS/PN/java/nanocontainer/src/test-comp/TestComp.jar";
096            File testCompJar = new File(testcompJarFileName);
097            assertTrue("The testcomp.jar system property should point to java/nanocontainer/src/test-comp/TestComp.jar", testCompJar.isFile());
098    
099            // Set up parent
100            NanoContainer parentContainer = new DefaultNanoContainer();
101            parentContainer.addClassLoaderURL(testCompJar.toURL());
102            parentContainer.registerComponentImplementation("parentTestComp", "TestComp");
103            parentContainer.registerComponentImplementation("java.lang.StringBuffer");
104    
105            PicoContainer parentContainerAdapterPico = parentContainer.getPico();
106            Object parentTestComp = parentContainerAdapterPico.getComponentInstance("parentTestComp");
107            assertEquals("TestComp", parentTestComp.getClass().getName());
108    
109            // Set up child
110            NanoContainer childContainer = new DefaultNanoContainer(parentContainer);
111            File testCompJar2 = new File(testCompJar.getParentFile(), "TestComp2.jar");
112            childContainer.addClassLoaderURL(testCompJar2.toURL());
113            childContainer.registerComponentImplementation("childTestComp", "TestComp2");
114    
115            PicoContainer childContainerAdapterPico = childContainer.getPico();
116            Object childTestComp = childContainerAdapterPico.getComponentInstance("childTestComp");
117    
118            assertEquals("TestComp2", childTestComp.getClass().getName());
119    
120            assertNotSame(parentTestComp, childTestComp);
121    
122            final ClassLoader parentCompClassLoader = parentTestComp.getClass().getClassLoader();
123            final ClassLoader childCompClassLoader = childTestComp.getClass().getClassLoader();
124            if(parentCompClassLoader != childCompClassLoader.getParent()) {
125                printClassLoader(parentCompClassLoader);
126                printClassLoader(childCompClassLoader);
127                fail("parentTestComp classloader should be parent of childTestComp classloader");
128            }
129            //PicoContainer.getParent() is now ImmutablePicoContainer
130            assertNotSame(parentContainerAdapterPico, childContainerAdapterPico.getParent());
131        }
132    
133        private void printClassLoader(ClassLoader classLoader) {
134            while(classLoader != null) {
135                System.out.println(classLoader);
136                classLoader = classLoader.getParent();
137            }
138            System.out.println("--");
139        }
140    
141        public static class AnotherFooComp {
142    
143        }
144    
145        public void testClassLoaderJugglingIsPossible() throws MalformedURLException, ClassNotFoundException {
146            NanoContainer parentContainer = new DefaultNanoContainer();
147    
148            String testcompJarFileName = System.getProperty("testcomp.jar", "src/test-comp/TestComp.jar");
149            // Paul's path to TestComp. PLEASE do not take out.
150            //testcompJarFileName = "D:/OSS/PN/java/nanocontainer/src/test-comp/TestComp.jar";
151            File testCompJar = new File(testcompJarFileName);
152            assertTrue("The testcomp.jar system property should point to java/nanocontainer/src/test-comp/TestComp.jar", testCompJar.isFile());
153    
154            parentContainer.registerComponentImplementation("foo", "org.nanocontainer.testmodel.DefaultWebServerConfig");
155    
156            Object fooWebServerConfig = parentContainer.getPico().getComponentInstance("foo");
157            assertEquals("org.nanocontainer.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass().getName());
158    
159            NanoContainer childContainer = new DefaultNanoContainer(parentContainer);
160            childContainer.addClassLoaderURL(testCompJar.toURL());
161            childContainer.registerComponentImplementation("bar", "TestComp");
162    
163            Object barTestComp = childContainer.getPico().getComponentInstance("bar");
164            assertEquals("TestComp", barTestComp.getClass().getName());
165    
166            assertNotSame(fooWebServerConfig.getClass().getClassLoader(), barTestComp.getClass().getClassLoader());
167    
168            // This kludge is needed because IDEA, Eclipse and Maven have different numbers of
169            // classloaders in their hierachies for junit invocation.
170            ClassLoader fooCL = fooWebServerConfig.getClass().getClassLoader();
171            ClassLoader barCL1 = barTestComp.getClass().getClassLoader().getParent();
172            ClassLoader barCL2, barCL3;
173            if (barCL1 != null && barCL1 != fooCL) {
174                barCL2 = barCL1.getParent();
175                if (barCL2 != null && barCL2 != fooCL) {
176                    barCL3 = barCL2.getParent();
177                    if (barCL3 != null && barCL3 != fooCL) {
178                        fail("One of the parent classloaders of TestComp, should be that of DefaultWebServerConfig");
179                    }
180                }
181            }
182        }
183    
184        public void TODO_testSecurityManagerCanPreventOperations() throws MalformedURLException, ClassNotFoundException {
185            NanoContainer parentContainer = new DefaultNanoContainer();
186    
187            String testcompJarFileName = System.getProperty("testcomp.jar");
188            // Paul's path to TestComp. PLEASE do not take out.
189            //testcompJarFileName = "D:/OSS/PN/java/nanocontainer/src/test-comp/TestComp.jar";
190            assertNotNull("The testcomp.jar system property should point to nano/reflection/src/test-comp/TestComp.jar", testcompJarFileName);
191            File testCompJar = new File(testcompJarFileName);
192            assertTrue(testCompJar.isFile());
193    
194            parentContainer.registerComponentImplementation("foo", "org.nanocontainer.testmodel.DefaultWebServerConfig");
195    
196            Object fooWebServerConfig = parentContainer.getPico().getComponentInstance("foo");
197            assertEquals("org.nanocontainer.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass().getName());
198    
199            NanoContainer childContainer = new DefaultNanoContainer(parentContainer);
200            childContainer.addClassLoaderURL(testCompJar.toURL());
201            //TODO childContainer.setPermission(some permission list, that includes the preventing of general file access);
202            // Or shoud this be done in the ctor for DRCA ?
203            // or should it a parameter in the addClassLoaderURL(..) method
204            childContainer.registerComponentImplementation("bar", "org.nanocontainer.testmodel.FileSystemUsing");
205    
206            try {
207                parentContainer.getPico().getComponentInstance("bar");
208                fail("Should have barfed");
209            } catch (java.security.AccessControlException e) {
210                // expected
211            }
212        }
213    
214    
215        public void testChainOfDecoratingPicoContainersCanDoInterceptionOfMutablePicoContainerMethods() throws ClassNotFoundException {
216            NanoContainer nanoContainer = new DefaultNanoContainer();
217            MutablePicoContainer decorating = nanoContainer.addDecoratingPicoContainer(FooDecoratingPicoContainer.class);
218            assertTrue(decorating instanceof FooDecoratingPicoContainer);
219            MutablePicoContainer decorating2 = nanoContainer.addDecoratingPicoContainer(BarDecoratingPicoContainer.class);
220            assertTrue(decorating2 instanceof BarDecoratingPicoContainer);
221            nanoContainer.registerComponentImplementation("java.util.Vector");
222            // decorators are fairly dirty - they replace a very select implementation in this TestCase.
223            assertNotNull(nanoContainer.getComponentInstanceOfType("java.util.ArrayList"));
224            assertNull(nanoContainer.getComponentInstanceOfType("java.util.Vector"));
225            assertNotNull(nanoContainer.getPico().getComponentInstanceOfType(ArrayList.class));
226            assertNull(nanoContainer.getPico().getComponentInstanceOfType(Vector.class));
227        }
228    
229        public static class FooDecoratingPicoContainer extends AbstractDelegatingMutablePicoContainer {
230            public FooDecoratingPicoContainer(MutablePicoContainer delegate) {
231                super(delegate);
232            }
233            public MutablePicoContainer makeChildContainer() {
234                return null;
235            }
236    
237            public ComponentAdapter registerComponentImplementation(Class compImpl) throws PicoRegistrationException {
238                assertEquals(HashMap.class, compImpl);
239                return super.registerComponentImplementation(ArrayList.class);
240            }
241        }
242    
243        public static class BarDecoratingPicoContainer extends AbstractDelegatingMutablePicoContainer {
244            public BarDecoratingPicoContainer(MutablePicoContainer delegate) {
245                super(delegate);
246            }
247            public MutablePicoContainer makeChildContainer() {
248                return null;
249            }
250            public ComponentAdapter registerComponentImplementation(Class compImpl) throws PicoRegistrationException {
251                assertEquals(Vector.class, compImpl);
252                return super.registerComponentImplementation(HashMap.class);
253            }
254        }
255    
256    
257    }