Package org.apache.drill.exec.compile

Source Code of org.apache.drill.exec.compile.JDKClassCompiler$DiagListener

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.drill.exec.compile;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
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.StandardLocation;
import javax.tools.ToolProvider;

import org.codehaus.commons.compiler.CompileException;
import org.codehaus.commons.compiler.Location;
import org.codehaus.commons.compiler.jdk.ByteArrayJavaFileManager;
import org.codehaus.commons.compiler.jdk.ByteArrayJavaFileManager.ByteArrayJavaFileObject;

import com.google.common.collect.Lists;


class JDKClassCompiler implements ClassCompiler {
  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JDKClassCompiler.class);

  private boolean debugLines;
  private boolean debugVars;
  private boolean debugSource;
  private Collection<String> compilerOptions = new ArrayList<String>();
  private DiagnosticListener<JavaFileObject> listener;
  private final JavaCompiler compiler;
  private final JavaFileManager fileManager;
 
  public JDKClassCompiler() {
    this.compiler = ToolProvider.getSystemJavaCompiler();
    if (compiler == null) {
      throw new UnsupportedOperationException(
          "JDK Java compiler not available - probably you're running a JRE, not a JDK");
    }
    this.fileManager = new ByteArrayJavaFileManager<JavaFileManager>(compiler.getStandardFileManager(null, null, null));
    this.listener = new DiagListener();
  }

  private JavaFileObject getCompilationUnit(final String s) {

    final URI uri;
    try {
      uri = new URI("drill-class-compiler");
    } catch (URISyntaxException use) {
      throw new RuntimeException(use);
    }
    JavaFileObject javaFileObject = new SimpleJavaFileObject(uri, Kind.SOURCE) {

      @Override
      public boolean isNameCompatible(String simpleName, Kind kind) {
        return true;
      }

      @Override
      public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
        return new StringReader(s);
      }

      @Override
      public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
        return s;
      }

    };

    return javaFileObject;
  }

  private List<String> getOptions() {
    List<String> opts = Lists.newArrayList(compilerOptions);
    String option = this.debugSource ? "-g:source" + (this.debugLines ? ",lines" : "")
        + (this.debugVars ? ",vars" : "") : this.debugLines ? "-g:lines" + (this.debugVars ? ",vars" : "")
        : this.debugVars ? "-g:vars" : "-g:none";
    opts.add(option);
    return opts;
  }

  /* (non-Javadoc)
   * @see org.apache.drill.exec.compile.ClassCompiler#getClassByteCode(java.lang.String, java.lang.String)
   */
  @Override
  public byte[] getClassByteCode(final String className, final String sourcecode) throws CompileException, IOException,
      ClassNotFoundException {

    // Create one Java source file in memory, which will be compiled later.
    JavaFileObject compilationUnit = getCompilationUnit(sourcecode);

    //logger.debug("Compiling the following source code\n{}", sourcecode);
    // Run the compiler.
    try {
      CompilationTask task = compiler.getTask(null, fileManager, listener, getOptions(), null, Collections.singleton(compilationUnit));
      long n0 = System.nanoTime();
      if(!task.call()){
        throw new CompileException("Compilation failed", null);
      }
      long n1 = (System.nanoTime() - n0)/1000/1000;
     
    } catch (RuntimeException rte) {
     
      // Unwrap the compilation exception and throw it.
      Throwable cause = rte.getCause();
      if (cause != null) {
        cause = cause.getCause();
        if (cause instanceof CompileException) throw (CompileException) cause;
        if (cause instanceof IOException) throw (IOException) cause;
      }
      throw rte;
    }

    JavaFileObject classFileObject = fileManager.getJavaFileForInput(StandardLocation.CLASS_OUTPUT, className, Kind.CLASS);

    if (classFileObject == null) {
      throw new ClassNotFoundException(className + ": Class file not created by compilation");
    }

    if (!(classFileObject instanceof ByteArrayJavaFileObject))
      throw new UnsupportedOperationException("Only supports byte array based java file objects.");

    ByteArrayJavaFileObject bajfo = (ByteArrayJavaFileObject) classFileObject;
    return bajfo.toByteArray();

  }

  private class DiagListener implements DiagnosticListener<JavaFileObject> {
    @Override
    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
      System.err.println("*** " + diagnostic.toString() + " *** " + diagnostic.getCode());

      Location loc = new Location( //
          diagnostic.getSource().toString(), //
          (short) diagnostic.getLineNumber(), //
          (short) diagnostic.getColumnNumber() //
      );
      String code = diagnostic.getCode();
      String message = diagnostic.getMessage(null) + " (" + code + ")";

      // Wrap the exception in a RuntimeException, because "report()" does not declare checked
      // exceptions.
      throw new RuntimeException(new CompileException(message, loc));
    }
  }


 
 

}
TOP

Related Classes of org.apache.drill.exec.compile.JDKClassCompiler$DiagListener

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.