1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jci.compilers;
19
20 import java.io.BufferedReader;
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.io.StringReader;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29
30 import org.apache.commons.jci.problems.CompilationProblem;
31 import org.apache.commons.jci.readers.ResourceReader;
32 import org.apache.commons.jci.stores.ResourceStore;
33 import org.apache.commons.jci.utils.ConversionUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.codehaus.janino.ClassLoaderIClassLoader;
37 import org.codehaus.janino.CompileException;
38 import org.codehaus.janino.DebuggingInformation;
39 import org.codehaus.janino.Descriptor;
40 import org.codehaus.janino.IClass;
41 import org.codehaus.janino.IClassLoader;
42 import org.codehaus.janino.Java;
43 import org.codehaus.janino.Location;
44 import org.codehaus.janino.Parser;
45 import org.codehaus.janino.Scanner;
46 import org.codehaus.janino.UnitCompiler;
47 import org.codehaus.janino.WarningHandler;
48 import org.codehaus.janino.Scanner.ScanException;
49 import org.codehaus.janino.UnitCompiler.ErrorHandler;
50 import org.codehaus.janino.util.ClassFile;
51
52
53
54
55 public final class JaninoJavaCompiler extends AbstractJavaCompiler {
56
57 private final Log log = LogFactory.getLog(JaninoJavaCompiler.class);
58
59 private class CompilingIClassLoader extends IClassLoader {
60
61 private final Map types = new HashMap();
62 private final ResourceReader resourceReader;
63 private final Map classes;
64 private final Collection problems = new ArrayList();
65
66 private CompilingIClassLoader(final ResourceReader pResourceReader, final Map pClasses, final ClassLoader classLoader) {
67 super( new ClassLoaderIClassLoader( classLoader ) );
68 resourceReader = pResourceReader;
69 classes = pClasses;
70 super.postConstruct();
71 }
72
73 protected Collection getProblems() {
74 return problems;
75 }
76
77 protected IClass findIClass(final String pType) {
78 final String className = Descriptor.toClassName(pType);
79 if (types.containsKey(pType)) {
80 return (IClass) types.get(pType);
81 }
82
83
84 final String resourceNameFromClass = className.replace('.', '/') + ".java";
85
86 final byte[] content = resourceReader.getBytes(resourceNameFromClass);
87 if (content == null) {
88 return null;
89 }
90 final Reader reader = new BufferedReader(new StringReader(new String(content)));
91 Scanner scanner = null;
92 try {
93 scanner = new Scanner(resourceNameFromClass, reader);
94 final Java.CompilationUnit unit = new Parser(scanner).parseCompilationUnit();
95 final UnitCompiler uc = new UnitCompiler(unit, this);
96 uc.setCompileErrorHandler(new ErrorHandler() {
97 public void handleError(final String pMessage, final Location pOptionalLocation) throws CompileException {
98 final CompilationProblem problem = new JaninoCompilationProblem(pOptionalLocation, pMessage, true);
99 if (problemHandler != null) {
100 problemHandler.handle(problem);
101 }
102 problems.add(problem);
103 }
104 });
105 uc.setWarningHandler(new WarningHandler() {
106 public void handleWarning(final String pHandle, final String pMessage, final Location pOptionalLocation) {
107 final CompilationProblem problem = new JaninoCompilationProblem(pOptionalLocation, pMessage, false);
108 if (problemHandler != null) {
109 problemHandler.handle(problem);
110 }
111 problems.add(problem);
112 }
113 });
114 log.debug("compile " + className);
115 final ClassFile[] classFiles = uc.compileUnit(DebuggingInformation.ALL);
116 for (int i = 0; i < classFiles.length; i++) {
117 log.debug("compiled " + classFiles[i].getThisClassName());
118 classes.put(classFiles[i].getThisClassName(), classFiles[i].toByteArray());
119 }
120 final IClass ic = uc.findClass(className);
121 if (null != ic) {
122 types.put(pType, ic);
123 }
124 return ic;
125 } catch (final ScanException e) {
126 problems.add(new JaninoCompilationProblem(e));
127 } catch (final IOException e) {
128 problems.add(new JaninoCompilationProblem(resourceNameFromClass, "IOException:" + e.getMessage(), true));
129 } catch (final Exception e) {
130 problems.add(new JaninoCompilationProblem(resourceNameFromClass, "Exception:" + e.getMessage(), true));
131 } finally {
132 if (scanner != null) {
133 try {
134 scanner.close();
135 } catch (IOException e) {
136 log.error("IOException occured while compiling " + className, e);
137 }
138 }
139 }
140 return null;
141 }
142 }
143
144 public CompilationResult compile( final String[] pSourceNames, final ResourceReader pResourceReader, final ResourceStore pStore, final ClassLoader pClassLoader, final JavaCompilerSettings pSettings ) {
145
146 final Map classFilesByName = new HashMap();
147
148 final CompilingIClassLoader icl = new CompilingIClassLoader(pResourceReader, classFilesByName, pClassLoader);
149 for (int i = 0; i < pSourceNames.length; i++) {
150 log.debug("compiling " + pSourceNames[i]);
151 try {
152 icl.loadIClass(Descriptor.fromClassName(ConversionUtils.convertResourceToClassName(pSourceNames[i])));
153 } catch (ClassNotFoundException e) {
154 log.error("ClassNotFoundException occured while compiling " + pSourceNames[i], e);
155 }
156 }
157
158
159 for (Iterator i = classFilesByName.entrySet().iterator(); i.hasNext();) {
160 final Map.Entry entry = (Map.Entry)i.next();
161 final String clazzName = (String)entry.getKey();
162 pStore.write(ConversionUtils.convertClassToResourcePath(clazzName), (byte[])entry.getValue());
163 }
164
165 final Collection problems = icl.getProblems();
166 final CompilationProblem[] result = new CompilationProblem[problems.size()];
167 problems.toArray(result);
168 return new CompilationResult(result);
169 }
170
171 public JavaCompilerSettings createDefaultSettings() {
172
173 return null;
174 }
175
176 }