1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 package org.apache.jasper.compiler;
40
41 import java.io.BufferedOutputStream;
42 import java.io.BufferedReader;
43 import java.io.ByteArrayOutputStream;
44 import java.io.File;
45 import java.io.FileInputStream;
46 import java.io.FileNotFoundException;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.InputStreamReader;
51 import java.io.OutputStreamWriter;
52 import java.io.Reader;
53 import java.io.Writer;
54 import java.io.UnsupportedEncodingException;
55
56 import java.util.ArrayList;
57 import java.util.HashMap;
58 import java.util.List;
59 import java.util.Locale;
60 import java.util.Map;
61 import java.util.StringTokenizer;
62 import java.util.logging.Logger;
63 import java.util.logging.Level;
64
65 import org.apache.jasper.JasperException;
66 import org.apache.jasper.JspCompilationContext;
67
68 import org.eclipse.jdt.core.compiler.IProblem;
69 import org.eclipse.jdt.internal.compiler.ClassFile;
70 import org.eclipse.jdt.internal.compiler.CompilationResult;
71 import org.eclipse.jdt.internal.compiler.Compiler;
72 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
73 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
74 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
75 import org.eclipse.jdt.internal.compiler.IProblemFactory;
76 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
77 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
78 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
79 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
80 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
81 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
82
83
84
85
86
87
88
89
90
91
92
93 public class JDTJavaCompiler implements JavaCompiler {
94
95 private final Map settings = new HashMap();
96 private JspCompilationContext ctxt;
97 private ErrorDispatcher errDispatcher;
98 private Logger log;
99 private String javaFileName;
100
101
102 public void init(JspCompilationContext ctxt,
103 ErrorDispatcher errDispatcher,
104 boolean suppressLogging) {
105 this.errDispatcher = errDispatcher;
106 this.ctxt = ctxt;
107 log = Logger.getLogger(JDTJavaCompiler.class.getName());
108 if (suppressLogging) {
109 log.setLevel(Level.OFF);
110 }
111 }
112
113 public void setExtdirs(String exts) {
114
115 }
116
117 public void setClassPath(List<File> cpath) {
118
119
120 }
121
122 public long getClassLastModified() {
123 File classFile = new File(ctxt.getClassFileName());
124 return classFile.lastModified();
125 }
126
127 public Writer getJavaWriter(String javaFileName,
128 String javaEncoding)
129 throws JasperException {
130
131 this.javaFileName = javaFileName;
132
133 Writer writer = null;
134 try {
135 writer = new OutputStreamWriter(
136 new FileOutputStream(javaFileName), javaEncoding);
137 } catch (UnsupportedEncodingException ex) {
138 errDispatcher.jspError("jsp.error.needAlternateJavaEncoding",
139 javaEncoding);
140 } catch (IOException ex) {
141 errDispatcher.jspError("jsp.error.unableToCreateOutputWriter",
142 javaFileName, ex);
143 }
144 return writer;
145 }
146
147 public void setDebug(boolean debug) {
148 settings.put(CompilerOptions.OPTION_LineNumberAttribute,
149 CompilerOptions.GENERATE);
150 settings.put(CompilerOptions.OPTION_SourceFileAttribute,
151 CompilerOptions.GENERATE);
152 settings.put(CompilerOptions.OPTION_ReportDeprecation,
153 CompilerOptions.IGNORE);
154 if (debug) {
155 settings.put(CompilerOptions.OPTION_LocalVariableAttribute,
156 CompilerOptions.GENERATE);
157 }
158 }
159
160 public void setSourceVM(String sourceVM) {
161 if(sourceVM.equals("1.1")) {
162 settings.put(CompilerOptions.OPTION_Source,
163 CompilerOptions.VERSION_1_1);
164 } else if(sourceVM.equals("1.2")) {
165 settings.put(CompilerOptions.OPTION_Source,
166 CompilerOptions.VERSION_1_2);
167 } else if(sourceVM.equals("1.3")) {
168 settings.put(CompilerOptions.OPTION_Source,
169 CompilerOptions.VERSION_1_3);
170 } else if(sourceVM.equals("1.4")) {
171 settings.put(CompilerOptions.OPTION_Source,
172 CompilerOptions.VERSION_1_4);
173 } else if(sourceVM.equals("1.5")) {
174 settings.put(CompilerOptions.OPTION_Source,
175 CompilerOptions.VERSION_1_5);
176 } else {
177 log.warning("Unknown source VM " + sourceVM + " ignored.");
178 settings.put(CompilerOptions.OPTION_Source,
179 CompilerOptions.VERSION_1_5);
180 }
181 }
182
183 public void setTargetVM(String targetVM) {
184 if(targetVM.equals("1.1")) {
185 settings.put(CompilerOptions.OPTION_TargetPlatform,
186 CompilerOptions.VERSION_1_1);
187 } else if(targetVM.equals("1.2")) {
188 settings.put(CompilerOptions.OPTION_TargetPlatform,
189 CompilerOptions.VERSION_1_2);
190 } else if(targetVM.equals("1.3")) {
191 settings.put(CompilerOptions.OPTION_TargetPlatform,
192 CompilerOptions.VERSION_1_3);
193 } else if(targetVM.equals("1.4")) {
194 settings.put(CompilerOptions.OPTION_TargetPlatform,
195 CompilerOptions.VERSION_1_4);
196 } else if(targetVM.equals("1.5")) {
197 settings.put(CompilerOptions.OPTION_TargetPlatform,
198 CompilerOptions.VERSION_1_5);
199 } else {
200 log.warning("Unknown target VM " + targetVM + " ignored.");
201 settings.put(CompilerOptions.OPTION_TargetPlatform,
202 CompilerOptions.VERSION_1_5);
203 }
204 }
205
206 public void saveClassFile(String className, String classFileName) {
207
208 }
209
210 public void doJavaFile(boolean keep) {
211 if (!keep) {
212 File javaFile = new File(javaFileName);
213 javaFile.delete();
214 }
215 }
216
217 public JavacErrorDetail[] compile(final String targetClassName,
218 final Node.Nodes pageNodes)
219 throws JasperException {
220
221 final String sourceFile = ctxt.getServletJavaFileName();
222 final String outputDir =
223 ctxt.getOptions().getScratchDir().getAbsolutePath();
224 String packageName = ctxt.getServletPackageName();
225
226 final ClassLoader classLoader = ctxt.getJspLoader();
227 String[] fileNames = new String[] {sourceFile};
228 String[] classNames = new String[] {targetClassName};
229 final ArrayList<JavacErrorDetail> problemList =
230 new ArrayList<JavacErrorDetail>();
231
232 class CompilationUnit implements ICompilationUnit {
233
234 String className;
235 String sourceFile;
236
237 CompilationUnit(String sourceFile, String className) {
238 this.className = className;
239 this.sourceFile = sourceFile;
240 }
241
242 public char[] getFileName() {
243 return className.toCharArray();
244 }
245
246 public char[] getContents() {
247 char[] result = null;
248 Reader reader = null;
249 try {
250 InputStreamReader isReader =
251 new InputStreamReader(new FileInputStream(sourceFile),
252 ctxt.getOptions().getJavaEncoding());
253 reader = new BufferedReader(isReader);
254 if (reader != null) {
255 char[] chars = new char[8192];
256 StringBuffer buf = new StringBuffer();
257 int count;
258 while ((count = reader.read(chars, 0,
259 chars.length)) > 0) {
260 buf.append(chars, 0, count);
261 }
262 result = new char[buf.length()];
263 buf.getChars(0, result.length, result, 0);
264 }
265 } catch (IOException e) {
266 log.log(Level.SEVERE, "Compilation error", e);
267 } finally {
268 if (reader != null) {
269 try {
270 reader.close();
271 } catch (IOException ioe) {
272
273 }
274 }
275 }
276 return result;
277 }
278
279 public char[] getMainTypeName() {
280 int dot = className.lastIndexOf('.');
281 if (dot > 0) {
282 return className.substring(dot + 1).toCharArray();
283 }
284 return className.toCharArray();
285 }
286
287 public char[][] getPackageName() {
288 StringTokenizer izer =
289 new StringTokenizer(className, ".");
290 char[][] result = new char[izer.countTokens()-1][];
291 for (int i = 0; i < result.length; i++) {
292 String tok = izer.nextToken();
293 result[i] = tok.toCharArray();
294 }
295 return result;
296 }
297 }
298
299 final INameEnvironment env = new INameEnvironment() {
300
301 public NameEnvironmentAnswer
302 findType(char[][] compoundTypeName) {
303 String result = "";
304 String sep = "";
305 for (int i = 0; i < compoundTypeName.length; i++) {
306 result += sep;
307 result += new String(compoundTypeName[i]);
308 sep = ".";
309 }
310 return findType(result);
311 }
312
313 public NameEnvironmentAnswer
314 findType(char[] typeName,
315 char[][] packageName) {
316 String result = "";
317 String sep = "";
318 for (int i = 0; i < packageName.length; i++) {
319 result += sep;
320 result += new String(packageName[i]);
321 sep = ".";
322 }
323 result += sep;
324 result += new String(typeName);
325 return findType(result);
326 }
327
328 private NameEnvironmentAnswer findType(String className) {
329
330 InputStream is = null;
331 try {
332 if (className.equals(targetClassName)) {
333 ICompilationUnit compilationUnit =
334 new CompilationUnit(sourceFile, className);
335 return
336 new NameEnvironmentAnswer(compilationUnit, null);
337 }
338 String resourceName =
339 className.replace('.', '/') + ".class";
340 is = classLoader.getResourceAsStream(resourceName);
341 if (is != null) {
342 byte[] classBytes;
343 byte[] buf = new byte[8192];
344 ByteArrayOutputStream baos =
345 new ByteArrayOutputStream(buf.length);
346 int count;
347 while ((count = is.read(buf, 0, buf.length)) > 0) {
348 baos.write(buf, 0, count);
349 }
350 baos.flush();
351 classBytes = baos.toByteArray();
352 char[] fileName = className.toCharArray();
353 ClassFileReader classFileReader =
354 new ClassFileReader(classBytes, fileName,
355 true);
356 return
357 new NameEnvironmentAnswer(classFileReader, null);
358 }
359 } catch (IOException exc) {
360 log.log(Level.SEVERE, "Compilation error", exc);
361 } catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc) {
362 log.log(Level.SEVERE, "Compilation error", exc);
363 } finally {
364 if (is != null) {
365 try {
366 is.close();
367 } catch (IOException exc) {
368
369 }
370 }
371 }
372 return null;
373 }
374
375 private boolean isPackage(String result) {
376 if (result.equals(targetClassName)) {
377 return false;
378 }
379 String resourceName = result.replace('.', '/') + ".class";
380 InputStream is =
381 classLoader.getResourceAsStream(resourceName);
382 return is == null;
383 }
384
385 public boolean isPackage(char[][] parentPackageName,
386 char[] packageName) {
387 String result = "";
388 String sep = "";
389 if (parentPackageName != null) {
390 for (int i = 0; i < parentPackageName.length; i++) {
391 result += sep;
392 String str = new String(parentPackageName[i]);
393 result += str;
394 sep = ".";
395 }
396 }
397 String str = new String(packageName);
398 if (Character.isUpperCase(str.charAt(0))) {
399 if (!isPackage(result)) {
400 return false;
401 }
402 }
403 result += sep;
404 result += str;
405 return isPackage(result);
406 }
407
408 public void cleanup() {
409 }
410
411 };
412
413 final IErrorHandlingPolicy policy =
414 DefaultErrorHandlingPolicies.proceedWithAllProblems();
415
416 if (ctxt.getOptions().getJavaEncoding() != null) {
417 settings.put(CompilerOptions.OPTION_Encoding,
418 ctxt.getOptions().getJavaEncoding());
419 }
420
421 final IProblemFactory problemFactory =
422 new DefaultProblemFactory(Locale.getDefault());
423
424 final ICompilerRequestor requestor = new ICompilerRequestor() {
425 public void acceptResult(CompilationResult result) {
426 try {
427 if (result.hasProblems()) {
428 IProblem[] problems = result.getProblems();
429 for (int i = 0; i < problems.length; i++) {
430 IProblem problem = problems[i];
431 if (problem.isError()) {
432 String name =
433 new String(problems[i].getOriginatingFileName());
434 try {
435 problemList.add(
436 ErrorDispatcher.createJavacError(
437 name,
438 pageNodes,
439 new StringBuffer(problem.getMessage()),
440 problem.getSourceLineNumber()));
441 } catch (JasperException e) {
442 log.log(Level.SEVERE, "Error visiting node", e);
443 }
444 }
445 }
446 }
447 if (problemList.isEmpty()) {
448 ClassFile[] classFiles = result.getClassFiles();
449 for (int i = 0; i < classFiles.length; i++) {
450 ClassFile classFile = classFiles[i];
451 char[][] compoundName =
452 classFile.getCompoundName();
453 String className = "";
454 String sep = "";
455 for (int j = 0;
456 j < compoundName.length; j++) {
457 className += sep;
458 className += new String(compoundName[j]);
459 sep = ".";
460 }
461 byte[] bytes = classFile.getBytes();
462 String outFile = outputDir + "/" +
463 className.replace('.', '/') + ".class";
464 FileOutputStream fout =
465 new FileOutputStream(outFile);
466 BufferedOutputStream bos =
467 new BufferedOutputStream(fout);
468 bos.write(bytes);
469 bos.close();
470 }
471 }
472 } catch (IOException exc) {
473 log.log(Level.SEVERE, "Compilation error", exc);
474 }
475 }
476 };
477
478 ICompilationUnit[] compilationUnits =
479 new ICompilationUnit[classNames.length];
480 for (int i = 0; i < compilationUnits.length; i++) {
481 compilationUnits[i] = new CompilationUnit(fileNames[i], classNames[i]);
482 }
483
484 Compiler compiler = new Compiler(env,
485 policy,
486 settings,
487 requestor,
488 problemFactory);
489 compiler.compile(compilationUnits);
490
491 if (problemList.isEmpty()) {
492 return null;
493 }
494 return problemList.toArray(new JavacErrorDetail[]{});
495 }
496
497 }