1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jci.compilers;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.StringTokenizer;
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.jci.utils.ConversionUtils;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.eclipse.jdt.core.compiler.IProblem;
35 import org.eclipse.jdt.internal.compiler.ClassFile;
36 import org.eclipse.jdt.internal.compiler.CompilationResult;
37 import org.eclipse.jdt.internal.compiler.Compiler;
38 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
39 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
40 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
41 import org.eclipse.jdt.internal.compiler.IProblemFactory;
42 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
43 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
44 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
45 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
46 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
47 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
48
49
50
51
52
53
54 public final class EclipseJavaCompiler extends AbstractJavaCompiler {
55
56 private final Log log = LogFactory.getLog(EclipseJavaCompiler.class);
57 private final EclipseJavaCompilerSettings defaultSettings;
58
59 public EclipseJavaCompiler() {
60 this(new EclipseJavaCompilerSettings());
61 }
62
63 public EclipseJavaCompiler(final Map pSettings) {
64 defaultSettings = new EclipseJavaCompilerSettings(pSettings);
65 }
66
67 public EclipseJavaCompiler(final EclipseJavaCompilerSettings pSettings) {
68 defaultSettings = pSettings;
69 }
70
71 final class CompilationUnit implements ICompilationUnit {
72
73 final private String clazzName;
74 final private String fileName;
75 final private char[] typeName;
76 final private char[][] packageName;
77 final private ResourceReader reader;
78
79 CompilationUnit( final ResourceReader pReader, final String pSourceFile ) {
80 reader = pReader;
81 clazzName = ConversionUtils.convertResourceToClassName(pSourceFile);
82 fileName = pSourceFile;
83 int dot = clazzName.lastIndexOf('.');
84 if (dot > 0) {
85 typeName = clazzName.substring(dot + 1).toCharArray();
86 } else {
87 typeName = clazzName.toCharArray();
88 }
89
90 log.debug("className=" + clazzName);
91 log.debug("fileName=" + fileName);
92 log.debug("typeName=" + new String(typeName));
93
94 final StringTokenizer izer = new StringTokenizer(clazzName, ".");
95 packageName = new char[izer.countTokens() - 1][];
96 for (int i = 0; i < packageName.length; i++) {
97 packageName[i] = izer.nextToken().toCharArray();
98 log.debug("package[" + i + "]=" + new String(packageName[i]));
99 }
100 }
101
102 public char[] getFileName() {
103 return fileName.toCharArray();
104 }
105
106 public char[] getContents() {
107 final byte[] content = reader.getBytes(fileName);
108
109 if (content == null) {
110 return null;
111
112 }
113
114 return new String(content).toCharArray();
115 }
116
117 public char[] getMainTypeName() {
118 return typeName;
119 }
120
121 public char[][] getPackageName() {
122 return packageName;
123 }
124 }
125
126
127 public org.apache.commons.jci.compilers.CompilationResult compile(
128 final String[] pSourceFiles,
129 final ResourceReader pReader,
130 final ResourceStore pStore,
131 final ClassLoader pClassLoader,
132 final JavaCompilerSettings pSettings
133 ) {
134
135 final Map settingsMap = ((EclipseJavaCompilerSettings) defaultSettings).getMap();
136
137 final Collection problems = new ArrayList();
138
139 final ICompilationUnit[] compilationUnits = new ICompilationUnit[pSourceFiles.length];
140 for (int i = 0; i < compilationUnits.length; i++) {
141 final String sourceFile = pSourceFiles[i];
142
143 if (pReader.isAvailable(sourceFile)) {
144 compilationUnits[i] = new CompilationUnit(pReader, sourceFile);
145 log.debug("compiling " + sourceFile);
146 } else {
147
148
149 final CompilationProblem problem = new CompilationProblem() {
150
151 public int getEndColumn() {
152 return 0;
153 }
154
155 public int getEndLine() {
156 return 0;
157 }
158
159 public String getFileName() {
160 return sourceFile;
161 }
162
163 public String getMessage() {
164 return "Source " + sourceFile + " could not be found";
165 }
166
167 public int getStartColumn() {
168 return 0;
169 }
170
171 public int getStartLine() {
172 return 0;
173 }
174
175 public boolean isError() {
176 return true;
177 }
178
179 public String toString() {
180 return getMessage();
181 }
182 };
183
184 if (problemHandler != null) {
185 problemHandler.handle(problem);
186 }
187
188 problems.add(problem);
189 }
190 }
191
192 if (problems.size() > 0) {
193 final CompilationProblem[] result = new CompilationProblem[problems.size()];
194 problems.toArray(result);
195 return new org.apache.commons.jci.compilers.CompilationResult(result);
196 }
197
198 final IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.proceedWithAllProblems();
199 final IProblemFactory problemFactory = new DefaultProblemFactory(Locale.getDefault());
200 final INameEnvironment nameEnvironment = new INameEnvironment() {
201
202 public NameEnvironmentAnswer findType( final char[][] pCompoundTypeName ) {
203 final StringBuffer result = new StringBuffer();
204 for (int i = 0; i < pCompoundTypeName.length; i++) {
205 if (i != 0) {
206 result.append('.');
207 }
208 result.append(pCompoundTypeName[i]);
209 }
210
211
212
213 return findType(result.toString());
214 }
215
216 public NameEnvironmentAnswer findType( final char[] pTypeName, final char[][] pPackageName ) {
217 final StringBuffer result = new StringBuffer();
218 for (int i = 0; i < pPackageName.length; i++) {
219 result.append(pPackageName[i]);
220 result.append('.');
221 }
222
223
224
225 result.append(pTypeName);
226 return findType(result.toString());
227 }
228
229 private NameEnvironmentAnswer findType( final String pClazzName ) {
230
231 if (isPackage(pClazzName)) {
232 return null;
233 }
234
235 log.debug("finding " + pClazzName);
236
237 final String resourceName = ConversionUtils.convertClassToResourcePath(pClazzName);
238
239 final byte[] clazzBytes = pStore.read(pClazzName);
240 if (clazzBytes != null) {
241 log.debug("loading from store " + pClazzName);
242
243 final char[] fileName = pClazzName.toCharArray();
244 try {
245 final ClassFileReader classFileReader = new ClassFileReader(clazzBytes, fileName, true);
246 return new NameEnvironmentAnswer(classFileReader, null);
247 } catch (final ClassFormatException e) {
248 log.error("wrong class format", e);
249 return null;
250 }
251 }
252
253 log.debug("not in store " + pClazzName);
254
255 final InputStream is = pClassLoader.getResourceAsStream(resourceName);
256 if (is == null) {
257 log.debug("class " + pClazzName + " not found");
258 return null;
259 }
260
261 final byte[] buffer = new byte[8192];
262 final ByteArrayOutputStream baos = new ByteArrayOutputStream(buffer.length);
263 int count;
264 try {
265 while ((count = is.read(buffer, 0, buffer.length)) > 0) {
266 baos.write(buffer, 0, count);
267 }
268 baos.flush();
269 final char[] fileName = pClazzName.toCharArray();
270 final ClassFileReader classFileReader = new ClassFileReader(baos.toByteArray(), fileName, true);
271 return new NameEnvironmentAnswer(classFileReader, null);
272 } catch (final IOException e) {
273 log.error("could not read class", e);
274 return null;
275 } catch (final ClassFormatException e) {
276 log.error("wrong class format", e);
277 return null;
278 } finally {
279 try {
280 baos.close();
281 } catch (final IOException oe) {
282 log.error("could not close output stream", oe);
283 }
284 try {
285 is.close();
286 } catch (final IOException ie) {
287 log.error("could not close input stream", ie);
288 }
289 }
290 }
291
292 private boolean isPackage( final String pClazzName ) {
293
294 final InputStream is = pClassLoader.getResourceAsStream(ConversionUtils.convertClassToResourcePath(pClazzName));
295 if (is != null) {
296 log.debug("found the class for " + pClazzName + "- no package");
297 return false;
298 }
299
300
301 final String source = pClazzName.replace('.', '/') + ".java";
302 if (pReader.isAvailable(source)) {
303 log.debug("found the source " + source + " for " + pClazzName + " - no package ");
304 return false;
305 }
306
307 return true;
308 }
309
310 public boolean isPackage( char[][] parentPackageName, char[] pPackageName ) {
311 final StringBuffer result = new StringBuffer();
312 if (parentPackageName != null) {
313 for (int i = 0; i < parentPackageName.length; i++) {
314 if (i != 0) {
315 result.append('.');
316 }
317 result.append(parentPackageName[i]);
318 }
319 }
320
321
322
323 if (parentPackageName != null && parentPackageName.length > 0) {
324 result.append('.');
325 }
326 result.append(pPackageName);
327 return isPackage(result.toString());
328 }
329
330 public void cleanup() {
331 log.debug("cleanup");
332 }
333 };
334
335 final ICompilerRequestor compilerRequestor = new ICompilerRequestor() {
336 public void acceptResult( final CompilationResult pResult ) {
337 if (pResult.hasProblems()) {
338 final IProblem[] iproblems = pResult.getProblems();
339 for (int i = 0; i < iproblems.length; i++) {
340 final IProblem iproblem = iproblems[i];
341 final CompilationProblem problem = new EclipseCompilationProblem(iproblem);
342 if (problemHandler != null) {
343 problemHandler.handle(problem);
344 }
345 problems.add(problem);
346 }
347 }
348 if (!pResult.hasErrors()) {
349 final ClassFile[] clazzFiles = pResult.getClassFiles();
350 for (int i = 0; i < clazzFiles.length; i++) {
351 final ClassFile clazzFile = clazzFiles[i];
352 final char[][] compoundName = clazzFile.getCompoundName();
353 final StringBuffer clazzName = new StringBuffer();
354 for (int j = 0; j < compoundName.length; j++) {
355 if (j != 0) {
356 clazzName.append('.');
357 }
358 clazzName.append(compoundName[j]);
359 }
360 pStore.write(clazzName.toString().replace('.', '/') + ".class", clazzFile.getBytes());
361 }
362 }
363 }
364 };
365
366 final Compiler compiler = new Compiler(nameEnvironment, policy, settingsMap, compilerRequestor, problemFactory, false);
367
368 compiler.compile(compilationUnits);
369
370 final CompilationProblem[] result = new CompilationProblem[problems.size()];
371 problems.toArray(result);
372 return new org.apache.commons.jci.compilers.CompilationResult(result);
373 }
374
375 public JavaCompilerSettings createDefaultSettings() {
376 return defaultSettings;
377 }
378 }