From c17882f43205c0add2322dfc26e79b6f76a1a64d Mon Sep 17 00:00:00 2001 From: sergiorussia <22471371+sergiorussia@users.noreply.github.com> Date: Mon, 29 Apr 2019 23:30:50 +0300 Subject: [PATCH 1/3] zip files support --- .../threerings/getdown/data/PathBuilder.java | 4 +- .../com/threerings/getdown/data/Resource.java | 42 +++---- .../com/threerings/getdown/tools/Differ.java | 39 +++---- .../com/threerings/getdown/tools/JarDiff.java | 109 +++++++++--------- .../getdown/tools/JarDiffPatcher.java | 83 ++++++------- .../com/threerings/getdown/tools/Patcher.java | 18 ++- .../com/threerings/getdown/util/FileUtil.java | 49 +++++--- 7 files changed, 166 insertions(+), 178 deletions(-) diff --git a/core/src/main/java/com/threerings/getdown/data/PathBuilder.java b/core/src/main/java/com/threerings/getdown/data/PathBuilder.java index b0a1dc92..57e9275b 100644 --- a/core/src/main/java/com/threerings/getdown/data/PathBuilder.java +++ b/core/src/main/java/com/threerings/getdown/data/PathBuilder.java @@ -10,7 +10,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.jar.JarFile; +import java.util.zip.ZipFile; import com.threerings.getdown.cache.GarbageCollector; import com.threerings.getdown.cache.ResourceCache; @@ -112,7 +112,7 @@ public static ClassPath buildLibsPath (Application app, if (!unpackedIndicator.exists()) { try { - FileUtil.unpackJar(new JarFile(cachedFile), cachedParent, false); + FileUtil.unpackJar(new ZipFile(cachedFile), cachedParent, false); unpackedIndicator.createNewFile(); } catch (IOException ioe) { log.warning("Failed to unpack native jar", diff --git a/core/src/main/java/com/threerings/getdown/data/Resource.java b/core/src/main/java/com/threerings/getdown/data/Resource.java index 3e2f4463..e8f8f1db 100644 --- a/core/src/main/java/com/threerings/getdown/data/Resource.java +++ b/core/src/main/java/com/threerings/getdown/data/Resource.java @@ -5,7 +5,10 @@ package com.threerings.getdown.data; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.security.MessageDigest; import java.util.Collections; @@ -13,13 +16,12 @@ import java.util.EnumSet; import java.util.List; import java.util.Locale; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import com.threerings.getdown.util.FileUtil; import com.threerings.getdown.util.ProgressObserver; import com.threerings.getdown.util.StringUtil; - import static com.threerings.getdown.Log.log; /** @@ -66,23 +68,22 @@ public static String computeDigest (int version, File target, MessageDigest md, // if this is a jar, we need to compute the digest in a "timestamp and file order" agnostic // manner to properly correlate jardiff patched jars with their unpatched originals if (isJar || isPacked200Jar){ - File tmpJarFile = null; - JarFile jar = null; + ZipFile jar = null; try { // if this is a compressed jar file, uncompress it to compute the jar file digest if (isPacked200Jar){ - tmpJarFile = new File(target.getPath() + ".tmp"); - FileUtil.unpackPacked200Jar(target, tmpJarFile); - jar = new JarFile(tmpJarFile); + File tmpJarFile = new File(target.getPath() + ".tmp"); + tmpJarFile.deleteOnExit(); + jar = FileUtil.unpackPacked200Jar(target, tmpJarFile); } else{ - jar = new JarFile(target); + jar = new ZipFile(target); } - List entries = Collections.list(jar.entries()); + List entries = Collections.list(jar.entries()); Collections.sort(entries, ENTRY_COMP); int eidx = 0; - for (JarEntry entry : entries) { + for (ZipEntry entry : entries) { // old versions of the digest code skipped metadata if (version < 2) { if (entry.getName().startsWith("META-INF")) { @@ -108,9 +109,6 @@ public static String computeDigest (int version, File target, MessageDigest md, log.warning("Error closing jar", "path", target, "jar", jar, "error", ioe); } } - if (tmpJarFile != null) { - FileUtil.deleteHarder(tmpJarFile); - } } } else { @@ -302,7 +300,7 @@ public void unpack () throws IOException throw new IOException("Requested to unpack non-jar file '" + _local + "'."); } if (_isJar) { - try (JarFile jar = new JarFile(_local)) { + try (ZipFile jar = new ZipFile(_local)) { FileUtil.unpackJar(jar, _unpacked, _attrs.contains(Attr.CLEAN)); } } else { @@ -341,11 +339,7 @@ public void erase () @Override public boolean equals (Object other) { - if (other instanceof Resource) { - return _path.equals(((Resource)other)._path); - } else { - return false; - } + return other instanceof Resource && _path.equals(((Resource) other)._path); } @Override public int hashCode () @@ -368,7 +362,7 @@ protected static void updateProgress (ProgressObserver obs, long pos, long total protected static boolean isJar (String path) { - return path.endsWith(".jar") || path.endsWith(".jar_new"); + return path.endsWith(".jar") || path.endsWith(".jar_new") || path.endsWith(".zip"); } protected static boolean isPacked200Jar (String path) @@ -384,8 +378,8 @@ protected static boolean isPacked200Jar (String path) protected boolean _isJar, _isPacked200Jar; /** Used to sort the entries in a jar file. */ - protected static final Comparator ENTRY_COMP = new Comparator() { - @Override public int compare (JarEntry e1, JarEntry e2) { + protected static final Comparator ENTRY_COMP = new Comparator() { + @Override public int compare (ZipEntry e1, ZipEntry e2) { return e1.getName().compareTo(e2.getName()); } }; diff --git a/core/src/main/java/com/threerings/getdown/tools/Differ.java b/core/src/main/java/com/threerings/getdown/tools/Differ.java index c2e740b6..31a0f0ad 100644 --- a/core/src/main/java/com/threerings/getdown/tools/Differ.java +++ b/core/src/main/java/com/threerings/getdown/tools/Differ.java @@ -11,15 +11,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; - +import java.security.MessageDigest; import java.util.ArrayList; import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; - -import java.security.MessageDigest; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import com.threerings.getdown.data.Application; import com.threerings.getdown.data.Digest; @@ -91,15 +88,15 @@ public void createDiff (File nvdir, File ovdir, boolean verbose) } } - protected void createPatch (File patch, ArrayList orsrcs, - ArrayList nrsrcs, boolean verbose) + protected static void createPatch(File patch, ArrayList orsrcs, + ArrayList nrsrcs, boolean verbose) throws IOException { int version = Digest.VERSION; MessageDigest md = Digest.getMessageDigest(version); try (FileOutputStream fos = new FileOutputStream(patch); BufferedOutputStream buffered = new BufferedOutputStream(fos); - JarOutputStream jout = new JarOutputStream(buffered)) { + ZipOutputStream jout = new ZipOutputStream(buffered)) { // for each file in the new application, it either already exists // in the old application, or it is new @@ -168,17 +165,16 @@ protected void createPatch (File patch, ArrayList orsrcs, } } - protected File rebuildJar (File target) - throws IOException + protected static File rebuildJar(File target) throws IOException { File temp = File.createTempFile("differ", "jar"); - try (JarFile jar = new JarFile(target); - FileOutputStream tempFos = new FileOutputStream(temp); - BufferedOutputStream tempBos = new BufferedOutputStream(tempFos); - JarOutputStream jout = new JarOutputStream(tempBos)) { + try (ZipFile jar = new ZipFile(target); + FileOutputStream tempFos = new FileOutputStream(temp); + BufferedOutputStream tempBos = new BufferedOutputStream(tempFos); + ZipOutputStream jout = new ZipOutputStream(tempBos)) { byte[] buffer = new byte[4096]; - for (Enumeration< JarEntry > iter = jar.entries(); iter.hasMoreElements();) { - JarEntry entry = iter.nextElement(); + for (Enumeration iter = jar.entries(); iter.hasMoreElements();) { + ZipEntry entry = iter.nextElement(); entry.setCompressedSize(-1); jout.putNextEntry(entry); try (InputStream in = jar.getInputStream(entry)) { @@ -193,8 +189,7 @@ protected File rebuildJar (File target) return temp; } - protected void jarDiff (File ofile, File nfile, JarOutputStream jout) - throws IOException + protected static void jarDiff(File ofile, File nfile, ZipOutputStream jout) throws IOException { JarDiff.createPatch(ofile.getPath(), nfile.getPath(), jout, false); } @@ -202,8 +197,7 @@ protected void jarDiff (File ofile, File nfile, JarOutputStream jout) public static void main (String[] args) { if (args.length < 2) { - System.err.println( - "Usage: Differ [-verbose] new_vers_dir old_vers_dir"); + System.err.println("Usage: Differ [-verbose] new_vers_dir old_vers_dir"); System.exit(255); } Differ differ = new Differ(); @@ -222,8 +216,7 @@ public static void main (String[] args) } } - protected static void pipe (File file, JarOutputStream jout) - throws IOException + protected static void pipe (File file, ZipOutputStream jout) throws IOException { try (FileInputStream fin = new FileInputStream(file)) { StreamUtil.copy(fin, jout); diff --git a/core/src/main/java/com/threerings/getdown/tools/JarDiff.java b/core/src/main/java/com/threerings/getdown/tools/JarDiff.java index 1cea0eac..90ddf0cb 100644 --- a/core/src/main/java/com/threerings/getdown/tools/JarDiff.java +++ b/core/src/main/java/com/threerings/getdown/tools/JarDiff.java @@ -41,9 +41,17 @@ package com.threerings.getdown.tools; -import java.io.*; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; import java.util.*; -import java.util.jar.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import static java.nio.charset.StandardCharsets.UTF_8; @@ -66,18 +74,16 @@ public class JarDiff implements JarDiffCodes private static boolean _debug; /** - * Creates a patch from the two passed in files, writing the result to os. + * Creates a patch from the two passed in files, writing the result to {@code os}. */ public static void createPatch (String oldPath, String newPath, OutputStream os, boolean minimal) throws IOException { - try (JarFile2 oldJar = new JarFile2(oldPath); - JarFile2 newJar = new JarFile2(newPath)) { - - HashMap moved = new HashMap<>(); - HashSet implicit = new HashSet<>(); - HashSet moveSrc = new HashSet<>(); - HashSet newEntries = new HashSet<>(); + try (JarFile2 oldJar = new JarFile2(oldPath); JarFile2 newJar = new JarFile2(newPath)) { + final Map moved = new HashMap<>(); + final Set implicit = new HashSet<>(); + final Set moveSrc = new HashSet<>(); + final Set newEntries = new HashSet<>(); // FIRST PASS // Go through the entries in new jar and @@ -86,7 +92,7 @@ public static void createPatch (String oldPath, String newPath, // and new.jar ) // and for files that cannot be implicitly moved, we will either // find out whether it is moved or new (modified) - for (JarEntry newEntry : newJar) { + for (ZipEntry newEntry : newJar) { String newname = newEntry.getName(); // Return best match of contents, will return a name match if possible @@ -122,7 +128,6 @@ public static void createPatch (String oldPath, String newPath, // for backward compatibility if (_debug) { - System.out.println("NEW: "+ newname); } newEntries.add(newname); @@ -136,12 +141,9 @@ public static void createPatch (String oldPath, String newPath, } // Check if this disables an implicit 'move ' if (implicit.contains(oldname) && minimal) { - if (_debug) { System.err.println("implicit.remove " + oldname); - System.err.println("moved.put " + oldname + " " + oldname); - } implicit.remove(oldname); moved.put(oldname, oldname); @@ -153,8 +155,8 @@ public static void createPatch (String oldPath, String newPath, // SECOND PASS: = - - // - - ArrayList deleted = new ArrayList<>(); - for (JarEntry oldEntry : oldJar) { + final List deleted = new ArrayList<>(); + for (ZipEntry oldEntry : oldJar) { String oldName = oldEntry.getName(); if (!implicit.contains(oldName) && !moveSrc.contains(oldName) && !newEntries.contains(oldName)) { @@ -180,7 +182,7 @@ public static void createPatch (String oldPath, String newPath, } } - JarOutputStream jos = new JarOutputStream(os); + ZipOutputStream jos = new ZipOutputStream(os); // Write out all the MOVEs and REMOVEs createIndex(jos, deleted, moved); @@ -199,12 +201,11 @@ public static void createPatch (String oldPath, String newPath, } /** - * Writes the index file out to jos. - * oldEntries gives the names of the files that were removed, - * movedMap maps from the new name to the old name. + * Writes the index file out to {@code jos}. + * {@code oldEntries} gives the names of the files that were removed, + * {@code movedMap} maps from the new name to the old name. */ - private static void createIndex (JarOutputStream jos, List oldEntries, - Map movedMap) + private static void createIndex (ZipOutputStream jos, List oldEntries, Map movedMap) throws IOException { StringWriter writer = new StringWriter(); @@ -220,22 +221,22 @@ private static void createIndex (JarOutputStream jos, List oldEntries, } // And those that have moved - for (String newName : movedMap.keySet()) { - String oldName = movedMap.get(newName); + for (Map.Entry entry : movedMap.entrySet()) { + String oldName = entry.getValue(); writer.write(MOVE_COMMAND); writer.write(" "); writeEscapedString(writer, oldName); writer.write(" "); - writeEscapedString(writer, newName); + writeEscapedString(writer, entry.getKey()); writer.write("\r\n"); } - jos.putNextEntry(new JarEntry(INDEX_NAME)); + jos.putNextEntry(new ZipEntry(INDEX_NAME)); byte[] bytes = writer.toString().getBytes(UTF_8); jos.write(bytes, 0, bytes.length); } - protected static Writer writeEscapedString (Writer writer, String string) + protected static void writeEscapedString (Writer writer, String string) throws IOException { int index = 0; @@ -261,10 +262,9 @@ protected static Writer writeEscapedString (Writer writer, String string) writer.write(string); } - return writer; } - private static void writeEntry (JarOutputStream jos, JarEntry entry, JarFile2 file) + private static void writeEntry (ZipOutputStream jos, ZipEntry entry, JarFile2 file) throws IOException { try (InputStream data = file.getJarFile().getInputStream(entry)) { @@ -278,31 +278,31 @@ private static void writeEntry (JarOutputStream jos, JarEntry entry, JarFile2 fi } /** - * JarFile2 wraps a JarFile providing some convenience methods. + * JarFile2 wraps a ZipFile providing some convenience methods. */ - private static class JarFile2 implements Iterable, Closeable + private static class JarFile2 implements Iterable, Closeable { - private JarFile _jar; - private List _entries; - private HashMap _nameToEntryMap; - private HashMap> _crcToEntryMap; + private ZipFile _jar; + private List _entries; + private HashMap _nameToEntryMap; + private HashMap> _crcToEntryMap; public JarFile2 (String path) throws IOException { - _jar = new JarFile(new File(path)); + _jar = new ZipFile(new File(path)); index(); } - public JarFile getJarFile () { + public ZipFile getJarFile () { return _jar; } - // from interface Iterable + // from interface Iterable @Override - public Iterator iterator () { + public Iterator iterator () { return _entries.iterator(); } - public JarEntry getEntryByName (String name) { + public ZipEntry getEntryByName (String name) { return _nameToEntryMap.get(name); } @@ -350,7 +350,7 @@ private static boolean differs (InputStream oldIS, InputStream newIS) throws IOE return retVal; } - public String getBestMatch (JarFile2 file, JarEntry entry) throws IOException { + public String getBestMatch (JarFile2 file, ZipEntry entry) throws IOException { // check for same name and same content, return name if found if (contains(file, entry)) { return (entry.getName()); @@ -360,9 +360,8 @@ public String getBestMatch (JarFile2 file, JarEntry entry) throws IOException { return (hasSameContent(file,entry)); } - public boolean contains (JarFile2 f, JarEntry e) throws IOException { - - JarEntry thisEntry = getEntryByName(e.getName()); + public boolean contains (JarFile2 f, ZipEntry e) throws IOException { + ZipEntry thisEntry = getEntryByName(e.getName()); // Look up name in 'this' Jar2File - if not exist return false if (thisEntry == null) @@ -379,17 +378,17 @@ public boolean contains (JarFile2 f, JarEntry e) throws IOException { } } - public String hasSameContent (JarFile2 file, JarEntry entry) throws IOException { + public String hasSameContent (JarFile2 file, ZipEntry entry) throws IOException { String thisName = null; - Long crcL = Long.valueOf(entry.getCrc()); + Long crcL = entry.getCrc(); // check if this jar contains files with the passed in entry's crc if (_crcToEntryMap.containsKey(crcL)) { // get the Linked List with files with the crc - LinkedList ll = _crcToEntryMap.get(crcL); + LinkedList ll = _crcToEntryMap.get(crcL); // go through the list and check for content match - ListIterator li = ll.listIterator(0); + ListIterator li = ll.listIterator(0); while (li.hasNext()) { - JarEntry thisEntry = li.next(); + ZipEntry thisEntry = li.next(); // check for content match try (InputStream oldIS = getJarFile().getInputStream(thisEntry); InputStream newIS = file.getJarFile().getInputStream(entry)) { @@ -404,7 +403,7 @@ public String hasSameContent (JarFile2 file, JarEntry entry) throws IOException } private void index () throws IOException { - Enumeration entries = _jar.entries(); + Enumeration entries = _jar.entries(); _nameToEntryMap = new HashMap<>(); _crcToEntryMap = new HashMap<>(); @@ -414,9 +413,9 @@ private void index () throws IOException { } if (entries != null) { while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); + ZipEntry entry = entries.nextElement(); long crc = entry.getCrc(); - Long crcL = Long.valueOf(crc); + Long crcL = crc; if (_debug) { System.out.println("\t" + entry.getName() + " CRC " + crc); } @@ -427,13 +426,13 @@ private void index () throws IOException { // generate the CRC to entries map if (_crcToEntryMap.containsKey(crcL)) { // key exist, add the entry to the correcponding linked list - LinkedList ll = _crcToEntryMap.get(crcL); + LinkedList ll = _crcToEntryMap.get(crcL); ll.add(entry); _crcToEntryMap.put(crcL, ll); } else { // create a new entry in the hashmap for the new key - LinkedList ll = new LinkedList(); + LinkedList ll = new LinkedList(); ll.add(entry); _crcToEntryMap.put(crcL, ll); } diff --git a/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java b/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java index b5a0a176..af421736 100644 --- a/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java +++ b/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java @@ -11,22 +11,18 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; - import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; - -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import com.threerings.getdown.util.ProgressObserver; - import static java.nio.charset.StandardCharsets.UTF_8; /** @@ -45,25 +41,23 @@ public class JarDiffPatcher implements JarDiffCodes * * @throws IOException if any problem occurs during patching. */ - public void patchJar (String jarPath, String diffPath, File target, ProgressObserver observer) + public static void patchJar(String jarPath, String diffPath, File target, ProgressObserver observer) throws IOException { File oldFile = new File(jarPath), diffFile = new File(diffPath); - - try (JarFile oldJar = new JarFile(oldFile); - JarFile jarDiff = new JarFile(diffFile); - JarOutputStream jos = new JarOutputStream(new FileOutputStream(target))) { - - Set ignoreSet = new HashSet<>(); - Map renameMap = new HashMap<>(); + try (ZipFile oldJar = new ZipFile(oldFile); + ZipFile jarDiff = new ZipFile(diffFile); + ZipOutputStream jos = new ZipOutputStream(new FileOutputStream(target))) { + final Set ignoreSet = new HashSet<>(); + final Map renameMap = new HashMap<>(); determineNameMapping(jarDiff, ignoreSet, renameMap); // get all keys in renameMap String[] keys = renameMap.keySet().toArray(new String[renameMap.size()]); // Files to implicit move - Set oldjarNames = new HashSet<>(); - Enumeration oldEntries = oldJar.entries(); + final Set oldjarNames = new HashSet<>(); + Enumeration oldEntries = oldJar.entries(); if (oldEntries != null) { while (oldEntries.hasMoreElements()) { oldjarNames.add(oldEntries.nextElement().getName()); @@ -83,10 +77,10 @@ public void patchJar (String jarPath, String diffPath, File target, ProgressObse size -= ignoreSet.size(); // Add content from JARDiff - Enumeration entries = jarDiff.entries(); + Enumeration entries = jarDiff.entries(); if (entries != null) { while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); + ZipEntry entry = entries.nextElement(); if (!INDEX_NAME.equals(entry.getName())) { updateObserver(observer, currentEntry, size); currentEntry++; @@ -114,15 +108,14 @@ public void patchJar (String jarPath, String diffPath, File target, ProgressObse // Apply move command String oldName = renameMap.get(newName); - // Get source JarEntry - JarEntry oldEntry = oldJar.getJarEntry(oldName); + // Get source ZipEntry + ZipEntry oldEntry = oldJar.getEntry(oldName); if (oldEntry == null) { - String moveCmd = MOVE_COMMAND + oldName + " " + newName; - throw new IOException("error.badmove: " + moveCmd); + throw new IOException("error.badmove: " + MOVE_COMMAND + oldName + " " + newName); } - // Create dest JarEntry - JarEntry newEntry = new JarEntry(newName); + // Create dest ZipEntry + ZipEntry newEntry = new ZipEntry(newName); newEntry.setTime(oldEntry.getTime()); newEntry.setSize(oldEntry.getSize()); newEntry.setCompressedSize(oldEntry.getCompressedSize()); @@ -149,33 +142,29 @@ public void patchJar (String jarPath, String diffPath, File target, ProgressObse } // implicit move - Iterator iEntries = oldjarNames.iterator(); - if (iEntries != null) { - while (iEntries.hasNext()) { - String name = iEntries.next(); - JarEntry entry = oldJar.getJarEntry(name); - if (entry == null) { - // names originally retrieved from the JAR, so this should never happen - throw new AssertionError("JAR entry not found: " + name); - } - updateObserver(observer, currentEntry, size); - currentEntry++; - writeEntry(jos, entry, oldJar); + for (String name : oldjarNames) { + ZipEntry entry = oldJar.getEntry(name); + if (entry == null) { + // names originally retrieved from the JAR, so this should never happen + throw new AssertionError("JAR entry not found: " + name); } + updateObserver(observer, currentEntry, size); + currentEntry++; + writeEntry(jos, entry, oldJar); } updateObserver(observer, currentEntry, size); } } - protected void updateObserver (ProgressObserver observer, double currentSize, double size) + protected static void updateObserver(ProgressObserver observer, double currentSize, double size) { if (observer != null) { observer.progress((int)(100*currentSize/size)); } } - protected void determineNameMapping ( - JarFile jarDiff, Set ignoreSet, Map renameMap) + protected static void determineNameMapping( + ZipFile jarDiff, Set ignoreSet, Map renameMap) throws IOException { InputStream is = jarDiff.getInputStream(jarDiff.getEntry(INDEX_NAME)); @@ -183,8 +172,7 @@ protected void determineNameMapping ( throw new IOException("error.noindex"); } - LineNumberReader indexReader = - new LineNumberReader(new InputStreamReader(is, UTF_8)); + LineNumberReader indexReader = new LineNumberReader(new InputStreamReader(is, UTF_8)); String line = indexReader.readLine(); if (line == null || !line.equals(VERSION_HEADER)) { throw new IOException("jardiff.error.badheader: " + line); @@ -219,12 +207,11 @@ protected void determineNameMapping ( } } - protected List getSubpaths (String path) + protected static List getSubpaths(String path) { int index = 0; int length = path.length(); - ArrayList sub = new ArrayList<>(); - + final List sub = new ArrayList<>(); while (index < length) { while (index < length && Character.isWhitespace (path.charAt(index))) { @@ -264,7 +251,7 @@ protected List getSubpaths (String path) return sub; } - protected void writeEntry (JarOutputStream jos, JarEntry entry, JarFile file) + protected static void writeEntry(ZipOutputStream jos, ZipEntry entry, ZipFile file) throws IOException { try (InputStream data = file.getInputStream(entry)) { @@ -272,10 +259,10 @@ protected void writeEntry (JarOutputStream jos, JarEntry entry, JarFile file) } } - protected void writeEntry (JarOutputStream jos, JarEntry entry, InputStream data) + protected static void writeEntry(ZipOutputStream jos, ZipEntry entry, InputStream data) throws IOException { - jos.putNextEntry(new JarEntry(entry.getName())); + jos.putNextEntry(new ZipEntry(entry.getName())); // Read the entry int size = data.read(newBytes); diff --git a/core/src/main/java/com/threerings/getdown/tools/Patcher.java b/core/src/main/java/com/threerings/getdown/tools/Patcher.java index 4ead59bb..922ebb0a 100644 --- a/core/src/main/java/com/threerings/getdown/tools/Patcher.java +++ b/core/src/main/java/com/threerings/getdown/tools/Patcher.java @@ -9,16 +9,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; - import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import com.threerings.getdown.util.FileUtil; import com.threerings.getdown.util.ProgressObserver; import com.threerings.getdown.util.StreamUtil; - import static com.threerings.getdown.Log.log; /** @@ -55,10 +52,10 @@ public void patch (File appdir, File patch, ProgressObserver obs) _obs = obs; _plength = patch.length(); - try (JarFile file = new JarFile(patch)) { - Enumeration entries = file.entries(); // old skool! + try (ZipFile file = new ZipFile(patch)) { + Enumeration entries = file.entries(); while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); + ZipEntry entry = entries.nextElement(); String path = entry.getName(); long elength = entry.getCompressedSize(); @@ -96,7 +93,7 @@ protected String strip (String path, String suffix) return path.substring(0, path.length() - suffix.length()); } - protected void createFile (JarFile file, ZipEntry entry, File target) + protected void createFile (ZipFile file, ZipEntry entry, File target) { // create our copy buffer if necessary if (_buffer == null) { @@ -124,8 +121,7 @@ protected void createFile (JarFile file, ZipEntry entry, File target) } } - protected void patchFile (JarFile file, ZipEntry entry, - File appdir, String path) + protected void patchFile (ZipFile file, ZipEntry entry, File appdir, String path) { File target = new File(appdir, path); File patch = new File(appdir, entry.getName()); @@ -158,7 +154,7 @@ public void progress (int percent) { // now apply the patch to create the new target file patcher = new JarDiffPatcher(); - patcher.patchJar(otarget.getPath(), patch.getPath(), target, obs); + JarDiffPatcher.patchJar(otarget.getPath(), patch.getPath(), target, obs); } catch (IOException ioe) { if (patcher == null) { diff --git a/core/src/main/java/com/threerings/getdown/util/FileUtil.java b/core/src/main/java/com/threerings/getdown/util/FileUtil.java index ec9d8874..08f4ac43 100644 --- a/core/src/main/java/com/threerings/getdown/util/FileUtil.java +++ b/core/src/main/java/com/threerings/getdown/util/FileUtil.java @@ -5,10 +5,26 @@ package com.threerings.getdown.util; -import java.io.*; -import java.util.*; -import java.util.jar.*; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Pack200; import java.util.zip.GZIPInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import com.threerings.getdown.Log; import static com.threerings.getdown.Log.log; @@ -16,7 +32,7 @@ /** * File related utilities. */ -public class FileUtil +public final class FileUtil { /** * Gets the specified source file to the specified destination file by hook or crook. Windows @@ -104,7 +120,9 @@ public static List readLines (Reader in) { List lines = new ArrayList<>(); try (BufferedReader bin = new BufferedReader(in)) { - for (String line = null; (line = bin.readLine()) != null; lines.add(line)) {} + for (String line; (line = bin.readLine()) != null;) { + lines.add(line); + } } return lines; } @@ -114,28 +132,28 @@ public static List readLines (Reader in) * @param cleanExistingDirs if true, all files in all directories contained in {@code jar} will * be deleted prior to unpacking the jar. */ - public static void unpackJar (JarFile jar, File target, boolean cleanExistingDirs) - throws IOException + public static void unpackJar (ZipFile jar, File target, boolean cleanExistingDirs) throws IOException { if (cleanExistingDirs) { - Enumeration entries = jar.entries(); + Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { - JarEntry entry = (JarEntry)entries.nextElement(); + ZipEntry entry = entries.nextElement(); if (entry.isDirectory()) { File efile = new File(target, entry.getName()); if (efile.exists()) { for (File f : efile.listFiles()) { - if (!f.isDirectory()) - f.delete(); + if (!f.isDirectory()) { + f.delete(); + } } } } } } - Enumeration entries = jar.entries(); + Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { - JarEntry entry = (JarEntry)entries.nextElement(); + ZipEntry entry = entries.nextElement(); File efile = new File(target, entry.getName()); // if we're unpacking a normal jar file, it will have special path @@ -169,10 +187,10 @@ public static void unpackJar (JarFile jar, File target, boolean cleanExistingDir * Unpacks a pack200 packed jar file from {@code packedJar} into {@code target}. If {@code * packedJar} has a {@code .gz} extension, it will be gunzipped first. */ - public static void unpackPacked200Jar (File packedJar, File target) throws IOException + public static JarFile unpackPacked200Jar (File packedJar, File target) throws IOException { try (InputStream packJarIn = new FileInputStream(packedJar); - JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(target))) { + JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(target))) { boolean gz = (packedJar.getName().endsWith(".gz") || packedJar.getName().endsWith(".gz_new")); try (InputStream packJarIn2 = (gz ? new GZIPInputStream(packJarIn) : packJarIn)) { @@ -180,6 +198,7 @@ public static void unpackPacked200Jar (File packedJar, File target) throws IOExc unpacker.unpack(packJarIn2, jarOut); } } + return new JarFile(target); } /** From 4973da5e45ee16a9980c941595112e97130488cf Mon Sep 17 00:00:00 2001 From: sergiorussia <22471371+sergiorussia@users.noreply.github.com> Date: Sun, 5 May 2019 17:24:38 +0300 Subject: [PATCH 2/3] revert non-related changes, small fixes --- .../com/threerings/getdown/data/Resource.java | 32 ++++++++++------ .../com/threerings/getdown/tools/Differ.java | 13 ++++--- .../com/threerings/getdown/tools/JarDiff.java | 38 +++++++++++-------- .../getdown/tools/JarDiffPatcher.java | 27 +++++++------ .../com/threerings/getdown/tools/Patcher.java | 5 ++- .../com/threerings/getdown/util/FileUtil.java | 9 ++--- 6 files changed, 73 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/com/threerings/getdown/data/Resource.java b/core/src/main/java/com/threerings/getdown/data/Resource.java index e8f8f1db..78ca8446 100644 --- a/core/src/main/java/com/threerings/getdown/data/Resource.java +++ b/core/src/main/java/com/threerings/getdown/data/Resource.java @@ -62,17 +62,18 @@ public static String computeDigest (int version, File target, MessageDigest md, byte[] buffer = new byte[DIGEST_BUFFER_SIZE]; int read; - boolean isJar = isJar(target.getPath()); - boolean isPacked200Jar = isPacked200Jar(target.getPath()); + boolean isJar = isJar(target); + boolean isPacked200Jar = isPacked200Jar(target); // if this is a jar, we need to compute the digest in a "timestamp and file order" agnostic // manner to properly correlate jardiff patched jars with their unpatched originals if (isJar || isPacked200Jar){ + File tmpJarFile = null; ZipFile jar = null; try { // if this is a compressed jar file, uncompress it to compute the jar file digest if (isPacked200Jar){ - File tmpJarFile = new File(target.getPath() + ".tmp"); + tmpJarFile = new File(target.getPath() + ".tmp"); tmpJarFile.deleteOnExit(); jar = FileUtil.unpackPacked200Jar(target, tmpJarFile); } else{ @@ -109,6 +110,9 @@ public static String computeDigest (int version, File target, MessageDigest md, log.warning("Error closing jar", "path", target, "jar", jar, "error", ioe); } } + if (tmpJarFile != null) { + FileUtil.deleteHarder(tmpJarFile); + } } } else { @@ -133,12 +137,11 @@ public Resource (String path, URL remote, File local, EnumSet attrs) _remote = remote; _local = local; _localNew = new File(local.toString() + "_new"); - String lpath = _local.getPath(); - _marker = new File(lpath + "v"); + _marker = new File(_local.getPath() + "v"); _attrs = attrs; - _isJar = isJar(lpath); - _isPacked200Jar = isPacked200Jar(lpath); + _isJar = isJar(local); + _isPacked200Jar = isPacked200Jar(local); boolean unpack = attrs.contains(Attr.UNPACK); if (unpack && _isJar) { _unpacked = _local.getParentFile(); @@ -339,7 +342,11 @@ public void erase () @Override public boolean equals (Object other) { - return other instanceof Resource && _path.equals(((Resource) other)._path); + if (other instanceof Resource) { + return _path.equals(((Resource)other)._path); + } else { + return false; + } } @Override public int hashCode () @@ -360,13 +367,16 @@ protected static void updateProgress (ProgressObserver obs, long pos, long total } } - protected static boolean isJar (String path) + protected static boolean isJar (File file) { - return path.endsWith(".jar") || path.endsWith(".jar_new") || path.endsWith(".zip"); + String path = file.getName(); + return path.endsWith(".jar") || path.endsWith(".jar_new") || + path.endsWith(".zip") || path.endsWith(".zip_new"); } - protected static boolean isPacked200Jar (String path) + protected static boolean isPacked200Jar (File file) { + String path = file.getName(); return path.endsWith(".jar.pack") || path.endsWith(".jar.pack_new") || path.endsWith(".jar.pack.gz")|| path.endsWith(".jar.pack.gz_new"); } diff --git a/core/src/main/java/com/threerings/getdown/tools/Differ.java b/core/src/main/java/com/threerings/getdown/tools/Differ.java index 31a0f0ad..97a7d29b 100644 --- a/core/src/main/java/com/threerings/getdown/tools/Differ.java +++ b/core/src/main/java/com/threerings/getdown/tools/Differ.java @@ -88,8 +88,8 @@ public void createDiff (File nvdir, File ovdir, boolean verbose) } } - protected static void createPatch(File patch, ArrayList orsrcs, - ArrayList nrsrcs, boolean verbose) + protected void createPatch (File patch, ArrayList orsrcs, + ArrayList nrsrcs, boolean verbose) throws IOException { int version = Digest.VERSION; @@ -165,7 +165,8 @@ protected static void createPatch(File patch, ArrayList orsrcs, } } - protected static File rebuildJar(File target) throws IOException + protected File rebuildJar (File target) + throws IOException { File temp = File.createTempFile("differ", "jar"); try (ZipFile jar = new ZipFile(target); @@ -189,7 +190,8 @@ protected static File rebuildJar(File target) throws IOException return temp; } - protected static void jarDiff(File ofile, File nfile, ZipOutputStream jout) throws IOException + protected void jarDiff (File ofile, File nfile, ZipOutputStream jout) + throws IOException { JarDiff.createPatch(ofile.getPath(), nfile.getPath(), jout, false); } @@ -197,7 +199,8 @@ protected static void jarDiff(File ofile, File nfile, ZipOutputStream jout) thro public static void main (String[] args) { if (args.length < 2) { - System.err.println("Usage: Differ [-verbose] new_vers_dir old_vers_dir"); + System.err.println( + "Usage: Differ [-verbose] new_vers_dir old_vers_dir"); System.exit(255); } Differ differ = new Differ(); diff --git a/core/src/main/java/com/threerings/getdown/tools/JarDiff.java b/core/src/main/java/com/threerings/getdown/tools/JarDiff.java index 90ddf0cb..734fc9c1 100644 --- a/core/src/main/java/com/threerings/getdown/tools/JarDiff.java +++ b/core/src/main/java/com/threerings/getdown/tools/JarDiff.java @@ -74,16 +74,18 @@ public class JarDiff implements JarDiffCodes private static boolean _debug; /** - * Creates a patch from the two passed in files, writing the result to {@code os}. + * Creates a patch from the two passed in files, writing the result to os. */ public static void createPatch (String oldPath, String newPath, OutputStream os, boolean minimal) throws IOException { - try (JarFile2 oldJar = new JarFile2(oldPath); JarFile2 newJar = new JarFile2(newPath)) { - final Map moved = new HashMap<>(); - final Set implicit = new HashSet<>(); - final Set moveSrc = new HashSet<>(); - final Set newEntries = new HashSet<>(); + try (JarFile2 oldJar = new JarFile2(oldPath); + JarFile2 newJar = new JarFile2(newPath)) { + + HashMap moved = new HashMap<>(); + HashSet implicit = new HashSet<>(); + HashSet moveSrc = new HashSet<>(); + HashSet newEntries = new HashSet<>(); // FIRST PASS // Go through the entries in new jar and @@ -128,6 +130,7 @@ public static void createPatch (String oldPath, String newPath, // for backward compatibility if (_debug) { + System.out.println("NEW: "+ newname); } newEntries.add(newname); @@ -141,9 +144,12 @@ public static void createPatch (String oldPath, String newPath, } // Check if this disables an implicit 'move ' if (implicit.contains(oldname) && minimal) { + if (_debug) { System.err.println("implicit.remove " + oldname); + System.err.println("moved.put " + oldname + " " + oldname); + } implicit.remove(oldname); moved.put(oldname, oldname); @@ -155,7 +161,7 @@ public static void createPatch (String oldPath, String newPath, // SECOND PASS: = - - // - - final List deleted = new ArrayList<>(); + ArrayList deleted = new ArrayList<>(); for (ZipEntry oldEntry : oldJar) { String oldName = oldEntry.getName(); if (!implicit.contains(oldName) && !moveSrc.contains(oldName) @@ -201,11 +207,12 @@ public static void createPatch (String oldPath, String newPath, } /** - * Writes the index file out to {@code jos}. - * {@code oldEntries} gives the names of the files that were removed, - * {@code movedMap} maps from the new name to the old name. + * Writes the index file out to jos. + * oldEntries gives the names of the files that were removed, + * movedMap maps from the new name to the old name. */ - private static void createIndex (ZipOutputStream jos, List oldEntries, Map movedMap) + private static void createIndex (ZipOutputStream jos, List oldEntries, + Map movedMap) throws IOException { StringWriter writer = new StringWriter(); @@ -236,7 +243,7 @@ private static void createIndex (ZipOutputStream jos, List oldEntries, M jos.write(bytes, 0, bytes.length); } - protected static void writeEscapedString (Writer writer, String string) + protected static Writer writeEscapedString (Writer writer, String string) throws IOException { int index = 0; @@ -262,6 +269,7 @@ protected static void writeEscapedString (Writer writer, String string) writer.write(string); } + return writer; } private static void writeEntry (ZipOutputStream jos, ZipEntry entry, JarFile2 file) @@ -380,7 +388,7 @@ public boolean contains (JarFile2 f, ZipEntry e) throws IOException { public String hasSameContent (JarFile2 file, ZipEntry entry) throws IOException { String thisName = null; - Long crcL = entry.getCrc(); + Long crcL = Long.valueOf(entry.getCrc()); // check if this jar contains files with the passed in entry's crc if (_crcToEntryMap.containsKey(crcL)) { // get the Linked List with files with the crc @@ -415,7 +423,7 @@ private void index () throws IOException { while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); long crc = entry.getCrc(); - Long crcL = crc; + Long crcL = Long.valueOf(crc); if (_debug) { System.out.println("\t" + entry.getName() + " CRC " + crc); } @@ -432,7 +440,7 @@ private void index () throws IOException { } else { // create a new entry in the hashmap for the new key - LinkedList ll = new LinkedList(); + LinkedList ll = new LinkedList<>(); ll.add(entry); _crcToEntryMap.put(crcL, ll); } diff --git a/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java b/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java index af421736..859d73e0 100644 --- a/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java +++ b/core/src/main/java/com/threerings/getdown/tools/JarDiffPatcher.java @@ -41,22 +41,22 @@ public class JarDiffPatcher implements JarDiffCodes * * @throws IOException if any problem occurs during patching. */ - public static void patchJar(String jarPath, String diffPath, File target, ProgressObserver observer) + public void patchJar (String jarPath, String diffPath, File target, ProgressObserver observer) throws IOException { File oldFile = new File(jarPath), diffFile = new File(diffPath); try (ZipFile oldJar = new ZipFile(oldFile); ZipFile jarDiff = new ZipFile(diffFile); ZipOutputStream jos = new ZipOutputStream(new FileOutputStream(target))) { - final Set ignoreSet = new HashSet<>(); - final Map renameMap = new HashMap<>(); + Set ignoreSet = new HashSet<>(); + Map renameMap = new HashMap<>(); determineNameMapping(jarDiff, ignoreSet, renameMap); // get all keys in renameMap String[] keys = renameMap.keySet().toArray(new String[renameMap.size()]); // Files to implicit move - final Set oldjarNames = new HashSet<>(); + Set oldjarNames = new HashSet<>(); Enumeration oldEntries = oldJar.entries(); if (oldEntries != null) { while (oldEntries.hasMoreElements()) { @@ -111,7 +111,8 @@ public static void patchJar(String jarPath, String diffPath, File target, Progre // Get source ZipEntry ZipEntry oldEntry = oldJar.getEntry(oldName); if (oldEntry == null) { - throw new IOException("error.badmove: " + MOVE_COMMAND + oldName + " " + newName); + String moveCmd = MOVE_COMMAND + oldName + " " + newName; + throw new IOException("error.badmove: " + moveCmd); } // Create dest ZipEntry @@ -156,14 +157,14 @@ public static void patchJar(String jarPath, String diffPath, File target, Progre } } - protected static void updateObserver(ProgressObserver observer, double currentSize, double size) + protected void updateObserver (ProgressObserver observer, double currentSize, double size) { if (observer != null) { observer.progress((int)(100*currentSize/size)); } } - protected static void determineNameMapping( + protected void determineNameMapping ( ZipFile jarDiff, Set ignoreSet, Map renameMap) throws IOException { @@ -172,7 +173,8 @@ protected static void determineNameMapping( throw new IOException("error.noindex"); } - LineNumberReader indexReader = new LineNumberReader(new InputStreamReader(is, UTF_8)); + LineNumberReader indexReader = + new LineNumberReader(new InputStreamReader(is, UTF_8)); String line = indexReader.readLine(); if (line == null || !line.equals(VERSION_HEADER)) { throw new IOException("jardiff.error.badheader: " + line); @@ -207,11 +209,12 @@ protected static void determineNameMapping( } } - protected static List getSubpaths(String path) + protected List getSubpaths (String path) { int index = 0; int length = path.length(); - final List sub = new ArrayList<>(); + ArrayList sub = new ArrayList<>(); + while (index < length) { while (index < length && Character.isWhitespace (path.charAt(index))) { @@ -251,7 +254,7 @@ protected static List getSubpaths(String path) return sub; } - protected static void writeEntry(ZipOutputStream jos, ZipEntry entry, ZipFile file) + protected void writeEntry (ZipOutputStream jos, ZipEntry entry, ZipFile file) throws IOException { try (InputStream data = file.getInputStream(entry)) { @@ -259,7 +262,7 @@ protected static void writeEntry(ZipOutputStream jos, ZipEntry entry, ZipFile fi } } - protected static void writeEntry(ZipOutputStream jos, ZipEntry entry, InputStream data) + protected void writeEntry (ZipOutputStream jos, ZipEntry entry, InputStream data) throws IOException { jos.putNextEntry(new ZipEntry(entry.getName())); diff --git a/core/src/main/java/com/threerings/getdown/tools/Patcher.java b/core/src/main/java/com/threerings/getdown/tools/Patcher.java index 922ebb0a..fc394263 100644 --- a/core/src/main/java/com/threerings/getdown/tools/Patcher.java +++ b/core/src/main/java/com/threerings/getdown/tools/Patcher.java @@ -121,7 +121,8 @@ protected void createFile (ZipFile file, ZipEntry entry, File target) } } - protected void patchFile (ZipFile file, ZipEntry entry, File appdir, String path) + protected void patchFile (ZipFile file, ZipEntry entry, + File appdir, String path) { File target = new File(appdir, path); File patch = new File(appdir, entry.getName()); @@ -154,7 +155,7 @@ public void progress (int percent) { // now apply the patch to create the new target file patcher = new JarDiffPatcher(); - JarDiffPatcher.patchJar(otarget.getPath(), patch.getPath(), target, obs); + patcher.patchJar(otarget.getPath(), patch.getPath(), target, obs); } catch (IOException ioe) { if (patcher == null) { diff --git a/core/src/main/java/com/threerings/getdown/util/FileUtil.java b/core/src/main/java/com/threerings/getdown/util/FileUtil.java index 08f4ac43..06ac41ca 100644 --- a/core/src/main/java/com/threerings/getdown/util/FileUtil.java +++ b/core/src/main/java/com/threerings/getdown/util/FileUtil.java @@ -120,9 +120,7 @@ public static List readLines (Reader in) { List lines = new ArrayList<>(); try (BufferedReader bin = new BufferedReader(in)) { - for (String line; (line = bin.readLine()) != null;) { - lines.add(line); - } + for (String line = null; (line = bin.readLine()) != null; lines.add(line)) {} } return lines; } @@ -142,9 +140,8 @@ public static void unpackJar (ZipFile jar, File target, boolean cleanExistingDir File efile = new File(target, entry.getName()); if (efile.exists()) { for (File f : efile.listFiles()) { - if (!f.isDirectory()) { - f.delete(); - } + if (!f.isDirectory()) + f.delete(); } } } From 7cf4ce0b2f725fe0fce61e5c383d8fac6f6f70e8 Mon Sep 17 00:00:00 2001 From: sergiorussia <22471371+sergiorussia@users.noreply.github.com> Date: Sun, 5 May 2019 18:06:52 +0300 Subject: [PATCH 3/3] unit tests --- .../getdown/cache/GarbageCollector.java | 6 ++- .../com/threerings/getdown/data/Resource.java | 45 ++++++++++--------- .../getdown/cache/GarbageCollectorTest.java | 28 +++++++++--- .../getdown/cache/ResourceCacheTest.java | 30 ++++++++++--- 4 files changed, 76 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java b/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java index 67ea6457..ae189902 100644 --- a/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java +++ b/core/src/main/java/com/threerings/getdown/cache/GarbageCollector.java @@ -6,6 +6,8 @@ package com.threerings.getdown.cache; import java.io.File; + +import com.threerings.getdown.data.Resource; import com.threerings.getdown.util.FileUtil; /** @@ -55,9 +57,9 @@ public static void collectNative (File cacheDir, final long retentionPeriodMilli if (subdirs != null) { for (File dir : subdirs) { if (dir.isDirectory()) { - // Get all the native jars in the directory (there should only be one) + // Get all the native jars or zips in the directory (there should only be one) for (File file : dir.listFiles()) { - if (!file.getName().endsWith(".jar")) { + if (!Resource.isJar(file) && !Resource.isZip(file)) { continue; } File cachedFile = getCachedFile(file); diff --git a/core/src/main/java/com/threerings/getdown/data/Resource.java b/core/src/main/java/com/threerings/getdown/data/Resource.java index 78ca8446..b45e326d 100644 --- a/core/src/main/java/com/threerings/getdown/data/Resource.java +++ b/core/src/main/java/com/threerings/getdown/data/Resource.java @@ -62,25 +62,25 @@ public static String computeDigest (int version, File target, MessageDigest md, byte[] buffer = new byte[DIGEST_BUFFER_SIZE]; int read; - boolean isJar = isJar(target); + boolean isZip = isJar(target) || isZip(target); // jar is a zip too boolean isPacked200Jar = isPacked200Jar(target); // if this is a jar, we need to compute the digest in a "timestamp and file order" agnostic // manner to properly correlate jardiff patched jars with their unpatched originals - if (isJar || isPacked200Jar){ + if (isPacked200Jar || isZip){ File tmpJarFile = null; - ZipFile jar = null; + ZipFile zip = null; try { - // if this is a compressed jar file, uncompress it to compute the jar file digest + // if this is a compressed zip file, uncompress it to compute the zip file digest if (isPacked200Jar){ tmpJarFile = new File(target.getPath() + ".tmp"); tmpJarFile.deleteOnExit(); - jar = FileUtil.unpackPacked200Jar(target, tmpJarFile); + zip = FileUtil.unpackPacked200Jar(target, tmpJarFile); } else{ - jar = new ZipFile(target); + zip = new ZipFile(target); } - List entries = Collections.list(jar.entries()); + List entries = Collections.list(zip.entries()); Collections.sort(entries, ENTRY_COMP); int eidx = 0; @@ -93,7 +93,7 @@ public static String computeDigest (int version, File target, MessageDigest md, } } - try (InputStream in = jar.getInputStream(entry)) { + try (InputStream in = zip.getInputStream(entry)) { while ((read = in.read(buffer)) != -1) { md.update(buffer, 0, read); } @@ -103,11 +103,11 @@ public static String computeDigest (int version, File target, MessageDigest md, } } finally { - if (jar != null) { + if (zip != null) { try { - jar.close(); + zip.close(); } catch (IOException ioe) { - log.warning("Error closing jar", "path", target, "jar", jar, "error", ioe); + log.warning("Error closing zip", "path", target, "zip", zip, "error", ioe); } } if (tmpJarFile != null) { @@ -140,10 +140,10 @@ public Resource (String path, URL remote, File local, EnumSet attrs) _marker = new File(_local.getPath() + "v"); _attrs = attrs; - _isJar = isJar(local); + _isZip = isJar(local) || isZip(local); _isPacked200Jar = isPacked200Jar(local); boolean unpack = attrs.contains(Attr.UNPACK); - if (unpack && _isJar) { + if (unpack && _isZip) { _unpacked = _local.getParentFile(); } else if(unpack && _isPacked200Jar) { String dotJar = ".jar", lname = _local.getName(); @@ -299,10 +299,10 @@ public void install (boolean validate) throws IOException { public void unpack () throws IOException { // sanity check - if (!_isJar && !_isPacked200Jar) { + if (!_isZip && !_isPacked200Jar) { throw new IOException("Requested to unpack non-jar file '" + _local + "'."); } - if (_isJar) { + if (_isZip) { try (ZipFile jar = new ZipFile(_local)) { FileUtil.unpackJar(jar, _unpacked, _attrs.contains(Attr.CLEAN)); } @@ -367,25 +367,30 @@ protected static void updateProgress (ProgressObserver obs, long pos, long total } } - protected static boolean isJar (File file) + public static boolean isJar (File file) { String path = file.getName(); - return path.endsWith(".jar") || path.endsWith(".jar_new") || - path.endsWith(".zip") || path.endsWith(".zip_new"); + return path.endsWith(".jar") || path.endsWith(".jar_new"); } - protected static boolean isPacked200Jar (File file) + public static boolean isPacked200Jar (File file) { String path = file.getName(); return path.endsWith(".jar.pack") || path.endsWith(".jar.pack_new") || path.endsWith(".jar.pack.gz")|| path.endsWith(".jar.pack.gz_new"); } + public static boolean isZip (File file) + { + String path = file.getName(); + return path.endsWith(".zip") || path.endsWith(".zip_new"); + } + protected String _path; protected URL _remote; protected File _local, _localNew, _marker, _unpacked; protected EnumSet _attrs; - protected boolean _isJar, _isPacked200Jar; + protected boolean _isZip, _isPacked200Jar; /** Used to sort the entries in a jar file. */ protected static final Comparator ENTRY_COMP = new Comparator() { diff --git a/core/src/test/java/com/threerings/getdown/cache/GarbageCollectorTest.java b/core/src/test/java/com/threerings/getdown/cache/GarbageCollectorTest.java index d5a39374..6834ff96 100644 --- a/core/src/test/java/com/threerings/getdown/cache/GarbageCollectorTest.java +++ b/core/src/test/java/com/threerings/getdown/cache/GarbageCollectorTest.java @@ -7,23 +7,41 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; import java.util.concurrent.TimeUnit; -import org.junit.*; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; import org.junit.rules.TemporaryFolder; - -import static org.junit.Assert.*; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; /** * Validates that cache garbage is collected and deleted correctly. */ +@RunWith(Parameterized.class) public class GarbageCollectorTest { + @Parameterized.Parameters(name = "{0}") + public static Collection data() { + return Arrays.asList(new Object[][] { + { ".jar" }, + { ".zip" } + }); + } + + @Parameterized.Parameter + public String extension; + @Before public void setupFiles () throws IOException { - _cachedFile = _folder.newFile("abc123.jar"); - _lastAccessedFile = _folder.newFile("abc123.jar" + ResourceCache.LAST_ACCESSED_FILE_SUFFIX); + _cachedFile = _folder.newFile("abc123" + extension); + _lastAccessedFile = _folder.newFile("abc123" + extension + ResourceCache.LAST_ACCESSED_FILE_SUFFIX); } @Test public void shouldDeleteCacheEntryIfRetentionPeriodIsReached () diff --git a/core/src/test/java/com/threerings/getdown/cache/ResourceCacheTest.java b/core/src/test/java/com/threerings/getdown/cache/ResourceCacheTest.java index 860c72a3..93ad683a 100644 --- a/core/src/test/java/com/threerings/getdown/cache/ResourceCacheTest.java +++ b/core/src/test/java/com/threerings/getdown/cache/ResourceCacheTest.java @@ -7,26 +7,44 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; import java.util.concurrent.TimeUnit; -import org.junit.*; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; import org.junit.rules.TemporaryFolder; - -import static org.junit.Assert.*; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * Asserts the correct functionality of the {@link ResourceCache}. */ +@RunWith(Parameterized.class) public class ResourceCacheTest { + @Parameterized.Parameters(name = "{0}") + public static Collection data() { + return Arrays.asList(new Object[][] { + { ".jar" }, + { ".zip" } + }); + } + + @Parameterized.Parameter + public String extension; + @Before public void setupCache () throws IOException { - _fileToCache = _folder.newFile("filetocache.jar"); + _fileToCache = _folder.newFile("filetocache" + extension); _cache = new ResourceCache(_folder.newFolder(".cache")); } @Test public void shouldCacheFile () throws IOException { - assertEquals("abc123.jar", cacheFile().getName()); + assertEquals("abc123" + extension, cacheFile().getName()); } private File cacheFile() throws IOException @@ -36,7 +54,7 @@ private File cacheFile() throws IOException @Test public void shouldTrackFileUsage () throws IOException { - String name = "abc123.jar" + ResourceCache.LAST_ACCESSED_FILE_SUFFIX; + String name = "abc123" + extension + ResourceCache.LAST_ACCESSED_FILE_SUFFIX; File lastAccessedFile = new File(cacheFile().getParentFile(), name); assertTrue(lastAccessedFile.exists()); }