diff graal/com.oracle.max.base/src/com/sun/max/ide/ToolChain.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children bc8527f3071c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.base/src/com/sun/max/ide/ToolChain.java	Sat Dec 17 19:59:18 2011 +0100
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.max.ide;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+import javax.tools.*;
+import javax.tools.JavaCompiler.*;
+
+import com.sun.max.program.*;
+
+/**
+ * Provides an interface for invoking a Java source compiler (e.g. javac) and a C header and stub generator (i.e.
+ * javah). The Java source compiler used is determined the <a
+ * href="http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html">service provider mechanism</a>. For
+ * example, if you want to use the Eclipse batch compiler, then simply place the stand alone ecj.jar JAR file on the
+ * classpath.
+ */
+public final class ToolChain {
+
+    private ToolChain() {
+    }
+
+    private static JavaCompiler javaCompiler;
+
+    private static JavaCompiler javaCompiler() {
+        if (javaCompiler == null) {
+            final Iterator<JavaCompiler> iterator = ServiceLoader.load(JavaCompiler.class).iterator();
+            if (iterator.hasNext()) {
+                javaCompiler = iterator.next();
+            } else {
+                javaCompiler = ToolProvider.getSystemJavaCompiler();
+            }
+            ProgramError.check(javaCompiler != null, "Cannot find a Java compiler");
+        }
+        return javaCompiler;
+    }
+
+    /**
+     * Compiles the source for a given class. The location of the source file to be compiled and the directory to which
+     * the output class files are to be written are determined by the current {@link JavaProject} context.
+     * <p>
+     * The supported {@code options} are:
+     * <p>
+     *
+     * <pre>
+     *     -noinlinejsr    implement {@code finally} clauses using the {@link Bytecode#JSR} and {@link Bytecode#RET} bytecodes
+     * </pre>
+     *
+     *
+     * @param projClass a class denoting a project (i.e. any class in the project)
+     * @param className the name of the class to be compiled
+     * @param options options for modifying the compilation
+     * @return true if the compilation succeeded without any errors, false otherwise
+     */
+    public static boolean compile(Class projClass, String className, String... options) {
+        return compile(projClass, new String[] {className}, options);
+    }
+
+    /**
+     * Compiles the source for one or more given classes. The location of the source files to be compiled and the
+     * directory to which the output class files are to be written are determined by a given project
+     * context.
+     * <p>
+     * The supported {@code options} are:
+     * <p>
+     *
+     * <pre>
+     *     -noinlinejsr    implement {@code finally} clauses using the {@link Bytecode#JSR} and {@link Bytecode#RET} bytecodes
+     * </pre>
+     *
+     *
+     * @param projClass a class denoting a project (i.e. any class in the project)
+     * @param className the name of the class to be compiled
+     * @param options options for modifying the compilation
+     * @return true if the compilation succeeded without any errors, false otherwise
+     */
+    public static boolean compile(Class projClass, String[] classNames, String... options) {
+
+        final Classpath classPath = JavaProject.getClassPath(projClass, true);
+        final Classpath sourcePath = JavaProject.getSourcePath(projClass, true);
+        final String outputDirectory = classPath.entries().get(0).toString();
+
+        final ArrayList<File> sourceFiles = new ArrayList<File>(classNames.length);
+        for (String className : classNames) {
+            final String sourceFilePathSuffix = className.replace('.', File.separatorChar) + ".java";
+            final File sourceFile = sourcePath.findFile(sourceFilePathSuffix);
+            if (sourceFile == null) {
+                ProgramWarning.message("Could not find source file for " + className);
+                return false;
+            }
+            sourceFiles.add(sourceFile);
+        }
+
+        final JavaCompiler compiler = javaCompiler();
+        final String compilerName = compiler.getClass().getName();
+        final List<String> opts = new ArrayList<String>(Arrays.asList(new String[] {"-cp", classPath.toString(), "-d", outputDirectory}));
+        if (compilerName.equals("com.sun.tools.javac.api.JavacTool")) {
+            opts.add("-cp");
+            opts.add(classPath.toString());
+            opts.add("-d");
+            opts.add(outputDirectory);
+            for (String option : options) {
+                if (option.equals("-noinlinejsr")) {
+                    opts.add("-source");
+                    opts.add("1.4");
+                    opts.add("-target");
+                    opts.add("1.4");
+                    opts.add("-XDjsrlimit=0");
+                } else {
+                    throw new IllegalArgumentException("Unsupported compiler option " + option);
+                }
+            }
+        } else if (compiler.getClass().getName().equals("org.eclipse.jdt.internal.compiler.tool.EclipseCompiler")) {
+            opts.add("-cp");
+            opts.add(classPath.toString());
+            opts.add("-d");
+            opts.add(outputDirectory);
+            opts.add("-noExit");
+            boolean inlineJSR = true;
+            for (String option : options) {
+                if (option.equals("-noinlinejsr")) {
+                    inlineJSR = false;
+                } else {
+                    throw new IllegalArgumentException("Unsupported compiler option " + option);
+                }
+            }
+            if (inlineJSR) {
+                opts.add("-inlineJSR");
+            } else {
+                opts.add("-source");
+                opts.add("1.4");
+                opts.add("-target");
+                opts.add("1.4");
+            }
+        } else {
+            ProgramWarning.message("Unknown Java compiler may not accept same command line options as javac: " + compilerName);
+            opts.add("-cp");
+            opts.add(classPath.toString());
+            opts.add("-d");
+            opts.add(outputDirectory);
+        }
+
+        final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
+        final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
+        final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFiles);
+        final CompilationTask task = compiler.getTask(null, fileManager, diagnostics, opts, null, compilationUnits);
+        final boolean result = task.call();
+        final Set<String> reportedDiagnostics = new HashSet<String>();
+        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
+            final String message = diagnostic.getMessage(Locale.getDefault());
+            if (!reportedDiagnostics.contains(message)) {
+                reportedDiagnostics.add(message);
+                if (!message.contains("is Sun proprietary API and may be removed in a future release")) {
+                    System.err.println(message);
+                }
+            }
+        }
+        try {
+            fileManager.close();
+        } catch (IOException e) {
+            ProgramWarning.message("Error closing file manager: " + e);
+        }
+        return result;
+    }
+
+    private static Method javahMainMethod;
+
+    private static Method javah() {
+        if (javahMainMethod == null) {
+            Class<?> javahMainClass = null;
+            try {
+                // On the Apple JDKs, there is no tools.jar: all the tools are in classes.jar
+                javahMainClass = Class.forName("com.sun.tools.javah.Main");
+            } catch (ClassNotFoundException classNotFoundException) {
+                // This is expected on non-Apple JDKs
+                final ClassLoader systemToolClassLoader = ToolProvider.getSystemToolClassLoader();
+                ProgramError.check(systemToolClassLoader != null, "Cannot find the standard system tools class loader");
+                try {
+                    javahMainClass = Class.forName("com.sun.tools.javah.Main", true, systemToolClassLoader);
+                    final URLClassLoader urlClassLoader = (URLClassLoader) javahMainClass.getClassLoader();
+                    updateJavaClassPath(urlClassLoader);
+                } catch (Exception exception) {
+                    ProgramWarning.message("Cannot find or initialize javah: " + exception);
+                }
+            }
+            try {
+                if (javahMainClass != null) {
+                    javahMainMethod = javahMainClass.getDeclaredMethod("main", String[].class);
+                }
+            } catch (Exception exception) {
+                ProgramWarning.message("Cannot find or initialize javah: " + exception);
+            }
+        }
+        return javahMainMethod;
+    }
+
+    /**
+     * This hack is necessary as javah uses a doclet to do its actual work. The doclet class is found by creating a URL class loader
+     * from the system property "java.class.path" which does not include the path to tools.jar for
+     * standard JDK installations.
+     */
+    private static void updateJavaClassPath(final URLClassLoader urlClassLoader) {
+        String javaClassPath = System.getProperty("java.class.path", ".");
+        for (URL url : urlClassLoader.getURLs()) {
+            final String path = url.getPath();
+            if (path != null && !path.isEmpty()) {
+                final File file = new File(path);
+                if (file.exists()) {
+                    javaClassPath += File.pathSeparator + file.getAbsolutePath();
+                }
+            }
+        }
+        System.setProperty("java.class.path", javaClassPath);
+    }
+
+    public static boolean javah(String[] args) {
+        try {
+            javah().invoke(null, (Object) args);
+            return true;
+        } catch (InvocationTargetException e) {
+            ProgramWarning.message("Error invoking javah: " + e.getTargetException());
+        } catch (Exception e) {
+            ProgramWarning.message("Error invoking javah: " + e);
+        }
+        return false;
+    }
+
+    private static Method javapMainMethod;
+
+    private static Method javap() {
+        if (javapMainMethod == null) {
+            Class<?> javapMainClass = null;
+            try {
+                // On the Apple JDKs, there is no tools.jar: all the tools are in classes.jar
+                javapMainClass = Class.forName("sun.tools.javap.Main");
+            } catch (ClassNotFoundException classNotFoundException) {
+                // This is expected on non-Apple JDKs
+                final ClassLoader systemToolClassLoader = ToolProvider.getSystemToolClassLoader();
+                ProgramError.check(systemToolClassLoader != null, "Cannot find the standard system tools class loader");
+                try {
+                    javapMainClass = Class.forName("sun.tools.javap.Main", true, systemToolClassLoader);
+                } catch (Exception exception) {
+                    ProgramWarning.message("Cannot find or initialize javap: " + exception);
+                }
+            }
+            try {
+                if (javapMainClass != null) {
+                    javapMainMethod = javapMainClass.getDeclaredMethod("main", String[].class);
+                }
+            } catch (Exception exception) {
+                ProgramWarning.message("Cannot find or initialize javap: " + exception);
+            }
+        }
+        return javapMainMethod;
+    }
+
+    public static boolean javap(String[] args) {
+        try {
+            javap().invoke(null, (Object) args);
+            return true;
+        } catch (InvocationTargetException e) {
+            ProgramWarning.message("Error invoking javap: " + e.getTargetException());
+        } catch (Exception e) {
+            ProgramWarning.message("Error invoking javap: " + e);
+        }
+        return false;
+    }
+}