001    /*******************************************************************************
002     * Copyright (C) PicoContainer Organization. All rights reserved.
003     * ---------------------------------------------------------------------------
004     * The software in this package is published under the terms of the BSD style
005     * license a copy of which has been included with this distribution in the
006     * LICENSE.txt file.
007     ******************************************************************************/
008    package org.picocontainer.script;
009    
010    import static org.junit.Assert.assertEquals;
011    import static org.junit.Assert.assertNotNull;
012    import static org.junit.Assert.assertNotSame;
013    import static org.junit.Assert.assertTrue;
014    import static org.junit.Assert.fail;
015    
016    import java.io.File;
017    import java.net.MalformedURLException;
018    
019    import org.junit.Test;
020    import org.picocontainer.PicoClassNotFoundException;
021    import org.picocontainer.PicoCompositionException;
022    import org.picocontainer.PicoException;
023    import org.picocontainer.classname.ClassLoadingPicoContainer;
024    import org.picocontainer.classname.DefaultClassLoadingPicoContainer;
025    import org.picocontainer.classname.ClassName;
026    import org.picocontainer.script.testmodel.WebServerImpl;
027    
028    /**
029     * @author Paul Hammant
030     */
031    public class ClassNameDefaultClassLoadingPicoContainerTestCase {
032    
033        @Test
034        public void testBasic() throws PicoCompositionException {
035            ClassLoadingPicoContainer container = new DefaultClassLoadingPicoContainer();
036            container.addComponent(new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
037            container.addComponent("org.picocontainer.script.testmodel.WebServer", new ClassName(
038                    "org.picocontainer.script.testmodel.WebServerImpl"));
039        }
040    
041        @Test
042        public void testProvision() throws PicoException {
043            ClassLoadingPicoContainer container = new DefaultClassLoadingPicoContainer();
044            container.addComponent(new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
045            container.addComponent(new ClassName("org.picocontainer.script.testmodel.WebServerImpl"));
046    
047            assertNotNull("WebServerImpl should exist", container.getComponent(WebServerImpl.class));
048            assertTrue("WebServerImpl should exist", container.getComponent(WebServerImpl.class) != null);
049        }
050    
051        @Test
052        public void testNoGenerationRegistration() throws PicoCompositionException {
053            ClassLoadingPicoContainer container = new DefaultClassLoadingPicoContainer();
054            try {
055                container.addComponent(new ClassName("Ping"));
056                fail("should have failed");
057            } catch (PicoClassNotFoundException e) {
058                // expected
059            }
060        }
061    
062        @Test
063        public void testThatTestCompIsNotNaturallyInTheClassPathForTesting() {
064            // the following tests try to load the jar containing TestComp - it
065            // won't do to have the class already available in the classpath
066            DefaultClassLoadingPicoContainer dfca = new DefaultClassLoadingPicoContainer();
067            try {
068                dfca.addComponent("foo", new ClassName("TestComp"));
069                Object o = dfca.getComponent("foo");
070                fail("Should have failed. Class was loaded from "
071                        + o.getClass().getProtectionDomain().getCodeSource().getLocation());
072            } catch (PicoClassNotFoundException expected) {
073            }
074    
075        }
076    
077        @Test
078        public void testChildContainerAdapterCanRelyOnParentContainerAdapter() throws MalformedURLException {
079    
080            File testCompJar = TestHelper.getTestCompJarFile();
081    
082            // Set up parent
083            ClassLoadingPicoContainer parentContainer = new DefaultClassLoadingPicoContainer();
084            parentContainer.addClassLoaderURL(testCompJar.toURL());
085            parentContainer.addComponent("parentTestComp", new ClassName("TestComp"));
086            parentContainer.addComponent(new ClassName("java.lang.StringBuffer"));
087    
088            Object parentTestComp = parentContainer.getComponent("parentTestComp");
089            assertEquals("TestComp", parentTestComp.getClass().getName());
090    
091            // Set up child
092            ClassLoadingPicoContainer childContainer = (ClassLoadingPicoContainer) parentContainer.makeChildContainer();
093            File testCompJar2 = new File(testCompJar.getParentFile(), "TestComp2.jar");
094            childContainer.addClassLoaderURL(testCompJar2.toURL());
095            childContainer.addComponent("childTestComp", new ClassName("TestComp2"));
096    
097            Object childTestComp = childContainer.getComponent("childTestComp");
098    
099            assertEquals("TestComp2", childTestComp.getClass().getName());
100    
101            assertNotSame(parentTestComp, childTestComp);
102    
103            final ClassLoader parentCompClassLoader = parentTestComp.getClass().getClassLoader();
104            final ClassLoader childCompClassLoader = childTestComp.getClass().getClassLoader();
105            if (parentCompClassLoader != childCompClassLoader.getParent()) {
106                printClassLoader(parentCompClassLoader);
107                printClassLoader(childCompClassLoader);
108                fail("parentTestComp classloader should be parent of childTestComp classloader");
109            }
110            // PicoContainer.getParent() is now ImmutablePicoContainer
111            assertNotSame(parentContainer, childContainer.getParent());
112        }
113    
114        private void printClassLoader(ClassLoader classLoader) {
115            while (classLoader != null) {
116                System.out.println(classLoader);
117                classLoader = classLoader.getParent();
118            }
119            System.out.println("--");
120        }
121    
122        public static class AnotherFooComp {
123    
124        }
125    
126        @Test
127        public void testClassLoaderJugglingIsPossible() throws MalformedURLException {
128            ClassLoadingPicoContainer parentContainer = new DefaultClassLoadingPicoContainer();
129    
130            File testCompJar = TestHelper.getTestCompJarFile();
131    
132            parentContainer.addComponent("foo", new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
133    
134            Object fooWebServerConfig = parentContainer.getComponent("foo");
135            assertEquals("org.picocontainer.script.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass()
136                    .getName());
137    
138            ClassLoadingPicoContainer childContainer = new DefaultClassLoadingPicoContainer(parentContainer);
139            childContainer.addClassLoaderURL(testCompJar.toURL());
140            childContainer.addComponent("bar", new ClassName("TestComp"));
141    
142            Object barTestComp = childContainer.getComponent("bar");
143            assertEquals("TestComp", barTestComp.getClass().getName());
144    
145            assertNotSame(fooWebServerConfig.getClass().getClassLoader(), barTestComp.getClass().getClassLoader());
146    
147            // This kludge is needed because IDEA, Eclipse and Maven have different
148            // numbers of
149            // classloaders in their hierachies for junit invocation.
150            ClassLoader fooCL = fooWebServerConfig.getClass().getClassLoader();
151            ClassLoader barCL1 = barTestComp.getClass().getClassLoader().getParent();
152            ClassLoader barCL2, barCL3;
153            if (barCL1 != null && barCL1 != fooCL) {
154                barCL2 = barCL1.getParent();
155                if (barCL2 != null && barCL2 != fooCL) {
156                    barCL3 = barCL2.getParent();
157                    if (barCL3 != null && barCL3 != fooCL) {
158                        fail("One of the parent classloaders of TestComp, should be that of DefaultWebServerConfig");
159                    }
160                }
161            }
162        }
163    
164        //TODO @Test
165        public void testSecurityManagerCanPreventOperations() throws MalformedURLException {
166            ClassLoadingPicoContainer parentContainer = new DefaultClassLoadingPicoContainer();
167    
168            String testcompJarFileName = System.getProperty("testcomp.jar");
169            assertNotNull("The testcomp.jar system property does not exist", testcompJarFileName);
170            File testCompJar = new File(testcompJarFileName);
171            assertTrue(testCompJar.isFile());
172    
173            parentContainer.addComponent("foo", new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
174    
175            Object fooWebServerConfig = parentContainer.getComponent("foo");
176            assertEquals("org.picocontainer.script.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass()
177                    .getName());
178    
179            ClassLoadingPicoContainer childContainer = new DefaultClassLoadingPicoContainer(parentContainer);
180            childContainer.addClassLoaderURL(testCompJar.toURL());
181            // TODO childContainer.setPermission(some permission list, that includes
182            // the preventing of general file access);
183            // Or shoud this be done in the ctor for DRCA ?
184            // or should it a parameter in the addClassLoaderURL(..) method
185            childContainer.addComponent("bar", new ClassName("org.picocontainer.script.testmodel.FileSystemUsing"));
186    
187            try {
188                parentContainer.getComponent("bar");
189                fail("Should have barfed");
190            } catch (java.security.AccessControlException e) {
191                // expected
192            }
193        }
194    
195    }