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.ByteArrayInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.ArrayList;
26 import java.util.Collection;
27
28 import org.apache.commons.jci.problems.CompilationProblem;
29 import org.apache.commons.jci.readers.ResourceReader;
30 import org.apache.commons.jci.stores.ResourceStore;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.codehaus.janino.ClassLoaderIClassLoader;
34 import org.codehaus.janino.CompileException;
35 import org.codehaus.janino.Compiler;
36 import org.codehaus.janino.DebuggingInformation;
37 import org.codehaus.janino.FilterWarningHandler;
38 import org.codehaus.janino.Location;
39 import org.codehaus.janino.WarningHandler;
40 import org.codehaus.janino.Parser.ParseException;
41 import org.codehaus.janino.Scanner.ScanException;
42 import org.codehaus.janino.UnitCompiler.ErrorHandler;
43 import org.codehaus.janino.util.StringPattern;
44 import org.codehaus.janino.util.resource.Resource;
45 import org.codehaus.janino.util.resource.ResourceCreator;
46 import org.codehaus.janino.util.resource.ResourceFinder;
47
48
49
50
51 public final class JaninoJavaCompiler extends AbstractJavaCompiler {
52
53 private final Log log = LogFactory.getLog(JaninoJavaCompiler.class);
54
55 private final JaninoJavaCompilerSettings defaultSettings;
56
57 public JaninoJavaCompiler() {
58 this(new JaninoJavaCompilerSettings());
59 }
60
61 public JaninoJavaCompiler( final JaninoJavaCompilerSettings pSettings ) {
62 defaultSettings = pSettings;
63 }
64
65 private final static class JciResource implements Resource {
66
67 private final String name;
68 private final byte[] bytes;
69
70 public JciResource( final String pName, final byte[] pBytes ) {
71 name = pName;
72 bytes = pBytes;
73 }
74
75 public String getFileName() {
76 return name;
77 }
78
79 public long lastModified() {
80 return 0;
81 }
82
83 public InputStream open() throws IOException {
84 return new ByteArrayInputStream(bytes);
85 }
86 }
87
88 private final static class JciOutputStream extends ByteArrayOutputStream {
89
90 private final String name;
91 private final ResourceStore store;
92
93 public JciOutputStream( final String pName, final ResourceStore pStore ) {
94 name = pName;
95 store = pStore;
96 }
97
98 public void close() throws IOException {
99 super.close();
100
101 final byte[] bytes = toByteArray();
102
103 store.write(name, bytes);
104 }
105 }
106
107 public CompilationResult compile( final String[] pSourceNames, final ResourceReader pResourceReader, final ResourceStore pStore, final ClassLoader pClassLoader, final JavaCompilerSettings pSettings ) {
108
109 final Collection problems = new ArrayList();
110
111 final StringPattern[] pattern = StringPattern.PATTERNS_NONE;
112
113 final Compiler compiler = new Compiler(
114 new ResourceFinder() {
115 public Resource findResource( final String pSourceName ) {
116 final byte[] bytes = pResourceReader.getBytes(pSourceName);
117
118 if (bytes == null) {
119 log.debug("failed to find source " + pSourceName);
120 return null;
121 }
122
123 log.debug("reading " + pSourceName + " (" + bytes.length + ")");
124
125 return new JciResource(pSourceName, bytes);
126 }
127 },
128 new ClassLoaderIClassLoader(pClassLoader),
129 new ResourceFinder() {
130 public Resource findResource( final String pResourceName ) {
131 final byte[] bytes = pStore.read(pResourceName);
132
133 if (bytes == null) {
134 log.debug("failed to find " + pResourceName);
135 return null;
136 }
137
138 log.debug("reading " + pResourceName + " (" + bytes.length + ")");
139
140 return new JciResource(pResourceName, bytes);
141 }
142 },
143 new ResourceCreator() {
144 public OutputStream createResource( final String pResourceName ) throws IOException {
145 return new JciOutputStream(pResourceName, pStore);
146 }
147
148 public boolean deleteResource( final String pResourceName ) {
149 log.debug("removing " + pResourceName);
150
151 pStore.remove(pResourceName);
152 return true;
153 }
154 },
155 pSettings.getSourceEncoding(),
156 false,
157 pSettings.isDebug()?DebuggingInformation.ALL:DebuggingInformation.NONE,
158 new FilterWarningHandler(pattern, new WarningHandler() {
159 public void handleWarning( final String pHandle, final String pMessage, final Location pLocation ) {
160 final CompilationProblem problem = new JaninoCompilationProblem(pLocation.getFileName(), pLocation, pMessage, false);
161 if (problemHandler != null) {
162 problemHandler.handle(problem);
163 }
164 problems.add(problem);
165 }
166 })
167 );
168
169
170 compiler.setCompileErrorHandler(new ErrorHandler() {
171 public void handleError( final String pMessage, final Location pLocation ) throws CompileException {
172 final CompilationProblem problem = new JaninoCompilationProblem(pLocation.getFileName(), pLocation, pMessage, true);
173 if (problemHandler != null) {
174 problemHandler.handle(problem);
175 }
176 problems.add(problem);
177 }
178 });
179
180
181 final Resource[] resources = new Resource[pSourceNames.length];
182 for (int i = 0; i < pSourceNames.length; i++) {
183 log.debug("compiling " + pSourceNames[i]);
184 final byte[] source = pResourceReader.getBytes(pSourceNames[i]);
185 resources[i] = new JciResource(pSourceNames[i], source);
186 }
187
188 try {
189 compiler.compile(resources);
190 } catch ( ScanException e ) {
191 problems.add(new JaninoCompilationProblem(e));
192 } catch ( ParseException e ) {
193 problems.add(new JaninoCompilationProblem(e));
194 } catch ( IOException e ) {
195
196 log.error("this error should have been cought before", e);
197 } catch ( CompileException e ) {
198
199 log.error("this error should have been cought before", e);
200 }
201 final CompilationProblem[] result = new CompilationProblem[problems.size()];
202 problems.toArray(result);
203 return new CompilationResult(result);
204 }
205
206 public JavaCompilerSettings createDefaultSettings() {
207 return new JaninoJavaCompilerSettings(defaultSettings);
208 }
209
210 }