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