    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    }