Gives legacy defaults for -extra and -workDir, to smooth migration to the new WAR-based output format. Patch by: fabbott Review by: jat, spoon, scottb git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4118 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/CompilePerms.java b/dev/core/src/com/google/gwt/dev/CompilePerms.java index 12faf69..53180f9 100644 --- a/dev/core/src/com/google/gwt/dev/CompilePerms.java +++ b/dev/core/src/com/google/gwt/dev/CompilePerms.java
@@ -29,8 +29,8 @@ import java.util.TreeSet; /** - * Performs the first phase of compilation, generating the set of permutations - * to compile, and a ready-to-compile AST. + * Performs the second phase of compilation, converting the Precompile's AST into + * JavaScript outputs. */ public class CompilePerms { @@ -180,6 +180,10 @@ */ final CompilePermsOptions options = new CompilePermsOptionsImpl(); if (new ArgProcessor(options).processArgs(args)) { + if (options.getWorkDir() == null) { + System.err.println("The -workDir is required for the CompilePerms phase."); + System.exit(1); + } CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { return new CompilePerms(options).run(logger);
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java index 9a85324..71c96a0 100644 --- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java +++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -21,11 +21,14 @@ import com.google.gwt.dev.CompileTaskRunner.CompileTask; import com.google.gwt.dev.Link.LinkOptionsImpl; import com.google.gwt.dev.Precompile.PrecompileOptionsImpl; +import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.dev.util.PerfLogger; +import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.arg.ArgHandlerExtraDir; import com.google.gwt.dev.util.arg.ArgHandlerOutDir; import java.io.File; +import java.io.IOException; /** * The main executable entry point for the GWT Java to JavaScript compiler. @@ -66,6 +69,10 @@ return linkOptions.getExtraDir(); } + public File getLegacyExtraDir(TreeLogger logger, ModuleDef module) { + return linkOptions.getLegacyExtraDir(logger, module); + } + public File getOutDir() { return linkOptions.getOutDir(); } @@ -86,19 +93,34 @@ * shutdown AWT related threads, since the contract for their termination is * still implementation-dependent. */ + boolean deleteWorkDir = false; final CompilerOptions options = new GWTCompilerOptionsImpl(); if (new ArgProcessor(options).processArgs(args)) { + try { + deleteWorkDir = options.ensureWorkDir(); + System.err.println("deleteWorkDir: " + deleteWorkDir); + } catch (IOException ex) { + System.err.println("Couldn't create new workDir: " + ex.getMessage()); + System.err.println("Either fix the error, or supply an explicit -workDir flag."); + System.exit(1); + } CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { return new GWTCompiler(options).run(logger); } }; if (CompileTaskRunner.runWithAppropriateLogger(options, task)) { + if (deleteWorkDir) { + Util.recursiveDelete(options.getWorkDir(), false); + } // Exit w/ success code. System.exit(0); } } // Exit w/ non-success code. + if (deleteWorkDir) { + Util.recursiveDelete(options.getWorkDir(), false); + } System.exit(1); }
diff --git a/dev/core/src/com/google/gwt/dev/Link.java b/dev/core/src/com/google/gwt/dev/Link.java index 97968b0..182d44b 100644 --- a/dev/core/src/com/google/gwt/dev/Link.java +++ b/dev/core/src/com/google/gwt/dev/Link.java
@@ -34,11 +34,12 @@ import java.io.File; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** - * Performs the first phase of compilation, generating the set of permutations - * to compile, and a ready-to-compile AST. + * Performs the last phase of compilation, merging the compilation outputs. */ public class Link { /** @@ -46,6 +47,20 @@ */ public interface LinkOptions extends CompileTaskOptions, OptionExtraDir, OptionOutDir { + + /** + * A born-deprecated method to enact "legacy" -aux support if -extra is not + * specified. This method will <i>either</i> return the same as + * {@link OptionExtraDir#getExtraDir()}, if -extra is specified, <i>or</i> + * return the legacy equivalent <i>outputDir</i>/<i>ModuleName</i>-aux. In + * this second case, it will also emit a warning to direct people to -extra, + * and flag the fact that non-deployable bits are in what should be the + * deployable output directory. + * + * @return pathname for extra files + */ + @Deprecated + File getLegacyExtraDir(TreeLogger logger, ModuleDef module); } static class ArgProcessor extends CompileArgProcessor { @@ -69,6 +84,7 @@ private File extraDir; private File outDir; + private Set<File> alreadyWarned = new HashSet<File>(); public LinkOptionsImpl() { } @@ -87,6 +103,26 @@ return extraDir; } + public File getLegacyExtraDir(TreeLogger logger, ModuleDef module) { + // safety that we need this at all... + if (extraDir != null) { + return extraDir; + } + // okay, figure the old location, by module... + String deployDir = module.getDeployTo(); + File moduleExtraDir = new File(outDir, + deployDir.substring(0, deployDir.length() - 1) + "-aux"); + // and warn the user about it, but only if it'd be new news. + if (!alreadyWarned.contains(moduleExtraDir)) { + logger.log(TreeLogger.WARN, "Non-deployed artificats will be in " + + moduleExtraDir.getPath() + + ", inside deployable output directory " + outDir.getPath() + + ". Use -extra to relocate the auxilliary files."); + alreadyWarned.add(moduleExtraDir); + } + return moduleExtraDir; + } + public File getOutDir() { return outDir; } @@ -117,6 +153,10 @@ */ final LinkOptions options = new LinkOptionsImpl(); if (new ArgProcessor(options).processArgs(args)) { + if (options.getWorkDir() == null) { + System.err.println("The -workDir is required for the Link phase."); + System.exit(1); + } CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { return new Link(options).run(logger); @@ -244,9 +284,12 @@ module = ModuleDefLoader.loadFromClassPath(logger, options.getModuleName()); moduleOutDir = new File(options.getOutDir(), module.getDeployTo()); Util.recursiveDelete(moduleOutDir, true); - if (options.getExtraDir() != null) { + if (options.getExtraDir() == null) { + // legacy location + moduleExtraDir = options.getLegacyExtraDir(logger, module); + } else { moduleExtraDir = new File(options.getExtraDir(), module.getDeployTo()); - Util.recursiveDelete(moduleExtraDir, false); } + Util.recursiveDelete(moduleExtraDir, false); } }
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java index a7e8bf0..6be2c2f 100644 --- a/dev/core/src/com/google/gwt/dev/Precompile.java +++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -47,8 +47,10 @@ import com.google.gwt.dev.util.arg.ArgHandlerValidateOnlyFlag; import com.google.gwt.dev.util.arg.OptionGenDir; import com.google.gwt.dev.util.arg.OptionValidateOnly; +import com.google.gwt.util.tools.Utility; import java.io.File; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; @@ -66,6 +68,7 @@ */ public interface PrecompileOptions extends JJSOptions, CompileTaskOptions, OptionGenDir, OptionValidateOnly { + boolean ensureWorkDir() throws IOException; } static class ArgProcessor extends CompileArgProcessor { @@ -106,6 +109,24 @@ setValidateOnly(other.isValidateOnly()); } + /** + * Checks that the workDir is set, or creates one if not using a temporary + * name. + * @returns true if intervention was required, i.e. we created a new directory + */ + public boolean ensureWorkDir() throws IOException { + File workDir = super.getWorkDir(); + if (workDir == null) { + // user didn't give us one, make one in a random location + workDir = Utility.makeTemporaryDirectory(null, "work-"); + System.err.println("Created new work directory at " + workDir.getAbsolutePath() + + ", which will be removed on exit. (Use -workDir DIRNAME to retain.)"); + super.setWorkDir(workDir); + return true; + } + return false; + } + public File getGenDir() { return genDir; } @@ -226,6 +247,10 @@ */ final PrecompileOptions options = new PrecompileOptionsImpl(); if (new ArgProcessor(options).processArgs(args)) { + if (options.getWorkDir() == null) { + System.err.println("The -workDir is required for the Precompile phase."); + System.exit(1); + } CompileTask task = new CompileTask() { public boolean run(TreeLogger logger) throws UnableToCompleteException { return new Precompile(options).run(logger);
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java index 1fc2d9b..166ac03 100644 --- a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java +++ b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
@@ -174,8 +174,11 @@ // Tell Tomcat its base directory so that it won't complain. // String catBase = System.getProperty("catalina.base"); - if (catBase == null) { - catBase = generateDefaultCatalinaBase(logger, topWorkDir); + if (catBase == null || !(new File(catBase)).exists()) { + if (catBase == null) { + catBase = topWorkDir.getAbsolutePath() + "tomcat"; + } + generateDefaultCatalinaBase(logger, new File(catBase)); System.setProperty("catalina.base", catBase); } @@ -328,10 +331,10 @@ * Extracts a valid catalina base instance from the classpath. Does not * overwrite any existing files. */ - private String generateDefaultCatalinaBase(TreeLogger logger, File workDir) { + private void generateDefaultCatalinaBase(TreeLogger logger, File catBase) { logger = logger.branch( TreeLogger.TRACE, - "Property 'catalina.base' not specified; checking for a standard catalina base image instead", + "Property 'catalina.base' not specified or not present; checking for a standard catalina base image instead", null); // Recursively copies out files and directories @@ -346,7 +349,6 @@ caught = e; } - File catBase = new File(workDir, "tomcat"); if (resourceMap == null || resourceMap.isEmpty()) { logger.log(TreeLogger.WARN, "Could not find " + tomcatEtcDir, caught); } else { @@ -354,8 +356,6 @@ copyFileNoOverwrite(logger, entry.getKey(), entry.getValue(), catBase); } } - - return catBase.getAbsolutePath(); } /**
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java index 42626cf..b45b807 100644 --- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java +++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java
@@ -20,7 +20,8 @@ import java.io.File; /** - * Argument handler for processing the extra directory option. + * Argument handler for processing the extra directory option. If not specified, + * legacy behavior is to write private artifacts to ${outdir}/Module-aux. */ public final class ArgHandlerExtraDir extends ArgHandlerDir {
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java index c08130f..7c3ef77 100644 --- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java +++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java
@@ -20,7 +20,10 @@ import java.io.File; /** - * Argument handler for processing the output directory flag. + * Argument handler for processing the output directory flag. If not specified, + * the GWTCompiler and Precompile classes will create one (under + * ${java.io.tmpdir}/GWT_TMP_DIR) with a guaranteed-unique name; the other tasks + * will fail. */ public final class ArgHandlerWorkDir extends ArgHandlerDir { @@ -32,14 +35,8 @@ this.option = option; } - public String[] getDefaultArgs() { - return new String[] { - "-workDir", - new File(System.getProperty("java.io.tmpdir"), GWT_TMP_DIR).getAbsolutePath()}; - } - public String getPurpose() { - return "The compiler work directory (must be writeable; defaults to system temp dir)"; + return "The compiler work directory (must be writeable; defaults to random name under system temp dir)"; } public String getTag() {
diff --git a/dev/core/src/com/google/gwt/util/tools/Utility.java b/dev/core/src/com/google/gwt/util/tools/Utility.java index 53a5e4c..3e99fcf 100644 --- a/dev/core/src/com/google/gwt/util/tools/Utility.java +++ b/dev/core/src/com/google/gwt/util/tools/Utility.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.util.tools; +import com.google.gwt.dev.util.arg.ArgHandlerWorkDir; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -226,6 +228,46 @@ return sInstallPath; } + /** + * Creates a randomly-named temporary directory. + * + * @param baseDir base directory to contain the new directory. May be + * {@code null}, in which case a subdirectory under the + * {@code java.io.tmpdir} system property, named by + * {@link ArgHandlerWorkDir#GWT_TMP_DIR}, will be used. + * @param prefix the initial characters of the new directory name. Since all the + * platforms we care about allow long names, this will not be pruned as for + * {@link File#createTempFile(String, String, File), but short names are still + * preferable. The directory created will have five random characters appended + * to the prefix. + * @returns a newly-created temporary directory + */ + public static File makeTemporaryDirectory(File baseDir, String prefix) + throws IOException { + if (baseDir == null) { + baseDir = new File(System.getProperty("java.io.tmpdir"), ArgHandlerWorkDir.GWT_TMP_DIR); + } + int tries = 0; + while (tries < 20) { + tries++; + int rand = (int) (Math.random() * Integer.MAX_VALUE); + StringBuffer tag = new StringBuffer(); + for (int i = 0; i < 5; i++) { + int bits = rand & 0x1f; // low 5 bits: [a-z][0-4] for 32 values + rand >>= 5; + tag.append(Character.forDigit(bits, 36)); + } + File result = new File(baseDir, prefix + tag.toString()); + if (!result.exists()) { + if (result.mkdirs()) { + return result; + } + } + } + throw new IOException("couldn't create temporary directory in 20 tries in " + + baseDir.getAbsolutePath()); + } + public static void streamOut(File file, OutputStream out, int bufferSize) throws IOException { FileInputStream fis = null;