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;