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            // System.err.println("--> " + testCompJar2.getAbsolutePath());
095            childContainer.addClassLoaderURL(testCompJar2.toURL());
096            childContainer.addComponent("childTestComp", new ClassName("TestComp2"));
097    
098            Object childTestComp = childContainer.getComponent("childTestComp");
099    
100            assertEquals("TestComp2", childTestComp.getClass().getName());
101    
102            assertNotSame(parentTestComp, childTestComp);
103    
104            final ClassLoader parentCompClassLoader = parentTestComp.getClass().getClassLoader();
105            final ClassLoader childCompClassLoader = childTestComp.getClass().getClassLoader();
106            if (parentCompClassLoader != childCompClassLoader.getParent()) {
107                printClassLoader(parentCompClassLoader);
108                printClassLoader(childCompClassLoader);
109                fail("parentTestComp classloader should be parent of childTestComp classloader");
110            }
111            // PicoContainer.getParent() is now ImmutablePicoContainer
112            assertNotSame(parentContainer, childContainer.getParent());
113        }
114    
115        private void printClassLoader(ClassLoader classLoader) {
116            while (classLoader != null) {
117                System.out.println(classLoader);
118                classLoader = classLoader.getParent();
119            }
120            System.out.println("--");
121        }
122    
123        public static class AnotherFooComp {
124    
125        }
126    
127        @Test
128        public void testClassLoaderJugglingIsPossible() throws MalformedURLException {
129            ClassLoadingPicoContainer parentContainer = new DefaultClassLoadingPicoContainer();
130    
131            File testCompJar = TestHelper.getTestCompJarFile();
132    
133            parentContainer.addComponent("foo", new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
134    
135            Object fooWebServerConfig = parentContainer.getComponent("foo");
136            assertEquals("org.picocontainer.script.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass()
137                    .getName());
138    
139            ClassLoadingPicoContainer childContainer = new DefaultClassLoadingPicoContainer(parentContainer);
140            childContainer.addClassLoaderURL(testCompJar.toURL());
141            childContainer.addComponent("bar", new ClassName("TestComp"));
142    
143            Object barTestComp = childContainer.getComponent("bar");
144            assertEquals("TestComp", barTestComp.getClass().getName());
145    
146            assertNotSame(fooWebServerConfig.getClass().getClassLoader(), barTestComp.getClass().getClassLoader());
147    
148            // This kludge is needed because IDEA, Eclipse and Maven have different
149            // numbers of
150            // classloaders in their hierachies for junit invocation.
151            ClassLoader fooCL = fooWebServerConfig.getClass().getClassLoader();
152            ClassLoader barCL1 = barTestComp.getClass().getClassLoader().getParent();
153            ClassLoader barCL2, barCL3;
154            if (barCL1 != null && barCL1 != fooCL) {
155                barCL2 = barCL1.getParent();
156                if (barCL2 != null && barCL2 != fooCL) {
157                    barCL3 = barCL2.getParent();
158                    if (barCL3 != null && barCL3 != fooCL) {
159                        fail("One of the parent classloaders of TestComp, should be that of DefaultWebServerConfig");
160                    }
161                }
162            }
163        }
164    
165        //TODO @Test
166        public void testSecurityManagerCanPreventOperations() throws MalformedURLException {
167            ClassLoadingPicoContainer parentContainer = new DefaultClassLoadingPicoContainer();
168    
169            String testcompJarFileName = System.getProperty("testcomp.jar");
170            assertNotNull("The testcomp.jar system property does not exist", testcompJarFileName);
171            File testCompJar = new File(testcompJarFileName);
172            assertTrue(testCompJar.isFile());
173    
174            parentContainer.addComponent("foo", new ClassName("org.picocontainer.script.testmodel.DefaultWebServerConfig"));
175    
176            Object fooWebServerConfig = parentContainer.getComponent("foo");
177            assertEquals("org.picocontainer.script.testmodel.DefaultWebServerConfig", fooWebServerConfig.getClass()
178                    .getName());
179    
180            ClassLoadingPicoContainer childContainer = new DefaultClassLoadingPicoContainer(parentContainer);
181            childContainer.addClassLoaderURL(testCompJar.toURL());
182            // TODO childContainer.setPermission(some permission list, that includes
183            // the preventing of general file access);
184            // Or shoud this be done in the ctor for DRCA ?
185            // or should it a parameter in the addClassLoaderURL(..) method
186            childContainer.addComponent("bar", new ClassName("org.picocontainer.script.testmodel.FileSystemUsing"));
187    
188            try {
189                parentContainer.getComponent("bar");
190                fail("Should have barfed");
191            } catch (java.security.AccessControlException e) {
192                // expected
193            }
194        }
195    
196    }