KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > flow > javascript > fom > CompilingClassLoader


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.flow.javascript.fom;
17
18 import org.apache.excalibur.source.Source;
19 import org.apache.excalibur.source.SourceResolver;
20 import org.tempuri.javac.JavaClassReader;
21 import org.tempuri.javac.JavaClassReaderFactory;
22 import org.tempuri.javac.JavaClassWriter;
23 import org.tempuri.javac.JavaClassWriterFactory;
24 import org.tempuri.javac.JavaCompiler;
25 import org.tempuri.javac.JavaCompilerErrorHandler;
26 import org.tempuri.javac.JavaSourceReader;
27 import org.tempuri.javac.JavaSourceReaderFactory;
28 import org.tempuri.javacImpl.eclipse.JavaCompilerImpl;
29
30 import java.io.ByteArrayInputStream JavaDoc;
31 import java.io.ByteArrayOutputStream JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.InputStream JavaDoc;
34 import java.io.InputStreamReader JavaDoc;
35 import java.io.Reader JavaDoc;
36 import java.net.MalformedURLException JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.LinkedList JavaDoc;
40 import java.util.List JavaDoc;
41
42 /**
43  * @version CVS $Id: CompilingClassLoader.java 123806 2004-12-31 16:07:39Z antonio $
44  */

45 public class CompilingClassLoader extends ClassLoader JavaDoc {
46
47     SourceResolver sourceResolver;
48     JavaCompiler compiler;
49     List JavaDoc sourcePath = new LinkedList JavaDoc();
50     HashSet JavaDoc sourceListeners = new HashSet JavaDoc();
51     ClassRepository classRepository;
52
53     public interface SourceListener {
54         public void sourceCompiled(Source src);
55         public void sourceCompilationError(Source src, String JavaDoc error);
56     }
57
58     public interface ClassRepository {
59         public byte[] getCompiledClass(String JavaDoc className);
60         public void addCompiledClass(String JavaDoc className,
61                                      Source source,
62                                      byte[] contents);
63     }
64
65     protected Class JavaDoc findClass(String JavaDoc className)
66     throws ClassNotFoundException JavaDoc {
67         final byte[] bytes = compile(className);
68         return defineClass(className, bytes, 0, bytes.length);
69     }
70
71     public CompilingClassLoader(ClassLoader JavaDoc parent,
72                                 SourceResolver sourceResolver,
73                                 ClassRepository classRepository) {
74         super(parent);
75         this.sourceResolver = sourceResolver;
76         this.classRepository = classRepository;
77         this.compiler = new JavaCompilerImpl();
78         this.sourcePath.add("");
79     }
80
81     static class ClassCompilationException extends ClassNotFoundException JavaDoc {
82         public ClassCompilationException(String JavaDoc msg) {
83             super(msg);
84         }
85     }
86
87     public void addSourceListener(SourceListener listener) {
88         synchronized (sourceListeners) {
89             sourceListeners.add(listener);
90         }
91     }
92
93     public void removeSourceListener(SourceListener listener) {
94         synchronized (sourceListeners) {
95             sourceListeners.remove(listener);
96         }
97     }
98
99     private void notifyListeners(Source src, String JavaDoc err) {
100         SourceListener arr[];
101         synchronized (sourceListeners) {
102             arr = new SourceListener[sourceListeners.size()];
103             sourceListeners.toArray(arr);
104         }
105         if (err != null) {
106             for (int i = 0; i < arr.length; i++) {
107                 arr[i].sourceCompilationError(src, err);
108             }
109         } else {
110             for (int i = 0; i < arr.length; i++) {
111                 arr[i].sourceCompiled(src);
112             }
113         }
114     }
115
116     public void setClassRepository(ClassRepository rep) {
117         classRepository = rep;
118     }
119
120     public ClassRepository getClassRepository() {
121         return classRepository;
122     }
123
124     public void setSourcePath(String JavaDoc[] path) {
125         synchronized (sourcePath) {
126             sourcePath.clear();
127             for (int i = 0; i < path.length; i++) {
128                 sourcePath.add(path[i]);
129             }
130             sourcePath.add("");
131         }
132     }
133
134     private Source getSource(String JavaDoc className) {
135         int dollar = className.indexOf('$');
136         if (dollar > 0) {
137             // inner class: use the parent
138
className = className.substring(0, dollar);
139         }
140
141         synchronized (sourcePath) {
142             Iterator JavaDoc i = sourcePath.iterator();
143             while (i.hasNext()) {
144                 String JavaDoc prefix = (String JavaDoc) i.next();
145                 if (prefix.length() > 0) {
146                     if (!prefix.endsWith("/")) {
147                         prefix += "/";
148                     }
149                 }
150                 String JavaDoc uri = prefix + className.replace('.', '/') + ".java";
151                 Source src;
152                 try {
153                     src = sourceResolver.resolveURI(uri);
154                 } catch (MalformedURLException JavaDoc ignored) {
155                     continue;
156                 } catch (IOException JavaDoc ignored) {
157                     continue;
158                 }
159
160                 if (src.exists()) {
161                     return src;
162                 }
163                 releaseSource(src);
164             }
165         }
166
167         return null;
168     }
169
170     private void releaseSource(Source src) {
171         sourceResolver.release(src);
172     }
173
174     class SourceReaderFactory implements JavaSourceReaderFactory {
175         public JavaSourceReader getSourceReader(final String JavaDoc className)
176         throws IOException JavaDoc {
177             Source src = getSource(className);
178             if (src == null) return null;
179             try {
180                 InputStream JavaDoc is = src.getInputStream();
181                 if (is == null) {
182                     return null;
183                 }
184
185                 byte[] buf = new byte[8192];
186                 ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
187                 int count;
188                 while ((count = is.read(buf, 0, buf.length)) > 0) {
189                     baos.write(buf, 0, count);
190                 }
191                 baos.flush();
192
193                 final Reader reader = new InputStreamReader JavaDoc(new ByteArrayInputStream JavaDoc(baos.toByteArray()));
194                 return new JavaSourceReader() {
195                     public Reader getReader() {
196                         return reader;
197                     }
198                     public String JavaDoc getClassName() {
199                         return className;
200                     }
201                 };
202             } finally {
203                 releaseSource(src);
204             }
205         }
206     }
207
208     private String JavaDoc makeFileName(String JavaDoc className) {
209         Source src = getSource(className);
210         if (src != null) {
211             String JavaDoc result = src.getURI();
212             releaseSource(src);
213             return result;
214         }
215         return className;
216     }
217
218     class ClassReaderFactory implements JavaClassReaderFactory {
219         public JavaClassReader getClassReader(final String JavaDoc className)
220         throws IOException JavaDoc {
221             final byte[] bytes = classRepository.getCompiledClass(className);
222             if (bytes != null) {
223                 return new JavaClassReader() {
224                     public String JavaDoc getClassName() {
225                         return className;
226                     }
227
228                     public InputStream JavaDoc getInputStream() {
229                         return new ByteArrayInputStream JavaDoc(bytes);
230                     }
231                 };
232             }
233
234             String JavaDoc classFile = className.replace('.', '/') + ".class";
235             final InputStream JavaDoc is = getResourceAsStream(classFile);
236             if (is != null) {
237                 return new JavaClassReader() {
238                     public String JavaDoc getClassName() {
239                         return className;
240                     }
241
242                     public InputStream JavaDoc getInputStream() {
243                         return is;
244                     }
245                 };
246             }
247
248             return null;
249         }
250     }
251
252     class ClassWriterFactory implements JavaClassWriterFactory {
253         public JavaClassWriter getClassWriter(final String JavaDoc className) {
254             return new JavaClassWriter() {
255                 public String JavaDoc getClassName() {
256                     return className;
257                 }
258
259                 public void writeClass(InputStream JavaDoc contents)
260                 throws IOException JavaDoc {
261                     byte[] buf = new byte[2048];
262                     ByteArrayOutputStream JavaDoc s = new ByteArrayOutputStream JavaDoc();
263
264                     int count;
265                     while ((count = contents.read(buf, 0, buf.length)) > 0) {
266                         s.write(buf, 0, count);
267                     }
268                     s.flush();
269
270                     System.out.println("Compiled: " + className);
271                     Source src = getSource(className);
272                     classRepository.addCompiledClass(className,
273                                                      src,
274                                                      s.toByteArray());
275                     notifyListeners(src, null);
276                     releaseSource(src);
277                 }
278             };
279         }
280     }
281
282     class ErrorHandler implements JavaCompilerErrorHandler {
283         List JavaDoc errList = new LinkedList JavaDoc();
284
285         public void handleError(String JavaDoc className,
286                                 int line,
287                                 int column,
288                                 Object JavaDoc errorMessage) {
289             String JavaDoc msg = className;
290             try {
291                 // try to it convert to a file name
292
msg = makeFileName(className);
293             } catch (Exception JavaDoc ignored) {
294                 // oh well, I tried
295
}
296
297             if (line > 0) {
298                 msg += ": Line " + line;
299             }
300             if (column >= 0) {
301                 msg += "." + column;
302             }
303             msg += ": ";
304             msg += errorMessage;
305             errList.add(msg);
306         }
307
308         public List JavaDoc getErrorList() {
309             return errList;
310         }
311     }
312
313     private byte[] compile(String JavaDoc className)
314     throws ClassNotFoundException JavaDoc {
315         byte[] result = classRepository.getCompiledClass(className);
316         if (result != null) {
317             return result;
318         }
319
320         Source src = getSource(className);
321         if (src == null) {
322             throw new ClassNotFoundException JavaDoc(className);
323         }
324
325         try {
326             // try to compile it
327
ErrorHandler errorHandler = new ErrorHandler();
328             compiler.compile(new String JavaDoc[] {className},
329                              new SourceReaderFactory(),
330                              new ClassReaderFactory(),
331                              new ClassWriterFactory(),
332                              errorHandler);
333             List JavaDoc errorList = errorHandler.getErrorList();
334             if (errorList.size() > 0) {
335                 StringBuffer JavaDoc msg = new StringBuffer JavaDoc("Failed to compile Java class ");
336                 msg.append(className);
337                 msg.append(": ");
338                 Iterator JavaDoc iter = errorList.iterator();
339                 while (iter.hasNext()) {
340                     msg.append("\n");
341                     msg.append((String JavaDoc)iter.next());
342                 }
343                 notifyListeners(src, msg.toString());
344                 throw new ClassCompilationException(msg.toString());
345             }
346
347             return classRepository.getCompiledClass(className);
348         } finally {
349             releaseSource(src);
350         }
351     }
352 }
353
Popular Tags