/* * SunJavaCompiler.java * Workaround for Runtime.exec() environment handling incompatibility.. * * A work based on JP.ac.tsukuba.openjava.SunJavaCompiler * * Apr 16, 1999 Michiaki Tatsubori (mt@is.tsukuba.ac.jp) * Oct 1, 1999 Shiro Kawai (shiro@squareusa.com) * Nov 22, 1999 Michiaki Tatsubori */ package JP.ac.tsukuba.openjava; import java.io.*; import openjava.ojc.JavaCompiler; /** * The class <code>SunJavaCompiler</code> is an adapter for Sun's javac. * * Message-Id: 19990930154627G.shiro@squareusa.com * <p> * I tried OpenJava1.0a1 on my IRIX box w/ SGI's JDK1.2 * and had a problem to run ojc. Somehow, Runtime.exec() * didn't pass all the environment variables to the invoked * process (more specifically, it only passed TZ). * Consequently the CLASSPATH env was not passed to javac kicked * by JP.ac.tsukuba.openjava.SunJavaCompiler.complie(), which * prevented ojc from finishing compilation. * <p> * So far I couldn't find exact specification about how the * environment variables should be treated in Java specification * and API documents. I guess it may depend on platforms. * <p> * We avoided the problem by explicitly passing CLASSPATH to * the subprocess my modifying SunJavaCompiler class, but wondering * if there'd be a better way to handle it... */ public class SunJavaCompiler implements JavaCompiler { public static void main( String[] args ) { new SunJavaCompiler().compile( args ); } public void compile( String[] args ) { String out = null; PrintWriter outWriter = new PrintWriter(System.err); String[] envp = new String[] { "CLASSPATH=" + System.getProperty("java.class.path")}; String[] commandArray = new String[args.length + 1]; commandArray[0] = "javac.exe"; System.arraycopy(args, 0, commandArray, 1, args.length); try { Process p = Runtime.getRuntime().exec( commandArray, envp); InputStream in = new BufferedInputStream( p.getErrorStream() ); Sucker sucker = new Sucker(in, outWriter); new Thread(sucker).start(); p.waitFor(); out = sucker.toString(); } catch (Exception e) { String command = toString(commandArray); throw new CompilationFailedException( e, "Compilation failed; command=[" + command + "]"); } finally { outWriter.close(); } if (out.indexOf(".java:") >= 0) { // typical error message: // "src\saffron\runtime\Dummy_742b49.java:41: cannot resolve // symbol" throw new CompilationFailedException(out); } } private class CompilationFailedException extends RuntimeException { Throwable throwable; public CompilationFailedException(String s) { super(s); } public CompilationFailedException(Throwable throwable, String s) { super(s); throwable.fillInStackTrace(); this.throwable = throwable; } public String getMessage() { if (throwable == null) { return super.getMessage(); } else { return super.getMessage() + "; exception=[" + throwable.getMessage() + "]"; } } } private static String toString(String[] strs) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < strs.length; ++i) { if (i > 0) { buf.append(" "); } buf.append(strs[i]); } return buf.toString(); } /** A <code>Sucker</code> collects the output from a reader in a string * buffer. If a print writer is specified, it also writes the output there * (like the UNIX <code>tee</code> command). */ static class Sucker implements Runnable { InputStream is; PrintWriter pw; StringWriter sw = new StringWriter(); /** * Constructs a <code>Sucker</code> * @param is stream to read from * @param pw writer to echo output to (may be null) */ Sucker(InputStream is, PrintWriter pw) { this.is = is; this.pw = pw; } public void run() { try { InputStreamReader reader = new InputStreamReader(is); final int len = 2000; char b[] = new char[len]; int bytesRead; while ((bytesRead = reader.read(b)) >= 0) { write(b, bytesRead); } } catch (IOException e) { write("Received exception: " + e.getMessage()); } } private void write(char[] b, int bytesRead) { sw.write(b, 0, bytesRead); if (pw != null) { pw.write(b, 0, bytesRead); } } private void write(String s) { sw.write(s); if (pw != null) { pw.write(s); } } public String toString() { return sw.toString(); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 1748 | Julian Hyde |
saffron: convert unit tests to JUnit; add CallingConvention.ITERABLE; lots of other stuff; release 0.1. |
||
#1 | 1461 | Julian Hyde |
saffron: First check in. Just documents, and the unmodified OpenJava 20001010 source files. |