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 }