001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.java;
031:
032: import com.caucho.loader.EnvironmentClassLoader;
033: import com.caucho.util.CharBuffer;
034: import com.caucho.vfs.Encoding;
035: import com.caucho.vfs.IOExceptionWrapper;
036: import com.caucho.vfs.MemoryStream;
037: import com.caucho.vfs.Path;
038: import com.caucho.vfs.ReadStream;
039: import com.caucho.vfs.WriteStream;
040:
041: import java.io.IOException;
042: import java.io.InputStream;
043: import java.io.PrintWriter;
044: import java.lang.reflect.Constructor;
045: import java.lang.reflect.InvocationTargetException;
046: import java.lang.reflect.Method;
047: import java.util.ArrayList;
048: import java.util.logging.Level;
049:
050: /**
051: * Compiles Java source, returning the loaded class.
052: */
053: public class EclipseCompiler extends AbstractJavaCompiler {
054: private static boolean _hasCompiler; // already tested for compiler
055:
056: private static final String COMPILER = "org.eclipse.jdt.internal.compiler.batch.Main";
057:
058: Process _process;
059: String _userPrefix;
060:
061: boolean _isDead;
062:
063: public EclipseCompiler(JavaCompiler compiler) {
064: super (compiler);
065: }
066:
067: protected void compileInt(String[] path, LineMap lineMap)
068: throws IOException, JavaCompileException {
069: if (!_hasCompiler) {
070: try {
071: Class.forName(COMPILER, false, Thread.currentThread()
072: .getContextClassLoader());
073:
074: _hasCompiler = true;
075: } catch (Exception e) {
076: e.printStackTrace();
077: throw new JavaCompileException(
078: L
079: .l(
080: "Resin can't load org.eclipse.jdt.core.JDTCompilerAdapter. Usually this means that eclipse-compiler.jar is missing from the classpath. You can either add eclipse-compiler.jar to the classpath or change the compiler with <java compiler='javac'/>.\n\n{0}",
081: String.valueOf(e)));
082: }
083: }
084:
085: executeInt(path, lineMap);
086: }
087:
088: /**
089: * Compiles the names files.
090: */
091: private void executeInt(String[] path, LineMap lineMap)
092: throws JavaCompileException, IOException {
093: MemoryStream tempStream = new MemoryStream();
094: WriteStream error = new WriteStream(tempStream);
095:
096: try {
097: // String parent = javaPath.getParent().getNativePath();
098:
099: ArrayList<String> argList = new ArrayList<String>();
100: /* This isn't needed since srcDirName is in the classpath
101: if ("1.2".compareTo(System.getProperty("java.version")) <= 0) {
102: argList.add("-sourcepath");
103: argList.add(srcDirName);
104: }
105: */
106: argList.add("-d");
107: argList.add(_compiler.getClassDirName());
108: if (_compiler.getEncoding() != null) {
109: String encoding = Encoding.getJavaName(_compiler
110: .getEncoding());
111: if (encoding != null && !encoding.equals("ISO8859_1")) {
112: argList.add("-encoding");
113: argList.add(_compiler.getEncoding());
114: }
115: }
116: argList.add("-classpath");
117: argList.add(_compiler.getClassPath());
118: ArrayList<String> args = _compiler.getArgs();
119: if (args != null)
120: argList.addAll(args);
121:
122: for (int i = 0; i < path.length; i++) {
123: Path javaPath = _compiler.getSourceDir()
124: .lookup(path[i]);
125: argList.add(javaPath.getNativePath());
126: }
127:
128: if (log.isLoggable(Level.FINE)) {
129: CharBuffer msg = CharBuffer.allocate();
130: msg.append("javac(int)");
131: for (int i = 0; i < argList.size(); i++) {
132: msg.append(" ");
133: msg.append(argList.get(i));
134: }
135: log.fine(msg.close());
136: }
137:
138: String[] argArray = argList.toArray(new String[argList
139: .size()]);
140:
141: int status = -1;
142:
143: Thread thread = Thread.currentThread();
144: ClassLoader oldLoader = thread.getContextClassLoader();
145: try {
146: EnvironmentClassLoader env;
147: env = new EnvironmentClassLoader(ClassLoader
148: .getSystemClassLoader());
149: thread.setContextClassLoader(env);
150:
151: try {
152: Class cl = Class.forName(COMPILER, false, env);
153: Constructor xtor = cl.getConstructor(new Class[] {
154: PrintWriter.class, PrintWriter.class,
155: boolean.class });
156:
157: Object value = xtor.newInstance(error
158: .getPrintWriter(), error.getPrintWriter(),
159: Boolean.FALSE);
160:
161: Method compile = cl.getMethod("compile",
162: new Class[] { String[].class });
163:
164: Object result = compile.invoke(value,
165: new Object[] { argArray });
166:
167: status = Boolean.TRUE.equals(result) ? 0 : -1;
168: } catch (ClassNotFoundException e) {
169: throw new JavaCompileException(
170: L
171: .l("Can't find internal Java compiler. Either configure an external compiler with <javac> or use a JDK which contains a Java compiler."));
172: } catch (NoSuchMethodException e) {
173: throw new JavaCompileException(e);
174: } catch (InstantiationException e) {
175: throw new JavaCompileException(e);
176: } catch (IllegalAccessException e) {
177: throw new JavaCompileException(e);
178: } catch (InvocationTargetException e) {
179: throw new IOExceptionWrapper(e);
180: }
181:
182: error.close();
183: tempStream.close();
184: } finally {
185: thread.setContextClassLoader(oldLoader);
186: }
187:
188: ReadStream read = tempStream.openReadAndSaveBuffer();
189: JavacErrorParser parser = new JavacErrorParser();
190:
191: String errors = parser.parseErrors((InputStream) read,
192: lineMap);
193: read.close();
194:
195: if (errors != null)
196: errors = errors.trim();
197:
198: if (log.isLoggable(Level.FINE)) {
199: read = tempStream.openReadAndSaveBuffer();
200: CharBuffer cb = new CharBuffer();
201: int ch;
202: while ((ch = read.read()) >= 0) {
203: cb.append((char) ch);
204: }
205: read.close();
206:
207: log.fine(cb.toString());
208: }
209: /* XXX: why should warnings be sent as warning?
210: else if (status == 0 && errors != null && ! errors.equals("")) {
211: final String msg = errors;
212:
213: new com.caucho.loader.ClassLoaderContext(_compiler.getClassLoader()) {
214: public void run()
215: {
216: log.warning(msg);
217: }
218: };
219: }
220: */
221:
222: if (status != 0)
223: throw new JavaCompileException(errors);
224: } finally {
225: tempStream.destroy();
226: }
227: }
228: }
|