/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: CompilationUtils.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.tools; import com.uwyn.rife.config.RifeConfig; import com.uwyn.rife.tools.exceptions.CompilationFailedException; import com.uwyn.rife.tools.exceptions.FileUtilsErrorException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public abstract class CompilationUtils { public static File compile(String filenameJava, File fileClass, String generationPath, String classpath) throws CompilationFailedException { try { // compile the java source file to a class file if ((!RifeConfig.Global.isJavaCompilerPathSet() || RifeConfig.Global.getJavaCompilerInternal()) && RifeConfig.Global.isInternalJavaCompilerAvailable()) { String[] args = new String[] {"-g", "-classpath", classpath, "-d", generationPath, filenameJava}; Method compile_method = null; ByteArrayOutputStream errors_outputstream = new ByteArrayOutputStream(); PrintWriter errors_printwriter = new PrintWriter(errors_outputstream); // try to compile with printwriter support for error handling // otherwise use the regular compile method // this is needed for ibm jdk support try { compile_method = com.sun.tools.javac.Main.class.getDeclaredMethod("compile", new Class[] {String[].class, PrintWriter.class}); } catch (Throwable e) { compile_method = null; } // use the compile method with error reporting if it exists if (compile_method != null) { try { Object status = compile_method.invoke(null, new Object[] {args, errors_printwriter}); if (Integer.parseInt(String.valueOf(status)) != 0) { throw new CompilationFailedException(filenameJava, errors_outputstream.toString(), null); } } catch (IllegalAccessException e) { compile_method = null; } catch (InvocationTargetException e) { compile_method = null; } catch (IllegalArgumentException e) { compile_method = null; } } // use the regular compile method if (null == compile_method) { int status = com.sun.tools.javac.Main.compile(args); if (status != 0) { throw new CompilationFailedException(filenameJava, "<unknown error>", null); } } } else { // setup the command List<String> command_elements = new ArrayList<String>(); command_elements.add(RifeConfig.Global.getJavaCompilerPath()); if (RifeConfig.Global.areJavaCompilerArgsSet()) { command_elements.addAll(RifeConfig.Global.getJavaCompilerArgs()); } command_elements.add("-g"); command_elements.add("-d"); command_elements.add(generationPath); command_elements.add(filenameJava); String[] commands = new String[command_elements.size()]; command_elements.toArray(commands); // execute the command Process javac = ExecUtils.exec(commands, new String[] {"CLASSPATH="+classpath}); if (javac.exitValue() != 0 || !fileClass.exists()) { String error_message = null; try { error_message = FileUtils.readString(javac.getErrorStream()); } catch (FileUtilsErrorException e) { error_message = "<unknown error>"; } if (fileClass.exists()) { fileClass.delete(); } throw new CompilationFailedException(filenameJava, error_message, null); } } } catch (IOException e) { if (fileClass.exists()) { fileClass.delete(); } throw new CompilationFailedException(filenameJava, "An error occurred while launching the Java compiler.\n\nThere can be several reasons for this:\n- the JDK is maybe not installed; or\n- the compiler can't be found through your operating system's PATH environment variable; or\n- your operating system can't find the compiler path '"+RifeConfig.Global.getJavaCompilerPath()+"', try setting it up through the JAVA_COMPILER_PATH configuration parameter; or\n- the tools.jar file from the JDK isn't present in the classpath of your execution environment (servlet container).", e); } catch (InterruptedException e) { if (fileClass.exists()) { fileClass.delete(); } throw new CompilationFailedException(filenameJava, null, e); } return fileClass; } }