Merging the new^4 linker change branch into trunk!!! BOOOYA!!!
Suggested by: bruce
Patch by: bobv
Review by: scottb
Inspired by: a hot Reuben sandwich
Not Inspired by: javax.servlet
Snide remarks by: knorton
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2192 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/linker/IFrameLinker.java b/dev/core/src/com/google/gwt/core/linker/IFrameLinker.java
similarity index 81%
rename from dev/core/src/com/google/gwt/dev/linker/IFrameLinker.java
rename to dev/core/src/com/google/gwt/core/linker/IFrameLinker.java
index 06aca6c..50c9b9d 100644
--- a/dev/core/src/com/google/gwt/dev/linker/IFrameLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/IFrameLinker.java
@@ -13,11 +13,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.linker;
+package com.google.gwt.core.linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.About;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.LinkerContext;
+import com.google.gwt.dev.linker.LinkerOrder;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
+import com.google.gwt.dev.linker.impl.SelectionScriptLinker;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Util;
import com.google.gwt.util.tools.Utility;
@@ -28,31 +33,35 @@
* Implements the canonical GWT bootstrap sequence that loads the GWT module in
* a separate iframe.
*/
+@LinkerOrder(Order.PRIMARY)
public class IFrameLinker extends SelectionScriptLinker {
- @Override
- protected String getCompilationExtension(TreeLogger logger,
- LinkerContext context) {
- return ".cache.html";
- }
-
public String getDescription() {
return "Standard";
}
@Override
- protected void doEmitArtifacts(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- super.doEmitArtifacts(logger, context);
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException {
+ ArtifactSet toReturn = super.link(logger, context, artifacts);
try {
// Add hosted mode iframe contents
- String hostedHtml = Utility.getFileFromClassPath("com/google/gwt/dev/linker/hosted.html");
- doEmit(logger, context, Util.getBytes(hostedHtml), "hosted.html");
+ // TODO move hosted.html into gwt-user if HostedModeLinker goes away
+ String hostedHtml = Utility.getFileFromClassPath("com/google/gwt/dev/linker/impl/hosted.html");
+ toReturn.add(emitBytes(logger, Util.getBytes(hostedHtml), "hosted.html"));
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to copy support resource", e);
throw new UnableToCompleteException();
}
+
+ return toReturn;
+ }
+
+ @Override
+ protected String getCompilationExtension(TreeLogger logger,
+ LinkerContext context) {
+ return ".cache.html";
}
@Override
@@ -110,7 +119,7 @@
@Override
protected String getSelectionScriptTemplate(TreeLogger logger,
LinkerContext context) {
- return "com/google/gwt/dev/linker/IFrameTemplate.js";
+ return "com/google/gwt/core/linker/IFrameTemplate.js";
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/IFrameTemplate.js b/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js
similarity index 100%
rename from dev/core/src/com/google/gwt/dev/linker/IFrameTemplate.js
rename to dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js
diff --git a/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java b/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java
new file mode 100644
index 0000000..f87d301
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.linker;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.EmittedArtifact;
+import com.google.gwt.dev.linker.GeneratedResource;
+import com.google.gwt.dev.linker.Linker;
+import com.google.gwt.dev.linker.LinkerContext;
+import com.google.gwt.dev.linker.LinkerOrder;
+import com.google.gwt.dev.linker.PublicResource;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
+
+import java.util.SortedSet;
+
+/**
+ * This class prevents generated resources whose partial path begins with
+ * {@value #PREFIX} from being emitted into the output.
+ */
+@LinkerOrder(Order.PRE)
+public class NoDeployResourcesLinker extends Linker {
+ public static final String PREFIX = "no-deploy/";
+
+ @Override
+ public String getDescription() {
+ return "Filter generated resources in the " + PREFIX + " path";
+ }
+
+ @Override
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException {
+
+ ArtifactSet toReturn = new ArtifactSet(artifacts);
+
+ SortedSet<EmittedArtifact> search = toReturn.find(PublicResource.class);
+
+ for (GeneratedResource artifact : toReturn.find(GeneratedResource.class)) {
+ if (artifact.getPartialPath().startsWith(PREFIX)) {
+ toReturn.remove(artifact);
+ }
+ }
+
+ return toReturn;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/SingleScriptLinker.java b/dev/core/src/com/google/gwt/core/linker/SingleScriptLinker.java
similarity index 72%
rename from dev/core/src/com/google/gwt/dev/linker/SingleScriptLinker.java
rename to dev/core/src/com/google/gwt/core/linker/SingleScriptLinker.java
index 07671be..99ea7a3 100644
--- a/dev/core/src/com/google/gwt/dev/linker/SingleScriptLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/SingleScriptLinker.java
@@ -13,11 +13,18 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.linker;
+package com.google.gwt.core.linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.About;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.CompilationResult;
+import com.google.gwt.dev.linker.EmittedArtifact;
+import com.google.gwt.dev.linker.LinkerContext;
+import com.google.gwt.dev.linker.LinkerOrder;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
+import com.google.gwt.dev.linker.impl.SelectionScriptLinker;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Util;
@@ -26,44 +33,15 @@
* this Linker requires that the module has exactly one distinct compilation
* result.
*/
+@LinkerOrder(Order.PRIMARY)
public class SingleScriptLinker extends SelectionScriptLinker {
public String getDescription() {
return "Single Script";
}
- /**
- * Guard against more than one CompilationResult and delegate to super-class.
- */
@Override
- protected void doEmitArtifacts(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- if (context.getCompilations().size() != 1) {
- logger = logger.branch(TreeLogger.ERROR,
- "The module must have exactly one distinct"
- + " permutation when using the " + getDescription() + " Linker.",
- null);
-
- int count = 0;
- for (CompilationResult result : context.getCompilations()) {
- logger.log(TreeLogger.INFO, "Permutation " + ++count + ": "
- + result.toString(), null);
- }
-
- throw new UnableToCompleteException();
- }
- super.doEmitArtifacts(logger, context);
- }
-
- /**
- * Emits the single compilation wrapped in an anonymous function block.
- */
- @Override
- protected void doEmitCompilation(TreeLogger logger, LinkerContext context,
- CompilationResult result) throws UnableToCompleteException {
- }
-
- @Override
- protected void emitSelectionScript(TreeLogger logger, LinkerContext context)
+ protected EmittedArtifact emitSelectionScript(TreeLogger logger,
+ LinkerContext context, ArtifactSet artifacts)
throws UnableToCompleteException {
DefaultTextOutput out = new DefaultTextOutput(true);
@@ -71,7 +49,7 @@
// Emit the selection script in a function closure.
out.print("(function () {");
out.newlineOpt();
- String bootstrap = generateSelectionScript(logger, context);
+ String bootstrap = generateSelectionScript(logger, context, artifacts);
bootstrap = context.optimizeJavaScript(logger, bootstrap);
out.print(bootstrap);
out.print("})();");
@@ -89,7 +67,19 @@
out.print("var $moduleName, $moduleBase;");
out.newlineOpt();
- CompilationResult result = context.getCompilations().first();
+ CompilationResult result = null;
+ for (CompilationResult artifact : artifacts.find(CompilationResult.class)) {
+ if (result == null) {
+ result = artifact;
+ } else {
+ logger = logger.branch(TreeLogger.ERROR,
+ "The module must have exactly one distinct"
+ + " permutation when using the " + getDescription()
+ + " Linker.", null);
+ throw new UnableToCompleteException();
+ }
+ }
+
out.print(result.getJavaScript());
// Add a callback to the selection script
@@ -107,7 +97,7 @@
out.newlineOpt();
byte[] selectionScriptBytes = Util.getBytes(out.toString());
- doEmit(logger, context, selectionScriptBytes, context.getModuleName()
+ return emitBytes(logger, selectionScriptBytes, context.getModuleName()
+ ".nocache.js");
}
@@ -144,6 +134,6 @@
@Override
protected String getSelectionScriptTemplate(TreeLogger logger,
LinkerContext context) throws UnableToCompleteException {
- return "com/google/gwt/dev/linker/SSOTemplate.js";
+ return "com/google/gwt/core/linker/SingleScriptTemplate.js";
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/SSOTemplate.js b/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
similarity index 100%
rename from dev/core/src/com/google/gwt/dev/linker/SSOTemplate.js
rename to dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
diff --git a/dev/core/src/com/google/gwt/dev/linker/XSLinker.java b/dev/core/src/com/google/gwt/core/linker/XSLinker.java
similarity index 90%
rename from dev/core/src/com/google/gwt/dev/linker/XSLinker.java
rename to dev/core/src/com/google/gwt/core/linker/XSLinker.java
index c06d230..1dc08c7 100644
--- a/dev/core/src/com/google/gwt/dev/linker/XSLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/XSLinker.java
@@ -13,16 +13,21 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.linker;
+package com.google.gwt.core.linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.About;
+import com.google.gwt.dev.linker.LinkerContext;
+import com.google.gwt.dev.linker.LinkerOrder;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
+import com.google.gwt.dev.linker.impl.SelectionScriptLinker;
import com.google.gwt.dev.util.DefaultTextOutput;
/**
* Generates a cross-site compatible bootstrap sequence.
*/
+@LinkerOrder(Order.PRIMARY)
public class XSLinker extends SelectionScriptLinker {
public String getDescription() {
@@ -90,6 +95,6 @@
@Override
protected String getSelectionScriptTemplate(TreeLogger logger,
LinkerContext context) throws UnableToCompleteException {
- return "com/google/gwt/dev/linker/XSTemplate.js";
+ return "com/google/gwt/core/linker/XSTemplate.js";
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/XSTemplate.js b/dev/core/src/com/google/gwt/core/linker/XSTemplate.js
similarity index 100%
rename from dev/core/src/com/google/gwt/dev/linker/XSTemplate.js
rename to dev/core/src/com/google/gwt/core/linker/XSTemplate.js
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 2de4086..f038c89 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -35,7 +35,6 @@
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
import com.google.gwt.dev.jjs.JsOutputOption;
-import com.google.gwt.dev.linker.Linker;
import com.google.gwt.dev.linker.SelectionProperty;
import com.google.gwt.dev.linker.impl.StandardCompilationResult;
import com.google.gwt.dev.linker.impl.StandardLinkerContext;
@@ -161,11 +160,15 @@
return out;
}
+ @SuppressWarnings("unused")
protected boolean recordDecision(String in, String out) {
+ // TODO(bobv): consider caching compilations again?
return false;
}
+ @SuppressWarnings("unused")
protected void recordGeneratedTypeHash(String typeName, String sourceHash) {
+ // TODO(bobv): consider caching compilations again?
}
}
@@ -217,8 +220,8 @@
}
}
- private static final String GENERATOR_DIR = ".gwt-compiler"
- + File.separatorChar + "generated";
+ public static final String GWT_COMPILER_DIR = ".gwt-tmp" + File.separatorChar
+ + "compiler";
public static void main(String[] args) {
/*
@@ -283,8 +286,6 @@
private StandardSourceOracle sourceOracle;
- private String[] targets;
-
private TypeOracle typeOracle;
private boolean useGuiLogger;
@@ -349,11 +350,17 @@
// Set up all the initial state.
checkModule(logger);
+ // Place generated resources inside the out dir as a sibling to the module
+ generatorResourcesDir = new File(outDir, GWT_COMPILER_DIR + File.separator
+ + moduleDef.getName() + File.separator + "generated");
+
// Tweak the output directory so that output lives under the module name.
outDir = new File(outDir, module.getName());
- // Clean out the generated resources directory and/or create it
- generatorResourcesDir = new File(outDir, GENERATOR_DIR);
+ // Clean the outDir.
+ Util.recursiveDelete(outDir, true);
+
+ // Clean out the generated resources directory and/or create it.
Util.recursiveDelete(generatorResourcesDir, true);
generatorResourcesDir.mkdirs();
@@ -383,31 +390,6 @@
jjs = new JavaToJavaScriptCompiler(logger, frontEnd, declEntryPts,
jjsOptions);
- if (!jjsOptions.isValidateOnly()) {
- if (targets != null) {
- // Make sure all targets specified on the command-line exist
- boolean badTarget = false;
- for (String target : targets) {
- if (module.getLinker(target) == null) {
- logger.log(TreeLogger.ERROR, "Unknown target " + target, null);
- badTarget = true;
- }
- }
- if (badTarget) {
- throw new UnableToCompleteException();
- }
- } else {
- // Otherwise, make sure at least one linker is set in the ModuleDef
- targets = module.getActiveLinkerNames();
- if (targets == null || targets.length == 0) {
- logger.log(TreeLogger.ERROR,
- "At least one Linker must be specified in the "
- + "module or on the command line", null);
- throw new UnableToCompleteException();
- }
- }
- }
-
StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
module, outDir, generatorResourcesDir, jjsOptions);
compilePermutations(logger, linkerContext);
@@ -419,11 +401,7 @@
logger.log(TreeLogger.INFO, "Compilation succeeded", null);
- // Use the LinkerContext to invoke the Linkers
- for (String linkerName : targets) {
- Linker l = module.getLinker(linkerName);
- linkerContext.invokeLinker(logger, linkerName, l);
- }
+ linkerContext.link(logger, linkerContext, null);
}
public File getGenDir() {
@@ -478,10 +456,6 @@
jjsOptions.setOutput(JsOutputOption.PRETTY);
}
- public void setTargets(String[] targets) {
- this.targets = targets;
- }
-
/**
* Ensure the module has at least one entry point (except in validation mode).
*/
diff --git a/dev/core/src/com/google/gwt/dev/GWTShell.java b/dev/core/src/com/google/gwt/dev/GWTShell.java
index ac742c1..c75dc4c 100644
--- a/dev/core/src/com/google/gwt/dev/GWTShell.java
+++ b/dev/core/src/com/google/gwt/dev/GWTShell.java
@@ -267,8 +267,8 @@
// Create a sandbox for the module.
//
- File moduleDir = new File(outDir, moduleName);
- File shellDir = new File(moduleDir, GWT_SHELL_PATH);
+ File shellDir = new File(outDir, GWT_SHELL_PATH + File.separator
+ + moduleName);
TypeOracle typeOracle = moduleDef.getTypeOracle(logger);
ShellModuleSpaceHost host = doCreateShellModuleSpaceHost(logger,
@@ -309,7 +309,8 @@
}
}
- public static final String GWT_SHELL_PATH = ".gwt-shell";
+ public static final String GWT_SHELL_PATH = ".gwt-tmp" + File.separator
+ + "shell";
private static Image[] icons;
diff --git a/dev/core/src/com/google/gwt/dev/cfg/Messages.java b/dev/core/src/com/google/gwt/dev/cfg/Messages.java
index a232c18..0c33373 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/Messages.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/Messages.java
@@ -31,6 +31,9 @@
public static final Message1String LINKER_NAME_INVALID = new Message1String(
TreeLogger.ERROR, "Invalid linker name '$0'");
+ public static final Message1String NAME_INVALID = new Message1String(
+ TreeLogger.ERROR, "Invalid name '$0'");
+
public static final Message1String PROPERTY_NAME_INVALID = new Message1String(
TreeLogger.ERROR, "Invalid property name '$0'");
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
index 2ab0fd6..2b2a88d 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -23,7 +23,8 @@
import com.google.gwt.dev.jdt.TypeOracleBuilder;
import com.google.gwt.dev.jdt.URLCompilationUnitProvider;
import com.google.gwt.dev.linker.Linker;
-import com.google.gwt.dev.linker.LinkerContextShim;
+import com.google.gwt.dev.linker.LinkerOrder;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.FileOracle;
import com.google.gwt.dev.util.FileOracleFactory;
@@ -41,6 +42,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -77,7 +79,9 @@
return true;
}
- private String[] activeLinkerNames = new String[0];
+ private final Set<Class<? extends Linker>> activeLinkers = new LinkedHashSet<Class<? extends Linker>>();
+
+ private Class<? extends Linker> activePrimaryLinker;
private final ArrayList<URLCompilationUnitProvider> allCups = new ArrayList<URLCompilationUnitProvider>();
@@ -98,14 +102,18 @@
private TypeOracle lazyTypeOracle;
- private final List<Class<? extends LinkerContextShim>> linkerContextShimTypes = new ArrayList<Class<? extends LinkerContextShim>>();
-
- private final Map<String, Linker> linkersByName = new HashMap<String, Linker>();
+ private final Map<String, Class<? extends Linker>> linkersTypesByName = new HashMap<String, Class<? extends Linker>>();
private final long moduleDefCreationTime = System.currentTimeMillis();
private final String name;
+ /**
+ * Must use a separate field to track override, because setNameOverride() will
+ * get called every time a module is inherited, but only the last one matters.
+ */
+ private String nameOverride;
+
private final Properties properties = new Properties();
private final FileOracleFactory publicPathEntries = new FileOracleFactory();
@@ -132,18 +140,15 @@
gwtXmlFiles.add(xmlFile);
}
- public void addLinker(String name, Linker linker) {
- linkersByName.put(name, linker);
- }
+ public void addLinker(String name) {
+ Class<? extends Linker> clazz = getLinker(name);
+ assert clazz != null;
- public void addLinkerContextShim(Class<? extends LinkerContextShim> clazz) {
- /*
- * It's possible a shim may be registered more than once, so this check is
- * used to de-duplicate the final list, which will reflect the order of the
- * first appearance of any LinkerContextShim type.
- */
- if (!linkerContextShimTypes.contains(clazz)) {
- linkerContextShimTypes.add(clazz);
+ LinkerOrder order = clazz.getAnnotation(LinkerOrder.class);
+ if (order.value() == Order.PRIMARY) {
+ activePrimaryLinker = clazz;
+ } else {
+ activeLinkers.add(clazz);
}
}
@@ -213,6 +218,10 @@
entryPointTypeNames.clear();
}
+ public void defineLinker(String name, Class<? extends Linker> linker) {
+ linkersTypesByName.put(name, linker);
+ }
+
public synchronized URL findPublicFile(String partialPath) {
return lazyPublicOracle.find(partialPath);
}
@@ -238,8 +247,12 @@
return null;
}
- public String[] getActiveLinkerNames() {
- return activeLinkerNames;
+ public Set<Class<? extends Linker>> getActiveLinkers() {
+ return activeLinkers;
+ }
+
+ public Class<? extends Linker> getActivePrimaryLinker() {
+ return activePrimaryLinker;
}
public String[] getAllPublicFiles() {
@@ -260,19 +273,15 @@
}
public synchronized String getFunctionName() {
- return name.replace('.', '_');
+ return getName().replace('.', '_');
}
- public Linker getLinker(String name) {
- return linkersByName.get(name);
- }
-
- public List<Class<? extends LinkerContextShim>> getLinkerContextShims() {
- return linkerContextShimTypes;
+ public Class<? extends Linker> getLinker(String name) {
+ return linkersTypesByName.get(name);
}
public synchronized String getName() {
- return name;
+ return nameOverride != null ? nameOverride : name;
}
/**
@@ -349,8 +358,12 @@
PerfLogger.end();
}
- public void setActiveLinkerNames(String... names) {
- activeLinkerNames = names;
+ /**
+ * Override the module's apparent name. Setting this value to
+ * <code>null<code> will disable the name override.
+ */
+ public void setNameOverride(String nameOverride) {
+ this.nameOverride = nameOverride;
}
/**
@@ -373,8 +386,7 @@
*
* @param logger Logs the activity.
*/
- synchronized void normalize(TreeLogger logger)
- throws UnableToCompleteException {
+ synchronized void normalize(TreeLogger logger) {
PerfLogger.start("ModuleDef.normalize");
// Normalize property providers.
@@ -435,24 +447,6 @@
branch = Messages.PUBLIC_PATH_LOCATIONS.branch(logger, null);
lazyPublicOracle = publicPathEntries.create(branch);
- boolean fail = false;
- for (String linkerName : activeLinkerNames) {
- if (!linkersByName.containsKey(linkerName)) {
- logger.log(TreeLogger.ERROR, "Unknown linker name " + linkerName, null);
- fail = true;
- }
- }
-
- if (linkersByName.size() == 0 || activeLinkerNames.length == 0) {
- logger.log(TreeLogger.ERROR, "At least one Linker must be defind and "
- + "at least one Linker must be active.", null);
- fail = true;
- }
-
- if (fail) {
- throw new UnableToCompleteException();
- }
-
PerfLogger.end();
}
@@ -462,7 +456,7 @@
TypeOracle newTypeOracle = null;
try {
- String msg = "Analyzing source in module '" + name + "'";
+ String msg = "Analyzing source in module '" + getName() + "'";
TreeLogger branch = logger.branch(TreeLogger.TRACE, msg, null);
long before = System.currentTimeMillis();
TypeOracleBuilder builder = new TypeOracleBuilder(getCacheManager());
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
index 09f2561..878ba02 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
@@ -26,7 +26,7 @@
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.linker.Linker;
-import com.google.gwt.dev.linker.LinkerContextShim;
+import com.google.gwt.dev.linker.LinkerOrder;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.xml.AttributeConverter;
@@ -35,7 +35,6 @@
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -49,6 +48,8 @@
public class ModuleDefSchema extends Schema {
private final class BodySchema extends Schema {
+ protected final String __add_linker_1_name = null;
+
protected final String __define_linker_1_name = null;
protected final String __define_linker_2_class = null;
@@ -59,8 +60,6 @@
protected final String __entry_point_1_class = null;
- protected final String __extend_linker_context_1_class = null;
-
protected final String __extend_property_1_name = null;
protected final String __extend_property_2_values = null;
@@ -89,8 +88,6 @@
protected final String __servlet_2_class = null;
- protected final String __set_linker_1_name = null;
-
protected final String __set_property_1_name = null;
protected final String __set_property_2_value = null;
@@ -119,9 +116,29 @@
private Schema fChild;
- protected Schema __define_linker_begin(LinkerName name, Linker linker)
+ protected Schema __add_linker_begin(LinkerName name)
throws UnableToCompleteException {
- moduleDef.addLinker(name.name, linker);
+ if (moduleDef.getLinker(name.name) == null) {
+ Messages.LINKER_NAME_INVALID.log(logger, name.name, null);
+ throw new UnableToCompleteException();
+ }
+ moduleDef.addLinker(name.name);
+ return null;
+ }
+
+ protected Schema __define_linker_begin(LinkerName name,
+ Class<? extends Linker> linker) throws UnableToCompleteException {
+ if (!Linker.class.isAssignableFrom(linker)) {
+ logger.log(TreeLogger.ERROR, "A linker must extend "
+ + Linker.class.getName(), null);
+ throw new UnableToCompleteException();
+ }
+ if (linker.getAnnotation(LinkerOrder.class) == null) {
+ logger.log(TreeLogger.ERROR, "Linkers must be annotated with the "
+ + LinkerOrder.class.getName() + " annotation", null);
+ throw new UnableToCompleteException();
+ }
+ moduleDef.defineLinker(name.name, linker);
return null;
}
@@ -148,18 +165,6 @@
return null;
}
- protected Schema __extend_linker_context_begin(Class<?> clazz)
- throws UnableToCompleteException {
- try {
- moduleDef.addLinkerContextShim(clazz.asSubclass(LinkerContextShim.class));
- return null;
- } catch (ClassCastException e) {
- Messages.INVALID_CLASS_DERIVATION.log(logger, clazz,
- LinkerContextShim.class, null);
- throw new UnableToCompleteException();
- }
- }
-
protected Schema __extend_property_begin(Property property,
PropertyValue[] values) {
for (int i = 0; i < values.length; i++) {
@@ -290,15 +295,6 @@
return null;
}
- protected Schema __set_linker_begin(LinkerName[] names) {
- String[] asString = new String[names.length];
- for (int i = 0; i < names.length; i++) {
- asString[i] = names[i].name;
- }
- moduleDef.setActiveLinkerNames(asString);
- return null;
- }
-
protected Schema __set_property_begin(Property prop, PropertyValue value) {
prop.setActiveValue(value.token);
@@ -586,31 +582,6 @@
/**
* Converts a string into a linker name, validating it in the process.
*/
- private final class LinkerNameArrayAttrCvt extends AttributeConverter {
-
- public Object convertToArg(Schema schema, int line, String elem,
- String attr, String value) throws UnableToCompleteException {
- String[] tokens = value.split(",");
- List<LinkerName> toReturn = new ArrayList<LinkerName>(tokens.length);
-
- for (String token : tokens) {
- token = token.trim();
- if (moduleDef.getLinker(token) == null) {
- Messages.LINKER_NAME_INVALID.log(logger, token, null);
- throw new UnableToCompleteException();
- }
-
- toReturn.add(new LinkerName(token));
- }
-
- // It is a valid list of names.
- return toReturn.toArray(new LinkerName[tokens.length]);
- }
- }
-
- /**
- * Converts a string into a linker name, validating it in the process.
- */
private final class LinkerNameAttrCvt extends AttributeConverter {
public Object convertToArg(Schema schema, int line, String elem,
@@ -627,6 +598,46 @@
}
/**
+ * A dotted Java identifier or null. Zero-length names are represented as
+ * null.
+ */
+ private static class NullableName {
+ public final String token;
+
+ public NullableName(String token) {
+ this.token = token;
+ }
+ }
+
+ /**
+ * Converts a string into a nullable name, validating it in the process.
+ */
+ private final class NullableNameAttrCvt extends AttributeConverter {
+
+ public Object convertToArg(Schema schema, int line, String elem,
+ String attr, String value) throws UnableToCompleteException {
+ if (value == null || value.length() == 0) {
+ return new NullableName(null);
+ }
+
+ // Ensure each part of the name is valid.
+ //
+ String[] tokens = (value + ". ").split("\\.");
+ for (int i = 0; i < tokens.length - 1; i++) {
+ String token = tokens[i];
+ if (!Util.isValidJavaIdent(token)) {
+ Messages.NAME_INVALID.log(logger, value, null);
+ throw new UnableToCompleteException();
+ }
+ }
+
+ // It is a valid name.
+ //
+ return new NullableName(value);
+ }
+ }
+
+ /**
* Creates singleton instances of objects based on an attribute containing a
* class name.
*/
@@ -844,26 +855,25 @@
return "yes".equalsIgnoreCase(s) || "true".equalsIgnoreCase(s);
}
+ protected final String __module_1_renameto = "";
+
private final BodySchema bodySchema;
private final ClassAttrCvt classAttrCvt = new ClassAttrCvt();
private boolean foundAnyPublic;
-
private boolean foundExplicitSourceOrSuperSource;
private final ObjAttrCvt<Generator> genAttrCvt = new ObjAttrCvt<Generator>(
Generator.class);
private final JsParser jsParser = new JsParser();
private final JsProgram jsPgm = new JsProgram();
- private final ObjAttrCvt<Linker> linkerAttrCvt = new ObjAttrCvt<Linker>(
- Linker.class);
- private final LinkerNameArrayAttrCvt linkerNameArrayAttrCvt = new LinkerNameArrayAttrCvt();
private final LinkerNameAttrCvt linkerNameAttrCvt = new LinkerNameAttrCvt();
private final ModuleDefLoader loader;
private final TreeLogger logger;
private final ModuleDef moduleDef;
private final String modulePackageAsPath;
private final URL moduleURL;
+ private final NullableNameAttrCvt nullableNameAttrCvt = new NullableNameAttrCvt();
private final PropertyAttrCvt propAttrCvt = new PropertyAttrCvt();
private final PropertyNameAttrCvt propNameAttrCvt = new PropertyNameAttrCvt();
private final PropertyValueArrayAttrCvt propValueArrayAttrCvt = new PropertyValueArrayAttrCvt();
@@ -884,17 +894,16 @@
registerAttributeConverter(PropertyValue.class, propValueAttrCvt);
registerAttributeConverter(PropertyValue[].class, propValueArrayAttrCvt);
registerAttributeConverter(Generator.class, genAttrCvt);
- registerAttributeConverter(Linker.class, linkerAttrCvt);
registerAttributeConverter(LinkerName.class, linkerNameAttrCvt);
- registerAttributeConverter(LinkerName[].class, linkerNameArrayAttrCvt);
+ registerAttributeConverter(NullableName.class, nullableNameAttrCvt);
registerAttributeConverter(Class.class, classAttrCvt);
}
- protected Schema __module_begin() {
+ protected Schema __module_begin(NullableName renameTo) {
return bodySchema;
}
- protected void __module_end() {
+ protected void __module_end(NullableName renameTo) {
// Maybe infer source and public.
//
if (!foundExplicitSourceOrSuperSource) {
@@ -906,6 +915,9 @@
bodySchema.addPublicPackage(modulePackageAsPath, "public", Empty.STRINGS,
Empty.STRINGS, true, true);
}
+
+ // We do this in __module_end so this value is never inherited
+ moduleDef.setNameOverride(renameTo.token);
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/linker/AbstractLinker.java b/dev/core/src/com/google/gwt/dev/linker/AbstractLinker.java
index bb33a16..deda779 100644
--- a/dev/core/src/com/google/gwt/dev/linker/AbstractLinker.java
+++ b/dev/core/src/com/google/gwt/dev/linker/AbstractLinker.java
@@ -19,126 +19,80 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.util.Util;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
* Provides basic functions common to all Linker implementations.
*/
public abstract class AbstractLinker extends Linker {
-
/**
- * Delegates to {@link #doEmitArtifacts(TreeLogger, LinkerContext)}.
+ * Internal type to wrap a byte array.
*/
- public final void link(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- doEmitArtifacts(logger, context);
+ private static class SyntheticArtifact extends EmittedArtifact {
+ private final byte[] data;
+
+ public SyntheticArtifact(Class<? extends Linker> linkerType,
+ String partialPath, byte[] data) {
+ super(linkerType, partialPath);
+ this.data = data;
+ }
+
+ @Override
+ public InputStream getContents(TreeLogger logger)
+ throws UnableToCompleteException {
+ return new ByteArrayInputStream(data);
+ }
}
/**
- * Emit a byte array into the output. Linkers that require knowledge of all
- * resources emitted may override this function to spy on the output.
+ * A helper method to create an artifact from an array of bytes.
*
- * @param logger a logger
- * @param context the LinkerContext
- * @param what the bytes to emit
- * @param where the partial path within the output directory
+ * @param logger a TreeLogger
+ * @param what the data to emit
+ * @param partialPath the partial path of the resource
+ * @return an artifact that contains the given data
* @throws UnableToCompleteException
*/
- protected void doEmit(TreeLogger logger, LinkerContext context, byte[] what,
- String where) throws UnableToCompleteException {
- OutputStream out = context.tryCreateArtifact(logger, where);
- if (out != null) {
- try {
- out.write(what);
- context.commit(logger, out);
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Unable to emit artifact", e);
- throw new UnableToCompleteException();
- }
- }
+ @SuppressWarnings("unused")
+ protected final EmittedArtifact emitBytes(TreeLogger logger, byte[] what,
+ String partialPath) throws UnableToCompleteException {
+ return new SyntheticArtifact(getClass(), partialPath, what);
}
/**
- * The default implementation will emit all compilations, public resources,
- * and generated resources by calling the relevant functions defined in the
- * linker interface.
- */
- protected void doEmitArtifacts(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- for (CompilationResult result : context.getCompilations()) {
- doEmitCompilation(logger, context, result);
- }
-
- // Copy the public resources
- for (PublicResource resource : context.getPublicResources()) {
- doEmitPublicResource(logger, context, resource);
- }
-
- // Copy the generated resources
- for (GeneratedResource resource : context.getGeneratedResources()) {
- doEmitGeneratedResource(logger, context, resource);
- }
- }
-
- /**
- * Linkers must implement this function to emit compilations.
+ * A helper method to create an artifact to emit the contents of an
+ * InputStream.
*
- * @param logger
- * @param context
- * @param result
- * @throws UnableToCompleteException
+ * @param logger a TreeLogger
+ * @param what the source InputStream
+ * @param partialPath the partial path of the emitted resource
+ * @return an artifact that contains the contents of the InputStream
*/
- protected abstract void doEmitCompilation(TreeLogger logger,
- LinkerContext context, CompilationResult result)
- throws UnableToCompleteException;
-
- protected void doEmitGeneratedResource(TreeLogger logger,
- LinkerContext context, GeneratedResource resource)
- throws UnableToCompleteException {
- emitInputStream(logger, context, resource.tryGetResourceAsStream(logger),
- resource.getPartialPath());
- }
-
- protected void doEmitPublicResource(TreeLogger logger, LinkerContext context,
- PublicResource resource) throws UnableToCompleteException {
- emitInputStream(logger, context, resource.tryGetResourceAsStream(logger),
- resource.getPartialPath());
- }
-
- /**
- * Helper method that emits the contents of an InputStream into the output.
- * This delegates to
- * {@link #doEmit(TreeLogger, LinkerContext, byte[], String)}.
- *
- * @param logger a logger
- * @param context the LinkerContext
- * @param what the stream to emit
- * @param where the partial path within the output directory
- * @throws UnableToCompleteException
- */
- protected final void emitInputStream(TreeLogger logger,
- LinkerContext context, InputStream what, String where)
- throws UnableToCompleteException {
+ protected final EmittedArtifact emitInputStream(TreeLogger logger,
+ InputStream what, String partialPath) throws UnableToCompleteException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Util.copy(logger, what, out);
- doEmit(logger, context, out.toByteArray(), where);
+ return new SyntheticArtifact(getClass(), partialPath, out.toByteArray());
}
/**
- * A helper method to emit a byte array into the output, using an
- * automatically-computed strong path. This function delegates to
- * {@link #doEmit(TreeLogger, LinkerContext, byte[], String)}.
+ * A helper method to create an artifact from an array of bytes with a strong
+ * name.
*
- * @return the partial path of the emitted resource.
+ * @param logger a TreeLogger
+ * @param what the data to emit
+ * @param prefix a non-null string to prepend to the hash to determine the
+ * Artifact's partial path
+ * @param suffix a non-null string to append to the hash to determine the
+ * Artifact's partial path
+ * @return an artifact that contains the given data
*/
- protected final String emitWithStrongName(TreeLogger logger,
- LinkerContext context, byte[] what, String prefix, String suffix)
+ protected final EmittedArtifact emitWithStrongName(TreeLogger logger,
+ byte[] what, String prefix, String suffix)
throws UnableToCompleteException {
String strongName = prefix + Util.computeStrongName(what) + suffix;
- doEmit(logger, context, what, strongName);
- return strongName;
+ return emitBytes(logger, what, strongName);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/Artifact.java b/dev/core/src/com/google/gwt/dev/linker/Artifact.java
new file mode 100644
index 0000000..4c25187
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/Artifact.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+/**
+ * A base type for all artifacts relating to the link process. In order to
+ * ensure stable output between runs of the compiler, Artifact types must
+ * implement a stable comparison between instances of a relevant base type (the
+ * exact comparison order is irrelevant).
+ *
+ * @param <C> The type of Artifact interface that the Artifact can be compared
+ * to.
+ */
+public abstract class Artifact<C extends Artifact<C>> implements
+ Comparable<Artifact<?>> {
+ private final Class<? extends Linker> linker;
+
+ protected Artifact(Class<? extends Linker> linker) {
+ this.linker = linker;
+ }
+
+ public final int compareTo(Artifact<?> o) {
+ if (getComparableArtifactType().equals(o.getComparableArtifactType())) {
+ return compareToComparableArtifact(getComparableArtifactType().cast(o));
+ } else {
+ return getComparableArtifactType().getName().compareTo(
+ o.getComparableArtifactType().getName());
+ }
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj instanceof Artifact) {
+ return compareTo((Artifact<?>) obj) == 0;
+ } else {
+ return false;
+ }
+ }
+
+ public final Class<? extends Linker> getLinker() {
+ return linker;
+ }
+
+ /**
+ * The class which is returned from {@link #getComparableArtifactType()} must
+ * declare a final implementation which returns the same hash code for objects
+ * for which {@link #compareToComparableArtifact(Artifact)} returns 0.
+ */
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public String toString() {
+ return getClass().getName() + " created by " + getLinker().getName();
+ }
+
+ /**
+ * Performs comparison with an artifact of a compatible base type. Objects
+ * which compare to 0 are assumed equal, and must return the same
+ * {@link #hashCode()}.
+ */
+ protected abstract int compareToComparableArtifact(C o);
+
+ /**
+ * Returns the base type to use for comparisons between Artifacts. All
+ * concrete implementations of this methods must be final.
+ */
+ protected abstract Class<C> getComparableArtifactType();
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/ArtifactSet.java b/dev/core/src/com/google/gwt/dev/linker/ArtifactSet.java
new file mode 100644
index 0000000..3a894ad
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/ArtifactSet.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Provides stable ordering and de-duplication of artifacts.
+ */
+public final class ArtifactSet implements SortedSet<Artifact<?>> {
+
+ private SortedSet<Artifact<?>> treeSet = new TreeSet<Artifact<?>>();
+
+ public ArtifactSet() {
+ }
+
+ public ArtifactSet(Collection<? extends Artifact<?>> copyFrom) {
+ addAll(copyFrom);
+ }
+
+ public boolean add(Artifact<?> o) {
+ return treeSet.add(o);
+ }
+
+ public boolean addAll(Collection<? extends Artifact<?>> c) {
+ return treeSet.addAll(c);
+ }
+
+ public void clear() {
+ treeSet.clear();
+ }
+
+ public Comparator<? super Artifact<?>> comparator() {
+ return treeSet.comparator();
+ }
+
+ public boolean contains(Object o) {
+ return treeSet.contains(o);
+ }
+
+ public boolean containsAll(Collection<?> c) {
+ return treeSet.containsAll(c);
+ }
+
+ public boolean equals(Object o) {
+ return treeSet.equals(o);
+ }
+
+ /**
+ * Find all Artifacts assignable to some base type. The returned value will be
+ * a snapshot of the values in the ArtifactSet. The following two examples
+ * result in an equivalent set:
+ *
+ * <pre>
+ * SortedSet<EmittedArtifact> search = artifactSet.find(PublicResource.class);
+ * search.addAll(artifactSet.find(GeneratedResource.class);
+ * </pre>
+ *
+ * or
+ *
+ * <pre>
+ * SortedSet<EmittedArtifact> search = artifactSet.find(EmittedArtifact.class);
+ * </pre>
+ *
+ * @param <A> a type bound possibly wider than the desired type of artifact
+ * @param <T> the desired type of Artifact
+ * @param artifactType the desired type of Artifact
+ * @return all Artifacts in the ArtifactSet assignable to the desired type
+ */
+ public <A extends Artifact<?>, T extends A> SortedSet<A> find(
+ Class<T> artifactType) {
+ // TODO make this sub-linear
+ SortedSet<A> toReturn = new TreeSet<A>();
+ for (Artifact<?> artifact : this) {
+ if (artifactType.isInstance(artifact)) {
+ toReturn.add(artifactType.cast(artifact));
+ }
+ }
+ return toReturn;
+ }
+
+ public Artifact<?> first() {
+ return treeSet.first();
+ }
+
+ /**
+ * Prevent further modification of the the ArtifactSet. Any attempts to alter
+ * the ArtifactSet after invoking this method will result in an
+ * UnsupportedOperationException.
+ */
+ public void freeze() {
+ if (treeSet instanceof TreeSet) {
+ treeSet = Collections.unmodifiableSortedSet(treeSet);
+ }
+ }
+
+ public int hashCode() {
+ return treeSet.hashCode();
+ }
+
+ public SortedSet<Artifact<?>> headSet(Artifact<?> toElement) {
+ return treeSet.headSet(toElement);
+ }
+
+ public boolean isEmpty() {
+ return treeSet.isEmpty();
+ }
+
+ public Iterator<Artifact<?>> iterator() {
+ return treeSet.iterator();
+ }
+
+ public Artifact<?> last() {
+ return treeSet.last();
+ }
+
+ public boolean remove(Object o) {
+ return treeSet.remove(o);
+ }
+
+ public boolean removeAll(Collection<?> c) {
+ return treeSet.removeAll(c);
+ }
+
+ /**
+ * Possibly replace an existing Artifact.
+ *
+ * @param artifact the replacement Artifact
+ * @return <code>true</code> if an equivalent Artifact was already present.
+ */
+ public boolean replace(Artifact<?> artifact) {
+ boolean toReturn = treeSet.remove(artifact);
+ treeSet.add(artifact);
+ return toReturn;
+ }
+
+ public boolean retainAll(Collection<?> c) {
+ return treeSet.retainAll(c);
+ }
+
+ public int size() {
+ return treeSet.size();
+ }
+
+ public SortedSet<Artifact<?>> subSet(Artifact<?> fromElement,
+ Artifact<?> toElement) {
+ return treeSet.subSet(fromElement, toElement);
+ }
+
+ public SortedSet<Artifact<?>> tailSet(Artifact<?> fromElement) {
+ return treeSet.tailSet(fromElement);
+ }
+
+ public Object[] toArray() {
+ return treeSet.toArray();
+ }
+
+ public <T> T[] toArray(T[] a) {
+ return treeSet.toArray(a);
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/CompilationResult.java b/dev/core/src/com/google/gwt/dev/linker/CompilationResult.java
index a5e916f..de375a7 100644
--- a/dev/core/src/com/google/gwt/dev/linker/CompilationResult.java
+++ b/dev/core/src/com/google/gwt/dev/linker/CompilationResult.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.linker;
+import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
@@ -22,12 +23,17 @@
* Represents a unique compilation of the module. Multiple permutations may
* result in identical JavaScript.
*/
-public interface CompilationResult {
+public abstract class CompilationResult extends Artifact<CompilationResult> {
+
+ protected CompilationResult(Class<? extends Linker> linkerType) {
+ super(linkerType);
+ }
+
/**
* Returns the JavaScript compilation. The exact form and function of the
* JavaScript should be considered opaque.
*/
- String getJavaScript();
+ public abstract String getJavaScript();
/**
* Provides values for {@link SelectionProperty} instances that are not
@@ -35,5 +41,37 @@
* multiple mappings, one for each permutation that resulted in the
* compilation.
*/
- SortedSet<SortedMap<SelectionProperty, String>> getPropertyMap();
+ public abstract SortedSet<SortedMap<SelectionProperty, String>> getPropertyMap();
+
+ @Override
+ public final int hashCode() {
+ return getJavaScript().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ b.append("{");
+ for (SortedMap<SelectionProperty, String> map : getPropertyMap()) {
+ b.append(" {");
+ for (Map.Entry<SelectionProperty, String> entry : map.entrySet()) {
+ b.append(" ").append(entry.getKey().getName()).append(":").append(
+ entry.getValue());
+ }
+ b.append(" }");
+ }
+ b.append(" }");
+
+ return b.toString();
+ }
+
+ @Override
+ protected final int compareToComparableArtifact(CompilationResult o) {
+ return getJavaScript().compareTo(o.getJavaScript());
+ }
+
+ @Override
+ protected final Class<CompilationResult> getComparableArtifactType() {
+ return CompilationResult.class;
+ }
}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/linker/EmittedArtifact.java b/dev/core/src/com/google/gwt/dev/linker/EmittedArtifact.java
new file mode 100644
index 0000000..6653a33
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/EmittedArtifact.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import java.io.InputStream;
+
+/**
+ * An artifact that intended to be emitted into the output.
+ */
+public abstract class EmittedArtifact extends Artifact<EmittedArtifact> {
+
+ private final String partialPath;
+
+ protected EmittedArtifact(Class<? extends Linker> linker, String partialPath) {
+ super(linker);
+ this.partialPath = partialPath;
+ }
+
+ public abstract InputStream getContents(TreeLogger logger)
+ throws UnableToCompleteException;
+
+ public final String getPartialPath() {
+ return partialPath;
+ }
+
+ @Override
+ public final int hashCode() {
+ return getPartialPath().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getPartialPath();
+ }
+
+ @Override
+ protected final int compareToComparableArtifact(EmittedArtifact o) {
+ return getPartialPath().compareTo(o.getPartialPath());
+ }
+
+ @Override
+ protected final Class<EmittedArtifact> getComparableArtifactType() {
+ return EmittedArtifact.class;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/GeneratedResource.java b/dev/core/src/com/google/gwt/dev/linker/GeneratedResource.java
index 6f80ef3..5c8f2ee 100644
--- a/dev/core/src/com/google/gwt/dev/linker/GeneratedResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/GeneratedResource.java
@@ -18,6 +18,9 @@
/**
* A resource generated during the compilation process by a Generator.
*/
-public interface GeneratedResource extends ModuleResource {
- String getPartialPath();
+public abstract class GeneratedResource extends EmittedArtifact {
+ protected GeneratedResource(Class<? extends Linker> linkerType,
+ String partialPath) {
+ super(linkerType, partialPath);
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/Linker.java b/dev/core/src/com/google/gwt/dev/linker/Linker.java
index 1ec9abd..b19f4f2 100644
--- a/dev/core/src/com/google/gwt/dev/linker/Linker.java
+++ b/dev/core/src/com/google/gwt/dev/linker/Linker.java
@@ -19,9 +19,10 @@
import com.google.gwt.core.ext.UnableToCompleteException;
/**
- * Defines a linker for the GWT compiler. One or more Linkers will be invoked
- * after the Java to JavaScript compilation process and are responsible for
- * assembly of the final output from the compiler.
+ * Defines a linker for the GWT compiler. Each Linker must be annotated with a
+ * {@link LinkerOrder} annotation to determine the relative ordering of the
+ * Linkers. Exact order of Linker execution will be determined by the order of
+ * <code>add-linker</code> tags in the module configuration.
*/
public abstract class Linker {
/**
@@ -30,14 +31,15 @@
public abstract String getDescription();
/**
- * Invoke the Linker. The implementation of this method should rely only on
- * the provided LinkerContext in order to manipulate the environment.
+ * Invoke the Linker.
*
* @param logger the TreeLogger to record to
* @param context provides access to the Linker's environment
+ * @param artifacts an unmodifiable view of the artifacts to link
+ * @return the artifacts that should be propagated through the linker chain
* @throws UnableToCompleteException if compilation violates assumptions made
* by the Linker or for errors encountered by the Linker
*/
- public abstract void link(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException;
+ public abstract ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException;
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/LinkerContext.java b/dev/core/src/com/google/gwt/dev/linker/LinkerContext.java
index 7767d25..b799b05 100644
--- a/dev/core/src/com/google/gwt/dev/linker/LinkerContext.java
+++ b/dev/core/src/com/google/gwt/dev/linker/LinkerContext.java
@@ -18,92 +18,16 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
-import java.io.OutputStream;
-import java.util.Comparator;
import java.util.SortedSet;
/**
- * Provides access to all information and runtime services required by a
- * {@link Linker}. Methods that return a {@link SortedSet} are guaranteed to
- * have stable iteration order between runs of the compiler over identical
- * input. Unless otherwise specified, the exact iteration order is left as an
- * implementation detail.
+ * Provides access to data about the linking process. Methods that return a
+ * {@link SortedSet} are guaranteed to have stable iteration order between runs
+ * of the compiler over identical input. Unless otherwise specified, the exact
+ * iteration order is left as an implementation detail.
*/
public interface LinkerContext {
/**
- * Orders CompilationResults by string comparison of their JavaScript.
- */
- Comparator<CompilationResult> COMPILATION_RESULT_COMPARATOR = new Comparator<CompilationResult>() {
- public int compare(CompilationResult o1, CompilationResult o2) {
- return o1.getJavaScript().compareTo(o2.getJavaScript());
- }
- };
-
- /**
- * Orders GeneratedResources by string comparison of their partial paths.
- */
- Comparator<GeneratedResource> GENERATED_RESOURCE_COMPARATOR = new Comparator<GeneratedResource>() {
- public int compare(GeneratedResource o1, GeneratedResource o2) {
- return o1.getPartialPath().compareTo(o2.getPartialPath());
- }
- };
-
- /**
- * Orders PublicResources by string comparison of their partial paths.
- */
- Comparator<PublicResource> PUBLIC_RESOURCE_COMPARATOR = new Comparator<PublicResource>() {
- public int compare(PublicResource o1, PublicResource o2) {
- return o1.getPartialPath().compareTo(o2.getPartialPath());
- }
- };
-
- /**
- * Orders ModuleScriptResources by string comparison of their src attributes.
- */
- Comparator<ModuleScriptResource> SCRIPT_RESOURCE_COMPARATOR = new Comparator<ModuleScriptResource>() {
- public int compare(ModuleScriptResource o1, ModuleScriptResource o2) {
- return o1.getSrc().compareTo(o2.getSrc());
- }
- };
-
- /**
- * Orders SelectionProperties by string comparison of their names.
- */
- Comparator<SelectionProperty> SELECTION_PROPERTY_COMPARATOR = new Comparator<SelectionProperty>() {
- public int compare(SelectionProperty o1, SelectionProperty o2) {
- return o1.getName().compareTo(o2.getName());
- }
- };
-
- /**
- * Orders ModuleStyleResources by string comparison of their src attributes.
- */
- Comparator<ModuleStylesheetResource> STYLE_RESOURCE_COMPARATOR = new Comparator<ModuleStylesheetResource>() {
- public int compare(ModuleStylesheetResource o1, ModuleStylesheetResource o2) {
- return o1.getSrc().compareTo(o2.getSrc());
- }
- };
-
- /**
- * Finalizes the OutputStream for a given artifact. This method must be called
- * in order to actually place the artifact into the output directory. If the
- * OutptStream has not already been closed, this method will close the
- * OutputStream.
- */
- void commit(TreeLogger logger, OutputStream out)
- throws UnableToCompleteException;
-
- /**
- * Returns all unique compilations of the module.
- */
- SortedSet<CompilationResult> getCompilations();
-
- /**
- * Returns all resources emitted through a GeneratorContext.
- */
- SortedSet<GeneratedResource> getGeneratedResources();
-
- /**
* Returns the name of the module's bootstrap function.
*/
String getModuleFunctionName();
@@ -114,18 +38,6 @@
String getModuleName();
/**
- * Provides access to all <code>script</code> tags referenced by the module
- * definition.
- */
- SortedSet<ModuleScriptResource> getModuleScripts();
-
- /**
- * Provides access to all <code>stylesheet</code> tags referenced by the
- * module definition.
- */
- SortedSet<ModuleStylesheetResource> getModuleStylesheets();
-
- /**
* Returns all deferred binding properties defined in the module. The
* SelectionProperties will be sorted by the standard string comparison
* function on the name of the property.
@@ -133,11 +45,6 @@
SortedSet<SelectionProperty> getProperties();
/**
- * Returns all files in the module's public path.
- */
- SortedSet<PublicResource> getPublicResources();
-
- /**
* Applies optimizations to a JavaScript program. This method is intended to
* be applied to bootstrap scripts in order to apply context-specific
* transformations to the program, based on the compiler's configuration. The
@@ -150,41 +57,4 @@
*/
String optimizeJavaScript(TreeLogger logger, String jsProgram)
throws UnableToCompleteException;
-
- /**
- * Attempt to create an artifact within the linker's output directory. If a
- * similarly-named resource has already been created, this method will return
- * <code>null</code>. The data written to the OutputStream will not be
- * written into the output directory unless
- * {@link #commit(TreeLogger, OutputStream)} is called.
- *
- * @param logger
- * @param partialPath the partial path of the artifact
- * @return An OutputStream through which the artifact may be written, or
- * <code>null</code> if the artifact had previously been created.
- */
- OutputStream tryCreateArtifact(TreeLogger logger, String partialPath);
-
- /**
- * Provides named access to generated resources.
- *
- * @param logger a logging destination
- * @param partialPath a partial path, generally obtained from
- * {@link GeneratedResource#getPartialPath()}
- * @return The requested resource, or <code>null</code> if no such resource
- * exists
- */
- GeneratedResource tryGetGeneratedResource(TreeLogger logger,
- String partialPath);
-
- /**
- * Provides name access to resources in the module's public path.
- *
- * @param logger a logging destination
- * @param partialPath a partial path, generally obtained from
- * {@link PublicResource#getPartialPath()}
- * @return The requested resource or <code>null</code> if no such resource
- * exists
- */
- PublicResource tryGetPublicResource(TreeLogger logger, String partialPath);
}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/linker/LinkerContextShim.java b/dev/core/src/com/google/gwt/dev/linker/LinkerContextShim.java
deleted file mode 100644
index 59b25c5..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/LinkerContextShim.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
-import java.io.OutputStream;
-import java.util.SortedSet;
-
-/**
- * This base class allows behaviors to be injected into the
- * {@link LinkerContext} that is observed by the {@link Linker} types operating
- * on the output from the compiler. Instances of LinkerContextShim are mapped
- * into the compilation process by including {@code <extend-linker-context>}
- * tags in the GWT module definition. Subclasses of LinkerContextShim must
- * define a two-argument constructor that accepts an instance of TreeLogger and
- * LinkerContext.
- * <p>
- * The default behavior of all methods in this class is to delegate to the
- * LinkerContext returned from {@link #getParent()}. Separate shim instances
- * are guaranteed to be used for each Linker instance.
- * <p>
- * No guarantees are made on the order in which or number of times any method on
- * the LinkerContextShim will be invoked. Implementations are encouraged to
- * precompute all return values for each method in their constructors and return
- * an unmodifiable wrapper around the collection using
- * {@link java.util.Collections#unmodifiableSortedSet(SortedSet)}.
- */
-public abstract class LinkerContextShim implements LinkerContext {
- private final LinkerContext parent;
-
- protected LinkerContextShim(TreeLogger logger, LinkerContext parent)
- throws UnableToCompleteException {
- this.parent = parent;
- }
-
- /**
- * Finalize all actions performed by the LinkerContextShim. This method will
- * be called in reverse order; it will not be called on a parent until all of
- * its children have been committed.
- */
- public void commit(TreeLogger logger) throws UnableToCompleteException {
- }
-
- public void commit(TreeLogger logger, OutputStream out)
- throws UnableToCompleteException {
- getParent().commit(logger, out);
- }
-
- public SortedSet<CompilationResult> getCompilations() {
- return getParent().getCompilations();
- }
-
- public SortedSet<GeneratedResource> getGeneratedResources() {
- return getParent().getGeneratedResources();
- }
-
- public String getModuleFunctionName() {
- return getParent().getModuleFunctionName();
- }
-
- public String getModuleName() {
- return getParent().getModuleName();
- }
-
- public SortedSet<ModuleScriptResource> getModuleScripts() {
- return getParent().getModuleScripts();
- }
-
- public SortedSet<ModuleStylesheetResource> getModuleStylesheets() {
- return getParent().getModuleStylesheets();
- }
-
- /**
- * Obtain a reference to the parent LinkerContext. This method is guaranteed
- * to return a useful value before any of the other LinkerContext-derived
- * methods are invoked.
- */
- // NB This is final because StandardLinkerContext depends on it to unwind
- public final LinkerContext getParent() {
- return parent;
- }
-
- public SortedSet<SelectionProperty> getProperties() {
- return getParent().getProperties();
- }
-
- public SortedSet<PublicResource> getPublicResources() {
- return getParent().getPublicResources();
- }
-
- public String optimizeJavaScript(TreeLogger logger, String jsProgram)
- throws UnableToCompleteException {
- return getParent().optimizeJavaScript(logger, jsProgram);
- }
-
- public OutputStream tryCreateArtifact(TreeLogger logger, String partialPath) {
- return getParent().tryCreateArtifact(logger, partialPath);
- }
-
- public GeneratedResource tryGetGeneratedResource(TreeLogger logger,
- String partialPath) {
- return getParent().tryGetGeneratedResource(logger, partialPath);
- }
-
- public PublicResource tryGetPublicResource(TreeLogger logger,
- String partialPath) {
- return getParent().tryGetPublicResource(logger, partialPath);
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/LinkerOrder.java b/dev/core/src/com/google/gwt/dev/linker/LinkerOrder.java
new file mode 100644
index 0000000..f26a78d
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/LinkerOrder.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines the relative order in which a Linker will be run.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface LinkerOrder {
+ /**
+ * Allowable values for the LinkerOrder.
+ */
+ public enum Order {
+ /**
+ * Runs after the primary linker.
+ */
+ POST,
+
+ /**
+ * Runs before the primary linker.
+ */
+ PRE,
+
+ /**
+ * Defines the primary linker. Adding a primary linker to the Linker stack
+ * will override the previously-set primary linker.
+ */
+ PRIMARY;
+ }
+
+ Order value();
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/ModuleResource.java b/dev/core/src/com/google/gwt/dev/linker/ModuleResource.java
deleted file mode 100644
index 4f65a9f..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/ModuleResource.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
-import java.io.InputStream;
-
-/**
- * Provides access to resources used by the module.
- */
-public interface ModuleResource {
- /**
- * Provides access to the contents of the resource if it is statically
- * available.
- *
- * @return An InputStream accessing the contents of the resource or
- * <code>null</code> if the resource is not available at link time.
- */
- InputStream tryGetResourceAsStream(TreeLogger logger)
- throws UnableToCompleteException;
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/linker/ModuleScriptResource.java b/dev/core/src/com/google/gwt/dev/linker/ModuleScriptResource.java
deleted file mode 100644
index a4a737d..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/ModuleScriptResource.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker;
-
-/**
- * An external script file referenced in the module manifest.
- */
-public interface ModuleScriptResource extends ModuleResource {
- /**
- * The <code>src</code> attribute of the resource. This string is returned
- * raw and may be a partial path or a URL.
- */
- String getSrc();
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/ModuleStylesheetResource.java b/dev/core/src/com/google/gwt/dev/linker/ModuleStylesheetResource.java
deleted file mode 100644
index 4d57310..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/ModuleStylesheetResource.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker;
-
-/**
- * An external stylesheet referenced in the module manifest.
- */
-public interface ModuleStylesheetResource extends ModuleResource {
- /**
- * The <code>src</code> attribute of the resource. This string is returned
- * raw and may be a partial path or a URL.
- */
- String getSrc();
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/NoDeployResourcesShim.java b/dev/core/src/com/google/gwt/dev/linker/NoDeployResourcesShim.java
deleted file mode 100644
index fd49ccc..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/NoDeployResourcesShim.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
-import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * This class prevents generated resources whose partial path begins with
- * {@value #PREFIX} from being visible.
- */
-public class NoDeployResourcesShim extends LinkerContextShim {
- public static final String PREFIX = "no-deploy/";
- private final SortedSet<GeneratedResource> generatedResources;
-
- public NoDeployResourcesShim(TreeLogger logger, LinkerContext parent)
- throws UnableToCompleteException {
- super(logger, parent);
-
- SortedSet<GeneratedResource> mutableSet = new TreeSet<GeneratedResource>(
- GENERATED_RESOURCE_COMPARATOR);
-
- SortedSet<GeneratedResource> view = super.getGeneratedResources();
- for (GeneratedResource res : view) {
- if (!res.getPartialPath().toLowerCase().startsWith(PREFIX)) {
- mutableSet.add(res);
- } else {
- logger.log(TreeLogger.SPAM, "Excluding generated resource "
- + res.getPartialPath(), null);
- }
- }
-
- assert mutableSet.size() <= view.size();
-
- if (mutableSet.size() == view.size()) {
- // Reuse the existing view
- generatedResources = view;
-
- } else {
- // Ensure that the new view is immutable
- generatedResources = Collections.unmodifiableSortedSet(mutableSet);
- }
- }
-
- @Override
- public SortedSet<GeneratedResource> getGeneratedResources() {
- return generatedResources;
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/PublicResource.java b/dev/core/src/com/google/gwt/dev/linker/PublicResource.java
index 07397da..c81a9b6 100644
--- a/dev/core/src/com/google/gwt/dev/linker/PublicResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/PublicResource.java
@@ -18,6 +18,9 @@
/**
* A resource in the module's public path.
*/
-public interface PublicResource extends ModuleResource {
- String getPartialPath();
+public abstract class PublicResource extends EmittedArtifact {
+ protected PublicResource(Class<? extends Linker> linkerType,
+ String partialPath) {
+ super(linkerType, partialPath);
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/ScriptReference.java b/dev/core/src/com/google/gwt/dev/linker/ScriptReference.java
new file mode 100644
index 0000000..82e91ba
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/ScriptReference.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+/**
+ * An external script file referenced in the module manifest.
+ */
+public abstract class ScriptReference extends Artifact<ScriptReference> {
+ private final String src;
+
+ protected ScriptReference(Class<? extends Linker> linkerType, String src) {
+ super(linkerType);
+ this.src = src;
+ }
+
+ /**
+ * The <code>src</code> attribute of the resource. This string is returned
+ * raw and may be a partial path or a URL.
+ */
+ public final String getSrc() {
+ return src;
+ }
+
+ @Override
+ public final int hashCode() {
+ return getSrc().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "<script src='" + getSrc() + "'>";
+ }
+
+ @Override
+ protected final int compareToComparableArtifact(ScriptReference o) {
+ return getSrc().compareTo(o.getSrc());
+ }
+
+ @Override
+ protected final Class<ScriptReference> getComparableArtifactType() {
+ return ScriptReference.class;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/StylesheetReference.java b/dev/core/src/com/google/gwt/dev/linker/StylesheetReference.java
new file mode 100644
index 0000000..2900f13
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/linker/StylesheetReference.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.linker;
+
+/**
+ * An external stylesheet referenced in the module manifest.
+ */
+public abstract class StylesheetReference extends Artifact<StylesheetReference> {
+ private final String src;
+
+ protected StylesheetReference(Class<? extends Linker> linkerType, String src) {
+ super(linkerType);
+ this.src = src;
+ }
+
+ /**
+ * The <code>src</code> attribute of the resource. This string is returned
+ * raw and may be a partial path or a URL.
+ */
+ public final String getSrc() {
+ return src;
+ }
+
+ @Override
+ public final int hashCode() {
+ return getSrc().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "<style src='" + getSrc() + "'>";
+ }
+
+ @Override
+ protected final int compareToComparableArtifact(StylesheetReference o) {
+ return getSrc().compareTo(o.getSrc());
+ }
+
+ @Override
+ protected Class<StylesheetReference> getComparableArtifactType() {
+ return StylesheetReference.class;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/linker/HostedModeLinker.java b/dev/core/src/com/google/gwt/dev/linker/impl/HostedModeLinker.java
similarity index 76%
rename from dev/core/src/com/google/gwt/dev/linker/HostedModeLinker.java
rename to dev/core/src/com/google/gwt/dev/linker/impl/HostedModeLinker.java
index 710a440..3aad6f2 100644
--- a/dev/core/src/com/google/gwt/dev/linker/HostedModeLinker.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/HostedModeLinker.java
@@ -13,10 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.linker;
+package com.google.gwt.dev.linker.impl;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.LinkerContext;
import com.google.gwt.dev.util.Util;
import com.google.gwt.util.tools.Utility;
@@ -26,25 +28,14 @@
* This is a partial implementation of the Linker interface to support hosted
* mode.
*/
+// TODO When this class is removed, move SelectionScriptLinker to gwt-user
public final class HostedModeLinker extends SelectionScriptLinker {
@Override
- public void doEmitArtifacts(TreeLogger logger, LinkerContext context)
+ public String generateSelectionScript(TreeLogger logger,
+ LinkerContext context, ArtifactSet artifacts)
throws UnableToCompleteException {
- try {
- // Add hosted mode iframe contents
- String hostedHtml = Utility.getFileFromClassPath("com/google/gwt/dev/linker/hosted.html");
- doEmit(logger, context, Util.getBytes(hostedHtml), "hosted.html");
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Unable to copy support resource", e);
- throw new UnableToCompleteException();
- }
- }
-
- @Override
- public String generateSelectionScript(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- return super.generateSelectionScript(logger, context);
+ return super.generateSelectionScript(logger, context, artifacts);
}
public String getDescription() {
@@ -52,6 +43,23 @@
}
@Override
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException {
+ ArtifactSet toReturn = new ArtifactSet(artifacts);
+
+ try {
+ // Add hosted mode iframe contents
+ String hostedHtml = Utility.getFileFromClassPath("com/google/gwt/dev/linker/impl/hosted.html");
+ toReturn.add(emitBytes(logger, Util.getBytes(hostedHtml), "hosted.html"));
+ } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Unable to copy support resource", e);
+ throw new UnableToCompleteException();
+ }
+
+ return toReturn;
+ }
+
+ @Override
protected String getCompilationExtension(TreeLogger logger,
LinkerContext context) throws UnableToCompleteException {
return unsupported(logger);
diff --git a/dev/core/src/com/google/gwt/dev/linker/SelectionScriptLinker.java b/dev/core/src/com/google/gwt/dev/linker/impl/SelectionScriptLinker.java
similarity index 81%
rename from dev/core/src/com/google/gwt/dev/linker/SelectionScriptLinker.java
rename to dev/core/src/com/google/gwt/dev/linker/impl/SelectionScriptLinker.java
index b2bd677..a7d4924 100644
--- a/dev/core/src/com/google/gwt/dev/linker/SelectionScriptLinker.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/SelectionScriptLinker.java
@@ -13,10 +13,18 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.linker;
+package com.google.gwt.dev.linker.impl;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.linker.AbstractLinker;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.CompilationResult;
+import com.google.gwt.dev.linker.EmittedArtifact;
+import com.google.gwt.dev.linker.LinkerContext;
+import com.google.gwt.dev.linker.ScriptReference;
+import com.google.gwt.dev.linker.SelectionProperty;
+import com.google.gwt.dev.linker.StylesheetReference;
import com.google.gwt.dev.util.Util;
import com.google.gwt.util.tools.Utility;
@@ -26,13 +34,19 @@
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.SortedSet;
/**
* A base class for Linkers that use an external script to boostrap the GWT
* module. This implementation injects JavaScript snippits into a JS program
* defined in an external file.
*/
-abstract class SelectionScriptLinker extends AbstractLinker {
+public abstract class SelectionScriptLinker extends AbstractLinker {
+ /**
+ * TODO(bobv): Move this class into c.g.g.core.linker when HostedModeLinker
+ * goes away?
+ */
+
/**
* Determines whether or not the URL is relative.
*
@@ -73,32 +87,39 @@
private final Map<CompilationResult, String> compilationPartialPaths = new IdentityHashMap<CompilationResult, String>();
@Override
- protected void doEmitArtifacts(TreeLogger logger, LinkerContext context)
- throws UnableToCompleteException {
- super.doEmitArtifacts(logger, context);
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException {
+ ArtifactSet toReturn = new ArtifactSet(artifacts);
- emitSelectionScript(logger, context);
+ for (CompilationResult compilation : toReturn.find(CompilationResult.class)) {
+ toReturn.add(doEmitCompilation(logger, context, compilation));
+ }
+
+ toReturn.add(emitSelectionScript(logger, context, artifacts));
+ return toReturn;
}
- @Override
- protected void doEmitCompilation(TreeLogger logger, LinkerContext context,
- CompilationResult result) throws UnableToCompleteException {
+ protected EmittedArtifact doEmitCompilation(TreeLogger logger,
+ LinkerContext context, CompilationResult result)
+ throws UnableToCompleteException {
StringBuffer b = new StringBuffer();
b.append(getModulePrefix(logger, context));
b.append(result.getJavaScript());
b.append(getModuleSuffix(logger, context));
- String partialPath = emitWithStrongName(logger, context,
+ EmittedArtifact toReturn = emitWithStrongName(logger,
Util.getBytes(b.toString()), "", getCompilationExtension(logger,
context));
- compilationPartialPaths.put(result, partialPath);
+ compilationPartialPaths.put(result, toReturn.getPartialPath());
+ return toReturn;
}
- protected void emitSelectionScript(TreeLogger logger, LinkerContext context)
+ protected EmittedArtifact emitSelectionScript(TreeLogger logger,
+ LinkerContext context, ArtifactSet artifacts)
throws UnableToCompleteException {
- String selectionScript = generateSelectionScript(logger, context);
+ String selectionScript = generateSelectionScript(logger, context, artifacts);
byte[] selectionScriptBytes = Util.getBytes(context.optimizeJavaScript(
logger, selectionScript));
- doEmit(logger, context, selectionScriptBytes, context.getModuleName()
+ return emitBytes(logger, selectionScriptBytes, context.getModuleName()
+ ".nocache.js");
}
@@ -147,7 +168,9 @@
}
protected String generateSelectionScript(TreeLogger logger,
- LinkerContext context) throws UnableToCompleteException {
+ LinkerContext context, ArtifactSet artifacts)
+ throws UnableToCompleteException {
+
StringBuffer selectionScript;
try {
selectionScript = new StringBuffer(
@@ -168,13 +191,13 @@
// Add external dependencies
startPos = selectionScript.indexOf("// __MODULE_DEPS_END__");
if (startPos != -1) {
- for (ModuleStylesheetResource resource : context.getModuleStylesheets()) {
+ for (StylesheetReference resource : artifacts.find(StylesheetReference.class)) {
String text = generateStylesheetInjector(resource.getSrc());
selectionScript.insert(startPos, text);
startPos += text.length();
}
- for (ModuleScriptResource resource : context.getModuleScripts()) {
+ for (ScriptReference resource : artifacts.find(ScriptReference.class)) {
String text = generateScriptInjector(resource.getSrc());
selectionScript.insert(startPos, text);
startPos += text.length();
@@ -192,23 +215,24 @@
}
// Possibly add permutations
+ SortedSet<CompilationResult> compilations = artifacts.find(CompilationResult.class);
startPos = selectionScript.indexOf("// __PERMUTATIONS_END__");
if (startPos != -1) {
StringBuffer text = new StringBuffer();
- if (context.getCompilations().size() == 0) {
+ if (compilations.size() == 0) {
// We'll see this when running in Hosted Mode. The way the selection
// templates are structured is such that this line won't be executed
text.append("strongName = null;");
- } else if (context.getCompilations().size() == 1) {
+ } else if (compilations.size() == 1) {
// Just one distinct compilation; no need to evaluate properties
- Iterator<CompilationResult> iter = context.getCompilations().iterator();
+ Iterator<CompilationResult> iter = compilations.iterator();
CompilationResult result = iter.next();
text.append("strongName = '" + compilationPartialPaths.get(result)
+ "';");
} else {
- for (CompilationResult r : context.getCompilations()) {
+ for (CompilationResult r : compilations) {
for (Map<SelectionProperty, String> propertyMap : r.getPropertyMap()) {
// unflatten([v1, v2, v3], 'strongName');
text.append("unflattenKeylistIntoAnswers([");
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardCompilationResult.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardCompilationResult.java
index b751a45..893a822 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardCompilationResult.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardCompilationResult.java
@@ -35,7 +35,7 @@
/**
* The standard implementation of {@link CompilationResult}.
*/
-public class StandardCompilationResult implements CompilationResult {
+public class StandardCompilationResult extends CompilationResult {
/**
* Smaller maps come before larger maps, then we compare the concatenation of
@@ -74,6 +74,7 @@
public StandardCompilationResult(TreeLogger logger, String js, File cacheDir)
throws UnableToCompleteException {
+ super(StandardLinkerContext.class);
this.js = new SoftReference<String>(js);
byte[] bytes = Util.getBytes(js);
@@ -110,21 +111,4 @@
public String getStrongName() {
return strongName;
}
-
- @Override
- public String toString() {
- StringBuffer b = new StringBuffer();
- b.append("{");
- for (SortedMap<SelectionProperty, String> map : propertyValues) {
- b.append(" {");
- for (Map.Entry<SelectionProperty, String> entry : map.entrySet()) {
- b.append(" ").append(entry.getKey().getName()).append(":").append(
- entry.getValue());
- }
- b.append(" }");
- }
- b.append(" }");
-
- return b.toString();
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardGeneratedResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardGeneratedResource.java
index 5f4bd81..ba2ce8d 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardGeneratedResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardGeneratedResource.java
@@ -15,21 +15,33 @@
*/
package com.google.gwt.dev.linker.impl;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.linker.GeneratedResource;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
/**
* The standard implementation of {@link GeneratedResource}.
*/
-public class StandardGeneratedResource extends StandardModuleResource implements
- GeneratedResource {
+public class StandardGeneratedResource extends GeneratedResource {
+ private final URL url;
public StandardGeneratedResource(String partialPath, URL url) {
- super(partialPath, url);
+ super(StandardLinkerContext.class, partialPath);
+ this.url = url;
}
- public String getPartialPath() {
- return getId();
+ @Override
+ public InputStream getContents(TreeLogger logger)
+ throws UnableToCompleteException {
+ try {
+ return url.openStream();
+ } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Unable to open file", e);
+ throw new UnableToCompleteException();
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardLinkerContext.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardLinkerContext.java
index 6471d2b..d949572 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardLinkerContext.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardLinkerContext.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.GWTCompiler;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.cfg.Script;
@@ -38,43 +39,39 @@
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsScope;
-import com.google.gwt.dev.linker.CompilationResult;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.EmittedArtifact;
import com.google.gwt.dev.linker.GeneratedResource;
import com.google.gwt.dev.linker.Linker;
import com.google.gwt.dev.linker.LinkerContext;
-import com.google.gwt.dev.linker.LinkerContextShim;
-import com.google.gwt.dev.linker.ModuleScriptResource;
-import com.google.gwt.dev.linker.ModuleStylesheetResource;
+import com.google.gwt.dev.linker.LinkerOrder;
import com.google.gwt.dev.linker.PublicResource;
import com.google.gwt.dev.linker.SelectionProperty;
+import com.google.gwt.dev.linker.LinkerOrder.Order;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Util;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
-import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.SortedSet;
+import java.util.Stack;
import java.util.TreeSet;
/**
* An implementation of {@link LinkerContext} that is initialized from a
* {@link ModuleDef}.
*/
-public class StandardLinkerContext implements LinkerContext {
+public class StandardLinkerContext extends Linker implements LinkerContext {
/**
* Applies the {@link JsStringInterner} optimization to each top-level
@@ -95,18 +92,16 @@
}
}
- private final File compilationsDir;
- private final SortedSet<GeneratedResource> generatedResources;
- private final Map<String, GeneratedResource> generatedResourcesByName = new HashMap<String, GeneratedResource>();
- private final JJSOptions jjsOptions;
+ static final Comparator<SelectionProperty> SELECTION_PROPERTY_COMPARATOR = new Comparator<SelectionProperty>() {
+ public int compare(SelectionProperty o1, SelectionProperty o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
- /**
- * This determines where a call to {@link #commit(TreeLogger, OutputStream)}
- * will write to. It's intended to be updated by
- * {@link #invokeLinker(TreeLogger, String, Linker)} so that each Linker will
- * write into a different output directory.
- */
- private File linkerOutDir;
+ private final ArtifactSet artifacts = new ArtifactSet();
+ private final File compilationsDir;
+ private final JJSOptions jjsOptions;
+ private final List<Class<? extends Linker>> linkerClasses;
private final String moduleFunctionName;
private final String moduleName;
@@ -115,32 +110,28 @@
* compilation.
*/
private final File moduleOutDir;
- private final Set<String> openPaths = new HashSet<String>();
- private final Map<ByteArrayOutputStream, File> outs = new IdentityHashMap<ByteArrayOutputStream, File>();
private final SortedSet<SelectionProperty> properties;
private final Map<String, StandardSelectionProperty> propertiesByName = new HashMap<String, StandardSelectionProperty>();
- private final SortedSet<PublicResource> publicResources;
- private final Map<String, PublicResource> publicResourcesByName = new HashMap<String, PublicResource>();
private final Map<String, StandardCompilationResult> resultsByStrongName = new HashMap<String, StandardCompilationResult>();
- private final SortedSet<ModuleScriptResource> scriptResources;
- private final List<Class<? extends LinkerContextShim>> shimClasses;
- private final SortedSet<ModuleStylesheetResource> stylesheetResources;
public StandardLinkerContext(TreeLogger logger, ModuleDef module,
- File outDir, File generatorDir, JJSOptions jjsOptions)
- throws UnableToCompleteException {
+ File moduleOutDir, File generatorDir, JJSOptions jjsOptions) {
logger = logger.branch(TreeLogger.DEBUG,
"Constructing StandardLinkerContext", null);
this.jjsOptions = jjsOptions;
this.moduleFunctionName = module.getFunctionName();
this.moduleName = module.getName();
- this.moduleOutDir = outDir;
- this.shimClasses = new ArrayList<Class<? extends LinkerContextShim>>(
- module.getLinkerContextShims());
+ this.moduleOutDir = moduleOutDir;
+ this.linkerClasses = new ArrayList<Class<? extends Linker>>(
+ module.getActiveLinkers());
+ linkerClasses.add(module.getActivePrimaryLinker());
if (moduleOutDir != null) {
- compilationsDir = new File(moduleOutDir, ".gwt-compiler/compilations");
+ compilationsDir = new File(moduleOutDir.getParentFile(),
+ GWTCompiler.GWT_COMPILER_DIR + File.separator + moduleName
+ + File.separator + "compilations");
+
Util.recursiveDelete(compilationsDir, true);
compilationsDir.mkdirs();
logger.log(TreeLogger.SPAM, "compilationsDir: "
@@ -161,34 +152,25 @@
}
properties = Collections.unmodifiableSortedSet(mutableProperties);
- SortedSet<ModuleScriptResource> scripts = new TreeSet<ModuleScriptResource>(
- SCRIPT_RESOURCE_COMPARATOR);
for (Script script : module.getScripts()) {
- scripts.add(new StandardScriptResource(script.getSrc(),
+ artifacts.add(new StandardScriptReference(script.getSrc(),
module.findPublicFile(script.getSrc())));
logger.log(TreeLogger.SPAM, "Added script " + script.getSrc(), null);
}
- scriptResources = Collections.unmodifiableSortedSet(scripts);
- SortedSet<ModuleStylesheetResource> styles = new TreeSet<ModuleStylesheetResource>(
- STYLE_RESOURCE_COMPARATOR);
for (String style : module.getStyles()) {
- styles.add(new StandardStylesheetResource(style,
+ artifacts.add(new StandardStylesheetReference(style,
module.findPublicFile(style)));
logger.log(TreeLogger.SPAM, "Added style " + style, null);
}
- stylesheetResources = Collections.unmodifiableSortedSet(styles);
- SortedSet<GeneratedResource> genResources = new TreeSet<GeneratedResource>(
- GENERATED_RESOURCE_COMPARATOR);
if (generatorDir != null) {
for (String path : Util.recursiveListPartialPaths(generatorDir, false)) {
+ String partialPath = path.replace(File.separatorChar, '/');
try {
- String partialPath = path.replace(File.separatorChar, '/');
GeneratedResource resource = new StandardGeneratedResource(
partialPath, (new File(generatorDir, path)).toURL());
- generatedResourcesByName.put(partialPath, resource);
- genResources.add(resource);
+ artifacts.add(resource);
logger.log(TreeLogger.SPAM, "Added generated resource " + resource,
null);
} catch (MalformedURLException e) {
@@ -198,53 +180,18 @@
}
}
}
- generatedResources = Collections.unmodifiableSortedSet(genResources);
- SortedSet<PublicResource> pubResources = new TreeSet<PublicResource>(
- PUBLIC_RESOURCE_COMPARATOR);
for (String path : module.getAllPublicFiles()) {
- PublicResource resource = new StandardPublicResource(path,
+ String partialPath = path.replace(File.separatorChar, '/');
+ PublicResource resource = new StandardPublicResource(partialPath,
module.findPublicFile(path));
- publicResourcesByName.put(path, resource);
- pubResources.add(resource);
+ artifacts.add(resource);
logger.log(TreeLogger.SPAM, "Added public resource " + resource, null);
}
- publicResources = Collections.unmodifiableSortedSet(pubResources);
}
- public void commit(TreeLogger logger, OutputStream toCommit)
- throws UnableToCompleteException {
- logger = logger.branch(TreeLogger.DEBUG,
- "Attempting to commit OutputStream", null);
-
- if (!outs.containsKey(toCommit)) {
- logger.log(TreeLogger.ERROR,
- "OutputStream was foreign to this LinkerContext", null);
- throw new UnableToCompleteException();
- }
-
- File f = outs.get(toCommit);
- if (f == null) {
- logger.log(TreeLogger.ERROR,
- "The OutputStream has already been committed", null);
- throw new UnableToCompleteException();
- }
-
- /*
- * Record that we will no longer accept this OutputStream as opposed to
- * removing it, which would erroneously indicate that it was a foreign
- * OutputStream.
- */
- ByteArrayOutputStream original = (ByteArrayOutputStream) toCommit;
- outs.put(original, null);
-
- try {
- Util.writeBytesToFile(logger, f, original.toByteArray());
- } finally {
- // Dump the byte buffer;
- original.reset();
- }
- logger.log(TreeLogger.DEBUG, "Successfully committed " + f.getPath(), null);
+ public ArtifactSet getArtifacts() {
+ return artifacts;
}
public StandardCompilationResult getCompilation(TreeLogger logger, String js)
@@ -255,19 +202,14 @@
if (result == null) {
result = new StandardCompilationResult(logger, js, compilationsDir);
resultsByStrongName.put(result.getStrongName(), result);
+ artifacts.add(result);
}
return result;
}
- public SortedSet<CompilationResult> getCompilations() {
- SortedSet<CompilationResult> toReturn = new TreeSet<CompilationResult>(
- COMPILATION_RESULT_COMPARATOR);
- toReturn.addAll(resultsByStrongName.values());
- return Collections.unmodifiableSortedSet(toReturn);
- }
-
- public SortedSet<GeneratedResource> getGeneratedResources() {
- return generatedResources;
+ @Override
+ public String getDescription() {
+ return "Root Linker";
}
public String getModuleFunctionName() {
@@ -278,14 +220,6 @@
return moduleName;
}
- public SortedSet<ModuleScriptResource> getModuleScripts() {
- return scriptResources;
- }
-
- public SortedSet<ModuleStylesheetResource> getModuleStylesheets() {
- return stylesheetResources;
- }
-
public SortedSet<SelectionProperty> getProperties() {
return properties;
}
@@ -294,82 +228,25 @@
return propertiesByName.get(name);
}
- public SortedSet<PublicResource> getPublicResources() {
- return publicResources;
- }
+ @Override
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts) throws UnableToCompleteException {
- /**
- * Run a linker in an isolated out directory.
- */
- public void invokeLinker(TreeLogger logger, String target, Linker linker)
- throws UnableToCompleteException {
- try {
- // Assign the directory the Linker will work in.
- linkerOutDir = new File(moduleOutDir, target);
- if (!moduleOutDir.equals(linkerOutDir.getParentFile())) {
- // This should never actually happen, since the target must be
- // a valid Java identifier
- logger.log(TreeLogger.ERROR,
- "Trying to create linker dir in wrong place", null);
- throw new UnableToCompleteException();
- }
+ logger = logger.branch(TreeLogger.INFO, "Linking compilation into "
+ + moduleOutDir.getPath(), null);
- // We nuke the contents of the directory
- Util.recursiveDelete(linkerOutDir, true);
- linkerOutDir.mkdirs();
+ artifacts = invokeLinkerStack(logger);
- if (!linkerOutDir.canWrite()) {
- logger.log(TreeLogger.ERROR, "Unable create linker dir"
- + linkerOutDir.getPath(), null);
- throw new UnableToCompleteException();
- }
+ for (EmittedArtifact artifact : artifacts.find(EmittedArtifact.class)) {
+ TreeLogger artifactLogger = logger.branch(TreeLogger.SPAM,
+ "Emitting resource " + artifact.getPartialPath(), null);
- logger = logger.branch(TreeLogger.INFO, "Linking compilation with "
- + linker.getDescription() + " Linker into " + linkerOutDir.getPath(),
- null);
-
- // Instantiate per-Linker instances of the LinkerContextShims
- LinkerContext shimParent = this;
- for (Class<? extends LinkerContextShim> clazz : shimClasses) {
- TreeLogger shimLogger = logger.branch(TreeLogger.DEBUG,
- "Constructing LinkerContextShim " + clazz.getName(), null);
- try {
- Constructor<? extends LinkerContextShim> constructor = clazz.getConstructor(
- TreeLogger.class, LinkerContext.class);
- shimParent = constructor.newInstance(shimLogger, shimParent);
- } catch (InstantiationException e) {
- shimLogger.log(TreeLogger.ERROR,
- "Unable to create LinkerContextShim", e);
- throw new UnableToCompleteException();
- } catch (InvocationTargetException e) {
- shimLogger.log(TreeLogger.ERROR,
- "Unable to create LinkerContextShim", e);
- throw new UnableToCompleteException();
- } catch (NoSuchMethodException e) {
- shimLogger.log(TreeLogger.ERROR,
- "LinkerContextShim subtypes must implement a two-argument "
- + "constructor accepting a TreeLogger and a LinkerContext", e);
- throw new UnableToCompleteException();
- } catch (IllegalAccessException e) {
- shimLogger.log(TreeLogger.ERROR,
- "Unable to create LinkerContextShim", e);
- throw new UnableToCompleteException();
- }
- }
-
- linker.link(logger, shimParent);
-
- // Unwind the LinkerContextShim stack
- while (shimParent != this) {
- LinkerContextShim shim = (LinkerContextShim) shimParent;
- shim.commit(logger.branch(TreeLogger.DEBUG,
- "Committing LinkerContextShim " + shim.getClass().getName(), null));
- shimParent = shim.getParent();
- }
-
- } finally {
- reset();
+ File outFile = new File(moduleOutDir, artifact.getPartialPath());
+ assert !outFile.exists() : "Attempted to overwrite " + outFile.getPath();
+ Util.copy(logger, artifact.getContents(artifactLogger), outFile);
}
+
+ return artifacts;
}
public String optimizeJavaScript(TreeLogger logger, String program)
@@ -428,36 +305,69 @@
return out.toString();
}
- public OutputStream tryCreateArtifact(TreeLogger logger, String partialPath) {
- File f = new File(linkerOutDir, partialPath);
- if (f.exists() || openPaths.contains(partialPath)) {
- logger.branch(TreeLogger.DEBUG, "Refusing to create artifact "
- + partialPath + " because it already exists or is already open.",
- null);
- return null;
+ /**
+ * Run the linker stack.
+ */
+ private ArtifactSet invokeLinkerStack(TreeLogger logger)
+ throws UnableToCompleteException {
+ ArtifactSet workingArtifacts = new ArtifactSet(artifacts);
+ Stack<Linker> linkerStack = new Stack<Linker>();
+
+ EnumSet<Order> phasePre = EnumSet.of(Order.PRE, Order.PRIMARY);
+ EnumSet<Order> phasePost = EnumSet.of(Order.POST);
+
+ // Instantiate instances of the Linkers
+ for (Class<? extends Linker> clazz : linkerClasses) {
+ Linker linker;
+
+ // Create an instance of the Linker
+ try {
+ linker = clazz.newInstance();
+ linkerStack.push(linker);
+ } catch (InstantiationException e) {
+ logger.log(TreeLogger.ERROR, "Unable to create LinkerContextShim", e);
+ throw new UnableToCompleteException();
+ } catch (IllegalAccessException e) {
+ logger.log(TreeLogger.ERROR, "Unable to create LinkerContextShim", e);
+ throw new UnableToCompleteException();
+ }
+
+ // Detemine if we need to invoke the Linker in the current link phase
+ Order order = clazz.getAnnotation(LinkerOrder.class).value();
+ if (!phasePre.contains(order)) {
+ continue;
+ }
+
+ // The primary Linker is guaranteed to be last in the order
+ if (order == Order.PRIMARY) {
+ assert linkerClasses.get(linkerClasses.size() - 1).equals(clazz);
+ }
+
+ TreeLogger linkerLogger = logger.branch(TreeLogger.INFO,
+ "Invoking Linker " + linker.getDescription(), null);
+
+ workingArtifacts.freeze();
+ workingArtifacts = linker.link(linkerLogger, this, workingArtifacts);
}
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- outs.put(out, f);
- openPaths.add(partialPath);
- return out;
- }
+ // Pop the primary linker off of the stack
+ linkerStack.pop();
- public GeneratedResource tryGetGeneratedResource(TreeLogger logger,
- String name) {
- return generatedResourcesByName.get(name);
- }
+ // Unwind the stack
+ while (!linkerStack.isEmpty()) {
+ Linker linker = linkerStack.pop();
+ Class<? extends Linker> linkerType = linker.getClass();
- public PublicResource tryGetPublicResource(TreeLogger logger, String name) {
- return publicResourcesByName.get(name);
- }
+ // See if the Linker should be run in the current phase
+ Order order = linkerType.getAnnotation(LinkerOrder.class).value();
+ if (phasePost.contains(order)) {
+ workingArtifacts.freeze();
+ workingArtifacts = linker.link(logger.branch(TreeLogger.INFO,
+ "Invoking Linker " + linker.getDescription(), null), this,
+ workingArtifacts);
+ }
+ }
- /**
- * Reset the context.
- */
- private void reset() {
- linkerOutDir = null;
- openPaths.clear();
- outs.clear();
+ return workingArtifacts;
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardModuleResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardModuleResource.java
deleted file mode 100644
index 5cbc300..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardModuleResource.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker.impl;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.linker.ModuleResource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-/**
- * The standard implementation of {@link ModuleResource}.
- */
-public abstract class StandardModuleResource implements ModuleResource {
- private final String id;
- private final URL url;
-
- protected StandardModuleResource(String id, URL url) {
- this.id = id;
- this.url = url;
- }
-
- public String getId() {
- return id;
- }
-
- public URL getURL() {
- return url;
- }
-
- public InputStream tryGetResourceAsStream(TreeLogger logger)
- throws UnableToCompleteException {
- if (url == null) {
- logger.branch(TreeLogger.DEBUG, "No contents for resource", null);
- return null;
- }
-
- logger = logger.branch(TreeLogger.DEBUG, "Attempting to get stream for "
- + url.toExternalForm(), null);
-
- try {
- return url.openStream();
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Unable to open stream", e);
- throw new UnableToCompleteException();
- }
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardPublicResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardPublicResource.java
index 269dbf4..a58ecdd 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardPublicResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardPublicResource.java
@@ -15,21 +15,33 @@
*/
package com.google.gwt.dev.linker.impl;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.linker.PublicResource;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
/**
* The standard implementation of {@link PublicResource}.
*/
-public class StandardPublicResource extends StandardModuleResource implements
- PublicResource {
+public class StandardPublicResource extends PublicResource {
+ private final URL url;
public StandardPublicResource(String partialPath, URL url) {
- super(partialPath, url);
+ super(StandardLinkerContext.class, partialPath);
+ this.url = url;
}
- public String getPartialPath() {
- return getId();
+ @Override
+ public InputStream getContents(TreeLogger logger)
+ throws UnableToCompleteException {
+ try {
+ return url.openStream();
+ } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Unable to open file", e);
+ throw new UnableToCompleteException();
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptReference.java
similarity index 61%
copy from dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java
copy to dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptReference.java
index 62303ea..1844609 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptReference.java
@@ -15,25 +15,20 @@
*/
package com.google.gwt.dev.linker.impl;
-import com.google.gwt.dev.linker.ModuleScriptResource;
+import com.google.gwt.dev.linker.ScriptReference;
import java.net.URL;
/**
- * The standard implementation of {@link ModuleScriptResource}.
+ * The standard implementation of {@link ScriptReference}.
*/
-public class StandardScriptResource extends StandardModuleResource implements
- ModuleScriptResource {
+public class StandardScriptReference extends ScriptReference {
- public StandardScriptResource(String src) {
- this(src, null);
- }
-
- public StandardScriptResource(String src, URL url) {
- super(src, url);
- }
-
- public String getSrc() {
- return getId();
+ /**
+ * Might use <code>url</code>someday.
+ */
+ @SuppressWarnings("unused")
+ public StandardScriptReference(String src, URL url) {
+ super(StandardLinkerContext.class, src);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetReference.java
similarity index 61%
rename from dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java
rename to dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetReference.java
index 62303ea..5aff3ea 100644
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardScriptResource.java
+++ b/dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetReference.java
@@ -15,25 +15,20 @@
*/
package com.google.gwt.dev.linker.impl;
-import com.google.gwt.dev.linker.ModuleScriptResource;
+import com.google.gwt.dev.linker.StylesheetReference;
import java.net.URL;
/**
- * The standard implementation of {@link ModuleScriptResource}.
+ * The standard implementation of {@link StylesheetReference}.
*/
-public class StandardScriptResource extends StandardModuleResource implements
- ModuleScriptResource {
+public class StandardStylesheetReference extends StylesheetReference {
- public StandardScriptResource(String src) {
- this(src, null);
- }
-
- public StandardScriptResource(String src, URL url) {
- super(src, url);
- }
-
- public String getSrc() {
- return getId();
+ /**
+ * Might use <code>url</code>someday.
+ */
+ @SuppressWarnings("unused")
+ public StandardStylesheetReference(String src, URL url) {
+ super(StandardLinkerContext.class, src);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetResource.java b/dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetResource.java
deleted file mode 100644
index 306ab97..0000000
--- a/dev/core/src/com/google/gwt/dev/linker/impl/StandardStylesheetResource.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.linker.impl;
-
-import com.google.gwt.dev.linker.ModuleStylesheetResource;
-
-import java.net.URL;
-
-/**
- * The standard implementation of {@link ModuleStylesheetResource}.
- */
-public class StandardStylesheetResource extends StandardModuleResource
- implements ModuleStylesheetResource {
-
- public StandardStylesheetResource(String src) {
- this(src, null);
- }
-
- public StandardStylesheetResource(String src, URL url) {
- super(src, url);
- }
-
- public String getSrc() {
- return getId();
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/linker/hosted.html b/dev/core/src/com/google/gwt/dev/linker/impl/hosted.html
similarity index 100%
rename from dev/core/src/com/google/gwt/dev/linker/hosted.html
rename to dev/core/src/com/google/gwt/dev/linker/impl/hosted.html
diff --git a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
index d647c3c..3593d94 100644
--- a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
+++ b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
@@ -21,7 +21,9 @@
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.jjs.JJSOptions;
-import com.google.gwt.dev.linker.HostedModeLinker;
+import com.google.gwt.dev.linker.ArtifactSet;
+import com.google.gwt.dev.linker.EmittedArtifact;
+import com.google.gwt.dev.linker.impl.HostedModeLinker;
import com.google.gwt.dev.linker.impl.StandardLinkerContext;
import com.google.gwt.dev.util.HttpHeaders;
import com.google.gwt.dev.util.Util;
@@ -390,10 +392,10 @@
ModuleDef moduleDef = getModuleDef(logger, moduleName);
foundResource = moduleDef.findPublicFile(partialPath);
- File moduleDir = new File(getOutputDir(), moduleName);
if (foundResource == null) {
// Look for generated files
- File shellDir = new File(moduleDir, GWTShell.GWT_SHELL_PATH);
+ File shellDir = new File(getOutputDir(), GWTShell.GWT_SHELL_PATH
+ + File.separator + moduleName);
File requestedFile = new File(shellDir, partialPath);
if (requestedFile.exists()) {
try {
@@ -410,9 +412,8 @@
* output directory of the first linker defined in the <set-linker> tab.
*/
if (foundResource == null) {
- File linkerDir = new File(moduleDir,
- moduleDef.getActiveLinkerNames()[0]);
- File requestedFile = new File(linkerDir, partialPath);
+ File moduleDir = new File(getOutputDir(), moduleName);
+ File requestedFile = new File(moduleDir, partialPath);
if (requestedFile.exists()) {
try {
foundResource = requestedFile.toURI().toURL();
@@ -521,13 +522,21 @@
logger.log(TreeLogger.TRACE, msg, null);
ModuleDef moduleDef = getModuleDef(logger, moduleName);
- File moduleDir = new File(getOutputDir(), moduleDef.getName());
+ File linkerDir = new File(getOutputDir(), GWTShell.GWT_SHELL_PATH
+ + File.separator + moduleName);
StandardLinkerContext context = new StandardLinkerContext(logger,
- moduleDef, moduleDir, null, new JJSOptions());
+ moduleDef, null, null, new JJSOptions());
HostedModeLinker linker = new HostedModeLinker();
- context.invokeLinker(logger, GWTShell.GWT_SHELL_PATH, linker);
- return linker.generateSelectionScript(logger, context);
+
+ ArtifactSet artifacts = linker.link(logger, context, new ArtifactSet());
+ for (EmittedArtifact artifact : artifacts.find(EmittedArtifact.class)) {
+ File out = new File(linkerDir, artifact.getPartialPath());
+ Util.copy(logger, artifact.getContents(logger), out);
+ }
+
+ return linker.generateSelectionScript(logger, context,
+ context.getArtifacts());
}
/**
@@ -921,10 +930,8 @@
// RemoteServiceServlets to load public and generated resources via
// ServeletContext.getResourceAsStream()
//
- File moduleDir = new File(getOutputDir(), moduleDef.getName());
-
ServletContext context = new HostedModeServletContextProxy(
- getServletContext(), moduleDef, moduleDir);
+ getServletContext(), moduleDef, getOutputDir());
ServletConfig config = new HostedModeServletConfigProxy(
getServletConfig(), context);
diff --git a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java b/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
index a016880..97f6058 100644
--- a/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
+++ b/dev/core/src/com/google/gwt/dev/shell/HostedModeServletContextProxy.java
@@ -38,13 +38,13 @@
class HostedModeServletContextProxy implements ServletContext {
private final ServletContext context;
private final ModuleDef moduleDef;
- private final File moduleDir;
+ private final File outDir;
HostedModeServletContextProxy(ServletContext context, ModuleDef moduleDef,
- File moduleDir) {
+ File outDir) {
this.context = context;
this.moduleDef = moduleDef;
- this.moduleDir = moduleDir;
+ this.outDir = outDir;
}
/**
@@ -161,7 +161,8 @@
URL url = moduleDef.findPublicFile(partialPath);
if (url == null) {
// Otherwise try the path but rooted in the shell's output directory
- File shellDir = new File(moduleDir, GWTShell.GWT_SHELL_PATH);
+ File shellDir = new File(outDir, GWTShell.GWT_SHELL_PATH + File.separator
+ + moduleDef.getName());
File requestedFile = new File(shellDir, partialPath);
if (requestedFile.exists()) {
url = requestedFile.toURI().toURL();
@@ -174,8 +175,8 @@
* the first linker defined in the <set-linker> tab.
*/
if (url == null) {
- File linkerDir = new File(moduleDir, moduleDef.getActiveLinkerNames()[0]);
- File requestedFile = new File(linkerDir, partialPath);
+ File requestedFile = new File(new File(outDir, moduleDef.getName()),
+ partialPath);
if (requestedFile.exists()) {
try {
url = requestedFile.toURI().toURL();
diff --git a/dev/core/src/com/google/gwt/dev/util/Util.java b/dev/core/src/com/google/gwt/dev/util/Util.java
index 77ffafe..42d2baa 100644
--- a/dev/core/src/com/google/gwt/dev/util/Util.java
+++ b/dev/core/src/com/google/gwt/dev/util/Util.java
@@ -31,6 +31,7 @@
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -94,6 +95,7 @@
return t;
}
+ @SuppressWarnings("unchecked")
public static <T> T[] append(T[] xs, T x) {
int n = xs.length;
T[] t = (T[]) Array.newInstance(xs.getClass().getComponentType(), n + 1);
@@ -102,6 +104,7 @@
return t;
}
+ @SuppressWarnings("unchecked")
public static <T> T[] append(T[] appendToThis, T[] these) {
if (appendToThis == null) {
throw new NullPointerException("attempt to append to a null array");
@@ -671,20 +674,39 @@
* directory
*/
public static void recursiveDelete(File file, boolean childrenOnly) {
+ recursiveDelete(file, childrenOnly, null);
+ }
+
+ /**
+ * Selectively deletes a file or recursively deletes a directory.
+ *
+ * @param file the file to delete, or if this is a directory, the directory
+ * that serves as the root of a recursive deletion
+ * @param childrenOnly if <code>true</code>, only the children of a
+ * directory are recursively deleted but the specified directory
+ * itself is spared; if <code>false</code>, the specified
+ * directory is also deleted; ignored if <code>file</code> is not a
+ * directory
+ * @param filter only files matching this filter will be deleted
+ */
+ public static void recursiveDelete(File file, boolean childrenOnly,
+ FileFilter filter) {
if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
for (int i = 0; i < children.length; i++) {
- recursiveDelete(children[i], false);
+ recursiveDelete(children[i], false, filter);
}
}
if (childrenOnly) {
// Do not delete the specified directory itself.
- //
return;
}
}
- file.delete();
+
+ if (filter == null || filter.accept(file)) {
+ file.delete();
+ }
}
/**
@@ -728,6 +750,7 @@
return new File(file.getParentFile(), name);
}
+ @SuppressWarnings("unchecked")
public static <T> T[] removeNulls(T[] a) {
int n = a.length;
for (int i = 0; i < a.length; i++) {
@@ -767,6 +790,7 @@
* Class<? super T> is used to allow creation of generic types, such as
* Map.Entry<K,V> since we can only pass in Map.Entry.class.
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] toArray(Class<? super T> componentType,
Collection<? extends T> coll) {
int n = coll.size();
@@ -778,6 +802,7 @@
* Like {@link #toArray(Class, Collection)}, but the option of having the
* array reversed.
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] toArrayReversed(Class<? super T> componentType,
Collection<? extends T> coll) {
int n = coll.size();
@@ -1002,7 +1027,7 @@
*
* @param byteLength number of bytes to read
* @return byte array containing the bytes read or <code>null</code> if
- * there is an {@link IOException} or if the requested number of bytes
+ * there is an {@link IOException} or if the requested number of bytes
* cannot be read from the {@link InputStream}
*/
private static byte[] readBytesFromInputStream(InputStream input,
diff --git a/user/src/com/google/gwt/core/Core.gwt.xml b/user/src/com/google/gwt/core/Core.gwt.xml
index 91aee75..fa52b58 100644
--- a/user/src/com/google/gwt/core/Core.gwt.xml
+++ b/user/src/com/google/gwt/core/Core.gwt.xml
@@ -18,13 +18,11 @@
<!-- Every module should directly or indirectly inherit this module. -->
<!-- -->
<module>
- <inherits name="com.google.gwt.dev.jjs.intrinsic.Intrinsic"/>
- <inherits name="com.google.gwt.emul.Emulation"/>
- <define-linker name="std" class="com.google.gwt.dev.linker.IFrameLinker" />
- <define-linker name="sso" class="com.google.gwt.dev.linker.SingleScriptLinker" />
- <define-linker name="xs" class="com.google.gwt.dev.linker.XSLinker" />
- <set-linker name="std" />
-
- <!-- Filters generated resources in the no-deploy/ directory -->
- <extend-linker-context class="com.google.gwt.dev.linker.NoDeployResourcesShim" />
+ <inherits name="com.google.gwt.dev.jjs.intrinsic.Intrinsic" />
+ <inherits name="com.google.gwt.emul.Emulation" />
+ <define-linker name="std" class="com.google.gwt.core.linker.IFrameLinker" />
+ <define-linker name="xs" class="com.google.gwt.core.linker.XSLinker" />
+ <define-linker name="sso" class="com.google.gwt.core.linker.SingleScriptLinker" />
+
+ <add-linker name="std" />
</module>
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index d79a3da..47fa350 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -39,4 +39,7 @@
<inherits name="com.google.gwt.user.TitledPanel" />
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.Accessibility"/>
+
+ <define-linker name="noDeploy" class="com.google.gwt.core.linker.NoDeployResourcesLinker" />
+ <add-linker name="noDeploy" />
</module>
diff --git a/user/test/com/google/gwt/dev/cfg/PublicTagTest.java b/user/test/com/google/gwt/dev/cfg/PublicTagTest.java
index 66c49ba..1af2ad6 100644
--- a/user/test/com/google/gwt/dev/cfg/PublicTagTest.java
+++ b/user/test/com/google/gwt/dev/cfg/PublicTagTest.java
@@ -68,7 +68,7 @@
String moduleName = PublicTagTest.class.getName();
// Find our module output directory and delete it
- File moduleDir = new File(curDir, "www/" + moduleName + "/std");
+ File moduleDir = new File(curDir, "www/" + moduleName);
if (moduleDir.exists()) {
Util.recursiveDelete(moduleDir, false);
}
diff --git a/user/test/com/google/gwt/module/client/NoDeployTest.java b/user/test/com/google/gwt/module/client/NoDeployTest.java
index eb4038b..31a8b96 100644
--- a/user/test/com/google/gwt/module/client/NoDeployTest.java
+++ b/user/test/com/google/gwt/module/client/NoDeployTest.java
@@ -66,7 +66,7 @@
public void testNoDeploy() throws RequestException {
if (!GWT.isScript()) {
- // LinkerContextShims aren't used in hosted-mode
+ // Linkers aren't used in hosted-mode
return;
}
diff --git a/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java b/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
index 46b1d94..0c1bceb 100644
--- a/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
+++ b/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
@@ -19,7 +19,7 @@
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.linker.NoDeployResourcesShim;
+import com.google.gwt.core.linker.NoDeployResourcesLinker;
import com.google.gwt.dev.util.Util;
import com.google.gwt.module.client.NoDeployTest;
@@ -37,7 +37,8 @@
try {
createFile(logger, context, "deploy/exists.txt");
- createFile(logger, context, NoDeployResourcesShim.PREFIX + "inGenerated.txt");
+ createFile(logger, context, NoDeployResourcesLinker.PREFIX
+ + "inGenerated.txt");
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to create test file", e);
throw new UnableToCompleteException();