2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - 2011 - Calixte DENIZET <calixte@contrib.scilab.org>
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13 package org.scilab.modules.external_objects_java;
16 import java.io.StringWriter;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 import java.net.MalformedURLException;
20 import java.net.URLClassLoader;
23 import java.util.Arrays;
24 import java.util.Locale;
25 import java.util.ServiceLoader;
26 import java.util.logging.Level;
28 import javax.tools.Diagnostic;
29 import javax.tools.DiagnosticCollector;
30 import javax.tools.JavaCompiler;
31 import javax.tools.JavaFileObject;
32 import javax.tools.SimpleJavaFileObject;
33 import javax.tools.StandardJavaFileManager;
34 import javax.tools.ToolProvider;
35 import javax.tools.JavaCompiler.CompilationTask;
36 import javax.tools.JavaFileObject.Kind;
39 * Class to provide a java compiler to JIMS.
40 * Try to find the compiler provide with JDK and if it is not found, use the Eclipse Compiler for Java
41 * @author Calixte DENIZET
43 @SuppressWarnings("serial")
44 public class ScilabJavaCompiler {
46 private static final String JAVACOMPILER = "javax.tools.JavaCompiler";
47 private static final String binpath = System.getProperty("java.io.tmpdir") + File.separator + "JIMS" + File.separator + "bin";
49 private static JavaCompiler compiler;
52 new File(System.getProperty("java.io.tmpdir") + File.separator + "JIMS").mkdir();
53 new File(binpath).mkdir();
55 URL binURL = new File(binpath).toURI().toURL();
56 addURLToClassPath(binURL);
57 } catch (MalformedURLException e) {
58 System.err.println(e);
63 * Just find a compiler
65 private static void findCompiler() throws ScilabJavaException {
66 if (compiler == null) {
68 compiler = ToolProvider.getSystemJavaCompiler();
69 } catch (Exception e) { }
71 if (compiler == null) {
72 ServiceLoader<JavaCompiler> jcompilers = ServiceLoader.load(JavaCompiler.class);
73 for (JavaCompiler jc : jcompilers) {
81 if (compiler == null) {
82 throw new ScilabJavaException("No java compiler in the classpath\nCheck for tools.jar (comes from JDK) or ecj-3.6.x.ajr (Eclipse Compiler for Java)");
88 * Compile code got as string
89 * @param className the class name
90 * @param code the lines giving the code to compile
91 * @return an integer corresponding to the compiled and loaded class.
93 public static int compileCode(String className, String[] code) throws ScilabJavaException {
96 if (ScilabJavaObject.debug) {
97 ScilabJavaObject.logger.log(Level.INFO, "Compilation of class \'" + className + "\'");
100 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
102 SourceString file = new SourceString(className, code);
103 StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null);
104 Iterable <? extends JavaFileObject > compilationUnits = Arrays.asList(file);
105 String[] compileOptions = new String[] {"-d", binpath} ;
106 Iterable<String> options = Arrays.asList(compileOptions);
108 CompilationTask task = compiler.getTask(null, stdFileManager, diagnostics, options, null, compilationUnits);
110 boolean success = task.call();
111 StringBuffer buf = new StringBuffer();
112 for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
113 buf.append(diagnostic.toString());
118 return ScilabClassLoader.loadJavaClass(className, true);
120 throw new ScilabJavaException(buf.toString());
125 * Add a class in the classpath
126 * @param url the class url
128 public static void addURLToClassPath(URL url) {
129 URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
131 final Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class});
132 method.setAccessible(true);
133 method.invoke(sysloader , new Object[] {url});
134 } catch (NoSuchMethodException e) {
135 System.err.println("Error: Cannot find the declared method: " + e.getLocalizedMessage());
136 } catch (IllegalAccessException e) {
137 System.err.println("Error: Illegal access: " + e.getLocalizedMessage());
138 } catch (InvocationTargetException e) {
139 System.err.println("Error: Could not invocate target: " + e.getLocalizedMessage());
144 * Inner class to handle String as File
146 private static class SourceString extends SimpleJavaFileObject {
148 private final String code;
150 private SourceString(String className, String[] code) {
151 super(new File(binpath + "/" + className.replace('.', '/') + Kind.SOURCE.extension).toURI(), Kind.SOURCE);
153 StringBuffer buf = new StringBuffer();
154 for (String str : code) {
158 this.code = buf.toString();
161 public CharSequence getCharContent(boolean ignoreEncodingErrors) {