001/*
002 * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
003 * Use is subject to license terms.
004 *
005 * Redistribution and use in source and binary forms, with or without modification, are 
006 * permitted provided that the following conditions are met: Redistributions of source code 
007 * must retain the above copyright notice, this list of conditions and the following disclaimer.
008 * Redistributions in binary form must reproduce the above copyright notice, this list of 
009 * conditions and the following disclaimer in the documentation and/or other materials 
010 * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
011 * is contributors may be used to endorse or promote products derived from this software 
012 * without specific prior written permission. 
013
014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
016 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
017 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
018 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
019 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
020 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
021 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
022 * POSSIBILITY OF SUCH DAMAGE.
023 */
024
025/*
026 * JavaCompiler.java
027 * @author A. Sundararajan
028 */
029
030package org.kepler.scriptengine.java;
031
032import java.io.IOException;
033import java.io.PrintWriter;
034import java.io.Writer;
035import java.util.ArrayList;
036import java.util.List;
037import java.util.Map;
038
039import javax.tools.Diagnostic;
040import javax.tools.DiagnosticCollector;
041import javax.tools.JavaFileObject;
042import javax.tools.StandardJavaFileManager;
043import javax.tools.ToolProvider;
044
045/**
046 * Simple interface to Java compiler using JSR 199 Compiler API.
047 */
048public class JavaCompiler {    
049    private javax.tools.JavaCompiler tool;
050    private StandardJavaFileManager stdManager;
051
052    public JavaCompiler() {
053        tool = ToolProvider.getSystemJavaCompiler();
054        stdManager = tool.getStandardFileManager(null, null, null);
055    }
056
057    public Map<String, byte[]> compile(String source, String fileName) {
058        PrintWriter err = new PrintWriter(System.err);
059        return compile(source, fileName, err, null, null);
060    }
061
062    public Map<String, byte[]> compile(String fileName, String source, 
063                                    Writer err) {
064        return compile(fileName, source, err, null, null);
065    }
066
067    public Map<String, byte[]> compile(String fileName, String source, 
068                                    Writer err, String sourcePath) {
069        return compile(fileName, source, err, sourcePath, null);
070    }
071
072    /**
073     * compile given String source and return bytecodes as a Map.
074     *
075     * @param fileName source fileName to be used for error messages etc.
076     * @param source Java source as String
077     * @param err error writer where diagnostic messages are written
078     * @param sourcePath location of additional .java source files
079     * @param classPath location of additional .class files
080     */
081    public Map<String, byte[]> compile(String fileName, String source, 
082                    Writer err, String sourcePath, String classPath) {
083        // to collect errors, warnings etc.
084        DiagnosticCollector<JavaFileObject> diagnostics = 
085            new DiagnosticCollector<JavaFileObject>();
086
087        // create a new memory JavaFileManager
088        MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager);
089
090        // prepare the compilation unit
091        List<JavaFileObject> compUnits = new ArrayList<JavaFileObject>(1);
092        compUnits.add(MemoryJavaFileManager.makeStringSource(fileName, source));
093
094        // javac options
095        List<String> options = new ArrayList<String>();
096        options.add("-Xlint:all");
097        options.add("-g:none");
098        options.add("-deprecation");
099        if (sourcePath != null) {
100            options.add("-sourcepath");
101            options.add(sourcePath);
102        }
103
104        if (classPath != null) {
105            options.add("-classpath");
106            options.add(classPath);
107        }
108       
109        //System.out.println("Going to compile: ");
110        //System.out.println(source);
111        
112        // create a compilation task
113        javax.tools.JavaCompiler.CompilationTask task =
114            tool.getTask(err, manager, diagnostics, 
115                         options, null, compUnits);
116
117        if (task.call() == false) {
118            PrintWriter perr = new PrintWriter(err);
119            for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {                
120                perr.println(diagnostic.getMessage(null));
121            }
122            perr.flush();
123            return null;
124        }
125
126        Map<String, byte[]> classBytes = manager.getClassBytes();
127        try {
128            manager.close();
129        } catch (IOException exp) {
130        }
131
132        return classBytes; 
133    }
134}