1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jci;
19
20 import java.io.File;
21
22 import org.apache.commons.io.FileUtils;
23 import org.apache.commons.jci.classes.ExtendedDump;
24 import org.apache.commons.jci.classes.SimpleDump;
25 import org.apache.commons.jci.compilers.CompilationResult;
26 import org.apache.commons.jci.compilers.JavaCompiler;
27 import org.apache.commons.jci.compilers.JavaCompilerSettings;
28 import org.apache.commons.jci.listeners.CompilingListener;
29 import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
30 import org.apache.commons.jci.problems.CompilationProblem;
31 import org.apache.commons.jci.problems.CompilationProblemHandler;
32 import org.apache.commons.jci.readers.ResourceReader;
33 import org.apache.commons.jci.stores.ResourceStore;
34 import org.apache.commons.jci.utils.ConversionUtils;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38
39
40
41
42 public final class CompilingClassLoaderTestCase extends AbstractTestCase {
43
44 private final Log log = LogFactory.getLog(CompilingClassLoaderTestCase.class);
45
46 private ReloadingClassLoader classloader;
47 private CompilingListener listener;
48 private FilesystemAlterationMonitor fam;
49
50 private final static class MockJavaCompiler implements JavaCompiler {
51
52 private final Log log = LogFactory.getLog(MockJavaCompiler.class);
53
54 public CompilationResult compile(String[] pResourcePaths, ResourceReader pReader, ResourceStore pStore, ClassLoader pClassLoader, JavaCompilerSettings pSettings ) {
55
56 for (int i = 0; i < pResourcePaths.length; i++) {
57 final String resourcePath = pResourcePaths[i];
58 final byte[] resourceContent = pReader.getBytes(resourcePath);
59
60 log.debug("resource " + resourcePath + " = " + ((resourceContent!=null)?new String(resourceContent):null) );
61
62 final byte[] data;
63
64 if ("jci/Simple.java".equals(resourcePath)) {
65
66 try {
67 data = SimpleDump.dump(new String(resourceContent));
68 } catch (Exception e) {
69 throw new RuntimeException("cannot handle resource " + resourcePath, e);
70 }
71
72 } else if ("jci/Extended.java".equals(resourcePath)) {
73
74 try {
75 data = ExtendedDump.dump();
76 } catch (Exception e) {
77 throw new RuntimeException("cannot handle resource " + resourcePath, e);
78 }
79
80 } else {
81 throw new RuntimeException("cannot handle resource " + resourcePath);
82 }
83
84 log.debug("compiling " + resourcePath + " (" + data.length + ")");
85
86 pStore.write(ConversionUtils.stripExtension(resourcePath) + ".class", data);
87
88 }
89
90 return new CompilationResult(new CompilationProblem[0]);
91 }
92
93 public CompilationResult compile(String[] pResourcePaths, ResourceReader pReader, ResourceStore pStore, ClassLoader pClassLoader) {
94 return compile(pResourcePaths, pReader, pStore, pClassLoader, null);
95 }
96
97 public CompilationResult compile(String[] pResourcePaths, ResourceReader pReader, ResourceStore pStore) {
98 return compile(pResourcePaths, pReader, pStore, null);
99 }
100
101 public void setCompilationProblemHandler(CompilationProblemHandler pHandler) {
102 }
103
104 public JavaCompilerSettings createDefaultSettings() {
105 return null;
106 }
107
108 }
109
110 protected void setUp() throws Exception {
111 super.setUp();
112
113 classloader = new ReloadingClassLoader(this.getClass().getClassLoader());
114 listener = new CompilingListener(new MockJavaCompiler());
115
116 listener.addReloadNotificationListener(classloader);
117
118 fam = new FilesystemAlterationMonitor();
119 fam.addListener(directory, listener);
120 fam.start();
121 }
122
123 private void initialCompile() throws Exception {
124 log.debug("initial compile");
125
126 listener.waitForFirstCheck();
127
128 writeFile("jci/Simple.java", "Simple1");
129 writeFile("jci/Extended.java", "Extended");
130
131 log.debug("waiting for compile changes to get applied");
132 listener.waitForCheck();
133
134 log.debug("*** ready to test");
135 }
136
137 public void testCreate() throws Exception {
138 initialCompile();
139
140 log.debug("loading Simple");
141 final Object simple = classloader.loadClass("jci.Simple").newInstance();
142 assertEquals("Simple1", simple.toString());
143
144 log.debug("loading Extended");
145 final Object extended = classloader.loadClass("jci.Extended").newInstance();
146 assertEquals("Extended:Simple1", extended.toString());
147 }
148
149 public void testChange() throws Exception {
150 initialCompile();
151
152 final Object simple = classloader.loadClass("jci.Simple").newInstance();
153 assertEquals("Simple1", simple.toString());
154
155 final Object extended = classloader.loadClass("jci.Extended").newInstance();
156 assertEquals("Extended:Simple1", extended.toString());
157
158 delay();
159 writeFile("jci/Simple.java", "Simple2");
160 listener.waitForCheck();
161
162 final Object simple2 = classloader.loadClass("jci.Simple").newInstance();
163 assertEquals("Simple2", simple2.toString());
164
165 final Object newExtended = classloader.loadClass("jci.Extended").newInstance();
166 assertEquals("Extended:Simple2", newExtended.toString());
167 }
168
169 public void testDelete() throws Exception {
170 initialCompile();
171
172 final Object simple = classloader.loadClass("jci.Simple").newInstance();
173 assertEquals("Simple1", simple.toString());
174
175 final Object extended = classloader.loadClass("jci.Extended").newInstance();
176 assertEquals("Extended:Simple1", extended.toString());
177
178 listener.waitForCheck();
179
180 log.debug("deleting source file");
181 assertTrue(new File(directory, "jci/Extended.java").delete());
182
183 listener.waitForCheck();
184
185 log.debug("loading Simple");
186 final Object oldSimple = classloader.loadClass("jci.Simple").newInstance();
187 assertEquals("Simple1", oldSimple.toString());
188
189 log.debug("trying to loading Extended");
190 try {
191 classloader.loadClass("jci.Extended").newInstance();
192 fail();
193 } catch(final ClassNotFoundException e) {
194 assertEquals("jci.Extended", e.getMessage());
195 }
196
197 log.debug("deleting whole directory");
198 FileUtils.deleteDirectory(new File(directory, "jci"));
199
200 listener.waitForCheck();
201
202 log.debug("trying to loading Simple");
203 try {
204 classloader.loadClass("jci.Simple").newInstance();
205 fail();
206 } catch(final ClassNotFoundException e) {
207 assertEquals("jci.Simple", e.getMessage());
208 }
209
210 }
211
212 public void testDeleteDependency() throws Exception {
213 initialCompile();
214
215 final Object simple = classloader.loadClass("jci.Simple").newInstance();
216 assertEquals("Simple1", simple.toString());
217
218 final Object extended = classloader.loadClass("jci.Extended").newInstance();
219 assertEquals("Extended:Simple1", extended.toString());
220
221 log.debug("deleting source file");
222 assertTrue(new File(directory, "jci/Simple.java").delete());
223 listener.waitForCheck();
224
225 log.debug("trying to load dependend class");
226 try {
227 classloader.loadClass("jci.Extended").newInstance();
228 fail();
229 } catch(final NoClassDefFoundError e) {
230 assertEquals("jci/Simple", e.getMessage());
231 }
232
233 }
234
235 protected void tearDown() throws Exception {
236 fam.removeListener(listener);
237 fam.stop();
238 super.tearDown();
239 }
240 }