This change is mostly resources related. We pre-split path of resources and avoid performing String.split() several times later. This gives about 5% speed up in GWT Designer. Review at http://gwt-code-reviews.appspot.com/1382801 Review by: conroy@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9867 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java b/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java index 7cec82a..cb2384a 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java
@@ -53,29 +53,29 @@ public boolean allows(String path) { return defaultAntIncludes.allows(path) && matches(path); } - }; - + }; + private final ResourceFilter defaultFilter = new ResourceFilter() { public boolean allows(String path) { return getFileTypeFilter().allows(path) - && !defaultExcludesPattern.matcher(path).matches(); + && !isDefaultExcluded(path); } }; - + private FilterFileType(String suffix) { this.suffix = suffix; } - + public ResourceFilter getDefaultFilter() { return defaultFilter; } - + /* used when defaultExcludes is false */ public ResourceFilter getFileTypeFilter() { return justThisFileTypeFilter; } - + public String getSuffix() { return suffix; } @@ -87,36 +87,10 @@ return path.endsWith(suffix); } } - - /* - * list copied from {@link org.apache.tools.ant.DirectoryScanner} - */ - private static final String DEFAULT_EXCLUDES[] = new String[]{ - // Miscellaneous typical temporary files - "**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*", - - // CVS - "**/CVS", "**/CVS/**", - // to not hit the weird formatting error. - "**/.cvsignore", - - // SCCS - "**/SCCS", "**/SCCS/**", - - // Visual SourceSafe - "**/vssver.scc", - - // Subversion - "**/.svn", "**/.svn/**", - - // Mac - "**/.DS_Store",}; // \w (word character), ., $, /, -, *, ~, #, % private static final Pattern antPattern = Pattern.compile("^[\\w\\.\\$/\\-\\*~#%]*$"); - private static final Pattern defaultExcludesPattern = getPatternFromAntStrings(DEFAULT_EXCLUDES); - // accepts all but paths starting with '/'. Default include list is '**' private static final ResourceFilter defaultAntIncludes = new ResourceFilter() { public boolean allows(String path) { @@ -125,6 +99,40 @@ }; /** + * @return <code>true</code> if given path should be excluded from resources. + */ + private static boolean isDefaultExcluded(String path) { + // CVS + if (path.endsWith("/CVS") || path.contains("/CVS/") || path.startsWith("CVS/") + || path.endsWith("/.cvsignore")) { + return true; + } + // Subversion + if (path.endsWith("/.svn") || path.contains("/.svn/") || path.startsWith(".svn/") + || path.endsWith("/.svnignore")) { + return true; + } + // Git + if (path.endsWith("/.git") || path.contains("/.git/") || path.startsWith(".git/") + || path.endsWith("/.gitignore")) { + return true; + } + // SCCS + if (path.endsWith("/SCCS") || path.contains("/SCCS/")) { + return true; + } + // Visual SourceSafe + if (path.endsWith("/vssver.scc")) { + return true; + } + // Mac + if (path.endsWith("/.DS_Store")) { + return true; + } + return false; + } + + /** * Returns a pattern string that can be passed in Java Pattern.compile(..). * For spec, see <a href="http://www.jajakarta.org/ant/ant-1.6.1/docs/ja/manual/api/org/apache/tools/ant/DirectoryScanner.html" * >DirectoryScanner</a> From the spec: There is a special case regarding the @@ -254,20 +262,6 @@ } return answer; } - - private static Pattern getPatternFromAntStrings(String... antPatterns) { - String patternStrings[] = new String[antPatterns.length]; - int count = 0; - for (String antPatternString : antPatterns) { - String patternString = getPatternFromAntPattern(antPatternString); - if (patternString == null) { - throw new RuntimeException("Unable to convert " + antPatternString - + " to java code"); - } - patternStrings[count++] = patternString; - } - return getPatternFromStrings(patternStrings); - } private static Pattern getPatternFromStrings(String... patterns) { StringBuffer entirePattern = new StringBuffer("^"); @@ -310,7 +304,7 @@ return getCustomFilter(includeList, excludeList, skipList, defaultExcludes, caseSensitive, FilterFileType.RESOURCE_FILES); } - + /** * Return a customResourceFiter that handles all the argument. If unable to * create a customResourceFilter that handles the arguments, catchAll is used @@ -349,7 +343,7 @@ return false; } if (defaultExcludes) { - return !defaultExcludesPattern.matcher(path).matches(); + return !isDefaultExcluded(path); } return true; }
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java index a1270ef..fe70e94 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
@@ -220,6 +220,14 @@ * match or the most specific prefix excludes the resource. */ public PathPrefix includesResource(String resourceAbstractPathName) { + String[] parts = resourceAbstractPathName.split("/"); + return includesResource(resourceAbstractPathName, parts); + } + + /** + * Implementation of {@link #includesDirectory(String)}. + */ + public PathPrefix includesResource(String resourceAbstractPathName, String[] parts) { /* * Algorithm: dive down the package hierarchy looking for the most specific * package that applies to this resource. The filter of the most specific @@ -234,7 +242,7 @@ PathPrefix mostSpecificPrefix = rootTrieNode.getPathPrefix(); // Walk all but the last path part, which is assumed to be a file name. - for (String part : resourceAbstractPathName.split("/")) { + for (String part : parts) { assert (!"".equals(part)); TrieNode childNode = currentNode.findChild(part); if (childNode != null) {
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 be2fc8f..67ddd50 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
@@ -28,7 +28,6 @@ import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; -import java.util.zip.ZipException; import java.util.zip.ZipFile; /** @@ -78,7 +77,7 @@ private final ZipFile zipFile; - public ZipFileClassPathEntry(File zipFile) throws ZipException, IOException { + public ZipFileClassPathEntry(File zipFile) throws IOException { assert zipFile.isAbsolute(); this.zipFile = new ZipFile(zipFile); this.location = zipFile.toURI().toString(); @@ -147,8 +146,9 @@ Map<AbstractResource, PathPrefix> results = new IdentityHashMap<AbstractResource, PathPrefix>(); for (ZipFileResource r : allZipFileResources) { String path = r.getPath(); + String[] pathParts = r.getPathParts(); PathPrefix prefix = null; - if ((prefix = pathPrefixSet.includesResource(path)) != null) { + if ((prefix = pathPrefixSet.includesResource(path, pathParts)) != null) { Messages.INCLUDING_RESOURCE.log(logger, path, null); results.put(r, prefix); } else {
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java index e899f0e..2f659b0 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.resource.impl; import com.google.gwt.dev.util.StringInterner; +import com.google.gwt.dev.util.Strings; import java.io.IOException; import java.io.InputStream; @@ -28,12 +29,13 @@ private final ZipFileClassPathEntry classPathEntry; private final String path; + private final String[] pathParts; private long lastModified; - public ZipFileResource(ZipFileClassPathEntry classPathEntry, String path, - long lastModified) { + public ZipFileResource(ZipFileClassPathEntry classPathEntry, String path, long lastModified) { this.classPathEntry = classPathEntry; this.path = StringInterner.get().intern(path); + this.pathParts = Strings.splitPath(path); this.lastModified = lastModified; } @@ -59,6 +61,13 @@ return path; } + /** + * @return components of {@link #getPath()}. + */ + public String[] getPathParts() { + return pathParts; + } + @Override public InputStream openContents() { try {
diff --git a/dev/core/src/com/google/gwt/dev/util/Strings.java b/dev/core/src/com/google/gwt/dev/util/Strings.java index 625102a..322d497 100644 --- a/dev/core/src/com/google/gwt/dev/util/Strings.java +++ b/dev/core/src/com/google/gwt/dev/util/Strings.java
@@ -15,23 +15,47 @@ */ package com.google.gwt.dev.util; +import com.google.gwt.thirdparty.guava.common.collect.Lists; + +import java.util.ArrayList; + /** * String manipulation utilities. */ public class Strings { + /** - * Join strings inserting separator between them. + * Join strings inserting separator between them. */ public static String join(String[] strings, String separator) { StringBuffer result = new StringBuffer(); - + for (String s : strings) { if (result.length() != 0) { result.append(separator); } result.append(s); } - + return result.toString(); } + + /** + * @return the path components, result of splitting by "/". + */ + public static String[] splitPath(String path) { + ArrayList<String> result = Lists.newArrayList(); + int length = path.length(); + int begin = 0; + for (int i = 0; i < length; i++) { + if (path.charAt(i) == '/') { + result.add(path.substring(begin, i)); + begin = i + 1; + } + } + if (begin < length) { + result.add(path.substring(begin)); + } + return result.toArray(new String[result.size()]); + } }
diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java index e592c6e..3509223 100644 --- a/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java +++ b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java
@@ -111,9 +111,9 @@ static class BasicPaths { String baseIncluded[] = { - "foo", "/foo", "foo/bar", "/foo/bar", "/foo/bar", "/foo$/$", "/foo-_", - "123FOO123", "cvs", "cvs/cvs/svn", ".foo_bar$", "foo/asvn"}; - String baseExcluded[] = {"foo/CVS/bar", "foo/.svn/bar", "foo/SCCS/bar",}; + "foo", "/foo", "foo/bar", "/foo/bar", "/foo/bar", "/foo$/$", "/foo-_", "123FOO123", "cvs", + "cvs/cvs/svn", ".foo_bar$", "foo/asvn"}; + String baseExcluded[] = {"foo/CVS/bar", "CVS/bar", "foo/.svn/bar", ".svn/bar", "foo/SCCS/bar",}; String baseSuffixExcluded[] = { "foo/.cvsignore", "foo/CVS", "foo/.svn", "foo/SCCS", "foo/bar/vssver.scc", "/foo/bar/.DS_Store"};
diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/ResourceTests.java b/dev/core/test/com/google/gwt/dev/resource/impl/ResourceTests.java new file mode 100644 index 0000000..4ed79e8 --- /dev/null +++ b/dev/core/test/com/google/gwt/dev/resource/impl/ResourceTests.java
@@ -0,0 +1,40 @@ +/* + * Copyright 2011 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.resource.impl; + +import com.google.gwt.dev.resource.Resource; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Suite of {@link Resource} related tests. + */ +public class ResourceTests { + public static Test suite() { + TestSuite suite = new TestSuite("Resource tests"); + suite.addTestSuite(ClassPathEntryTest.class); + suite.addTestSuite(DefaultFiltersTest.class); + suite.addTestSuite(FileResourceTest.class); + suite.addTestSuite(PathPrefixSetTest.class); + suite.addTestSuite(ResourceOracleImplRealClasspathTest.class); + suite.addTestSuite(ResourceOracleImplTest.class); + return suite; + } + + private ResourceTests() { + } +}
diff --git a/dev/core/test/com/google/gwt/dev/util/StringsTest.java b/dev/core/test/com/google/gwt/dev/util/StringsTest.java new file mode 100644 index 0000000..b505daf --- /dev/null +++ b/dev/core/test/com/google/gwt/dev/util/StringsTest.java
@@ -0,0 +1,34 @@ +/* + * Copyright 2011 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.util; + +import junit.framework.TestCase; + +import java.util.Arrays; + +/** + * Tests for {@link Strings}. + */ +public class StringsTest extends TestCase { + /** + * Test for {@link Strings#splitPath(String)}. + */ + public void test_splitPath() throws Exception { + assertTrue(Arrays.equals(new String[]{"a"}, Strings.splitPath("a"))); + assertTrue(Arrays.equals(new String[]{"a", "bb", "ccc"}, Strings.splitPath("a/bb/ccc"))); + assertTrue(Arrays.equals(new String[]{"", "a", "bb"}, Strings.splitPath("/a/bb/"))); + } +}
diff --git a/eclipse/samples/Hello/Hello-compModule.launch b/eclipse/samples/Hello/Hello-compModule.launch index 48d2178..f88c3ae 100644 --- a/eclipse/samples/Hello/Hello-compModule.launch +++ b/eclipse/samples/Hello/Hello-compModule.launch
@@ -1,23 +1,23 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> -<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> -<listEntry value="/Hello"/> -</listAttribute> -<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> -<listEntry value="4"/> -</listAttribute> -<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> -<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER" javaProject="Hello" path="1" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/Hello/core/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-user/core/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-user/core/super" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-dev/core/super" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="Hello"/> </runtimeClasspathEntry> "/> -</listAttribute> -<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> -<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.CompileModule"/> -<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="com.google.gwt.sample.hello.Hello"/> -<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Hello"/> -<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Xmx512M -Dgwt.devjar=${gwt_devjar} -Dgwt.speedtracerlog=log.html"/> -</launchConfiguration> +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/Hello"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER" javaProject="Hello" path="1" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/Hello/core/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-user/core/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-user/core/super" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/gwt-dev/core/super" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="Hello"/> </runtimeClasspathEntry> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.CompileModule"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="com.google.gwt.sample.hello.Hello"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Hello"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Xmx512M -Dgwt.devjar=${gwt_devjar} -Dgwt.speedtracerlog=log.html"/> +</launchConfiguration>