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

juzu.impl.compiler.Compiler Maven / Gradle / Ivy

/*
 * Copyright 2013 eXo Platform SAS
 *
 * 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 juzu.impl.compiler;

import juzu.impl.common.Tools;
import juzu.impl.common.FileKey;
import juzu.impl.compiler.file.JavaFileObjectImpl;
import juzu.impl.compiler.file.SimpleFileManager;
import juzu.impl.fs.Filter;
import juzu.impl.fs.Visitor;
import juzu.impl.fs.spi.ReadFileSystem;
import juzu.impl.fs.spi.ReadWriteFileSystem;
import juzu.impl.fs.spi.ram.RAMFileSystem;
import juzu.impl.common.Location;
import juzu.impl.common.Spliterator;

import javax.annotation.processing.Processor;
import javax.inject.Provider;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/** @author Julien Viet */
public class Compiler {

  public static Builder builder() {
    return new Builder(null, null, null, new ArrayList>());
  }

  public static class Builder {

    /** . */
    private ReadFileSystem sourcePath;

    /** . */
    private ReadWriteFileSystem classOutput;

    /** . */
    private ReadWriteFileSystem sourceOutput;

    /** . */
    private List> classPaths;

    /** . */
    private Provider processor;

    /** . */
    private Provider javaCompiler;

    /** . */
    private CompilerConfig config;

    private Builder(
      ReadFileSystem sourcePath,
      ReadWriteFileSystem sourceOutput,
      ReadWriteFileSystem classOutput,
      List> classPaths) {
      Provider javaCompiler = new Provider() {
        public JavaCompiler get() {
          return ToolProvider.getSystemJavaCompiler();
        }
      };
      this.processor = null;
      this.javaCompiler = javaCompiler;
      this.sourcePath = sourcePath;
      this.sourceOutput = sourceOutput;
      this.classOutput = classOutput;
      this.classPaths = classPaths;
      this.config = new CompilerConfig();
    }

    public Builder javaCompiler(Provider javaCompiler) {
      this.javaCompiler = javaCompiler;
      return this;
    }

    public Builder processor(Provider processor) {
      this.processor = processor;
      return this;
    }

    public Builder classOutput(ReadWriteFileSystem classOutput) {
      this.classOutput = classOutput;
      return this;
    }

    public Builder output(ReadWriteFileSystem output) {
      this.classOutput = this.sourceOutput = output;
      return this;
    }

    public Builder sourcePath(ReadFileSystem sourcePath) {
      this.sourcePath = sourcePath;
      return this;
    }

    public Builder sourceOutput(ReadWriteFileSystem sourceOutput) {
      this.sourceOutput = sourceOutput;
      return this;
    }

    public Builder addClassPath(ReadFileSystem classPath) {
      classPaths.add(classPath);
      return this;
    }

    public Builder addClassPath(Iterable> classPaths) {
      for (ReadFileSystem classPath : classPaths) {
        addClassPath(classPath);
      }
      return this;
    }

    public Builder config(CompilerConfig config) {
      this.config = config;
      return this;
    }

    public Compiler build() {
      if (sourcePath == null) {
        throw new IllegalStateException("No null source path");
      }
      if (classOutput == null) {
        throw new IllegalStateException("No null class output");
      }
      if (sourceOutput == null) {
        throw new IllegalStateException("No null source output");
      }
      Compiler compiler = new Compiler(
        javaCompiler.get(),
        sourcePath,
        classPaths,
        sourceOutput,
        classOutput,
        config
      );
      if (processor != null) {
        compiler.addAnnotationProcessor(processor.get());
      }
      return compiler;
    }
  }

  /** . */
  private JavaCompiler javaCompiler;

  /** . */
  private Set processors;

  /** . */
  private ReadFileSystem sourcePath;

  /** . */
  private ReadWriteFileSystem classOutput;

  /** . */
  private ReadWriteFileSystem sourceOutput;

  /** . */
  private Collection> classPaths;

  /** . */
  private CompilerConfig config;

  public Compiler(
    ReadFileSystem sourcePath,
    ReadWriteFileSystem output,
    CompilerConfig config) {
    this(sourcePath, output, output, config);
  }

  public Compiler(
    ReadFileSystem sourcePath,
    ReadWriteFileSystem sourceOutput,
    ReadWriteFileSystem classOutput,
    CompilerConfig config) {
    this(sourcePath, Collections.>emptyList(), sourceOutput, classOutput, config);
  }

  public Compiler(
    ReadFileSystem sourcePath,
    ReadFileSystem classPath,
    ReadWriteFileSystem sourceOutput,
    ReadWriteFileSystem classOutput,
    CompilerConfig config) {
    this(sourcePath, Collections.>singletonList(classPath), sourceOutput, classOutput, config);
  }

  public Compiler(
      ReadFileSystem sourcePath,
      Collection> classPaths,
      ReadWriteFileSystem sourceOutput,
      ReadWriteFileSystem classOutput,
      CompilerConfig config) {
    this(ToolProvider.getSystemJavaCompiler(), sourcePath, classPaths, sourceOutput, classOutput, config);
  }

  public Compiler(
    JavaCompiler javaCompiler,
    ReadFileSystem sourcePath,
    Collection> classPaths,
    ReadWriteFileSystem sourceOutput,
    ReadWriteFileSystem classOutput,
    CompilerConfig config) {
    this.sourcePath = sourcePath;
    this.classPaths = classPaths;
    this.sourceOutput = sourceOutput;
    this.classOutput = classOutput;
    this.javaCompiler = javaCompiler;
    this.processors = new HashSet();
    this.config = config;
  }

  public void addAnnotationProcessor(Processor annotationProcessorType) {
    if (annotationProcessorType == null) {
      throw new NullPointerException("No null processor allowed");
    }
    processors.add(annotationProcessorType);
  }

  public void compile(String... compilationUnits) throws IOException, CompilationException {
    // Copy anything that is not a java file
    RAMFileSystem sourcePath1 = new RAMFileSystem();
    sourcePath.copy(new Filter() {
      public boolean acceptDir(Object dir, String name) throws IOException {
        return true;
      }

      public boolean acceptFile(Object file, String name) throws IOException {
        return !name.endsWith(".java");
      }
    }, sourcePath1);

    //
    VirtualFileManager fileManager = new VirtualFileManager(
      javaCompiler.getStandardFileManager(null, null, null),
      sourcePath1,
      classPaths,
      sourceOutput,
      classOutput
    );

    //
    Collection files = getFromSourcePath(sourcePath, compilationUnits);

    //
    compile(fileManager, files);
  }

  private 

Collection getFromSourcePath(ReadFileSystem

fs, String... compilationUnits) throws IOException { SimpleFileManager

manager = new SimpleFileManager

(StandardLocation.SOURCE_PATH, fs); ArrayList tmp = new ArrayList(); final ArrayList javaFiles = new ArrayList(); for (String compilationUnit : compilationUnits) { tmp.clear(); ArrayList names = Spliterator.split(compilationUnit.substring(1), '/', tmp); String name = tmp.get(tmp.size() - 1); if (!name.endsWith(".java")) { throw new IllegalArgumentException("Illegal compilation unit: " + compilationUnit); } P file = manager.getFileSystem().getPath(names); if (file == null) { throw new IllegalArgumentException("Could not find compilation unit: " + compilationUnit); } names.remove(names.size() - 1); String pkg = Tools.join('.', names); FileKey key = FileKey.newJavaName(pkg, name); javaFiles.add(manager.getReadable(key)); } return javaFiles; } public void compile() throws IOException, CompilationException { VirtualFileManager fileManager = new VirtualFileManager( javaCompiler.getStandardFileManager(null, null, null), sourcePath, classPaths, sourceOutput, classOutput ); compile(fileManager, getFromSourcePath(fileManager.sourcePath)); } private

Collection getFromSourcePath(final SimpleFileManager

fileManager) throws IOException { final ArrayList javaFiles = new ArrayList(); final StringBuilder buffer = new StringBuilder(); fileManager.getFileSystem().traverse(new Visitor.Default

() { @Override public void enterDir(Object dir, String name) throws IOException { if (name.length() > 0) { buffer.append(name).append('.'); } } public void file(P file, String name) throws IOException { if (name.endsWith(".java")) { FileKey key = FileKey.newJavaName(buffer.substring(0, buffer.length() - 1), name); JavaFileObject fileObject = fileManager.getReadable(key); javaFiles.add(fileObject); } } @Override public void leaveDir(Object dir, String name) throws IOException { if (name.length() > 0) { buffer.setLength(buffer.length() - name.length() - 1); } } }); return javaFiles; } private void compile( VirtualFileManager fileManager, Collection compilationUnits) throws IOException, CompilationException { if (compilationUnits.isEmpty()) { if (!config.getForce()) { return; } else { URI uri = URI.create("/Dumb.java"); compilationUnits = Collections.singleton(new SimpleJavaFileObject(uri, JavaFileObject.Kind.SOURCE) { @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return "public class Dumb {}"; } }); } } // final List errors = new ArrayList(); DiagnosticListener listener = new DiagnosticListener() { public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { int columnNumber = (int)diagnostic.getColumnNumber(); int lineNumber = (int)diagnostic.getLineNumber(); Location location = (columnNumber > 0 && lineNumber > 0) ? new Location(columnNumber, lineNumber) : null; // We pass the default locale instead of null as ECJ has issues with null String s = diagnostic.getMessage(Locale.getDefault()); // Message message = Message.parse(s); // Best effort to get a java.io.File JavaFileObject obj = diagnostic.getSource(); String source = null; File resolvedFile = null; if (obj != null) { URI uri = obj.toUri(); source = uri.getPath(); if (obj instanceof JavaFileObjectImpl) { JavaFileObjectImpl foo = (JavaFileObjectImpl)obj; try { resolvedFile = foo.getFile(); } catch (Exception ignore) { } } else { // We are likely in eclipse (with its JavaFileObject wrapper) and we should get the file from the URI if (uri.getScheme().equals("file")) { resolvedFile = new File(uri); } } } // errors.add(new CompilationError( message != null ? message.getCode() : null, message != null ? Arrays.asList(message.getArguments()): Collections.emptyList(), source, resolvedFile, location, s)); } } }; // List options = new ArrayList(); options.add("-g"); for (String optionName : config.getProcessorOptionNames()) { options.add("-A" + optionName + "=" + config.getProcessorOptionValue(optionName)); } // JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, listener, options, null, compilationUnits); task.setProcessors(processors); // We don't use the return value because sometime it says it is failed although // it is not, need to investigate this at some piont boolean ok = task.call(); // Clear caches fileManager.sourceOutput.clearCache(); fileManager.classOutput.clearCache(); fileManager.sourceOutput.clearCache(); if (fileManager.classPath != null) { fileManager.classPath.clearCache(); } // Clear processors as we should not reuse them processors.clear(); // if (!ok) { throw new CompilationException(errors); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy