diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java index 5a819cd2f7b..2d4cdbb3bf6 100644 --- a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java +++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java @@ -639,7 +639,7 @@ private static class InputSummary { private final ImmutableMap bindingProperties; private final long moduleLastModified; private final long resourcesLastModified; - private final long filenameHash; + private final String filenameHash; InputSummary(Map bindingProperties, ModuleDef module) { this.bindingProperties = ImmutableMap.copyOf(bindingProperties); @@ -655,7 +655,7 @@ public boolean equals(Object obj) { return bindingProperties.equals(other.bindingProperties) && moduleLastModified == other.moduleLastModified && resourcesLastModified == other.resourcesLastModified && - filenameHash == other.filenameHash; + filenameHash.equals(other.filenameHash); } return false; } diff --git a/dev/codeserver/javatests/com/google/gwt/dev/codeserver/SourceHandlerTest.java b/dev/codeserver/javatests/com/google/gwt/dev/codeserver/SourceHandlerTest.java index e1adff4dcb8..1972c264237 100644 --- a/dev/codeserver/javatests/com/google/gwt/dev/codeserver/SourceHandlerTest.java +++ b/dev/codeserver/javatests/com/google/gwt/dev/codeserver/SourceHandlerTest.java @@ -15,16 +15,19 @@ */ package com.google.gwt.dev.codeserver; -import com.google.gwt.dev.util.Util; - +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import junit.framework.TestCase; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + /** * Tests for {@link SourceHandler} */ public class SourceHandlerTest extends TestCase { - private static final String VALID_STRONG_NAME = Util.computeStrongName("foo-bar".getBytes()); + private static final String VALID_STRONG_NAME = Hashing.murmur3_128() + .hashString("foo-bar", StandardCharsets.UTF_8).toString().toUpperCase(Locale.ROOT); public void testIsSourceMapRequest() { checkSourceMapRequest("/sourcemaps/myModule/"); 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 9c004662a2d..6a1e29e588b 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 @@ -19,9 +19,11 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.dev.util.Util; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.util.Locale; /** * Provides basic functions common to all Linker implementations. @@ -132,7 +134,8 @@ protected final SyntheticArtifact emitString(TreeLogger logger, String what, protected final SyntheticArtifact emitWithStrongName(TreeLogger logger, byte[] what, String prefix, String suffix) throws UnableToCompleteException { - String strongName = prefix + Util.computeStrongName(what) + suffix; + String hash = Hashing.murmur3_128().hashBytes(what).toString().toUpperCase(Locale.ROOT); + String strongName = prefix + hash + suffix; return emitBytes(logger, what, strongName); } @@ -152,7 +155,8 @@ protected final SyntheticArtifact emitWithStrongName(TreeLogger logger, protected final SyntheticArtifact emitWithStrongName(TreeLogger logger, byte[] what, String prefix, String suffix, long lastModified) throws UnableToCompleteException { - String strongName = prefix + Util.computeStrongName(what) + suffix; + String hash = Hashing.murmur3_128().hashBytes(what).toString().toUpperCase(Locale.ROOT); + String strongName = prefix + hash + suffix; return emitBytes(logger, what, strongName, lastModified); } } diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCacheManager.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCacheManager.java index 752cef704c7..8f4be720486 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCacheManager.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCacheManager.java @@ -19,11 +19,10 @@ import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; import com.google.gwt.thirdparty.guava.common.cache.Cache; import com.google.gwt.thirdparty.guava.common.cache.CacheBuilder; -import com.google.gwt.thirdparty.guava.common.io.Closeables; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import com.google.gwt.thirdparty.guava.common.util.concurrent.Futures; import com.google.gwt.thirdparty.guava.common.util.concurrent.MoreExecutors; -import com.google.gwt.util.tools.shared.Md5Utils; -import com.google.gwt.util.tools.shared.StringUtils; +import com.google.gwt.thirdparty.guava.common.io.Closeables; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -33,6 +32,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.nio.charset.StandardCharsets; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; @@ -270,22 +270,26 @@ private String computeMinimalRebuildCacheName(String moduleName, String currentWorkingDirectory = System.getProperty("user.dir"); String compilerVersionHash = CompilerVersion.getHash(); String permutationDescriptionString = permutationDescription.toString(); - String optionsDescriptionString = " Options ["; + StringBuilder optionsDescriptionString = new StringBuilder(" Options ["); String separator = ""; - for (Map.Entry entry : options.entrySet()) { - optionsDescriptionString += - String.format("%s%s = %s", separator, entry.getKey(), entry.getValue()); + for (Map.Entry entry : options.entrySet()) { + optionsDescriptionString.append(String.format("%s%s = %s", separator, entry.getKey(), entry.getValue())); separator = ","; } - optionsDescriptionString += "]"; + optionsDescriptionString.append("]"); - String consistentHash = StringUtils.toHexString(Md5Utils.getMd5Digest(( - compilerVersionHash - + moduleName - + currentWorkingDirectory - + permutationDescriptionString - + optionsDescriptionString) - .getBytes())); + String consistentHash = Hashing.murmur3_128().newHasher() + // Compiler hash is constant length, no need to write length + .putString(compilerVersionHash, StandardCharsets.UTF_8) + .putInt(moduleName.length()) + .putString(moduleName, StandardCharsets.UTF_8) + .putInt(currentWorkingDirectory.length()) + .putString(currentWorkingDirectory, StandardCharsets.UTF_8) + // permutationDescriptionString has start/end delimiter + .putString(permutationDescriptionString, StandardCharsets.UTF_8) + // optionsDescriptionString has start/end delimiter + .putString(optionsDescriptionString, StandardCharsets.UTF_8) + .hash().toString(); return REBUILD_CACHE_PREFIX + "-" + consistentHash; } 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 ff68743b463..b48dfbeba3d 100644 --- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java +++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java @@ -37,17 +37,17 @@ import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event; -import com.google.gwt.thirdparty.guava.common.base.Charsets; import com.google.gwt.thirdparty.guava.common.base.Predicates; import com.google.gwt.thirdparty.guava.common.collect.ImmutableList; import com.google.gwt.thirdparty.guava.common.collect.Iterators; import com.google.gwt.thirdparty.guava.common.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Maps; import com.google.gwt.thirdparty.guava.common.collect.Sets; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.File; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -455,31 +455,24 @@ public String getGwtXmlFilePath(String moduleName) { * For example, consider a glob that matches fewer files than before because a file was * deleted. */ - public int getInputFilenameHash() { - List filenames = new ArrayList(); - - filenames.addAll(gwtXmlPathByModuleName.values()); + public String getInputFilenameHash() { + List filenames = new ArrayList<>(gwtXmlPathByModuleName.values()); for (Resource resource : getResourcesNewerThan(Integer.MIN_VALUE)) { filenames.add(resource.getLocation()); } - // Take the first four bytes of the SHA-1 hash. + // Take the first eight bytes of the murmur3 hash. Collections.sort(filenames); - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("SHA-1 unavailable", e); - } + Hasher hasher = Hashing.murmur3_128().newHasher(); + hasher.putInt(filenames.size()); for (String filename : filenames) { - digest.update(filename.getBytes(Charsets.UTF_8)); + hasher.putInt(filename.length()); + hasher.putString(filename, StandardCharsets.UTF_8); } - byte[] bytes = digest.digest(); - - return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; + return hasher.hash().toString(); } public Class getLinker(String name) { diff --git a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java index a70120930ba..558bf28638e 100644 --- a/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java +++ b/dev/core/src/com/google/gwt/dev/javac/BytecodeSignatureMaker.java @@ -15,7 +15,7 @@ */ package com.google.gwt.dev.javac; -import com.google.gwt.dev.util.Util; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; @@ -24,6 +24,7 @@ import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Opcodes; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -60,7 +61,7 @@ public CompileDependencyVisitor() { } public String getSignature() { - return Util.computeStrongName(Util.getBytes(getRawString())); + return Hashing.murmur3_128().hashString(getRawString(), StandardCharsets.UTF_8).toString(); } @Override @@ -203,7 +204,7 @@ private String getRawString() { * methods in a class. * * @param byteCode byte code for class to analyze. - * @return a hex string representing an MD5 digest. + * @return a hex string representing a murmur3 hash. */ public static String getCompileDependencySignature(byte[] byteCode) { CompileDependencyVisitor v = visitCompileDependenciesInBytecode(byteCode); diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java index 39f07d06776..af8bb482207 100644 --- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java +++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java @@ -27,7 +27,6 @@ import com.google.gwt.dev.js.ast.JsRootScope; import com.google.gwt.dev.resource.Resource; import com.google.gwt.dev.util.StringInterner; -import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.DevModeEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; @@ -39,6 +38,10 @@ import com.google.gwt.thirdparty.guava.common.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Maps; import com.google.gwt.thirdparty.guava.common.collect.Sets; +import com.google.gwt.thirdparty.guava.common.hash.Funnels; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.io.ByteStreams; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; @@ -48,13 +51,13 @@ import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -553,23 +556,21 @@ private boolean verifyContentId(TreeLogger logger, Resource resource, Compilatio } private ContentId getResourceContentId(Resource resource) { - ByteArrayOutputStream out = new ByteArrayOutputStream(1024); - try { - InputStream in = resource.openContents(); - /** + try (InputStream in = resource.openContents()) { + /* * In most cases openContents() will throw an exception, however in the case of a * ZipFileResource it might return null causing an NPE in Util.copyNoClose(), see issue 4359. */ if (in == null) { throw new RuntimeException("Unexpected error reading resource '" + resource + "'"); } - // TODO: deprecate com.google.gwt.dev.util.Util and use Guava. - Util.copy(in, out); + Hasher hasher = Hashing.murmur3_128().newHasher(); + ByteStreams.copy(in, Funnels.asOutputStream(hasher)); + String hash = hasher.hash().toString().toUpperCase(Locale.ROOT); + return new ContentId(Shared.getTypeName(resource), hash); } catch (IOException e) { throw new RuntimeException("Unexpected error reading resource '" + resource + "'", e); } - byte[] content = out.toByteArray(); - return new ContentId(Shared.getTypeName(resource), Util.computeStrongName(content)); } /** diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitBuilder.java index 61d4fc1abaf..5e9a49d21f6 100644 --- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitBuilder.java +++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitBuilder.java @@ -18,6 +18,8 @@ import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.resource.Resource; import com.google.gwt.dev.util.Util; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.hash.HashingOutputStream; import org.eclipse.jdt.core.compiler.CategorizedProblem; @@ -26,6 +28,7 @@ import java.io.InputStream; import java.util.Collection; import java.util.List; +import java.util.Locale; /** * Builds a {@link CompilationUnit}. @@ -135,9 +138,10 @@ protected String doGetSource() { */ lastModifed = resource.getLastModified(); ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + HashingOutputStream hasher = new HashingOutputStream(Hashing.murmur3_128(), out); try { InputStream in = resource.openContents(); - /** + /* * In most cases openContents() will throw an exception, however in the case of a * ZipFileResource it might return null causing an NPE in Util.copyNoClose(), * see issue 4359. @@ -145,12 +149,12 @@ protected String doGetSource() { if (in == null) { throw new RuntimeException("Unexpected error reading resource '" + resource + "'"); } - Util.copy(in, out); + Util.copy(in, hasher); } catch (IOException e) { throw new RuntimeException("Unexpected error reading resource '" + resource + "'", e); } byte[] content = out.toByteArray(); - contentId = new ContentId(getTypeName(), Util.computeStrongName(content)); + contentId = new ContentId(getTypeName(), hasher.hash().toString().toUpperCase(Locale.ROOT)); return Util.toString(content); } diff --git a/dev/core/src/com/google/gwt/dev/javac/ContentId.java b/dev/core/src/com/google/gwt/dev/javac/ContentId.java index 215cadf2f34..3c34b728ae3 100644 --- a/dev/core/src/com/google/gwt/dev/javac/ContentId.java +++ b/dev/core/src/com/google/gwt/dev/javac/ContentId.java @@ -21,15 +21,7 @@ * A key that encapsulates one revision of the source code content for a type. */ class ContentId extends StringKey { - - private String sourceTypeName; - public ContentId(String sourceTypeName, String strongHash) { super(sourceTypeName + ':' + strongHash); - this.sourceTypeName = sourceTypeName; - } - - public String getSourceTypeName() { - return sourceTypeName; } } diff --git a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java index 51fef86825e..d3696e0cef9 100644 --- a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java +++ b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java @@ -45,6 +45,7 @@ import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import com.google.gwt.thirdparty.guava.common.io.Files; import java.io.ByteArrayOutputStream; @@ -54,10 +55,12 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -149,8 +152,9 @@ public void abort() { @Override public void commit(TreeLogger logger) { String source = sw.toString(); - strongHash = Util.computeStrongName(Util.getBytes(source)); - sourceToken = diskCache.writeString(source); + byte[] sourceBytes = source.getBytes(StandardCharsets.UTF_8); + strongHash = Hashing.murmur3_128().hashBytes(sourceBytes).toString().toUpperCase(Locale.ROOT); + sourceToken = diskCache.writeByteArray(sourceBytes); sw = null; creationTime = System.currentTimeMillis(); } diff --git a/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java b/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java index 3532013288e..7d3b9817448 100644 --- a/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java +++ b/dev/core/src/com/google/gwt/dev/javac/UnitCacheSingleton.java @@ -18,11 +18,10 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.dev.jjs.JJSOptions; -import com.google.gwt.thirdparty.guava.common.base.Joiner; -import com.google.gwt.util.tools.shared.Md5Utils; -import com.google.gwt.util.tools.shared.StringUtils; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.File; +import java.nio.charset.StandardCharsets; /** * Lazily creates a singleton cache for {@link CompilationUnit} instances. @@ -52,13 +51,11 @@ public static synchronized void clearCache() throws UnableToCompleteException { } public static String getRelevantOptionsHash(JJSOptions options) { - return StringUtils.toHexString( - Md5Utils.getMd5Digest( - Joiner.on('-').join( - options.getJsInteropExportFilter(), - options.shouldGenerateJsInteropExports(), - options.getSourceLevel() - ).getBytes())); + return Hashing.murmur3_128().newHasher() + .putString(options.getJsInteropExportFilter().toString(), StandardCharsets.UTF_8) + .putBoolean(options.shouldGenerateJsInteropExports()) + .putInt(options.getSourceLevel().ordinal()) + .hash().toString(); } /** diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java index 7c857d5c61d..57852978ad4 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java +++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java @@ -184,6 +184,8 @@ import com.google.gwt.thirdparty.guava.common.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Multimap; import com.google.gwt.thirdparty.guava.common.collect.Sets; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import org.xml.sax.SAXException; @@ -193,12 +195,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.management.ManagementFactory; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -1526,11 +1530,15 @@ private static class PermutationResultImpl implements PermutationResult { public PermutationResultImpl(String[] jsFragments, Permutation permutation, SymbolData[] symbolMap, StatementRanges[] statementRanges) { byte[][] bytes = new byte[jsFragments.length][]; + Hasher h = Hashing.murmur3_128().newHasher(); + h.putInt(jsFragments.length); for (int i = 0; i < jsFragments.length; ++i) { - bytes[i] = Util.getBytes(jsFragments[i]); + bytes[i] = jsFragments[i].getBytes(StandardCharsets.UTF_8); + h.putInt(bytes[i].length); + h.putBytes(bytes[i]); } this.js = bytes; - this.jsStrongName = Util.computeStrongName(bytes); + this.jsStrongName = h.hash().toString().toUpperCase(Locale.ROOT); this.permutation = permutation; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/dev/core/src/com/google/gwt/dev/util/CompilerVersion.java b/dev/core/src/com/google/gwt/dev/util/CompilerVersion.java index 027810a9a83..9a2704b659e 100644 --- a/dev/core/src/com/google/gwt/dev/util/CompilerVersion.java +++ b/dev/core/src/com/google/gwt/dev/util/CompilerVersion.java @@ -14,47 +14,54 @@ package com.google.gwt.dev.util; import com.google.gwt.dev.jjs.ast.JNode; +import com.google.gwt.thirdparty.guava.common.hash.Funnels; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.io.ByteStreams; import com.google.gwt.thirdparty.guava.common.io.Files; -import com.google.gwt.util.tools.shared.Md5Utils; -import com.google.gwt.util.tools.shared.StringUtils; import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URLConnection; +import java.util.UUID; /** * Utility for uniquely identifying the current compiler version. */ public class CompilerVersion { - private static String versionHash; + private static final String versionHash = computeCompilerHash(); + + private static String computeCompilerHash() { + Hasher hash = Hashing.murmur3_128().newHasher(); + try { + URLConnection urlConnection = JNode.class.getResource("JNode.class").openConnection(); + if (urlConnection instanceof JarURLConnection) { + String gwtdevJar = ((JarURLConnection) urlConnection).getJarFile().getName(); + ByteStreams.copy( + Files.asByteSource(new File(gwtdevJar)).openStream(), + Funnels.asOutputStream(hash) + ); + return hash.hash().toString(); + } else { + System.err.println("Could not find the GWT compiler jarfile. " + + "Serialization errors might occur when accessing the persistent unit cache."); + return "unknown-version-" + UUID.randomUUID(); + } + } catch (IOException e) { + System.err.println("Could not compute the hash for the GWT compiler jarfile." + + "Serialization errors might occur when accessing the persistent unit cache."); + return "unknown-version-" + UUID.randomUUID(); + } + } /** * Calculates and returns a hash to uniquely identify the current compiler version if possible. *

* If the compiler jar can not be found then a random hash is returned. */ - public static synchronized String getHash() { - if (versionHash == null) { - versionHash = "unknown-version-" + StringUtils.toHexString( - Md5Utils.getMd5Digest(Long.toString((long) (Long.MAX_VALUE * Math.random())))); - - try { - URLConnection urlConnection = JNode.class.getResource("JNode.class").openConnection(); - if (urlConnection instanceof JarURLConnection) { - String gwtdevJar = ((JarURLConnection) urlConnection).getJarFile().getName(); - versionHash = Files.hash(new File(gwtdevJar), Hashing.sha1()).toString(); - } else { - System.err.println("Could not find the GWT compiler jarfile. " - + "Serialization errors might occur when accessing the persistent unit cache."); - } - } catch (IOException e) { - System.err.println("Could not compute the hash for the GWT compiler jarfile." - + "Serialization errors might occur when accessing the persistent unit cache."); - } - } + public static String getHash() { return versionHash; } } diff --git a/dev/core/src/com/google/gwt/dev/util/DiskCachingUtil.java b/dev/core/src/com/google/gwt/dev/util/DiskCachingUtil.java index a4b319160f9..92fc453f34b 100644 --- a/dev/core/src/com/google/gwt/dev/util/DiskCachingUtil.java +++ b/dev/core/src/com/google/gwt/dev/util/DiskCachingUtil.java @@ -14,11 +14,11 @@ package com.google.gwt.dev.util; import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.thirdparty.guava.common.base.Joiner; -import com.google.gwt.util.tools.shared.Md5Utils; -import com.google.gwt.util.tools.shared.StringUtils; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -37,8 +37,15 @@ public static synchronized File computePreferredCacheDir(List moduleName TreeLogger logger) { String tempDir = System.getProperty("java.io.tmpdir"); String currentWorkingDirectory = System.getProperty("user.dir"); - String preferredCacheDirName = "gwt-cache-" + StringUtils.toHexString( - Md5Utils.getMd5Digest(currentWorkingDirectory + Joiner.on(", ").join(moduleNames))); + + Hasher hasher = Hashing.murmur3_128().newHasher() + .putInt(currentWorkingDirectory.length()) + .putString(currentWorkingDirectory, StandardCharsets.UTF_8); + for (String moduleName : moduleNames) { + hasher.putInt(moduleName.length()) + .putString(moduleName, StandardCharsets.UTF_8); + } + String preferredCacheDirName = "gwt-cache-" + hasher.hash(); File preferredCacheDir = new File(tempDir, preferredCacheDirName); if (!preferredCacheDir.exists() && !preferredCacheDir.mkdir()) { diff --git a/dev/core/src/com/google/gwt/dev/util/Util.java b/dev/core/src/com/google/gwt/dev/util/Util.java index 2f639185552..bce90205b02 100644 --- a/dev/core/src/com/google/gwt/dev/util/Util.java +++ b/dev/core/src/com/google/gwt/dev/util/Util.java @@ -22,6 +22,7 @@ import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import com.google.gwt.thirdparty.guava.common.io.Closeables; import com.google.gwt.util.tools.Utility; import com.google.gwt.util.tools.shared.StringUtils; @@ -60,6 +61,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Collection; +import java.util.Locale; /** * A smattering of useful methods. Methods in this class are candidates for @@ -92,8 +94,9 @@ public final class Util { * @return a big fat string encoding of the MD5 for the content, suitably * formatted for use as a file name */ + @Deprecated public static String computeStrongName(byte[] content) { - return computeStrongName(new byte[][] {content}); + return Hashing.murmur3_128().hashBytes(content).toString().toUpperCase(Locale.ROOT); } /** @@ -102,6 +105,7 @@ public static String computeStrongName(byte[] content) { * @return a big fat string encoding of the MD5 for the content, suitably * formatted for use as a file name */ + @Deprecated public static String computeStrongName(byte[][] contents) { MessageDigest md5; try { diff --git a/dev/core/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java b/dev/core/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java index f3f7cd473b6..8ea3ff1c66c 100644 --- a/dev/core/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java +++ b/dev/core/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java @@ -20,16 +20,16 @@ import com.google.gwt.core.ext.linker.ModuleMetricsArtifact; import com.google.gwt.core.ext.linker.PrecompilationMetricsArtifact; import com.google.gwt.core.ext.soyc.impl.SizeMapRecorder; -import com.google.gwt.dev.util.Util; import com.google.gwt.soyc.io.OutputDirectory; import com.google.gwt.thirdparty.guava.common.base.Joiner; import com.google.gwt.thirdparty.guava.common.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Sets; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; @@ -646,11 +646,7 @@ private static String escapeXml(String unescaped) { * implementation simply hashes the long name. */ private static String hashedFilenameFragment(String longFileName) { - try { - return Util.computeStrongName(longFileName.getBytes(Util.DEFAULT_ENCODING)); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + return Hashing.murmur3_128().hashString(longFileName, StandardCharsets.UTF_8).toString(); } private static String headerLineForBreakdown(SizeBreakdown breakdown) { diff --git a/dev/core/test/com/google/gwt/dev/javac/CompilationStateTestBase.java b/dev/core/test/com/google/gwt/dev/javac/CompilationStateTestBase.java index 1247245c2c0..3a0834ac226 100644 --- a/dev/core/test/com/google/gwt/dev/javac/CompilationStateTestBase.java +++ b/dev/core/test/com/google/gwt/dev/javac/CompilationStateTestBase.java @@ -21,12 +21,13 @@ import com.google.gwt.dev.javac.testing.impl.JavaResourceBase; import com.google.gwt.dev.javac.testing.impl.MockResource; import com.google.gwt.dev.javac.testing.impl.MockResourceOracle; -import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.log.AbstractTreeLogger; import com.google.gwt.dev.util.log.PrintWriterTreeLogger; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import junit.framework.TestCase; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -80,7 +81,7 @@ public long getSourceToken() { @Override public String getStrongHash() { - return Util.computeStrongName(Util.getBytes(getSource())); + return Hashing.murmur3_128().hashString(getSource(), StandardCharsets.UTF_8).toString(); } @Override diff --git a/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java b/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java index 8dd25592720..90c9fb99d0d 100644 --- a/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java +++ b/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java @@ -15,14 +15,19 @@ */ package com.google.gwt.resources.rebind.context; +import static java.nio.charset.StandardCharsets.UTF_8; + 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.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.TypeOracleException; -import com.google.gwt.dev.util.Util; import com.google.gwt.resources.ext.ClientBundleRequirements; +import com.google.gwt.thirdparty.guava.common.hash.HashCode; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; + +import java.util.Locale; /** * Generates Multipart HTML files. @@ -74,8 +79,8 @@ protected void doAddFieldsAndRequirements(TreeLogger logger, protected void doCreateBundleForPermutation(TreeLogger logger, GeneratorContext generatorContext, FieldsImpl fields, String generatedSimpleSourceName) throws UnableToCompleteException { - String partialPath = Util.computeStrongName(Util.getBytes(generatedSimpleSourceName)) - + BUNDLE_EXTENSION; + HashCode hash = Hashing.murmur3_128().hashString(generatedSimpleSourceName, UTF_8); + String partialPath = hash.toString().toUpperCase(Locale.ROOT) + BUNDLE_EXTENSION; resourceContext.setPartialPath(partialPath); fields.setInitializer(bundleBaseIdent, "\"mhtml:\" + GWT.getModuleBaseURL() + \"" + partialPath + "!cid:\""); diff --git a/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java b/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java index 64078aac02e..c0b2ef21493 100644 --- a/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java +++ b/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java @@ -19,13 +19,14 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.dev.util.Util; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -66,7 +67,7 @@ public class MhtmlResourceContext extends StaticResourceContext { public String deploy(String suggestedFileName, String mimeType, byte[] data, boolean forceExternal) throws UnableToCompleteException { - String strongName = Util.computeStrongName(data); + String strongName = Hashing.murmur3_128().hashBytes(data).toString().toUpperCase(Locale.ROOT); String toReturn = strongNameToExpressions.get(strongName); if (toReturn != null) { return toReturn; diff --git a/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java b/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java index 6dc2e3c847d..5054a45c1c5 100644 --- a/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java +++ b/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java @@ -22,10 +22,11 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.dev.util.Util; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import java.io.IOException; import java.io.OutputStream; +import java.util.Locale; class StaticResourceContext extends AbstractResourceContext { /** @@ -59,7 +60,7 @@ public String deploy(String suggestedFileName, String mimeType, byte[] data, // Determine the final filename for the resource's file String outputName; if (Boolean.parseBoolean(enableRenaming)) { - String strongName = Util.computeStrongName(data); + String strongName = Hashing.murmur3_128().hashBytes(data).toString().toUpperCase(Locale.ROOT); // Determine the extension of the original file String extension; @@ -70,7 +71,7 @@ public String deploy(String suggestedFileName, String mimeType, byte[] data, extension = "noext"; } - // The name will be MD5.cache.ext + // The name will be .cache.ext outputName = strongName + ".cache." + extension; } else { outputName = suggestedFileName.substring(suggestedFileName.lastIndexOf('/') + 1); diff --git a/user/src/com/google/gwt/resources/rg/ExternalTextResourceGenerator.java b/user/src/com/google/gwt/resources/rg/ExternalTextResourceGenerator.java index 04307599713..29ab8770181 100644 --- a/user/src/com/google/gwt/resources/rg/ExternalTextResourceGenerator.java +++ b/user/src/com/google/gwt/resources/rg/ExternalTextResourceGenerator.java @@ -34,10 +34,12 @@ import com.google.gwt.resources.ext.ResourceGeneratorUtil; import com.google.gwt.resources.ext.SupportsGeneratorResultCaching; import com.google.gwt.safehtml.shared.UriUtils; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; import com.google.gwt.user.rebind.SourceWriter; import com.google.gwt.user.rebind.StringSourceWriter; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -55,13 +57,15 @@ public final class ExternalTextResourceGenerator extends // This string must stay in sync with the values in JsonpRequest.java static final String JSONP_CALLBACK_PREFIX = "__gwt_jsonp__.P"; - private StringBuffer data; + private StringBuilder data; private boolean first; private String urlExpression; private Map hashes; private Map offsets; private int currentIndex; + private String hash; + private String externalTextUrlIdent; private String externalTextCacheIdent; @@ -80,7 +84,7 @@ public String createAssignment(TreeLogger logger, ResourceContext context, sw.println(externalTextCacheIdent + ", "); sw.println(offsets.get(method.getName()).toString()); if (shouldUseJsonp(context, logger)) { - sw.println(", \"" + getMd5HashOfData() + "\""); + sw.println(", \"" + getMurmurHashOfData() + "\""); } sw.outdent(); sw.print(")"); @@ -92,12 +96,12 @@ public String createAssignment(TreeLogger logger, ResourceContext context, public void createFields(TreeLogger logger, ResourceContext context, ClientBundleFields fields) throws UnableToCompleteException { data.append(']'); - StringBuffer wrappedData = new StringBuffer(); + StringBuilder wrappedData = new StringBuilder(); if (shouldUseJsonp(context, logger)) { wrappedData.append(JSONP_CALLBACK_PREFIX); - wrappedData.append(getMd5HashOfData()); + wrappedData.append(getMurmurHashOfData()); wrappedData.append(".onSuccess(\n"); - wrappedData.append(data.toString()); + wrappedData.append(data); wrappedData.append(")"); } else { wrappedData = data; @@ -126,7 +130,7 @@ public void createFields(TreeLogger logger, ResourceContext context, @Override public void init(TreeLogger logger, ResourceContext context) throws UnableToCompleteException { - data = new StringBuffer("[\n"); + data = new StringBuilder("[\n"); first = true; urlExpression = null; hashes = new HashMap(); @@ -170,8 +174,11 @@ public void prepare(TreeLogger logger, ResourceContext context, offsets.put(method.getName(), hashes.get(toWrite)); } - private String getMd5HashOfData() { - return Util.computeStrongName(Util.getBytes(data.toString())); + private String getMurmurHashOfData() { + if (hash == null) { + hash = Hashing.murmur3_128().hashString(data, StandardCharsets.UTF_8).toString(); + } + return hash; } private boolean shouldUseJsonp(ResourceContext context, TreeLogger logger) { diff --git a/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java b/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java index 30904951927..580e1191fd7 100644 --- a/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java +++ b/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java @@ -36,6 +36,10 @@ import com.google.gwt.resources.rg.ImageBundleBuilder.Arranger; import com.google.gwt.resources.rg.ImageBundleBuilder.ImageRect; import com.google.gwt.safehtml.shared.UriUtils; +import com.google.gwt.thirdparty.guava.common.hash.Funnels; +import com.google.gwt.thirdparty.guava.common.hash.Hasher; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.io.ByteStreams; import com.google.gwt.thirdparty.guava.common.io.Closeables; import com.google.gwt.user.rebind.SourceWriter; import com.google.gwt.user.rebind.StringSourceWriter; @@ -43,9 +47,11 @@ import java.awt.geom.AffineTransform; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -420,23 +426,31 @@ public static LocalizedImage create(TreeLogger logger, URL resource = resources[0]; - LocalizedImage toReturn = new LocalizedImage(image, resource); - return toReturn; + try { + return new LocalizedImage(image, resource); + } catch (IOException e) { + logger.log(TreeLogger.ERROR, "Unable to read image data", e); + throw new UnableToCompleteException(); + } } - private static String key(ImageResourceDeclaration image, URL url) { - return Util.computeStrongName(Util.readURLAsBytes(url)) + ":" - + image.getScaleHeight() + ":" + image.getScaleWidth(); + private static String key(ImageResourceDeclaration image, URL url) throws IOException { + try (InputStream inputStream = url.openStream()) { + Hasher hasher = Hashing.murmur3_128().newHasher(); + ByteStreams.copy(inputStream, Funnels.asOutputStream(hasher)); + String hash = hasher.hash().toString().toUpperCase(Locale.ROOT); + return hash + ":" + image.getScaleHeight() + ":" + image.getScaleWidth(); + } } private final ImageResourceDeclaration image; private final URL url; - public LocalizedImage(LocalizedImage other, URL alternateUrl) { + public LocalizedImage(LocalizedImage other, URL alternateUrl) throws IOException { this(other.image, alternateUrl); } - private LocalizedImage(ImageResourceDeclaration image, URL url) { + private LocalizedImage(ImageResourceDeclaration image, URL url) throws IOException { super(key(image, url)); this.image = image; this.url = url; diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java index f5f5880afbb..2f8da902488 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java +++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java @@ -40,12 +40,13 @@ import com.google.gwt.core.ext.typeinfo.NotFoundException; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.dev.generator.NameFactory; -import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.hash.HashingOutputStream; import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import com.google.gwt.user.client.rpc.RpcToken; @@ -77,6 +78,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -743,8 +745,9 @@ protected String writeSerializationPolicyFile(TreeLogger logger, GeneratorContex throws UnableToCompleteException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); + HashingOutputStream hashStream = new HashingOutputStream(Hashing.murmur3_128(), baos); OutputStreamWriter osw = - new OutputStreamWriter(baos, SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING); + new OutputStreamWriter(hashStream, SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING); PrintWriter pw = new PrintWriter(osw); JType[] serializableTypes = @@ -805,7 +808,7 @@ protected String writeSerializationPolicyFile(TreeLogger logger, GeneratorContex pw.close(); byte[] serializationPolicyFileContents = baos.toByteArray(); - String serializationPolicyName = Util.computeStrongName(serializationPolicyFileContents); + String serializationPolicyName = hashStream.hash().toString().toUpperCase(Locale.ROOT); String serializationPolicyFileName = SerializationPolicyLoader.getSerializationPolicyFileName(serializationPolicyName); @@ -901,9 +904,10 @@ private void emitPolicyFileArtifact(TreeLogger logger, GeneratorContext context, writer.close(); byte[] manifestBytes = baos.toByteArray(); - String md5 = Util.computeStrongName(manifestBytes); + String hash = Hashing.murmur3_128().hashBytes(manifestBytes) + .toString().toUpperCase(Locale.ROOT); OutputStream os = - context.tryCreateResource(logger, MANIFEST_ARTIFACT_DIR + "/" + md5 + ".txt"); + context.tryCreateResource(logger, MANIFEST_ARTIFACT_DIR + "/" + hash + ".txt"); os.write(manifestBytes); GeneratedResource resource = context.commitResource(logger, os); diff --git a/user/src/com/google/gwt/user/rebind/ui/ImageBundleBuilder.java b/user/src/com/google/gwt/user/rebind/ui/ImageBundleBuilder.java index 2f7921bcf94..4b67a8ac767 100644 --- a/user/src/com/google/gwt/user/rebind/ui/ImageBundleBuilder.java +++ b/user/src/com/google/gwt/user/rebind/ui/ImageBundleBuilder.java @@ -18,9 +18,10 @@ 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.util.Util; import com.google.gwt.dev.util.log.speedtracer.CompilerEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; +import com.google.gwt.thirdparty.guava.common.hash.Hashing; +import com.google.gwt.thirdparty.guava.common.hash.HashingOutputStream; import java.awt.Graphics2D; import java.awt.image.BufferedImage; @@ -318,23 +319,20 @@ public ImageRect getMapping(String imageName) { public String writeBundledImage(TreeLogger logger, GeneratorContext context) throws UnableToCompleteException { - // Create the bundled image from all of the constituent images. + // Create the bundled image from the constituent images. BufferedImage bundledImage = drawBundledImage(); - // Write the bundled image into a byte array, so that we can compute - // its strong name. - byte[] imageBytes; - + ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); + HashingOutputStream hashingOutputStream = new HashingOutputStream(Hashing.murmur3_128(), + byteOutputStream); try { - ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); - boolean writerAvailable = ImageIO.write(bundledImage, BUNDLE_FILE_TYPE, - byteOutputStream); + boolean writerAvailable = ImageIO.write(bundledImage, BUNDLE_FILE_TYPE, hashingOutputStream); + if (!writerAvailable) { logger.log(TreeLogger.ERROR, "No " + BUNDLE_FILE_TYPE + " writer available"); throw new UnableToCompleteException(); } - imageBytes = byteOutputStream.toByteArray(); } catch (IOException e) { logger.log(TreeLogger.ERROR, "An error occurred while trying to write the image bundle.", e); @@ -344,8 +342,8 @@ public String writeBundledImage(TreeLogger logger, GeneratorContext context) // Compute the file name. The strong name is generated from the bytes of // the bundled image. The '.cache' part indicates that it can be // permanently cached. - String bundleFileName = Util.computeStrongName(imageBytes) + ".cache." - + BUNDLE_FILE_TYPE; + String strongName = hashingOutputStream.hash().toString().toUpperCase(Locale.ROOT); + String bundleFileName = strongName + ".cache." + BUNDLE_FILE_TYPE; // Try and write the file to disk. If a file with bundleFileName already // exists, then the file will not be written. @@ -354,7 +352,7 @@ public String writeBundledImage(TreeLogger logger, GeneratorContext context) if (outStream != null) { try { // Write the image bytes from the byte array to the pending stream. - outStream.write(imageBytes); + outStream.write(byteOutputStream.toByteArray()); // Commit the stream. context.commitResource(logger, outStream); diff --git a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java index 26425601a7b..f21de44147e 100644 --- a/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java +++ b/user/src/com/google/gwt/user/server/rpc/impl/ServerSerializationStreamReader.java @@ -55,7 +55,6 @@ public final class ServerSerializationStreamReader extends AbstractSerialization * A basic sanity check for strong names. Only allow certain characters to protect serialization * policy providers that use it blindly to load files. (This is normally a hex string, but we * allow a few more safe characters in case it's useful for testing.) - * @see com.google.gwt.dev.util.Util#computeStrongName */ private static final Pattern ALLOWED_STRONG_NAME = Pattern.compile("[a-zA-Z0-9_]+"); diff --git a/user/src/com/google/web/bindery/requestfactory/vm/impl/OperationKey.java b/user/src/com/google/web/bindery/requestfactory/vm/impl/OperationKey.java index 84ea2175245..d3ac8c265ca 100644 --- a/user/src/com/google/web/bindery/requestfactory/vm/impl/OperationKey.java +++ b/user/src/com/google/web/bindery/requestfactory/vm/impl/OperationKey.java @@ -18,7 +18,7 @@ import com.google.gwt.dev.util.StringKey; import com.google.gwt.user.server.Base64Utils; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -42,12 +42,10 @@ public class OperationKey extends StringKey { public static String hash(String raw) { try { MessageDigest md = MessageDigest.getInstance("SHA1"); - byte[] data = md.digest(raw.getBytes("UTF-8")); + byte[] data = md.digest(raw.getBytes(StandardCharsets.UTF_8)); return Base64Utils.toBase64(data); } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("No MD5 algorithm", e); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("No UTF-8", e); + throw new RuntimeException("No SHA1 algorithm", e); } }