All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrdf.repository.object.compiler.source.JavaCompiler Maven / Gradle / Ivy

Go to download

The Object Composition library merges multiple Java objects into a single multi-subject object.

There is a newer version: 2.4
Show newest version
/*
 * Copyright (c) 2007-2008, James Leigh All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution. 
 * - Neither the name of the openrdf.org nor the names of its contributors may
 *   be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 */
package org.openrdf.repository.object.compiler.source;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Java Compiler that can detects the present of a JDK.
 * 
 * @author James Leigh
 * 
 */
public class JavaCompiler {

	final Logger logger = LoggerFactory.getLogger(JavaCompiler.class);

	private String version = "5";
	private boolean useTools = true;

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public void compile(Iterable content, File dir, List classpath)
			throws IOException {
		List source = new ArrayList();
		for (String name : content) {
			String filename = name.replace('.', File.separatorChar);
			source.add(new File(dir.getAbsoluteFile(), filename + ".java"));
		}
		File argfile = buildJavacArgfile(source, classpath);
		try {
			String[] args = new String[] { "@" + argfile.getAbsolutePath() };
			if (javac(args) != 0)
				throw new IOException("Could not compile");
		} finally {
			argfile.delete();
		}
	}

	/**
	 * Try and run any available compiler. Try embedded compilers before
	 * external commands. Only fail if all compilers have be attempted.
	 */
	private int javac(String[] args) throws IOException {
		int result = -1;
		if (useTools) {
			result = javaCompilerTool(args);
			if (result < 0) {
				result = javaSunTools(args);
			}
		}
		if (result == 0)
			return result;
		result = javacCommand(args);
		if (result == 0) {
			useTools = false;
		}
		if (result >= 0)
			return result;
		throw new AssertionError("No Compiler Found");
	}

	/**
	 * Requires JDK6. This will sometimes try and write to user.dir and may
	 * throw an {@link java.security.AccessControlException}.
	 */
	private int javaCompilerTool(String[] args) {
		try {
			Class provider = forName("javax.tools.ToolProvider");
			Method getJavaCompiler = provider
					.getMethod("getSystemJavaCompiler");
			Class tool = forName("javax.tools.Tool");
			Method run = tool.getMethod("run", InputStream.class,
					OutputStream.class, OutputStream.class, args.getClass());
			Object compiler = getJavaCompiler.invoke(null);
			if (compiler == null) {
				return -1;
			}
			logger.debug("invoke javax.tools.JavaCompiler#run");
			Object[] param = new Object[] { null, null, null, args };
			Object result = run.invoke(compiler, param);
			return ((Number) result).intValue();
		} catch (InvocationTargetException e) {
			logger.warn(e.toString());
			return -1;
		} catch (ClassNotFoundException e) {
			return -1;
		} catch (IllegalArgumentException e) {
			return -1;
		} catch (IllegalAccessException e) {
			return -1;
		} catch (SecurityException e) {
			return -1;
		} catch (NoSuchMethodException e) {
			return -1;
		}
	}

	private Class forName(String className) throws ClassNotFoundException {
		ClassLoader cl = getClass().getClassLoader();
		if (cl == null)
			return Class.forName(className);
		synchronized (cl) {
			return Class.forName(className, true, cl);
		}
	}

	/**
	 * Requires Sun tools.jar in class-path.
	 */
	private int javaSunTools(String[] args) {
		try {
			Class sun;
			try {
				sun = forName("com.sun.tools.javac.Main");
			} catch (ClassNotFoundException e) {
				return -1;
			}
			Method method = sun.getMethod("compile", args.getClass());
			logger.debug("invoke com.sun.tools.javac.Main#compile");
			Object result = method.invoke(null, new Object[] { args });
			return ((Number) result).intValue();
		} catch (InvocationTargetException e) {
			logger.warn(e.toString());
			return -1;
		} catch (IllegalArgumentException e) {
			return -1;
		} catch (IllegalAccessException e) {
			return -1;
		} catch (SecurityException e) {
			return -1;
		} catch (NoSuchMethodException e) {
			return -1;
		}
	}

	/**
	 * Requires JDK installation.
	 * 
	 * @throws IOException
	 */
	private int javacCommand(String[] args) throws IOException {
		String javac = findJavac();
		if (javac == null)
			return -1;
		return exec(javac, args);
	}

	private String findJavac() {
		String javac = findJavac(System.getProperty("jdk.home"));
		if (javac == null)
			javac = findJavac(System.getProperty("java.home"));
		if (javac == null)
			javac = findJavac(System.getenv("JAVA_HOME"));
		if (javac == null) {
			String systemPath = System.getenv("PATH");
			for (String path : systemPath.split(File.pathSeparator)) {
				File file = new File(path, "javac");
				if (exists(file))
					return file.getPath();
			}
		}
		return javac;
	}

	private String findJavac(String home) {
		if (home == null)
			return null;
		File javac = new File(new File(home, "bin"), "javac");
		if (exists(javac))
			return javac.getPath();
		javac = new File(new File(home, "bin"), "javac.exe");
		if (exists(javac))
			return javac.getPath();
		File parent = new File(home).getParentFile();
		javac = new File(new File(parent, "bin"), "javac");
		if (exists(javac))
			return javac.getPath();
		javac = new File(new File(parent, "bin"), "javac.exe");
		if (exists(javac))
			return javac.getPath();
		for (File dir : parent.listFiles()) {
			javac = new File(new File(dir, "bin"), "javac");
			if (exists(javac))
				return javac.getPath();
			javac = new File(new File(dir, "bin"), "javac.exe");
			if (exists(javac))
				return javac.getPath();
		}
		return null;
	}

	private boolean exists(File javac) {
		try {
			return javac.exists();
		} catch (SecurityException e) {
			logger.warn(e.getMessage());
			return false;
		}
	}

	private int exec(String cmd, String[] args) throws IOException {
		logger.debug("exec {}", cmd);
		String[] cmdArray = new String[1 + args.length];
		cmdArray[0] = cmd;
		System.arraycopy(args, 0, cmdArray, 1, args.length);
		File wd = File.createTempFile("javac", "dir");
		wd.delete();
		wd = wd.getParentFile();
		final Process exec = Runtime.getRuntime().exec(cmdArray, null, wd);
		try {
			Thread gobbler = new Thread() {
				@Override
				public void run() {
					try {
						InputStream in = exec.getInputStream();
						try {
							InputStreamReader isr = new InputStreamReader(in);
							BufferedReader br = new BufferedReader(isr);
							String line = null;
							while ((line = br.readLine()) != null) {
								System.out.println(line);
							}
						} finally {
							in.close();
						}
					} catch (IOException ioe) {
						logger.error(ioe.getMessage(), ioe);
					}
				}
			};
			gobbler.start();
			InputStream stderr = exec.getErrorStream();
			try {
				exec.getOutputStream().close();
				InputStreamReader isr = new InputStreamReader(stderr);
				BufferedReader br = new BufferedReader(isr);
				String line = null;
				while ((line = br.readLine()) != null) {
					System.err.println(line);
				}
			} finally {
				stderr.close();
			}
			try {
				return exec.waitFor();
			} catch (InterruptedException cause) {
				InterruptedIOException e = new InterruptedIOException(cause.getMessage());
				e.initCause(cause);
				throw e;
			}
		} finally {
			exec.destroy();
		}
	}

	private File buildJavacArgfile(List sources, List classpath) throws IOException {
		File args = File.createTempFile("javac", "args");
		PrintWriter w = new PrintWriter(new FileWriter(args));
		try {
			w.println("-nowarn");
			w.println("-source");
			w.println(version);
			w.println("-target");
			w.println(version);
			w.println("-classpath");
			w.print("\"");
			for (File jar : classpath) {
				w.print(jar.getAbsolutePath().replace("\\", "\\\\"));
				w.print(File.pathSeparatorChar);
			}
			w.println("\"");
			for (int i = 0, n = sources.size(); i < n; i++) {
				w.print("\"");
				w.print(sources.get(i).getAbsolutePath().replace("\\", "\\\\"));
				w.println("\"");
			}
		} finally {
			w.close();
		}
		return args;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy