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 }