test/tools/javac/lambdaShapes/org/openjdk/tests/separate/Compiler.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 2174
62a67e0875ff
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

     1 /*
     2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package org.openjdk.tests.separate;
    28 import java.util.*;
    29 import java.util.concurrent.atomic.AtomicInteger;
    30 import java.util.concurrent.ConcurrentHashMap;
    31 import java.io.*;
    32 import java.net.URI;
    33 import javax.tools.*;
    35 import com.sun.source.util.JavacTask;
    37 import static org.openjdk.tests.separate.SourceModel.Type;
    38 import static org.openjdk.tests.separate.SourceModel.Class;
    39 import static org.openjdk.tests.separate.SourceModel.Extends;
    40 import static org.openjdk.tests.separate.SourceModel.SourceProcessor;
    42 public class Compiler {
    44     public enum Flags {
    45         VERBOSE, // Prints out files as they are compiled
    46         USECACHE // Keeps results around for reuse.  Only use this is
    47                  // you're sure that each compilation name maps to the
    48                  // same source code
    49     }
    51     private static final AtomicInteger counter = new AtomicInteger();
    52     private static final String targetDir = "gen-separate";
    53     private static final File root = new File(targetDir);
    54     private static ConcurrentHashMap<String,File> cache =
    55             new ConcurrentHashMap<>();
    57     Set<Flags> flags;
    59     private JavaCompiler systemJavaCompiler;
    60     private StandardJavaFileManager fm;
    61     private List<File> tempDirs;
    62     private List<ClassFilePreprocessor> postprocessors;
    64     private static class SourceFile extends SimpleJavaFileObject {
    65         private final String content;
    67         public SourceFile(String name, String content) {
    68             super(URI.create("myfo:/" + name + ".java"), Kind.SOURCE);
    69             this.content = content;
    70         }
    72         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
    73             return toString();
    74         }
    76         public String toString() { return this.content; }
    77     }
    79     public Compiler(Flags ... flags) {
    80         setFlags(flags);
    81         this.tempDirs = new ArrayList<>();
    82         this.postprocessors = new ArrayList<>();
    83         this.systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
    84         this.fm = systemJavaCompiler.getStandardFileManager(null, null, null);
    85     }
    87     public void setFlags(Flags ... flags) {
    88         this.flags = new HashSet<>(Arrays.asList(flags));
    89     }
    91     public void addPostprocessor(ClassFilePreprocessor cfp) {
    92         this.postprocessors.add(cfp);
    93     }
    95     /**
    96      * Compile hierarchies starting with each of the 'types' and return
    97      * a ClassLoader that can be used to load the compiled classes.
    98      */
    99     public ClassLoader compile(Type ... types) {
   100         ClassFilePreprocessor[] cfps = this.postprocessors.toArray(
   101             new ClassFilePreprocessor[0]);
   103         DirectedClassLoader dcl = new DirectedClassLoader(cfps);
   105         for (Type t : types) {
   106             for (Map.Entry<String,File> each : compileHierarchy(t).entrySet()) {
   107                 dcl.setLocationFor(each.getKey(), each.getValue());
   108             }
   109         }
   110         return dcl;
   111     }
   113     /**
   114      * Compiles and loads a hierarchy, starting at 'type'
   115      */
   116     public java.lang.Class<?> compileAndLoad(Type type)
   117             throws ClassNotFoundException {
   119         ClassLoader loader = compile(type);
   120         return java.lang.Class.forName(type.getName(), false, loader);
   121     }
   123     /**
   124      * Compiles a hierarchy, starting at 'type' and return a mapping of the
   125      * name to the location where the classfile for that type resides.
   126      */
   127     private Map<String,File> compileHierarchy(Type type) {
   128         HashMap<String,File> outputDirs = new HashMap<>();
   130         File outDir = compileOne(type);
   131         outputDirs.put(type.getName(), outDir);
   133         Class superClass = type.getSuperclass();
   134         if (superClass != null)
   135             outputDirs.putAll(compileHierarchy(superClass));
   136         for (Extends ext : type.getSupertypes())
   137             outputDirs.putAll(compileHierarchy(ext.getType()));
   139         return outputDirs;
   140     }
   142     private File compileOne(Type type) {
   143         if (this.flags.contains(Flags.USECACHE)) {
   144             File dir = cache.get(type.getName());
   145             if (dir != null) {
   146                 return dir;
   147             }
   148         }
   149         List<JavaFileObject> files = new ArrayList<>();
   150         SourceProcessor accum =
   151             (name, src) -> { files.add(new SourceFile(name, src)); };
   153         Collection<Type> deps = type.typeDependencies(type.isFullCompilation());
   154         for (Type dep : deps) {
   155             if (type.isFullCompilation())
   156                 dep.generate(accum);
   157             else
   158                 dep.generateAsDependency(accum, type.methodDependencies());
   159         }
   161         type.generate(accum);
   163         JavacTask ct = (JavacTask)this.systemJavaCompiler.getTask(
   164             null, this.fm, null, null, null, files);
   165         File destDir = null;
   166         do {
   167             int value = counter.incrementAndGet();
   168             destDir = new File(root, Integer.toString(value));
   169         } while (destDir.exists());
   171         if (this.flags.contains(Flags.VERBOSE)) {
   172             System.out.println("Compilation unit for " + type.getName() +
   173                 " : compiled into " + destDir);
   174             for (JavaFileObject jfo : files) {
   175                 System.out.println(jfo.toString());
   176             }
   177         }
   179         try {
   180             destDir.mkdirs();
   181             this.fm.setLocation(
   182                 StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir));
   183         } catch (IOException e) {
   184             throw new RuntimeException(
   185                 "IOException encountered during compilation", e);
   186         }
   187         Boolean result = ct.call();
   188         if (result == Boolean.FALSE) {
   189             throw new RuntimeException(
   190                 "Compilation failure in " + type.getName() + " unit");
   191         }
   192         if (this.flags.contains(Flags.USECACHE)) {
   193             File existing = cache.putIfAbsent(type.getName(), destDir);
   194             if (existing != null) {
   195                 deleteDir(destDir);
   196                 return existing;
   197             }
   198         } else {
   199         this.tempDirs.add(destDir);
   200         }
   201         return destDir;
   202     }
   204     private static void deleteDir(File dir) {
   205         for (File f : dir.listFiles()) {
   206             f.delete();
   207         };
   208         dir.delete();
   209     }
   211     public void cleanup() {
   212         if (!this.flags.contains(Flags.USECACHE)) {
   213             for (File d : tempDirs) {
   214                 deleteDir(d);
   215             };
   216             tempDirs = new ArrayList<>();
   217         }
   218     }
   220     // Removes all of the elements in the cache and deletes the associated
   221     // output directories.  This may not actually empty the cache if there
   222     // are concurrent users of it.
   223     public static void purgeCache() {
   224         for (Map.Entry<String,File> entry : cache.entrySet()) {
   225             cache.remove(entry.getKey());
   226             deleteDir(entry.getValue());
   227         }
   228     }
   229 }

mercurial