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

org.embulk.parser.seqfile.writable.EmbulkWritableFactory Maven / Gradle / Ivy

package org.embulk.parser.seqfile.writable;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Writable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EmbulkWritableFactory {
    private static final Logger log = LoggerFactory.getLogger(EmbulkWritableFactory.class);

    private static final String WRITABLE_PACKAGE = "package {packageName};";
    private static final String WRITABLE_CLASS = "public class {simpleName} extends " + EmbulkWritable.class.getName() + " {}";

    private static final JavaCompiler compiler;
    private static final ClassFileManager manager;
    static {
        compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            throw new UnsupportedOperationException(MessageFormat.format("This java({0}) does not support ToolProvider.getSystemJavaCompiler()", System.getProperty("java.home")));
        }
        manager = new ClassFileManager(compiler, null);
    }

    public static Writable createWritable(String className) {
        if (className.equals(NullWritable.class.getName())) {
            return NullWritable.get();
        }

        try {
            Class clazz = Class.forName(className, true, Writable.class.getClassLoader());
            return newInstance(clazz);
        } catch (ClassNotFoundException ignore) {
            // fall through
        }

        Class clazz = getWritableClass(className);
        return newInstance(clazz);
    }

    protected static Writable newInstance(Class clazz) {
        try {
            return Writable.class.cast(clazz.getConstructor().newInstance());
        } catch (IllegalArgumentException | ReflectiveOperationException | SecurityException e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public static Class getWritableClass(String className) {
        String sourceCode = getWritableSourceCode(className);
        JavaFileObject sourceFile = new JavaSourceFromString(className, sourceCode);

        List compilationUnits = Arrays.asList(sourceFile);
        String classPath = getClassPath();
        log.debug("EmbulkWritable classpath: " + classPath);
        List options = Arrays.asList("-classpath", classPath);
        CompilationTask task = compiler.getTask(null, manager, null, options, null, compilationUnits);

        boolean successCompile = task.call();
        if (!successCompile) {
            throw new RuntimeException("Writable compile failed. className=" + className);
        }

        ClassLoader classLoader = manager.getClassLoader(null);
        try {
            return (Class) classLoader.loadClass(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private static String getWritableSourceCode(String className) {
        String packageName, simpleName;
        {
            int n = className.lastIndexOf('.');
            if (n < 0) {
                packageName = null;
                simpleName = className;
            } else {
                packageName = className.substring(0, n);
                simpleName = className.substring(n + 1);
            }
        }

        String source;
        if (packageName == null) {
            source = "";
        } else {
            source = WRITABLE_PACKAGE.replace("{packageName}", packageName);
        }
        source += WRITABLE_CLASS.replace("{simpleName}", simpleName);

        return source;
    }

    private static String CLASS_PATH = null;

    private static String getClassPath() {
        if (CLASS_PATH == null) {
            ClassLoader classLoader = EmbulkWritable.class.getClassLoader();
            if (classLoader instanceof URLClassLoader) {
                @SuppressWarnings("resource")
                URLClassLoader urlClassLoader = (URLClassLoader) classLoader;

                StringBuilder sb = new StringBuilder(1024 * 11);
                for (URL url : urlClassLoader.getURLs()) {
                    if (sb.length() != 0) {
                        sb.append(File.pathSeparator);
                    }
                    try {
                        sb.append(Paths.get(url.toURI()));
                    } catch (URISyntaxException ignore) {
                        log.debug("ignore classLoader URI", ignore);
                    }
                }
                CLASS_PATH = sb.toString();
            } else {
                CLASS_PATH = System.getProperty("java.class.path");
            }
        }
        return CLASS_PATH;
    }

    public static ClassLoader getClassLoader() {
        return manager.getClassLoader(null);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy