Java tutorial
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.axis.components.compiler; import org.apache.axis.components.logger.LogFactory; import org.apache.axis.utils.Messages; import org.apache.commons.logging.Log; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * This class wraps IBM's <i>Jikes</i> Java compiler * NOTE: inspired by the Apache Jasper implementation. * @author <a href="mailto:dims@yahoo.com">Davanum Srinivas</a> * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> * @since 2.0 */ public class Jikes extends AbstractCompiler { protected static Log log = LogFactory.getLog(Jikes.class.getName()); static final int OUTPUT_BUFFER_SIZE = 1024; static final int BUFFER_SIZE = 512; private class StreamPumper extends Thread { private BufferedInputStream stream; private boolean endOfStream = false; private boolean stopSignal = false; private int SLEEP_TIME = 5; private OutputStream out; public StreamPumper(BufferedInputStream is, OutputStream out) { this.stream = is; this.out = out; } public void pumpStream() throws IOException { byte[] buf = new byte[BUFFER_SIZE]; if (!endOfStream) { int bytesRead = stream.read(buf, 0, BUFFER_SIZE); if (bytesRead > 0) { out.write(buf, 0, bytesRead); } else if (bytesRead == -1) { endOfStream = true; } } } public void run() { try { while (!endOfStream) { pumpStream(); sleep(SLEEP_TIME); } } catch (Exception e) { // getLogger().warn("Jikes.run()", e); } } } /** * Copy arguments to a string array * * @param arguments The compiler arguments * @return A string array containing compilation arguments */ protected String[] toStringArray(List arguments) { int i; for (i = 0; i < arguments.size(); i++) { String arg = (String) arguments.get(i); if (arg.equals("-sourcepath")) { // Remove -sourcepath option. Jikes does not understand that. arguments.remove(i); arguments.remove(i); break; } } String[] args = new String[arguments.size() + fileList.size()]; for (i = 0; i < arguments.size(); i++) { args[i] = (String) arguments.get(i); } for (int j = 0; j < fileList.size(); i++, j++) { args[i] = (String) fileList.get(j); } return args; } /** * Execute the compiler */ public boolean compile() throws IOException { List args = new ArrayList(); // command line name args.add("jikes"); // indicate Emacs output mode must be used args.add("+E"); // avoid warnings // Option nowarn with one hyphen only args.add("-nowarn"); int exitValue; ByteArrayOutputStream tmpErr = new ByteArrayOutputStream(OUTPUT_BUFFER_SIZE); try { Process p = Runtime.getRuntime().exec(toStringArray(fillArguments(args))); BufferedInputStream compilerErr = new BufferedInputStream(p.getErrorStream()); StreamPumper errPumper = new StreamPumper(compilerErr, tmpErr); errPumper.start(); p.waitFor(); exitValue = p.exitValue(); // Wait until the complete error stream has been read errPumper.join(); compilerErr.close(); p.destroy(); tmpErr.close(); this.errors = new ByteArrayInputStream(tmpErr.toByteArray()); } catch (InterruptedException somethingHappened) { log.debug("Jikes.compile():SomethingHappened", somethingHappened); return false; } // Jikes returns 0 even when there are some types of errors. // Check if any error output as well // Return should be OK when both exitValue and // tmpErr.size() are 0 ?! return ((exitValue == 0) && (tmpErr.size() == 0)); } /** * Parse the compiler error stream to produce a list of * <code>CompilerError</code>s * * @param input The error stream * @return The list of compiler error messages * @exception IOException If an error occurs during message collection */ protected List parseStream(BufferedReader input) throws IOException { List errors = null; String line = null; StringBuffer buffer = null; while (true) { // cleanup the buffer buffer = new StringBuffer(); // this is faster than clearing it // first line is not space-starting if (line == null) line = input.readLine(); if (line == null) return errors; log.debug(line); buffer.append(line); // all other space-starting lines are one error while (true) { line = input.readLine(); // EOF if (line == null) break; // Continuation of previous error starts with ' ' if (line.length() > 0 && line.charAt(0) != ' ') break; log.debug(line); buffer.append('\n'); buffer.append(line); } // if error is found create the vector if (errors == null) errors = new ArrayList(); // add the error bean errors.add(parseError(buffer.toString())); } } /** * Parse an individual compiler error message * * @param error The error text * @return A mssaged <code>CompilerError</code> */ private CompilerError parseError(String error) { StringTokenizer tokens = new StringTokenizer(error, ":"); String file = tokens.nextToken(); if (file.length() == 1) file = new StringBuffer(file).append(":").append(tokens.nextToken()).toString(); StringBuffer message = new StringBuffer(); String type = ""; int startline = 0; int startcolumn = 0; int endline = 0; int endcolumn = 0; try { startline = Integer.parseInt(tokens.nextToken()); startcolumn = Integer.parseInt(tokens.nextToken()); endline = Integer.parseInt(tokens.nextToken()); endcolumn = Integer.parseInt(tokens.nextToken()); } catch (Exception e) { // FIXME: VG: This is not needed anymore? message.append(Messages.getMessage("compilerFail00")); type = "error"; log.error(Messages.getMessage("compilerFail00"), e); } if ("".equals(message)) { type = tokens.nextToken().trim().toLowerCase(); message.append(tokens.nextToken("\n").substring(1).trim()); while (tokens.hasMoreTokens()) message.append("\n").append(tokens.nextToken()); } return new CompilerError(file, type.equals("error"), startline, startcolumn, endline, endcolumn, message.toString()); } public String toString() { return Messages.getMessage("ibmJikes"); } }