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: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Vasily Zakharov
021: * @version $Revision: 1.1.2.6 $
022: */package org.apache.harmony.rmi.common;
023:
024: import java.io.File;
025: import java.io.FilenameFilter;
026:
027: import org.apache.harmony.rmi.internal.nls.Messages;
028:
029: /**
030: * Representation of a Java Compiler.
031: *
032: * @author Vasily Zakharov
033: * @version $Revision: 1.1.2.6 $
034: */
035: public abstract class JavaCompiler implements RMIProperties {
036:
037: /**
038: * Compiler-specific options, may be re-initialized by subclasses.
039: */
040: protected String[] compilerOptions = new String[0];
041:
042: /**
043: * Compiles the files specified (together with options)
044: * with a command line.
045: *
046: * @param commandLine
047: * Command line. Can be <code>null</code>.
048: *
049: * @return Java Compiler return value.
050: *
051: * @throws JavaCompilerException
052: * If some error occurs.
053: */
054: public int compile(String commandLine) throws JavaCompilerException {
055: return compile((commandLine != null) ? commandLine.trim()
056: .split("\\s") : new String[0]); //$NON-NLS-1$
057: }
058:
059: /**
060: * Compiles the files specified in parameters (together with options).
061: *
062: * @param args
063: * Java Compiler options and source files to compile.
064: * Can be <code>null</code>.
065: *
066: * @return Java Compiler return value.
067: *
068: * @throws JavaCompilerException
069: * If some error occurs.
070: */
071: public int compile(String[] args) throws JavaCompilerException {
072: return compile(args, (String[]) null);
073: }
074:
075: /**
076: * Compiles the specified files with specified options.
077: *
078: * @param options
079: * Java Compiler options. Can be <code>null</code>.
080: *
081: * @param files
082: * Source files to compile. Can be <code>null</code>.
083: *
084: * @return Java Compiler return value.
085: *
086: * @throws JavaCompilerException
087: * If some error occurs.
088: */
089: public int compile(String[] options, File[] files)
090: throws JavaCompilerException {
091: int length = ((files != null) ? files.length : 0);
092: String[] fileNames = new String[length];
093:
094: for (int i = 0; i < length; i++) {
095: fileNames[i] = files[i].getPath();
096: }
097: return compile(options, fileNames);
098: }
099:
100: /**
101: * Compiles the specified files with specified options.
102: *
103: * @param options
104: * Java Compiler options. Can be <code>null</code>.
105: *
106: * @param fileNames
107: * Source files to compile. Can be <code>null</code>.
108: *
109: * @return Java Compiler return value.
110: *
111: * @throws JavaCompilerException
112: * If some error occurs.
113: */
114: public int compile(String[] options, String[] fileNames)
115: throws JavaCompilerException {
116: int optionsLength = ((options != null) ? options.length : 0);
117: int fileNamesLength = ((fileNames != null) ? fileNames.length
118: : 0);
119: int compilerOptionsLength = ((compilerOptions != null) ? compilerOptions.length
120: : 0);
121: String[] args;
122:
123: if ((fileNamesLength == 0) && (compilerOptionsLength == 0)) {
124: args = ((options != null) ? options : new String[0]);
125: } else {
126: args = new String[compilerOptionsLength + optionsLength
127: + fileNamesLength];
128:
129: if (compilerOptionsLength != 0) {
130: System.arraycopy(compilerOptions, 0, args, 0,
131: compilerOptionsLength);
132: }
133:
134: if (optionsLength != 0) {
135: System.arraycopy(options, 0, args,
136: compilerOptionsLength, optionsLength);
137: }
138:
139: if (fileNamesLength != 0) {
140: System.arraycopy(fileNames, 0, args,
141: compilerOptionsLength + optionsLength,
142: fileNamesLength);
143: }
144: }
145: return run(args);
146: }
147:
148: /**
149: * Runs the compilation process with the specified arguments.
150: *
151: * This method must be overridden by the subclasses.
152: *
153: * @param args
154: * Full non-<code>null</code> arguments list. Can be empty.
155: *
156: * @return Java Compiler return value.
157: *
158: * @throws JavaCompilerException
159: * If some error occurs.
160: *
161: * @throws NullPointerException
162: * If args is <code>null</code>.
163: */
164: protected abstract int run(String[] args)
165: throws JavaCompilerException;
166:
167: /**
168: * Locates the file from the given environment
169: * variable using the specified parameters.
170: *
171: * @param variableName
172: * Name of the environment variable to use.
173: *
174: * @param path
175: * Path from the directory designated by the specified environment
176: * variable to the directory, containing the file needed.
177: *
178: * @param pattern
179: * Pattern (regular expression)
180: * describing the file that has to be returned.
181: * The first file matching this pattern would be returned.
182: *
183: * @param name
184: * Descriptive name of the file being searched for,
185: * to be mentioned in exception message if error occurs.
186: *
187: * @return The first file matching the
188: * <code>$variableName/path/pattern</code>.
189: *
190: * @throws JavaCompilerException
191: * If no matching file is found.
192: */
193: protected static File getFileFromVariable(String variableName,
194: String path, final String pattern, String name)
195: throws JavaCompilerException {
196: String parent;
197:
198: try {
199: parent = System.getenv(variableName);
200: } catch (Error e) {
201: // TODO
202: // Workaround until System.getenv() is implemented.
203: parent = System.getProperty(variableName);
204: }
205:
206: if (parent == null) {
207: // rmi.4C={0} variable not found
208: throw new JavaCompilerException(Messages.getString(
209: "rmi.4C", variableName)); //$NON-NLS-1$
210: }
211:
212: File[] files = new File(parent, path)
213: .listFiles(new FilenameFilter() {
214: public boolean accept(File dir, String name) {
215: // Ignoring dir.
216: return (name.matches(pattern));
217: }
218: });
219:
220: if ((files == null) || (files.length < 1)) {
221: // rmi.4D={0} not found
222: throw new JavaCompilerException(Messages.getString(
223: "rmi.4D", name)); //$NON-NLS-1$
224: }
225: return files[0];
226: }
227:
228: /**
229: * Locates Java Compiler using the following algorithm:
230: *
231: * 1. Check if {@link #JAVA_COMPILER_CLASS_PROPERTY} system property is set.
232: * If set, configure the returned compiler to use the specified class.
233: * Also check {@link #JAVA_COMPILER_METHOD_PROPERTY} system property,
234: * if set, configure the returned compiler to use the specified method,
235: * otherwise, the
236: * {@linkplain MethodJavaCompiler#DEFAULT_COMPILER_METHOD default method}
237: * is used.
238: *
239: * 2. Check if {@link #JAVA_COMPILER_EXECUTABLE_PROPERTY} system property
240: * is set. If found, configure the returned compiler to use the specified
241: * executable.
242: *
243: * 3. Check if the Eclipse Compiler class
244: * ({@link EclipseJavaCompiler#ECLIPSE_COMPILER_CLASS_NAME})
245: * is accessible via classpath, if so, use it to compile.
246: *
247: * 4. Check if
248: * {@link EclipseJavaCompiler#ECLIPSE_HOME_VARIABLE ECLIPSE_HOME}
249: * environment variable is set. If set, locate Eclipse compiler JAR
250: * ({@link EclipseJavaCompiler#ECLIPSE_HOME_VARIABLE
251: * $ECLIPSE_HOME}<code>/</code>{@link
252: * EclipseJavaCompiler#ECLIPSE_JAR_PATH plugins}<code>/</code>{@link
253: * EclipseJavaCompiler#ECLIPSE_JAR_PATTERN org.eclipse.jdt.core_*.jar}),
254: * load ({@link EclipseJavaCompiler#ECLIPSE_COMPILER_CLASS_NAME
255: * Eclipse Compiler class}) from it and use it to compile.
256: *
257: * 5. Check if {@link ExecJavaCompiler#JAVA_HOME_VARIABLE JAVA_HOME}
258: * environment variable is set. If set, search if
259: * {@link ExecJavaCompiler#JAVA_HOME_VARIABLE
260: * $JAVA_HOME}<code>/</code>{@link ExecJavaCompiler#JAVA_COMPILER_PATH
261: * bin}<code>/</code>{@link ExecJavaCompiler#JAVA_COMPILER_PATTERN
262: * javac} executable, if found, execute it to compile.
263: *
264: * 6. If nothing found, just execute
265: * {@link ExecJavaCompiler#DEFAULT_COMPILER_PROGRAM javac}
266: * hoping it would be found in the system path.
267: *
268: * @param verbose
269: * If notes and warnings should be printed to {@link System#err}.
270: *
271: * @return Configured {@link JavaCompiler} implementation.
272: *
273: * @throws JavaCompilerException
274: * If compiler could not be found of configured.
275: */
276: public static final JavaCompiler locateJavaCompiler(boolean verbose)
277: throws JavaCompilerException {
278:
279: // Checking JAVA_COMPILER_CLASS_PROPERTY.
280: String compilerClassName = System
281: .getProperty(JAVA_COMPILER_CLASS_PROPERTY);
282:
283: if (compilerClassName != null) {
284: String compilerMethodName = System
285: .getProperty(JAVA_COMPILER_METHOD_PROPERTY);
286:
287: if (verbose) {
288: // rmi.console.08=NOTE: Using compiler class:
289: System.err
290: .println(Messages.getString("rmi.console.08") + //$NON-NLS-1$
291: compilerClassName
292: + ((compilerMethodName != null) ? (", method: " + compilerMethodName) : "")); //$NON-NLS-1$ //$NON-NLS-2$
293: }
294: return new MethodJavaCompiler(compilerClassName,
295: compilerMethodName);
296: }
297:
298: // Checking JAVA_COMPILER_EXECUTABLE_PROPERTY.
299: String executableName = System
300: .getProperty(JAVA_COMPILER_EXECUTABLE_PROPERTY);
301:
302: if (executableName != null) {
303: if (verbose) {
304: // rmi.console.09=NOTE: Using compiler executable: {0}
305: System.err.println(Messages.getString("rmi.console.09", //$NON-NLS-1$
306: executableName));
307: }
308: return new ExecJavaCompiler(executableName);
309: }
310:
311: // Trying to run Eclipse Compiler.
312: try {
313: JavaCompiler compiler = new EclipseJavaCompiler();
314:
315: if (verbose) {
316: // rmi.console.0A=NOTE: Using Eclipse Compiler
317: System.err
318: .println(Messages.getString("rmi.console.0A")); //$NON-NLS-1$
319: }
320: return compiler;
321: } catch (JavaCompilerException e) {
322: if (verbose) {
323: // rmi.console.0B=NOTE: Eclipse Compiler class not found: {0}
324: System.err.println(Messages.getString(
325: "rmi.console.0B", e)); //$NON-NLS-1$
326: }
327: }
328:
329: // Trying to run Javac executable from JAVA_HOME.
330: try {
331: JavaCompiler compiler = new ExecJavaCompiler(true);
332:
333: if (verbose) {
334: // rmi.console.0C=NOTE: Using JAVA_HOME Javac compiler
335: System.err
336: .println(Messages.getString("rmi.console.0C")); //$NON-NLS-1$
337: }
338: return compiler;
339: } catch (JavaCompilerException e) {
340: if (verbose) {
341: // rmi.console.0D=NOTE: JAVA_HOME Javac compiler not found: {0}
342: System.err.println(Messages.getString(
343: "rmi.console.0D", e)); //$NON-NLS-1$
344: }
345: }
346:
347: // Trying to run Javac executable from system path, as a last resort.
348: return new ExecJavaCompiler(false);
349: }
350: }
|