001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: */
055:
056: package com.sun.portal.providers.jsp.jasper3.jasper.compiler;
057:
058: import java.io.BufferedInputStream;
059: import java.io.OutputStream;
060: import java.io.IOException;
061: import java.io.File;
062: import java.io.ByteArrayOutputStream;
063:
064: /**
065: * A Plug-in class for specifying a 'jikes' compile.
066: *
067: * @author Jeffrey Chiu
068: * @author Hans Bergsten <hans@gefionsoftware.com>
069: */
070: public class JikesJavaCompiler implements JavaCompiler {
071:
072: static final int OUTPUT_BUFFER_SIZE = 1024;
073: static final int BUFFER_SIZE = 512;
074:
075: String encoding;
076: String classpath;
077: String compilerPath = "jikes";
078: String outdir;
079: OutputStream out;
080: boolean classDebugInfo = false;
081:
082: /**
083: * Specify where the compiler can be found
084: */
085: public void setCompilerPath(String compilerPath) {
086: this .compilerPath = compilerPath;
087: }
088:
089: /**
090: * Set the encoding (character set) of the source
091: */
092: public void setEncoding(String encoding) {
093: this .encoding = encoding;
094: }
095:
096: /**
097: * Set the class path for the compiler
098: */
099: public void setClasspath(String classpath) {
100: this .classpath = classpath;
101: }
102:
103: /**
104: * Set the output directory
105: */
106: public void setOutputDir(String outdir) {
107: this .outdir = outdir;
108: }
109:
110: /**
111: * Set where you want the compiler output (messages) to go
112: */
113: public void setMsgOutput(OutputStream out) {
114: this .out = out;
115: }
116:
117: /**
118: * Set if you want debugging information in the class file
119: */
120: public void setClassDebugInfo(boolean classDebugInfo) {
121: this .classDebugInfo = classDebugInfo;
122: }
123:
124: /**
125: * Execute the compiler
126: * @param source - file name of the source to be compiled
127: */
128: public boolean compile(String source) {
129: Process p;
130: int exitValue = -1;
131: String[] compilerCmd;
132:
133: if (classDebugInfo) {
134: compilerCmd = new String[] { compilerPath, "-g",
135: //XXX - add encoding once Jikes supports it
136: "-classpath", classpath, "-d", outdir,
137: // Only report errors, to be able to test on output in addition to exit code
138: "-nowarn", source };
139: } else {
140: compilerCmd = new String[] { compilerPath,
141: //XXX - add encoding once Jikes supports it
142: "-classpath", classpath, "-d", outdir,
143: // Only report errors, to be able to test on output in addition to exit code
144: "-nowarn", source };
145: }
146:
147: ByteArrayOutputStream tmpErr = new ByteArrayOutputStream(
148: OUTPUT_BUFFER_SIZE);
149: try {
150: p = Runtime.getRuntime().exec(compilerCmd);
151:
152: BufferedInputStream compilerErr = new BufferedInputStream(p
153: .getErrorStream());
154:
155: StreamPumper errPumper = new StreamPumper(compilerErr,
156: tmpErr);
157:
158: errPumper.start();
159:
160: p.waitFor();
161: exitValue = p.exitValue();
162:
163: // Wait until the complete error stream has been read
164: errPumper.join();
165: compilerErr.close();
166:
167: p.destroy();
168:
169: // Write the compiler error messages, if any, to the real stream
170: tmpErr.close();
171: tmpErr.writeTo(out);
172:
173: } catch (IOException ioe) {
174: return false;
175:
176: } catch (InterruptedException ie) {
177: return false;
178: }
179:
180: boolean isOkay = exitValue == 0;
181: // Jikes returns 0 even when there are some types of errors.
182: // Check if any error output as well
183: if (tmpErr.size() > 0) {
184: isOkay = false;
185: }
186: return isOkay;
187: }
188:
189: // Inner class for continually pumping the input stream during
190: // Process's runtime.
191: class StreamPumper extends Thread {
192: private BufferedInputStream stream;
193: private boolean endOfStream = false;
194: private boolean stopSignal = false;
195: private int SLEEP_TIME = 5;
196: private OutputStream out;
197:
198: public StreamPumper(BufferedInputStream is, OutputStream out) {
199: this .stream = is;
200: this .out = out;
201: }
202:
203: public void pumpStream() throws IOException {
204: byte[] buf = new byte[BUFFER_SIZE];
205: if (!endOfStream) {
206: int bytesRead = stream.read(buf, 0, BUFFER_SIZE);
207:
208: if (bytesRead > 0) {
209: out.write(buf, 0, bytesRead);
210: } else if (bytesRead == -1) {
211: endOfStream = true;
212: }
213: }
214: }
215:
216: public void run() {
217: try {
218: //while (!endOfStream || !stopSignal) {
219: while (!endOfStream) {
220: pumpStream();
221: sleep(SLEEP_TIME);
222: }
223: } catch (InterruptedException ie) {
224: } catch (IOException ioe) {
225: }
226: }
227: }
228: }
|