Add an isPrivate flag to EmittedArtifact.
Private resources are emitted into a module's auxiliary directory.
Track the Generator that created a GeneratedResource.
Update i18n Generator to use private artifacts.
Removes no-deploy/ partial path treatments from generated resources.
Patch by: bobv, jat (i18n)
Review by: jat, bruce
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2276 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorContext.java b/dev/core/src/com/google/gwt/core/ext/GeneratorContext.java
index 33de516..336fa55 100644
--- a/dev/core/src/com/google/gwt/core/ext/GeneratorContext.java
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorContext.java
@@ -15,6 +15,8 @@
*/
package com.google.gwt.core.ext;
+import com.google.gwt.core.ext.linker.Artifact;
+import com.google.gwt.core.ext.linker.GeneratedResource;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import java.io.OutputStream;
@@ -32,14 +34,33 @@
void commit(TreeLogger logger, PrintWriter pw);
/**
+ * Add an Artifact to the {@link com.google.gwt.core.ext.linker.ArtifactSet}
+ * that will be presented to the {@link Linker} chain at the end of the
+ * compilation cycle. Custom sub-classes of Artifact can be used to write
+ * cooperating Generator and Linker combinations. This method is semantically
+ * equivalent to calling
+ * {@link com.google.gwt.core.ext.linker.ArtifactSet#replace(Artifact)} if an
+ * equivalent Artifact had previously been committed.
+ *
+ * @param logger a logger; normally the logger passed into
+ * {@link Generator#generate(TreeLogger, GeneratorContext, String)}
+ * or a branch thereof
+ * @param artifact the Artifact to provide to the Linker chain.
+ */
+ void commitArtifact(TreeLogger logger, Artifact<?> artifact)
+ throws UnableToCompleteException;
+
+ /**
* Commits resource generation begun with
* {@link #tryCreateResource(TreeLogger, String)}.
*
+ * @return the GeneratedResource that was created as a result of committing
+ * the OutputStream.
* @throws UnableToCompleteException if the resource cannot be written to
* disk, if the specified stream is unknown, or if the stream has
* already been committed
*/
- void commitResource(TreeLogger logger, OutputStream os)
+ GeneratedResource commitResource(TreeLogger logger, OutputStream os)
throws UnableToCompleteException;
/**
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/AbstractLinker.java b/dev/core/src/com/google/gwt/core/ext/linker/AbstractLinker.java
index 0d086c3..f2b3cd3 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/AbstractLinker.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/AbstractLinker.java
@@ -20,7 +20,6 @@
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.InputStream;
@@ -29,26 +28,6 @@
*/
public abstract class AbstractLinker extends Linker {
/**
- * Internal type to wrap a byte array.
- */
- private static class SyntheticArtifact extends EmittedArtifact {
- private final byte[] data;
-
- public SyntheticArtifact(Class<? extends Linker> linkerType,
- String partialPath, byte[] data) {
- super(linkerType, partialPath);
- assert data != null;
- this.data = data;
- }
-
- @Override
- public InputStream getContents(TreeLogger logger)
- throws UnableToCompleteException {
- return new ByteArrayInputStream(data);
- }
- }
-
- /**
* A helper method to create an artifact from an array of bytes.
*
* @param logger a TreeLogger
@@ -57,8 +36,7 @@
* @return an artifact that contains the given data
* @throws UnableToCompleteException
*/
- @SuppressWarnings("unused")
- protected final EmittedArtifact emitBytes(TreeLogger logger, byte[] what,
+ protected final SyntheticArtifact emitBytes(TreeLogger logger, byte[] what,
String partialPath) throws UnableToCompleteException {
return new SyntheticArtifact(getClass(), partialPath, what);
}
@@ -72,7 +50,7 @@
* @param partialPath the partial path of the emitted resource
* @return an artifact that contains the contents of the InputStream
*/
- protected final EmittedArtifact emitInputStream(TreeLogger logger,
+ protected final SyntheticArtifact emitInputStream(TreeLogger logger,
InputStream what, String partialPath) throws UnableToCompleteException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Util.copy(logger, what, out);
@@ -87,8 +65,8 @@
* @param partialPath the partial path of the emitted resource
* @return an artifact that contains the contents of the given String
*/
- protected final EmittedArtifact emitString(TreeLogger logger,
- String what, String partialPath) throws UnableToCompleteException {
+ protected final SyntheticArtifact emitString(TreeLogger logger, String what,
+ String partialPath) throws UnableToCompleteException {
return emitBytes(logger, Util.getBytes(what), partialPath);
}
@@ -104,7 +82,7 @@
* Artifact's partial path
* @return an artifact that contains the given data
*/
- protected final EmittedArtifact emitWithStrongName(TreeLogger logger,
+ protected final SyntheticArtifact emitWithStrongName(TreeLogger logger,
byte[] what, String prefix, String suffix)
throws UnableToCompleteException {
String strongName = prefix + Util.computeStrongName(what) + suffix;
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/EmittedArtifact.java b/dev/core/src/com/google/gwt/core/ext/linker/EmittedArtifact.java
index 9c4aba1..85c4ed2 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/EmittedArtifact.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/EmittedArtifact.java
@@ -32,15 +32,27 @@
private final String partialPath;
+ /**
+ * This is mutable because it has no effect on identity.
+ */
+ private boolean isPrivate;
+
protected EmittedArtifact(Class<? extends Linker> linker, String partialPath) {
super(linker);
assert partialPath != null;
this.partialPath = partialPath;
}
+ /**
+ * Provides access to the contents of the EmittedResource.
+ */
public abstract InputStream getContents(TreeLogger logger)
throws UnableToCompleteException;
+ /**
+ * Returns the partial path within the output directory of the
+ * EmittedArtifact.
+ */
public final String getPartialPath() {
return partialPath;
}
@@ -50,6 +62,31 @@
return getPartialPath().hashCode();
}
+ /**
+ * Returns whether or not the data contained in the EmittedArtifact should be
+ * written into the module output directory or into an auxiliary directory.
+ * <p>
+ * EmittedArtifacts that return <code>true</code> for this method will not
+ * be emitted into the normal module output location, but will instead be
+ * written into a directory that is a sibling to the module output directory.
+ * The partial path of the EmittedArtifact will be prepended with the
+ * short-name of the Linker type that created the EmittedArtifact.
+ * <p>
+ * Private EmittedArtifacts are intended for resources that generally should
+ * not be deployed to the server in the same location as the module
+ * compilation artifacts.
+ */
+ public boolean isPrivate() {
+ return isPrivate;
+ }
+
+ /**
+ * Sets the private attribute of the EmittedResource.
+ */
+ public void setPrivate(boolean isPrivate) {
+ this.isPrivate = isPrivate;
+ }
+
@Override
public String toString() {
return getPartialPath();
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/GeneratedResource.java b/dev/core/src/com/google/gwt/core/ext/linker/GeneratedResource.java
index 99b1ac6..28c9400 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/GeneratedResource.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/GeneratedResource.java
@@ -15,14 +15,27 @@
*/
package com.google.gwt.core.ext.linker;
+import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.Linker;
/**
- * A resource generated during the compilation process by a Generator.
+ * A resource created by a {@link Generator} invoking
+ * {@link com.google.gwt.core.ext.GeneratorContext#tryCreateResource(com.google.gwt.core.ext.TreeLogger, String)}
+ * during the compilation process.
*/
public abstract class GeneratedResource extends EmittedArtifact {
+ private final Class<? extends Generator> generatorType;
+
protected GeneratedResource(Class<? extends Linker> linkerType,
- String partialPath) {
+ Class<? extends Generator> generatorType, String partialPath) {
super(linkerType, partialPath);
+ this.generatorType = generatorType;
+ }
+
+ /**
+ * The type of Generator that created the resource.
+ */
+ public final Class<? extends Generator> getGenerator() {
+ return generatorType;
}
}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/SyntheticArtifact.java b/dev/core/src/com/google/gwt/core/ext/linker/SyntheticArtifact.java
new file mode 100644
index 0000000..5e93e34
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/linker/SyntheticArtifact.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ext.linker;
+
+import com.google.gwt.core.ext.Linker;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * Artifacts created by {@link AbstractLinker}.
+ */
+public class SyntheticArtifact extends EmittedArtifact {
+ private final byte[] data;
+
+ SyntheticArtifact(Class<? extends Linker> linkerType, String partialPath,
+ byte[] data) {
+ super(linkerType, partialPath);
+ assert data != null;
+ this.data = data;
+ }
+
+ @Override
+ public InputStream getContents(TreeLogger logger)
+ throws UnableToCompleteException {
+ return new ByteArrayInputStream(data);
+ }
+}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardGeneratedResource.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardGeneratedResource.java
index 3bd14f3..d520f33 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardGeneratedResource.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardGeneratedResource.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.core.ext.linker.impl;
+import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.GeneratedResource;
@@ -29,8 +30,9 @@
public class StandardGeneratedResource extends GeneratedResource {
private final URL url;
- public StandardGeneratedResource(String partialPath, URL url) {
- super(StandardLinkerContext.class, partialPath);
+ public StandardGeneratedResource(Class<? extends Generator> generatorType,
+ String partialPath, URL url) {
+ super(StandardLinkerContext.class, generatorType, partialPath);
this.url = url;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
index 2cf9cd1..a480c17 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
@@ -21,7 +21,6 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact;
-import com.google.gwt.core.ext.linker.GeneratedResource;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.PublicResource;
import com.google.gwt.core.ext.linker.SelectionProperty;
@@ -55,7 +54,6 @@
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
-import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -102,6 +100,12 @@
private final File compilationsDir;
private final JJSOptions jjsOptions;
private final List<Class<? extends Linker>> linkerClasses;
+ private final Map<Class<? extends Linker>, String> linkerShortNames = new HashMap<Class<? extends Linker>, String>();
+
+ /**
+ * This is the output directory for private files.
+ */
+ private final File moduleAuxDir;
private final String moduleFunctionName;
private final String moduleName;
@@ -136,10 +140,29 @@
compilationsDir.mkdirs();
logger.log(TreeLogger.SPAM, "compilationsDir: "
+ compilationsDir.getPath(), null);
+
+ this.moduleAuxDir = new File(moduleOutDir.getParentFile(), moduleName
+ + "-aux");
+ if (moduleAuxDir.exists()) {
+ Util.recursiveDelete(moduleAuxDir, false);
+ }
+ logger.log(TreeLogger.SPAM, "mouduleAuxDir: " + moduleAuxDir.getPath(),
+ null);
} else {
compilationsDir = null;
+ moduleAuxDir = null;
}
+ for (Map.Entry<String, Class<? extends Linker>> entry : module.getLinkers().entrySet()) {
+ linkerShortNames.put(entry.getValue(), entry.getKey());
+ }
+
+ /*
+ * This will make all private PublicResources and GeneratedResources appear
+ * in the root of the module auxiliary directory.
+ */
+ linkerShortNames.put(this.getClass(), "");
+
// Always return the properties in the same order as a convenience
SortedSet<SelectionProperty> mutableProperties = new TreeSet<SelectionProperty>(
SELECTION_PROPERTY_COMPARATOR);
@@ -164,22 +187,7 @@
logger.log(TreeLogger.SPAM, "Added style " + style, null);
}
- if (generatorDir != null) {
- for (String path : Util.recursiveListPartialPaths(generatorDir, false)) {
- String partialPath = path.replace(File.separatorChar, '/');
- try {
- GeneratedResource resource = new StandardGeneratedResource(
- partialPath, (new File(generatorDir, path)).toURL());
- artifacts.add(resource);
- logger.log(TreeLogger.SPAM, "Added generated resource " + resource,
- null);
- } catch (MalformedURLException e) {
- // This won't happen unless there's a bad partial path from Util
- logger.log(TreeLogger.ERROR,
- "Unable to convert generated resource to URL", e);
- }
- }
- }
+ // Generated files should be passed in via addArtifacts()
for (String path : module.getAllPublicFiles()) {
String partialPath = path.replace(File.separatorChar, '/');
@@ -190,10 +198,25 @@
}
}
+ /**
+ * Adds or replaces Artifacts in the ArtifactSet that will be passed into the
+ * Linkers invoked.
+ */
+ public void addOrReplaceArtifacts(ArtifactSet artifacts) {
+ this.artifacts.removeAll(artifacts);
+ this.artifacts.addAll(artifacts);
+ }
+
+ /**
+ * Returns the ArtifactSet that will passed into the invoke Linkers.
+ */
public ArtifactSet getArtifacts() {
return artifacts;
}
+ /**
+ * Gets or creates a CompilationResult for the given JavaScript program.
+ */
public StandardCompilationResult getCompilation(TreeLogger logger, String js)
throws UnableToCompleteException {
@@ -245,7 +268,14 @@
TreeLogger artifactLogger = logger.branch(TreeLogger.DEBUG,
"Emitting resource " + artifact.getPartialPath(), null);
- File outFile = new File(moduleOutDir, artifact.getPartialPath());
+ File outFile;
+ if (artifact.isPrivate()) {
+ outFile = new File(getLinkerAuxDir(artifact.getLinker()),
+ artifact.getPartialPath());
+ } else {
+ outFile = new File(moduleOutDir, artifact.getPartialPath());
+ }
+
assert !outFile.exists() : "Attempted to overwrite " + outFile.getPath();
Util.copy(logger, artifact.getContents(artifactLogger), outFile);
}
@@ -310,6 +340,24 @@
}
/**
+ * Creates a linker-specific subdirectory in the module's auxiliary output
+ * directory.
+ */
+ private File getLinkerAuxDir(Class<? extends Linker> linkerType) {
+ // The auxiliary directory is create lazily
+ if (!moduleAuxDir.exists()) {
+ moduleAuxDir.mkdirs();
+ }
+ assert linkerShortNames.containsKey(linkerType) : linkerType.getName()
+ + " unknown";
+ File toReturn = new File(moduleAuxDir, linkerShortNames.get(linkerType));
+ if (!toReturn.exists()) {
+ toReturn.mkdirs();
+ }
+ return toReturn;
+ }
+
+ /**
* Run the linker stack.
*/
private ArtifactSet invokeLinkerStack(TreeLogger logger)
diff --git a/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java b/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java
deleted file mode 100644
index 89836fe..0000000
--- a/dev/core/src/com/google/gwt/core/linker/NoDeployResourcesLinker.java
+++ /dev/null
@@ -1,54 +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.core.linker;
-
-import com.google.gwt.core.ext.Linker;
-import com.google.gwt.core.ext.LinkerContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.core.ext.linker.GeneratedResource;
-import com.google.gwt.core.ext.linker.LinkerOrder;
-import com.google.gwt.core.ext.linker.LinkerOrder.Order;
-
-/**
- * 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);
-
- 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/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index e431b83..a83801e 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.TreeLogger.Type;
+import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.impl.StandardCompilationResult;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
@@ -120,9 +121,9 @@
private final Map<String, String> cache = new HashMap<String, String>();
- public CompilationRebindOracle() {
+ public CompilationRebindOracle(ArtifactSet generatorArtifacts) {
super(typeOracle, propOracle, module, rules, genDir,
- generatorResourcesDir, cacheManager);
+ generatorResourcesDir, cacheManager, generatorArtifacts);
}
/**
@@ -175,21 +176,25 @@
private class DistillerRebindPermutationOracle implements
RebindPermutationOracle {
- private final StandardRebindOracle rebindOracle = new StandardRebindOracle(
- typeOracle, propOracle, module, rules, genDir, generatorResourcesDir,
- cacheManager) {
+ private final StandardRebindOracle rebindOracle;
- /**
- * Record generated types.
- */
- @Override
- protected void onGeneratedTypes(String result, JClassType[] genTypes) {
- List<JClassType> list = new ArrayList<JClassType>();
- Util.addAll(list, genTypes);
- Object existing = generatedTypesByResultTypeName.put(result, list);
- assert (existing == null) : "Internal error: redundant notification of generated types";
- }
- };
+ public DistillerRebindPermutationOracle(ArtifactSet generatorArtifacts) {
+ rebindOracle = new StandardRebindOracle(typeOracle, propOracle, module,
+ rules, genDir, generatorResourcesDir, cacheManager,
+ generatorArtifacts) {
+
+ /**
+ * Record generated types.
+ */
+ @Override
+ protected void onGeneratedTypes(String result, JClassType[] genTypes) {
+ List<JClassType> list = new ArrayList<JClassType>();
+ Util.addAll(list, genTypes);
+ Object existing = generatedTypesByResultTypeName.put(result, list);
+ assert (existing == null) : "Internal error: redundant notification of generated types";
+ }
+ };
+ }
public String[] getAllPossibleRebindAnswers(TreeLogger logger,
String requestTypeName) throws UnableToCompleteException {
@@ -382,7 +387,9 @@
// Use the real entry points.
declEntryPts = module.getEntryPointTypeNames();
}
- rebindPermOracle = new DistillerRebindPermutationOracle();
+
+ ArtifactSet generatorArtifacts = new ArtifactSet();
+ rebindPermOracle = new DistillerRebindPermutationOracle(generatorArtifacts);
properties = module.getProperties();
perms = new PropertyPermutations(properties);
WebModeCompilerFrontEnd frontEnd = new WebModeCompilerFrontEnd(
@@ -392,7 +399,7 @@
StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
module, outDir, generatorResourcesDir, jjsOptions);
- compilePermutations(logger, linkerContext);
+ compilePermutations(logger, linkerContext, generatorArtifacts);
if (jjsOptions.isValidateOnly()) {
logger.log(TreeLogger.INFO, "Validation succeeded", null);
@@ -400,7 +407,7 @@
}
logger.log(TreeLogger.INFO, "Compilation succeeded", null);
-
+ linkerContext.addOrReplaceArtifacts(generatorArtifacts);
linkerContext.link(logger, linkerContext, null);
}
@@ -468,7 +475,8 @@
}
private void compilePermutations(TreeLogger logger,
- StandardLinkerContext linkerContext) throws UnableToCompleteException {
+ StandardLinkerContext linkerContext, ArtifactSet generatedArtifacts)
+ throws UnableToCompleteException {
logger = logger.branch(TreeLogger.DEBUG, "Compiling permutations", null);
Property[] orderedProps = perms.getOrderedProperties();
int permNumber = 1;
@@ -476,7 +484,7 @@
String[] orderedPropValues = iter.next();
String js = realizePermutation(logger, orderedProps, orderedPropValues,
- permNumber);
+ permNumber, generatedArtifacts);
// This is the case in validateOnly mode, which doesn't produce output
if (js == null) {
@@ -523,7 +531,8 @@
* </ul>
*/
private String realizePermutation(TreeLogger logger, Property[] currentProps,
- String[] currentValues, int permNumber) throws UnableToCompleteException {
+ String[] currentValues, int permNumber, ArtifactSet generatorArtifacts)
+ throws UnableToCompleteException {
String msg = "Analyzing permutation #" + permNumber;
logger = logger.branch(TreeLogger.TRACE, msg, null);
@@ -532,7 +541,8 @@
// Create a rebind oracle that will record decisions so that we can cache
// them and avoid future computations.
//
- CompilationRebindOracle rebindOracle = new CompilationRebindOracle();
+ CompilationRebindOracle rebindOracle = new CompilationRebindOracle(
+ generatorArtifacts);
// Tell the property provider above about the current property values.
// Note that the rebindOracle is actually sensitive to these values because
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 ce9b8a1..e716af6 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -42,6 +42,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -102,7 +103,7 @@
private TypeOracle lazyTypeOracle;
- private final Map<String, Class<? extends Linker>> linkersTypesByName = new HashMap<String, Class<? extends Linker>>();
+ private final Map<String, Class<? extends Linker>> linkerTypesByName = new LinkedHashMap<String, Class<? extends Linker>>();
private final long moduleDefCreationTime = System.currentTimeMillis();
@@ -219,7 +220,7 @@
}
public void defineLinker(String name, Class<? extends Linker> linker) {
- linkersTypesByName.put(name, linker);
+ linkerTypesByName.put(name, linker);
}
public synchronized URL findPublicFile(String partialPath) {
@@ -285,7 +286,11 @@
}
public Class<? extends Linker> getLinker(String name) {
- return linkersTypesByName.get(name);
+ return linkerTypesByName.get(name);
+ }
+
+ public Map<String, Class<? extends Linker>> getLinkers() {
+ return linkerTypesByName;
}
public synchronized String getName() {
diff --git a/dev/core/src/com/google/gwt/dev/cfg/RuleGenerateWith.java b/dev/core/src/com/google/gwt/dev/cfg/RuleGenerateWith.java
index 83481f0..a221bcb 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/RuleGenerateWith.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/RuleGenerateWith.java
@@ -19,6 +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.shell.StandardGeneratorContext;
/**
* A rule to replace the type being rebound with a class whose name is
@@ -39,6 +40,10 @@
String msg = "Invoking " + toString();
logger = logger.branch(TreeLogger.DEBUG, msg, null);
+ if (context instanceof StandardGeneratorContext) {
+ ((StandardGeneratorContext) context).setCurrentGenerator(generator.getClass());
+ }
+
long before = System.currentTimeMillis();
String className = generator.generate(logger, context, typeName);
long after = System.currentTimeMillis();
diff --git a/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java b/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
index 518223e..109d96a 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
@@ -113,7 +113,7 @@
//
Rules rules = module.getRules();
rebindOracle = new StandardRebindOracle(typeOracle, propOracle, module,
- rules, genDir, shellDir, module.getCacheManager());
+ rules, genDir, shellDir, module.getCacheManager(), null);
// Create a completely isolated class loader which owns all classes
// associated with a particular module. This effectively builds a
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
index f31780a..f8fb4cd 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
@@ -15,10 +15,15 @@
*/
package com.google.gwt.dev.shell;
+import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.Artifact;
+import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.GeneratedResource;
+import com.google.gwt.core.ext.linker.impl.StandardGeneratedResource;
import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
@@ -154,10 +159,14 @@
}
}
+ private final ArtifactSet artifactSet;
+
private final CacheManager cacheManager;
private final Set<GeneratedCompilationUnitProvider> committedGeneratedCups = new HashSet<GeneratedCompilationUnitProvider>();
+ private Class<? extends Generator> currentGenerator;
+
private final File genDir;
private final Set<String> generatedTypeNames = new HashSet<String>();
@@ -180,13 +189,14 @@
*/
public StandardGeneratorContext(TypeOracle typeOracle,
PropertyOracle propOracle, PublicOracle publicOracle, File genDir,
- File outDir, CacheManager cacheManager) {
+ File outDir, CacheManager cacheManager, ArtifactSet artifactSet) {
this.typeOracle = typeOracle;
this.propOracle = propOracle;
this.publicOracle = publicOracle;
this.genDir = genDir;
this.outDir = outDir;
this.cacheManager = cacheManager;
+ this.artifactSet = artifactSet;
}
/**
@@ -204,7 +214,19 @@
}
}
- public void commitResource(TreeLogger logger, OutputStream os)
+ /**
+ * Adds an Artifact to the ArtifactSet if one has been provided to the
+ * context.
+ */
+ public void commitArtifact(TreeLogger logger, Artifact<?> artifact)
+ throws UnableToCompleteException {
+ // The artifactSet will be null in hosted mode, since we never run Linkers
+ if (artifactSet != null) {
+ artifactSet.replace(artifact);
+ }
+ }
+
+ public GeneratedResource commitResource(TreeLogger logger, OutputStream os)
throws UnableToCompleteException {
// Find the pending resource using its output stream as a key.
@@ -214,11 +236,27 @@
pendingResource.commit(logger);
cacheManager.addGeneratedResource(pendingResource.getPartialPath());
- // The resource is now no longer pending, so remove it from the map.
- // If the commit above throws an exception, it's okay to leave the entry
- // in the map because it will be reported later as not having been
- // committed, which is accurate.
- pendingResourcesByOutputStream.remove(os);
+ // Add the GeneratedResource to the ArtifactSet
+ GeneratedResource toReturn;
+ try {
+ toReturn = new StandardGeneratedResource(currentGenerator,
+ pendingResource.getPartialPath(), pendingResource.getFile().toURL());
+ commitArtifact(logger, toReturn);
+
+ /*
+ * The resource is now no longer pending, so remove it from the map. If
+ * the commit above throws an exception, it's okay to leave the entry in
+ * the map because it will be reported later as not having been
+ * committed, which is accurate.
+ */
+ pendingResourcesByOutputStream.remove(os);
+
+ return toReturn;
+ } catch (MalformedURLException e) {
+ // This is very unlikely, since the file already exists
+ logger.log(TreeLogger.ERROR, "Unable to commit artifact", e);
+ throw new UnableToCompleteException();
+ }
} else {
logger.log(TreeLogger.WARN,
"Generator attempted to commit an unknown OutputStream", null);
@@ -320,6 +358,10 @@
return typeOracle;
}
+ public void setCurrentGenerator(Class<? extends Generator> currentGenerator) {
+ this.currentGenerator = currentGenerator;
+ }
+
public final PrintWriter tryCreate(TreeLogger logger, String packageName,
String simpleTypeName) {
String typeName = packageName + "." + simpleTypeName;
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
index fbb237b..554a351 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
@@ -18,12 +18,12 @@
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.cfg.PublicOracle;
import com.google.gwt.dev.cfg.Rule;
import com.google.gwt.dev.cfg.Rules;
-import com.google.gwt.dev.cfg.StaticPropertyOracle;
import com.google.gwt.dev.jdt.CacheManager;
import com.google.gwt.dev.jdt.RebindOracle;
import com.google.gwt.dev.util.Util;
@@ -54,7 +54,7 @@
public Rebinder(TypeOracle typeOracle, PropertyOracle propOracle,
PublicOracle publicOracle) {
genCtx = new StandardGeneratorContext(typeOracle, propOracle,
- publicOracle, genDir, outDir, cacheManager);
+ publicOracle, genDir, outDir, cacheManager, artifactSet);
}
public String rebind(TreeLogger logger, String typeName)
@@ -133,6 +133,8 @@
}
}
+ private final ArtifactSet artifactSet;
+
private final CacheManager cacheManager;
private final File genDir;
@@ -149,7 +151,7 @@
public StandardRebindOracle(TypeOracle typeOracle, PropertyOracle propOracle,
PublicOracle publicOracle, Rules rules, File genDir, File moduleOutDir,
- CacheManager cacheManager) {
+ CacheManager cacheManager, ArtifactSet artifactSet) {
this.typeOracle = typeOracle;
this.propOracle = propOracle;
this.publicOracle = publicOracle;
@@ -161,14 +163,7 @@
} else {
this.cacheManager = new CacheManager(typeOracle);
}
- }
-
- public StandardRebindOracle(TypeOracle typeOracle,
- StaticPropertyOracle propOracle, PublicOracle publicOracle, Rules rules,
- File genDir, File moduleOutDir) {
- // This is a path used for non-hosted mode execution; therefore no caching.
- this(typeOracle, propOracle, publicOracle, rules, genDir, moduleOutDir,
- null);
+ this.artifactSet = artifactSet;
}
public String rebind(TreeLogger logger, String typeName)
diff --git a/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java b/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
index bbfa58b..f88a339 100644
--- a/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
+++ b/dev/core/test/com/google/gwt/dev/shell/StandardGeneratorContextTest.java
@@ -16,9 +16,15 @@
package com.google.gwt.dev.shell;
import com.google.gwt.core.ext.BadPropertyValueException;
+import com.google.gwt.core.ext.Generator;
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.Artifact;
+import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.GeneratedResource;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.cfg.PublicOracle;
import com.google.gwt.dev.jdt.CacheManager;
@@ -42,6 +48,28 @@
*/
public class StandardGeneratorContextTest extends TestCase {
+ private static class MockArtifact extends Artifact<MockArtifact> {
+
+ public MockArtifact() {
+ super(Linker.class);
+ }
+
+ @Override
+ protected int compareToComparableArtifact(MockArtifact o) {
+ return 0;
+ }
+
+ @Override
+ protected Class<MockArtifact> getComparableArtifactType() {
+ return MockArtifact.class;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+ }
+
private static class MockCacheManager extends CacheManager {
}
@@ -57,6 +85,14 @@
}
}
+ private static class MockGenerator extends Generator {
+ @Override
+ public String generate(TreeLogger logger, GeneratorContext context,
+ String typeName) throws UnableToCompleteException {
+ return typeName;
+ }
+ }
+
private static class MockPublicOracle implements PublicOracle {
public URL findPublicFile(String partialPath) {
@@ -93,6 +129,8 @@
private static class MockTypeOracle extends TypeOracle {
}
+ private final ArtifactSet artifactSet = new ArtifactSet();
+
/**
* Stores the File objects to delete in the order they were created. Delete
* them in reverse order.
@@ -112,7 +150,7 @@
tempGenDir = createTempDir("gwt-gen-");
tempOutDir = createTempDir("gwt-out-");
genCtx = new StandardGeneratorContext(mockTypeOracle, mockPropOracle,
- mockPublicOracle, tempGenDir, tempOutDir, mockCacheManager);
+ mockPublicOracle, tempGenDir, tempOutDir, mockCacheManager, artifactSet);
}
public void testTryCreateResource_badFileName() {
@@ -165,9 +203,16 @@
String path = createTempOutFilename();
OutputStream os = genCtx.tryCreateResource(mockLogger, path);
os.write("going to call commit twice after this...".getBytes(Util.DEFAULT_ENCODING));
- genCtx.commitResource(mockLogger, os);
+ genCtx.setCurrentGenerator(MockGenerator.class);
+ GeneratedResource res = genCtx.commitResource(mockLogger, os);
+ assertEquals(path, res.getPartialPath());
+ assertEquals(MockGenerator.class, res.getGenerator());
File createdFile = new File(tempOutDir, path);
assertTrue(createdFile.exists());
+ assertEquals(1, artifactSet.size());
+ GeneratedResource generatedResource = (GeneratedResource) artifactSet.iterator().next();
+ assertEquals(path, generatedResource.getPartialPath());
+ assertEquals(MockGenerator.class, generatedResource.getGenerator());
rememberToDelete(createdFile);
try {
genCtx.commitResource(mockLogger, os);
@@ -175,6 +220,8 @@
} catch (UnableToCompleteException e) {
// Success
}
+ // Didn't change the artifactSet
+ assertEquals(1, artifactSet.size());
}
public void testTryCreateResource_commitNotCalled()
@@ -189,6 +236,7 @@
File wouldBeCreatedFile = new File(tempOutDir, path);
assertFalse(wouldBeCreatedFile.exists());
+ assertEquals(0, artifactSet.size());
}
public void testTryCreateResource_commitWithBadStream() {
@@ -198,6 +246,7 @@
} catch (UnableToCompleteException e) {
// Success
}
+ assertEquals(0, artifactSet.size());
try {
OutputStream os = new ByteArrayOutputStream();
@@ -206,6 +255,7 @@
} catch (UnableToCompleteException e) {
// Success
}
+ assertEquals(0, artifactSet.size());
}
/**
@@ -287,11 +337,13 @@
assertNull(
"tryCreateResource() should return null when the target file is already on the public path",
os);
+ assertEquals(0, artifactSet.size());
}
@Override
protected void setUp() throws Exception {
mockCacheManager.invalidateVolatileFiles();
+ artifactSet.clear();
}
@Override
diff --git a/user/src/com/google/gwt/i18n/client/LocalizableResource.java b/user/src/com/google/gwt/i18n/client/LocalizableResource.java
index 3f111b1..b1791a4 100644
--- a/user/src/com/google/gwt/i18n/client/LocalizableResource.java
+++ b/user/src/com/google/gwt/i18n/client/LocalizableResource.java
@@ -105,12 +105,14 @@
* A platform-specific filename for output. If not present, the file will be
* named based on the fully-qualified name of the annotated interface. File
* names without a slash are given a relative name based on the
- * fully-qualified package name of the annotated interface. Relative pathnames
- * are generated in the directory specified by the "-out" flag to the
- * compiler, or the current directory if not present. Unless exactly one locale
- * is specified for locales (not just only one locale happened to be compiled for),
- * the locale will be appended to the name (such as _default [for the default
- * locale], _en_US, etc) as well as the proper extension for the specified format.
+ * fully-qualified package name of the annotated interface. Relative
+ * pathnames are generated in the auxiliary module directory (moduleName-aux
+ * in the output directory, which is specified by the "-out" flag to the
+ * compiler, or the current directory if not present) -- absolute path names
+ * are not allowed. Unless exactly one locale is specified for locales (not
+ * just only one locale happened to be compiled for), the locale will be
+ * appended to the name (such as _default [for the default locale], _en_US,
+ * etc) as well as the proper extension for the specified format.
*
* Note that if multiple generators are used, they will have the same base
* filename so the extensions must be different.
diff --git a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
index 1af5e11..3b1f1b8 100644
--- a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
@@ -134,7 +134,7 @@
Generate generate = targetClass.getAnnotation(Generate.class);
if (generate != null) {
try {
- String path = "no-deploy" + File.separatorChar + generate.fileName();
+ String path = generate.fileName();
if (Generate.DEFAULT.equals(path)) {
path = targetClass.getPackage().getName() + "."
+ targetClass.getName().replace('.', '_');
@@ -175,7 +175,7 @@
new OutputStreamWriter(outStr, "UTF-8")), false);
msgWriter.write(logger, resource, out, targetClass);
out.flush();
- context.commitResource(logger, outStr);
+ context.commitResource(logger, outStr).setPrivate(true);
}
}
}
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index 47fa350..d79a3da 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -39,7 +39,4 @@
<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/module/client/NoDeployTest.java b/user/test/com/google/gwt/module/client/NoDeployTest.java
index 31a8b96..e67dd78 100644
--- a/user/test/com/google/gwt/module/client/NoDeployTest.java
+++ b/user/test/com/google/gwt/module/client/NoDeployTest.java
@@ -49,7 +49,7 @@
// Try fetching a file that should exist
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
- GWT.getHostPageBaseURL() + "deploy/exists.txt");
+ GWT.getHostPageBaseURL() + "publicFile.txt");
delayTestFinish(500);
builder.sendRequest("", new RequestCallback() {
@@ -74,7 +74,7 @@
// Try fetching a file that shouldn't exist
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
- GWT.getHostPageBaseURL() + "no-deploy/inGenerated.txt");
+ GWT.getHostPageBaseURL() + "privateFile.txt");
delayTestFinish(500);
builder.sendRequest("", new RequestCallback() {
diff --git a/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java b/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
index 0c1bceb..d5b86f1 100644
--- a/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
+++ b/user/test/com/google/gwt/module/rebind/NoDeployGenerator.java
@@ -19,7 +19,6 @@
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.core.linker.NoDeployResourcesLinker;
import com.google.gwt.dev.util.Util;
import com.google.gwt.module.client.NoDeployTest;
@@ -36,9 +35,8 @@
String typeName) throws UnableToCompleteException {
try {
- createFile(logger, context, "deploy/exists.txt");
- createFile(logger, context, NoDeployResourcesLinker.PREFIX
- + "inGenerated.txt");
+ createFile(logger, context, "publicFile.txt", false);
+ createFile(logger, context, "privateFile.txt", true);
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to create test file", e);
throw new UnableToCompleteException();
@@ -48,7 +46,8 @@
}
private void createFile(TreeLogger logger, GeneratorContext context,
- String path) throws UnableToCompleteException, IOException {
+ String path, boolean isPrivate) throws UnableToCompleteException,
+ IOException {
OutputStream out = context.tryCreateResource(logger, path);
if (out == null) {
@@ -56,6 +55,6 @@
}
out.write(Util.getBytes(NoDeployTest.TEST_TEXT));
- context.commitResource(logger, out);
+ context.commitResource(logger, out).setPrivate(isPrivate);
}
}