All Downloads are FREE. Search and download functionalities are using the official Maven repository.

one.nio.compiler.Javac Maven / Gradle / Ivy

/*
 * Copyright 2015 Odnoklassniki Ltd, Mail.Ru Group
 *
 * 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 one.nio.compiler;

import one.nio.util.JavaInternals;
import one.nio.util.URLEncoder;
import sun.misc.URLClassPath;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;

public class Javac {
    private final JavaCompiler compiler;
    private final StandardJavaFileManager fileManager;
    private final String classPath;

    public Javac() {
        this(System.getProperty("java.class.path"));
    }

    public Javac(ClassLoader loader) {
        this(buildPathFromClassLoader(loader));
    }

    public Javac(String classPath) {
        this.compiler = ToolProvider.getSystemJavaCompiler();
        this.fileManager = compiler.getStandardFileManager(null, null, null);
        this.classPath = classPath;
    }

    public byte[] compile(CharSequence code) throws CompilationException {
        CharArrayWriter messages = new CharArrayWriter();
        List options = Arrays.asList("-classpath", classPath);
        List input = Arrays.asList(new MemoryInputFileObject(code));
        final ByteArrayOutputStream output = new ByteArrayOutputStream(200);

        JavaFileManager manager = new ForwardingJavaFileManager(fileManager) {
            @Override
            public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
                return new MemoryOutputFileObject(output);
            }
        };

        if (compiler.getTask(messages, manager, null, options, null, input).call()) {
            return output.toByteArray();
        }

        throw new CompilationException(messages.toString());
    }

    private static String buildPathFromClassLoader(ClassLoader loader) {
        StringBuilder builder = new StringBuilder();
        Field ucp = JavaInternals.getField(URLClassLoader.class, "ucp");

        while (loader instanceof URLClassLoader) {
            for (URL url : getURLsFromClassLoader((URLClassLoader) loader, ucp)) {
                if ("file".equals(url.getProtocol())) {
                    String file = URLEncoder.decode(url.getFile());
                    builder.append(file).append(File.pathSeparatorChar);
                }
            }
            loader = loader.getParent();
        }

        return builder.toString();
    }

    private static URL[] getURLsFromClassLoader(URLClassLoader loader, Field ucp) {
        if (ucp != null) {
            try {
                // Some custom URLClassLoaders do not return getURLs. Hack them using internal API.
                return ((URLClassPath) ucp.get(loader)).getURLs();
            } catch (Exception e) {
                // Fallback to public API
            }
        }
        return loader.getURLs();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy