This patch fixes the caching logic so that Gwt no longer re-reads and re-processes all jars on the classpath on every refresh. Patch by: amitmanjhi Review by: jat (desk review) git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4830 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java index f7a0420..96f37c9 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
@@ -20,6 +20,7 @@ import java.io.File; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Map; @@ -52,11 +53,21 @@ TreeLogger.DEBUG, "$0"); } + private static class ZipFileSnapshot { + private final int prefixSetSize; + private final Map<AbstractResource, PathPrefix> cachedAnswers; + + ZipFileSnapshot(int prefixSetSize, + Map<AbstractResource, PathPrefix> cachedAnswers) { + this.prefixSetSize = prefixSetSize; + this.cachedAnswers = cachedAnswers; + } + } + private Set<ZipFileResource> allZipFileResources; - private Map<AbstractResource, PathPrefix> cachedAnswers; + private final Map<PathPrefixSet, ZipFileSnapshot> cachedSnapshots = new HashMap<PathPrefixSet, ZipFileSnapshot>( + 2); // currently gwt has just 2 ResourceOracles. private String cachedLocation; - private PathPrefixSet lastPrefixSet; - private int lastPrefixSetSize; private final ZipFile zipFile; public ZipFileClassPathEntry(ZipFile zipFile) { @@ -74,13 +85,13 @@ allZipFileResources = buildIndex(logger); } - if (cachedAnswers == null || lastPrefixSet != pathPrefixSet - || lastPrefixSetSize != pathPrefixSet.getSize()) { - cachedAnswers = computeApplicableResources(logger, pathPrefixSet); - lastPrefixSet = pathPrefixSet; - lastPrefixSetSize = pathPrefixSet.getSize(); + ZipFileSnapshot snapshot = cachedSnapshots.get(pathPrefixSet); + if (snapshot == null || snapshot.prefixSetSize != pathPrefixSet.getSize()) { + snapshot = new ZipFileSnapshot(pathPrefixSet.getSize(), + computeApplicableResources(logger, pathPrefixSet)); + cachedSnapshots.put(pathPrefixSet, snapshot); } - return cachedAnswers; + return snapshot.cachedAnswers; } @Override
diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java b/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java index 560ed05..788449a 100644 --- a/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java +++ b/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java
@@ -15,6 +15,10 @@ */ package com.google.gwt.dev.resource.impl; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.dev.resource.Resource; +import com.google.gwt.util.tools.Utility; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -28,10 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Set; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.dev.resource.Resource; -import com.google.gwt.util.tools.Utility; +import java.util.jar.JarFile; /** * Tests {@link ResourceOracleImpl}. @@ -131,6 +132,37 @@ } } + public void testCachingOfJarResources() throws IOException, + URISyntaxException { + TreeLogger logger = createTestTreeLogger(); + ClassPathEntry cpe1jar = new ZipFileClassPathEntry(new JarFile( + findJarFile("com/google/gwt/dev/resource/impl/testdata/cpe1.jar"))); + + // test basic caching + PathPrefixSet pps1 = new PathPrefixSet(); + pps1.add(new PathPrefix("com/google/gwt", null, false)); + Map<AbstractResource, PathPrefix> resourceMap1 = cpe1jar.findApplicableResources( + logger, pps1); + assertSame(resourceMap1, cpe1jar.findApplicableResources(logger, pps1)); + + // test that cache is invalidated if PathPrefixSet is modified. + pps1.add(new PathPrefix("com/google/gwt/user", null, false)); + Map<AbstractResource, PathPrefix> resourceMap2 = cpe1jar.findApplicableResources( + logger, pps1); + assertNotSame(resourceMap1, resourceMap2); + + PathPrefixSet pps2 = new PathPrefixSet(); + pps2.add(new PathPrefix("org/example/bar", null, false)); + Map<AbstractResource, PathPrefix> resourceMap3 = cpe1jar.findApplicableResources( + logger, pps2); + // check that the entry did go in the cache + assertSame(resourceMap3, cpe1jar.findApplicableResources(logger, pps2)); + + // check that the cache does not thrash + assertSame(resourceMap2, cpe1jar.findApplicableResources(logger, pps1)); + assertSame(resourceMap3, cpe1jar.findApplicableResources(logger, pps2)); + } + /** * Test that ResourceOracleImpl preserves the order in which the same logical * resource is occurs in multiple ClassPathEntries.