/**
 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
 * your own risk. This code and its internal interfaces are subject to change or deletion without
 * notice.</b>
 */
@SuppressWarnings("deprecation")
public class AptJavaCompiler extends com.sun.tools.javac.main.JavaCompiler {
  /** The context key for the compiler. */
  protected static final Context.Key<AptJavaCompiler> compilerKey =
      new Context.Key<AptJavaCompiler>();

  /** Get the JavaCompiler instance for this context. */
  public static AptJavaCompiler instance(Context context) {
    AptJavaCompiler instance = context.get(compilerKey);
    if (instance == null) instance = new AptJavaCompiler(context);
    return instance;
  }

  java.util.Set<String> genSourceFileNames;
  java.util.Set<String> genClassFileNames;

  public java.util.Set<String> getSourceFileNames() {
    return genSourceFileNames;
  }

  /** List of names of generated class files. */
  public java.util.Set<String> getClassFileNames() {
    return genClassFileNames;
  }

  java.util.Set<java.io.File> aggregateGenFiles = java.util.Collections.emptySet();

  public java.util.Set<java.io.File> getAggregateGenFiles() {
    return aggregateGenFiles;
  }

  /** The bark to be used for error reporting. */
  Bark bark;

  /** The log to be used for error reporting. */
  Log log;

  /** The annotation framework */
  Apt apt;

  private static Context preRegister(Context context) {
    Bark.preRegister(context);

    if (context.get(JavaFileManager.class) == null) JavacFileManager.preRegister(context);

    return context;
  }

  /** Construct a new compiler from a shared context. */
  public AptJavaCompiler(Context context) {
    super(preRegister(context));

    context.put(compilerKey, this);
    apt = Apt.instance(context);

    ClassReader classReader = ClassReader.instance(context);
    classReader.preferSource = true;

    // TEMPORARY NOTE: bark==log, but while refactoring, we maintain their
    // original identities, to remember the original intent.
    log = Log.instance(context);
    bark = Bark.instance(context);

    Options options = Options.instance(context);
    classOutput = options.get("-retrofit") == null;
    nocompile = options.get("-nocompile") != null;
    print = options.get("-print") != null;
    classesAsDecls = options.get("-XclassesAsDecls") != null;

    genSourceFileNames = new java.util.LinkedHashSet<String>();
    genClassFileNames = new java.util.LinkedHashSet<String>();

    // this forces a copy of the line map to be kept in the tree,
    // for use by com.sun.mirror.util.SourcePosition.
    lineDebugInfo = true;
  }

  /* Switches:
   */

  /**
   * Emit class files. This switch is always set, except for the first phase of retrofitting, where
   * signatures are parsed.
   */
  public boolean classOutput;

  /** The internal printing annotation processor should be used. */
  public boolean print;

  /** Compilation should not be done after annotation processing. */
  public boolean nocompile;

  /** Are class files being treated as declarations */
  public boolean classesAsDecls;

  /**
   * Try to open input stream with given name. Report an error if this fails.
   *
   * @param filename The file name of the input stream to be opened.
   */
  // PROVIDED FOR EXTREME BACKWARDS COMPATIBILITY
  // There are some very obscure errors that can arise while translating
  // the contents of a file from bytes to characters. In Tiger, these
  // diagnostics were ignored. This method provides compatibility with
  // that behavior. It would be better to honor those diagnostics, in which
  // case, this method can be deleted.
  @Override
  public CharSequence readSource(JavaFileObject filename) {
    try {
      inputFiles.add(filename);
      boolean prev = bark.setDiagnosticsIgnored(true);
      try {
        return filename.getCharContent(false);
      } finally {
        bark.setDiagnosticsIgnored(prev);
      }
    } catch (IOException e) {
      bark.error(Position.NOPOS, "cant.read.file", filename);
      return null;
    }
  }

  /**
   * Parse contents of input stream.
   *
   * @param filename The name of the file from which input stream comes.
   * @param input The input stream to be parsed.
   */
  // PROVIDED FOR BACKWARDS COMPATIBILITY
  // In Tiger, diagnostics from the scanner and parser were ignored.
  // This method provides compatibility with that behavior.
  // It would be better to honor those diagnostics, in which
  // case, this method can be deleted.
  @Override
  protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) {
    boolean prev = bark.setDiagnosticsIgnored(true);
    try {
      return super.parse(filename, content);
    } finally {
      bark.setDiagnosticsIgnored(prev);
    }
  }

  @Override
  protected boolean keepComments() {
    return true; // make doc comments available to mirror API impl.
  }

  /** Track when the JavaCompiler has been used to compile something. */
  private boolean hasBeenUsed = false;

  /**
   * Main method: compile a list of files, return all compiled classes
   *
   * @param filenames The names of all files to be compiled.
   */
  public List<ClassSymbol> compile(
      List<String> filenames,
      Map<String, String> origOptions,
      ClassLoader aptCL,
      AnnotationProcessorFactory providedFactory,
      java.util.Set<Class<? extends AnnotationProcessorFactory>> productiveFactories,
      java.util.Set<java.io.File> aggregateGenFiles)
      throws Throwable {
    // as a JavaCompiler can only be used once, throw an exception if
    // it has been used before.
    assert !hasBeenUsed : "attempt to reuse JavaCompiler";
    hasBeenUsed = true;

    this.aggregateGenFiles = aggregateGenFiles;

    long msec = System.currentTimeMillis();

    ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>();
    try {
      JavacFileManager fm = (JavacFileManager) fileManager;
      // parse all files
      ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>();
      for (List<String> l = filenames; l.nonEmpty(); l = l.tail) {
        if (classesAsDecls) {
          if (!l.head.endsWith(".java")) { // process as class file
            ClassSymbol cs = reader.enterClass(names.fromString(l.head));
            try {
              cs.complete();
            } catch (Symbol.CompletionFailure cf) {
              bark.aptError("CantFindClass", l);
              continue;
            }

            classes.append(cs); // add to list of classes
            continue;
          }
        }
        JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next();
        trees.append(parse(fo));
      }

      // enter symbols for all files
      List<JCCompilationUnit> roots = trees.toList();

      if (errorCount() == 0) {
        boolean prev = bark.setDiagnosticsIgnored(true);
        try {
          enter.main(roots);
        } finally {
          bark.setDiagnosticsIgnored(prev);
        }
      }

      if (errorCount() == 0) {
        apt.main(roots, classes, origOptions, aptCL, providedFactory, productiveFactories);
        genSourceFileNames.addAll(apt.getSourceFileNames());
        genClassFileNames.addAll(apt.getClassFileNames());
      }

    } catch (Abort ex) {
    }

    if (verbose) log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec));

    chk.reportDeferredDiagnostics();

    printCount("error", errorCount());
    printCount("warn", warningCount());

    return classes.toList();
  }
}
Example #2
0
  public static void upgrade(File wrFile) throws Exception {
    System.out.println("Installing/upgrading Myna in '" + wrFile.toString() + "'...");
    wrFile.mkdirs();
    File web_inf = new File(wrFile.toURI().resolve("WEB-INF"));
    boolean isUpgrade = false;
    File backupDir = null;
    if (web_inf.exists()) {

      String dateString =
          new java.text.SimpleDateFormat("MM-dd-yyyy_HH.mm.ss.S").format(new Date());
      String backupBase = "WEB-INF/upgrade_backups/backup_" + dateString;
      backupDir = new File(wrFile.toURI().resolve(backupBase));
      backupDir.mkdirs();
      isUpgrade = true;
      System.out.println("Backups stored in " + backupDir);
      // backup entire /myna folder because we're wiping it out
      FileUtils.copyDirectory(
          new File(wrFile.toURI().resolve("myna")), new File(backupDir.toURI().resolve("myna")));
      FileUtils.deleteDirectory(new File(wrFile.toURI().resolve("myna")));
    }

    if (isJar) {
      String jarFilePath = classUrl.substring(classUrl.indexOf(":") + 1, classUrl.indexOf("!"));
      File jarFile = new File(new java.net.URL(jarFilePath).toURI());
      ZipFile zipFile = new ZipFile(jarFile);

      for (ZipEntry entry : java.util.Collections.list(zipFile.entries())) {;
        File outputFile =
            new File(wrFile.toURI().resolve(java.net.URLEncoder.encode(entry.getName(), "UTF-8")));
        File backupFile = null;
        if (isUpgrade) {
          backupFile =
              new File(
                  backupDir.toURI().resolve(java.net.URLEncoder.encode(entry.getName(), "UTF-8")));
        }
        if (entry.isDirectory()) {
          outputFile.mkdirs();
          if (isUpgrade) backupFile.mkdirs();
        } else {
          if (isUpgrade && outputFile.exists()) {

            java.io.InputStream sourceIS = zipFile.getInputStream(entry);
            java.io.InputStream targetIS = FileUtils.openInputStream(outputFile);
            boolean isSame = IOUtils.contentEquals(sourceIS, targetIS);
            sourceIS.close();
            targetIS.close();

            if (isSame
                || entry.toString().equals("index.html")
                || entry.toString().equals("application.sjs")
                || entry.toString().equals("WEB-INF/classes/general.properties")
                || entry.toString().startsWith("WEB-INF/myna/ds")) {
              continue;
            } else {
              System.out.println("...backing up " + entry);
              FileUtils.copyFile(outputFile, backupFile, true);
              // outputFile.copyTo(backupFile);
              // fusebox.upgradeLog("Backup: " + backupFile);
            }
          }
          java.io.InputStream is = zipFile.getInputStream(entry);
          java.io.OutputStream os = FileUtils.openOutputStream(outputFile);
          IOUtils.copyLarge(is, os);
          is.close();
          os.close();
        }
      }
      zipFile.close();
      // FileUtils.deleteDirectory()

      System.out.println("Done unpacking.");
    }
  }