Clean up; close streams, readers (potential memory leaks)

This commit is contained in:
Stephen Neal
2015-06-23 13:47:27 +09:30
parent ae26c43a31
commit 1fa262cd49
5 changed files with 201 additions and 158 deletions
@@ -102,28 +102,34 @@ public class Digest
{ {
MessageDigest md = getMessageDigest(); MessageDigest md = getMessageDigest();
StringBuilder data = new StringBuilder(); StringBuilder data = new StringBuilder();
PrintWriter pout = new PrintWriter( PrintWriter pout = null;
new OutputStreamWriter(new FileOutputStream(output), "UTF-8")); try {
pout = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(output), "UTF-8"));
// compute and append the MD5 digest of each resource in the list // compute and append the MD5 digest of each resource in the list
for (Resource rsrc : resources) { for (Resource rsrc : resources) {
String path = rsrc.getPath(); String path = rsrc.getPath();
try { try {
String digest = rsrc.computeDigest(md, null); String digest = rsrc.computeDigest(md, null);
note(data, path, digest); note(data, path, digest);
pout.println(path + " = " + digest); pout.println(path + " = " + digest);
} catch (Throwable t) { } catch (Throwable t) {
throw (IOException) new IOException( throw (IOException) new IOException(
"Error computing digest for: " + rsrc).initCause(t); "Error computing digest for: " + rsrc).initCause(t);
}
}
// finally compute and append the digest for the file contents
md.reset();
byte[] contents = data.toString().getBytes("UTF-8");
pout.println(DIGEST_FILE + " = " + StringUtil.hexlate(md.digest(contents)));
} finally {
if (pout != null) {
pout.close();
} }
} }
// finally compute and append the digest for the file contents
md.reset();
byte[] contents = data.toString().getBytes("UTF-8");
pout.println(DIGEST_FILE + " = " + StringUtil.hexlate(md.digest(contents)));
pout.close();
} }
/** /**
@@ -20,6 +20,7 @@ import java.util.List;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import com.samskivert.io.StreamUtil;
import com.threerings.getdown.data.Application; import com.threerings.getdown.data.Application;
import com.threerings.getdown.data.Digest; import com.threerings.getdown.data.Digest;
import com.threerings.getdown.data.Resource; import com.threerings.getdown.data.Resource;
@@ -81,26 +82,36 @@ public class Digester
File inputFile = new File(appdir, Digest.DIGEST_FILE); File inputFile = new File(appdir, Digest.DIGEST_FILE);
File signatureFile = new File(appdir, Digest.DIGEST_FILE + Application.SIGNATURE_SUFFIX); File signatureFile = new File(appdir, Digest.DIGEST_FILE + Application.SIGNATURE_SUFFIX);
// initialize the keystore FileInputStream storeInput = null;
KeyStore store = KeyStore.getInstance("JKS"); FileInputStream dataInput = null;
FileInputStream storeInput = new FileInputStream(storePath); FileOutputStream signatureOutput = null;
store.load(storeInput, storePass.toCharArray()); try {
PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray()); // initialize the keystore
KeyStore store = KeyStore.getInstance("JKS");
storeInput = new FileInputStream(storePath);
store.load(storeInput, storePass.toCharArray());
PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray());
// sign the digest file // sign the digest file
Signature sig = Signature.getInstance("SHA1withRSA"); Signature sig = Signature.getInstance("SHA1withRSA");
FileInputStream dataInput = new FileInputStream(inputFile); dataInput = new FileInputStream(inputFile);
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
int length; int length;
sig.initSign(key);
while ((length = dataInput.read(buffer)) != -1) {
sig.update(buffer, 0, length);
}
sig.initSign(key); // Write out the signature
while ((length = dataInput.read(buffer)) != -1) { signatureOutput = new FileOutputStream(signatureFile);
sig.update(buffer, 0, length); String signed = new String(Base64.encodeBase64(sig.sign()));
signatureOutput.write(signed.getBytes("utf8"));
} finally {
StreamUtil.close(storeInput);
StreamUtil.close(dataInput);
StreamUtil.close(signatureOutput);
} }
// Write out the signature
FileOutputStream signatureOutput = new FileOutputStream(signatureFile);
String signed = new String(Base64.encodeBase64(sig.sign()));
signatureOutput.write(signed.getBytes("utf8"));
} }
} }
@@ -5,25 +5,25 @@
package com.threerings.getdown.tools; package com.threerings.getdown.tools;
import java.io.IOException;
import java.io.OutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Set; import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.Map;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.jar.JarFile;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import com.threerings.getdown.util.ProgressObserver; import com.threerings.getdown.util.ProgressObserver;
@@ -43,122 +43,130 @@ public class JarDiffPatcher implements JarDiffCodes
* *
* @throws IOException if any problem occurs during patching. * @throws IOException if any problem occurs during patching.
*/ */
public void patchJar (String jarPath, String diffPath, OutputStream target, public void patchJar (String jarPath, String diffPath, File target,
ProgressObserver observer) ProgressObserver observer)
throws IOException throws IOException
{ {
File oldFile = new File(jarPath); File oldFile = new File(jarPath);
File diffFile = new File(diffPath); File diffFile = new File(diffPath);
JarOutputStream jos = new JarOutputStream(target); JarOutputStream jos = null;
JarFile oldJar = new JarFile(oldFile); JarFile oldJar = null;
JarFile jarDiff = new JarFile(diffFile); JarFile jarDiff = null;
Set<String> ignoreSet = new HashSet<String>(); try {
jos = new JarOutputStream(new FileOutputStream(target));
oldJar = new JarFile(oldFile);
jarDiff = new JarFile(diffFile);
Set<String> ignoreSet = new HashSet<String>();
Map<String, String> renameMap = new HashMap<String, String>(); Map<String, String> renameMap = new HashMap<String, String>();
determineNameMapping(jarDiff, ignoreSet, renameMap); determineNameMapping(jarDiff, ignoreSet, renameMap);
// get all keys in renameMap // get all keys in renameMap
String[] keys = renameMap.keySet().toArray(new String[renameMap.size()]); String[] keys = renameMap.keySet().toArray(new String[renameMap.size()]);
// Files to implicit move // Files to implicit move
Set<String> oldjarNames = new HashSet<String>(); Set<String> oldjarNames = new HashSet<String>();
Enumeration<JarEntry> oldEntries = oldJar.entries(); Enumeration<JarEntry> oldEntries = oldJar.entries();
if (oldEntries != null) { if (oldEntries != null) {
while (oldEntries.hasMoreElements()) { while (oldEntries.hasMoreElements()) {
oldjarNames.add(oldEntries.nextElement().getName()); oldjarNames.add(oldEntries.nextElement().getName());
}
} }
}
// size depends on the three parameters below, which is basically the
// size depends on the three parameters below, which is basically the // counter for each loop that do the actual writes to the output file
// counter for each loop that do the actual writes to the output file // since oldjarNames.size() changes in the first two loop below, we
// since oldjarNames.size() changes in the first two loop below, we // need to adjust the size accordingly also when oldjarNames.size()
// need to adjust the size accordingly also when oldjarNames.size() // changes
// changes double size = oldjarNames.size() + keys.length + jarDiff.size();
double size = oldjarNames.size() + keys.length + jarDiff.size(); double currentEntry = 0;
double currentEntry = 0;
// Handle all remove commands
// Handle all remove commands oldjarNames.removeAll(ignoreSet);
oldjarNames.removeAll(ignoreSet); size -= ignoreSet.size();
size -= ignoreSet.size();
// Add content from JARDiff
// Add content from JARDiff Enumeration<JarEntry> entries = jarDiff.entries();
Enumeration<JarEntry> entries = jarDiff.entries(); if (entries != null) {
if (entries != null) { while (entries.hasMoreElements()) {
while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement();
JarEntry entry = entries.nextElement(); if (!INDEX_NAME.equals(entry.getName())) {
if (!INDEX_NAME.equals(entry.getName())) { updateObserver(observer, currentEntry, size);
updateObserver(observer, currentEntry, size); currentEntry++;
currentEntry++; writeEntry(jos, entry, jarDiff);
writeEntry(jos, entry, jarDiff);
// Remove entry from oldjarNames since no implicit move is
// Remove entry from oldjarNames since no implicit move is // needed
// needed boolean wasInOld = oldjarNames.remove(entry.getName());
boolean wasInOld = oldjarNames.remove(entry.getName());
// Update progress counters. If it was in old, we do not
// Update progress counters. If it was in old, we do not // need an implicit move, so adjust total size.
// need an implicit move, so adjust total size. if (wasInOld) {
if (wasInOld) { size--;
}
} else {
// no write is done, decrement size
size--; size--;
} }
}
} else { }
// no write is done, decrement size
// go through the renameMap and apply move for each entry
for (String newName : keys) {
// Apply move <oldName> <newName> command
String oldName = renameMap.get(newName);
// Get source JarEntry
JarEntry oldEntry = oldJar.getJarEntry(oldName);
if (oldEntry == null) {
String moveCmd = MOVE_COMMAND + oldName + " " + newName;
throw new IOException("error.badmove: " + moveCmd);
}
// Create dest JarEntry
JarEntry newEntry = new JarEntry(newName);
newEntry.setTime(oldEntry.getTime());
newEntry.setSize(oldEntry.getSize());
newEntry.setCompressedSize(oldEntry.getCompressedSize());
newEntry.setCrc(oldEntry.getCrc());
newEntry.setMethod(oldEntry.getMethod());
newEntry.setExtra(oldEntry.getExtra());
newEntry.setComment(oldEntry.getComment());
updateObserver(observer, currentEntry, size);
currentEntry++;
writeEntry(jos, newEntry, oldJar.getInputStream(oldEntry));
// Remove entry from oldjarNames since no implicit move is needed
boolean wasInOld = oldjarNames.remove(oldName);
// Update progress counters. If it was in old, we do not need an
// implicit move, so adjust total size.
if (wasInOld) {
size--; size--;
} }
} }
}
// implicit move
// go through the renameMap and apply move for each entry Iterator<String> iEntries = oldjarNames.iterator();
for (String newName : keys) { if (iEntries != null) {
// Apply move <oldName> <newName> command while (iEntries.hasNext()) {
String oldName = renameMap.get(newName); String name = iEntries.next();
JarEntry entry = oldJar.getJarEntry(name);
// Get source JarEntry updateObserver(observer, currentEntry, size);
JarEntry oldEntry = oldJar.getJarEntry(oldName); currentEntry++;
if (oldEntry == null) { writeEntry(jos, entry, oldJar);
String moveCmd = MOVE_COMMAND + oldName + " " + newName; }
throw new IOException("error.badmove: " + moveCmd);
} }
// Create dest JarEntry
JarEntry newEntry = new JarEntry(newName);
newEntry.setTime(oldEntry.getTime());
newEntry.setSize(oldEntry.getSize());
newEntry.setCompressedSize(oldEntry.getCompressedSize());
newEntry.setCrc(oldEntry.getCrc());
newEntry.setMethod(oldEntry.getMethod());
newEntry.setExtra(oldEntry.getExtra());
newEntry.setComment(oldEntry.getComment());
updateObserver(observer, currentEntry, size); updateObserver(observer, currentEntry, size);
currentEntry++;
writeEntry(jos, newEntry, oldJar.getInputStream(oldEntry)); } finally {
jos = closeStream(jos);
// Remove entry from oldjarNames since no implicit move is needed oldJar = closeFile(oldJar);
boolean wasInOld = oldjarNames.remove(oldName); jarDiff = closeFile(jarDiff);
// Update progress counters. If it was in old, we do not need an
// implicit move, so adjust total size.
if (wasInOld) {
size--;
}
} }
// implicit move
Iterator<String> iEntries = oldjarNames.iterator();
if (iEntries != null) {
while (iEntries.hasNext()) {
String name = iEntries.next();
JarEntry entry = oldJar.getJarEntry(name);
updateObserver(observer, currentEntry, size);
currentEntry++;
writeEntry(jos, entry, oldJar);
}
}
updateObserver(observer, currentEntry, size);
jos.finish();
} }
protected void updateObserver (ProgressObserver observer, protected void updateObserver (ProgressObserver observer,
@@ -281,7 +289,27 @@ public class JarDiffPatcher implements JarDiffCodes
data.close(); data.close();
} }
protected static final int DEFAULT_READ_SIZE = 2048; private static JarFile closeFile(JarFile jar) {
if (jar != null) {
try {
jar.close();
} catch (IOException e) {
}
}
return null;
}
private static JarOutputStream closeStream(JarOutputStream jar) {
if (jar != null) {
try {
jar.close();
} catch (IOException e) {
}
}
return null;
}
protected static final int DEFAULT_READ_SIZE = 2048;
protected static byte[] newBytes = new byte[DEFAULT_READ_SIZE]; protected static byte[] newBytes = new byte[DEFAULT_READ_SIZE];
protected static byte[] oldBytes = new byte[DEFAULT_READ_SIZE]; protected static byte[] oldBytes = new byte[DEFAULT_READ_SIZE];
@@ -149,8 +149,6 @@ public class Patcher
FileOutputStream fout = null; FileOutputStream fout = null;
try { try {
StreamUtil.copy(in = file.getInputStream(entry), fout = new FileOutputStream(patch)); StreamUtil.copy(in = file.getInputStream(entry), fout = new FileOutputStream(patch));
StreamUtil.close(fout);
fout = null;
// move the current version of the jar to .old // move the current version of the jar to .old
if (!FileUtil.renameTo(target, otarget)) { if (!FileUtil.renameTo(target, otarget)) {
@@ -168,8 +166,7 @@ public class Patcher
// now apply the patch to create the new target file // now apply the patch to create the new target file
patcher = new JarDiffPatcher(); patcher = new JarDiffPatcher();
fout = new FileOutputStream(target); patcher.patchJar(otarget.getPath(), patch.getPath(), target, obs);
patcher.patchJar(otarget.getPath(), patch.getPath(), fout, obs);
} catch (IOException ioe) { } catch (IOException ioe) {
if (patcher == null) { if (patcher == null) {
@@ -32,11 +32,10 @@ public class VersionUtil
*/ */
public static long readVersion (File vfile) public static long readVersion (File vfile)
{ {
FileInputStream fin = null;
long fileVersion = -1; long fileVersion = -1;
BufferedReader bin = null;
try { try {
fin = new FileInputStream(vfile); bin = new BufferedReader(new InputStreamReader(new FileInputStream(vfile)));
BufferedReader bin = new BufferedReader(new InputStreamReader(fin));
String vstr = bin.readLine(); String vstr = bin.readLine();
if (!StringUtil.isBlank(vstr)) { if (!StringUtil.isBlank(vstr)) {
fileVersion = Long.parseLong(vstr); fileVersion = Long.parseLong(vstr);
@@ -44,7 +43,7 @@ public class VersionUtil
} catch (Exception e) { } catch (Exception e) {
log.info("Unable to read version file: " + e.getMessage()); log.info("Unable to read version file: " + e.getMessage());
} finally { } finally {
StreamUtil.close(fin); StreamUtil.close(bin);
} }
return fileVersion; return fileVersion;
@@ -89,15 +88,15 @@ public class VersionUtil
*/ */
public static long readReleaseVersion (File relfile, String versRegex) public static long readReleaseVersion (File relfile, String versRegex)
{ {
BufferedReader in = null;
try { try {
BufferedReader in = new BufferedReader(new FileReader(relfile)); in = new BufferedReader(new FileReader(relfile));
String line = null, relvers = null; String line = null, relvers = null;
while ((line = in.readLine()) != null) { while ((line = in.readLine()) != null) {
if (line.startsWith("JAVA_VERSION=")) { if (line.startsWith("JAVA_VERSION=")) {
relvers = line.substring("JAVA_VERSION=".length()).replace('"', ' ').trim(); relvers = line.substring("JAVA_VERSION=".length()).replace('"', ' ').trim();
} }
} }
in.close();
if (relvers == null) { if (relvers == null) {
log.warning("No JAVA_VERSION line in 'release' file", "file", relfile); log.warning("No JAVA_VERSION line in 'release' file", "file", relfile);
@@ -108,6 +107,8 @@ public class VersionUtil
} catch (Exception e) { } catch (Exception e) {
log.warning("Failed to read version from 'release' file", "file", relfile, e); log.warning("Failed to read version from 'release' file", "file", relfile, e);
return 0L; return 0L;
} finally {
StreamUtil.close(in);
} }
} }