001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.compiler;
019:
020: import java.io.ByteArrayOutputStream;
021: import java.io.File;
022: import java.io.FileNotFoundException;
023: import java.io.IOException;
024: import java.io.PrintStream;
025: import java.util.StringTokenizer;
026:
027: import org.apache.jasper.JasperException;
028: import org.apache.tools.ant.BuildException;
029: import org.apache.tools.ant.DefaultLogger;
030: import org.apache.tools.ant.Project;
031: import org.apache.tools.ant.taskdefs.Javac;
032: import org.apache.tools.ant.types.Path;
033: import org.apache.tools.ant.types.PatternSet;
034:
035: /**
036: * Main JSP compiler class. This class uses Ant for compiling.
037: *
038: * @author Anil K. Vijendran
039: * @author Mandar Raje
040: * @author Pierre Delisle
041: * @author Kin-man Chung
042: * @author Remy Maucherat
043: * @author Mark Roth
044: */
045: public class AntCompiler extends Compiler {
046:
047: protected static Object javacLock = new Object();
048:
049: static {
050: System.setErr(new SystemLogHandler(System.err));
051: }
052:
053: // ----------------------------------------------------- Instance Variables
054:
055: protected Project project = null;
056: protected JasperAntLogger logger;
057:
058: // ------------------------------------------------------------ Constructor
059:
060: // Lazy eval - if we don't need to compile we probably don't need the project
061: protected Project getProject() {
062:
063: if (project != null)
064: return project;
065:
066: // Initializing project
067: project = new Project();
068: logger = new JasperAntLogger();
069: logger.setOutputPrintStream(System.out);
070: logger.setErrorPrintStream(System.err);
071: logger.setMessageOutputLevel(Project.MSG_INFO);
072: project.addBuildListener(logger);
073: if (System.getProperty("catalina.home") != null) {
074: project.setBasedir(System.getProperty("catalina.home"));
075: }
076:
077: if (options.getCompiler() != null) {
078: if (log.isDebugEnabled())
079: log.debug("Compiler " + options.getCompiler());
080: project
081: .setProperty("build.compiler", options
082: .getCompiler());
083: }
084: project.init();
085: return project;
086: }
087:
088: public class JasperAntLogger extends DefaultLogger {
089:
090: protected StringBuffer reportBuf = new StringBuffer();
091:
092: protected void printMessage(final String message,
093: final PrintStream stream, final int priority) {
094: }
095:
096: protected void log(String message) {
097: reportBuf.append(message);
098: reportBuf.append(System.getProperty("line.separator"));
099: }
100:
101: protected String getReport() {
102: String report = reportBuf.toString();
103: reportBuf.setLength(0);
104: return report;
105: }
106: }
107:
108: // --------------------------------------------------------- Public Methods
109:
110: /**
111: * Compile the servlet from .java file to .class file
112: */
113: protected void generateClass(String[] smap)
114: throws FileNotFoundException, JasperException, Exception {
115:
116: long t1 = 0;
117: if (log.isDebugEnabled()) {
118: t1 = System.currentTimeMillis();
119: }
120:
121: String javaEncoding = ctxt.getOptions().getJavaEncoding();
122: String javaFileName = ctxt.getServletJavaFileName();
123: String classpath = ctxt.getClassPath();
124:
125: String sep = System.getProperty("path.separator");
126:
127: StringBuffer errorReport = new StringBuffer();
128:
129: StringBuffer info = new StringBuffer();
130: info.append("Compile: javaFileName=" + javaFileName + "\n");
131: info.append(" classpath=" + classpath + "\n");
132:
133: // Start capturing the System.err output for this thread
134: SystemLogHandler.setThread();
135:
136: // Initializing javac task
137: getProject();
138: Javac javac = (Javac) project.createTask("javac");
139:
140: // Initializing classpath
141: Path path = new Path(project);
142: path.setPath(System.getProperty("java.class.path"));
143: info.append(" cp=" + System.getProperty("java.class.path")
144: + "\n");
145: StringTokenizer tokenizer = new StringTokenizer(classpath, sep);
146: while (tokenizer.hasMoreElements()) {
147: String pathElement = tokenizer.nextToken();
148: File repository = new File(pathElement);
149: path.setLocation(repository);
150: info.append(" cp=" + repository + "\n");
151: }
152:
153: if (log.isDebugEnabled())
154: log.debug("Using classpath: "
155: + System.getProperty("java.class.path") + sep
156: + classpath);
157:
158: // Initializing sourcepath
159: Path srcPath = new Path(project);
160: srcPath.setLocation(options.getScratchDir());
161:
162: info.append(" work dir=" + options.getScratchDir() + "\n");
163:
164: // Initialize and set java extensions
165: String exts = System.getProperty("java.ext.dirs");
166: if (exts != null) {
167: Path extdirs = new Path(project);
168: extdirs.setPath(exts);
169: javac.setExtdirs(extdirs);
170: info.append(" extension dir=" + exts + "\n");
171: }
172:
173: // Add endorsed directories if any are specified and we're forking
174: // See Bugzilla 31257
175: if (ctxt.getOptions().getFork()) {
176: String endorsed = System.getProperty("java.endorsed.dirs");
177: if (endorsed != null) {
178: Javac.ImplementationSpecificArgument endorsedArg = javac
179: .createCompilerArg();
180: endorsedArg.setLine("-J-Djava.endorsed.dirs="
181: + endorsed);
182: info.append(" endorsed dir=" + endorsed + "\n");
183: } else {
184: info.append(" no endorsed dirs specified\n");
185: }
186: }
187:
188: // Configure the compiler object
189: javac.setEncoding(javaEncoding);
190: javac.setClasspath(path);
191: javac.setDebug(ctxt.getOptions().getClassDebugInfo());
192: javac.setSrcdir(srcPath);
193: javac.setTempdir(options.getScratchDir());
194: javac.setOptimize(!ctxt.getOptions().getClassDebugInfo());
195: javac.setFork(ctxt.getOptions().getFork());
196: info.append(" srcDir=" + srcPath + "\n");
197:
198: // Set the Java compiler to use
199: if (options.getCompiler() != null) {
200: javac.setCompiler(options.getCompiler());
201: info.append(" compiler=" + options.getCompiler() + "\n");
202: }
203:
204: if (options.getCompilerTargetVM() != null) {
205: javac.setTarget(options.getCompilerTargetVM());
206: info.append(" compilerTargetVM="
207: + options.getCompilerTargetVM() + "\n");
208: }
209:
210: if (options.getCompilerSourceVM() != null) {
211: javac.setSource(options.getCompilerSourceVM());
212: info.append(" compilerSourceVM="
213: + options.getCompilerSourceVM() + "\n");
214: }
215:
216: // Build includes path
217: PatternSet.NameEntry includes = javac.createInclude();
218:
219: includes.setName(ctxt.getJavaPath());
220: info.append(" include=" + ctxt.getJavaPath() + "\n");
221:
222: BuildException be = null;
223:
224: try {
225: if (ctxt.getOptions().getFork()) {
226: javac.execute();
227: } else {
228: synchronized (javacLock) {
229: javac.execute();
230: }
231: }
232: } catch (BuildException e) {
233: be = e;
234: log.error(Localizer.getMessage("jsp.error.javac"), e);
235: log.error(Localizer.getMessage("jsp.error.javac.env")
236: + info.toString());
237: }
238:
239: errorReport.append(logger.getReport());
240:
241: // Stop capturing the System.err output for this thread
242: String errorCapture = SystemLogHandler.unsetThread();
243: if (errorCapture != null) {
244: errorReport.append(System.getProperty("line.separator"));
245: errorReport.append(errorCapture);
246: }
247:
248: if (!ctxt.keepGenerated()) {
249: File javaFile = new File(javaFileName);
250: javaFile.delete();
251: }
252:
253: if (be != null) {
254: String errorReportString = errorReport.toString();
255: log.error(Localizer.getMessage("jsp.error.compilation",
256: javaFileName, errorReportString));
257: JavacErrorDetail[] javacErrors = ErrorDispatcher
258: .parseJavacErrors(errorReportString, javaFileName,
259: pageNodes);
260: if (javacErrors != null) {
261: errDispatcher.javacError(javacErrors);
262: } else {
263: errDispatcher.javacError(errorReportString, be);
264: }
265: }
266:
267: if (log.isDebugEnabled()) {
268: long t2 = System.currentTimeMillis();
269: log.debug("Compiled " + ctxt.getServletJavaFileName() + " "
270: + (t2 - t1) + "ms");
271: }
272:
273: logger = null;
274: project = null;
275:
276: if (ctxt.isPrototypeMode()) {
277: return;
278: }
279:
280: // JSR45 Support
281: if (!options.isSmapSuppressed()) {
282: SmapUtil.installSmap(smap);
283: }
284: }
285:
286: protected static class SystemLogHandler extends PrintStream {
287:
288: // ----------------------------------------------------------- Constructors
289:
290: /**
291: * Construct the handler to capture the output of the given steam.
292: */
293: public SystemLogHandler(PrintStream wrapped) {
294: super (wrapped);
295: this .wrapped = wrapped;
296: }
297:
298: // ----------------------------------------------------- Instance Variables
299:
300: /**
301: * Wrapped PrintStream.
302: */
303: protected PrintStream wrapped = null;
304:
305: /**
306: * Thread <-> PrintStream associations.
307: */
308: protected static ThreadLocal streams = new ThreadLocal();
309:
310: /**
311: * Thread <-> ByteArrayOutputStream associations.
312: */
313: protected static ThreadLocal data = new ThreadLocal();
314:
315: // --------------------------------------------------------- Public Methods
316:
317: public PrintStream getWrapped() {
318: return wrapped;
319: }
320:
321: /**
322: * Start capturing thread's output.
323: */
324: public static void setThread() {
325: ByteArrayOutputStream baos = new ByteArrayOutputStream();
326: data.set(baos);
327: streams.set(new PrintStream(baos));
328: }
329:
330: /**
331: * Stop capturing thread's output and return captured data as a String.
332: */
333: public static String unsetThread() {
334: ByteArrayOutputStream baos = (ByteArrayOutputStream) data
335: .get();
336: if (baos == null) {
337: return null;
338: }
339: streams.set(null);
340: data.set(null);
341: return baos.toString();
342: }
343:
344: // ------------------------------------------------------ Protected Methods
345:
346: /**
347: * Find PrintStream to which the output must be written to.
348: */
349: protected PrintStream findStream() {
350: PrintStream ps = (PrintStream) streams.get();
351: if (ps == null) {
352: ps = wrapped;
353: }
354: return ps;
355: }
356:
357: // ---------------------------------------------------- PrintStream Methods
358:
359: public void flush() {
360: findStream().flush();
361: }
362:
363: public void close() {
364: findStream().close();
365: }
366:
367: public boolean checkError() {
368: return findStream().checkError();
369: }
370:
371: protected void setError() {
372: //findStream().setError();
373: }
374:
375: public void write(int b) {
376: findStream().write(b);
377: }
378:
379: public void write(byte[] b) throws IOException {
380: findStream().write(b);
381: }
382:
383: public void write(byte[] buf, int off, int len) {
384: findStream().write(buf, off, len);
385: }
386:
387: public void print(boolean b) {
388: findStream().print(b);
389: }
390:
391: public void print(char c) {
392: findStream().print(c);
393: }
394:
395: public void print(int i) {
396: findStream().print(i);
397: }
398:
399: public void print(long l) {
400: findStream().print(l);
401: }
402:
403: public void print(float f) {
404: findStream().print(f);
405: }
406:
407: public void print(double d) {
408: findStream().print(d);
409: }
410:
411: public void print(char[] s) {
412: findStream().print(s);
413: }
414:
415: public void print(String s) {
416: findStream().print(s);
417: }
418:
419: public void print(Object obj) {
420: findStream().print(obj);
421: }
422:
423: public void println() {
424: findStream().println();
425: }
426:
427: public void println(boolean x) {
428: findStream().println(x);
429: }
430:
431: public void println(char x) {
432: findStream().println(x);
433: }
434:
435: public void println(int x) {
436: findStream().println(x);
437: }
438:
439: public void println(long x) {
440: findStream().println(x);
441: }
442:
443: public void println(float x) {
444: findStream().println(x);
445: }
446:
447: public void println(double x) {
448: findStream().println(x);
449: }
450:
451: public void println(char[] x) {
452: findStream().println(x);
453: }
454:
455: public void println(String x) {
456: findStream().println(x);
457: }
458:
459: public void println(Object x) {
460: findStream().println(x);
461: }
462:
463: }
464:
465: }
|