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); } }