# HG changeset patch # User lana # Date 1409262829 25200 # Node ID 6ce251a8713750aa833e7864b5fdf841e3a599f7 # Parent cfcea23d2d19eb583af316b8f1249197d39c9b4e# Parent 0430c63da650708196e4f524b84c75ff3c0a86e0 Merge diff -r cfcea23d2d19 -r 6ce251a87137 langtools/.hgtags diff -r cfcea23d2d19 -r 6ce251a87137 langtools/make/build.properties --- a/langtools/make/build.properties Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/make/build.properties Thu Aug 28 14:53:49 2014 -0700 @@ -68,7 +68,7 @@ # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all -Werror +javac.lint.opts = -Xlint:all,-deprecation -Werror # options for the task for javac #javadoc.jls3.url=http://java.sun.com/docs/books/jls/ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/make/intellij/langtools.iml --- a/langtools/make/intellij/langtools.iml Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/make/intellij/langtools.iml Thu Aug 28 14:53:49 2014 -0700 @@ -6,10 +6,14 @@ - - + + + + + + - + diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Aug 28 14:53:49 2014 -0700 @@ -2196,16 +2196,6 @@ } @Override - public Type visitWildcardType(WildcardType t, Boolean recurse) { - final List annos = t.getAnnotationMirrors(); - Type erased = erasure(wildUpperBound(t), recurse); - if (!annos.isEmpty()) { - erased = erased.annotatedType(annos); - } - return erased; - } - - @Override public Type visitClassType(ClassType t, Boolean recurse) { Type erased = t.tsym.erasure(Types.this); List annos = t.getAnnotationMirrors(); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Aug 28 14:53:49 2014 -0700 @@ -919,14 +919,14 @@ // Empty bodies are only allowed for // abstract, native, or interface methods, or for methods // in a retrofit signature class. - if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && - !relax) - log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); if (tree.defaultValue != null) { if ((owner.flags() & ANNOTATION) == 0) log.error(tree.pos(), "default.allowed.in.intf.annotation.member"); } + if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && + !relax) + log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); } else if ((tree.sym.flags() & ABSTRACT) != 0 && !isDefaultMethod) { if ((owner.flags() & INTERFACE) != 0) { log.error(tree.body.pos(), "intf.meth.cant.have.body"); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,15 +31,17 @@ import java.util.Map; import java.util.Set; +import com.sun.tools.javac.util.Assert; + /** * The build state class captures the source code and generated artifacts * from a build. There are usually two build states, the previous one (prev), * loaded from the javac_state file, and the current one (now). * - *

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.

+ *

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. */ public class BuildState { private Map modules = new HashMap<>(); @@ -75,7 +77,7 @@ */ Module findModuleFromPackageName(String pkg) { int cp = pkg.indexOf(':'); - assert(cp != -1); + Assert.check(cp != -1); String mod = pkg.substring(0, cp); return lookupModule(mod); } @@ -94,7 +96,7 @@ for (Map.Entry j : i.packages().entrySet()) { Package p = packages.get(j.getKey()); // Check that no two different packages are stored under same name. - assert(p == null || p == j.getValue()); + Assert.check(p == null || p == j.getValue()); if (p == null) { p = j.getValue(); packages.put(j.getKey(),j.getValue()); @@ -102,7 +104,7 @@ for (Map.Entry k : p.sources().entrySet()) { Source s = sources.get(k.getKey()); // Check that no two different sources are stored under same name. - assert(s == null || s == k.getValue()); + Assert.check(s == null || s == k.getValue()); if (s == null) { s = k.getValue(); sources.put(k.getKey(), k.getValue()); @@ -111,7 +113,7 @@ for (Map.Entry g : p.artifacts().entrySet()) { File f = artifacts.get(g.getKey()); // Check that no two artifacts are stored under the same file. - assert(f == null || f == g.getValue()); + Assert.check(f == null || f == g.getValue()); if (f == null) { f = g.getValue(); artifacts.put(g.getKey(), g.getValue()); @@ -134,13 +136,13 @@ for (Map.Entry j : i.packages().entrySet()) { Package p = packages.get(j.getKey()); // Check that no two different packages are stored under same name. - assert(p == null || p == j.getValue()); + Assert.check(p == null || p == j.getValue()); p = j.getValue(); packages.put(j.getKey(),j.getValue()); for (Map.Entry g : p.artifacts().entrySet()) { File f = artifacts.get(g.getKey()); // Check that no two artifacts are stored under the same file. - assert(f == null || f == g.getValue()); + Assert.check(f == null || f == g.getValue()); artifacts.put(g.getKey(), g.getValue()); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Thu Aug 28 14:53:49 2014 -0700 @@ -36,19 +36,18 @@ import java.util.Properties; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The clean properties transform should not be necessary. * Eventually we will cleanup the property file sources in the OpenJDK instead. * - *

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.

+ *

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. */ -public class CleanProperties implements Transformer -{ +public class CleanProperties implements Transformer { public void setExtra(String e) { // Any extra information is ignored for clean properties. } @@ -57,7 +56,7 @@ // Any extra information is ignored for clean properties. } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, @@ -70,8 +69,7 @@ boolean incremental, int numCores, PrintStream out, - PrintStream err) - { + PrintStream err) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = pkgName.replace('.',File.separatorChar); @@ -87,9 +85,12 @@ return rc; } - boolean clean(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel, - Map> packageArtifacts) - { + boolean clean(String pkgName, + String pkgNameF, + File src, + File destRoot, + int debugLevel, + Map> packageArtifacts) { // Load the properties file. Properties p = new Properties(); try { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,10 @@ * A compile chunk is a list of sources/packages to be compiled. Possibly a subset of * the total number of sources/packages to be compiled for this sjavac invocation. * - *

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.

+ *

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. */ public class CompileChunk implements Comparable { public int numPackages; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Thu Aug 28 14:53:49 2014 -0700 @@ -30,13 +30,12 @@ import java.net.URI; import java.util.Arrays; import java.util.Collections; -import java.util.Random; import java.util.Set; import java.util.Map; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.server.CompilationResult; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.SysInfo; /** @@ -67,7 +66,7 @@ args = a; } - public boolean transform(final JavacService javacService, + public boolean transform(final Sjavac sjavac, Map> pkgSrcs, final Set visibleSources, final Map> visibleClasses, @@ -86,18 +85,12 @@ boolean concurrentCompiles = true; // Fetch the id. - String idOpt = Util.extractStringOption("id", args.getServerConf()); - if (idOpt == null || idOpt.equals("")) { - // No explicit id set. Create a random id so that the requests can be - // grouped properly in the server. - idOpt = "id"+(((new Random()).nextLong())&Long.MAX_VALUE); - } - final String id = idOpt; + final String id = Util.extractStringOption("id", sjavac.serverSettings()); // Only keep portfile and sjavac settings.. - String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), args.getServerConf()); + String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), sjavac.serverSettings()); // Get maximum heap size from the server! - SysInfo sysinfo = javacService.getSysInfo(); + SysInfo sysinfo = sjavac.getSysInfo(); if (sysinfo.numCores == -1) { Log.error("Could not query server for sysinfo!"); return false; @@ -222,7 +215,7 @@ requests[i] = new Thread() { @Override public void run() { - rn[ii] = javacService.compile("n/a", + rn[ii] = sjavac.compile("n/a", id + "-" + ii, args.prepJavacArgs(), Collections.emptyList(), @@ -253,6 +246,8 @@ requests[ii].run(); // If there was an error, then stop early when running single threaded. if (rn[i].returnCode != 0) { + Log.info(rn[i].stdout); + Log.error(rn[i].stderr); return false; } } @@ -269,6 +264,8 @@ for (int i=0; i 0) { if (rn[i].returnCode != 0) { + Log.info(rn[i].stdout); + Log.error(rn[i].stderr); rc = false; } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Thu Aug 28 14:53:49 2014 -0700 @@ -38,20 +38,19 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * Compile properties transform a properties file into a Java source file. * Java has built in support for reading properties from either a text file * in the source or a compiled java source file. * - *

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.

+ *

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. */ -public class CompileProperties implements Transformer -{ +public class CompileProperties implements Transformer { // Any extra information passed from the command line, for example if: // -tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle // then extra will be "sun.util.resources.LocaleNamesBundle" @@ -64,7 +63,7 @@ public void setExtra(Options a) { } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Thu Aug 28 14:53:49 2014 -0700 @@ -32,16 +32,16 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The copy file transform simply copies a matching file from -src to -d . * Such files are typically images, xml documents and other data files. * - *

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.

+ *

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. */ public class CopyFile implements Transformer { @@ -51,7 +51,7 @@ public void setExtra(Options a) { } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,7 +26,6 @@ package com.sun.tools.sjavac; import java.io.*; -import java.nio.file.Path; import java.util.Collections; import java.util.Date; import java.util.Set; @@ -39,20 +38,18 @@ import java.util.*; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.options.SourceLocation; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The javac state class maintains the previous (prev) and the current (now) * build states and everything else that goes into the javac_state file. * - *

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.

+ *

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. */ -public class JavacState -{ +public class JavacState { // The arguments to the compile. If not identical, then it cannot // be an incremental build! String theArgs; @@ -60,7 +57,6 @@ int numCores; // The bin_dir/javac_state - private String javacStateFilename; private File javacState; // The previous build state is loaded from javac_state @@ -99,7 +95,7 @@ private Set recompiledPackages; // The output directories filled with tasty artifacts. - private File binDir, gensrcDir, headerDir; + private File binDir, gensrcDir, headerDir, stateDir; // The current status of the file system. private Set binArtifacts; @@ -128,7 +124,11 @@ // Where to send stdout and stderr. private PrintStream out, err; - JavacState(Options options, boolean removeJavacState, PrintStream o, PrintStream e) { + // Command line options. + private Options options; + + JavacState(Options op, boolean removeJavacState, PrintStream o, PrintStream e) { + options = op; out = o; err = e; numCores = options.getNumCores(); @@ -136,8 +136,8 @@ binDir = Util.pathToFile(options.getDestDir()); gensrcDir = Util.pathToFile(options.getGenSrcDir()); headerDir = Util.pathToFile(options.getHeaderDir()); - javacStateFilename = binDir.getPath()+File.separator+"javac_state"; - javacState = new File(javacStateFilename); + stateDir = Util.pathToFile(options.getStateDir()); + javacState = new File(stateDir, "javac_state"); if (removeJavacState && javacState.exists()) { javacState.delete(); } @@ -148,7 +148,7 @@ // We do not want to risk building a broken incremental build. // BUT since the makefiles still copy things straight into the bin_dir et al, // we avoid deleting files here, if the option --permit-unidentified-classes was supplied. - if (!options.isUnidentifiedArtifactPermitted()) { + if (!options.areUnidentifiedArtifactsPermitted()) { deleteContents(binDir); deleteContents(gensrcDir); deleteContents(headerDir); @@ -268,7 +268,7 @@ */ public void save() throws IOException { if (!needsSaving) return; - try (FileWriter out = new FileWriter(javacStateFilename)) { + try (FileWriter out = new FileWriter(javacState)) { StringBuilder b = new StringBuilder(); long millisNow = System.currentTimeMillis(); Date d = new Date(millisNow); @@ -311,7 +311,7 @@ boolean newCommandLine = false; boolean syntaxError = false; - try (BufferedReader in = new BufferedReader(new FileReader(db.javacStateFilename))) { + try (BufferedReader in = new BufferedReader(new FileReader(db.javacState))) { for (;;) { String l = in.readLine(); if (l==null) break; @@ -512,7 +512,8 @@ allKnownArtifacts.add(javacState); for (File f : binArtifacts) { - if (!allKnownArtifacts.contains(f)) { + if (!allKnownArtifacts.contains(f) && + !options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) { Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state."); f.delete(); } @@ -605,13 +606,16 @@ /** * Recursively delete a directory and all its contents. */ - private static void deleteContents(File dir) { + private void deleteContents(File dir) { if (dir != null && dir.exists()) { for (File f : dir.listFiles()) { if (f.isDirectory()) { deleteContents(f); } - f.delete(); + if (!options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) { + Log.debug("Removing "+f.getAbsolutePath()); + f.delete(); + } } } } @@ -648,7 +652,7 @@ /** * Compile all the java sources. Return true, if it needs to be called again! */ - public boolean performJavaCompilations(JavacService javacService, + public boolean performJavaCompilations(Sjavac sjavac, Options args, Set recentlyCompiled, boolean[] rcValue) { @@ -656,7 +660,7 @@ suffixRules.put(".java", compileJavaPackages); compileJavaPackages.setExtra(args); - rcValue[0] = perform(javacService, binDir, suffixRules); + rcValue[0] = perform(sjavac, binDir, suffixRules); recentlyCompiled.addAll(taintedPackages()); clearTaintedPackages(); boolean again = !packagesWithChangedPublicApis.isEmpty(); @@ -686,10 +690,9 @@ * For all packages, find all sources belonging to the package, group the sources * based on their transformers and apply the transformers on each source code group. */ - private boolean perform(JavacService javacService, + private boolean perform(Sjavac sjavac, File outputDir, - Map suffixRules) - { + Map suffixRules) { boolean rc = true; // Group sources based on transforms. A source file can only belong to a single transform. Map>> groupedSources = new HashMap<>(); @@ -713,7 +716,7 @@ Map packagePublicApis = Collections.synchronizedMap(new HashMap()); - boolean r = t.transform(javacService, + boolean r = t.transform(sjavac, srcs, visibleSrcs, visibleClasses, @@ -791,9 +794,7 @@ * Used to detect bugs where the makefile and sjavac have different opinions on which files * should be compiled. */ - public void compareWithMakefileList(File makefileSourceList) - throws ProblemException - { + public void compareWithMakefileList(File makefileSourceList) throws ProblemException { // If we are building on win32 using for example cygwin the paths in the makefile source list // might be /cygdrive/c/.... which does not match c:\.... // We need to adjust our calculated sources to be identical, if necessary. diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Thu Aug 28 14:53:49 2014 -0700 @@ -31,10 +31,10 @@ * Utility class only for sjavac logging. * The log level can be set using for example --log=DEBUG on the sjavac command line. * - *

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.

+ *

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. */ public class Log { private static PrintStream out, err; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java Thu Aug 28 14:53:49 2014 -0700 @@ -31,19 +31,21 @@ import java.nio.file.Path; import java.nio.file.Files; +import com.sun.tools.sjavac.client.SjavacClient; +import com.sun.tools.sjavac.comp.SjavacImpl; +import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.SourceLocation; -import com.sun.tools.sjavac.server.JavacService; -import com.sun.tools.sjavac.server.JavacServer; -import com.sun.tools.sjavac.server.JavacServiceClient; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SjavacServer; /** * The main class of the smart javac wrapper tool. * - *

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.

+ *

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. */ public class Main { @@ -163,13 +165,19 @@ return; } // Spawn a background server. - int rc = JavacServer.startServer(args[0], System.err); - System.exit(rc); + try { + SjavacServer server = new SjavacServer(args[0], System.err); + int rc = server.startServer(); + System.exit(rc); + } catch (IOException ioex) { + Log.error("IOException caught: " + ioex); + System.exit(-1); + } } Main main = new Main(); int rc = main.go(args, System.out, System.err); // Remove the portfile, but only if this background=false was used. - JavacServer.cleanup(args); + SjavacServer.cleanup(args); System.exit(rc); } @@ -205,6 +213,9 @@ if (!createIfMissing(options.getDestDir())) return -1; + if (!createIfMissing(options.getStateDir())) + return -1; + Path gensrc = options.getGenSrcDir(); if (gensrc != null && !createIfMissing(gensrc)) return -1; @@ -302,7 +313,7 @@ // For examples, files that have been manually copied into these dirs. // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp // in javac_state) have already been removed when the javac_state was loaded. - if (!options.isUnidentifiedArtifactPermitted()) { + if (!options.areUnidentifiedArtifactsPermitted()) { javac_state.removeUnidentifiedArtifacts(); } // Go through all sources and taint all packages that miss artifacts. @@ -338,15 +349,22 @@ // Collect the name of all compiled packages. Set recently_compiled = new HashSet<>(); boolean[] rc = new boolean[1]; + Sjavac sjavac; + boolean background = Util.extractBooleanOption("background", options.getServerConf(), true); do { // Clean out artifacts in tainted packages. javac_state.deleteClassArtifactsInTaintedPackages(); - // Create a JavacService to delegate the actual compilation to. - // Currently sjavac always connects to a server through a socket - // regardless if sjavac runs as a background service or not. - // This will most likely change in the future. - JavacService javacService = new JavacServiceClient(options.getServerConf()); - again = javac_state.performJavaCompilations(javacService, options, recently_compiled, rc); + // Create an sjavac implementation to be used for compilation + if (background) { + sjavac = new SjavacClient(options); + } else { + int poolsize = Util.extractIntOption("poolsize", options.getServerConf()); + if (poolsize <= 0) + poolsize = Runtime.getRuntime().availableProcessors(); + sjavac = new PooledSjavac(new SjavacImpl(), poolsize); + } + + again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc); if (!rc[0]) break; } while (again); // Only update the state if the compile went well. @@ -357,6 +375,8 @@ // Remove artifacts that were generated during the last compile, but not this one. javac_state.removeSuperfluousArtifacts(recently_compiled); } + if (!background) + sjavac.shutdown(); return rc[0] ? 0 : -1; } catch (ProblemException e) { Log.error(e.getMessage()); @@ -375,8 +395,6 @@ err = "Please specify output directory."; } else if (options.isJavaFilesAmongJavacArgs()) { err = "Sjavac does not handle explicit compilation of single .java files."; - } else if (options.isAtFilePresent()) { - err = "Sjavac does not handle @-files."; } else if (options.getServerConf() == null) { err = "No server configuration provided."; } else if (!options.getImplicitPolicy().equals("none")) { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,10 @@ * The module is the root of a set of packages/sources/artifacts. * At the moment there is only one module in use, the empty/no-name/default module. * - *

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.

+ *

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. */ public class Module implements Comparable { private String name; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.sun.tools.javac.util.Assert; /** * The Package class maintains meta information about a package. @@ -54,10 +55,10 @@ * the visible recompilation of the dependent packages indicates how much circular * dependencies your code has. * - *

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.

+ *

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. */ public class Package implements Comparable { // The module this package belongs to. (There is a legacy module with an empty string name, @@ -83,9 +84,9 @@ public Package(Module m, String n) { int c = n.indexOf(":"); - assert(c != -1); + Assert.check(c != -1); String mn = n.substring(0,c); - assert(m.name().equals(m.name())); + Assert.check(m.name().equals(m.name())); name = n; dirname = n.replace('.', File.separatorChar); if (m.name().length() > 0) { @@ -256,7 +257,7 @@ } public void setArtifacts(Set as) { - assert(!artifacts.isEmpty()); + Assert.check(!artifacts.isEmpty()); artifacts = new HashMap<>(); addArtifacts(as); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,10 @@ /** * Used to signal serious problems when running sjavac. * - *

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.

+ *

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. */ public class ProblemException extends Exception { static final long serialVersionUID = -3387516993124229949L; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Thu Aug 28 14:53:49 2014 -0700 @@ -37,10 +37,10 @@ * The class also knows how to find source files (scanRoot) given include/exclude * patterns and a root. * - *

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.

+ *

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. */ public class Source implements Comparable { // The package the source belongs to. diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Thu Aug 28 14:53:49 2014 -0700 @@ -31,7 +31,7 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The transform interface is used to transform content inside a package, from one form to another. @@ -39,13 +39,12 @@ * but can also be an unpredictable number of generated source files (eg idl2java) * or a single predictable output file (eg when copying,cleaning or compiling a properties file). * - *

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.

+ *

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. */ -public interface Transformer -{ +public interface Transformer { /** * The transform method takes a set of package names, mapped to their source files and to the * pubapis of the packages. @@ -83,7 +82,7 @@ * If num_cores is set to a non-zero value. The transform should attempt to use no more than these * number of threads for heavy work. */ - boolean transform(JavacService javacService, + boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSources, Map> visibleClasses, diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,8 +26,6 @@ package com.sun.tools.sjavac; import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.nio.file.Path; import java.util.Arrays; import java.util.HashSet; @@ -37,10 +35,10 @@ /** * Utilities. * - *

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.

+ *

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. */ public class Util { @@ -64,7 +62,8 @@ public static String justPackageName(String pkgName) { int c = pkgName.indexOf(":"); - assert(c != -1); + if (c == -1) + throw new IllegalArgumentException("Expected ':' in package name (" + pkgName + ")"); return pkgName.substring(c+1); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.sjavac.client; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.util.List; +import java.util.Set; + +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.ProblemException; +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.PortFile; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SjavacServer; +import com.sun.tools.sjavac.server.SysInfo; +import com.sun.tools.sjavac.options.Options; + +/** + * Sjavac implementation that delegates requests to a SjavacServer. + * + *

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. + */ +public class SjavacClient implements Sjavac { + + // The id can perhaps be used in the future by the javac server to reuse the + // JavaCompiler instance for several compiles using the same id. + private final String id; + private final String portfileName; + private final String logfile; + private final String stdouterrfile; + private final boolean background; + + // Default keepalive for server is 120 seconds. + // I.e. it will accept 120 seconds of inactivity before quitting. + private final int keepalive; + private final int poolsize; + + // The sjavac option specifies how the server part of sjavac is spawned. + // If you have the experimental sjavac in your path, you are done. If not, you have + // to point to a com.sun.tools.sjavac.Main that supports --startserver + // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main + private final String sjavacForkCmd; + + // Wait 2 seconds for response, before giving up on javac server. + static int CONNECTION_TIMEOUT = 2000; + static int MAX_CONNECT_ATTEMPTS = 3; + static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; + + // Store the server conf settings here. + private final String settings; + + public SjavacClient(Options options) { + String tmpServerConf = options.getServerConf(); + String serverConf = (tmpServerConf!=null)? tmpServerConf : ""; + String tmpId = Util.extractStringOption("id", serverConf); + id = (tmpId!=null) ? tmpId : "id"+(((new java.util.Random()).nextLong())&Long.MAX_VALUE); + String p = Util.extractStringOption("portfile", serverConf); + portfileName = (p!=null) ? p : options.getStateDir().toFile().getAbsolutePath()+File.separatorChar+"javac_server"; + logfile = Util.extractStringOption("logfile", serverConf, portfileName + ".javaclog"); + stdouterrfile = Util.extractStringOption("stdouterrfile", serverConf, portfileName + ".stdouterr"); + background = Util.extractBooleanOption("background", serverConf, true); + sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac"); + int poolsize = Util.extractIntOption("poolsize", serverConf); + keepalive = Util.extractIntOption("keepalive", serverConf, 120); + + this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors(); + settings = (serverConf.equals("")) ? "id="+id+",portfile="+portfileName : serverConf; + } + + /** + * Hand out the server settings. + * @return The server settings, possibly a default value. + */ + public String serverSettings() { + return settings; + } + + /** + * Make a request to the server only to get the maximum possible heap size to use for compilations. + * + * @param port_file The port file used to synchronize creation of this server. + * @param id The identify of the compilation. + * @param out Standard out information. + * @param err Standard err information. + * @return The maximum heap size in bytes. + */ + @Override + public SysInfo getSysInfo() { + try (Socket socket = tryConnect()) { + // The ObjectInputStream constructor will block until the + // corresponding ObjectOutputStream has written and flushed the + // header, so it is important that the ObjectOutputStreams on server + // and client are opened before the ObjectInputStreams. + ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + oos.writeObject(id); + oos.writeObject(SjavacServer.CMD_SYS_INFO); + oos.flush(); + return (SysInfo) ois.readObject(); + } catch (IOException | ClassNotFoundException ex) { + Log.error("[CLIENT] Exception caught: " + ex); + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + } + return null; + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + CompilationResult result; + try (Socket socket = tryConnect()) { + // The ObjectInputStream constructor will block until the + // corresponding ObjectOutputStream has written and flushed the + // header, so it is important that the ObjectOutputStreams on server + // and client are opened before the ObjectInputStreams. + ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + oos.writeObject(id); + oos.writeObject(SjavacServer.CMD_COMPILE); + oos.writeObject(protocolId); + oos.writeObject(invocationId); + oos.writeObject(args); + oos.writeObject(explicitSources); + oos.writeObject(sourcesToCompile); + oos.writeObject(visibleSources); + oos.flush(); + result = (CompilationResult) ois.readObject(); + } catch (IOException | ClassNotFoundException ex) { + Log.error("Exception caught: " + ex); + result = new CompilationResult(CompilationResult.ERROR_FATAL); + result.stderr = ex.getMessage(); + } + return result; + } + + private Socket tryConnect() throws IOException { + + PortFile portFile; + try { + // This should be taken care of at a higher level (JDK-8048451) + portFile = SjavacServer.getPortFile(portfileName); + } catch (FileNotFoundException e) { + // Reached for instance if directory of port file does not exist + Log.error("Port file inaccessable: " + e); + throw new RuntimeException(e); + } + for (int i = 0; i < MAX_CONNECT_ATTEMPTS; i++) { + Log.info(String.format("Trying to connect (attempt %d of %d)", + i+1, MAX_CONNECT_ATTEMPTS)); + try { + if (!makeSureServerIsRunning(portFile)) + continue; + Socket socket = new Socket(); + InetAddress localhost = InetAddress.getByName(null); + socket.connect(new InetSocketAddress(localhost, portFile.getPort()), + CONNECTION_TIMEOUT); + return socket; + } catch (ProblemException | IOException ex) { + Log.error("Caught exception during tryConnect: " + ex); + } + + try { + Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + throw new IOException("Could not connect to server"); + } + + private boolean makeSureServerIsRunning(PortFile portFile) + throws IOException, ProblemException, FileNotFoundException { + + synchronized (portFile) { + portFile.lock(); + portFile.getValues(); + portFile.unlock(); + } + + if (!portFile.containsPortInfo()) { + String forkCmd = SjavacServer.fork(sjavacForkCmd, + portFile.getFilename(), + logfile, + poolsize, + keepalive, + System.err, + stdouterrfile, + background); + if (!portFile.waitForValidValues()) { + // This can be simplified once JDK-8048457 has been addressed + // since we won't have an SjavacClient if background = false + if (background) { + // There seems be some problem with spawning the external + // process (for instance no fork command provided and no + // sjavac on path) + StringWriter sw = new StringWriter(); + SjavacClient.printFailedAttempt(forkCmd, + stdouterrfile, + new PrintWriter(sw)); + Log.error(sw.toString()); + } + } + } + return portFile.containsPortInfo(); + } + + + public static void printFailedAttempt(String cmd, String f, PrintWriter err) { + err.println("---- Failed to start javac server with this command -----"); + err.println(cmd); + try { + BufferedReader in = new BufferedReader(new FileReader(f)); + err.println("---- stdout/stderr output from attempt to start javac server -----"); + for (;;) { + String l = in.readLine(); + if (l == null) { + break; + } + err.println(l); + } + err.println("------------------------------------------------------------------"); + } catch (Exception e) { + err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start."); + } + } + + @Override + public void shutdown() { + // Nothing to clean up + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java Thu Aug 28 14:53:49 2014 -0700 @@ -30,10 +30,10 @@ /** Subclass to Attr that overrides reportDepedence. * - *

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.

+ *

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. */ public class AttrWithDeps extends Attr { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java Thu Aug 28 14:53:49 2014 -0700 @@ -34,6 +34,7 @@ import java.util.Set; import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; @@ -41,10 +42,10 @@ /** Utility class containing dependency information between packages * and the pubapi for a package. * - *

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.

+ *

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. */ public class Dependencies { protected static final Context.Key dependenciesKey = new Context.Key<>(); @@ -154,7 +155,7 @@ Name n = ((ClassSymbol)e).fullname; Name p = ((ClassSymbol)e).packge().fullname; StringBuffer sb = publicApiPerClass.get(n); - assert(sb == null); + Assert.check(sb == null); sb = new StringBuffer(); PubapiVisitor v = new PubapiVisitor(sb); v.visit(e); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java Thu Aug 28 14:53:49 2014 -0700 @@ -32,29 +32,29 @@ /** Subclass to Resolve that overrides collect. * - *

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.

+ *

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. */ public class JavaCompilerWithDeps extends JavaCompiler { /** The dependency database */ protected Dependencies deps; - protected JavacServiceImpl javacService; + protected SjavacErrorHandler errorHandler; - public JavaCompilerWithDeps(Context context, JavacServiceImpl jsi) { + public JavaCompilerWithDeps(Context context, SjavacErrorHandler eh) { super(context); deps = Dependencies.instance(context); - javacService = jsi; + errorHandler = eh; needRootClasses = true; } - public static void preRegister(Context context, final JavacServiceImpl t) { + public static void preRegister(Context context, final SjavacErrorHandler eh) { context.put(compilerKey, new Context.Factory() { public JavaCompiler make(Context c) { - JavaCompiler instance = new JavaCompilerWithDeps(c, t); + JavaCompiler instance = new JavaCompilerWithDeps(c, eh); c.put(JavaCompiler.class, instance); return instance; } @@ -97,7 +97,7 @@ // Now check if the truncated uri ends with the path. (It does not == failure!) if (path.length() > 0 && !path.equals("/unnamed package/") && !pp.endsWith(path)) { - javacService.logError("Error: The source file "+sym.sourcefile.getName()+ + errorHandler.logError("Error: The source file "+sym.sourcefile.getName()+ " is located in the wrong package directory, because it contains the class "+ sym.getQualifiedName()); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavacServiceImpl.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavacServiceImpl.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.comp; - -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.server.CompilationResult; -import com.sun.tools.sjavac.server.JavacServer; -import com.sun.tools.sjavac.server.JavacService; -import com.sun.tools.sjavac.server.SysInfo; - -public class JavacServiceImpl implements JavacService { - - JavacServer javacServer; - private ThreadLocal forcedExit; - - public JavacServiceImpl(JavacServer javacServer) { - this.javacServer = javacServer; - - } - - public void logError(String msg) { -// stderr.println(msg); - forcedExit.set(true); - } - - @Override - public SysInfo getSysInfo() { - return new SysInfo(Runtime.getRuntime().availableProcessors(), - Runtime.getRuntime().maxMemory()); - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - - JavacTool compiler = JavacTool.create(); - StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); - SmartFileManager smartFileManager = new SmartFileManager(fileManager); - Context context = new Context(); - ResolveWithDeps.preRegister(context); - AttrWithDeps.preRegister(context); - JavaCompilerWithDeps.preRegister(context, this); - - // Now setup the actual compilation.... - CompilationResult compilationResult = new CompilationResult(0); - - // First deal with explicit source files on cmdline and in at file. - ListBuffer compilationUnits = new ListBuffer<>(); - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) { - compilationUnits.append(i); - } - // Now deal with sources supplied as source_to_compile. - ListBuffer sourcesToCompileFiles = new ListBuffer<>(); - for (URI u : sourcesToCompile) { - sourcesToCompileFiles.append(new File(u)); - } - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { - compilationUnits.append(i); - } - // Log the options to be used. - StringBuilder options = new StringBuilder(); - for (String s : args) { - options.append(">").append(s).append("< "); - } - javacServer.log(protocolId+" <"+invocationId+"> options "+options.toString()); - - forcedExit.set(false); - // Create a new logger. - StringWriter stdoutLog = new StringWriter(); - StringWriter stderrLog = new StringWriter(); - PrintWriter stdout = new PrintWriter(stdoutLog); - PrintWriter stderr = new PrintWriter(stderrLog); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; - try { - if (compilationUnits.size() > 0) { - smartFileManager.setVisibleSources(visibleSources); - smartFileManager.cleanArtifacts(); - smartFileManager.setLog(stdout); - - - // Do the compilation! - CompilationTask task = compiler.getTask(stderr, smartFileManager, null, Arrays.asList(args), null, compilationUnits, context); - rc = ((JavacTaskImpl) task).doCall(); - smartFileManager.flush(); - } - } catch (Exception e) { - stderr.println(e.getMessage()); - forcedExit.set(true); - } - - compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts(); - - Dependencies deps = Dependencies.instance(context); - compilationResult.packageDependencies = deps.getDependencies(); - compilationResult.packagePubapis = deps.getPubapis(); - - compilationResult.stdout = stdoutLog.toString(); - compilationResult.stderr = stderrLog.toString(); - compilationResult.returnCode = rc.exitCode == 0 && forcedExit.get() ? -1 : rc.exitCode; - - return compilationResult; - } -} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.comp; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + +/** + * An sjavac implementation that limits the number of concurrent calls by + * wrapping invocations in Callables and delegating them to a FixedThreadPool. + * + *

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. + */ +public class PooledSjavac implements Sjavac { + + final Sjavac delegate; + final ExecutorService pool; + + public PooledSjavac(Sjavac delegate, int poolsize) { + Objects.requireNonNull(delegate); + this.delegate = delegate; + pool = Executors.newFixedThreadPool(poolsize, new ThreadFactory() { + AtomicInteger count = new AtomicInteger(); + @Override + public Thread newThread(Runnable runnable) { + String cls = PooledSjavac.class.getSimpleName(); + int num = count.incrementAndGet(); + Thread t = new Thread(runnable, cls + "-" + num); + t.setDaemon(true); + return t; + } + }); + } + + @Override + public SysInfo getSysInfo() { + try { + return pool.submit(new Callable() { + @Override + public SysInfo call() throws Exception { + return delegate.getSysInfo(); + } + }).get(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error during getSysInfo", e); + } + } + + @Override + public CompilationResult compile(final String protocolId, + final String invocationId, + final String[] args, + final List explicitSources, + final Set sourcesToCompile, + final Set visibleSources) { + try { + return pool.submit(new Callable() { + @Override + public CompilationResult call() throws Exception { + return delegate.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + } + }).get(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error during compile", e); + } + } + + @Override + public void shutdown() { + pool.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + pool.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) + Log.error("ThreadPool did not terminate"); + } + // Grace period for thread termination + Thread.sleep(1000); + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + + delegate.shutdown(); + } + + @Override + public String serverSettings() { + return delegate.serverSettings(); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,10 +37,10 @@ /** Utility class that constructs a textual representation * of the public api of a class. * - *

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.

+ *

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. */ public class PubapiVisitor extends ElementScanner9 { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,10 @@ /** Subclass to Resolve that overrides collect. * - *

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.

+ *

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. */ public class ResolveWithDeps extends Resolve { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacErrorHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacErrorHandler.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.sjavac.comp; + +/** + *

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. + */ +public interface SjavacErrorHandler { + void logError(String msg); +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.comp; + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Options; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + +/** + * The sjavac implementation that interacts with javac and performs the actual + * compilation. + * + *

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. + */ +public class SjavacImpl implements Sjavac { + + @Override + public SysInfo getSysInfo() { + return new SysInfo(Runtime.getRuntime().availableProcessors(), + Runtime.getRuntime().maxMemory()); + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + final AtomicBoolean forcedExit = new AtomicBoolean(); + + JavacTool compiler = JavacTool.create(); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + SmartFileManager smartFileManager = new SmartFileManager(fileManager); + Context context = new Context(); + ResolveWithDeps.preRegister(context); + AttrWithDeps.preRegister(context); + JavaCompilerWithDeps.preRegister(context, new SjavacErrorHandler() { + @Override + public void logError(String msg) { + forcedExit.set(true); + } + }); + + // Now setup the actual compilation.... + CompilationResult compilationResult = new CompilationResult(0); + + // First deal with explicit source files on cmdline and in at file. + ListBuffer compilationUnits = new ListBuffer<>(); + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) { + compilationUnits.append(i); + } + // Now deal with sources supplied as source_to_compile. + ListBuffer sourcesToCompileFiles = new ListBuffer<>(); + for (URI u : sourcesToCompile) { + sourcesToCompileFiles.append(new File(u)); + } + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { + compilationUnits.append(i); + } + forcedExit.set(false); + // Create a new logger. + StringWriter stdoutLog = new StringWriter(); + StringWriter stderrLog = new StringWriter(); + PrintWriter stdout = new PrintWriter(stdoutLog); + PrintWriter stderr = new PrintWriter(stderrLog); + com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + try { + if (compilationUnits.size() > 0) { + smartFileManager.setVisibleSources(visibleSources); + smartFileManager.cleanArtifacts(); + smartFileManager.setLog(stdout); + + // Do the compilation! + CompilationTask task = compiler.getTask(stderr, + smartFileManager, + null, + Arrays.asList(args), + null, + compilationUnits, + context); + smartFileManager.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file")); + rc = ((JavacTaskImpl) task).doCall(); + smartFileManager.flush(); + } + } catch (Exception e) { + stderrLog.append(e.getMessage()); + forcedExit.set(true); + } + + compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts(); + + Dependencies deps = Dependencies.instance(context); + compilationResult.packageDependencies = deps.getDependencies(); + compilationResult.packagePubapis = deps.getPubapis(); + + compilationResult.stdout = stdoutLog.toString(); + compilationResult.stderr = stderrLog.toString(); + + compilationResult.returnCode = rc.exitCode == 0 && forcedExit.get() ? -1 : rc.exitCode; + + return compilationResult; + } + + @Override + public void shutdown() { + // Nothing to clean up + // ... maybe we should wait for any current request to finish? + } + + + @Override + public String serverSettings() { + return ""; + } + +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Thu Aug 28 14:53:49 2014 -0700 @@ -37,7 +37,6 @@ import javax.tools.JavaFileObject.Kind; import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.util.BaseFileManager; import com.sun.tools.javac.util.ListBuffer; /** @@ -50,10 +49,10 @@ * Can also blind out the filemanager from seeing certain files in the file system. * Necessary to prevent javac from seeing some sources where the source path points. * - *

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.

+ *

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. */ public class SmartFileManager extends ForwardingJavaFileManager { @@ -97,9 +96,7 @@ public Iterable list(Location location, String packageName, Set kinds, - boolean recurse) - throws IOException - { + boolean recurse) throws IOException { // Acquire the list of files. Iterable files = super.list(location, packageName, kinds, recurse); if (visibleSources.isEmpty()) { @@ -112,8 +109,7 @@ String t = uri.toString(); if (t.startsWith("jar:") || t.endsWith(".class") - || visibleSources.contains(uri)) - { + || visibleSources.contains(uri)) { filteredFiles.add(f); } } @@ -128,9 +124,7 @@ @Override public JavaFileObject getJavaFileForInput(Location location, String className, - Kind kind) - throws IOException - { + Kind kind) throws IOException { JavaFileObject file = super.getJavaFileForInput(location, className, kind); if (file == null || visibleSources.isEmpty()) { return file; @@ -146,9 +140,7 @@ public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, - FileObject sibling) - throws IOException - { + FileObject sibling) throws IOException { JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); if (file == null) return file; int dp = className.lastIndexOf('.'); @@ -165,9 +157,7 @@ @Override public FileObject getFileForInput(Location location, String packageName, - String relativeName) - throws IOException - { + String relativeName) throws IOException { FileObject file = super.getFileForInput(location, packageName, relativeName); if (file == null || visibleSources.isEmpty()) { return file; @@ -183,9 +173,7 @@ public FileObject getFileForOutput(Location location, String packageName, String relativeName, - FileObject sibling) - throws IOException - { + FileObject sibling) throws IOException { FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling); if (file == null) return file; if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,10 @@ * and compare the new content with the old content on disk. Only if they differ, * will the file be updated. * - *

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.

+ *

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. */ public class SmartFileObject implements JavaFileObject { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,9 @@ * If not, the file is not touched. * *

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.

+ * 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. */ public class SmartWriter extends Writer { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java Thu Aug 28 14:53:49 2014 -0700 @@ -27,6 +27,12 @@ import java.util.Iterator; +/** + *

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. + */ public class ArgumentIterator implements Iterator { /** The underlying argument iterator */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Thu Aug 28 14:53:49 2014 -0700 @@ -47,6 +47,11 @@ * This enum represents all options from (1) and (2). Note that instances of * this enum only entail static information about the option. For storage of * option values, refer to com.sun.tools.sjavac.options.Options. + * + *

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. */ public enum Option { @@ -231,7 +236,14 @@ helper.logLevel("info"); } }, - PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Keep unidentified artifacts in destination directory") { + PERMIT_ARTIFACT("--permit-artifact=", "Allow this artifact in destination directory") { + @Override + protected void processMatching(ArgumentIterator iter, OptionHelper helper) { + String a = iter.current().substring(arg.length()); + helper.permitArtifact(Paths.get(a).toFile().getAbsolutePath()); + } + }, + PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Allow unidentified artifacts in destination directory") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.permitUnidentifiedArtifacts(); @@ -274,8 +286,16 @@ if (dir != null) helper.headerDir(dir); } + }, + STATE_DIR("--state-dir=", "Directory used to store sjavac state and log files.") { + @Override + protected void processMatching(ArgumentIterator iter, OptionHelper helper) { + String p = iter.current().substring(arg.length()); + helper.stateDir(Paths.get(p)); + } }; + public final String arg; final String description; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,17 +25,23 @@ package com.sun.tools.sjavac.options; -import java.nio.file.Files; +import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import com.sun.tools.javac.main.CommandLine; import com.sun.tools.sjavac.Transformer; /** * This class is used to decode sjavac options. * See com.sun.tools.sjavac.options.Options for example usage. + * + *

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. */ public abstract class OptionHelper { @@ -78,6 +84,9 @@ /** Record path for reference source list */ public abstract void compareFoundSources(Path referenceList); + /** Record a single permitted artifact */ + public abstract void permitArtifact(String f); + /** Record the fact that unidentified artifacts are permitted */ public abstract void permitUnidentifiedArtifacts(); @@ -102,6 +111,9 @@ /** Sets the directory for generated headers */ public abstract void headerDir(Path dir); + /** Sets the directory for state and log files generated by sjavac */ + public abstract void stateDir(Path dir); + /** Sets the implicit policy */ public abstract void implicit(String policy); @@ -112,7 +124,11 @@ * @param args the arguments to traverse. */ void traverse(String[] args) { - + try { + args = CommandLine.parse(args); // Detect @file and load it as a command line. + } catch (java.io.IOException e) { + throw new IllegalArgumentException("Problem reading @"+e.getMessage()); + } ArgumentIterator argIter = new ArgumentIterator(Arrays.asList(args)); nextArg: diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Aug 28 14:53:49 2014 -0700 @@ -32,16 +32,23 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.HashSet; import com.sun.tools.sjavac.Transformer; /** * Instances of this class represent values for sjavac command line options. + * + *

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. */ public class Options { // Output directories - private Path destDir, genSrcDir, headerDir; + private Path destDir, genSrcDir, headerDir, stateDir; // Input directories private List sources = new ArrayList<>(); @@ -51,7 +58,8 @@ private String logLevel = "info"; - private boolean permitUnidentifiedArtifact = false; + private Set permitted_artifacts = new HashSet<>(); + private boolean permitUnidentifiedArtifacts = false; private boolean permitSourcesInDefaultPackage = false; private Path sourceReferenceList; @@ -86,6 +94,11 @@ return headerDir; } + /** Get the path for the state directory, defaults to destDir. */ + public Path getStateDir() { + return stateDir != null ? stateDir : destDir; + } + /** Get all source locations for files to be compiled */ public List getSources() { return sources; @@ -114,10 +127,15 @@ return logLevel; } + /** Returns true iff the artifact is permitted in the output dir. */ + public boolean isUnidentifiedArtifactPermitted(String f) { + return permitted_artifacts.contains(f); + } + /** Returns true iff artifacts in the output directories should be kept, * even if they would not be generated in a clean build. */ - public boolean isUnidentifiedArtifactPermitted() { - return permitUnidentifiedArtifact; + public boolean areUnidentifiedArtifactsPermitted() { + return permitUnidentifiedArtifacts; } /** Returns true iff sources in the default package should be permitted. */ @@ -176,14 +194,6 @@ return false; } - /** Returns true iff an @-file is among the javac arguments */ - public boolean isAtFilePresent() { - for (String javacArg : javacArgs) - if (javacArg.startsWith("@")) - return true; - return false; - } - /** * Returns a string representation of the options that affect the result of * the compilation. (Used for saving the state of the options used in a @@ -239,6 +249,9 @@ if (destDir != null) args.addArg(Option.D, destDir.normalize()); + if (stateDir != null) + args.addArg(Option.STATE_DIR, stateDir.normalize()); + // Source roots args.addSourceLocations(Option.SRC, sources); args.addSourceLocations(Option.SOURCEPATH, sourceSearchPaths); @@ -249,7 +262,11 @@ if (permitSourcesInDefaultPackage) args.addArg(Option.PERMIT_SOURCES_WITHOUT_PACKAGE); - if (permitUnidentifiedArtifact) + for (String f : permitted_artifacts) { + args.addArg(Option.PERMIT_ARTIFACT, f); + } + + if (permitUnidentifiedArtifacts) args.addArg(Option.PERMIT_UNIDENTIFIED_ARTIFACTS); // Translation rules @@ -327,6 +344,7 @@ boolean headerProvided = false; boolean genSrcProvided = false; + boolean stateProvided = false; @Override public void reportError(String msg) { @@ -399,8 +417,13 @@ } @Override + public void permitArtifact(String f) { + permitted_artifacts.add(f); + } + + @Override public void permitUnidentifiedArtifacts() { - permitUnidentifiedArtifact = true; + permitUnidentifiedArtifacts = true; } @Override @@ -465,6 +488,16 @@ headerDir = dir.toAbsolutePath(); } + @Override + public void stateDir(Path dir) { + if (stateProvided) { + reportError("State directory already specified."); + return; + } + stateProvided = true; + stateDir = dir.toAbsolutePath(); + } + private List createSourceLocations(List paths) { List result = new ArrayList<>(); for (Path path : paths) { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Thu Aug 28 14:53:49 2014 -0700 @@ -37,6 +37,11 @@ /** * Represents a directory to be used for input to sjavac. (For instance a * sourcepath or classpath.) + * + *

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. */ public class SourceLocation { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,28 +25,35 @@ package com.sun.tools.sjavac.server; +import java.io.Serializable; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.Set; -public class CompilationResult { +/** + * + *

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. + */ +public class CompilationResult implements Serializable { + + static final long serialVersionUID = 46739181113L; // Return code constants - public final static int ERROR_BUT_TRY_AGAIN = -4712; public final static int ERROR_FATAL = -1; public int returnCode; public Map> packageArtifacts = new HashMap<>(); public Map> packageDependencies = new HashMap<>(); public Map packagePubapis = new HashMap<>(); - public SysInfo sysinfo; - public String stdout; - public String stderr; + public String stdout = ""; + public String stderr = ""; public CompilationResult(int returnCode) { this.returnCode = returnCode; - this.sysinfo = new SysInfo(-1, -1); } public void setReturnCode(int returnCode) { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerPool.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerPool.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.server; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; -import java.util.Stack; -import java.util.concurrent.Future; - -import com.sun.tools.sjavac.comp.JavacServiceImpl; - -/** The compiler pool maintains compiler threads. - * - *

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.

- */ -public class CompilerPool { - // The javac server that created this pool. - private JavacServer javacServer; - // A semaphore protecting the poolsize number of threads. - private Semaphore available; - // The stack of compiler threads. - private Stack compilers = new Stack<>(); - // And the executor server to spawn threads. - private final ExecutorService executorPool; - // How many requests are active right now? - private int concurrentRequests = 0; - // When was the last request finished? - private long lastRequestFinished = 0; - // The total number of requests to this pool. - private int numRequests = 0; - // Protect access to the three above values. - private static final Object conc = new Object(); - - /** - * Return the javac server that this pool belongs to. - */ - public JavacServer getJavacServer() { - return javacServer; - } - - /** - * Return how many threads are running at this very moment. - */ - public int numActiveRequests() - { - synchronized (conc) { - return concurrentRequests; - } - } - - /** - * Return when the last request was finished. - * I.e. the pool has been idle since. - */ - public long lastRequestFinished() - { - synchronized (conc) { - return lastRequestFinished; - } - } - - /** - * Up the number of active requests. - */ - public int startRequest() { - int n; - synchronized (conc) { - concurrentRequests++; - numRequests++; - n = numRequests; - } - return n; - } - - /** - * Down the number of active requests. Return the current time. - */ - public long stopRequest() { - synchronized (conc) { - concurrentRequests--; - lastRequestFinished = System.currentTimeMillis(); - } - return lastRequestFinished; - } - - /** - * Create a new compiler pool. - */ - CompilerPool(int poolsize, JavacServer server) { - available = new Semaphore(poolsize, true); - javacServer = server; - executorPool = Executors.newFixedThreadPool(poolsize); - lastRequestFinished = System.currentTimeMillis(); - } - - /** - * Execute a compiler thread. - */ - public void execute(CompilerThread ct) { - executorPool.execute(ct); - } - - /** - * Execute a minor task, for example generating bytecodes and writing them to disk, - * that belong to a major compiler thread task. - */ - public Future executeSubtask(CompilerThread t, Runnable r) { - return executorPool.submit(r); - } - - /** - * Shutdown the pool. - */ - public void shutdown() { - executorPool.shutdown(); - } - - /** - * Acquire a compiler thread from the pool, or block until a thread is available. - * If the pools is empty, create a new thread, but never more than is "available". - */ - public CompilerThread grabCompilerThread() throws InterruptedException { - available.acquire(); - if (compilers.empty()) { - return new CompilerThread(this, new JavacServiceImpl(javacServer)); - } - return compilers.pop(); - } - - /** - * Return the specified compiler thread to the pool. - */ - public void returnCompilerThread(CompilerThread h) { - compilers.push(h); - available.release(); - } -} - diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerThread.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerThread.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.server; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.Socket; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Future; - -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Options; -import com.sun.tools.javac.util.StringUtils; -import com.sun.tools.sjavac.comp.AttrWithDeps; -import com.sun.tools.sjavac.comp.Dependencies; -import com.sun.tools.sjavac.comp.JavaCompilerWithDeps; -import com.sun.tools.sjavac.comp.JavacServiceImpl; -import com.sun.tools.sjavac.comp.ResolveWithDeps; -import com.sun.tools.sjavac.comp.SmartFileManager; - -/** - * The compiler thread maintains a JavaCompiler instance and - * can receive a request from the client, perform the compilation - * requested and report back the results. - * - * *

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.

- */ -public class CompilerThread implements Runnable { - private JavacServer javacServer; - private CompilerPool compilerPool; - private JavacServiceImpl javacServiceImpl; - private List> subTasks; - - // Communicating over this socket. - private Socket socket; - - // The necessary classes to do a compilation. - private com.sun.tools.javac.api.JavacTool compiler; - private StandardJavaFileManager fileManager; - private SmartFileManager smartFileManager; - private Context context; - - // If true, then this thread is serving a request. - private boolean inUse = false; - - CompilerThread(CompilerPool cp, JavacServiceImpl javacServiceImpl) { - compilerPool = cp; - javacServer = cp.getJavacServer(); - this.javacServiceImpl = javacServiceImpl; - } - - /** - * Execute a minor task, for example generating bytecodes and writing them to disk, - * that belong to a major compiler thread task. - */ - public synchronized void executeSubtask(Runnable r) { - subTasks.add(compilerPool.executeSubtask(this, r)); - } - - /** - * Count the number of active sub tasks. - */ - public synchronized int numActiveSubTasks() { - int c = 0; - for (Future f : subTasks) { - if (!f.isDone() && !f.isCancelled()) { - c++; - } - } - return c; - } - - /** - * Use this socket for the upcoming request. - */ - public void setSocket(Socket s) { - socket = s; - } - - /** - * Prepare the compiler thread for use. It is not yet started. - * It will be started by the executor service. - */ - public synchronized void use() { - assert(!inUse); - inUse = true; - compiler = com.sun.tools.javac.api.JavacTool.create(); - fileManager = compiler.getStandardFileManager(null, null, null); - smartFileManager = new SmartFileManager(fileManager); - context = new Context(); - ResolveWithDeps.preRegister(context); - AttrWithDeps.preRegister(context); - JavaCompilerWithDeps.preRegister(context, javacServiceImpl); - subTasks = new ArrayList<>(); - } - - /** - * Prepare the compiler thread for idleness. - */ - public synchronized void unuse() { - assert(inUse); - inUse = false; - compiler = null; - fileManager = null; - smartFileManager = null; - context = null; - subTasks = null; - } - - /** - * Expect this key on the next line read from the reader. - */ - private static boolean expect(BufferedReader in, String key) throws IOException { - String s = in.readLine(); - if (s != null && s.equals(key)) { - return true; - } - return false; - } - - // The request identifier, for example GENERATE_NEWBYTECODE - String id = ""; - - public String currentRequestId() { - return id; - } - - PrintWriter stdout; - PrintWriter stderr; - int forcedExitCode = 0; - - public void logError(String msg) { - stderr.println(msg); - forcedExitCode = -1; - } - - /** - * Invoked by the executor service. - */ - public void run() { - // Unique nr that identifies this request. - int thisRequest = compilerPool.startRequest(); - long start = System.currentTimeMillis(); - int numClasses = 0; - StringBuilder compiledPkgs = new StringBuilder(); - use(); - - PrintWriter out = null; - try { - javacServer.log("<"+thisRequest+"> Connect from "+socket.getRemoteSocketAddress()+" activethreads="+compilerPool.numActiveRequests()); - BufferedReader in = new BufferedReader(new InputStreamReader( - socket.getInputStream())); - out = new PrintWriter(new OutputStreamWriter( - socket.getOutputStream())); - if (!expect(in, JavacServer.PROTOCOL_COOKIE_VERSION)) { - javacServer.log("<"+thisRequest+"> Bad protocol from ip "+socket.getRemoteSocketAddress()); - return; - } - - String cookie = in.readLine(); - if (cookie == null || !cookie.equals(""+javacServer.getCookie())) { - javacServer.log("<"+thisRequest+"> Bad cookie from ip "+socket.getRemoteSocketAddress()); - return; - } - if (!expect(in, JavacServer.PROTOCOL_CWD)) { - return; - } - String cwd = in.readLine(); - if (cwd == null) - return; - if (!expect(in, JavacServer.PROTOCOL_ID)) { - return; - } - id = in.readLine(); - if (id == null) - return; - if (!expect(in, JavacServer.PROTOCOL_ARGS)) { - return; - } - ArrayList the_options = new ArrayList<>(); - ArrayList the_classes = new ArrayList<>(); - Iterable path = Arrays. asList(new File(cwd)); - - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_SOURCES_TO_COMPILE)) - break; - if (l.startsWith("--server:")) - continue; - if (!l.startsWith("-") && l.endsWith(".java")) { - the_classes.add(new File(l)); - numClasses++; - } else { - the_options.add(l); - } - continue; - } - - // Load sources to compile - Set sourcesToCompile = new HashSet<>(); - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_VISIBLE_SOURCES)) - break; - try { - sourcesToCompile.add(new URI(l)); - numClasses++; - } catch (URISyntaxException e) { - return; - } - } - // Load visible sources - Set visibleSources = new HashSet<>(); - boolean fix_drive_letter_case = - StringUtils.toLowerCase(System.getProperty("os.name")).startsWith("windows"); - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_END)) - break; - try { - URI u = new URI(l); - if (fix_drive_letter_case) { - // Make sure the driver letter is lower case. - String s = u.toString(); - if (s.startsWith("file:/") && - Character.isUpperCase(s.charAt(6))) { - u = new URI("file:/"+Character.toLowerCase(s.charAt(6))+s.substring(7)); - } - } - visibleSources.add(u); - } catch (URISyntaxException e) { - return; - } - } - - // A completed request has been received. - - // Now setup the actual compilation.... - // First deal with explicit source files on cmdline and in at file. - ListBuffer compilationUnits = new ListBuffer<>(); - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(the_classes)) { - compilationUnits.append(i); - } - // Now deal with sources supplied as source_to_compile. - ListBuffer sourcesToCompileFiles = new ListBuffer<>(); - for (URI u : sourcesToCompile) { - sourcesToCompileFiles.append(new File(u)); - } - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { - compilationUnits.append(i); - } - // Log the options to be used. - StringBuilder options = new StringBuilder(); - for (String s : the_options) { - options.append(">").append(s).append("< "); - } - javacServer.log(id+" <"+thisRequest+"> options "+options.toString()); - - forcedExitCode = 0; - // Create a new logger. - StringWriter stdoutLog = new StringWriter(); - StringWriter stderrLog = new StringWriter(); - stdout = new PrintWriter(stdoutLog); - stderr = new PrintWriter(stderrLog); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; - try { - if (compilationUnits.size() > 0) { - smartFileManager.setVisibleSources(visibleSources); - smartFileManager.cleanArtifacts(); - smartFileManager.setLog(stdout); - - // Do the compilation! - CompilationTask task = compiler.getTask(stderr, smartFileManager, null, the_options, null, compilationUnits, context); - smartFileManager.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file")); - rc = ((JavacTaskImpl) task).doCall(); - - while (numActiveSubTasks()>0) { - try { Thread.sleep(1000); } catch (InterruptedException e) { } - } - - smartFileManager.flush(); - } - } catch (Exception e) { - stderr.println(e.getMessage()); - forcedExitCode = -1; - } - - // Send the response.. - out.println(JavacServer.PROTOCOL_STDOUT); - out.print(stdoutLog); - out.println(JavacServer.PROTOCOL_STDERR); - out.print(stderrLog); - // The compilation is complete! And errors will have already been printed on out! - out.println(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS); - Map> pa = smartFileManager.getPackageArtifacts(); - for (String aPkgName : pa.keySet()) { - out.println("+"+aPkgName); - Set as = pa.get(aPkgName); - for (URI a : as) { - out.println(" "+a.toString()); - } - } - Dependencies deps = Dependencies.instance(context); - out.println(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES); - Map> pd = deps.getDependencies(); - for (String aPkgName : pd.keySet()) { - out.println("+"+aPkgName); - Set ds = pd.get(aPkgName); - // Everything depends on java.lang - if (!ds.contains(":java.lang")) ds.add(":java.lang"); - for (String d : ds) { - out.println(" "+d); - } - } - out.println(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS); - Map pp = deps.getPubapis(); - for (String aPkgName : pp.keySet()) { - out.println("+"+aPkgName); - String ps = pp.get(aPkgName); - // getPubapis added a space to each line! - out.println(ps); - compiledPkgs.append(aPkgName+" "); - } - out.println(JavacServer.PROTOCOL_SYSINFO); - out.println("num_cores=" + Runtime.getRuntime().availableProcessors()); - out.println("max_memory=" + Runtime.getRuntime().maxMemory()); - out.println(JavacServer.PROTOCOL_RETURN_CODE); - - // Errors from sjavac that affect compilation status! - int rcv = rc.exitCode; - if (rcv == 0 && forcedExitCode != 0) { - rcv = forcedExitCode; - } - out.println("" + rcv); - out.println(JavacServer.PROTOCOL_END); - out.flush(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (out != null) out.close(); - if (!socket.isClosed()) { - socket.close(); - } - socket = null; - } catch (Exception e) { - javacServer.log("ERROR "+e); - e.printStackTrace(); - } - compilerPool.stopRequest(); - long duration = System.currentTimeMillis()-start; - javacServer.addBuildTime(duration); - float classpersec = ((float)numClasses)*(((float)1000.0)/((float)duration)); - javacServer.log(id+" <"+thisRequest+"> "+compiledPkgs+" duration " + duration+ " ms num_classes="+numClasses+ - " classpersec="+classpersec+" subtasks="+subTasks.size()); - javacServer.flushLog(); - unuse(); - compilerPool.returnCompilerThread(this); - } - } -} - diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * An sjavac implementation that keeps track of idleness and shuts down the + * given Terminable upon idleness timeout. + * + * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last + * request is completed. + * + *

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. + */ +public class IdleResetSjavac implements Sjavac { + + private final Sjavac delegate; + private final AtomicInteger outstandingCalls = new AtomicInteger(); + private final Terminable toShutdown; + private final Timer idlenessTimer = new Timer(); + private final long idleTimeout; + + // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled + private TimerTask idlenessTimerTask; + + public IdleResetSjavac(Sjavac delegate, + Terminable toShutdown, + long idleTimeout) { + this.delegate = delegate; + this.toShutdown = toShutdown; + this.idleTimeout = idleTimeout; + scheduleTimeout(); + } + + @Override + public SysInfo getSysInfo() { + startCall(); + try { + return delegate.getSysInfo(); + } finally { + endCall(); + } + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + startCall(); + try { + return delegate.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + } finally { + endCall(); + } + } + + private void startCall() { + // Was there no outstanding calls before this call? + if (outstandingCalls.incrementAndGet() == 1) { + // Then the timer task must have been scheduled + if (idlenessTimerTask == null) + throw new IllegalStateException("Idle timeout already cancelled"); + // Cancel timeout task + idlenessTimerTask.cancel(); + idlenessTimerTask = null; + } + } + + private void endCall() { + if (outstandingCalls.decrementAndGet() == 0) { + // No more outstanding calls. Schedule timeout. + scheduleTimeout(); + } + } + + private void scheduleTimeout() { + if (idlenessTimerTask != null) + throw new IllegalStateException("Idle timeout already scheduled"); + idlenessTimerTask = new TimerTask() { + public void run() { + toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); + } + }; + idlenessTimer.schedule(idlenessTimerTask, idleTimeout); + } + + @Override + public void shutdown() { + idlenessTimer.cancel(); + delegate.shutdown(); + } + + @Override + public String serverSettings() { + return delegate.serverSettings(); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServer.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServer.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2011-2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.tools.sjavac.server; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.FileNotFoundException; -import java.util.HashMap; -import java.util.Map; - -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Random; - -import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.ProblemException; -import java.io.*; - -/** - * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. - * - *

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.

- */ -public class JavacServer { - // Responding to this tcp/ip port on localhost. - - private final ServerSocket serverSocket; - // The secret cookie shared between server and client through the port file. - private final long myCookie; - // When the server was started. - private long serverStart; - // Accumulated build time for all requests, not counting idle time. - private long totalBuildTime; - // The javac server specific log file. - PrintWriter theLog; - // The compiler pool that maintains the compiler threads. - CompilerPool compilerPool; - // For the client, all port files fetched, one per started javac server. - // Though usually only one javac server is started by a client. - private static Map allPortFiles; - private static Map maxServerMemory; - final static String PROTOCOL_COOKIE_VERSION = "----THE-COOKIE-V2----"; - final static String PROTOCOL_CWD = "----THE-CWD----"; - final static String PROTOCOL_ID = "----THE-ID----"; - final static String PROTOCOL_ARGS = "----THE-ARGS----"; - final static String PROTOCOL_SOURCES_TO_COMPILE = "----THE-SOURCES-TO-COMPILE----"; - final static String PROTOCOL_VISIBLE_SOURCES = "----THE-VISIBLE-SOURCES----"; - final static String PROTOCOL_END = "----THE-END----"; - final static String PROTOCOL_STDOUT = "----THE-STDOUT----"; - final static String PROTOCOL_STDERR = "----THE-STDERR----"; - final static String PROTOCOL_PACKAGE_ARTIFACTS = "----THE-PACKAGE_ARTIFACTS----"; - final static String PROTOCOL_PACKAGE_DEPENDENCIES = "----THE-PACKAGE_DEPENDENCIES----"; - final static String PROTOCOL_PACKAGE_PUBLIC_APIS = "----THE-PACKAGE-PUBLIC-APIS----"; - final static String PROTOCOL_SYSINFO = "----THE-SYSINFO----"; - final static String PROTOCOL_RETURN_CODE = "----THE-RETURN-CODE----"; - // Check if the portfile is gone, every 5 seconds. - static int CHECK_PORTFILE_INTERVAL = 5; - // Wait 2 seconds for response, before giving up on javac server. - static int CONNECTION_TIMEOUT = 2; - static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 1; - static int MAX_NUM_CONNECT_ATTEMPTS = 3; - - /** - * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. - */ - public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { - if (allPortFiles == null) { - allPortFiles = new HashMap<>(); - } - PortFile pf = allPortFiles.get(filename); - - // Port file known. Does it still exist? - if (pf != null) { - try { - if (!pf.exists()) - pf = null; - } catch (IOException ioex) { - ioex.printStackTrace(); - } - } - - if (pf == null) { - pf = new PortFile(filename); - allPortFiles.put(filename, pf); - } - return pf; - } - - /** - * Get the cookie used for this server. - */ - long getCookie() { - return myCookie; - } - - /** - * Get the port used for this server. - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Sum up the total build time for this javac server. - */ - public void addBuildTime(long inc) { - totalBuildTime += inc; - } - - /** - * Log this message. - */ - public void log(String msg) { - if (theLog != null) { - theLog.println(msg); - } else { - System.err.println(msg); - } - } - - /** - * Make sure the log is flushed. - */ - public void flushLog() { - if (theLog != null) { - theLog.flush(); - } - } - - /** - * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" - * is sent as the settings parameter. Returns 0 on success, -1 on failure. - */ - public static int startServer(String settings, PrintStream err) { - try { - String portfile = Util.extractStringOption("portfile", settings); - // The log file collects more javac server specific log information. - String logfile = Util.extractStringOption("logfile", settings); - // The stdouterr file collects all the System.out and System.err writes to disk. - String stdouterrfile = Util.extractStringOption("stdouterrfile", settings); - // We could perhaps use System.setOut and setErr here. - // But for the moment we rely on the client to spawn a shell where stdout - // and stderr are redirected already. - // The pool size is a limit the number of concurrent compiler threads used. - // The server might use less than these to avoid memory problems. - int defaultPoolSize = Runtime.getRuntime().availableProcessors(); - int poolsize = Util.extractIntOption("poolsize", settings, defaultPoolSize); - - // How many seconds of inactivity will the server accept before quitting? - int keepalive = Util.extractIntOption("keepalive", settings, 120); - - // The port file is locked and the server port and cookie is written into it. - PortFile portFile = getPortFile(portfile); - JavacServer s; - - synchronized (portFile) { - portFile.lock(); - portFile.getValues(); - if (portFile.containsPortInfo()) { - err.println("Javac server not started because portfile exists!"); - portFile.unlock(); - return -1; - } - s = new JavacServer(poolsize, logfile); - portFile.setValues(s.getPort(), s.getCookie()); - portFile.unlock(); - } - - // Run the server. Will delete the port file when shutting down. - // It will shut down automatically when no new requests have come in - // during the last 125 seconds. - s.run(portFile, err, keepalive); - // The run loop for the server has exited. - return 0; - } catch (Exception e) { - e.printStackTrace(err); - return -1; - } - } - - /** - * Spawn the server instance. - */ - - private JavacServer(int poolSize, String logfile) throws IOException { - serverStart = System.currentTimeMillis(); - // Create a server socket on a random port that is bound to the localhost/127.0.0.1 interface. - // I.e only local processes can connect to this port. - serverSocket = new ServerSocket(0, 128, InetAddress.getByName(null)); - compilerPool = new CompilerPool(poolSize, this); - Random rnd = new Random(); - myCookie = rnd.nextLong(); - theLog = new PrintWriter(logfile); - log("Javac server started. port=" + getPort() + " date=" + (new java.util.Date()) + " with poolsize=" + poolSize); - flushLog(); - } - - /** - * Fork a background process. Returns the command line used that can be printed if something failed. - */ - public static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive, - final PrintStream err, String stdouterrfile, boolean background) - throws IOException, ProblemException { - if (stdouterrfile != null && stdouterrfile.trim().equals("")) { - stdouterrfile = null; - } - final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive; - - if (background) { - sjavac += "%20" + startserver; - sjavac = sjavac.replaceAll("%20", " "); - sjavac = sjavac.replaceAll("%2C", ","); - // If the java/sh/cmd launcher fails the failure will be captured by stdouterr because of the redirection here. - String[] cmd = {"/bin/sh", "-c", sjavac + " >> " + stdouterrfile + " 2>&1"}; - if (!(new File("/bin/sh")).canExecute()) { - ArrayList wincmd = new ArrayList<>(); - wincmd.add("cmd"); - wincmd.add("/c"); - wincmd.add("start"); - wincmd.add("cmd"); - wincmd.add("/c"); - wincmd.add(sjavac + " >> " + stdouterrfile + " 2>&1"); - cmd = wincmd.toArray(new String[wincmd.size()]); - } - Process pp = null; - try { - pp = Runtime.getRuntime().exec(cmd); - } catch (Exception e) { - e.printStackTrace(err); - e.printStackTrace(new PrintWriter(stdouterrfile)); - } - StringBuilder rs = new StringBuilder(); - for (String s : cmd) { - rs.append(s + " "); - } - return rs.toString(); - } - - // Do not spawn a background server, instead run it within the same JVM. - Thread t = new Thread() { - @Override - public void run() { - try { - JavacServer.startServer(startserver, err); - } catch (Throwable t) { - t.printStackTrace(err); - } - } - }; - t.start(); - return ""; - } - - /** - * Run the server thread until it exits. Either because of inactivity or because the port file has been deleted by someone else, or overtaken by some other - * javac server. - */ - private void run(PortFile portFile, PrintStream err, int keepalive) { - boolean fileDeleted = false; - long timeSinceLastCompile; - try { - // Every 5 second (check_portfile_interval) we test if the portfile has disappeared => quit - // Or if the last request was finished more than 125 seconds ago => quit - // 125 = seconds_of_inactivity_before_shutdown+check_portfile_interval - serverSocket.setSoTimeout(CHECK_PORTFILE_INTERVAL*1000); - for (;;) { - try { - Socket s = serverSocket.accept(); - CompilerThread ct = compilerPool.grabCompilerThread(); - ct.setSocket(s); - compilerPool.execute(ct); - flushLog(); - } catch (java.net.SocketTimeoutException e) { - if (compilerPool.numActiveRequests() > 0) { - // Never quit while there are active requests! - continue; - } - // If this is the timeout after the portfile - // has been deleted by us. Then we truly stop. - if (fileDeleted) { - log("Quitting because of "+(keepalive+CHECK_PORTFILE_INTERVAL)+" seconds of inactivity!"); - break; - } - // Check if the portfile is still there. - if (!portFile.exists()) { - // Time to quit because the portfile was deleted by another - // process, probably by the makefile that is done building. - log("Quitting because portfile was deleted!"); - flushLog(); - break; - } - // Check if portfile.stop is still there. - if (portFile.markedForStop()) { - // Time to quit because another process touched the file - // server.port.stop to signal that the server should stop. - // This is necessary on some operating systems that lock - // the port file hard! - log("Quitting because a portfile.stop file was found!"); - portFile.delete(); - flushLog(); - break; - } - // Does the portfile still point to me? - if (!portFile.stillMyValues()) { - // Time to quit because another build has started. - log("Quitting because portfile is now owned by another javac server!"); - flushLog(); - break; - } - - // Check how long since the last request finished. - long diff = System.currentTimeMillis() - compilerPool.lastRequestFinished(); - if (diff < keepalive * 1000) { - // Do not quit if we have waited less than 120 seconds. - continue; - } - // Ok, time to quit because of inactivity. Perhaps the build - // was killed and the portfile not cleaned up properly. - portFile.delete(); - fileDeleted = true; - log("" + keepalive + " seconds of inactivity quitting in " - + CHECK_PORTFILE_INTERVAL + " seconds!"); - flushLog(); - // Now we have a second 5 second grace - // period where javac remote requests - // that have loaded the data from the - // recently deleted portfile can connect - // and complete their requests. - } - } - } catch (Exception e) { - e.printStackTrace(err); - e.printStackTrace(theLog); - flushLog(); - } finally { - compilerPool.shutdown(); - } - long realTime = System.currentTimeMillis() - serverStart; - log("Shutting down."); - log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - flushLog(); - } - - public static void cleanup(String... args) { - String settings = Util.findServerSettings(args); - if (settings == null) return; - String portfile = Util.extractStringOption("portfile", settings); - String background = Util.extractStringOption("background", settings); - if (background != null && background.equals("false")) { - // If the server runs within this jvm, then delete the portfile, - // since this jvm is about to exit soon. - File f = new File(portfile); - f.delete(); - } - } -} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacService.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacService.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.server; - -import java.io.File; -import java.net.URI; -import java.util.List; -import java.util.Set; - -public interface JavacService { - - SysInfo getSysInfo(); - - CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources); -} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServiceClient.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServiceClient.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.server; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.URI; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.sun.tools.sjavac.Util; - -import static com.sun.tools.sjavac.server.CompilationResult.ERROR_BUT_TRY_AGAIN; -import static com.sun.tools.sjavac.server.CompilationResult.ERROR_FATAL; - -public class JavacServiceClient implements JavacService { - - - // The id can perhaps be used in the future by the javac server to reuse the - // JavaCompiler instance for several compiles using the same id. - private final String id; - private final String portfile; - private final String logfile; - private final String stdouterrfile; - private final boolean background; - - // Default keepalive for server is 120 seconds. - // I.e. it will accept 120 seconds of inactivity before quitting. - private final int keepalive; - private final int poolsize; - - // The sjavac option specifies how the server part of sjavac is spawned. - // If you have the experimental sjavac in your path, you are done. If not, you have - // to point to a com.sun.tools.sjavac.Main that supports --startserver - // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main - private final String sjavac; - - public JavacServiceClient(String settings) { - id = Util.extractStringOption("id", settings); - portfile = Util.extractStringOption("portfile", settings); - logfile = Util.extractStringOption("logfile", settings, portfile + ".javaclog"); - stdouterrfile = Util.extractStringOption("stdouterrfile", settings, portfile + ".stdouterr"); - background = Util.extractBooleanOption("background", settings, true); - sjavac = Util.extractStringOption("sjavac", settings, "sjavac"); - int poolsize = Util.extractIntOption("poolsize", settings); - keepalive = Util.extractIntOption("keepalive", settings, 120); - - this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors(); - } - - - /** - * Make a request to the server only to get the maximum possible heap size to use for compilations. - * - * @param port_file The port file used to synchronize creation of this server. - * @param id The identify of the compilation. - * @param out Standard out information. - * @param err Standard err information. - * @return The maximum heap size in bytes. - */ - @Override - public SysInfo getSysInfo() { - try { - CompilationResult cr = useServer(new String[0], - Collections.emptySet(), - Collections.emptySet(), - Collections.>emptyMap()); - return cr.sysinfo; - } catch (Exception e) { - return new SysInfo(-1, -1); - } - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - // Delegate to useServer, which delegates to compileHelper - return useServer(args, sourcesToCompile, visibleSources, null); - } - - /** - * Connect and compile using the javac server settings and the args. When using more advanced features, the sources_to_compile and visible_sources are - * supplied to the server and meta data is returned in package_artifacts, package_dependencies and package_pubapis. - */ - public CompilationResult compileHelper(String id, - String[] args, - Set sourcesToCompile, - Set visibleSources) { - - CompilationResult rc = new CompilationResult(-3); - - try { - PortFile portFile = JavacServer.getPortFile(this.portfile); - - int port = portFile.containsPortInfo() ? portFile.getPort() : 0; - if (port == 0) { - return new CompilationResult(ERROR_BUT_TRY_AGAIN); - } - long cookie = portFile.getCookie(); - // Acquire the localhost/127.0.0.1 address. - InetAddress addr = InetAddress.getByName(null); - SocketAddress sockaddr = new InetSocketAddress(addr, port); - Socket sock = new Socket(); - int timeoutMs = JavacServer.CONNECTION_TIMEOUT * 1000; - try { - sock.connect(sockaddr, timeoutMs); - } catch (java.net.ConnectException e) { - rc.setReturnCode(ERROR_BUT_TRY_AGAIN); - rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename() + " " + e; - return rc; - } - if (!sock.isConnected()) { - rc.setReturnCode(ERROR_BUT_TRY_AGAIN); - rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename(); - return rc; - } - - // - // Send arguments - // - BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream())); - PrintWriter sockout = new PrintWriter(sock.getOutputStream()); - - sockout.println(JavacServer.PROTOCOL_COOKIE_VERSION); - sockout.println("" + cookie); - sockout.println(JavacServer.PROTOCOL_CWD); - sockout.println(System.getProperty("user.dir")); - sockout.println(JavacServer.PROTOCOL_ID); - sockout.println(id); - sockout.println(JavacServer.PROTOCOL_ARGS); - for (String s : args) { - StringBuffer buf = new StringBuffer(); - String[] paths = s.split(File.pathSeparator); - int c = 0; - for (String path : paths) { - File f = new File(path); - if (f.isFile() || f.isDirectory()) { - buf.append(f.getAbsolutePath()); - c++; - if (c < paths.length) { - buf.append(File.pathSeparator); - } - } else { - buf = new StringBuffer(s); - break; - } - } - sockout.println(buf.toString()); - } - sockout.println(JavacServer.PROTOCOL_SOURCES_TO_COMPILE); - for (URI uri : sourcesToCompile) { - sockout.println(uri.toString()); - } - sockout.println(JavacServer.PROTOCOL_VISIBLE_SOURCES); - for (URI uri : visibleSources) { - sockout.println(uri.toString()); - } - sockout.println(JavacServer.PROTOCOL_END); - sockout.flush(); - - // - // Receive result - // - StringBuffer stdout = new StringBuffer(); - StringBuffer stderr = new StringBuffer(); - - if (!JavacServiceClient.expect(in, JavacServer.PROTOCOL_STDOUT)) { - return new CompilationResult(ERROR_FATAL); - } - // Load stdout - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_STDERR)) { - break; - } - stdout.append(l); - stdout.append('\n'); - } - // Load stderr - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS)) { - break; - } - stderr.append(l); - stderr.append('\n'); - } - // Load the package artifacts - Set lastUriSet = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastUriSet = new HashSet<>(); - rc.packageArtifacts.put(pkg, lastUriSet); - } else if (l.length() > 1 && lastUriSet != null) { - lastUriSet.add(new URI(l.substring(1))); - } - } - // Load package dependencies - Set lastPackageSet = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastPackageSet = new HashSet<>(); - rc.packageDependencies.put(pkg, lastPackageSet); - } else if (l.length() > 1 && lastPackageSet != null) { - lastPackageSet.add(l.substring(1)); - } - } - // Load package pubapis - Map tmp = new HashMap<>(); - StringBuffer lastPublicApi = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_SYSINFO)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastPublicApi = new StringBuffer(); - tmp.put(pkg, lastPublicApi); - } else if (l.length() > 1 && lastPublicApi != null) { - lastPublicApi.append(l.substring(1)); - lastPublicApi.append("\n"); - } - } - for (String p : tmp.keySet()) { - //assert (packagePublicApis.get(p) == null); - String api = tmp.get(p).toString(); - rc.packagePubapis.put(p, api); - } - // Now reading the max memory possible. - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_RETURN_CODE)) { - break; - } - if (l.startsWith("num_cores=")) { - rc.sysinfo.numCores = Integer.parseInt(l.substring(10)); - } - if (l.startsWith("max_memory=")) { - rc.sysinfo.maxMemory = Long.parseLong(l.substring(11)); - } - } - String l = in.readLine(); - if (l == null) { - rc.setReturnCode(ERROR_FATAL); - rc.stderr = "No return value from the server!"; - return rc; - } - rc.setReturnCode(Integer.parseInt(l)); - rc.stdout = stdout.toString(); - rc.stderr = stderr.toString(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - rc.stderr = sw.toString(); - } - return rc; - } - - /** - * Dispatch a compilation request to a javac server. - * - * @param args are the command line args to javac and is allowed to contain source files, @file and other command line options to javac. - * - * The generated classes, h files and other artifacts from the javac invocation are stored by the javac server to disk. - * - * @param sources_to_compile The sources to compile. - * - * @param visibleSources If visible sources has a non zero size, then visible_sources are the only files in the file system that the javac server can see! - * (Sources to compile are always visible.) The visible sources are those supplied by the (filtered) -sourcepath - * - * @param visibleClasses If visible classes for a specific root/jar has a non zero size, then visible_classes are the only class files that the javac server - * can see, in that root/jar. It maps from a classpath root or a jar file to the set of visible classes for that root/jar. - * - * The server return meta data about the build in the following parameters. - * @param package_artifacts, map from package name to set of created artifacts for that package. - * @param package_dependencies, map from package name to set of packages that it depends upon. - * @param package_pubapis, map from package name to unique string identifying its pub api. - */ - public CompilationResult useServer(String[] args, - Set sourcesToCompile, - Set visibleSources, - Map> visibleClasses) { - try { - if (portfile == null) { - CompilationResult cr = new CompilationResult(CompilationResult.ERROR_FATAL); - cr.stderr = "No portfile was specified!"; - return cr; - } - - int attempts = 0; - CompilationResult rc; - do { - PortFile port_file = JavacServer.getPortFile(portfile); - synchronized (port_file) { - port_file.lock(); - port_file.getValues(); - port_file.unlock(); - } - if (!port_file.containsPortInfo()) { - String cmd = JavacServer.fork(sjavac, port_file.getFilename(), logfile, poolsize, keepalive, System.err, stdouterrfile, background); - - if (background && !port_file.waitForValidValues()) { - // Ouch the server did not start! Lets print its stdouterrfile and the command used. - StringWriter sw = new StringWriter(); - JavacServiceClient.printFailedAttempt(cmd, stdouterrfile, new PrintWriter(sw)); - // And give up. - CompilationResult cr = new CompilationResult(ERROR_FATAL); - cr.stderr = sw.toString(); - return cr; - } - } - rc = compileHelper(id, args, sourcesToCompile, visibleSources); - // Try again until we manage to connect. Any error after that - // will cause the compilation to fail. - if (rc.returnCode == CompilationResult.ERROR_BUT_TRY_AGAIN) { - // We could not connect to the server. Try again. - attempts++; - try { - Thread.sleep(JavacServer.WAIT_BETWEEN_CONNECT_ATTEMPTS * 1000); - } catch (InterruptedException e) { - } - } - } while (rc.returnCode == ERROR_BUT_TRY_AGAIN && attempts < JavacServer.MAX_NUM_CONNECT_ATTEMPTS); - return rc; - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - CompilationResult cr = new CompilationResult(ERROR_FATAL); - cr.stderr = sw.toString(); - return cr; - } - } - - public static void printFailedAttempt(String cmd, String f, PrintWriter err) { - err.println("---- Failed to start javac server with this command -----"); - err.println(cmd); - try { - BufferedReader in = new BufferedReader(new FileReader(f)); - err.println("---- stdout/stderr output from attempt to start javac server -----"); - for (;;) { - String l = in.readLine(); - if (l == null) { - break; - } - err.println(l); - } - err.println("------------------------------------------------------------------"); - } catch (Exception e) { - err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start."); - } - } - - /** - * Expect this key on the next line read from the reader. - */ - public static boolean expect(BufferedReader in, String key) throws IOException { - String s = in.readLine(); - if (s != null && s.equals(key)) { - return true; - } - return false; - } -} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Aug 28 14:53:49 2014 -0700 @@ -33,6 +33,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.FileLockInterruptionException; +import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.Log; /** @@ -41,12 +42,12 @@ * primitives to avoid race conditions when several javac clients are started at the same. Note that file * system locking is not always supported on a all operating systems and/or file systems. * - *

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.

+ *

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. */ -class PortFile { +public class PortFile { // Port file format: // byte ordering: high byte first = big endian @@ -72,8 +73,7 @@ * Create a new portfile. * @param filename is the path to the file. */ - public PortFile(String fn) throws FileNotFoundException - { + public PortFile(String fn) throws FileNotFoundException { filename = fn; file = new File(filename); stopFile = new File(filename+".stop"); @@ -88,7 +88,7 @@ /** * Lock the port file. */ - void lock() throws IOException { + public void lock() throws IOException { lock = channel.lock(); } @@ -115,7 +115,7 @@ containsPortInfo = false; } } - } catch (Exception e) { + } catch (IOException e) { containsPortInfo = false; } } @@ -131,7 +131,7 @@ * If so, then we can acquire the tcp/ip port on localhost. */ public int getPort() { - assert(containsPortInfo); + Assert.check(containsPortInfo); return serverPort; } @@ -139,7 +139,7 @@ * If so, then we can acquire the server cookie. */ public long getCookie() { - assert(containsPortInfo); + Assert.check(containsPortInfo); return serverCookie; } @@ -147,7 +147,7 @@ * Store the values into the locked port file. */ public void setValues(int port, long cookie) throws IOException { - assert(lock != null); + Assert.check(lock != null); rwfile.seek(0); // Write the magic nr that identifes a port file. rwfile.writeInt(magicNr); @@ -192,7 +192,7 @@ * Unlock the port file. */ public void unlock() throws IOException { - assert(lock != null); + Assert.check(lock != null); lock.release(); lock = null; } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Monitors the presence of a port file and shuts down the given SjavacServer + * whenever the port file is deleted or invalidated. + * + * TODO: JDK-8046882 + * + *

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. + */ +public class PortFileMonitor { + + // Check if the portfile is gone, every 5 seconds. + private final static int CHECK_PORTFILE_INTERVAL = 5000; + + final private Timer timer = new Timer(); + final private PortFile portFile; + final private SjavacServer server; + + public PortFileMonitor(PortFile portFile, + SjavacServer server) { + this.portFile = portFile; + this.server = server; + } + + public void start() { + TimerTask shutdownCheck = new TimerTask() { + public void run() { + try { + if (!portFile.exists()) { + // Time to quit because the portfile was deleted by another + // process, probably by the makefile that is done building. + server.shutdown("Quitting because portfile was deleted!"); + } else if (portFile.markedForStop()) { + // Time to quit because another process touched the file + // server.port.stop to signal that the server should stop. + // This is necessary on some operating systems that lock + // the port file hard! + server.shutdown("Quitting because a portfile.stop file was found!"); + } else if (!portFile.stillMyValues()) { + // Time to quit because another build has started. + server.shutdown("Quitting because portfile is now owned by another javac server!"); + } + } catch (IOException e) { + e.printStackTrace(server.theLog); + server.flushLog(); + } + } + }; + + timer.schedule(shutdownCheck, 0, CHECK_PORTFILE_INTERVAL); + } + + public void shutdown() { + timer.cancel(); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.Socket; +import java.net.URI; +import java.util.List; +import java.util.Set; + +import com.sun.tools.sjavac.Log; + +/** + * A RequestHandler handles requests performed over a socket. Specifically it + * - Reads the command string specifying which method is to be invoked + * - Reads the appropriate arguments + * - Delegates the actual invocation to the given sjavac implementation + * - Writes the result back to the socket output stream + * + * None of the work performed by this class is really bound by the CPU. It + * should be completely fine to have a large number of RequestHandlers active. + * To limit the number of concurrent compilations, use PooledSjavac. + * + *

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. + */ +public class RequestHandler implements Runnable { + + private final Socket socket; + private final Sjavac sjavac; + + public RequestHandler(Socket socket, Sjavac sjavac) { + this.socket = socket; + this.sjavac = sjavac; + } + + @Override + public void run() { + try (ObjectOutputStream oout = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream oin = new ObjectInputStream(socket.getInputStream())) { + String id = (String) oin.readObject(); + String cmd = (String) oin.readObject(); + Log.info("Handling request, id: " + id + " cmd: " + cmd); + switch (cmd) { + case SjavacServer.CMD_SYS_INFO: handleSysInfoRequest(oin, oout); break; + case SjavacServer.CMD_COMPILE: handleCompileRequest(oin, oout); break; + default: Log.error("Unknown command: " + cmd); + } + } catch (Exception ex) { + // Not much to be done at this point. The client side request + // code will most likely throw an IOException and the + // compilation will fail. + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + Log.error(sw.toString()); + } + } + + private void handleSysInfoRequest(ObjectInputStream oin, + ObjectOutputStream oout) throws IOException { + oout.writeObject(sjavac.getSysInfo()); + oout.flush(); + } + + @SuppressWarnings("unchecked") + private void handleCompileRequest(ObjectInputStream oin, + ObjectOutputStream oout) throws IOException { + try { + // Read request arguments + String protocolId = (String) oin.readObject(); + String invocationId = (String) oin.readObject(); + String[] args = (String[]) oin.readObject(); + List explicitSources = (List) oin.readObject(); + Set sourcesToCompile = (Set) oin.readObject(); + Set visibleSources = (Set) oin.readObject(); + + // Perform compilation + CompilationResult cr = sjavac.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + // Write request response + oout.writeObject(cr); + oout.flush(); + } catch (ClassNotFoundException cnfe) { + throw new IOException(cnfe); + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Set; + +/** + * Interface of the SjavacImpl, the sjavac client and all wrappers such as + * PooledSjavac etc. + * + *

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. + */ +public interface Sjavac { + + SysInfo getSysInfo(); + + CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources); + + void shutdown(); + String serverSettings(); +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.sun.tools.sjavac.ProblemException; +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.comp.SjavacImpl; +import com.sun.tools.sjavac.comp.PooledSjavac; + +/** + * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. + * + *

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. + */ +public class SjavacServer implements Terminable { + + // Used in protocol to indicate which method to invoke + public final static String CMD_COMPILE = "compile"; + public final static String CMD_SYS_INFO = "sys-info"; + + final private String portfilename; + final private String logfile; + final private String stdouterrfile; + final private int poolsize; + final private int keepalive; + final private PrintStream err; + + // The secret cookie shared between server and client through the port file. + // Used to prevent clients from believing that they are communicating with + // an old server when a new server has started and reused the same port as + // an old server. + private final long myCookie; + + // Accumulated build time, not counting idle time, used for logging purposes + private long totalBuildTime; + + // The javac server specific log file. + PrintWriter theLog; + + // The sjavac implementation to delegate requests to + Sjavac sjavac; + + private ServerSocket serverSocket; + + private PortFile portFile; + private PortFileMonitor portFileMonitor; + + // Set to false break accept loop + final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); + + // For the client, all port files fetched, one per started javac server. + // Though usually only one javac server is started by a client. + private static Map allPortFiles; + private static Map maxServerMemory; + + public SjavacServer(String settings, PrintStream err) throws FileNotFoundException { + // Extract options. TODO: Change to proper constructor args + portfilename = Util.extractStringOption("portfile", settings); + logfile = Util.extractStringOption("logfile", settings); + stdouterrfile = Util.extractStringOption("stdouterrfile", settings); + keepalive = Util.extractIntOption("keepalive", settings, 120); + poolsize = Util.extractIntOption("poolsize", settings, + Runtime.getRuntime().availableProcessors()); + this.err = err; + + myCookie = new Random().nextLong(); + theLog = new PrintWriter(logfile); + } + + + /** + * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. + */ + public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { + if (allPortFiles == null) { + allPortFiles = new HashMap<>(); + } + PortFile pf = allPortFiles.get(filename); + + // Port file known. Does it still exist? + if (pf != null) { + try { + if (!pf.exists()) + pf = null; + } catch (IOException ioex) { + ioex.printStackTrace(); + } + } + + if (pf == null) { + pf = new PortFile(filename); + allPortFiles.put(filename, pf); + } + return pf; + } + + /** + * Get the cookie used for this server. + */ + long getCookie() { + return myCookie; + } + + /** + * Get the port used for this server. + */ + int getPort() { + return serverSocket.getLocalPort(); + } + + /** + * Sum up the total build time for this javac server. + */ + public void addBuildTime(long inc) { + totalBuildTime += inc; + } + + /** + * Log this message. + */ + public void log(String msg) { + if (theLog != null) { + theLog.println(msg); + } else { + System.err.println(msg); + } + } + + /** + * Make sure the log is flushed. + */ + public void flushLog() { + if (theLog != null) { + theLog.flush(); + } + } + + /** + * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" + * is sent as the settings parameter. Returns 0 on success, -1 on failure. + */ + public int startServer() throws IOException { + long serverStart = System.currentTimeMillis(); + + // The port file is locked and the server port and cookie is written into it. + portFile = getPortFile(portfilename); + + synchronized (portFile) { + portFile.lock(); + portFile.getValues(); + if (portFile.containsPortInfo()) { + err.println("Javac server not started because portfile exists!"); + portFile.unlock(); + return -1; + } + + // .-----------. .--------. .------. + // socket -->| IdleReset |-->| Pooled |-->| Impl |--> javac + // '-----------' '--------' '------' + sjavac = new SjavacImpl(); + sjavac = new PooledSjavac(sjavac, poolsize); + sjavac = new IdleResetSjavac(sjavac, + this, + keepalive * 1000); + + serverSocket = new ServerSocket(); + InetAddress localhost = InetAddress.getByName(null); + serverSocket.bind(new InetSocketAddress(localhost, 0)); + + // At this point the server accepts connections, so it is now safe + // to publish the port / cookie information + portFile.setValues(getPort(), getCookie()); + portFile.unlock(); + } + + portFileMonitor = new PortFileMonitor(portFile, this); + portFileMonitor.start(); + + log("Sjavac server started. Accepting connections..."); + log(" port: " + getPort()); + log(" time: " + new java.util.Date()); + log(" poolsize: " + poolsize); + flushLog(); + + keepAcceptingRequests.set(true); + do { + try { + Socket socket = serverSocket.accept(); + new Thread(new RequestHandler(socket, sjavac)).start(); + } catch (SocketException se) { + // Caused by serverSocket.close() and indicates shutdown + } + } while (keepAcceptingRequests.get()); + + log("Shutting down."); + + // No more connections accepted. If any client managed to connect after + // the accept() was interrupted but before the server socket is closed + // here, any attempt to read or write to the socket will result in an + // IOException on the client side. + + long realTime = System.currentTimeMillis() - serverStart; + log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); + flushLog(); + + // Shut down + sjavac.shutdown(); + + return 0; + } + + /** + * Fork a background process. Returns the command line used that can be printed if something failed. + */ + public static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive, + final PrintStream err, String stdouterrfile, boolean background) + throws IOException, ProblemException { + if (stdouterrfile != null && stdouterrfile.trim().equals("")) { + stdouterrfile = null; + } + final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive; + + if (background) { + sjavac += "%20" + startserver; + sjavac = sjavac.replaceAll("%20", " "); + sjavac = sjavac.replaceAll("%2C", ","); + // If the java/sh/cmd launcher fails the failure will be captured by stdouterr because of the redirection here. + String[] cmd = {"/bin/sh", "-c", sjavac + " >> " + stdouterrfile + " 2>&1"}; + if (!(new File("/bin/sh")).canExecute()) { + ArrayList wincmd = new ArrayList<>(); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add("start"); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add(sjavac + " >> " + stdouterrfile + " 2>&1"); + cmd = wincmd.toArray(new String[wincmd.size()]); + } + Process pp = null; + try { + pp = Runtime.getRuntime().exec(cmd); + } catch (Exception e) { + e.printStackTrace(err); + e.printStackTrace(new PrintWriter(stdouterrfile)); + } + StringBuilder rs = new StringBuilder(); + for (String s : cmd) { + rs.append(s + " "); + } + return rs.toString(); + } + + // Do not spawn a background server, instead run it within the same JVM. + Thread t = new Thread() { + @Override + public void run() { + try { + SjavacServer server = new SjavacServer(startserver, err); + server.startServer(); + } catch (Throwable t) { + t.printStackTrace(err); + } + } + }; + t.setDaemon(true); + t.start(); + return ""; + } + + @Override + public void shutdown(String quitMsg) { + if (!keepAcceptingRequests.compareAndSet(false, true)) { + // Already stopped, no need to shut down again + return; + } + + log("Quitting: " + quitMsg); + flushLog(); + + portFileMonitor.shutdown(); // No longer any need to monitor port file + + // Unpublish port before shutting down socket to minimize the number of + // failed connection attempts + try { + portFile.delete(); + } catch (IOException e) { + e.printStackTrace(theLog); + } + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(theLog); + } + } + + public static void cleanup(String... args) { + String settings = Util.findServerSettings(args); + if (settings == null) return; + String portfile = Util.extractStringOption("portfile", settings); + String background = Util.extractStringOption("background", settings); + if (background != null && background.equals("false")) { + // If the server runs within this jvm, then delete the portfile, + // since this jvm is about to exit soon. + File f = new File(portfile); + f.delete(); + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,18 @@ */ package com.sun.tools.sjavac.server; -public class SysInfo { +import java.io.Serializable; + +/** + *

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. + */ +public class SysInfo implements Serializable { + + static final long serialVersionUID = -3096346807579L; + public int numCores; public long maxMemory; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.sjavac.server; + +/** + *

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. + */ +public interface Terminable { + void shutdown(String quitMsg); +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/com/sun/javadoc/lib/JavadocTester.java --- a/langtools/test/com/sun/javadoc/lib/JavadocTester.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/com/sun/javadoc/lib/JavadocTester.java Thu Aug 28 14:53:49 2014 -0700 @@ -38,6 +38,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.file.Files; +import java.util.Arrays; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -290,6 +291,7 @@ break; } } + out.println("args: " + Arrays.toString(args)); // log.setOutDir(outputDir); outputDirectoryCheck.check(outputDir); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java --- a/langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 4908512 5024825 4957203 4993280 4996963 6174696 6177059 7041249 * @summary Make sure apt is removed and doesn't come back - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckAptIsRemovedTest */ @@ -34,7 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/apt/Basics/apt.sh +// Original test: test/tools/apt/Basics/apt.sh public class CheckAptIsRemovedTest { //I think this class can be let with the imports only and that should be enough for as test's purpose private static final String NullAPFSrc = @@ -77,20 +77,18 @@ Path aptLin = Paths.get(testJDK, "bin", "apt"); Path aptWin = Paths.get(testJDK, "bin", "apt.exe"); -// if [ -f "${TESTJAVA}/bin/apt" -o -f "${TESTJAVA}/bin/apt.exe" ];then if (Files.exists(aptLin) || Files.exists(aptWin)) { throw new AssertionError("apt executable should not exist"); } -// JAVAC="${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} -source 1.5 -sourcepath ${TESTSRC} -classpath ${TESTJAVA}/lib/tools.jar -d . " -// $JAVAC ${TESTSRC}/NullAPF.java Path classpath = Paths.get(testJDK, "lib", "tools.jar"); - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-sourcepath", ".", - "-classpath", classpath.toString()) - .setSources(NullAPFSrc); - ToolBox.javac(javacArgs); + ToolBox tb = new ToolBox(); + tb.new JavacTask() + .classpath(classpath.toString()) // TODO: add overload + .sourcepath(".") + .sources(NullAPFSrc) + .run(ToolBox.Expect.FAIL) + .writeAll(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java --- a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,17 @@ * @test * @bug 4846262 * @summary check that javac operates correctly in EBCDIC locale - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckEBCDICLocaleTest */ import java.io.File; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.List; public class CheckEBCDICLocaleTest { @@ -58,39 +60,32 @@ } public void test() throws Exception { - String native2asciiBinary = Paths.get( - System.getProperty("test.jdk"),"bin", "native2ascii").toString(); - - ToolBox.createJavaFileFromSource(TestSrc); - Files.createDirectory(Paths.get("output")); + ToolBox tb = new ToolBox(); + Path native2asciiBinary = tb.getJDKTool("native2ascii"); - ToolBox.AnyToolArgs nativeCmdParams = - new ToolBox.AnyToolArgs() - .appendArgs(native2asciiBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-reverse", "-encoding", "IBM1047", "Test.java", - "output/Test.java"); - ToolBox.executeCommand(nativeCmdParams); + tb.writeFile("Test.java", TestSrc); + tb.createDirectories("output"); + + tb.new ExecTask(native2asciiBinary) + .args("-reverse", "-encoding", "IBM1047", "Test.java", "output/Test.java") + .run(); - ToolBox.AnyToolArgs javacParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-J-Duser.language=en", - "-J-Duser.region=US", "-J-Dfile.encoding=IBM1047", - "output/Test.java") - .setErrOutput(new File("Test.tmp")); - ToolBox.executeCommand(javacParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .redirect(ToolBox.OutputKind.STDERR, "Test.tmp") + .options("-J-Duser.language=en", + "-J-Duser.region=US", + "-J-Dfile.encoding=IBM1047") + .files("output/Test.java") + .run(ToolBox.Expect.FAIL); - nativeCmdParams = new ToolBox.AnyToolArgs() - .appendArgs(native2asciiBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-encoding", "IBM1047", "Test.tmp", "Test.out"); - ToolBox.executeCommand(nativeCmdParams); + tb.new ExecTask(native2asciiBinary) + .args("-encoding", "IBM1047", "Test.tmp", "Test.out") + .run(); - String goldenFile = String.format(TestOutTemplate, File.separator); - ToolBox.compareLines(Paths.get("Test.out"), - Arrays.asList(goldenFile.split("\n")), null, true); + List expectLines = Arrays.asList( + String.format(TestOutTemplate, File.separator).split("\n")); + List actualLines = Files.readAllLines(Paths.get("Test.out")); + tb.checkEqual(expectLines, actualLines); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java --- a/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 6302184 6350124 6357979 * @summary javac hidden options that generate source should use the given * encoding, if available - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile -encoding iso-8859-1 -XD-printsource T6302184.java * @run main HiddenOptionsShouldUseGivenEncodingTest @@ -34,16 +34,19 @@ import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; -//original test: test/tools/javac/6302184/T6302184.sh +// Original test: test/tools/javac/6302184/T6302184.sh public class HiddenOptionsShouldUseGivenEncodingTest { public static void main(String[] args) throws Exception { -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -cp ${TC} -encoding iso-8859-1 -XD-printsource ${TS}${FS}T6302184.java 2>&1 -//diff ${DIFFOPTS} -c ${TC}${FS}T6302184.java ${TS}${FS}T6302184.out - Path path1 = Paths.get(System.getProperty("test.classes"), "T6302184.java"); - Path path2 = Paths.get(System.getProperty("test.src"), "T6302184.out"); - ToolBox.compareLines(path1, path2, "iso-8859-1"); + ToolBox tb = new ToolBox(); + String encoding = "iso-8859-1"; + Path path1 = Paths.get(ToolBox.testClasses, "T6302184.java"); + List file1 = tb.readAllLines(path1, encoding); + Path path2 = Paths.get(ToolBox.testSrc, "T6302184.out"); + List file2 = tb.readAllLines(path2, encoding); + tb.checkEqual(file1, file2); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/AnonymousSubclassTest.java --- a/langtools/test/tools/javac/AnonymousSubclassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/AnonymousSubclassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,19 +25,18 @@ * @test * @bug 8023945 * @summary javac wrongly allows a subclass of an anonymous class - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AnonymousSubclassTest */ -import java.util.ArrayList; -import java.io.IOException; - public class AnonymousSubclassTest { public static void main(String... args) throws Exception { new AnonymousSubclassTest().run(); } + ToolBox tb = new ToolBox(); + // To trigger the error we want, first we need to compile // a class with an anonymous inner class: Foo$1. final String foo = @@ -65,20 +64,21 @@ "}"; void compOk(String code) throws Exception { - ToolBox.javac(new ToolBox.JavaToolArgs().setSources(code)); + tb.new JavacTask() + .sources(code) + .run(); } void compFail(String code) throws Exception { - ArrayList errors = new ArrayList<>(); - ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs(); - args.setSources(code) - .appendArgs("-cp", ".", "-XDrawDiagnostics") - .set(ToolBox.Expect.FAIL) - .setErrOutput(errors); - ToolBox.javac(args); + String errs = tb.new JavacTask() + .sources(code) + .classpath(".") + .options("-XDrawDiagnostics") + .run(ToolBox.Expect.FAIL) + .writeAll() + .getOutput(ToolBox.OutputKind.DIRECT); - if (!errors.get(0).contains("cant.inherit.from.anon")) { - System.out.println(errors.get(0)); + if (!errs.contains("cant.inherit.from.anon")) { throw new Exception("test failed"); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/ClassPathTest/ClassPathTest.java --- a/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,14 @@ * @test * @bug 4241229 4785453 * @summary Test -classpath option and classpath defaults. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ClassPathTest */ import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -//original test: test/tools/javac/ClassPathTest/ClassPathTest.sh +// Original test: test/tools/javac/ClassPathTest/ClassPathTest.sh public class ClassPathTest { private static final String ClassPathTest1Src = @@ -70,12 +65,12 @@ "package pkg;\n" + "public class ClassPathTestAux3 {}"; - ProcessBuilder pb = null; - public static void main(String[] args) throws Exception { new ClassPathTest().test(); } + ToolBox tb = new ToolBox(); + public void test() throws Exception { createOutputDirAndSourceFiles(); checkCompileCommands(); @@ -83,14 +78,16 @@ void createOutputDirAndSourceFiles() throws Exception { //dirs and files creation - ToolBox.createJavaFileFromSource(ClassPathTest1Src); - ToolBox.createJavaFileFromSource(ClassPathTest2Src); - ToolBox.createJavaFileFromSource(ClassPathTest3Src); - ToolBox.createJavaFileFromSource(Paths.get("foo"), + tb.writeJavaFiles(Paths.get("."), + ClassPathTest1Src, + ClassPathTest2Src, + ClassPathTest3Src); + tb.writeJavaFiles(Paths.get("foo"), fooPkgClassPathTestAux1Src); - ToolBox.createJavaFileFromSource(Paths.get("bar"), + tb.writeJavaFiles(Paths.get("bar"), barPkgClassPathTestAux2Src); - ToolBox.createJavaFileFromSource(pkgClassPathTestAux3Src); + tb.writeJavaFiles(Paths.get("."), + pkgClassPathTestAux3Src); } void checkCompileCommands() throws Exception { @@ -99,80 +96,55 @@ // automatically but this is not happening when called using ProcessBuilder // testJavac success ClassPathTest3.java - List mainArgs = new ArrayList<>(); - mainArgs.add(ToolBox.javacBinary.toString()); - if (ToolBox.testToolVMOpts != null) { - mainArgs.addAll(ToolBox.testToolVMOpts); - } - - List commonArgs = new ArrayList<>(); - commonArgs.addAll(mainArgs); - commonArgs.addAll(Arrays.asList("-cp", ".")); - - ToolBox.AnyToolArgs successParams = new ToolBox.AnyToolArgs() - .appendArgs(commonArgs) - .appendArgs("ClassPathTest3.java"); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .classpath(".") + .files("ClassPathTest3.java") + .run(); // testJavac failure ClassPathTest1.java - ToolBox.AnyToolArgs failParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest1.java"); - ToolBox.executeCommand(failParams); - -// This is done inside the executeCommand method -// CLASSPATH=bar; export CLASSPATH - - Map extVars = new TreeMap<>(); - extVars.put("CLASSPATH", "bar"); + tb.new JavacTask(ToolBox.Mode.EXEC) + .classpath(".") + .files("ClassPathTest1.java") + .run(ToolBox.Expect.FAIL); // testJavac success ClassPathTest2.java - successParams = new ToolBox.AnyToolArgs() - .appendArgs(mainArgs) - .appendArgs("ClassPathTest2.java") - .set(extVars); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest2.java") + .run(); // testJavac failure ClassPathTest1.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(mainArgs) - .appendArgs("ClassPathTest1.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest1.java") + .run(ToolBox.Expect.FAIL); // testJavac failure ClassPathTest3.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(mainArgs) - .appendArgs("ClassPathTest3.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest3.java") + .run(ToolBox.Expect.FAIL); // testJavac success -classpath foo ClassPathTest1.java - - commonArgs.clear(); - commonArgs.addAll(mainArgs); - commonArgs.addAll(Arrays.asList("-cp", "foo")); - - successParams = new ToolBox.AnyToolArgs() - .appendArgs(commonArgs) - .appendArgs("ClassPathTest1.java") - .set(extVars); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest1.java") + .run(); // testJavac failure -classpath foo ClassPathTest2.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest2.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest2.java") + .run(ToolBox.Expect.FAIL); // testJavac failure -classpath foo ClassPathTest3.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest3.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest3.java") + .run(ToolBox.Expect.FAIL); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/ConstFoldTest.java --- a/langtools/test/tools/javac/ConstFoldTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/ConstFoldTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8025505 * @summary Constant folding deficiency - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ConstFoldTest */ @@ -45,23 +45,23 @@ int x; if (1 != 2) x=1; else x=0; if (1 == 2) x=1; else x=0; - if ("" != null) x=1; else x=0; - if ("" == null) x=1; else x=0; + if ("" != null) x=1; else x=0; + if ("" == null) x=1; else x=0; if (null == null) x=1; else x=0; if (null != null) x=1; else x=0; x = 1 != 2 ? 1 : 0; x = 1 == 2 ? 1 : 0; - x = "" != null ? 1 : 0; - x = "" == null ? 1 : 0; + x = "" != null ? 1 : 0; + x = "" == null ? 1 : 0; x = null == null ? 1 : 0; x = null != null ? 1 : 0; boolean b; b = 1 != 2 && true; b = 1 == 2 || true; - b = ("" != null) && true; - b = ("" == null) || true; + b = ("" != null) && true; + b = ("" == null) || true; b = (null == null) && true; b = (null != null) || true; } @@ -72,11 +72,17 @@ final String regex = "\\sif(?:null|nonnull|eq|ne){1}\\s"; void run() throws Exception { + ToolBox tb = new ToolBox(); + URL url = ConstFoldTest.class.getResource("ConstFoldTest$CFTest.class"); - String result = ToolBox.javap(new ToolBox.JavaToolArgs().setAllArgs("-c", url.getFile())); - System.out.println(result); + List result = tb.new JavapTask() + .options("-c") + .classes(url.getFile()) + .run() + .write(ToolBox.OutputKind.DIRECT) + .getOutputLines(ToolBox.OutputKind.DIRECT); - List bad_codes = ToolBox.grep(regex, result, "\n"); + List bad_codes = tb.grep(regex, result); if (!bad_codes.isEmpty()) { for (String code : bad_codes) System.out.println("Bad OpCode Found: " + code); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/ExtDirs/ExtDirTest.java --- a/langtools/test/tools/javac/ExtDirs/ExtDirTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/ExtDirs/ExtDirTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,14 @@ * @test * @bug 4204897 4256097 4785453 4863609 * @summary Test that '.jar' files in -extdirs are found. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ExtDirTest */ import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -//original test: test/tools/javac/ExtDirs/ExtDirs.sh +// Original test: test/tools/javac/ExtDirs/ExtDirs.sh public class ExtDirTest { private static final String ExtDirTestClass1Src = @@ -100,72 +96,73 @@ "SHA-Digest: ILJOhwHg5US+yuw1Sc1d+Avu628=\n" + "MD5-Digest: j8wnz8wneEcuJ/gjXBBQNA==\n"; - List ouputDirParam = Arrays.asList("-d", "."); - public static void main(String args[]) throws Exception { new ExtDirTest().run(); } + private final ToolBox tb = new ToolBox(); + void run() throws Exception { createJars(); compileWithExtDirs(); } void createJars() throws Exception { - sun.tools.jar.Main jarGenerator = - new sun.tools.jar.Main(System.out, System.err, "jar"); + tb.new JavacTask() + .outdir(".") + .sources(ExtDirTestClass1Src) + .run(); - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setOptions(ouputDirParam) - .setSources(ExtDirTestClass1Src); - ToolBox.javac(javacParams); + tb.new JarTask("pkg1.jar") + .manifest(jar1Manifest) + .files("pkg1/ExtDirTestClass1.class") + .run(); - ToolBox.writeFile(Paths.get("pkg1", "MANIFEST.MF"), jar1Manifest); - jarGenerator.run(new String[] {"cfm", "pkg1.jar", "pkg1/MANIFEST.MF", - "pkg1/ExtDirTestClass1.class"}); - - javacParams.setSources(ExtDirTestClass2Src); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(ExtDirTestClass2Src) + .run(); - ToolBox.writeFile(Paths.get("pkg2", "MANIFEST.MF"), jar2Manifest); - jarGenerator.run(new String[] {"cfm", "pkg2.jar", "pkg2/MANIFEST.MF", - "pkg2/ExtDirTestClass2.class"}); - - ToolBox.copyFile(Paths.get("ext1", "pkg1.jar"), Paths.get("pkg1.jar")); - ToolBox.copyFile(Paths.get("ext2", "pkg2.jar"), Paths.get("pkg2.jar")); - ToolBox.copyFile(Paths.get("ext3", "pkg1.jar"), Paths.get("pkg1.jar")); - ToolBox.copyFile(Paths.get("ext3", "pkg2.jar"), Paths.get("pkg2.jar")); + tb.new JarTask("pkg2.jar") + .manifest(jar2Manifest) + .files("pkg2/ExtDirTestClass2.class") + .run(); - Files.delete(Paths.get("pkg1.jar")); - Files.delete(Paths.get("pkg2.jar")); + tb.createDirectories("ext1", "ext2", "ext3"); + tb.copyFile("pkg1.jar", "ext1"); + tb.copyFile("pkg2.jar", "ext2"); + tb.copyFile("pkg1.jar", "ext3"); + tb.copyFile("pkg2.jar", "ext3"); - Files.delete(Paths.get("pkg1", "ExtDirTestClass1.class")); - Files.delete(Paths.get("pkg1", "MANIFEST.MF")); - Files.delete(Paths.get("pkg1")); - Files.delete(Paths.get("pkg2", "ExtDirTestClass2.class")); - Files.delete(Paths.get("pkg2", "MANIFEST.MF")); - Files.delete(Paths.get("pkg2")); + tb.deleteFiles( + "pkg1.jar", + "pkg2.jar", + "pkg1/ExtDirTestClass1.class", + "pkg1", + "pkg2/ExtDirTestClass2.class", + "pkg2" + ); } void compileWithExtDirs() throws Exception { - -//javac -extdirs ext1 ExtDirTest_1.java - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs() - .setOptions("-d", ".", "-extdirs", "ext1") - .setSources(ExtDirTest_1Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext1") + .sources(ExtDirTest_1Src) + .run() + .writeAll(); -//javac -extdirs ext1:ext2 ExtDirTest_2.java - params.setOptions("-d", ".", "-extdirs", "ext1" + File.pathSeparator + "ext2") - .setSources(ExtDirTest_2Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext1" + File.pathSeparator + "ext2") + .sources(ExtDirTest_2Src) + .run(); -//javac -extdirs ext3 ExtDirTest_3.java - params.setOptions("-d", ".", "-extdirs", "ext3") - .setSources(ExtDirTest_3Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext3") + .sources(ExtDirTest_3Src) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java --- a/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8034924 * @summary Incorrect inheritance of inaccessible static method - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main IncorrectInheritanceTest */ @@ -59,10 +59,11 @@ } public void test() throws Exception { - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setSources(ASrc, BSrc, CSrc); - ToolBox.javac(javacParams); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(ASrc, BSrc, CSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java --- a/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,25 +26,26 @@ * @bug 4509051 4785453 * @summary javac sourcefiles should catch Exception, when sourcefiles * doesn't exist. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main MissingIncludeTest */ -//original test: test/tools/javac/MissingInclude.sh +// Original test: test/tools/javac/MissingInclude.sh public class MissingIncludeTest { - private static final String MissingIncludeSrc = - "class MissingInclude {}"; + private static final String MissingIncludeFile = "MissingInclude.java"; + private static final String MissingIncludeSrc = "class MissingInclude {}"; public static void main(String[] args) throws Exception { - ToolBox.createJavaFileFromSource(MissingIncludeSrc); + ToolBox tb = new ToolBox(); + + tb.writeFile(MissingIncludeFile, MissingIncludeSrc); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} @/nonexistent_file MissingInclude.java 2> ${TMP1} - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setAllArgs("@/nonexistent_file", "MissingInclude.java"); - ToolBox.javac(params); + tb.new JavacTask(ToolBox.Mode.CMDLINE) + .options("@/nonexistent_file") + .files(MissingIncludeFile) + .run(ToolBox.Expect.FAIL); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/Paths/AbsolutePathTest.java --- a/langtools/test/tools/javac/Paths/AbsolutePathTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/Paths/AbsolutePathTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -23,36 +23,49 @@ /* * @test + * @ignore 8055500 [javac] fix for 8030046 is incorrect * @bug 8030046 * @summary javac incorrectly handles absolute paths in manifest classpath * @author govereau - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AbsolutePathTest */ import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; public class AbsolutePathTest { public static void main(String... cmdline) throws Exception { + ToolBox tb = new ToolBox(); + // compile test.Test - ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs(); - args.appendArgs("-d", "."); // this is needed to get the classfiles in test - ToolBox.javac(args.setSources("package test; public class Test{}")); + tb.new JavacTask() + .outdir(".") // this is needed to get the classfiles in test + .sources("package test; public class Test{}") + .run(); // build test.jar containing test.Test // we need the jars in a directory different from the working - // directory to trigger the bug. I will reuse test/ - ToolBox.jar("cf", "test/test.jar", "test/Test.class"); + // directory to trigger the bug. + Files.createDirectory(Paths.get("jars")); + tb.new JarTask("jars/test.jar") + .files("test/Test.class") + .run(); - // build second jar in test directory using + // build second jar in jars directory using // an absolute path reference to the first jar - String path = new File("test/test.jar").getAbsolutePath(); - ToolBox.mkManifestWithClassPath(null, path); - ToolBox.jar("cfm", "test/test2.jar", "MANIFEST.MF"); + tb.new JarTask("jars/test2.jar") + .classpath(new File("jars/test.jar").getAbsolutePath()) + .run(); // this should not fail - args.appendArgs("-cp", "."); - ToolBox.javac(args.setSources("import test.Test; class Test2 {}")); + tb.new JavacTask() + .outdir(".") + .classpath("jars/test2.jar") + .sources("import test.Test; class Test2 {}") + .run() + .writeAll(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java --- a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,13 @@ * @test * @bug 4087314 4800342 4307565 * @summary Verify allowed access to protected class from another package - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ProtectedInnerClassesTest */ -//original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh -//and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java +// Original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh +// and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java public class ProtectedInnerClassesTest { private static final String protectedInnerClass1Src = @@ -74,45 +74,36 @@ new ProtectedInnerClassesTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileAndExecute(); compileOnly(); } void compileAndExecute() throws Exception { -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d "${TESTCLASSES}" "${TESTSRC}${FS}p1${FS}ProtectedInnerClass1.java" "${TESTSRC}${FS}p2${FS}ProtectedInnerClass2.java" - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", ".") - .setSources(protectedInnerClass1Src, protectedInnerClass2Src); - - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass1Src, protectedInnerClass2Src) + .run(); -//"${TESTJAVA}${FS}bin${FS}java" ${TESTVMOPTS} -classpath "${CLASSPATH}${PS}${TESTCLASSES}" p2.ProtectedInnerClass2 - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs("-classpath", System.getProperty("user.dir"), - "p2.ProtectedInnerClass2"); - ToolBox.executeCommand(javaParams); + tb.new JavaTask() + .classpath(System.getProperty("user.dir")) + .className("p2.ProtectedInnerClass2") + .run(); } //from test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java void compileOnly() throws Exception { -//@run compile p1/ProtectedInnerClass1.java - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", ".") - .setSources(protectedInnerClass1Src); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass1Src) + .run(); - ToolBox.javac(javacParams); - -//@run compile/fail p2/ProtectedInnerClass3.java - javacParams = new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .appendArgs("-d", ".") - .setSources(protectedInnerClass3Src); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass3Src) + .run(ToolBox.Expect.FAIL); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T5090006/AssertionFailureTest.java --- a/langtools/test/tools/javac/T5090006/AssertionFailureTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T5090006/AssertionFailureTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 5090006 * @summary javac fails with assertion error - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AssertionFailureTest */ @@ -33,7 +33,7 @@ import java.io.File; import java.nio.file.Paths; -//original test: test/tools/javac/T5090006/compiler.sh +// Original test: test/tools/javac/T5090006/compiler.sh public class AssertionFailureTest { private static final String testSrc = @@ -54,16 +54,14 @@ "}"; public static void main(String args[]) throws Exception { - String classpath = Paths.get(System.getProperty("test.src"), "broken.jar") - .toString(); - classpath = new StringBuilder(classpath) - .append(File.pathSeparator).append(".").toString(); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -verbose -d "${TESTCLASSES}" -cp "${TESTSRC}${FS}broken.jar" "${TESTSRC}${FS}$1" - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs() - .setOptions("-cp", classpath) - .setSources(testSrc); - ToolBox.javac(params); + ToolBox tb = new ToolBox(); + String classpath = Paths.get(tb.testSrc, "broken.jar") + + File.pathSeparator + + "."; + tb.new JavacTask() + .classpath(classpath) + .sources(testSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java --- a/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 6970173 * @summary Debug pointer at bad position - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main DebugPointerAtBadPositionTest */ @@ -75,9 +75,10 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + ToolBox tb = new ToolBox(); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind) throws Exception { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java --- a/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 7008643 * @summary inlined finally clauses confuse debuggers - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main InlinedFinallyConfuseDebuggersTest */ @@ -73,6 +73,8 @@ new InlinedFinallyConfuseDebuggersTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileTestClass(); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), @@ -80,9 +82,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind) throws Exception { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java --- a/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ * @test * @bug 8009640 * @summary -profile does not work when -bootclasspath specified - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckRejectProfileBCPOptionsIfUsedTogetherTest */ import com.sun.tools.javac.util.Assert; -import java.util.ArrayList; -import java.util.List; +import java.nio.file.Paths; public class CheckRejectProfileBCPOptionsIfUsedTogetherTest { @@ -44,21 +43,16 @@ "}"; public static void main(String args[]) throws Exception { - List errOutput = new ArrayList<>(); - String testJDK = ToolBox.jdkUnderTest; - ToolBox.createJavaFileFromSource(TestSrc); + ToolBox tb = new ToolBox(); - ToolBox.AnyToolArgs javacParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-profile", "compact1", "-bootclasspath", - testJDK + "/jre/lib/rt.jar", "Test.java") - .setErrOutput(errOutput); + ToolBox.Result result = tb.new JavacTask(ToolBox.Mode.CMDLINE) + .options("-profile", "compact1", + "-bootclasspath", Paths.get(ToolBox.testJDK, "jre/lib/rt.jar").toString()) + .sources(TestSrc) + .run(ToolBox.Expect.FAIL); - ToolBox.executeCommand(javacParams); - - Assert.check(errOutput.get(0).startsWith( + String out = result.getOutput(ToolBox.OutputKind.DIRECT); + Assert.check(out.startsWith( "javac: profile and bootclasspath options cannot be used together"), "Incorrect javac error output"); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java --- a/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @test * @bug 8010659 * @summary Javac Crashes while building OpenJFX - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CompilerCrashWhenMixingBinariesAndSourcesTest */ @@ -48,19 +48,18 @@ " Object m(int i) {return null;}\n" + "}"; - public static void main (String[] args) throws Exception{ - ToolBox.JavaToolArgs javacParams = new ToolBox.JavaToolArgs() - .setSources(ASource, BSource, CSource, DSource); - ToolBox.javac(javacParams); + public static void main(String[] args) throws Exception { + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(ASource, BSource, CSource, DSource) + .run(); - ToolBox.rm("A.class"); - ToolBox.rm("A$1.class"); - ToolBox.rm("C.class"); - ToolBox.rm("D.class"); + tb.deleteFiles("A.class", "A$1.class", "C.class", "D.class"); - javacParams = new ToolBox.JavaToolArgs() - .setOptions("-cp", ".") - .setSources(ASource, CSource, DSource); - ToolBox.javac(javacParams); + tb.new JavacTask() + .classpath(".") + .sources(ASource, CSource, DSource) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java --- a/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @test * @bug 8013394 * @summary compile of iterator use fails with error "defined in an inaccessible class or interface" - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CompileErrorWithIteratorTest */ @@ -71,15 +71,16 @@ new CompileErrorWithIteratorTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compile(); } void compile() throws Exception { - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setSources(TestCollectionSrc, TestSrc); - ToolBox.javac(javacParams); + tb.new JavacTask() + .sources(TestCollectionSrc, TestSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java --- a/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @test * @bug 8019486 8026861 8027142 * @summary javac, generates erroneous LVT for a test case with lambda code - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main WrongLNTForLambdaTest */ @@ -125,6 +125,8 @@ new WrongLNTForLambdaTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileTestClass(); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), @@ -146,9 +148,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind, int[][] expectedLNT) throws Exception { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java --- a/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,11 @@ * @test * @bug 8022162 * @summary Incorrect signature determination for certain inner class generics - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main IncorrectSignatureDeterminationForInnerClassesTest */ -import java.nio.file.Files; -import java.nio.file.Paths; - public class IncorrectSignatureDeterminationForInnerClassesTest { private static final String DSrc = @@ -69,21 +66,20 @@ } void compile() throws Exception { - Files.createDirectory(Paths.get("classes")); + ToolBox tb = new ToolBox(); + tb.createDirectories("classes"); - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", "classes") - .setSources(DSrc); - - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir("classes") + .sources(DSrc) + .run(); // compile class H against the class files for classes D and Q - javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", "classes", "-cp", "classes") - .setSources(HSrc); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir("classes") + .classpath("classes") + .sources(HSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java --- a/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @test * @bug 8024039 * @summary javac, previous solution for JDK-8022186 was incorrect - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NoDeadCodeGenerationOnTrySmtTest */ @@ -76,6 +76,8 @@ static final String[] methodsToLookFor = {"m1", "m2"}; + ToolBox tb = new ToolBox(); + public static void main(String[] args) throws Exception { new NoDeadCodeGenerationOnTrySmtTest().run(); } @@ -87,9 +89,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String[] methodsToFind) throws Exception { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java --- a/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @test * @bug 8024437 * @summary Inferring the exception thrown by a lambda: sometimes fails to compile - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ExceptionInferenceFromClassFileTest */ @@ -56,19 +56,19 @@ "}"; public static void main(String[] args) throws Exception { - Files.createDirectory(Paths.get("out")); + ToolBox tb = new ToolBox(); + tb.createDirectories("out"); - ToolBox.JavaToolArgs compileABParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", "out") - .setSources(ABSrc); - ToolBox.javac(compileABParams); + tb.new JavacTask() + .outdir("out") + .sources(ABSrc) + .run(); - ToolBox.JavaToolArgs compileCParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", "out", "-cp", "out") - .setSources(CSrc); - ToolBox.javac(compileCParams); + tb.new JavacTask() + .outdir("out") + .classpath("out") + .sources(CSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8054964 + * @summary Invalid package annotations + * @author sogoel + * + * @compile/fail/ref=InvalidPackageAnno.out -XDrawDiagnostics bar/package-info.java + */ + +package bar; + diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +package-info.java:24:1: compiler.err.annotation.type.not.applicable +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java --- a/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoAnnotationMethods.java + * @compile/fail/ref=NoAnnotationMethods.out -XDrawDiagnostics NoAnnotationMethods.java */ public @interface NoAnnotationMethods { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +NoAnnotationMethods.java:10:9: compiler.err.intf.annotation.member.clash: annotationType(), java.lang.annotation.Annotation +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoClone.java --- a/langtools/test/tools/javac/annotations/neg/NoClone.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoClone.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoClone.java + * @compile/fail/ref=NoClone.out -XDrawDiagnostics NoClone.java */ public @interface NoClone { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoClone.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoClone.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,3 @@ +NoClone.java:10:5: compiler.err.invalid.annotation.member.type +NoClone.java:10:12: compiler.err.intf.annotation.member.clash: clone(), java.lang.Object +2 errors diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoObjectMethods.java --- a/langtools/test/tools/javac/annotations/neg/NoObjectMethods.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoObjectMethods.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoObjectMethods.java + * @compile/fail/ref=NoObjectMethods.out -XDrawDiagnostics NoObjectMethods.java */ public @interface NoObjectMethods { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/NoObjectMethods.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoObjectMethods.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +NoObjectMethods.java:10:9: compiler.err.intf.annotation.member.clash: clone(), java.lang.Object +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/ObjectMembers.java --- a/langtools/test/tools/javac/annotations/neg/ObjectMembers.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/ObjectMembers.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901264 * @summary JSR175 (2): don't allow annotating members from Object * @author gafter * - * @compile/fail ObjectMembers.java + * @compile/fail/ref=ObjectMembers.out -XDrawDiagnostics ObjectMembers.java */ @ObjectMembers(hashCode = 23) diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/ObjectMembers.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/ObjectMembers.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +ObjectMembers.java:10:16: compiler.err.no.annotation.member: hashCode, ObjectMembers +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/OverrideNo.java --- a/langtools/test/tools/javac/annotations/neg/OverrideNo.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/OverrideNo.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901275 4989669 * @summary JSR175 (7): implement Overrides * @author gafter * - * @compile/fail OverrideNo.java + * @compile/fail/ref=OverrideNo.out -XDrawDiagnostics OverrideNo.java */ package overrideNo; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/OverrideNo.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/OverrideNo.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +OverrideNo.java:16:5: compiler.err.method.does.not.override.superclass +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Package.java --- a/langtools/test/tools/javac/annotations/neg/Package.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Package.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901290 * @summary Package annotations * @author gafter * - * @compile/fail Package.java + * @compile/fail/ref=Package.out -XDrawDiagnostics Package.java */ @java.lang.annotation.Documented diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Package.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Package.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Package.java:10:1: compiler.err.pkg.annotations.sb.in.package-info.java +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Recovery.java --- a/langtools/test/tools/javac/annotations/neg/Recovery.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Recovery.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4993451 * @summary compiler crash with malformed annotations * @author gafter * - * @compile/fail Recovery.java + * @compile/fail/ref=Recovery.out -XDrawDiagnostics Recovery.java */ import java.lang.annotation.*; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Recovery.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Recovery.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Recovery.java:12:2: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.annotation.RetentionPolicy, java.lang.annotation.Annotation) +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Recovery1.java --- a/langtools/test/tools/javac/annotations/neg/Recovery1.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Recovery1.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4963450 * @summary Assertion error is thrown when an annotation class cannot be found. * @author gafter * - * @compile/fail Recovery1.java + * @compile/fail/ref=Recovery1.out -XDrawDiagnostics Recovery1.java */ package recovery1; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Recovery1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Recovery1.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,4 @@ +Recovery1.java:14:5: compiler.err.cant.resolve.location: kindname.class, Marker, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +Recovery1.java:14:30: compiler.err.cant.resolve.location: kindname.class, Marker, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +Recovery1.java:18:43: compiler.err.cant.resolve.location.args: kindname.method, markerToo, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +3 errors diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Scope.java --- a/langtools/test/tools/javac/annotations/neg/Scope.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Scope.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901280 * @summary name lookup scope for annotations * @author gafter * - * @compile/fail Scope.java + * @compile/fail/ref=Scope.out -XDrawDiagnostics Scope.java */ package annotation.scope; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Scope.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Scope.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Scope.java:12:4: compiler.err.cant.resolve: kindname.variable, red, , +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Syntax1.java --- a/langtools/test/tools/javac/annotations/neg/Syntax1.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Syntax1.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4974524 * @summary compiler crash with ill-formed annotation * @author gafter * - * @compile/fail Syntax1.java + * @compile/fail/ref=Syntax1.out -XDrawDiagnostics Syntax1.java */ package syntax1; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Syntax1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Syntax1.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,4 @@ +Syntax1.java:17:20: compiler.err.annotation.value.must.be.name.value +Syntax1.java:17:40: compiler.err.annotation.value.must.be.name.value +Syntax1.java:17:1: compiler.err.annotation.missing.default.value: java.lang.annotation.Target, value +3 errors diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongTarget.java --- a/langtools/test/tools/javac/annotations/neg/WrongTarget.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,35 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901271 * @summary java.lang.annotation.Target * @author gafter * - * @compile/fail WrongTarget.java + * @compile/fail/ref=WrongTarget.out -XDrawDiagnostics WrongTarget.java */ +import static java.lang.annotation.ElementType.*; + @java.lang.annotation.Target({FIELD}) @interface foo { } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongTarget.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +WrongTarget.java:16:1: compiler.err.annotation.type.not.applicable +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongTarget2.java --- a/langtools/test/tools/javac/annotations/neg/WrongTarget2.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget2.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4973504 * @summary Compiler allows Inherited meta-attribute on local variable declaration. * @author gafter * - * @compile/fail WrongTarget2.java + * @compile/fail/ref=WrongTarget2.out -XDrawDiagnostics WrongTarget2.java */ import java.lang.annotation.Inherited; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongTarget2.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget2.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +WrongTarget2.java:12:6: compiler.err.annotation.type.not.applicable +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongValue.java --- a/langtools/test/tools/javac/annotations/neg/WrongValue.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongValue.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4951298 * @summary compiler: crashes when attributes with same elements are used in place of other * @author gafter * - * @compile/fail WrongValue.java + * @compile/fail/ref=WrongValue.out -XDrawDiagnostics WrongValue.java */ @interface TestM2 { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/WrongValue.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongValue.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +WrongValue.java:25:5: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TestM3, TestM2) +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z1.java --- a/langtools/test/tools/javac/annotations/neg/Z1.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z1.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z1.java + * @compile/fail/ref=Z1.out -XDrawDiagnostics Z1.java */ enum Color { red, green, blue } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z1.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z1.java:16:10: compiler.err.cant.resolve: kindname.variable, teal, , +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z10.java --- a/langtools/test/tools/javac/annotations/neg/Z10.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z10.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z10.java + * @compile/fail/ref=Z10.out -XDrawDiagnostics Z10.java */ -enum Color { red, green, blue } - @interface An { int[][] a(); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z10.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z10.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z10.java:11:8: compiler.err.invalid.annotation.member.type +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z11.java --- a/langtools/test/tools/javac/annotations/neg/Z11.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z11.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z11.java + * @compile/fail/ref=Z11.out -XDrawDiagnostics Z11.java */ -enum Color { red, green, blue } - class X {} @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z11.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z11.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z11.java:13:5: compiler.err.invalid.annotation.member.type +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z12.java --- a/langtools/test/tools/javac/annotations/neg/Z12.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z12.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z12.java + * @compile/fail/ref=Z12.out -XDrawDiagnostics Z12.java */ -enum Color { red, green, blue } - @interface An { void a(); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z12.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z12.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z12.java:11:5: compiler.err.invalid.annotation.member.type +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z13.java --- a/langtools/test/tools/javac/annotations/neg/Z13.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z13.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z13.java + * @compile/fail/ref=Z13.out -XDrawDiagnostics Z13.java */ @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z13.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z13.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z13.java:11:20: compiler.err.throws.not.allowed.in.intf.annotation +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z14.java --- a/langtools/test/tools/javac/annotations/neg/Z14.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z14.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z14.java + * @compile/fail/ref=Z14.out -XDrawDiagnostics Z14.java */ @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z14.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z14.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z14.java:10:15: compiler.err.intf.annotation.cant.have.type.params +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z15.java --- a/langtools/test/tools/javac/annotations/neg/Z15.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z15.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z15.java + * @compile/fail/ref=Z15.out -XDrawDiagnostics Z15.java */ @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z15.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z15.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z15.java:11:36: compiler.err.attribute.value.must.be.constant +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z16.java --- a/langtools/test/tools/javac/annotations/neg/Z16.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z16.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z16.java + * @compile/fail/ref=Z16.out -XDrawDiagnostics Z16.java */ enum Color { red, green, blue } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z16.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z16.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z16.java:13:27: compiler.err.cant.resolve.location: kindname.variable, redx, , , (compiler.misc.location: kindname.annotation, Colored, null) +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z2.java --- a/langtools/test/tools/javac/annotations/neg/Z2.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z2.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z2.java + * @compile/fail/ref=Z2.out -XDrawDiagnostics Z2.java */ enum Color { red, green, blue } interface Colored { - Color value() default red; + Color value() default Color.red; } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z2.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z2.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z2.java:13:11: compiler.err.default.allowed.in.intf.annotation.member +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z3.java --- a/langtools/test/tools/javac/annotations/neg/Z3.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z3.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4865660 + * @test /nodynamiccopyright/ + * @bug 4865660 8054556 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z3.java + * @compile/fail/ref=Z3.out -XDrawDiagnostics Z3.java */ enum Color { red, green, blue } class Colored { - Color value() default red; + Color value() default Color.red; } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z3.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z3.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z3.java:13:11: compiler.err.default.allowed.in.intf.annotation.member +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z4.java --- a/langtools/test/tools/javac/annotations/neg/Z4.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z4.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z4.java + * @compile/fail/ref=Z4.out -XDrawDiagnostics Z4.java */ enum Color { red, green, blue } @interface Colored { - Color value() default teal; + Color value() default Color.teal; } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z4.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z4.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z4.java:13:32: compiler.err.cant.resolve.location: kindname.variable, teal, , , (compiler.misc.location: kindname.class, Color, null) +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z5.java --- a/langtools/test/tools/javac/annotations/neg/Z5.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z5.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z5.java + * @compile/fail/ref=Z5.out -XDrawDiagnostics Z5.java */ interface Foo {} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z5.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z5.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z5.java:12:28: compiler.err.cant.extend.intf.annotation +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z8.java --- a/langtools/test/tools/javac/annotations/neg/Z8.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z8.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z8.java + * @compile/fail/ref=Z8.out -XDrawDiagnostics Z8.java */ @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z8.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z8.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z8.java:11:15: compiler.err.intf.annotation.members.cant.have.params +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z9.java --- a/langtools/test/tools/javac/annotations/neg/Z9.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z9.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z9.java + * @compile/fail/ref=Z9.out -XDrawDiagnostics Z9.java */ @interface An { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/Z9.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z9.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +Z9.java:11:6: compiler.err.intf.annotation.members.cant.have.type.params +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/neg/bar/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/bar/package-info.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +@java.lang.annotation.Documented +package bar; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,30 +1,7 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test + * @test /nodynamiccopyright/ * @summary Smoke test for repeating annotations - * @compile/fail RepeatingAndContainerPresent.java + * @compile/fail/ref=RepeatingAndContainerPresent.out -XDrawDiagnostics RepeatingAndContainerPresent.java * @bug 7151010 */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +RepeatingAndContainerPresent.java:20:1: compiler.err.invalid.repeatable.annotation.repeated.and.container.present: Foos +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,30 +1,7 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test + * @test /nodynamiccopyright/ * @summary Smoke test for repeating annotations - * @compile/fail UseWrongRepeatable.java + * @compile/fail/ref=UseWrongRepeatable.out -XDrawDiagnostics UseWrongRepeatable.java * @bug 7151010 */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,4 @@ +UseWrongRepeatable.java:17:1: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +UseWrongRepeatable.java:17:21: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +UseWrongRepeatable.java:14:1: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +3 errors diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,35 +1,12 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test type annotation on void generic methods + * @author Mahmood Ali + * @compile/fail/ref=VoidGenericMethod.out -XDrawDiagnostics VoidGenericMethod.java */ import java.lang.annotation.*; - -/* - * @test - * @bug 6843077 8006775 - * @summary test type annotation on void generic methods - * @author Mahmood Ali - * @compile/fail VoidGenericMethod.java - */ class VoidGenericMethod { public @A void method() { } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.out Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,2 @@ +VoidGenericMethod.java:11:10: compiler.err.annotation.type.not.applicable +1 error diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java --- a/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,21 +25,19 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main HelloWorldTest */ -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; // verify that running a simple program, such as this one, does not trigger // the loading of ToolProvider or any com.sun.tools.javac class public class HelloWorldTest { public static void main(String... args) throws Exception { if (args.length > 0) { - System.err.println(Arrays.asList(args)); + System.err.println(Arrays.toString(args)); return; } @@ -47,27 +45,26 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); + String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs("-verbose:class", - "-classpath", classpath, - HelloWorldTest.class.getName(), - "Hello", "World") - .setErrOutput(output) - .setStdOutput(output); + ToolBox.Result tr = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(HelloWorldTest.class.getName()) + .classArgs("Hello", "World") + .run(); - ToolBox.executeCommand(javaParams); - - for (String line : output) { - System.err.println(line); - if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac.")) - error(">>> " + line); + if (tr.getOutput(ToolBox.OutputKind.STDOUT).contains("java.lang.Object")) { + for (String line : tr.getOutputLines(ToolBox.OutputKind.STDOUT)) { + System.err.println(line); + if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac.")) + error(">>> " + line); + } + } else { + tr.writeAll(); + error("verbose output not as expected"); } if (errors > 0) diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java --- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,11 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ToolProviderTest1 */ -import java.util.ArrayList; import java.util.List; // verify that running accessing ToolProvider by itself does not @@ -46,24 +45,18 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs("-verbose:class", - "-classpath", classpath, - ToolProviderTest1.class.getName(), - "javax.tools.ToolProvider") - .setErrOutput(output) - .setStdOutput(output); + List lines = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(getClass().getName()) + .classArgs("javax.tools.ToolProvider") + .run() + .getOutputLines(ToolBox.OutputKind.STDOUT); - ToolBox.executeCommand(javaParams); - - for (String line : output) { + for (String line : lines) { System.err.println(line); if (line.contains("com.sun.tools.javac.")) error(">>> " + line); diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java --- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,12 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ToolProviderTest2 */ import javax.tools.ToolProvider; -import java.util.ArrayList; import java.util.List; // control for ToolProviderTest1 -- verify that using ToolProvider to @@ -47,25 +46,19 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs( "-verbose:class", - "-classpath", classpath, - ToolProviderTest2.class.getName(), - "javax.tools.ToolProvider") - .setErrOutput(output) - .setStdOutput(output); - - ToolBox.executeCommand(javaParams); + List lines = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(getClass().getName()) + .classArgs("javax.tools.ToolProvider") + .run() + .getOutputLines(ToolBox.OutputKind.STDOUT); boolean found = false; - for (String line : output) { + for (String line : lines) { System.err.println(line); if (line.contains("com.sun.tools.javac.")) found = true; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java --- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary local variable table attribute test. * @bug 8040097 - * @library /tools/javac/lib ../lib - * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager * @compile -g LocalVariableTableTest.java * @run main LocalVariableTableTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java --- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary local variable type table attribute test. * @bug 8040097 - * @library /tools/javac/lib ../lib - * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager * @compile -g LocalVariableTypeTableTest.java * @run main LocalVariableTypeTableTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for anonymous class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main AnonymousClassTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for inner class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main InnerClassTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for local class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main LocalClassTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for complex structure of nested classes and other types. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main MixTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for file compiled without debug information. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @compile -g:none NoSourceFileAttribute.java * @run main NoSourceFileAttribute */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for synthetic class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main SyntheticClassTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for two type in one file. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main TopLevelClassesOneFileTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java --- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,8 +25,8 @@ * @test * @bug 8042261 * @summary Checking that deprecated attribute does not apply to classes of deprecated package. - * @library /tools/javac/lib ../lib - * @build DeprecatedPackageTest TestBase TestResult InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox TestBase TestResult InMemoryFileManager * @run main DeprecatedPackageTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java --- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,8 +26,8 @@ * @bug 8042261 * @summary Checking what attribute is generated by annotation Deprecated * or javadoc deprecated for field, method, class(inner/local), interface. - * @library /tools/javac/lib ../lib - * @build DeprecatedTest TestBase TestResult InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox TestBase TestResult InMemoryFileManager * @run main DeprecatedTest */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerAnnotationTest + */ + +public class InnerAnnotationsInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerClassTest + */ + +public class InnerAnnotationsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setForbiddenWithoutStaticInOuterMods(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerEnumTest + */ + +public class InnerAnnotationsInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC, Modifier.ABSTRACT); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ANNOTATION); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerInterfaceTest + */ + +public class InnerAnnotationsInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesHierarchyTest + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.*; +import java.util.stream.Collectors; + +public class InnerClassesHierarchyTest extends TestResult { + + private final Map> innerClasses; + private final String outerClassName; + + public InnerClassesHierarchyTest() throws IOException, ConstantPoolException { + innerClasses = new HashMap<>(); + outerClassName = InnerClassesHierarchyTest.class.getSimpleName(); + File classDir = getClassDir(); + FilenameFilter filter = + (dir, name) -> name.matches(outerClassName + ".*\\.class"); + for (File file : Arrays.asList(classDir.listFiles(filter))) { + ClassFile classFile = readClassFile(file); + String className = classFile.getName(); + for (ConstantPool.CPInfo info : classFile.constant_pool.entries()) { + if (info instanceof ConstantPool.CONSTANT_Class_info) { + ConstantPool.CONSTANT_Class_info classInfo = + (ConstantPool.CONSTANT_Class_info) info; + String cpClassName = classInfo.getBaseName(); + if (isInnerClass(cpClassName)) { + get(className).add(cpClassName); + } + } + } + } + } + + private boolean isInnerClass(String cpClassName) { + return cpClassName.contains("$"); + } + + private Set get(String className) { + if (!innerClasses.containsKey(className)) { + innerClasses.put(className, new HashSet<>()); + } + return innerClasses.get(className); + } + + public static void main(String[] args) throws IOException, ConstantPoolException, TestFailedException { + new InnerClassesHierarchyTest().test(); + } + + private void test() throws TestFailedException { + addTestCase("Source file is InnerClassesHierarchyTest.java"); + try { + Queue queue = new LinkedList<>(); + Set visitedClasses = new HashSet<>(); + queue.add(outerClassName); + while (!queue.isEmpty()) { + String currentClassName = queue.poll(); + if (!currentClassName.startsWith(outerClassName)) { + continue; + } + ClassFile cf = readClassFile(currentClassName); + InnerClasses_attribute attr = (InnerClasses_attribute) + cf.getAttribute(Attribute.InnerClasses); + assertNotNull(attr, "Class should not contain " + + "inner classes attribute : " + currentClassName); + assertTrue(innerClasses.containsKey(currentClassName), + "map contains class name : " + currentClassName); + Set setClasses = innerClasses.get(currentClassName); + if (setClasses == null) { + continue; + } + assertEquals(attr.number_of_classes, + setClasses.size(), + "Check number of inner classes : " + setClasses); + for (Info info : attr.classes) { + String innerClassName = info + .getInnerClassInfo(cf.constant_pool).getBaseName(); + assertTrue(setClasses.contains(innerClassName), + currentClassName + " contains inner class : " + + innerClassName); + if (visitedClasses.add(innerClassName)) { + queue.add(innerClassName); + } + } + } + Set allClasses = innerClasses.entrySet().stream() + .flatMap(entry -> entry.getValue().stream()) + .collect(Collectors.toSet()); + + Set a_b = removeAll(visitedClasses, allClasses); + Set b_a = removeAll(allClasses, visitedClasses); + assertEquals(visitedClasses, allClasses, + "All classes are found\n" + + "visited - all classes : " + a_b + + "\nall classes - visited : " + b_a); + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + private Set removeAll(Set set1, Set set2) { + Set set = new HashSet<>(set1); + set.removeAll(set2); + return set; + } + + public static class A1 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + public void f() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public enum A2 {; + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + public void a2() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public interface A3 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + default void a1() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + static void a2() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + } + + public @interface A4 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + } + + { + new A1() { + class B1 { + } + + public void a2() { + new B1() { + }; + class B5 { + } + } + }; + new A3() { + class B1 { + } + + public void a3() { + new B1() { + }; + class B5 { + } + } + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + static { + new A1() { + class B1 { + } + + public void a2() { + new B1() { + }; + class B5 { + } + } + }; + new A3() { + class B1 { + } + + public void a3() { + new B1() { + }; + class B5 { + } + } + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public void a5() { + class A5 { + + class B1 { + } + + public void a5() { + new B1() { + }; + + class B5 { + } + } + } + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in anonymous class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInAnonymousClassTest + */ + +import java.util.*; + +public class InnerClassesInAnonymousClassTest extends InnerClassesTestBase { + + private ClassType currentClassType; + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInAnonymousClassTest(); + test.test("InnerClassesSrc$1", "Anonymous", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + setOuterClassType(ClassType.OTHER); + setInnerClassType(ClassType.CLASS); + setSuffix("};}"); + } + + @Override + public List generateTestCases() { + currentClassType = ClassType.CLASS; + setPrefix("class Anonymous {} {new Anonymous() {"); + List sources = super.generateTestCases(); + + currentClassType = ClassType.INTERFACE; + setPrefix("interface Anonymous {} {new Anonymous() {"); + sources.addAll(super.generateTestCases()); + + currentClassType = ClassType.ANNOTATION; + setPrefix("@interface Anonymous {} {new Anonymous() {@Override public " + + "Class " + + "annotationType() {return null;}"); + sources.addAll(super.generateTestCases()); + return sources; + } + + @Override + public void getAdditionalFlags(Map> class2Flags, ClassType type, Modifier... flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Anonymous", getFlags(currentClassType, Arrays.asList(flags))); + class2Flags.put("1", new HashSet<>()); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerAnnotationTest + */ + +public class InnerClassesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.CLASS); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerClassTest + */ + +import java.util.List; + +public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setHasSyntheticClass(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.CLASS); + } + + @Override + public List generateTestCases() { + setForbiddenWithoutStaticInOuterMods(true); + List sources = super.generateTestCases(); + + setForbiddenWithoutStaticInOuterMods(false); + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + sources.addAll(super.generateTestCases()); + + return sources; + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * + * Base class for tests that check inner classes in inner class. + * + * @author Andrei Eremeev + */ +public abstract class InnerClassesInInnerClassTestBase extends InnerClassesTestBase { + + public InnerClassesInInnerClassTestBase() { + setPrefix("Inner {"); + setSuffix("}"); + } + + @Override + public void getAdditionalFlags( + Map> class2Flags, ClassType type, Modifier...flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Inner", getFlags(type, Arrays.asList(flags))); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerEnumTest + */ + +public class InnerClassesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerInterfaceTest + */ + +public class InnerClassesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.CLASS); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in local class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInLocalClassTest + */ + +import java.util.*; + +public class InnerClassesInLocalClassTest extends InnerClassesTestBase { + + private final static Modifier[] LOCAL_CLASS_MODIFIERS = + new Modifier[]{Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL}; + private final static String CLASS_TEMPLATE = + "public %CLASS% OuterClass {\n" + + "%SOURCE%\n" + + "}"; + + private final List innerClassesData; + + public InnerClassesInLocalClassTest() { + innerClassesData = new ArrayList<>(); + for (Modifier outerModifier : LOCAL_CLASS_MODIFIERS) { + StringBuilder sb = new StringBuilder(); + sb.append(outerModifier.getString()).append(' '); + sb.append("class Local {"); + Map> class2Flags = new HashMap<>(); + for (int i = 0; i < LOCAL_CLASS_MODIFIERS.length; ++i) { + Modifier innerModifier = LOCAL_CLASS_MODIFIERS[i]; + sb.append(innerModifier.getString()).append(' ') + .append("class").append(' ') + .append('A').append(i).append("{}\n"); + class2Flags.put("A" + i, getFlags(innerModifier)); + } + sb.append("};"); + class2Flags.put("1Local", getFlags(outerModifier)); + innerClassesData.add(new Data(sb.toString(), class2Flags)); + } + } + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInLocalClassTest(); + test.test("OuterClass$1Local", "1Local"); + } + + @Override + public void setProperties() { + } + + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + testCases.addAll(localClassInClassMethod()); + testCases.addAll(localClassInInterfaceMethod()); + return testCases; + } + + private List localClassInClassMethod() { + List list = new ArrayList<>(); + String template = CLASS_TEMPLATE.replace("%CLASS%", "class"); + list.addAll(lambda(template)); + list.addAll(constructor(template)); + list.addAll(method(template, + new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}, + new Modifier[]{Modifier.EMPTY, Modifier.FINAL, Modifier.STATIC})); + list.addAll(staticAndInstanceInitializer(template)); + return list; + } + + private List localClassInInterfaceMethod() { + String template = CLASS_TEMPLATE.replace("%CLASS%", "interface"); + return method(template, + new Modifier[]{Modifier.EMPTY, Modifier.PUBLIC}, + new Modifier[]{Modifier.DEFAULT, Modifier.STATIC}); + } + + private List generate(String template, String prefix, String suffix) { + List list = new ArrayList<>(); + for (Data data : innerClassesData) { + list.add(new TestCase(template.replace("%SOURCE%", + prefix + data.sources + suffix), + data.class2Flags)); + } + return list; + } + + private List lambda(String template) { + return generate(template, "Runnable run = () -> {", "};"); + } + + private List constructor(String template) { + List list = new ArrayList<>(); + for (Modifier modifier : + new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}) { + list.addAll(generate(template, modifier.getString() + " OuterClass() {", "}")); + } + return list; + } + + private List method(String template, Modifier[] mods, Modifier[] otherMods) { + List list = new ArrayList<>(); + for (Modifier modifier : mods) { + for (Modifier otherMod : otherMods) { + list.addAll(generate(template, + String.format("%s %s void method() {", + modifier.getString(), + otherMod.getString()), + "}")); + } + } + return list; + } + + private List staticAndInstanceInitializer(String template) { + List list = new ArrayList<>(); + for (Modifier modifier : new Modifier[]{Modifier.EMPTY, Modifier.STATIC}) { + list.addAll(generate(template, modifier.getString() + "{", "}")); + } + return list; + } + + private Set getFlags(Modifier modifier) { + HashSet set = new HashSet<>(); + if (modifier != Modifier.EMPTY) { + set.add("ACC_" + modifier.getString().toUpperCase()); + } + return set; + } + + /** + * Class represents part of sources which is inserted in other code. + */ + private static class Data { + public final String sources; + public final Map> class2Flags; + + public Data(String sources, Map> class2Flags) { + this.sources = sources; + this.class2Flags = class2Flags; + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that outer_class_info_index of local and anonymous class is zero. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesIndexTest + */ + +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +public class InnerClassesIndexTest extends TestResult { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesIndexTest().test(); + } + + private boolean isExcluded(String className) { + return !className.startsWith(InnerClassesIndexTest.class.getName()) + || "InnerClassesIndexTest$Inner".equals(className); + } + + private Set getInnerClasses() { + FilenameFilter filter = (dir, name) -> name.matches("InnerClassesIndexTest\\$.*\\.class"); + return Stream.of(getClassDir().listFiles(filter)) + .map(File::getName) + .map(s -> s.replace(".class", "")) + .collect(Collectors.toSet()); + } + + public void test() throws TestFailedException { + try { + addTestCase("Source is InnerClassesIndexTest.java"); + ClassFile classFile = readClassFile(InnerClassesIndexTest.class); + InnerClasses_attribute attr = (InnerClasses_attribute) + classFile.getAttribute(Attribute.InnerClasses); + + Set foundClasses = new HashSet<>(); + for (Info info : attr.classes) { + String innerName = classFile.constant_pool. + getClassInfo(info.inner_class_info_index).getBaseName(); + echo("Testing class : " + innerName); + if (isExcluded(innerName)) { + echo("Ignored : " + innerName); + continue; + } + foundClasses.add(innerName); + assertEquals(info.outer_class_info_index, 0, + "outer_class_info_index of " + innerName); + if (innerName.matches("\\$\\d+")) { + assertEquals(info.inner_name_index, 0, + "inner_name_index of anonymous class"); + } + } + Set expectedClasses = getInnerClasses(); + expectedClasses.remove("InnerClassesIndexTest$Inner"); + assertEquals(foundClasses, expectedClasses, "All classes are found"); + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + static class Inner { + } + + Inner inner1 = new Inner() { + }; + + static Inner inner2 = new Inner() { + }; + + Runnable r = () -> { + class Local { + } + new Local() { + }; + }; + + public void local() { + class Local { + } + new Local() { + }; + } + + public InnerClassesIndexTest() { + class Local { + } + new Local() { + }; + } + + { + class Local { + } + new Local() { + }; + } + + static { + class Local { + } + new Local() { + }; + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing inner classes attributes. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesTest + */ + +import java.util.List; + +public class InnerClassesTest extends InnerClassesTestBase { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesTest().test("InnerClassesSrc"); + } + + private List generateClasses() { + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + return super.generateTestCases(); + } + + private List generateEnums() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerClassType(ClassType.ENUM); + setHasSyntheticClass(false); + return super.generateTestCases(); + } + + private List generateInterfaces() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerClassType(ClassType.INTERFACE); + return super.generateTestCases(); + } + + private List generateAnnotations() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerClassType(ClassType.ANNOTATION); + return super.generateTestCases(); + } + + @Override + public void setProperties() { + setOuterAccessModifiers(Modifier.EMPTY); + setOuterOtherModifiers(Modifier.EMPTY); + setOuterClassType(ClassType.OTHER); + } + + @Override + public List generateTestCases() { + List sources = generateClasses(); + sources.addAll(generateEnums()); + sources.addAll(generateInterfaces()); + sources.addAll(generateAnnotations()); + return sources; + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Base class for tests of inner classes attribute. + * The scenario of tests: + * 1. set possible values of class modifiers. + * 2. according to set class modifiers, a test generates sources + * and golden data with {@code generateTestCases}. + * 3. a test loops through all test cases and checks InnerClasses + * attribute with {@code test}. + * + * Example, possible flags for outer class are {@code Modifier.PRIVATE and Modifier.PUBLIC}, + * possible flags for inner class are {@code Modifier.EMPTY}. + * At the second step the test generates two test cases: + * 1. public class A { + * public class B { + * class C {} + * } + * } + * 2. public class A { + * private class B { + * class C {} + * } + * } + */ +public abstract class InnerClassesTestBase extends TestResult { + + private Modifier[] outerAccessModifiers = {Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}; + private Modifier[] outerOtherModifiers = {Modifier.EMPTY, Modifier.STATIC, Modifier.FINAL, Modifier.ABSTRACT}; + private Modifier[] innerAccessModifiers = outerAccessModifiers; + private Modifier[] innerOtherModifiers = outerOtherModifiers; + private boolean isForbiddenWithoutStaticInOuterMods = false; + + private ClassType outerClassType; + private ClassType innerClassType; + private boolean hasSyntheticClass; + private String prefix = ""; + private String suffix = ""; + + /** + * Sets properties. + * + * Returns generated list of test cases. Method is called in {@code test()}. + */ + public abstract void setProperties(); + + /** + * Runs the test. + * + * @param classToTest expected name of outer class + * @param skipClasses classes that names should not be checked + */ + public void test(String classToTest, String...skipClasses) throws TestFailedException { + try { + for (TestCase test : generateTestCases()) { + addTestCase(test.getSource()); + test(classToTest, test, skipClasses); + } + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + /** + * If {@code flag} is {@code true} an outer class can not have static modifier. + * + * @param flag if {@code true} the outer class can not have static modifier + */ + public void setForbiddenWithoutStaticInOuterMods(boolean flag) { + isForbiddenWithoutStaticInOuterMods = flag; + } + + /** + * Sets the possible access flags of an outer class. + * + * @param mods the possible access flags of an outer class + */ + public void setOuterAccessModifiers(Modifier...mods) { + outerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an outer class. + * + * @param mods the possible flags of an outer class + */ + public void setOuterOtherModifiers(Modifier...mods) { + outerOtherModifiers = mods; + } + + /** + * Sets the possible access flags of an inner class. + * + * @param mods the possible access flags of an inner class + */ + public void setInnerAccessModifiers(Modifier...mods) { + innerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an inner class. + * + * @param mods the possible flags of an inner class + */ + public void setInnerOtherModifiers(Modifier...mods) { + innerOtherModifiers = mods; + } + + /** + * Sets the suffix for the generated source. + * + * @param suffix a suffix + */ + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + /** + * Sets the prefix for the generated source. + * + * @param prefix a prefix + */ + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + /** + * If {@code true} synthetic class is generated. + * + * @param hasSyntheticClass if {@code true} synthetic class is generated + */ + public void setHasSyntheticClass(boolean hasSyntheticClass) { + this.hasSyntheticClass = hasSyntheticClass; + } + + /** + * Sets the inner class type. + * + * @param innerClassType the inner class type + */ + public void setInnerClassType(ClassType innerClassType) { + this.innerClassType = innerClassType; + } + + /** + * Sets the outer class type. + * + * @param outerClassType the outer class type + */ + public void setOuterClassType(ClassType outerClassType) { + this.outerClassType = outerClassType; + } + + private void test(String classToTest, TestCase test, String...skipClasses) { + printf("Testing :\n%s\n", test.getSource()); + try { + Map> class2Flags = test.getFlags(); + ClassFile cf = readClassFile(compile(test.getSource()) + .getClasses().get(classToTest)); + InnerClasses_attribute innerClasses = (InnerClasses_attribute) + cf.getAttribute(Attribute.InnerClasses); + int count = 0; + for (Attribute a : cf.attributes.attrs) { + if (a instanceof InnerClasses_attribute) { + ++count; + } + } + assertEquals(1, count, "Number of inner classes attribute"); + if (innerClasses == null) { + return; + } + assertEquals(cf.constant_pool. + getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses", + "innerClasses.attribute_name_index"); + // Inner Classes attribute consists of length (2 bytes) + // and 8 bytes for each inner class's entry. + assertEquals(innerClasses.attribute_length, + 2 + 8 * class2Flags.size(), "innerClasses.attribute_length"); + assertEquals(innerClasses.number_of_classes, + class2Flags.size(), "innerClasses.number_of_classes"); + Set visitedClasses = new HashSet<>(); + for (Info e : innerClasses.classes) { + String baseName = cf.constant_pool.getClassInfo( + e.inner_class_info_index).getBaseName(); + if (cf.major_version >= 51 && e.inner_name_index == 0) { + assertEquals(e.outer_class_info_index, 0, + "outer_class_info_index " + + "in case of inner_name_index is zero : " + + baseName); + } + String className = baseName.replaceFirst(".*\\$", ""); + assertTrue(class2Flags.containsKey(className), + className); + assertTrue(visitedClasses.add(className), + "there are no duplicates in attribute : " + className); + assertEquals(e.inner_class_access_flags.getInnerClassFlags(), + class2Flags.get(className), + "inner_class_access_flags " + className); + if (!Arrays.asList(skipClasses).contains(className)) { + assertEquals( + cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(), + classToTest + "$" + className, + "inner_class_info_index of " + className); + if (e.outer_class_info_index > 0) { + assertEquals( + cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(), + classToTest, + "outer_class_info_index of " + className); + } + } + } + } catch (Exception e) { + addFailure(e); + } + } + + /** + * Methods generates list of test cases. Method generates all possible combinations + * of acceptable flags for nested inner classes. + * + * @return generated list of test cases + */ + protected List generateTestCases() { + setProperties(); + List list = new ArrayList<>(); + + List> outerMods = getAllCombinations(outerAccessModifiers, outerOtherModifiers); + List> innerMods = getAllCombinations(innerAccessModifiers, innerOtherModifiers); + + for (List outerMod : outerMods) { + if (isForbiddenWithoutStaticInOuterMods && !outerMod.contains(Modifier.STATIC)) { + continue; + } + StringBuilder sb = new StringBuilder(); + sb.append("public class InnerClassesSrc {") + .append(toString(outerMod)).append(' ') + .append(outerClassType).append(' ') + .append(prefix).append(' ').append('\n'); + int count = 0; + Map> class2Flags = new HashMap<>(); + List syntheticClasses = new ArrayList<>(); + for (List innerMod : innerMods) { + ++count; + String privateConstructor = ""; + if (hasSyntheticClass && !innerMod.contains(Modifier.ABSTRACT)) { + privateConstructor = "private A" + count + "() {}"; + syntheticClasses.add("new A" + count + "();"); + } + sb.append(toString(innerMod)).append(' '); + sb.append(String.format("%s A%d {%s}\n", innerClassType, count, privateConstructor)); + Set flags = getFlags(innerClassType, innerMod); + class2Flags.put("A" + count, flags); + } + if (hasSyntheticClass) { + // Source to generate synthetic classes + sb.append(syntheticClasses.stream().collect(Collectors.joining(" ", "{", "}"))); + class2Flags.put("1", new HashSet<>(Arrays.asList("ACC_STATIC", "ACC_SYNTHETIC"))); + } + sb.append(suffix).append("\n}"); + getAdditionalFlags(class2Flags, outerClassType, outerMod.toArray(new Modifier[outerMod.size()])); + list.add(new TestCase(sb.toString(), class2Flags)); + } + return list; + } + + /** + * Methods returns flags which must have type. + * + * @param type class, interface, enum or annotation + * @param mods modifiers + * @return set of access flags + */ + protected Set getFlags(ClassType type, List mods) { + Set flags = mods.stream() + .map(Modifier::getString) + .filter(str -> !str.isEmpty()) + .map(str -> "ACC_" + str.toUpperCase()) + .collect(Collectors.toSet()); + type.addSpecificFlags(flags); + return flags; + } + + private List> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) { + List> list = new ArrayList<>(); + for (Modifier access : accessModifiers) { + for (int i = 0; i < otherModifiers.length; ++i) { + Modifier mod1 = otherModifiers[i]; + for (int j = i + 1; j < otherModifiers.length; ++j) { + Modifier mod2 = otherModifiers[j]; + if (isForbidden(mod1, mod2)) { + continue; + } + list.add(Arrays.asList(access, mod1, mod2)); + } + if (mod1 == Modifier.EMPTY) { + list.add(Arrays.asList(access)); + } + } + } + return list; + } + + private boolean isForbidden(Modifier mod1, Modifier mod2) { + return mod1 == Modifier.FINAL && mod2 == Modifier.ABSTRACT + || mod1 == Modifier.ABSTRACT && mod2 == Modifier.FINAL; + } + + private String toString(List mods) { + return mods.stream() + .map(Modifier::getString) + .filter(s -> !s.isEmpty()) + .collect(Collectors.joining(" ")); + } + + /** + * Method is called in generateTestCases(). + * If you need to add additional access flags, you should override this method. + * + * + * @param class2Flags map with flags + * @param type class, interface, enum or @annotation + * @param mods modifiers + */ + public void getAdditionalFlags(Map> class2Flags, ClassType type, Modifier...mods) { + class2Flags.values().forEach(type::addFlags); + } + + public enum ClassType { + CLASS("class") { + @Override + public void addSpecificFlags(Set flags) { + } + }, + INTERFACE("interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + } + }, + ANNOTATION("@interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + flags.add("ACC_ANNOTATION"); + } + }, + ENUM("enum") { + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_ENUM"); + flags.add("ACC_FINAL"); + flags.add("ACC_STATIC"); + } + }, + OTHER("") { + @Override + public void addSpecificFlags(Set flags) { + } + }; + + private final String classType; + + private ClassType(String clazz) { + this.classType = clazz; + } + + public abstract void addSpecificFlags(Set flags); + + public String toString() { + return classType; + } + + public void addFlags(Set set) { + } + } + + public enum Modifier { + PUBLIC("public"), PRIVATE("private"), + PROTECTED("protected"), DEFAULT("default"), + FINAL("final"), ABSTRACT("abstract"), + STATIC("static"), EMPTY(""); + + private final String str; + + private Modifier(String str) { + this.str = str; + } + + public String getString() { + return str; + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerAnnotationTest + */ + +public class InnerEnumInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ENUM); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerEnumTest + */ + +public class InnerEnumInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ENUM); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerInterfaceTest + */ + +public class InnerEnumInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ENUM); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumsInInnerClassTest + */ + +public class InnerEnumsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ENUM); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerAnnotationTest + */ + +public class InnerInterfacesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Testing InnerClasses_attribute of inner interfaces in inner class. + * @author aeremeev + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerClassTest + */ + +public class InnerInterfacesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerEnumTest + */ + +public class InnerInterfacesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.INTERFACE); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerInterfaceTest + */ + +import java.util.List; + +public class InnerInterfacesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that there are no inner classes attributes in case of there are no inner classes. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase InMemoryFileManager ToolBox + * @run main NoInnerClassesTest + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; + +import java.io.IOException; + +public class NoInnerClassesTest extends TestBase { + + public static void main(String[] args) throws IOException, ConstantPoolException { + new NoInnerClassesTest().test(); + } + + public void test() throws IOException, ConstantPoolException { + ClassFile classFile = readClassFile("NoInnerClassesTest"); + assertNull(classFile.getAttribute(Attribute.InnerClasses), "Found inner class attribute"); + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,92 @@ +The description of the tests for the InnerClasses attribute. + +InnerClassesTestBase is the base class for tests of inner classes attribute. +Each tests extends the base class. +The scenario of tests: + 1. set possible values of class modifiers, outer/inner class types. + 2. according to set class modifiers, a test generates sources + and golden data with generateTestCases. + 3. a test loops through all test cases and checks InnerClasses attribute in method test(). + +Example, possible flags for outer class are Modifier.PRIVATE and Modifier.PUBLIC, +possible flags for inner class are Modifier.EMPTY, outer class type is CLASS +and inner class type is CLASS. +At the second step the test generates two test cases: + 1. public class A { + public class B { + class C {} + } + } + 2. public class A { + private class B { + class C {} + } + } + +The list of tests. + +Test: test if there is not inner class, the InnerClasses attribute +is not generated (NoInnerClasses.java). + +Test: inner classes in anonymous class (InnerClassesInAnonymousClassTest.java). +Possible access flags of the inner class: abstract and final. + +Test: inner classes in local class (InnerClassesInLocalClassTest.java). +Locations of local class: static and instance initializer, constructor, method, lambda, +default and static methods of interface. + +Test: test the outer_class_info_index and inner_name_index of +local and anonymous classes (InnerClassesIndexTest.java). + +List of test cases for Inner*InInner*Test: + * InnerClassesInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerClassesInInnerEnumTest + outer flags: all access flags, abstract + inner flags: all possible flags + * InnerClassesInInnerAnnotationTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + * InnerClassesInInnerInterfaceTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + + * InnerEnumsInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerEnumTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerAnnotationTest + outer flags: all access flags, abstract, static + inner flags: public, static + * InnerEnumsInInnerInterfaceTest + outer flags: all access flags, abstract, static + inner flags: public, static + + * InnerAnnotationInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerAnnotationInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + + * InnerInterfaceInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerInterfaceInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static \ No newline at end of file diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; +import java.util.Set; + +/** + * Class represents test cases. This class contains source code and + * access flags for each inner class in source code. + */ +public class TestCase { + + private final String sourceCode; + private final Map> class2Flags; + + public TestCase(String sourceCode, Map> class2Flags) { + this.sourceCode = sourceCode; + this.class2Flags = class2Flags; + } + + /** + * Returns source code. + * + * @return source code + */ + public String getSource() { + return sourceCode; + } + + /** + * Returns map with entries (ClassName, set of access flags for the ClassName). + * + * @return map with entries (ClassName, set of access flags for the ClassName) + */ + public Map> getFlags() { + return class2Flags; + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Thu Aug 28 14:53:49 2014 -0700 @@ -22,22 +22,23 @@ */ import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Stream; +import java.util.stream.Collectors; + import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; -import static java.lang.String.format; -import static java.lang.System.lineSeparator; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; /** * Base class for class file attribute tests. @@ -46,7 +47,7 @@ */ public class TestBase { - public static final String LINE_SEPARATOR = lineSeparator(); + public static final String LINE_SEPARATOR = System.lineSeparator(); private InMemoryFileManager compile( List options, @@ -57,7 +58,7 @@ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); List src = sources.stream() .map(src2JavaFileObject) - .collect(toList()); + .collect(Collectors.toList()); DiagnosticCollector dc = new DiagnosticCollector<>(); try (InMemoryFileManager fileManager @@ -67,7 +68,7 @@ if (!success) { String errorMessage = dc.getDiagnostics().stream() .map(Object::toString) - .collect(joining("\n")); + .collect(Collectors.joining("\n")); throw new CompilationException("Compilation Error\n\n" + errorMessage); } return fileManager; @@ -82,7 +83,7 @@ */ public InMemoryFileManager compile(String... sources) throws IOException, CompilationException { - return compile(emptyList(), sources); + return compile(Collections.emptyList(), sources); } /** @@ -94,7 +95,7 @@ */ public InMemoryFileManager compile(List options, String... sources) throws IOException, CompilationException { - return compile(options, ToolBox.JavaSource::new, asList(sources)); + return compile(options, ToolBox.JavaSource::new, Arrays.asList(sources)); } /** @@ -105,7 +106,7 @@ */ public InMemoryFileManager compile(String[]... sources) throws IOException, CompilationException { - return compile(emptyList(), sources); + return compile(Collections.emptyList(), sources); } /** @@ -117,12 +118,73 @@ */ public InMemoryFileManager compile(List options, String[]... sources) throws IOException, CompilationException { - return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources)); + return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), Arrays.asList(sources)); + } + + /** + * Returns class file that is read from {@code is}. + * + * @param is an input stream + * @return class file that is read from {@code is} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(InputStream is) throws IOException, ConstantPoolException { + return ClassFile.read(is); + } + + /** + * Returns class file that is read from {@code fileObject}. + * + * @param fileObject a file object + * @return class file that is read from {@code fileObject} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException { + return readClassFile(fileObject.openInputStream()); + } + + /** + * Returns class file that corresponds to {@code clazz}. + * + * @param clazz a class + * @return class file that is read from {@code clazz} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(Class clazz) throws IOException, ConstantPoolException { + return readClassFile(getClassFile(clazz)); + } + + /** + * Returns class file that corresponds to {@code className}. + * + * @param className a class name + * @return class file that is read from {@code className} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(String className) throws IOException, ConstantPoolException { + return readClassFile(getClassFile(className + ".class")); + } + + /** + * Returns class file that is read from {@code file}. + * + * @param file a file + * @return class file that is read from {@code file} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(File file) throws IOException, ConstantPoolException { + return readClassFile(new FileInputStream(file)); } public void assertEquals(Object actual, Object expected, String message) { if (!Objects.equals(actual, expected)) - throw new AssertionFailedException(format("%s%nGot: %s, Expected: %s", message, actual, expected)); + throw new AssertionFailedException(String.format("%s%nGot: %s, Expected: %s", + message, actual, expected)); } public void assertNull(Object actual, String message) { @@ -169,22 +231,18 @@ * @param message string to print. */ public void echo(String message) { - System.err.println(message.replace("\n", LINE_SEPARATOR)); + printf(message + "\n"); } /** - * Substitutes args in template and prints result to standard error. New lines are converted to system dependent NL. + * Substitutes args in template and prints result to standard error. + * New lines are converted to system dependent NL. * * @param template template in standard String.format(...) format. * @param args arguments to substitute in template. */ public void printf(String template, Object... args) { - System.err.printf(template, Stream.of(args) - .map(Objects::toString) - .map(m -> m.replace("\n", LINE_SEPARATOR)) - .collect(toList()) - .toArray()); - + System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR)); } public static class CompilationException extends Exception { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Thu Aug 28 14:53:49 2014 -0700 @@ -23,13 +23,15 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.stream.Stream; import static java.lang.String.format; import static java.util.stream.Collectors.joining; +/** + * This class accumulates test results. Test results can be checked with method @{code checkStatus}. + */ public class TestResult extends TestBase { private final List testCases; @@ -39,15 +41,18 @@ testCases.add(new Info("Global test info")); } - public void addTestCase(String src) { - testCases.add(new Info(src)); + /** + * Adds new test case info. + * + * @param info the information about test case + */ + public void addTestCase(String info) { + testCases.add(new Info(info)); } - public String errorMessage() { + private String errorMessage() { return testCases.stream().filter(Info::isFailed) - .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), - (tc.asserts.size() > 0 ? tc.getAssertMessage() + "\n" : "") - + tc.getErrorMessage())) + .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage())) .collect(joining("\n")); } @@ -76,8 +81,14 @@ getLastTestCase().assertEquals(actual, true, message); } + public void assertContains(Set found, Set expected, String message) { + Set copy = new HashSet<>(expected); + copy.removeAll(found); + assertTrue(found.containsAll(expected), message + " : " + copy); + } + public void addFailure(Throwable th) { - getLastTestCase().addFailure(th); + testCases.get(testCases.size() - 1).addFailure(th); } private Info getLastTestCase() { @@ -87,6 +98,13 @@ return testCases.get(testCases.size() - 1); } + /** + * Throws {@code TestFailedException} if one of the asserts are failed + * or an exception occurs. Prints error message of failed test cases. + * + * @throws TestFailedException if one of the asserts are failed + * or an exception occurs + */ public void checkStatus() throws TestFailedException { if (testCases.stream().anyMatch(Info::isFailed)) { echo(errorMessage()); @@ -120,7 +138,13 @@ } public void addFailure(String message) { - asserts.add(message); + String stackTrace = Stream.of(Thread.currentThread().getStackTrace()) + // just to get stack trace without TestResult and Thread + .filter(e -> !"TestResult.java".equals(e.getFileName()) && + !"java.lang.Thread".equals(e.getClassName())) + .map(e -> "\tat " + e) + .collect(joining("\n")); + asserts.add(format("%s\n%s", message, stackTrace)); printf("[ASSERT] : %s\n", message); } @@ -138,6 +162,10 @@ } } + public String getMessage() { + return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage(); + } + public String getAssertMessage() { return asserts.stream() .map(failure -> "[ASSERT] : " + failure) @@ -146,8 +174,7 @@ public String getErrorMessage() { return errors.stream() - .map(throwable -> - format("[ERROR] : %s", getStackTrace(throwable))) + .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable))) .collect(joining("\n")); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java --- a/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,7 +26,7 @@ * @bug 8029240 8030855 * @summary Default methods not always visible under -source 7 * Default methods should be visible under source previous to 8 - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main DefaultMethodsNotVisibleForSourceLessThan8Test */ @@ -111,6 +111,7 @@ String outDir; String source; + ToolBox tb = new ToolBox(); void run(String source) throws Exception { this.source = source; @@ -127,50 +128,53 @@ /* as an extra check let's make sure that interface 'I' can't be compiled * with source < 8 */ - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-d", outDir, "-source", source) - .setSources(ISrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .options("-source", source) + .sources(ISrc) + .run(ToolBox.Expect.FAIL); //but it should compile with source >= 8 - javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-d", outDir) - .setSources(ISrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .sources(ISrc) + .run(); - javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(JSrc, ASrc, BSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(JSrc, ASrc, BSrc) + .run(); } void testLegacyImplementations() throws Exception { //compile C1-4 - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(C1Src, C2Src, C3Src, C4Src); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(C1Src, C2Src, C3Src, C4Src) + .run(); } void testLegacyInvocations() throws Exception { //compile LegacyInvocation - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(LegacyInvocationSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(LegacyInvocationSrc) + .run(); } void testSuperInvocations() throws Exception { //compile SubA, SubB - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(SubASrc, SubBSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(SubASrc, SubBSrc) + .run(); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java --- a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,12 @@ * @test * @bug 4263768 4785453 * @summary Verify that the compiler does not crash when java.lang is not - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NoJavaLangTest */ -import java.util.ArrayList; -import java.util.List; - -//original test: test/tools/javac/fatalErrors/NoJavaLang.sh +// Original test: test/tools/javac/fatalErrors/NoJavaLang.sh public class NoJavaLangTest { private static final String noJavaLangSrc = @@ -49,26 +46,20 @@ "Fatal Error: Unable to find package java.lang in classpath or bootclasspath"; public static void main(String[] args) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} NoJavaLang.java 2> "${TMP1}" - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(noJavaLangSrc); - ToolBox.javac(javacSuccessArgs); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(noJavaLangSrc) + .run(); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -bootclasspath . NoJavaLang.java 2> "${TMP1}" - List output = new ArrayList<>(); - ToolBox.JavaToolArgs javacFailArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-bootclasspath", ".") - .setSources(noJavaLangSrc) - .setErrOutput(output); + String out = tb.new JavacTask() + .options("-bootclasspath", ".") + .sources(noJavaLangSrc) + .run(ToolBox.Expect.FAIL, 3) + .writeAll() + .getOutput(ToolBox.OutputKind.DIRECT); - int cr = ToolBox.javac(javacFailArgs); - if (cr != 3) { - throw new AssertionError("Compiler exit result should be 3"); - } - -// diff ${DIFFOPTS} -c "${TESTSRC}${FS}NoJavaLang.out" "${TMP1}" - if (!(output.size() == 1 && output.get(0).equals(compilerErrorMessage))) { + if (!out.trim().equals(compilerErrorMessage)) { throw new AssertionError("javac generated error output is not correct"); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java --- a/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,15 @@ * @test * @bug 4491755 4785453 * @summary Prob w/static inner class with same name as a regular class - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main InnerClassFileTest */ +import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/javac/innerClassFile/Driver.sh +// Original test: test/tools/javac/innerClassFile/Driver.sh public class InnerClassFileTest { private static final String BSrc = @@ -90,38 +91,37 @@ new InnerClassFileTest().run(); } + private final ToolBox tb = new ToolBox(); + void run() throws Exception { createFiles(); compileFiles(); } void createFiles() throws Exception { -// mkdir src -// cp -r ${TESTSRC}${FS}* src - ToolBox.createJavaFileFromSource(Paths.get("src"), BSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), CSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), MainSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), R1Src); - ToolBox.createJavaFileFromSource(Paths.get("src"), R2Src); - ToolBox.createJavaFileFromSource(Paths.get("src"), R3Src); + Path srcDir = Paths.get("src"); + tb.writeJavaFiles(srcDir, BSrc, CSrc, MainSrc, R1Src, R2Src, R3Src); } void compileFiles() throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath . -// -sourcepath src src/x/B.java src/x/C.java src/y/Main.java - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs() - .setAllArgs("-d", ".", "-cp" , ".", "-sourcepath", "src", - "src/x/B.java", "src/x/C.java", "src/y/Main.java"); - ToolBox.javac(args); + tb.new JavacTask() + .outdir(".") + .classpath(".") + .sourcepath("src") + .files("src/x/B.java", "src/x/C.java", "src/y/Main.java") + .run() + .writeAll(); -// rm y/R3.class - ToolBox.rm(Paths.get("y", "R3.class")); + tb.deleteFiles("y/R3.class"); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath . -// -sourcepath src src/y/Main.java - args.setAllArgs("-d", ".", "-cp", ".", "-sourcepath", "src", "src/y/Main.java"); - ToolBox.javac(args); + tb.new JavacTask() + .outdir(".") + .classpath(".") + .sourcepath("src") + .files("src/y/Main.java") + .run() + .writeAll(); + } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/javazip/JavaZipTest.java --- a/langtools/test/tools/javac/javazip/JavaZipTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/javazip/JavaZipTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,16 @@ * @test * @bug 4098712 6304984 6388453 * @summary check that source files inside zip files on the class path are ignored - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main JavaZipTest */ -import java.io.File; +import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Arrays; -//original test: test/tools/javac/javazip/Test.sh +// Original test: test/tools/javac/javazip/Test.sh public class JavaZipTest { private static final String ASrc = @@ -62,7 +63,7 @@ {"-d", "output", "-cp", "good.jar", "A.java"}, }; - private static final String[][] unSuccessfulCompilationArgs = { + private static final String[][] unsuccessfulCompilationArgs = { {"-d", "output", "A.java", "bad/B.java"}, {"-d", "output", "-cp", "bad", "A.java"}, {"-d", "output", "-sourcepath", "bad", "A.java"}, @@ -74,53 +75,57 @@ new JavaZipTest().test(); } + private final ToolBox tb = new ToolBox(); + public void test() throws Exception { createOutputDirAndSourceFiles(); createZipsAndJars(); check(ToolBox.Expect.SUCCESS, successfulCompilationArgs); - check(ToolBox.Expect.FAIL, unSuccessfulCompilationArgs); + check(ToolBox.Expect.FAIL, unsuccessfulCompilationArgs); } void createOutputDirAndSourceFiles() throws Exception { //create output dir - new File("output").mkdir(); + Files.createDirectory(Paths.get("output")); //source file creation - ToolBox.createJavaFileFromSource(Paths.get("good"), BGoodSrc); - ToolBox.createJavaFileFromSource(Paths.get("bad"), BBadSrc); - ToolBox.createJavaFileFromSource(ASrc); + tb.writeJavaFiles(Paths.get("good"), BGoodSrc); + tb.writeJavaFiles(Paths.get("bad"), BBadSrc); + tb.writeJavaFiles(ToolBox.currDir, ASrc); } void createZipsAndJars() throws Exception { //jar and zip creation -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.jar" -C "${TESTSRC}${FS}good" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.zip" -C "${TESTSRC}${FS}good" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.jar" -C "${TESTSRC}${FS}bad" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.zip" -C "${TESTSRC}${FS}bad" B.java for (String[] args: jarArgs) { - ToolBox.jar(args); + tb.new JarTask().run(args).writeAll(); } } - void check(ToolBox.Expect whatToExpect, String[][] theArgs) throws Exception { -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}good${FS}B.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}good" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}good" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.zip" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.jar" "${TESTSRC}${FS}A.java" + void check(ToolBox.Expect expectedStatus, String[][] theArgs) throws Exception { -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}bad${FS}B.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}bad" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}bad" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.zip" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.jar" "${TESTSRC}${FS}A.java" - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs(whatToExpect); for (String[] allArgs: theArgs) { - args.setAllArgs(allArgs); - ToolBox.javac(args); + tb.new JavacTask() + .options(opts(allArgs)) + .files(files(allArgs)) + .run(expectedStatus) + .writeAll(); + } } + private String[] opts(String... allArgs) { + int i = allArgs.length; + while (allArgs[i - 1].endsWith(".java")) + i--; + return Arrays.copyOfRange(allArgs, 0, i); + } + + private String[] files(String... allArgs) { + int i = allArgs.length; + while (allArgs[i - 1].endsWith(".java")) + i--; + return Arrays.copyOfRange(allArgs, i, allArgs.length); + } + } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java --- a/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8023668 * @summary Desugar serializable lambda bodies using more robust naming scheme - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main TestSerializedLambdaNameStability */ @@ -125,6 +125,7 @@ static final String compiledDir = System.getProperty("user.dir"); static final String sourceBaseDir = System.getProperty("test.src"); + final ToolBox tb = new ToolBox(); final String context; public TestClassLoader(String context) { @@ -154,10 +155,10 @@ else throw new Exception("Did not expect to load " + name); Path srcFile = Paths.get(sourceBaseDir, context, srcName + ".java"); - String testSource = new String(Files.readAllBytes(srcFile)); - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .outdir(compiledDir) + .files(srcFile) + .run(); Path cfFile = Paths.get(compiledDir, name + ".class"); byte[] bytes = Files.readAllBytes(cfFile); return bytes; diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/lib/ToolBox.java --- a/langtools/test/tools/javac/lib/ToolBox.java Thu Aug 21 14:16:28 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1080 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.SimpleJavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.api.JavacTaskImpl; - -import sun.tools.jar.Main; - -import static java.nio.file.StandardCopyOption.*; - -/** - * Toolbox for jtreg tests. - */ - -public class ToolBox { - - public static final String lineSeparator = System.getProperty("line.separator"); - public static final String jdkUnderTest = System.getProperty("test.jdk"); - public static final Path javaBinary = Paths.get(jdkUnderTest, "bin", "java"); - public static final Path javacBinary = Paths.get(jdkUnderTest, "bin", "javac"); - - public static final List testVMOpts = readOptions("test.vm.opts"); - public static final List testToolVMOpts = readOptions("test.tool.vm.opts"); - public static final List testJavaOpts = readOptions("test.java.opts"); - - private static final Charset defaultCharset = Charset.defaultCharset(); - - static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); - - private static List readOptions(String property) { - String options = System.getProperty(property, ""); - return options.length() > 0 ? Arrays.asList(options.split("\\s+")) : Collections.emptyList(); - } - - /** - * The expected result of command-like method execution. - */ - public enum Expect {SUCCESS, FAIL} - - enum AcceptedParams { - EXPECT, - SOURCES, - OPTIONS, - STD_OUTPUT, - ERR_OUTPUT, - EXTRA_ENV, - } - - enum OutputKind {STD, ERR} - - /** - * Helper class to abstract the processing of command's output. - */ - static abstract class WriterHelper { - OutputKind kind; - public abstract void pipeOutput(ProcessBuilder pb); - public abstract void readFromStream(Process p) throws IOException; - public abstract void addAll(Collection c) throws IOException; - } - - /** - * Helper class for redirecting command's output to a file. - */ - static class FileWriterHelper extends WriterHelper { - File file; - - FileWriterHelper(File file, OutputKind kind) { - this.file = file; - this.kind = kind; - } - - @Override - public void pipeOutput(ProcessBuilder pb) { - if (file != null) { - switch (kind) { - case STD: - pb.redirectInput(file); - break; - case ERR: - pb.redirectError(file); - break; - } - } - } - - @Override - public void readFromStream(Process p) throws IOException {} - - @Override - public void addAll(Collection c) throws IOException { - if (file.exists()) - Files.write(file.toPath(), c, defaultCharset, - StandardOpenOption.WRITE, StandardOpenOption.APPEND); - else - Files.write(file.toPath(), c, defaultCharset); - } - } - - /** - * Helper class for redirecting command's output to a String list. - */ - static class ListWriterHelper extends WriterHelper { - List list; - - public ListWriterHelper(List list, OutputKind kind) { - this.kind = kind; - this.list = list; - } - - @Override - public void pipeOutput(ProcessBuilder pb) {} - - @Override - public void readFromStream(Process p) throws IOException { - BufferedReader br = null; - switch (kind) { - case STD: - br = new BufferedReader(new InputStreamReader(p.getInputStream())); - break; - case ERR: - br = new BufferedReader(new InputStreamReader(p.getErrorStream())); - break; - } - String line; - while ((line = br.readLine()) != null) { - list.add(line); - } - } - - public void addAll(Collection c) { - list.addAll(c); - } - } - - /** - * Simple factory class for creating a WriterHelper instance. - */ - static class WriterHelperFactory { - static WriterHelper make(File file, OutputKind kind) { - return new FileWriterHelper(file, kind); - } - - static WriterHelper make(List list, OutputKind kind) { - return new ListWriterHelper(list, kind); - } - } - - /** - * A generic class for holding command's arguments. - */ - public static abstract class GenericArgs { - protected static List> minAcceptedParams; - - protected Set currentParams = - EnumSet.noneOf(AcceptedParams.class); - - protected Expect whatToExpect; - protected WriterHelper stdOutput; - protected WriterHelper errOutput; - protected List args = new ArrayList<>(); - protected String[] argsArr; - - protected GenericArgs() { - set(Expect.SUCCESS); - } - - public T set(Expect whatToExpt) { - currentParams.add(AcceptedParams.EXPECT); - this.whatToExpect = whatToExpt; - return (T)this; - } - - public T setStdOutput(List stdOutput) { - currentParams.add(AcceptedParams.STD_OUTPUT); - this.stdOutput = WriterHelperFactory.make(stdOutput, OutputKind.STD); - return (T)this; - } - - public T setStdOutput(File output) { - currentParams.add(AcceptedParams.STD_OUTPUT); - this.stdOutput = WriterHelperFactory.make(output, OutputKind.STD); - return (T)this; - } - - public T setErrOutput(List errOutput) { - currentParams.add(AcceptedParams.ERR_OUTPUT); - this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR); - return (T)this; - } - - public T setErrOutput(File errOutput) { - currentParams.add(AcceptedParams.ERR_OUTPUT); - this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR); - return (T)this; - } - - public T setAllArgs(String... args) { - currentParams.add(AcceptedParams.OPTIONS); - this.argsArr = args; - return (T) this; - } - - - public T appendArgs(String... args) { - appendArgs(Arrays.asList(args)); - return (T)this; - } - - public T appendArgs(Path... args) { - if (args != null) { - List list = new ArrayList<>(); - for (int i = 0; i < args.length; i++) { - if (args[i] != null) { - list.add(args[i].toString()); - } - } - appendArgs(list); - } - return (T)this; - } - - public T appendArgs(List args) { - if (args != null && args.size() > 0) { - currentParams.add(AcceptedParams.OPTIONS); - for (int i = 0; i < args.size(); i++) { - if (args.get(i) != null) { - this.args.add(args.get(i)); - } - } - } - return (T)this; - } - - public T setOptions(List options) { - currentParams.add(AcceptedParams.OPTIONS); - this.args = options; - return (T)this; - } - - public T setOptions(String... options) { - currentParams.add(AcceptedParams.OPTIONS); - this.args = Arrays.asList(options); - return (T)this; - } - - public boolean hasMinParams() { - for (Set minSet : minAcceptedParams) { - if (currentParams.containsAll(minSet)) { - return true; - } - } - return false; - } - } - - /** - * A more specific class for holding javac-like command's arguments. - */ - public static class JavaToolArgs extends GenericArgs { - - static { - minAcceptedParams = new ArrayList<>(); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.OPTIONS)); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.SOURCES)); - } - - protected List sources; - - public JavaToolArgs() { - super(); - } - - public JavaToolArgs(Expect whatToExpt) { - super.set(whatToExpt); - } - - public JavaToolArgs setSources(List sources) { - currentParams.add(AcceptedParams.SOURCES); - this.sources = sources; - return this; - } - - public JavaToolArgs setSources(JavaSource... sources) { - return setSources(Arrays.asList(sources)); - } - - public JavaToolArgs setSources(String... sources) { - List javaSrcs = new ArrayList<>(); - for (String source : sources) { - javaSrcs.add(new JavaSource(source)); - } - return setSources(javaSrcs); - } - } - - /** - * A more specific class for holding any command's arguments. - */ - public static class AnyToolArgs extends GenericArgs { - - static { - minAcceptedParams = new ArrayList<>(); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.OPTIONS)); - } - - Map extraEnv; - - public AnyToolArgs() { - super(); - } - - public AnyToolArgs(Expect whatToExpt) { - set(whatToExpt); - } - - public AnyToolArgs set(Map extraEnv) { - currentParams.add(AcceptedParams.EXTRA_ENV); - this.extraEnv = extraEnv; - return this; - } - } - - /** - * Custom exception for bad command execution. - */ - public static class CommandExecutionException extends Exception { - CommandExecutionException(List command, Expect whatToExpt) { - super(createMessage(command, whatToExpt)); - } - - CommandExecutionException(Expect whatToExpt, String... command) { - this(Arrays.asList(command), whatToExpt); - } - - private static String createMessage(List command, Expect whatToExpt) { - StringBuilder sb = new StringBuilder().append("Command : "); - sb.append(command.toString()).append(lineSeparator); - switch (whatToExpt) { - case SUCCESS: - sb.append(" has unexpectedly failed"); - break; - case FAIL: - sb.append(" has been unexpectedly successful"); - break; - } - return sb.toString(); - } - } - - /** - * Custom exception for not equal resources. - */ - public static class ResourcesNotEqualException extends Exception { - public ResourcesNotEqualException(List res1, List res2) { - super(createMessage(res1, res2)); - } - - public ResourcesNotEqualException(String line1, String line2) { - super(createMessage(line1, line2)); - } - - public ResourcesNotEqualException(Path path1, Path path2) { - super(createMessage(path1, path2)); - } - - private static String createMessage(Path path1, Path path2) { - return new StringBuilder() - .append("The resources provided for comparison in paths \n") - .append(path1.toString()).append(" and \n") - .append(path2.toString()).append("are different").toString(); - } - - private static String createMessage(String line1, String line2) { - return new StringBuilder() - .append("The resources provided for comparison are different at lines: \n") - .append(line1).append(" and \n") - .append(line2).toString(); - } - - private static String createMessage(List res1, List res2) { - return new StringBuilder() - .append("The resources provided for comparison are different: \n") - .append("Resource 1 is: ").append(res1).append("\n and \n") - .append("Resource 2 is: ").append(res2).append("\n").toString(); - } - } - - /** - * A javac compiler caller method. - */ - public static int javac(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - if (params.argsArr != null) { - return genericJavaCMD(JavaCMD.JAVAC, params); - } else { - return genericJavaCMD(JavaCMD.JAVAC_API, params); - } - } - throw new AssertionError("javac command has been invoked with less parameters than needed"); - } - - /** - * Run javac and return the resulting classfiles. - */ - public static Map compile(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - if (params.argsArr != null) { - throw new AssertionError("setAllArgs is not supported for compile"); - } - - StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); - MemoryFileManager mfm = new MemoryFileManager(fm); - StringWriter sw = null; - boolean rc; - - try (PrintWriter pw = (params.errOutput == null) ? - null : new PrintWriter(sw = new StringWriter())) { - JavacTask ct = (JavacTask)comp.getTask(pw, mfm, null, - params.args, null, params.sources); - rc = ct.call(); - } - - String out = (sw == null) ? null : sw.toString(); - - if (params.errOutput != null && (out != null) && !out.isEmpty()) { - params.errOutput.addAll(splitLines(out, lineSeparator)); - } - - if ( ( rc && params.whatToExpect == Expect.SUCCESS) || - (!rc && params.whatToExpect == Expect.FAIL) ) { - return mfm.classes; - } - - throw new CommandExecutionException(JavaCMD.JAVAC_API.getExceptionMsgContent(params), - params.whatToExpect); - } - throw new AssertionError("compile command has been invoked with less parameters than needed"); - } - - /** - * A javap calling method. - */ - public static String javap(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - List list = new ArrayList<>(); - params.setErrOutput(list); - genericJavaCMD(JavaCMD.JAVAP, params); - return listToString(list); - } - throw new AssertionError("javap command has been invoked with less parameters than needed"); - } - - /** - * A javah calling method. - */ - public static int javah(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - return genericJavaCMD(JavaCMD.JAVAH, params); - } - throw new AssertionError("javah command has been invoked with less parameters than needed"); - } - - /** - * A enum class for langtools commands. - */ - enum JavaCMD { - JAVAC { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javac.Main.compile(params.argsArr, pw); - } - }, - JAVAC_API { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - JavacTask ct = (JavacTask)comp.getTask(pw, null, null, - params.args, null, params.sources); - return ((JavacTaskImpl)ct).doCall().exitCode; - } - - @Override - String getName() { - return "javac"; - } - - @Override - List getExceptionMsgContent(JavaToolArgs params) { - List result = super.getExceptionMsgContent(params); - for (JavaFileObject source : params.sources) { - if (source instanceof JavaSource) { - result.add(((JavaSource)source).name); - } - } - return result; - } - }, - JAVAH { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javah.Main.run(params.argsArr, pw); - } - }, - JAVAP { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javap.Main.run(params.argsArr, pw); - } - }; - - abstract int run(JavaToolArgs params, PrintWriter pw); - - String getName() { - return this.name().toLowerCase(); - } - - List getExceptionMsgContent(JavaToolArgs params) { - List result = new ArrayList<>(); - result.add(getName()); - result.addAll(params.argsArr != null ? - Arrays.asList(params.argsArr) : - params.args); - return result; - } - } - - /** - * A helper method for executing langtools commands. - */ - private static int genericJavaCMD( - JavaCMD cmd, - JavaToolArgs params) - throws CommandExecutionException, IOException { - int rc = 0; - StringWriter sw = null; - try (PrintWriter pw = (params.errOutput == null) ? - null : new PrintWriter(sw = new StringWriter())) { - rc = cmd.run(params, pw); - } - String out = (sw == null) ? null : sw.toString(); - - if (params.errOutput != null && (out != null) && !out.isEmpty()) { - params.errOutput.addAll(splitLines(out, lineSeparator)); - } - - if ( (rc == 0 && params.whatToExpect == Expect.SUCCESS) || - (rc != 0 && params.whatToExpect == Expect.FAIL) ) { - return rc; - } - - throw new CommandExecutionException(cmd.getExceptionMsgContent(params), - params.whatToExpect); - } - - /** - * A jar calling method. - */ - public static boolean jar(String... params) throws CommandExecutionException { - Main jarGenerator = new Main(System.out, System.err, "jar"); - boolean result = jarGenerator.run(params); - if (!result) { - List command = new ArrayList<>(); - command.add("jar"); - command.addAll(Arrays.asList(params)); - throw new CommandExecutionException(command, Expect.SUCCESS); - } - return result; - } - - /** - * A general command calling method. - */ - public static int executeCommand(AnyToolArgs params) - throws CommandExecutionException, IOException, InterruptedException { - if (params.hasMinParams()) { - List cmd = (params.args != null) ? - params.args : - Arrays.asList(params.argsArr); - return executeCommand(cmd, params.extraEnv, params.stdOutput, - params.errOutput, params.whatToExpect); - } - throw new AssertionError("command has been invoked with less parameters than needed"); - } - - /** - * A helper method for calling a general command. - */ - private static int executeCommand( - List command, - Map extraEnv, - WriterHelper stdOutput, - WriterHelper errOutput, - Expect whatToExpt) - throws IOException, InterruptedException, CommandExecutionException { - ProcessBuilder pb = new ProcessBuilder(command); - - if (stdOutput != null) stdOutput.pipeOutput(pb); - if (errOutput != null) errOutput.pipeOutput(pb); - - if (extraEnv != null) { - pb.environment().putAll(extraEnv); - } - - Process p = pb.start(); - - if (stdOutput != null) stdOutput.readFromStream(p); - if (errOutput != null) errOutput.readFromStream(p); - - int result = p.waitFor(); - if ( (result == 0 && whatToExpt == Expect.SUCCESS) || - (result != 0 && whatToExpt == Expect.FAIL) ) { - return result; - } - - throw new CommandExecutionException(command, whatToExpt); - } - - /** - * This set of methods can be used instead of diff when the only needed - * result is the equality or inequality of the two given resources. - * - * A resource can be a file or a String list. - */ - public static void compareLines(Path aPath, Path otherPath, String encoding) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - compareLines(aPath, otherPath, encoding, false); - } - - public static void compareLines( - Path aPath, Path otherPath, String encoding, boolean trim) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - Charset charset = encoding != null ? - Charset.forName(encoding) : - defaultCharset; - List list1 = Files.readAllLines(aPath, charset); - List list2 = Files.readAllLines(otherPath, charset); - compareLines(list1, list2, trim); - } - - public static void compareLines(Path path, List strings, String encoding) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - compareLines(path, strings, encoding, false); - } - - public static void compareLines(Path path, List strings, - String encoding, boolean trim) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - Charset charset = encoding != null ? - Charset.forName(encoding) : - defaultCharset; - List list = Files.readAllLines(path, charset); - compareLines(list, strings, trim); - } - - public static void compareLines(List list1, List list2) - throws ResourcesNotEqualException { - compareLines(list1, list2, false); - } - - public static void compareLines(List list1, - List list2, boolean trim) throws ResourcesNotEqualException { - if ((list1 == list2) || (list1 == null && list2 == null)) return; - if (list1.size() != list2.size()) - throw new ResourcesNotEqualException(list1, list2); - int i = 0; - int j = 0; - while (i < list1.size() && - j < list2.size() && - equals(list1.get(i), list2.get(j), trim)) { - i++; j++; - } - if (!(i == list1.size() && j == list2.size())) - throw new ResourcesNotEqualException(list1, list2); - } - - private static boolean equals(String s1, String s2, boolean trim) { - return (trim ? s1.trim().equals(s2.trim()) : s1.equals(s2)); - } - - /** - * A set of simple grep-like methods, looks for regExpr in text. - * The content of text is split using the new line character as a pattern - * and later the regExpr is seek in every split line. If a match is found, - * the whole line is added to the result. - */ - public static List grep(String regExpr, String text, String sep) { - return grep(regExpr, splitLines(text, sep)); - } - - public static List grep(String regExpr, List text) { - List result = new ArrayList<>(); - Pattern pattern = Pattern.compile(regExpr); - for (String s : text) { - if (pattern.matcher(s).find()) { - result.add(s); - } - } - return result; - } - - public static List grep(String regExpr, File f) - throws IOException { - List lines = Files.readAllLines(f.toPath(), defaultCharset); - return grep(regExpr, lines); - } - - /** - * A touch-like method. - */ - public static boolean touch(String fileName) { - File file = new File(fileName); - return touch(file); - } - - public static boolean touch(File file) { - if (file.exists()) { - file.setLastModified(System.currentTimeMillis()); - return true; - } - return false; - } - - public static void createJavaFile(File outFile) throws IOException { - createJavaFile(outFile, null); - } - - /** - * A method for creating a valid but very simple java file. - */ - public static void createJavaFile(File outFile, File superClass) - throws IOException { - String srcStr = "public class " + getSimpleName(outFile) + " "; - if (superClass != null) { - srcStr = srcStr.concat("extends " + getSimpleName(superClass) + " "); - } - srcStr = srcStr.concat("{}"); - try (PrintWriter ps = new PrintWriter(new FileWriter(outFile))) { - ps.println(srcStr); - } - } - - /** - * Creates a java file name given its source. - * The file is created in the working directory, creating a directory - * tree if there is a package declaration. - */ - public static void createJavaFileFromSource(String source) throws IOException { - createJavaFileFromSource(null, source); - } - - /** - * Creates a java file name given its source. - * The file is created in the working directory, creating a directory - * tree if there is a package declaration or the argument initialPath - * has a valid path. - * - * e.i. if initialPath is foo/ and the source is: - * package bar; - * - * public class bazz {} - * - * this method will create the file foo/bar/bazz.java in the working - * directory. - */ - public static void createJavaFileFromSource(Path initialPath, - String source) throws IOException { - String fileName = getJavaFileNameFromSource(source); - String dirTree = getDirTreeFromSource(source); - Path path = (dirTree != null) ? - Paths.get(dirTree, fileName) : - Paths.get(fileName); - path = (initialPath != null) ? - initialPath.resolve(path): - path; - writeFile(path, source); - } - - static Pattern publicClassPattern = - Pattern.compile("public\\s+(?:class|enum|interface){1}\\s+(\\w+)"); - static Pattern packageClassPattern = - Pattern.compile("(?:class|enum|interface){1}\\s+(\\w+)"); - - /** - * Extracts the java file name from the class declaration. - * This method is intended for simple files and uses regular expressions, - * so comments matching the pattern can make the method fail. - */ - static String getJavaFileNameFromSource(String source) { - String className = null; - Matcher matcher = publicClassPattern.matcher(source); - if (matcher.find()) { - className = matcher.group(1) + ".java"; - } else { - matcher = packageClassPattern.matcher(source); - if (matcher.find()) { - className = matcher.group(1) + ".java"; - } else { - throw new AssertionError("Could not extract the java class " + - "name from the provided source"); - } - } - return className; - } - - static Pattern packagePattern = - Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); - - /** - * Extracts the path from the package declaration if present. - * This method is intended for simple files and uses regular expressions, - * so comments matching the pattern can make the method fail. - */ - private static String getDirTreeFromSource(String source) { - Matcher matcher = packagePattern.matcher(source); - return matcher.find() ? - matcher.group(1).replace(".", File.separator) : - null; - } - - /** - * A method for creating a jar's manifest file with supplied data. - */ - public static void mkManifestWithClassPath(String mainClass, - String... classes) throws IOException { - List lines = new ArrayList<>(); - - StringBuilder sb = new StringBuilder("Class-Path: ".length() + - classes[0].length()).append("Class-Path: ").append(classes[0]); - for (int i = 1; i < classes.length; i++) { - sb.append(" ").append(classes[i]); - } - lines.add(sb.toString()); - if (mainClass != null) { - lines.add(new StringBuilder("Main-Class: ".length() + - mainClass.length()) - .append("Main-Class: ") - .append(mainClass).toString()); - } - Files.write(Paths.get("MANIFEST.MF"), lines, - StandardOpenOption.CREATE, StandardOpenOption.WRITE, - StandardOpenOption.TRUNCATE_EXISTING); - } - - /** - * A utility method to obtain the file name. - */ - static String getSimpleName(File inFile) { - return inFile.toPath().getFileName().toString(); - } - - /** - * A method to write to a file, the directory tree is created if needed. - */ - public static File writeFile(Path path, String body) throws IOException { - File result; - if (path.getParent() != null) { - Files.createDirectories(path.getParent()); - } - try (FileWriter out = new FileWriter(result = path.toAbsolutePath().toFile())) { - out.write(body); - } - return result; - } - - public static File writeFile(String path, String body) throws IOException { - return writeFile(Paths.get(path), body); - } - - /** - * A rm-like method, the file is deleted only if it exists. - */ - public static void rm(Path path) throws Exception { - Files.deleteIfExists(path); - } - - public static void rm(String filename) throws Exception { - rm(Paths.get(filename)); - } - - public static void rm(File f) throws Exception { - rm(f.toPath()); - } - - /** - * Copy source file to destination file. - */ - public static void copyFile(File destfile, File srcfile) - throws IOException { - copyFile(destfile.toPath(), srcfile.toPath()); - } - - public static void copyFile(Path destPath, Path srcPath) - throws IOException { - Files.createDirectories(destPath); - Files.copy(srcPath, destPath, REPLACE_EXISTING); - } - - /** - * Splits a String using the System's line separator character as splitting point. - */ - public static List splitLines(String lines, String sep) { - return Arrays.asList(lines.split(sep)); - } - - /** - * Converts a String list into one String by appending the System's line separator - * character after each component. - */ - private static String listToString(List lines) { - StringBuilder sb = new StringBuilder(); - for (String s : lines) { - sb.append(s).append(lineSeparator); - } - return sb.toString(); - } - - /** - * Returns true if the OS is a Windows version. - */ - public static boolean isWindows() { - String osName = System.getProperty("os.name"); - return osName.toUpperCase().startsWith("WINDOWS"); - } - - /** - * Class representing an in-memory java source file. It is able to extract - * the file name from simple source codes using regular expressions. - */ - public static class JavaSource extends SimpleJavaFileObject { - String source; - String name; - - public JavaSource(String className, String source) { - super(URI.create(className), - JavaFileObject.Kind.SOURCE); - this.name = className; - this.source = source; - } - - public JavaSource(String source) { - super(URI.create(getJavaFileNameFromSource(source)), - JavaFileObject.Kind.SOURCE); - this.name = getJavaFileNameFromSource(source); - this.source = source; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - /** - * A file manager for compiling strings to byte arrays. - * This file manager delegates to another file manager - * to lookup classes on boot class path. - */ - public static final class MemoryFileManager extends ForwardingJavaFileManager { - /** - * Maps binary class names to class files stored as byte arrays. - */ - private final Map classes; - - /** - * Construct a memory file manager which delegates to the specified - * file manager for unknown sources. - * @param fileManager a file manager used to look up class files on class path, etc. - */ - public MemoryFileManager(JavaFileManager fileManager) { - super(fileManager); - classes = new HashMap<>(); - } - - @java.lang.Override - public JavaFileObject getJavaFileForOutput(Location location, - String name, - Kind kind, - FileObject sibling) - throws UnsupportedOperationException - { - return new JavaClassInArray(name); - } - - /** - * A file object representing a Java class file stored in a byte array. - */ - private class JavaClassInArray extends SimpleJavaFileObject { - - private final String name; - - /** - * Constructs a JavaClassInArray object. - * @param name binary name of the class to be stored in this file object - */ - JavaClassInArray(String name) { - super(URI.create("mfm:///" + name.replace('.','/') + Kind.CLASS.extension), - Kind.CLASS); - this.name = name; - } - - public OutputStream openOutputStream() { - return new FilterOutputStream(new ByteArrayOutputStream()) { - public void close() throws IOException { - out.close(); - ByteArrayOutputStream bos = (ByteArrayOutputStream)out; - classes.put(name, bos.toByteArray()); - } - }; - } - } - - } - -} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/links/LinksTest.java --- a/langtools/test/tools/javac/links/LinksTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/links/LinksTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 4266026 * @summary javac no longer follows symlinks - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main LinksTest */ @@ -33,7 +33,7 @@ import java.nio.file.Files; import java.nio.file.Paths; -//original test: test/tools/javac/links/links.sh +// Original test: test/tools/javac/links/links.sh public class LinksTest { private static final String BSrc = @@ -44,20 +44,18 @@ private static final String TSrc = "class T extends a.B {}"; - public static void main(String args[]) - throws Exception { -// mkdir tmp -// cp ${TESTSRC}/b/B.java tmp - ToolBox.writeFile(Paths.get("tmp", "B.java"), BSrc); + public static void main(String... args) throws Exception { + ToolBox tb = new ToolBox(); + tb.writeFile("tmp/B.java", BSrc); try { -// ln -s `pwd`/tmp "${TESTCLASSES}/a" Files.createSymbolicLink(Paths.get("a"), Paths.get("tmp")); - ////"${TESTJAVA}/bin/javac" ${TESTTOOLVMOPTS} -sourcepath "${TESTCLASSES}" -d "${TESTCLASSES}/classes" "${TESTSRC}/T.java" 2>&1 - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-sourcepath", ".", "-d", ".").setSources(TSrc); - ToolBox.javac(javacArgs); + + tb.new JavacTask() + .sourcepath(".") + .outdir(".") + .sources(TSrc) + .run(); } catch (UnsupportedOperationException e) { System.err.println("Symbolic links not supported on this system. The test can't finish"); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/newlines/NewLineTest.java --- a/langtools/test/tools/javac/newlines/NewLineTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/newlines/NewLineTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 4110560 4785453 * @summary portability : javac.properties - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NewLineTest */ @@ -39,18 +39,13 @@ public class NewLineTest { public static void main(String args[]) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -J-Dline.separator='@' > ${TMP1} 2>&1 + ToolBox tb = new ToolBox(); File javacErrOutput = new File("output.txt"); - ToolBox.AnyToolArgs cmdArgs = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-J-Dline.separator='@'") - .setErrOutput(javacErrOutput); - ToolBox.executeCommand(cmdArgs); + tb.new JavacTask(ToolBox.Mode.EXEC) + .redirect(ToolBox.OutputKind.STDERR, javacErrOutput.getPath()) + .options("-J-Dline.separator='@'") + .run(ToolBox.Expect.FAIL); -// result=`cat ${TMP1} | wc -l` -// if [ "$result" -eq 0 ] passed List lines = Files.readAllLines(javacErrOutput.toPath(), Charset.defaultCharset()); if (lines.size() != 1) { diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java --- a/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,8 +26,8 @@ * @bug 8038455 * @summary Ensure that formatting diagnostics with an already closed JavaCompiler won't crash * the compiler. - * @library /tools/javac/lib - * @build CompleteOnClosed ToolBox JavacTestingAbstractProcessor + * @library /tools/lib /tools/javac/lib + * @build ToolBox JavacTestingAbstractProcessor * @run main CompleteOnClosed */ diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java --- a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Aug 28 14:53:49 2014 -0700 @@ -26,7 +26,7 @@ * @bug 8038455 * @summary Verify that annotation processor can overwrite source and class files it generated * during previous compilations, and that the Symbols are updated appropriatelly. - * @library /tools/javac/lib/ + * @library /tools/lib /tools/javac/lib/ * @clean * * @build OverwriteBetweenCompilations ToolBox JavacTestingAbstractProcessor * @compile/ref=OverwriteBetweenCompilations_1.out -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java @@ -49,6 +49,7 @@ @SupportedOptions("pass") public class OverwriteBetweenCompilations extends JavacTestingAbstractProcessor { int round = 1; + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { Log log = Log.instance(((JavacProcessingEnvironment) processingEnv).getContext()); @@ -85,11 +86,17 @@ try (OutputStream out = filer.createClassFile("GeneratedClass").openOutputStream()) { String code = pass != 2 ? GENERATED_INIT : GENERATED_UPDATE; code = code.replace("NAME", "GeneratedClass"); - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs().appendArgs("-parameters").setSources(code); - Map codeMap = ToolBox.compile(args); - out.write(codeMap.get("GeneratedClass")); - } catch (IOException | ToolBox.CommandExecutionException e) { + + ToolBox tb = new ToolBox(); + ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager(); + tb.new JavacTask() + .fileManager(mfm) + .options("-parameters") + .sources(code) + .run(); + + out.write(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "GeneratedClass")); + } catch (IOException e) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString()); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javac/stackmap/StackMapTest.java --- a/langtools/test/tools/javac/stackmap/StackMapTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javac/stackmap/StackMapTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 4955930 * @summary The "method0" StackMap attribute should have two entries instead of three - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile StackMapTest.java * @run main StackMapTest @@ -34,7 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/javac/stackmap/T4955930.sh +// Original test: test/tools/javac/stackmap/T4955930.sh public class StackMapTest { class Test { @@ -48,16 +48,15 @@ } public static void main(String args[]) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} T4955930.java + ToolBox tb = new ToolBox(); + Path pathToClass = Paths.get(ToolBox.testClasses, "StackMapTest$Test.class"); + String javapOut = tb.new JavapTask() + .options("-v") + .classes(pathToClass.toString()) + .run() + .getOutput(ToolBox.OutputKind.DIRECT); -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -verbose T4955930 > ${TMP1} - Path pathToClass = Paths.get(System.getProperty("test.classes"), - "StackMapTest$Test.class"); - ToolBox.JavaToolArgs javapArgs = - new ToolBox.JavaToolArgs().setAllArgs("-v", pathToClass.toString()); - -// grep "StackMapTable: number_of_entries = 2" ${TMP1} - if (!ToolBox.javap(javapArgs).contains("StackMapTable: number_of_entries = 2")) + if (!javapOut.contains("StackMapTable: number_of_entries = 2")) throw new AssertionError("The number of entries of the stack map " + "table should be equal to 2"); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javah/6257087/T6257087.java --- a/langtools/test/tools/javah/6257087/T6257087.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javah/6257087/T6257087.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,12 @@ * @test * @bug 6257087 * @summary javah doesn't produce proper signatures for inner class native methods - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main T6257087 */ -import java.nio.file.Paths; +import java.util.List; public class T6257087 { @@ -58,13 +58,14 @@ "#endif"; public static void main(String[] args) throws Exception { - ToolBox.JavaToolArgs javahArgs = - new ToolBox.JavaToolArgs() - .setAllArgs("-cp", System.getProperty("test.classes"), "foo"); - ToolBox.javah(javahArgs); + ToolBox tb = new ToolBox(); + tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("foo") + .run(); - ToolBox.compareLines(Paths.get("foo_bar.h"), - ToolBox.splitLines(fooBarGoldenFile, "\n"), null, true); + List fooBarFile = tb.readAllLines("foo_bar.h"); + tb.checkEqual(fooBarFile, tb.split(fooBarGoldenFile, "\n")); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javah/T4942232/MissingParamClassTest.java --- a/langtools/test/tools/javah/T4942232/MissingParamClassTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javah/T4942232/MissingParamClassTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary Verifies that javah won't attempt to generate a header file if a * native method in a supplied class contains a parameter type whose corresponding * class is missing or not in the classpath - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile MissingParamClassTest.java * @clean MissingParamClassException @@ -39,32 +39,21 @@ import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -//original test: test/tools/javah/MissingParamClassTest.sh +// Original test: test/tools/javah/MissingParamClassTest.sh public class MissingParamClassTest { public static void main(String[] args) throws Exception { - //first steps done now by jtreg -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java" -//rm -f MissingParamClassException.class + ToolBox tb = new ToolBox(); -//"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1} - List errOutput = new ArrayList<>(); - ToolBox.JavaToolArgs javahParams = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setAllArgs("-classpath", System.getProperty("test.classes"), "ParamClassTest") - .setErrOutput(errOutput); - ToolBox.javah(javahParams); + String out = tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("ParamClassTest") + .run(ToolBox.Expect.FAIL) + .getOutput(ToolBox.OutputKind.DIRECT); -//if [ -f $GENERATED_HEADER_FILE ]; then fail -//if [ ! -s ${TMP1} ]; then fail - if (Files.exists(Paths.get("ParamClassTest.h")) || errOutput.size() == 0) + if (Files.exists(Paths.get("ParamClassTest.h")) || out.isEmpty()) throw new AssertionError("The only output generated by javah must be an error message"); - //jtreg again -//rm -f MissingParamClassException.class ParamClassTest.class -//rm -f $GENERATED_HEADER_FILE $TMP1 } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javah/constMacroTest/ConstMacroTest.java --- a/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,15 @@ * @summary Validates rewritten javah handling of class defined constants and * ensures that the appropriate macro definitions are placed in the generated * header file. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ConstMacroTest */ import java.io.*; -import java.nio.file.Paths; +import java.util.List; -//original test: test/tools/javah/ConstMacroTest.sh +// Original test: test/tools/javah/ConstMacroTest.sh public class ConstMacroTest { private static final String subClassConstsGoldenFileTemplate = @@ -71,27 +71,21 @@ "#endif\n" + "#endif"; - private static final String serialVersionUIDSuffix = - ToolBox.isWindows() ? "i64" : "LL"; ; + public static void main(String[] args) throws Exception { + ToolBox tb = new ToolBox(); - public static void main(String[] args) throws Exception { - //first steps are now done by jtreg -// cp "${TESTSRC}${FS}SuperClassConsts.java" . -// cp "${TESTSRC}${FS}SubClassConsts.java" . - -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}SubClassConsts.java" + tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("SubClassConsts") + .run(); -// "${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} SubClassConsts - ToolBox.JavaToolArgs successParams = - new ToolBox.JavaToolArgs() - .setAllArgs("-cp", System.getProperty("test.classes"), "SubClassConsts"); - ToolBox.javah(successParams); + String longSuffix = tb.isWindows() ? "i64" : "LL"; + List subClassConstsGoldenFile = tb.split( + String.format(subClassConstsGoldenFileTemplate, longSuffix), "\n"); -// diff ${DIFFOPTS} "${TESTSRC}${FS}${EXPECTED_JAVAH_OUT_FILE}" "${GENERATED_HEADER_FILE}" - String subClassConstGoldenFile = String.format(subClassConstsGoldenFileTemplate, - serialVersionUIDSuffix); - ToolBox.compareLines(Paths.get("SubClassConsts.h"), - ToolBox.splitLines(subClassConstGoldenFile, "\n"), null, true); + List subClassConstsFile = tb.readAllLines("SubClassConsts.h"); + + tb.checkEqual(subClassConstsFile, subClassConstsGoldenFile); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java --- a/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,23 @@ /* * @test * @bug 4798312 - * @summary In Windows, javap doesnt load classes from rt.jar - * @library /tools/javac/lib + * @summary In Windows, javap doesn't load classes from rt.jar + * @library /tools/lib * @build ToolBox * @run main JavapShouldLoadClassesFromRTJarTest */ + public class JavapShouldLoadClassesFromRTJarTest { public static void main(String[] args) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} java.lang.String - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs(). - setAllArgs("-v", "java.lang.String"); - if (ToolBox.javap(params).isEmpty()) + ToolBox tb = new ToolBox(); + String out = tb.new JavapTask() + .options("-v") + .classes("java.lang.String") + .run() + .getOutput(ToolBox.OutputKind.DIRECT); + + if (out.isEmpty()) throw new AssertionError("javap generated no output"); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javap/4866831/PublicInterfaceTest.java --- a/langtools/test/tools/javap/4866831/PublicInterfaceTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javap/4866831/PublicInterfaceTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,9 +1,5 @@ - -import java.nio.file.Path; -import java.nio.file.Paths; - /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,23 +25,29 @@ * @test * @bug 4866831 * @summary Verify that javap marks public interfaces as public - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main PublicInterfaceTest */ -//original test: test/tools/javap/PublicInterfaceTest.sh +import java.nio.file.Path; +import java.nio.file.Paths; + +// Original test: test/tools/javap/PublicInterfaceTest.sh public class PublicInterfaceTest { public interface Test {} public static void main(String[] args) throws Exception { -// "$JAVAP" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" NotPackagePrivateInterface | grep public - Path pathToClass = Paths.get(System.getProperty("test.classes"), - "PublicInterfaceTest$Test.class"); - ToolBox.JavaToolArgs javapParams = - new ToolBox.JavaToolArgs() - .setAllArgs(pathToClass.toString()); - if (!ToolBox.javap(javapParams).contains("public")) + ToolBox tb = new ToolBox(); + + Path pathToClass = Paths.get(ToolBox.testClasses, "PublicInterfaceTest$Test.class"); + + String out = tb.new JavapTask() + .classes(pathToClass.toString()) + .run() + .getOutput(ToolBox.OutputKind.DIRECT); + + if (!out.contains("public")) throw new AssertionError("The javap output does not contain \"public\""); } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/javap/stackmap/StackmapTest.java --- a/langtools/test/tools/javap/stackmap/StackmapTest.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/javap/stackmap/StackmapTest.java Thu Aug 28 14:53:49 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,15 @@ * @test * @bug 6271292 * @summary Verify that javap prints StackMapTable attribute contents - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main StackmapTest */ -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; -//original test: test/tools/javap/stackmap/T6271292.sh +// Original test: test/tools/javap/stackmap/T6271292.sh public class StackmapTest { private static final String TestSrc = @@ -58,41 +58,42 @@ "}\n"; private static final String goldenOut = - "frame_type = 255 /* full_frame */\n" + - "frame_type = 255 /* full_frame */\n" + - "frame_type = 73 /* same_locals_1_stack_item */\n" + - "frame_type = 255 /* full_frame */\n" + - "offset_delta = 19\n" + - "offset_delta = 0\n" + - "offset_delta = 2\n" + - "stack = [ uninitialized 0, uninitialized 0 ]\n" + - "stack = [ uninitialized 0, uninitialized 0, double ]\n" + - "stack = [ this ]\n" + - "stack = [ this, double ]\n" + - "locals = [ class \"[Ljava/lang/String;\" ]\n" + - "locals = [ class \"[Ljava/lang/String;\" ]\n" + - "locals = [ this, int ]\n"; + " frame_type = 255 /* full_frame */\n" + + " frame_type = 255 /* full_frame */\n" + + " frame_type = 73 /* same_locals_1_stack_item */\n" + + " frame_type = 255 /* full_frame */\n" + + " offset_delta = 19\n" + + " offset_delta = 0\n" + + " offset_delta = 2\n" + + " stack = [ uninitialized 0, uninitialized 0 ]\n" + + " stack = [ uninitialized 0, uninitialized 0, double ]\n" + + " stack = [ this ]\n" + + " stack = [ this, double ]\n" + + " locals = [ class \"[Ljava/lang/String;\" ]\n" + + " locals = [ class \"[Ljava/lang/String;\" ]\n" + + " locals = [ this, int ]\n"; public static void main(String[] args) throws Exception { - // @compile T6271292.java - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs().setSources(TestSrc); - ToolBox.javac(javacParams); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(TestSrc) + .run(); -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" -verbose T6271292 > "${JAVAPFILE}" - ToolBox.JavaToolArgs javapParams = - new ToolBox.JavaToolArgs() - .setAllArgs("-v", "Test.class"); - String out = ToolBox.javap(javapParams); - List grepResult = ToolBox.grep("frame_type", out, - ToolBox.lineSeparator); - grepResult.addAll(ToolBox.grep("offset_delta", out, ToolBox.lineSeparator)); - grepResult.addAll(ToolBox.grep("stack = ", out, ToolBox.lineSeparator)); - grepResult.addAll(ToolBox.grep("locals = ", out, ToolBox.lineSeparator)); - List goldenList = Arrays.asList(goldenOut.split("\n")); + List out = tb.new JavapTask() + .options("-v") + .classes("Test.class") + .run() + .getOutputLines(ToolBox.OutputKind.DIRECT); -// diff -w "${OUTFILE}" "${TESTSRC}${FS}T6271292.out" - ToolBox.compareLines(goldenList, grepResult, true); + List grepResult = new ArrayList<>(); + grepResult.addAll(tb.grep("frame_type", out)); + grepResult.addAll(tb.grep("offset_delta", out)); + grepResult.addAll(tb.grep("stack = ", out)); + grepResult.addAll(tb.grep("locals = ", out)); + + List goldenList = tb.split(goldenOut, "\n"); + tb.checkEqual(goldenList, grepResult); } } diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/lib/ToolBox.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/lib/ToolBox.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,1920 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FilterOutputStream; +import java.io.FilterWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URI; +import java.nio.charset.Charset; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import java.io.IOError; + +/** + * Utility methods and classes for writing jtreg tests for + * javac, javah, javap, and sjavac. (For javadoc support, + * see JavadocTester.) + * + *

There is support for common file operations similar to + * shell commands like cat, cp, diff, mv, rm, grep. + * + *

There is also support for invoking various tools, like + * javac, javah, javap, jar, java and other JDK tools. + * + *

File separators: for convenience, many operations accept strings + * to represent filenames. On all platforms on which JDK is supported, + * "/" is a legal filename component separator. In particular, even + * on Windows, where the official file separator is "\", "/" is a legal + * alternative. It is therefore recommended that any client code using + * strings to specify filenames should use "/". + * + * @author Vicente Romero (original) + * @author Jonathan Gibbons (revised) + */ +public class ToolBox { + /** The platform line separator. */ + public static final String lineSeparator = System.getProperty("line.separator"); + /** The platform OS name. */ + public static final String osName = System.getProperty("os.name"); + + /** The location of the class files for this test, or null if not set. */ + public static final String testClasses = System.getProperty("test.classes"); + /** The location of the source files for this test, or null if not set. */ + public static final String testSrc = System.getProperty("test.src"); + /** The location of the test JDK for this test, or null if not set. */ + public static final String testJDK = System.getProperty("test.jdk"); + + /** The current directory. */ + public static final Path currDir = Paths.get("."); + + /** The stream used for logging output. */ + public PrintStream out = System.err; + + JavaCompiler compiler; + StandardJavaFileManager standardJavaFileManager; + + /** + * Checks if the host OS is some version of Windows. + * @return true if the host OS is some version of Windows + */ + public boolean isWindows() { + return osName.toLowerCase(Locale.ENGLISH).startsWith("windows"); + } + + /** + * Splits a string around matches of the given regular expression. + * If the string is empty, an empty list will be returned. + * @param text the string to be split + * @param sep the delimiting regular expression + * @return the strings between the separators + */ + public List split(String text, String sep) { + if (text.isEmpty()) + return Collections.emptyList(); + return Arrays.asList(text.split(sep)); + } + + /** + * Checks if two lists of strings are equal. + * @param l1 the first list of strings to be compared + * @param l2 the second list of strings to be compared + * @throws Error if the lists are not equal + */ + public void checkEqual(List l1, List l2) throws Error { + if (!Objects.equals(l1, l2)) { + // l1 and l2 cannot both be null + if (l1 == null) + throw new Error("comparison failed: l1 is null"); + if (l2 == null) + throw new Error("comparison failed: l2 is null"); + // report first difference + for (int i = 0; i < Math.min(l1.size(), l2.size()); i++) { + String s1 = l1.get(i); + String s2 = l1.get(i); + if (!Objects.equals(s1, s2)) { + throw new Error("comparison failed, index " + i + + ", (" + s1 + ":" + s2 + ")"); + } + } + throw new Error("comparison failed: l1.size=" + l1.size() + ", l2.size=" + l2.size()); + } + } + + /** + * Filters a list of strings according to the given regular expression. + * @param regex the regular expression + * @param lines the strings to be filtered + * @return the strings matching the regular expression + */ + public List grep(String regex, List lines) { + return grep(Pattern.compile(regex), lines); + } + + /** + * Filters a list of strings according to the given regular expression. + * @param pattern the regular expression + * @param lines the strings to be filtered + * @return the strings matching the regular expression + */ + public List grep(Pattern pattern, List lines) { + return lines.stream() + .filter(s -> pattern.matcher(s).find()) + .collect(Collectors.toList()); + } + + /** + * Copies a file. + * If the given destination exists and is a directory, the copy is created + * in that directory. Otherwise, the copy will be placed at the destination, + * possibly overwriting any existing file. + *

Similar to the shell "cp" command: {@code cp from to}. + * @param from the file to be copied + * @param to where to copy the file + * @throws IOException if any error occurred while copying the file + */ + public void copyFile(String from, String to) throws IOException { + copyFile(Paths.get(from), Paths.get(to)); + } + + /** + * Copies a file. + * If the given destination exists and is a directory, the copy is created + * in that directory. Otherwise, the copy will be placed at the destination, + * possibly overwriting any existing file. + *

Similar to the shell "cp" command: {@code cp from to}. + * @param from the file to be copied + * @param to where to copy the file + * @throws IOException if an error occurred while copying the file + */ + public void copyFile(Path from, Path to) throws IOException { + if (Files.isDirectory(to)) { + to = to.resolve(from.getFileName()); + } else { + Files.createDirectories(to.getParent()); + } + Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Creates one of more directories. + * For each of the series of paths, a directory will be created, + * including any necessary parent directories. + *

Similar to the shell command: {@code mkdir -p paths}. + * @param paths the directories to be created + * @throws IOException if an error occurred while creating the directories + */ + public void createDirectories(String... paths) throws IOException { + if (paths.length == 0) + throw new IllegalArgumentException("no directories specified"); + for (String p: paths) + Files.createDirectories(Paths.get(p)); + } + + /** + * Creates one or more directories. + * For each of the series of paths, a directory will be created, + * including any necessary parent directories. + *

Similar to the shell command: {@code mkdir -p paths}. + * @param paths the directories to be created + * @throws IOException if an error occurred while creating the directories + */ + public void createDirectories(Path... paths) throws IOException { + if (paths.length == 0) + throw new IllegalArgumentException("no directories specified"); + for (Path p: paths) + Files.createDirectories(p); + } + + /** + * Deletes one or more files. + * Any directories to be deleted must be empty. + *

Similar to the shell command: {@code rm files}. + * @param files the files to be deleted + * @throws IOException if an error occurred while deleting the files + */ + public void deleteFiles(String... files) throws IOException { + if (files.length == 0) + throw new IllegalArgumentException("no files specified"); + for (String file: files) + Files.delete(Paths.get(file)); + } + + /** + * Moves a file. + * If the given destination exists and is a directory, the file will be moved + * to that directory. Otherwise, the file will be moved to the destination, + * possibly overwriting any existing file. + *

Similar to the shell "mv" command: {@code mv from to}. + * @param from the file to be moved + * @param to where to move the file + * @throws IOException if an error occurred while moving the file + */ + public void moveFile(String from, String to) throws IOException { + moveFile(Paths.get(from), Paths.get(to)); + } + + /** + * Moves a file. + * If the given destination exists and is a directory, the file will be moved + * to that directory. Otherwise, the file will be moved to the destination, + * possibly overwriting any existing file. + *

Similar to the shell "mv" command: {@code mv from to}. + * @param from the file to be moved + * @param to where to move the file + * @throws IOException if an error occurred while moving the file + */ + public void moveFile(Path from, Path to) throws IOException { + if (Files.isDirectory(to)) { + to = to.resolve(from.getFileName()); + } else { + Files.createDirectories(to.getParent()); + } + Files.move(from, to, StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Reads the lines of a file. + * The file is read using the default character encoding. + * @param path the file to be read + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(String path) throws IOException { + return readAllLines(path, null); + } + + /** + * Reads the lines of a file. + * The file is read using the default character encoding. + * @param path the file to be read + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(Path path) throws IOException { + return readAllLines(path, null); + } + + /** + * Reads the lines of a file using the given encoding. + * @param path the file to be read + * @param encoding the encoding to be used to read the file + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(String path, String encoding) throws IOException { + return readAllLines(Paths.get(path), encoding); + } + + /** + * Reads the lines of a file using the given encoding. + * @param path the file to be read + * @param encoding the encoding to be used to read the file + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(Path path, String encoding) throws IOException { + return Files.readAllLines(path, getCharset(encoding)); + } + + private Charset getCharset(String encoding) { + return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding); + } + + /** + * Writes a file containing the given content. + * Any necessary directories for the file will be created. + * @param path where to write the file + * @param content the content for the file + * @throws IOException if an error occurred while writing the file + */ + public void writeFile(String path, String content) throws IOException { + writeFile(Paths.get(path), content); + } + + /** + * Writes a file containing the given content. + * Any necessary directories for the file will be created. + * @param path where to write the file + * @param content the content for the file + * @throws IOException if an error occurred while writing the file + */ + public void writeFile(Path path, String content) throws IOException { + Path dir = path.getParent(); + if (dir != null) + Files.createDirectories(dir); + try (BufferedWriter w = Files.newBufferedWriter(path)) { + w.write(content); + } + } + + /** + * Writes one or more files containing Java source code. + * For each file to be written, the filename will be inferred from the + * given base directory, the package declaration (if present) and from the + * the name of the first class, interface or enum declared in the file. + *

For example, if the base directory is /my/dir/ and the content + * contains "package p; class C { }", the file will be written to + * /my/dir/p/C.java. + *

Note: the content is analyzed using regular expressions; + * errors can occur if any contents have initial comments that might trip + * up the analysis. + * @param dir the base directory + * @param contents the contents of the files to be written + * @throws IOException if an error occurred while writing any of the files. + */ + public void writeJavaFiles(Path dir, String... contents) throws IOException { + if (contents.length == 0) + throw new IllegalArgumentException("no content specified for any files"); + for (String c: contents) { + new JavaSource(c).write(dir); + } + } + + /** + * Returns the path for the binary of a JDK tool within {@link testJDK}. + * @param tool the name of the tool + * @return the path of the tool + */ + public Path getJDKTool(String tool) { + return Paths.get(testJDK, "bin", tool); + } + + /** + * Returns a string representing the contents of an {@code Iterable} as a list. + * @param the type parameter of the {@code Iterable} + * @param items the iterable + * @return the string + */ + String toString(Iterable items) { + return StreamSupport.stream(items.spliterator(), false) + .map(Objects::toString) + .collect(Collectors.joining(",", "[", "]")); + } + + /** + * The supertype for tasks. + * Complex operations are modelled by building and running a "Task" object. + * Tasks are typically configured in a fluent series of calls. + */ + public interface Task { + /** + * Returns the name of the task. + * @return the name of the task + */ + String name(); + + /** + * Executes the task as currently configured. + * @return a Result object containing the results of running the task + * @throws TaskError if the outcome of the task was not as expected + */ + Result run() throws TaskError; + } + + /** + * Exception thrown by {@code Task.run} when the outcome is not as + * expected. + */ + public static class TaskError extends Error { + /** + * Creates a TaskError object with the given message. + * @param message the message + */ + public TaskError(String message) { + super(message); + } + } + + /** + * An enum to indicate the mode a task should use it is when executed. + */ + public enum Mode { + /** + * The task should use the interface used by the command + * line launcher for the task. + * For example, for javac: com.sun.tools.javac.Main.compile + */ + CMDLINE, + /** + * The task should use a publicly defined API for the task. + * For example, for javac: javax.tools.JavaCompiler + */ + API, + /** + * The task should use the standard launcher for the task. + * For example, $JAVA_HOME/bin/javac + */ + EXEC + } + + /** + * An enum to indicate the expected success or failure of executing a task. + */ + public enum Expect { + /** It is expected that the task will complete successfully. */ + SUCCESS, + /** It is expected that the task will not complete successfully. */ + FAIL + } + + /** + * An enum to identify the streams that may be written by a {@code Task}. + */ + public enum OutputKind { + /** Identifies output written to {@code System.out} or {@code stdout}. */ + STDOUT, + /** Identifies output written to {@code System.err} or {@code stderr}. */ + STDERR, + /** Identifies output written to a stream provided directly to the task. */ + DIRECT + }; + + /** + * The results from running a {@link Task}. + * The results contain the exit code returned when the tool was invoked, + * and a map containing the output written to any streams during the + * execution of the tool. + * All tools support "stdout" and "stderr". + * Tools that take an explicit PrintWriter save output written to that + * stream as "main". + */ + public class Result { + + final Task task; + final int exitCode; + final Map outputMap; + + Result(Task task, int exitCode, Map outputMap) { + this.task = task; + this.exitCode = exitCode; + this.outputMap = outputMap; + } + + /** + * Returns the content of a specified stream. + * @param outputKind the kind of the selected stream + * @return the content that was written to that stream when the tool + * was executed. + */ + public String getOutput(OutputKind outputKind) { + return outputMap.get(outputKind); + } + + /** + * Returns the content of a named stream as a list of lines. + * @param outputKind the kind of the selected stream + * @return the content that was written to that stream when the tool + * was executed. + */ + public List getOutputLines(OutputKind outputKind) { + return Arrays.asList(outputMap.get(outputKind).split(lineSeparator)); + } + + /** + * Writes the content of the specified stream to the log. + * @param kind the kind of the selected stream + * @return this Result object + */ + public Result write(OutputKind kind) { + String text = getOutput(kind); + if (text == null || text.isEmpty()) + out.println("[" + task.name() + ":" + kind + "]: empty"); + else { + out.println("[" + task.name() + ":" + kind + "]:"); + out.print(text); + } + return this; + } + + /** + * Writes the content of all streams with any content to the log. + * @return this Result object + */ + public Result writeAll() { + outputMap.forEach((name, text) -> { + if (!text.isEmpty()) { + out.println("[" + name + "]:"); + out.print(text); + } + }); + return this; + } + } + + /** + * A utility base class to simplify the implementation of tasks. + * Provides support for running the task in a process and for + * capturing output written by the task to stdout, stderr and + * other writers where applicable. + * @param the implementing subclass + */ + protected static abstract class AbstractTask> implements Task { + protected final Mode mode; + private final Map redirects = new EnumMap<>(OutputKind.class); + private final Map envVars = new HashMap<>(); + private Expect expect = Expect.SUCCESS; + int expectedExitCode = 0; + + /** + * Create a task that will execute in the specified mode. + * @param mode the mode + */ + protected AbstractTask(Mode mode) { + this.mode = mode; + } + + /** + * Sets the expected outcome of the task and calls {@code run()}. + * @param expect the expected outcome + * @return the result of calling {@code run()} + */ + public Result run(Expect expect) { + expect(expect, Integer.MIN_VALUE); + return run(); + } + + /** + * Sets the expected outcome of the task and calls {@code run()}. + * @param expect the expected outcome + * @param exitCode the expected exit code if the expected outcome + * is {@code FAIL} + * @return the result of calling {@code run()} + */ + public Result run(Expect expect, int exitCode) { + expect(expect, exitCode); + return run(); + } + + /** + * Sets the expected outcome and expected exit code of the task. + * The exit code will not be checked if the outcome is + * {@code Expect.SUCCESS} or if the exit code is set to + * {@code Integer.MIN_VALUE}. + * @param expect the expected outcome + * @param exitCode the expected exit code + */ + protected void expect(Expect expect, int exitCode) { + this.expect = expect; + this.expectedExitCode = exitCode; + } + + /** + * Checks the exit code contained in a {@code Result} against the + * expected outcome and exit value + * @param result the result object + * @return the result object + * @throws TaskError if the exit code stored in the result object + * does not match the expected outcome and exit code. + */ + protected Result checkExit(Result result) throws TaskError { + switch (expect) { + case SUCCESS: + if (result.exitCode != 0) { + result.writeAll(); + throw new TaskError("Task " + name() + " failed: rc=" + result.exitCode); + } + break; + + case FAIL: + if (result.exitCode == 0) { + result.writeAll(); + throw new TaskError("Task " + name() + " succeeded unexpectedly"); + } + + if (expectedExitCode != Integer.MIN_VALUE + && result.exitCode != expectedExitCode) { + result.writeAll(); + throw new TaskError("Task " + name() + "failed with unexpected exit code " + + result.exitCode + ", expected " + expectedExitCode); + } + break; + } + return result; + } + + /** + * Sets an environment variable to be used by this task. + * @param name the name of the environment variable + * @param value the value for the environment variable + * @return this task object + * @throws IllegalStateException if the task mode is not {@code EXEC} + */ + protected T envVar(String name, String value) { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + envVars.put(name, value); + return (T) this; + } + + /** + * Redirects output from an output stream to a file. + * @param outputKind the name of the stream to be redirected. + * @param path the file + * @return this task object + * @throws IllegalStateException if the task mode is not {@code EXEC} + */ + protected T redirect(OutputKind outputKind, String path) { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + redirects.put(outputKind, path); + return (T) this; + } + + /** + * Returns a {@code ProcessBuilder} initialized with any + * redirects and environment variables that have been set. + * @return a {@code ProcessBuilder} + */ + protected ProcessBuilder getProcessBuilder() { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + ProcessBuilder pb = new ProcessBuilder(); + if (redirects.get(OutputKind.STDOUT) != null) + pb.redirectOutput(new File(redirects.get(OutputKind.STDOUT))); + if (redirects.get(OutputKind.STDERR) != null) + pb.redirectError(new File(redirects.get(OutputKind.STDERR))); + pb.environment().putAll(envVars); + return pb; + } + + /** + * Collects the output from a process and saves it in a {@code Result}. + * @param tb the {@code ToolBox} containing the task {@code t} + * @param t the task initiating the process + * @param p the process + * @return a Result object containing the output from the process and its + * exit value. + * @throws InterruptedException if the thread is interrupted + */ + protected Result runProcess(ToolBox tb, Task t, Process p) throws InterruptedException { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + ProcessOutput sysOut = new ProcessOutput(p.getInputStream()).start(); + ProcessOutput sysErr = new ProcessOutput(p.getErrorStream()).start(); + sysOut.waitUntilDone(); + sysErr.waitUntilDone(); + int rc = p.waitFor(); + Map outputMap = new EnumMap<>(OutputKind.class); + outputMap.put(OutputKind.STDOUT, sysOut.getOutput()); + outputMap.put(OutputKind.STDERR, sysErr.getOutput()); + return checkExit(tb.new Result(t, rc, outputMap)); + } + + /** + * Thread-friendly class to read the output from a process until the stream + * is exhausted. + */ + static class ProcessOutput implements Runnable { + ProcessOutput(InputStream from) { + in = new BufferedReader(new InputStreamReader(from)); + out = new StringBuilder(); + } + + ProcessOutput start() { + new Thread(this).start(); + return this; + } + + @Override + public void run() { + try { + String line; + while ((line = in.readLine()) != null) { + out.append(line).append("\n"); + } + } catch (IOException e) { + } + synchronized (this) { + done = true; + notifyAll(); + } + } + + synchronized void waitUntilDone() throws InterruptedException { + boolean interrupted = false; + + // poll interrupted flag, while waiting for copy to complete + while (!(interrupted = Thread.interrupted()) && !done) + wait(1000); + + if (interrupted) + throw new InterruptedException(); + } + + String getOutput() { + return out.toString(); + } + + private BufferedReader in; + private final StringBuilder out; + private boolean done; + } + + /** + * Utility class to simplify the handling of temporarily setting a + * new stream for System.out or System.err. + */ + static class StreamOutput { + // Functional interface to set a stream. + // Expected use: System::setOut, System::setErr + private interface Initializer { + void set(PrintStream s); + } + + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + private final PrintStream ps = new PrintStream(baos); + private final PrintStream prev; + private final Initializer init; + + StreamOutput(PrintStream s, Initializer init) { + prev = s; + init.set(ps); + this.init = init; + } + + /** + * Closes the stream and returns the contents that were written to it. + * @return the contents that were written to it. + */ + String close() { + init.set(prev); + ps.close(); + return baos.toString(); + } + } + + /** + * Utility class to simplify the handling of creating an in-memory PrintWriter. + */ + static class WriterOutput { + private final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + + /** + * Closes the stream and returns the contents that were written to it. + * @return the contents that were written to it. + */ + String close() { + pw.close(); + return sw.toString(); + } + } + } + + /** + * A task to configure and run the Java compiler, javac. + */ + public class JavacTask extends AbstractTask { + private boolean includeStandardOptions; + private String classpath; + private String sourcepath; + private String outdir; + private List options; + private List classes; + private List files; + private List fileObjects; + private JavaFileManager fileManager; + + /** + * Creates a task to execute {@code javac} using API mode. + */ + public JavacTask() { + super(Mode.API); + } + + /** + * Creates a task to execute {@code javac} in a specified mode. + * @param mode the mode to be used + */ + public JavacTask(Mode mode) { + super(mode); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavacTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the sourcepath. + * @param sourcepath the sourcepath + * @return this task object + */ + public JavacTask sourcepath(String sourcepath) { + this.sourcepath = sourcepath; + return this; + } + + /** + * Sets the output directory. + * @param outdir the output directory + * @return this task object + */ + public JavacTask outdir(String outdir) { + this.outdir = outdir; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavacTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavacTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * Sets the files to be compiled or analyzed. + * @param files the files + * @return this task object + */ + public JavacTask files(String... files) { + this.files = Arrays.asList(files); + return this; + } + + /** + * Sets the files to be compiled or analyzed. + * @param files the files + * @return this task object + */ + public JavacTask files(Path... files) { + this.files = Stream.of(files) + .map(Path::toString) + .collect(Collectors.toList()); + return this; + } + + /** + * Sets the sources to be compiled or analyzed. + * Each source string is converted into an in-memory object that + * can be passed directly to the compiler. + * @param sources the sources + * @return this task object + */ + public JavacTask sources(String... sources) { + fileObjects = Stream.of(sources) + .map(s -> new JavaSource(s)) + .collect(Collectors.toList()); + return this; + } + + /** + * Sets the file manager to be used by this task. + * @param fileManager the file manager + * @return this task object + */ + public JavacTask fileManager(JavaFileManager fileManager) { + this.fileManager = fileManager; + return this; + } + + /** + * {@inheritDoc} + * @return the name "javac" + */ + @Override + public String name() { + return "javac"; + } + + /** + * Calls the compiler with the arguments as currently configured. + * @return a Result object indicating the outcome of the compilation + * and the content of any output written to stdout, stderr, or the + * main stream by the compiler. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + if (mode == Mode.EXEC) + return runExec(); + + WriterOutput direct = new WriterOutput(); + // The following are to catch output to System.out and System.err, + // in case these are used instead of the primary (main) stream + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + int rc; + Map outputMap = new HashMap<>(); + try { + switch (mode == null ? Mode.API : mode) { + case API: + rc = runAPI(direct.pw); + break; + case CMDLINE: + rc = runCommand(direct.pw); + break; + default: + throw new IllegalStateException(); + } + } catch (IOException e) { + out.println("Exception occurred: " + e); + rc = 99; + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + + private int runAPI(PrintWriter pw) throws IOException { +// if (compiler == null) { + // TODO: allow this to be set externally +// compiler = ToolProvider.getSystemJavaCompiler(); + compiler = JavacTool.create(); +// } + + if (fileManager == null) + fileManager = compiler.getStandardFileManager(null, null, null); + if (outdir != null) + setLocation(StandardLocation.CLASS_OUTPUT, toFiles(outdir)); + if (classpath != null) + setLocation(StandardLocation.CLASS_PATH, toFiles(classpath)); + if (sourcepath != null) + setLocation(StandardLocation.SOURCE_PATH, toFiles(sourcepath)); + List allOpts = new ArrayList<>(); + if (options != null) + allOpts.addAll(options); + + Iterable allFiles = joinFiles(files, fileObjects); + JavaCompiler.CompilationTask task = compiler.getTask(pw, + fileManager, + null, // diagnostic listener; should optionally collect diags + allOpts, + classes, + allFiles); + return ((JavacTaskImpl) task).doCall().exitCode; + } + + private void setLocation(StandardLocation location, List files) throws IOException { + if (!(fileManager instanceof StandardJavaFileManager)) + throw new IllegalStateException("not a StandardJavaFileManager"); + ((StandardJavaFileManager) fileManager).setLocation(location, files); + } + + private int runCommand(PrintWriter pw) { + List args = getAllArgs(); + String[] argsArray = args.toArray(new String[args.size()]); + return com.sun.tools.javac.Main.compile(argsArray, pw); + } + + private Result runExec() { + List args = new ArrayList<>(); + Path javac = getJDKTool("javac"); + args.add(javac.toString()); + if (includeStandardOptions) { + args.addAll(split(System.getProperty("test.tool.vm.opts"), " +")); + args.addAll(split(System.getProperty("test.compiler.opts"), " +")); + } + args.addAll(getAllArgs()); + + String[] argsArray = args.toArray(new String[args.size()]); + ProcessBuilder pb = getProcessBuilder(); + pb.command(argsArray); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + + private List getAllArgs() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (outdir != null) { + args.add("-d"); + args.add(outdir); + } + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (sourcepath != null) { + args.add("-sourcepath"); + args.add(sourcepath); + } + if (classes != null) + args.addAll(classes); + if (files != null) + args.addAll(files); + + return args; + } + + private List toFiles(String path) { + List result = new ArrayList<>(); + for (String s: path.split(File.pathSeparator)) { + if (!s.isEmpty()) + result.add(new File(s)); + } + return result; + } + + private Iterable joinFiles( + List files, List fileObjects) { + if (files == null) + return fileObjects; + if (standardJavaFileManager == null) + standardJavaFileManager = compiler.getStandardFileManager(null, null, null); + Iterable filesAsFileObjects = + standardJavaFileManager.getJavaFileObjectsFromStrings(files); + if (fileObjects == null) + return filesAsFileObjects; + List combinedList = new ArrayList<>(); + for (JavaFileObject o: filesAsFileObjects) + combinedList.add(o); + combinedList.addAll(fileObjects); + return combinedList; + } + } + + /** + * A task to configure and run the native header tool, javah. + */ + public class JavahTask extends AbstractTask { + private String classpath; + private List options; + private List classes; + + /** + * Create a task to execute {@code javah} using {@code CMDLINE} mode. + */ + public JavahTask() { + super(Mode.CMDLINE); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavahTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavahTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavahTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * {@inheritDoc} + * @return the name "javah" + */ + @Override + public String name() { + return "javah"; + } + + /** + * Calls the javah tool with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout, stderr, or the + * main stream provided to the task. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (classes != null) + args.addAll(classes); + + WriterOutput direct = new WriterOutput(); + // These are to catch output to System.out and System.err, + // in case these are used instead of the primary streams + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + int rc; + Map outputMap = new HashMap<>(); + try { + rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), direct.pw); + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + } + + /** + * A task to configure and run the disassembler tool, javap. + */ + public class JavapTask extends AbstractTask { + private String classpath; + private List options; + private List classes; + + /** + * Create a task to execute {@code javap} using {@code CMDLINE} mode. + */ + public JavapTask() { + super(Mode.CMDLINE); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavapTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavapTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavapTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * {@inheritDoc} + * @return the name "javap" + */ + @Override + public String name() { + return "javap"; + } + + /** + * Calls the javap tool with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout, stderr, or the + * main stream. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (classes != null) + args.addAll(classes); + + WriterOutput direct = new WriterOutput(); + // These are to catch output to System.out and System.err, + // in case these are used instead of the primary streams + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + + int rc; + Map outputMap = new HashMap<>(); + try { + rc = com.sun.tools.javap.Main.run(args.toArray(new String[args.size()]), direct.pw); + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + } + + /** + * A task to configure and run the jar file utility. + */ + public class JarTask extends AbstractTask { + private Path jar; + private Manifest manifest; + private String classpath; + private String mainClass; + private Path baseDir; + private List paths; + + /** + * Creates a task to write jar files, using API mode. + */ + public JarTask() { + super(Mode.API); + paths = Collections.emptyList(); + } + + /** + * Creates a JarTask for use with a given jar file. + * @param path the file + */ + public JarTask(String path) { + this(); + jar = Paths.get(path); + } + + /** + * Sets a manifest for the jar file. + * @param manifest the manifest + * @return this task object + */ + public JarTask manifest(Manifest manifest) { + this.manifest = manifest; + return this; + } + + /** + * Sets a manifest for the jar file. + * @param manifest a string containing the contents of the manifest + * @return this task object + * @throws IOException if there is a problem creating the manifest + */ + public JarTask manifest(String manifest) throws IOException { + this.manifest = new Manifest(new ByteArrayInputStream(manifest.getBytes())); + return this; + } + + /** + * Sets the classpath to be written to the {@code Class-Path} + * entry in the manifest. + * @param classpath the classpath + * @return this task object + */ + public JarTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the class to be written to the {@code Main-Class} + * entry in the manifest.. + * @param mainClass the name of the main class + * @return this task object + */ + public JarTask mainClass(String mainClass) { + this.mainClass = mainClass; + return this; + } + + /** + * Sets the base directory for files to be written into the jar file. + * @param baseDir the base directory + * @return this task object + */ + public JarTask baseDir(String baseDir) { + this.baseDir = Paths.get(baseDir); + return this; + } + + /** + * Sets the files to be written into the jar file. + * @param files the files + * @return this task object + */ + public JarTask files(String... files) { + this.paths = Stream.of(files) + .map(file -> Paths.get(file)) + .collect(Collectors.toList()); + return this; + } + + /** + * Provides limited jar command-like functionality. + * The supported commands are: + *

    + *
  • jar cf jarfile -C dir files... + *
  • jar cfm jarfile manifestfile -C dir files... + *
+ * Any values specified by other configuration methods will be ignored. + * @param args arguments in the style of those for the jar command + * @return a Result object containing the results of running the task + */ + public Result run(String... args) { + if (args.length < 2) + throw new IllegalArgumentException(); + + ListIterator iter = Arrays.asList(args).listIterator(); + String first = iter.next(); + switch (first) { + case "cf": + jar = Paths.get(iter.next()); + break; + case "cfm": + jar = Paths.get(iter.next()); + try (InputStream in = Files.newInputStream(Paths.get(iter.next()))) { + manifest = new Manifest(in); + } catch (IOException e) { + throw new IOError(e); + } + break; + } + + if (iter.hasNext()) { + if (iter.next().equals("-C")) + baseDir = Paths.get(iter.next()); + else + iter.previous(); + } + + paths = new ArrayList<>(); + while (iter.hasNext()) + paths.add(Paths.get(iter.next())); + + return run(); + } + + /** + * {@inheritDoc} + * @return the name "jar" + */ + @Override + public String name() { + return "jar"; + } + + /** + * Creates a jar file with the arguments as currently configured. + * @return a Result object indicating the outcome of the compilation + * and the content of any output written to stdout, stderr, or the + * main stream by the compiler. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + Manifest m = (manifest == null) ? new Manifest() : manifest; + Attributes mainAttrs = m.getMainAttributes(); + if (mainClass != null) + mainAttrs.put(Attributes.Name.MAIN_CLASS, mainClass); + if (classpath != null) + mainAttrs.put(Attributes.Name.CLASS_PATH, classpath); + + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + + int rc; + Map outputMap = new HashMap<>(); + + try (OutputStream os = Files.newOutputStream(jar); + JarOutputStream jos = openJar(os, m)) { + Path base = (baseDir == null) ? currDir : baseDir; + for (Path path: paths) { + Files.walkFileTree(base.resolve(path), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + JarEntry e = new JarEntry(base.relativize(file).toString()); + jos.putNextEntry(e); + jos.write(Files.readAllBytes(file)); + jos.closeEntry(); + return FileVisitResult.CONTINUE; + } catch (IOException e) { + System.err.println("Error adding " + file + " to jar file: " + e); + return FileVisitResult.TERMINATE; + } + } + }); + } + rc = 0; + } catch (IOException e) { + System.err.println("Error opening " + jar + ": " + e); + rc = 1; + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + + private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException { + if (m == null || m.getMainAttributes().isEmpty() && m.getEntries().isEmpty()) { + return new JarOutputStream(os); + } else { + if (m.getMainAttributes().get(Attributes.Name.MANIFEST_VERSION) == null) + m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + return new JarOutputStream(os, m); + } + } + + } + + /** + * A task to configure and run the Java launcher. + */ + public class JavaTask extends AbstractTask { + boolean includeStandardOptions = true; + private String classpath; + private List vmOptions; + private String className; + private List classArgs; + + /** + * Create a task to run the Java launcher, using {@code EXEC} mode. + */ + public JavaTask() { + super(Mode.EXEC); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavaTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the VM options. + * @param vmOptions the options + * @return this task object + */ + public JavaTask vmOptions(String... vmOptions) { + this.vmOptions = Arrays.asList(vmOptions); + return this; + } + + /** + * Sets the name of the class to be executed. + * @param className the name of the class + * @return this task object + */ + public JavaTask className(String className) { + this.className = className; + return this; + } + + /** + * Sets the arguments for the class to be executed. + * @param classArgs the arguments + * @return this task object + */ + public JavaTask classArgs(String... classArgs) { + this.classArgs = Arrays.asList(classArgs); + return this; + } + + /** + * {@inheritDoc} + * @return the name "java" + */ + @Override + public String name() { + return "java"; + } + + /** + * Calls the Java launcher with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout or stderr. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + args.add(getJDKTool("java").toString()); + if (includeStandardOptions) { + args.addAll(split(System.getProperty("test.vm.opts"), " +")); + args.addAll(split(System.getProperty("test.java.opts"), " +")); + } + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (vmOptions != null) + args.addAll(vmOptions); + if (className != null) + args.add(className); + if (classArgs != null) + args.addAll(classArgs); + ProcessBuilder pb = getProcessBuilder(); + pb.command(args); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + } + + /** + * A task to configure and run a general command. + */ + public class ExecTask extends AbstractTask { + private final String command; + private List args; + + /** + * Create a task to execute a given command, to be run using {@code EXEC} mode. + * @param command the command to be executed + */ + public ExecTask(String command) { + super(Mode.EXEC); + this.command = command; + } + + /** + * Create a task to execute a given command, to be run using {@code EXEC} mode. + * @param command the command to be executed + */ + public ExecTask(Path command) { + super(Mode.EXEC); + this.command = command.toString(); + } + + /** + * Sets the arguments for the command to be executed + * @param args the arguments + * @return this task object + */ + public ExecTask args(String... args) { + this.args = Arrays.asList(args); + return this; + } + + /** + * {@inheritDoc} + * @return the name "exec" + */ + @Override + public String name() { + return "exec"; + } + + /** + * Calls the command with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout or stderr. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List cmdArgs = new ArrayList<>(); + cmdArgs.add(command); + if (args != null) + cmdArgs.addAll(args); + ProcessBuilder pb = getProcessBuilder(); + pb.command(cmdArgs); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + } + + /** + * An in-memory Java source file. + * It is able to extract the file name from simple source text using + * regular expressions. + */ + public static class JavaSource extends SimpleJavaFileObject { + private final String source; + + /** + * Creates a in-memory file object for Java source code. + * @param className the name of the class + * @param source the source text + */ + public JavaSource(String className, String source) { + super(URI.create(className), JavaFileObject.Kind.SOURCE); + this.source = source; + } + + /** + * Creates a in-memory file object for Java source code. + * The name of the class will be inferred from the source code. + * @param source the source text + */ + public JavaSource(String source) { + super(URI.create(getJavaFileNameFromSource(source)), + JavaFileObject.Kind.SOURCE); + this.source = source; + } + + /** + * Writes the source code to a file in the current directory. + * @throws IOException if there is a problem writing the file + */ + public void write() throws IOException { + write(currDir); + } + + /** + * Writes the source code to a file in a specified directory. + * @param dir the directory + * @throws IOException if there is a problem writing the file + */ + public void write(Path dir) throws IOException { + Path file = dir.resolve(getJavaFileNameFromSource(source)); + Files.createDirectories(file.getParent()); + try (BufferedWriter out = Files.newBufferedWriter(file)) { + out.write(source.replace("\n", lineSeparator)); + } + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + + private static Pattern packagePattern = + Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); + private static Pattern classPattern = + Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)"); + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + */ + static String getJavaFileNameFromSource(String source) { + String packageName = null; + + Matcher matcher = packagePattern.matcher(source); + if (matcher.find()) + packageName = matcher.group(1).replace(".", "/"); + + matcher = classPattern.matcher(source); + if (matcher.find()) { + String className = matcher.group(1) + ".java"; + return (packageName == null) ? className : packageName + "/" + className; + } else { + throw new Error("Could not extract the java class " + + "name from the provided source"); + } + } + } + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + * @deprecated This is a legacy method for compatibility with ToolBox v1. + * Use {@link JavaSource#getName JavaSource.getName} instead. + * @param source the source text + * @return the Java file name inferred from the source + */ + @Deprecated + public static String getJavaFileNameFromSource(String source) { + return JavaSource.getJavaFileNameFromSource(source); + } + + /** + * A memory file manager, for saving generated files in memory. + * The file manager delegates to a separate file manager for listing and + * reading input files. + */ + public static class MemoryFileManager extends ForwardingJavaFileManager { + private interface Content { + byte[] getBytes(); + String getString(); + } + + /** + * Maps binary class names to generated content. + */ + final Map> files; + + /** + * Construct a memory file manager which stores output files in memory, + * and delegates to a default file manager for input files. + */ + public MemoryFileManager() { + this(JavacTool.create().getStandardFileManager(null, null, null)); + } + + /** + * Construct a memory file manager which stores output files in memory, + * and delegates to a specified file manager for input files. + * @param fileManager the file manager to be used for input files + */ + public MemoryFileManager(JavaFileManager fileManager) { + super(fileManager); + files = new HashMap<>(); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, + String name, + JavaFileObject.Kind kind, + FileObject sibling) + { + return new MemoryFileObject(location, name, kind); + } + + /** + * Returns the content written to a file in a given location, + * or null if no such file has been written. + * @param location the location + * @param name the name of the file + * @return the content as an array of bytes + */ + public byte[] getFileBytes(Location location, String name) { + Content content = getFile(location, name); + return (content == null) ? null : content.getBytes(); + } + + /** + * Returns the content written to a file in a given location, + * or null if no such file has been written. + * @param location the location + * @param name the name of the file + * @return the content as a string + */ + public String getFileString(Location location, String name) { + Content content = getFile(location, name); + return (content == null) ? null : content.getString(); + } + + private Content getFile(Location location, String name) { + Map filesForLocation = files.get(location); + return (filesForLocation == null) ? null : filesForLocation.get(name); + } + + private void save(Location location, String name, Content content) { + Map filesForLocation = files.get(location); + if (filesForLocation == null) + files.put(location, filesForLocation = new HashMap<>()); + filesForLocation.put(name, content); + } + + /** + * A writable file object stored in memory. + */ + private class MemoryFileObject extends SimpleJavaFileObject { + private final Location location; + private final String name; + + /** + * Constructs a memory file object. + * @param name binary name of the class to be stored in this file object + */ + MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) { + super(URI.create("mfm:///" + name.replace('.','/') + kind.extension), + Kind.CLASS); + this.location = location; + this.name = name; + } + + @Override + public OutputStream openOutputStream() { + return new FilterOutputStream(new ByteArrayOutputStream()) { + @Override + public void close() throws IOException { + out.close(); + byte[] bytes = ((ByteArrayOutputStream) out).toByteArray(); + save(location, name, new Content() { + @Override + public byte[] getBytes() { + return bytes; + } + @Override + public String getString() { + return new String(bytes); + } + + }); + } + }; + } + + @Override + public Writer openWriter() { + return new FilterWriter(new StringWriter()) { + @Override + public void close() throws IOException { + out.close(); + String text = ((StringWriter) out).toString(); + save(location, name, new Content() { + @Override + public byte[] getBytes() { + return text.getBytes(); + } + @Override + public String getString() { + return text; + } + + }); + } + }; + } + } + + } + +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/sjavac/IdleShutdown.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/sjavac/IdleShutdown.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044131 + * @summary Tests the hooks used for detecting idleness of the sjavac server. + * @build Wrapper + * @run main Wrapper IdleShutdown + */ +import java.io.File; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.IdleResetSjavac; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; +import com.sun.tools.sjavac.server.Terminable; + + +public class IdleShutdown { + + final static long TEST_START = System.currentTimeMillis(); + final static long TIMEOUT_MS = 3000; + + public static void main(String[] args) throws InterruptedException { + + final AtomicLong timeoutTimestamp = new AtomicLong(-1); + + log("Starting IdleCallbackJavacService with timeout: " + TIMEOUT_MS); + Sjavac service = new IdleResetSjavac( + new NoopJavacService(), + new Terminable() { + public void shutdown(String msg) { + // Record the idle timeout time + log("Timeout detected"); + timeoutTimestamp.set(System.currentTimeMillis()); + } + }, + TIMEOUT_MS); + + // Make sure it didn't timeout immediately + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + // Call various methods and wait less than TIMEOUT_MS in between + Thread.sleep(TIMEOUT_MS - 1000); + log("Getting sys info"); + service.getSysInfo(); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Getting sys info"); + service.getSysInfo(); + + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Compiling"); + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Compiling"); + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + long expectedTimeout = System.currentTimeMillis() + TIMEOUT_MS; + + // Wait for actual timeout + log("Awaiting idle timeout"); + Thread.sleep(TIMEOUT_MS + 1000); + + // Check result + if (timeoutTimestamp.get() == -1) + throw new AssertionError("Timeout never occurred"); + + long error = Math.abs(expectedTimeout - timeoutTimestamp.get()); + log("Timeout error: " + error + " ms"); + if (error > TIMEOUT_MS * .1) + throw new AssertionError("Error too big"); + + log("Shutting down"); + service.shutdown(); + } + + private static void log(String msg) { + long logTime = System.currentTimeMillis() - TEST_START; + System.out.printf("After %5d ms: %s%n", logTime, msg); + } + + private static class NoopJavacService implements Sjavac { + @Override + public SysInfo getSysInfo() { + // Attempt to trigger idle timeout during a call by sleeping + try { + Thread.sleep(TIMEOUT_MS + 1000); + } catch (InterruptedException e) { + } + return null; + } + @Override + public void shutdown() { + } + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + return null; + } + @Override + public String serverSettings() { + return ""; + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/sjavac/OptionDecoding.java --- a/langtools/test/tools/sjavac/OptionDecoding.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/sjavac/OptionDecoding.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,7 +25,7 @@ /* * @test - * @bug 8035063 + * @bug 8035063 8054465 * @summary Tests decoding of String[] into Options. * * @build Wrapper @@ -192,13 +192,16 @@ assertEquals(17, options.getNumCores()); assertEquals("debug", options.getLogLevel()); assertEquals(false, options.isDefaultPackagePermitted()); - assertEquals(false, options.isUnidentifiedArtifactPermitted()); + assertEquals(false, options.areUnidentifiedArtifactsPermitted()); + assertEquals(false, options.isUnidentifiedArtifactPermitted(Paths.get("bar.txt").toFile().getAbsolutePath())); options = Options.parseArgs("--permit-unidentified-artifacts", + "--permit-artifact=bar.txt", "--permit-sources-without-package"); assertEquals("info", options.getLogLevel()); assertEquals(true, options.isDefaultPackagePermitted()); - assertEquals(true, options.isUnidentifiedArtifactPermitted()); + assertEquals(true, options.areUnidentifiedArtifactsPermitted()); + assertEquals(true, options.isUnidentifiedArtifactPermitted(Paths.get("bar.txt").toFile().getAbsolutePath())); } // Test server configuration options diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/sjavac/PooledExecution.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/sjavac/PooledExecution.java Thu Aug 28 14:53:49 2014 -0700 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044131 + * @summary Makes sure sjavac poolsize option is honored. + * @build Wrapper + * @run main Wrapper PooledExecution + */ +import java.io.File; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import com.sun.tools.sjavac.comp.PooledSjavac; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + + +public class PooledExecution { + + public static void main(String[] args) throws InterruptedException { + new PooledExecutionTest().runTest(); + } + + static class PooledExecutionTest { + + final int POOL_SIZE = 15; + final int NUM_REQUESTS = 100; + + // Number of tasks that has not yet started + CountDownLatch leftToStart = new CountDownLatch(NUM_REQUESTS); + + // Highest number of concurrently active request seen + int highWaterMark = 0; + + public void runTest() throws InterruptedException { + ConcurrencyLoggingService loggingService = new ConcurrencyLoggingService(); + final Sjavac service = new PooledSjavac(loggingService, POOL_SIZE); + + // Keep track of the number of finished tasks so we can make sure all + // tasks finishes gracefully upon shutdown. + Thread[] tasks = new Thread[NUM_REQUESTS]; + final AtomicInteger tasksFinished = new AtomicInteger(0); + + for (int i = 0; i < NUM_REQUESTS; i++) { + tasks[i] = new Thread() { + public void run() { + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + tasksFinished.incrementAndGet(); + } + }; + tasks[i].start(); + } + + // Wait for all tasks to start (but not necessarily run to completion) + leftToStart.await(); + + // Shutdown before all tasks are completed + System.out.println("Shutting down!"); + service.shutdown(); + + // Wait for all tasks to complete + for (Thread t : tasks) + t.join(); + + if (tasksFinished.get() != NUM_REQUESTS) { + throw new AssertionError(tasksFinished.get() + " out of " + + NUM_REQUESTS + " finished. Broken shutdown?"); + } + + if (highWaterMark > POOL_SIZE) { + throw new AssertionError("Pool size overused: " + highWaterMark + + " used out of " + POOL_SIZE + " allowed."); + } + + // Assuming more than POOL_SIZE requests can be processed within 1 sek: + if (highWaterMark < POOL_SIZE) { + throw new AssertionError("Pool size underused: " + highWaterMark + + " used out of " + POOL_SIZE + " allowed."); + } + } + + + private class ConcurrencyLoggingService implements Sjavac { + + // Keeps track of currently active requests + AtomicInteger activeRequests = new AtomicInteger(0); + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + leftToStart.countDown(); + int numActiveRequests = activeRequests.incrementAndGet(); + System.out.printf("Left to start: %2d / Currently active: %2d%n", + leftToStart.getCount(), + numActiveRequests); + highWaterMark = Math.max(highWaterMark, numActiveRequests); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + throw new RuntimeException("Interrupted", ie); + } + activeRequests.decrementAndGet(); + System.out.println("Task completed"); + return null; + } + + @Override + public SysInfo getSysInfo() { + return null; + } + + @Override + public void shutdown() { + } + + @Override + public String serverSettings() { + return ""; + } + } + } +} diff -r cfcea23d2d19 -r 6ce251a87137 langtools/test/tools/sjavac/SJavac.java --- a/langtools/test/tools/sjavac/SJavac.java Thu Aug 21 14:16:28 2014 -0700 +++ b/langtools/test/tools/sjavac/SJavac.java Thu Aug 28 14:53:49 2014 -0700 @@ -25,7 +25,7 @@ /* * @test * @summary Test all aspects of sjavac. - * @bug 8004658 8042441 8042699 + * @bug 8004658 8042441 8042699 8054461 8054474 8054465 * * @build Wrapper * @run main Wrapper SJavac @@ -99,6 +99,9 @@ compileCircularSources(); compileExcludingDependency(); incrementalCompileTestFullyQualifiedRef(); + compileWithAtFile(); + testStateDir(); + testPermittedArtifact(); delete(gensrc); delete(gensrc2); @@ -463,6 +466,98 @@ "bin/javac_state"); } + /** + * Tests @atfile + * @throws Exception If test fails + */ + void compileWithAtFile() throws Exception { + System.out.println("\nTest @atfile with command line content."); + System.out.println("---------------------------------------"); + + delete(gensrc); + delete(gensrc2); + delete(bin); + + populate(gensrc, + "list.txt", + "-if */alfa/omega/A.java\n-if */beta/B.java\ngensrc\n-d bin\n", + "alfa/omega/A.java", + "package alfa.omega; import beta.B; public class A { B b; }", + "beta/B.java", + "package beta; public class B { }", + "beta/C.java", + "broken"); + previous_bin_state = collectState(bin); + compile("@gensrc/list.txt", "--server:portfile=testserver,background=false"); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/javac_state", + "bin/alfa/omega/A.class", + "bin/beta/B.class"); + } + + /** + * Tests storing javac_state into another directory. + * @throws Exception If test fails + */ + void testStateDir() throws Exception { + System.out.println("\nVerify that --state-dir=bar works."); + System.out.println("----------------------------------"); + + Path bar = defaultfs.getPath("bar"); + Files.createDirectory(bar); + + delete(gensrc); + delete(bin); + delete(bar); + previous_bin_state = collectState(bin); + Map previous_bar_state = collectState(bar); + + populate(gensrc, + "alfa/omega/A.java", + "package alfa.omega; public class A { }"); + + compile("--state-dir=bar", "-src", "gensrc", "-d", "bin", serverArg); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class"); + Map new_bar_state = collectState(bar); + verifyThatFilesHaveBeenAdded(previous_bar_state, new_bar_state, + "bar/javac_state"); + } + + /** + * Test white listing of external artifacts inside the destination dir. + * @throws Exception If test fails + */ + void testPermittedArtifact() throws Exception { + System.out.println("\nVerify that --permit-artifact=bar works."); + System.out.println("-------------------------------------------"); + + delete(gensrc); + delete(bin); + + previous_bin_state = collectState(bin); + + populate(gensrc, + "alfa/omega/A.java", + "package alfa.omega; public class A { }"); + + populate(bin, + "alfa/omega/AA.class", + "Ugh, a messy build system (tobefixed) wrote this class file, sjavac must not delete it."); + + compile("--log=debug", "--permit-artifact=bin/alfa/omega/AA.class", "-src", "gensrc", "-d", "bin", serverArg); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/alfa/omega/AA.class", + "bin/javac_state"); + } + void removeFrom(Path dir, String... args) throws IOException { for (String filename : args) { Path p = dir.resolve(filename);