Package com.firefly.utils

Source Code of com.firefly.utils.CompilerUtils

package com.firefly.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class CompilerUtils {
  private static final Map<String, JavaFileObject> output = new ConcurrentHashMap<String, JavaFileObject>();
  private static final ClassLoader classLoader = new CompilerClassLoader(CompilerUtils.class.getClassLoader());
  private static final Map<String, Class<?>> classCache = new ConcurrentHashMap<String, Class<?>>();
 
  public static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 
  public static Class<?> compileSource(String completeClassName, String source) throws Throwable {
    boolean result = false;
    JavaFileManager fileManager = CompilerUtils.getStringSourceJavaFileManager(compiler, null, null, Charset.forName("UTF-8"));
    try {
      CompilationTask task = compiler.getTask(null, fileManager, null, null, null,Arrays.asList(new JavaSourceFromString(completeClassName, source)));
      result = task.call();
    } finally {
      fileManager.close();
    }
   
    if(!result)
      return null;
   
    return getClassByName(completeClassName);
  }
 
  public static Class<?> getClassByName(String name) throws ClassNotFoundException {
    Class<?> ret = classCache.get(name);
    if(ret != null)
      return ret;
   
    synchronized(classCache) {
      ret = classCache.get(name);
      if(ret != null)
        return ret;
     
      ret = Class.forName(name, false, classLoader);
      classCache.put(name, ret);
      return ret;
    }
  }
 
  public static JavaFileManager getStringSourceJavaFileManager(JavaCompiler compiler, DiagnosticListener<? super JavaFileObject> diagnosticListener, Locale locale, Charset charset) {
   
    JavaFileManager fileManager = new ForwardingJavaFileManager<StandardJavaFileManager>(compiler.getStandardFileManager(diagnosticListener, locale,charset)) {
      @Override
      public JavaFileObject getJavaFileForOutput(Location location,
          String className, Kind kind, FileObject sibling)
          throws IOException {
        JavaFileObject jfo = new ByteJavaObject(className, kind);
        output.put(className, jfo);
        return jfo;
      }
    };
    return fileManager;
  }

  public static class JavaSourceFromString extends SimpleJavaFileObject {
    /**
     * The source code of this "file".
     */
    final String code;

    /**
     * Constructs a new JavaSourceFromString.
     *
     * @param name
     *            the name of the compilation unit represented by this file
     *            object
     * @param code
     *            the source code for the compilation unit represented by
     *            this file object
     */
    public JavaSourceFromString(String name, String code) {
      super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
      this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      return code;
    }
  }

  private static class ByteJavaObject extends SimpleJavaFileObject {

    private ByteArrayOutputStream baos;

    public ByteJavaObject(String name, Kind kind) {
      super(toURI(name), kind);
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors)
        throws IOException, IllegalStateException,
        UnsupportedOperationException {
      throw new UnsupportedOperationException();
    }

    @Override
    public InputStream openInputStream() throws IOException,
        IllegalStateException, UnsupportedOperationException {
      return new ByteArrayInputStream(baos.toByteArray());
    }

    @Override
    public OutputStream openOutputStream() throws IOException,
        IllegalStateException, UnsupportedOperationException {
      return baos = new ByteArrayOutputStream();
    }
  }

  private static class CompilerClassLoader extends ClassLoader {

    public CompilerClassLoader(ClassLoader classLoader) {
      super(classLoader);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      JavaFileObject jfo = output.get(name);
      if (jfo != null) {
        byte[] bytes = ((ByteJavaObject) jfo).baos.toByteArray();
        output.remove(name);
        return defineClass(name, bytes, 0, bytes.length);
      }
      return super.findClass(name);
    }
  }

  private static URI toURI(String name) {
    try {
      return new URI(name);
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }
  }

}
TOP

Related Classes of com.firefly.utils.CompilerUtils

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.