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

io.vlingo.common.compiler.DynaCompiler Maven / Gradle / Ivy

There is a newer version: 1.7.5
Show newest version
// Copyright © 2012-2020 VLINGO LABS. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.

package io.vlingo.common.compiler;

import static io.vlingo.common.compiler.DynaFile.RootOfMainClasses;
import static io.vlingo.common.compiler.DynaFile.RootOfTestClasses;
import static io.vlingo.common.compiler.DynaFile.persistDynaClass;
import static io.vlingo.common.compiler.DynaFile.toFullPath;
import static io.vlingo.common.compiler.DynaFile.toPackagePath;

import java.io.File;
import java.util.Arrays;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class DynaCompiler {
  public static class Input {
    public final DynaClassLoader classLoader;
    public final String fullyQualifiedClassname;
    public final boolean persist;
    public final Class protocol;
    public final DynaType type;
    public final String source;
    public final File sourceFile;
    
    public  Input(
            final Class protocol,
            final String fullyQualifiedClassname,
            final String source,
            final File sourceFile,
            final DynaClassLoader classLoader,
            final DynaType type,
            final boolean persist) {
      this.protocol = protocol;
      this.fullyQualifiedClassname = fullyQualifiedClassname;
      this.source = source;
      this.sourceFile = sourceFile;
      this.classLoader = classLoader;
      this.type = type;
      this.persist = persist;
    }
  }
  
  private final JavaCompiler compiler;
  
  public DynaCompiler() {
    this.compiler = ToolProvider.getSystemJavaCompiler();
  }

  public  Class compile(final Input input) throws Exception {
    final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    final DiagnosticListener listener = new DynaDiagnosticListener<>();
    
    try (final DynaFileManager dynaFileManager = new DynaFileManager(input.protocol, fileManager, input.classLoader)) {
      final Iterable sources = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(input.sourceFile));
      final CompilationTask task = compiler.getTask(null, dynaFileManager, listener, null, null, sources);
      if (task.call()) {
        persist(input, dynaFileManager.byteCode);
        return input.classLoader.addDynaClass(input.fullyQualifiedClassname, dynaFileManager.byteCode);
      }
    } catch (Exception e) {
      System.out.println("Dynamically generated class source for " + input.fullyQualifiedClassname + " did not compile because: " + e.getMessage());
      e.printStackTrace();
      // fall through
    }
    
    throw new IllegalArgumentException("Dynamically generated class source did not compile: " + input.fullyQualifiedClassname);
  }
  
  private File persist(final Input input, final ByteCode byteCode) throws Exception {
    final String relativePathToClass = toFullPath(input.fullyQualifiedClassname);
    final String pathToCompiledClass = toPackagePath(input.fullyQualifiedClassname);
    final String rootOfGenerated = input.type == DynaType.Main ? RootOfMainClasses : RootOfTestClasses;
    new File(rootOfGenerated + pathToCompiledClass).mkdirs();
    final String pathToClass = rootOfGenerated + relativePathToClass + ".class";
    
    return input.persist ? persistDynaClass(pathToClass, byteCode.bytes()) : new File(relativePathToClass);
  }

  private static class DynaDiagnosticListener implements DiagnosticListener {
    @Override
    public void report(final Diagnostic diagnostic) {
      if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
        // TODO: log
        System.out.println("vlingo/common: DynaCompiler ERROR: " + diagnostic);
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy