Package jetbrick.template.compiler

Source Code of jetbrick.template.compiler.JdkCompiler

/**
* jetbrick-template
* http://subchen.github.io/jetbrick-template/
*
* Copyright 2010-2014 Guoqiang Chen. All rights reserved.
* Email: subchen@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrick.template.compiler;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import jetbrick.template.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* 利用 JDK6 提供的 Java Compiler 进行编译,提供详细的错误输出。
*/
public class JdkCompiler extends JavaCompiler {
    final Logger log = LoggerFactory.getLogger(JdkCompiler.class);
    private final boolean isJdk6;
    private javax.tools.JavaCompiler jc;
    private StandardJavaFileManager fileManager;
    private List<String> options; // 编译参数

    public JdkCompiler() {
        String version = System.getProperty("java.version");
        if (version != null && version.contains("1.6.")) {
            this.isJdk6 = true;
        } else {
            this.isJdk6 = false;
        }
    }

    @Override
    protected void initialize() {
        javax.tools.JavaCompiler jcc = ToolProvider.getSystemJavaCompiler();
        if (jcc == null) {
            // JDT 支持 ServiceLoader 方式载入。
            ServiceLoader<javax.tools.JavaCompiler> serviceLoader = ServiceLoader.load(javax.tools.JavaCompiler.class);
            Iterator<javax.tools.JavaCompiler> iterator = serviceLoader.iterator();
            if (iterator.hasNext()) {
                jcc = iterator.next();
            }
        }
        if (jcc == null) {
            throw new IllegalStateException("Can't get system java compiler. Please add jdk tools.jar to your classpath.");
        }

        this.jc = jcc;
        this.fileManager = jc.getStandardFileManager(null, null, null);
        this.options = Arrays.asList("-encoding", JavaSource.JAVA_FILE_ENCODING, "-g", "-nowarn", "-source", "1.6", "-target", "1.6");

        setDefaultClasspath(fileManager);
    }

    private void setDefaultClasspath(StandardJavaFileManager fileManager) {
        ClassLoader contextClassLoader = ClassLoaderUtils.getContextClassLoader();
        Collection<URL> classpath = ClassLoaderUtils.getClasspathURLs(contextClassLoader);

        // add dependences
        // @formatter:off
        List<String> classlist = Arrays.asList(
            "jetbrick.template.JetEngine",
            "javax.servlet.ServletContext",
            "org.slf4j.LoggerFactory"
        );
        // @formatter:on
        for (String klass : classlist) {
            try {
                Class<?> cls = contextClassLoader.loadClass(klass);
                classpath.add(cls.getProtectionDomain().getCodeSource().getLocation());
            } catch (ClassNotFoundException e) {
            }
        }

        if (classpath.size() > 0) {
            try {
                Set<File> files = new LinkedHashSet<File>(classpath.size() + 16);
                for (URL url : classpath) {
                    File file = URLUtils.toFileObject(url);
                    if (file.exists()) {
                        files.add(file);
                    }
                }
                Iterable<? extends File> list = fileManager.getLocation(StandardLocation.CLASS_PATH);
                for (File file : list) {
                    files.add(file);
                }
                fileManager.setLocation(StandardLocation.CLASS_PATH, files);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }

        // 输出编译用的 classpath
        if (debugEnabled) {
            if (log.isInfoEnabled()) {
                Iterable<? extends File> files = fileManager.getLocation(StandardLocation.CLASS_PATH);
                for (File file : files) {
                    log.info("Compilation classpath: " + file.getAbsolutePath());
                }
            }
        }
    }

    @Override
    protected void generateJavaClass(JavaSource source) {
        // 编译代码
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); // 编译器编译中的诊断信息
        Iterable<? extends JavaFileObject> files = fileManager.getJavaFileObjects(source.getJavaFile()); // 要编译的所有Java文件
        CompilationTask task = jc.getTask(null, fileManager, diagnostics, options, null, files);

        Boolean result;
        if (isJdk6) {
            // jdk6 的 compiler 是线程不安全的,需要手动同步
            synchronized (this) {
                result = task.call();
            }
        } else {
            // jdk7+ 的 compiler 是线程安全的
            result = task.call();
        }

        // 返回编译结果
        if ((result == null) || !result.booleanValue()) {
            String[] sourceCodeLines = source.getSourceCode().split("\r?\n", -1);
            StringBuilder sb = new StringBuilder();
            sb.append("Compilation failed.");
            sb.append('\n');
            for (Diagnostic<? extends JavaFileObject> d : diagnostics.getDiagnostics()) {
                sb.append(d.getMessage(Locale.ENGLISH)).append('\n');
                sb.append(StringUtils.getPrettyError(sourceCodeLines, (int) d.getLineNumber(), (int) d.getColumnNumber(), (int) d.getPosition(), (int) d.getPosition(), 3));
            }
            sb.append(diagnostics.getDiagnostics().size());
            sb.append(" error(s)\n");
            throw new CompileErrorException(sb.toString());
        }
    }
}
TOP

Related Classes of jetbrick.template.compiler.JdkCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.