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 @Override
111 protected void setUp() throws Exception {
112 super.setUp();
113
114 classloader = new ReloadingClassLoader(this.getClass().getClassLoader());
115 listener = new CompilingListener(new MockJavaCompiler());
116
117 listener.addReloadNotificationListener(classloader);
118
119 fam = new FilesystemAlterationMonitor();
120 fam.addListener(directory, listener);
121 fam.start();
122 }
123
124 private void initialCompile() throws Exception {
125 log.debug("initial compile");
126
127 listener.waitForFirstCheck();
128
129 writeFile("jci/Simple.java", "Simple1");
130 writeFile("jci/Extended.java", "Extended");
131
132 log.debug("waiting for compile changes to get applied");
133 listener.waitForCheck();
134
135 log.debug("*** ready to test");
136 }
137
138 public void testCreate() throws Exception {
139 initialCompile();
140
141 log.debug("loading Simple");
142 final Object simple = classloader.loadClass("jci.Simple").newInstance();
143 assertEquals("Simple1", simple.toString());
144
145 log.debug("loading Extended");
146 final Object extended = classloader.loadClass("jci.Extended").newInstance();
147 assertEquals("Extended:Simple1", extended.toString());
148 }
149
150 public void testChange() throws Exception {
151 initialCompile();
152
153 final Object simple = classloader.loadClass("jci.Simple").newInstance();
154 assertEquals("Simple1", simple.toString());
155
156 final Object extended = classloader.loadClass("jci.Extended").newInstance();
157 assertEquals("Extended:Simple1", extended.toString());
158
159 delay();
160 writeFile("jci/Simple.java", "Simple2");
161 listener.waitForCheck();
162
163 final Object simple2 = classloader.loadClass("jci.Simple").newInstance();
164 assertEquals("Simple2", simple2.toString());
165
166 final Object newExtended = classloader.loadClass("jci.Extended").newInstance();
167 assertEquals("Extended:Simple2", newExtended.toString());
168 }
169
170 public void testDelete() throws Exception {
171 initialCompile();
172
173 final Object simple = classloader.loadClass("jci.Simple").newInstance();
174 assertEquals("Simple1", simple.toString());
175
176 final Object extended = classloader.loadClass("jci.Extended").newInstance();
177 assertEquals("Extended:Simple1", extended.toString());
178
179 listener.waitForCheck();
180
181 log.debug("deleting source file");
182 assertTrue(new File(directory, "jci/Extended.java").delete());
183
184 listener.waitForCheck();
185
186 log.debug("loading Simple");
187 final Object oldSimple = classloader.loadClass("jci.Simple").newInstance();
188 assertEquals("Simple1", oldSimple.toString());
189
190 log.debug("trying to loading Extended");
191 try {
192 classloader.loadClass("jci.Extended").newInstance();
193 fail();
194 } catch(final ClassNotFoundException e) {
195 assertEquals("jci.Extended", e.getMessage());
196 }
197
198 log.debug("deleting whole directory");
199 FileUtils.deleteDirectory(new File(directory, "jci"));
200
201 listener.waitForCheck();
202
203 log.debug("trying to loading Simple");
204 try {
205 classloader.loadClass("jci.Simple").newInstance();
206 fail();
207 } catch(final ClassNotFoundException e) {
208 assertEquals("jci.Simple", e.getMessage());
209 }
210
211 }
212
213 public void testDeleteDependency() throws Exception {
214 initialCompile();
215
216 final Object simple = classloader.loadClass("jci.Simple").newInstance();
217 assertEquals("Simple1", simple.toString());
218
219 final Object extended = classloader.loadClass("jci.Extended").newInstance();
220 assertEquals("Extended:Simple1", extended.toString());
221
222 log.debug("deleting source file");
223 assertTrue(new File(directory, "jci/Simple.java").delete());
224 listener.waitForCheck();
225
226 log.debug("trying to load dependend class");
227 try {
228 classloader.loadClass("jci.Extended").newInstance();
229 fail();
230 } catch(final NoClassDefFoundError e) {
231 assertEquals("jci/Simple", e.getMessage());
232 }
233
234 }
235
236 @Override
237 protected void tearDown() throws Exception {
238 fam.removeListener(listener);
239 fam.stop();
240 super.tearDown();
241 }
242 }