Use try-with-resources: in some cases, resources were not always being released; in others, behavior was correct and we are just simplifying code

This commit is contained in:
Daniel Gredler
2018-08-24 11:01:04 -04:00
parent 07412a792a
commit 44ae6d99d0
16 changed files with 273 additions and 406 deletions
@@ -1241,27 +1241,23 @@ public class Application
} }
if (_latest != null) { if (_latest != null) {
InputStream in = null; try (InputStream in = ConnectionUtil.open(_latest, 0, 0).getInputStream()) {
PrintStream out = null;
try {
in = ConnectionUtil.open(_latest, 0, 0).getInputStream();
BufferedReader bin = new BufferedReader(new InputStreamReader(in)); BufferedReader bin = new BufferedReader(new InputStreamReader(in));
for (String[] pair : Config.parsePairs(bin, Config.createOpts(false))) { for (String[] pair : Config.parsePairs(bin, Config.createOpts(false))) {
if (pair[0].equals("version")) { if (pair[0].equals("version")) {
_targetVersion = Math.max(Long.parseLong(pair[1]), _targetVersion); _targetVersion = Math.max(Long.parseLong(pair[1]), _targetVersion);
if (fileVersion != -1 && _targetVersion > fileVersion) { if (fileVersion != -1 && _targetVersion > fileVersion) {
// replace the file with the newest version // replace the file with the newest version
out = new PrintStream(new FileOutputStream(vfile)); try (FileOutputStream fos = new FileOutputStream(vfile);
out.println(_targetVersion); PrintStream out = new PrintStream(fos)) {
out.println(_targetVersion);
}
} }
break; break;
} }
} }
} catch (Exception e) { } catch (Exception e) {
log.warning("Unable to retrieve version from latest config file.", e); log.warning("Unable to retrieve version from latest config file.", e);
} finally {
StreamUtil.close(in);
StreamUtil.close(out);
} }
} }
} }
@@ -1567,21 +1563,16 @@ public class Application
} else { } else {
File signatureFile = downloadFile(path + SIGNATURE_SUFFIX); File signatureFile = downloadFile(path + SIGNATURE_SUFFIX);
byte[] signature = null; byte[] signature = null;
FileReader reader = null; try (FileReader reader = new FileReader(signatureFile)) {
try {
reader = new FileReader(signatureFile);
signature = StreamUtil.toByteArray(new FileInputStream(signatureFile)); signature = StreamUtil.toByteArray(new FileInputStream(signatureFile));
} finally { } finally {
StreamUtil.close(reader);
FileUtil.deleteHarder(signatureFile); // delete the file regardless FileUtil.deleteHarder(signatureFile); // delete the file regardless
} }
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
int length, validated = 0; int length, validated = 0;
for (Certificate cert : _signers) { for (Certificate cert : _signers) {
FileInputStream dataInput = null; try (FileInputStream dataInput = new FileInputStream(target)) {
try {
dataInput = new FileInputStream(target);
Signature sig = Signature.getInstance(Digest.sigAlgorithm(sigVersion)); Signature sig = Signature.getInstance(Digest.sigAlgorithm(sigVersion));
sig.initVerify(cert); sig.initVerify(cert);
while ((length = dataInput.read(buffer)) != -1) { while ((length = dataInput.read(buffer)) != -1) {
@@ -1602,9 +1593,6 @@ public class Application
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
// no problem! // no problem!
} finally {
StreamUtil.close(dataInput);
dataInput = null;
} }
} }
@@ -1645,27 +1633,22 @@ public class Application
log.info("Attempting to refetch '" + path + "' from '" + targetURL + "'."); log.info("Attempting to refetch '" + path + "' from '" + targetURL + "'.");
// stream the URL into our temporary file // stream the URL into our temporary file
InputStream fin = null; URLConnection uconn = ConnectionUtil.open(targetURL, 0, 0);
FileOutputStream fout = null; // we have to tell Java not to use caches here, otherwise it will cache any request for
try { // same URL for the lifetime of this JVM (based on the URL string, not the URL object);
URLConnection uconn = ConnectionUtil.open(targetURL, 0, 0); // if the getdown.txt file, for example, changes in the meanwhile, we would never hear
// we have to tell Java not to use caches here, otherwise it will cache any request for // about it; turning off caches is not a performance concern, because when Getdown asks
// same URL for the lifetime of this JVM (based on the URL string, not the URL object); // to download a file, it expects it to come over the wire, not from a cache
// if the getdown.txt file, for example, changes in the meanwhile, we would never hear uconn.setUseCaches(false);
// about it; turning off caches is not a performance concern, because when Getdown asks uconn.setRequestProperty("Accept-Encoding", "gzip");
// to download a file, it expects it to come over the wire, not from a cache try (InputStream fin = uconn.getInputStream()) {
uconn.setUseCaches(false);
uconn.setRequestProperty("Accept-Encoding", "gzip");
fin = uconn.getInputStream();
String encoding = uconn.getContentEncoding(); String encoding = uconn.getContentEncoding();
if ("gzip".equalsIgnoreCase(encoding)) { boolean gzip = "gzip".equalsIgnoreCase(encoding);
fin = new GZIPInputStream(fin); try (InputStream fin2 = (gzip ? new GZIPInputStream(fin) : fin)) {
try (FileOutputStream fout = new FileOutputStream(target)) {
StreamUtil.copy(fin2, fout);
}
} }
fout = new FileOutputStream(target);
StreamUtil.copy(fin, fout);
} finally {
StreamUtil.close(fin);
StreamUtil.close(fout);
} }
return target; return target;
@@ -6,12 +6,12 @@
package com.threerings.getdown.data; package com.threerings.getdown.data;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import com.samskivert.io.StreamUtil;
import com.samskivert.text.MessageUtil; import com.samskivert.text.MessageUtil;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
@@ -99,9 +99,9 @@ public class Digest
} }
StringBuilder data = new StringBuilder(); StringBuilder data = new StringBuilder();
PrintWriter pout = null; try (FileOutputStream fos = new FileOutputStream(output);
try { OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
pout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), "UTF-8")); PrintWriter pout = new PrintWriter(osw)) {
// compute and append the digest of each resource in the list // compute and append the digest of each resource in the list
for (Resource rsrc : resources) { for (Resource rsrc : resources) {
String path = rsrc.getPath(); String path = rsrc.getPath();
@@ -114,9 +114,6 @@ public class Digest
byte[] contents = data.toString().getBytes("UTF-8"); byte[] contents = data.toString().getBytes("UTF-8");
String filename = digestFile(version); String filename = digestFile(version);
pout.println(filename + " = " + StringUtil.hexlate(md.digest(contents))); pout.println(filename + " = " + StringUtil.hexlate(md.digest(contents)));
} finally {
StreamUtil.close(pout);
} }
long elapsed = System.currentTimeMillis() - start; long elapsed = System.currentTimeMillis() - start;
@@ -15,7 +15,6 @@ import java.util.List;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import com.samskivert.io.StreamUtil;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.getdown.util.FileUtil; import com.threerings.getdown.util.FileUtil;
@@ -83,15 +82,12 @@ public class Resource implements Comparable<Resource>
} }
} }
InputStream in = null; try (InputStream in = jar.getInputStream(entry)) {
try {
in = jar.getInputStream(entry);
while ((read = in.read(buffer)) != -1) { while ((read = in.read(buffer)) != -1) {
md.update(buffer, 0, read); md.update(buffer, 0, read);
} }
} finally {
StreamUtil.close(in);
} }
updateProgress(obs, eidx, entries.size()); updateProgress(obs, eidx, entries.size());
} }
@@ -110,16 +106,12 @@ public class Resource implements Comparable<Resource>
} else { } else {
long totalSize = target.length(), position = 0L; long totalSize = target.length(), position = 0L;
FileInputStream fin = null; try (FileInputStream fin = new FileInputStream(target)) {
try {
fin = new FileInputStream(target);
while ((read = fin.read(buffer)) != -1) { while ((read = fin.read(buffer)) != -1) {
md.update(buffer, 0, read); md.update(buffer, 0, read);
position += read; position += read;
updateProgress(obs, position, totalSize); updateProgress(obs, position, totalSize);
} }
} finally {
StreamUtil.close(fin);
} }
} }
return StringUtil.hexlate(md.digest()); return StringUtil.hexlate(md.digest());
@@ -282,8 +274,10 @@ public class Resource implements Comparable<Resource>
throw new IOException("Requested to unpack non-jar file '" + _local + "'."); throw new IOException("Requested to unpack non-jar file '" + _local + "'.");
} }
if (_isJar) { if (_isJar) {
FileUtil.unpackJar(new JarFile(_local), _unpacked); try (JarFile jar = new JarFile(_local)) {
} else{ FileUtil.unpackJar(jar, _unpacked);
}
} else {
FileUtil.unpackPacked200Jar(_local, _unpacked); FileUtil.unpackPacked200Jar(_local, _unpacked);
} }
} }
@@ -229,13 +229,11 @@ public abstract class Getdown extends Thread
// if we're provided with valid values, create a proxy.txt file // if we're provided with valid values, create a proxy.txt file
if (!StringUtil.isBlank(host)) { if (!StringUtil.isBlank(host)) {
File pfile = _app.getLocalPath("proxy.txt"); File pfile = _app.getLocalPath("proxy.txt");
try { try (PrintStream pout = new PrintStream(new FileOutputStream(pfile))) {
PrintStream pout = new PrintStream(new FileOutputStream(pfile));
pout.println("host = " + host); pout.println("host = " + host);
if (!StringUtil.isBlank(port)) { if (!StringUtil.isBlank(port)) {
pout.println("port = " + port); pout.println("port = " + port);
} }
pout.close();
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Error creating proxy file '" + pfile + "': " + ioe); log.warning("Error creating proxy file '" + pfile + "': " + ioe);
} }
@@ -570,6 +568,7 @@ public abstract class Getdown extends Thread
} }
// documentation inherited from interface // documentation inherited from interface
@Override
public void updateStatus (String message) public void updateStatus (String message)
{ {
setStatusAsync(message, -1, -1L, true); setStatusAsync(message, -1, -1L, true);
@@ -580,6 +579,7 @@ public abstract class Getdown extends Thread
* if we can find a localized version by sticking a {@code _<language>} in front of the "." in * if we can find a localized version by sticking a {@code _<language>} in front of the "." in
* the filename. * the filename.
*/ */
@Override
public BufferedImage loadImage (String path) public BufferedImage loadImage (String path)
{ {
if (StringUtil.isBlank(path)) { if (StringUtil.isBlank(path)) {
@@ -92,11 +92,9 @@ public class GetdownApp
File crtFile = new File(appDir, Digest.digestFile(Digest.VERSION) + ".crt"); File crtFile = new File(appDir, Digest.digestFile(Digest.VERSION) + ".crt");
List<Certificate> crts = new ArrayList<>(); List<Certificate> crts = new ArrayList<>();
if (crtFile.exists()) { if (crtFile.exists()) {
try { try (FileInputStream fis = new FileInputStream(crtFile)) {
FileInputStream fis = new FileInputStream(crtFile);
X509Certificate certificate = (X509Certificate) X509Certificate certificate = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(fis); CertificateFactory.getInstance("X.509").generateCertificate(fis);
fis.close();
crts.add(certificate); crts.add(certificate);
} catch (Exception e) { } catch (Exception e) {
log.warning("Certificate error: " + e.getMessage()); log.warning("Certificate error: " + e.getMessage());
@@ -233,6 +233,7 @@ public class GetdownApplet extends JApplet
} }
// implemented from ImageLoader // implemented from ImageLoader
@Override
public Image loadImage (String path) public Image loadImage (String path)
{ {
try { try {
@@ -293,10 +294,9 @@ public class GetdownApplet extends JApplet
*/ */
protected boolean writeToFile (File tofile, String contents) protected boolean writeToFile (File tofile, String contents)
{ {
try { try (FileOutputStream fos = new FileOutputStream(tofile);
PrintStream out = new PrintStream(new FileOutputStream(tofile)); PrintStream out = new PrintStream(fos)) {
out.println(contents); out.println(contents);
out.close();
return true; return true;
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failed to create '" + tofile + "'.", ioe); log.warning("Failed to create '" + tofile + "'.", ioe);
@@ -311,11 +311,8 @@ public class GetdownApplet extends JApplet
if (keyUrl == null) { if (keyUrl == null) {
return null; return null;
} }
InputStream is = keyUrl.openStream(); try (InputStream is = keyUrl.openStream()) {
try {
return CertificateFactory.getInstance("X.509").generateCertificate(is); return CertificateFactory.getInstance("X.509").generateCertificate(is);
} finally {
is.close();
} }
} catch (CertificateException e) { } catch (CertificateException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -394,10 +394,9 @@ public class GetdownAppletConfig
*/ */
protected boolean writeToFile (File tofile, String contents) protected boolean writeToFile (File tofile, String contents)
{ {
try { try (FileOutputStream fos = new FileOutputStream(tofile);
PrintStream out = new PrintStream(new FileOutputStream(tofile)); PrintStream out = new PrintStream(fos)) {
out.println(contents); out.println(contents);
out.close();
return true; return true;
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failed to create '" + tofile + "'.", ioe); log.warning("Failed to create '" + tofile + "'.", ioe);
@@ -12,10 +12,7 @@ import java.net.HttpURLConnection;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.Collection; import java.util.Collection;
import com.samskivert.io.StreamUtil;
import com.threerings.getdown.data.Resource; import com.threerings.getdown.data.Resource;
import com.threerings.getdown.data.SysProps;
import com.threerings.getdown.util.ConnectionUtil; import com.threerings.getdown.util.ConnectionUtil;
import static com.threerings.getdown.Log.log; import static com.threerings.getdown.Log.log;
@@ -74,19 +71,16 @@ public class HTTPDownloader extends Downloader
long actualSize = conn.getContentLength(); long actualSize = conn.getContentLength();
log.info("Downloading resource", "url", rsrc.getRemote(), "size", actualSize); log.info("Downloading resource", "url", rsrc.getRemote(), "size", actualSize);
InputStream in = null;
FileOutputStream out = null;
long currentSize = 0L; long currentSize = 0L;
try { try (InputStream in = conn.getInputStream();
in = conn.getInputStream(); FileOutputStream out = new FileOutputStream(rsrc.getLocalNew())) {
out = new FileOutputStream(rsrc.getLocalNew());
int read;
// TODO: look to see if we have a download info file // TODO: look to see if we have a download info file
// containing info on potentially partially downloaded data; // containing info on potentially partially downloaded data;
// if so, use a "Range: bytes=HAVE-" header. // if so, use a "Range: bytes=HAVE-" header.
// read in the file data // read in the file data
int read;
while ((read = in.read(_buffer)) != -1) { while ((read = in.read(_buffer)) != -1) {
// write it out to our local copy // write it out to our local copy
out.write(_buffer, 0, read); out.write(_buffer, 0, read);
@@ -100,9 +94,6 @@ public class HTTPDownloader extends Downloader
currentSize += read; currentSize += read;
updateObserver(rsrc, currentSize, actualSize); updateObserver(rsrc, currentSize, actualSize);
} }
} finally {
StreamUtil.close(in);
StreamUtil.close(out);
} }
} }
} }
@@ -96,10 +96,9 @@ public class Differ
{ {
int version = Digest.VERSION; int version = Digest.VERSION;
MessageDigest md = Digest.getMessageDigest(version); MessageDigest md = Digest.getMessageDigest(version);
JarOutputStream jout = null; try (FileOutputStream fos = new FileOutputStream(patch);
try { BufferedOutputStream buffered = new BufferedOutputStream(fos);
jout = new JarOutputStream( JarOutputStream jout = new JarOutputStream(buffered)) {
new BufferedOutputStream(new FileOutputStream(patch)));
// for each file in the new application, it either already exists // for each file in the new application, it either already exists
// in the old application, or it is new // in the old application, or it is new
@@ -160,11 +159,9 @@ public class Differ
jout.putNextEntry(new ZipEntry(rsrc.getPath() + Patcher.DELETE)); jout.putNextEntry(new ZipEntry(rsrc.getPath() + Patcher.DELETE));
} }
StreamUtil.close(jout);
System.out.println("Created patch file: " + patch); System.out.println("Created patch file: " + patch);
} catch (IOException ioe) { } catch (IOException ioe) {
StreamUtil.close(jout);
patch.delete(); patch.delete();
throw ioe; throw ioe;
} }
@@ -173,25 +170,25 @@ public class Differ
protected File rebuildJar (File target) protected File rebuildJar (File target)
throws IOException throws IOException
{ {
JarFile jar = new JarFile(target);
File temp = File.createTempFile("differ", "jar"); File temp = File.createTempFile("differ", "jar");
JarOutputStream jout = new JarOutputStream( try (JarFile jar = new JarFile(target);
new BufferedOutputStream(new FileOutputStream(temp))); FileOutputStream tempFos = new FileOutputStream(temp);
byte[] buffer = new byte[4096]; BufferedOutputStream tempBos = new BufferedOutputStream(tempFos);
for (Enumeration<JarEntry> iter = jar.entries(); iter.hasMoreElements(); ) { JarOutputStream jout = new JarOutputStream(tempBos)) {
JarEntry entry = iter.nextElement(); byte[] buffer = new byte[4096];
entry.setCompressedSize(-1); for (Enumeration< JarEntry > iter = jar.entries(); iter.hasMoreElements();) {
jout.putNextEntry(entry); JarEntry entry = iter.nextElement();
InputStream in = jar.getInputStream(entry); entry.setCompressedSize(-1);
int size = in.read(buffer); jout.putNextEntry(entry);
while (size != -1) { try (InputStream in = jar.getInputStream(entry)) {
jout.write(buffer, 0, size); int size = in.read(buffer);
size = in.read(buffer); while (size != -1) {
jout.write(buffer, 0, size);
size = in.read(buffer);
}
}
} }
in.close();
} }
jout.close();
jar.close();
return temp; return temp;
} }
@@ -227,11 +224,8 @@ public class Differ
protected static void pipe (File file, JarOutputStream jout) protected static void pipe (File file, JarOutputStream jout)
throws IOException throws IOException
{ {
FileInputStream fin = null; try (FileInputStream fin = new FileInputStream(file)) {
try { StreamUtil.copy(fin, jout);
StreamUtil.copy(fin = new FileInputStream(file), jout);
} finally {
StreamUtil.close(fin);
} }
} }
} }
@@ -18,7 +18,6 @@ import java.security.Signature;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
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;
@@ -99,19 +98,18 @@ public class Digester
File inputFile = new File(appdir, filename); File inputFile = new File(appdir, filename);
File signatureFile = new File(appdir, filename + Application.SIGNATURE_SUFFIX); File signatureFile = new File(appdir, filename + Application.SIGNATURE_SUFFIX);
FileInputStream storeInput = null, dataInput = null; try (FileInputStream storeInput = new FileInputStream(storePath);
FileOutputStream signatureOutput = null; FileInputStream dataInput = new FileInputStream(inputFile);
try { FileOutputStream signatureOutput = new FileOutputStream(signatureFile)) {
// initialize the keystore // initialize the keystore
KeyStore store = KeyStore.getInstance("JKS"); KeyStore store = KeyStore.getInstance("JKS");
storeInput = new FileInputStream(storePath);
store.load(storeInput, storePass.toCharArray()); store.load(storeInput, storePass.toCharArray());
PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray()); PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray());
// sign the digest file // sign the digest file
String algo = Digest.sigAlgorithm(version); String algo = Digest.sigAlgorithm(version);
Signature sig = Signature.getInstance(algo); Signature sig = Signature.getInstance(algo);
dataInput = new FileInputStream(inputFile);
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
int length; int length;
@@ -121,14 +119,8 @@ public class Digester
} }
// Write out the signature // Write out the signature
signatureOutput = new FileOutputStream(signatureFile);
String signed = Base64.encodeToString(sig.sign(), Base64.DEFAULT); String signed = Base64.encodeToString(sig.sign(), Base64.DEFAULT);
signatureOutput.write(signed.getBytes("utf8")); signatureOutput.write(signed.getBytes("utf8"));
} finally {
StreamUtil.close(signatureOutput);
StreamUtil.close(dataInput);
StreamUtil.close(storeInput);
} }
} }
} }
@@ -41,9 +41,25 @@
package com.threerings.getdown.tools; package com.threerings.getdown.tools;
import java.io.*; import java.io.Closeable;
import java.util.*; import java.io.File;
import java.util.jar.*; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
/** /**
* JarDiff is able to create a jar file containing the delta between two jar files (old and new). * JarDiff is able to create a jar file containing the delta between two jar files (old and new).
@@ -69,10 +85,9 @@ public class JarDiff implements JarDiffCodes
public static void createPatch (String oldPath, String newPath, public static void createPatch (String oldPath, String newPath,
OutputStream os, boolean minimal) throws IOException OutputStream os, boolean minimal) throws IOException
{ {
JarFile2 oldJar = new JarFile2(oldPath); try (JarFile2 oldJar = new JarFile2(oldPath);
JarFile2 newJar = new JarFile2(newPath); JarFile2 newJar = new JarFile2(newPath)) {
try {
HashMap<String,String> moved = new HashMap<>(); HashMap<String,String> moved = new HashMap<>();
HashSet<String> implicit = new HashSet<>(); HashSet<String> implicit = new HashSet<>();
HashSet<String> moveSrc = new HashSet<>(); HashSet<String> moveSrc = new HashSet<>();
@@ -194,21 +209,7 @@ public class JarDiff implements JarDiffCodes
jos.finish(); jos.finish();
// jos.close(); // jos.close();
}
} catch (IOException ioE){
throw ioE;
} finally {
try {
oldJar.getJarFile().close();
} catch (IOException e1) {
//ignore
}
try {
newJar.getJarFile().close();
} catch (IOException e1) {
//ignore
}
} // finally
} }
/** /**
@@ -220,36 +221,36 @@ public class JarDiff implements JarDiffCodes
Map<String,String> movedMap) Map<String,String> movedMap)
throws IOException throws IOException
{ {
StringWriter writer = new StringWriter(); try (StringWriter writer = new StringWriter()) {
writer.write(VERSION_HEADER); writer.write(VERSION_HEADER);
writer.write("\r\n");
// Write out entries that have been removed
for (String name : oldEntries) {
writer.write(REMOVE_COMMAND);
writer.write(" ");
writeEscapedString(writer, name);
writer.write("\r\n"); writer.write("\r\n");
// Write out entries that have been removed
for (String name : oldEntries) {
writer.write(REMOVE_COMMAND);
writer.write(" ");
writeEscapedString(writer, name);
writer.write("\r\n");
}
// And those that have moved
for (String newName : movedMap.keySet()) {
String oldName = movedMap.get(newName);
writer.write(MOVE_COMMAND);
writer.write(" ");
writeEscapedString(writer, oldName);
writer.write(" ");
writeEscapedString(writer, newName);
writer.write("\r\n");
}
JarEntry je = new JarEntry(INDEX_NAME);
byte[] bytes = writer.toString().getBytes("UTF-8");
jos.putNextEntry(je);
jos.write(bytes, 0, bytes.length);
} }
// And those that have moved
for (String newName : movedMap.keySet()) {
String oldName = movedMap.get(newName);
writer.write(MOVE_COMMAND);
writer.write(" ");
writeEscapedString(writer, oldName);
writer.write(" ");
writeEscapedString(writer, newName);
writer.write("\r\n");
}
JarEntry je = new JarEntry(INDEX_NAME);
byte[] bytes = writer.toString().getBytes("UTF-8");
writer.close();
jos.putNextEntry(je);
jos.write(bytes, 0, bytes.length);
} }
private static void writeEscapedString (Writer writer, String string) private static void writeEscapedString (Writer writer, String string)
@@ -282,7 +283,9 @@ public class JarDiff implements JarDiffCodes
private static void writeEntry (JarOutputStream jos, JarEntry entry, JarFile2 file) private static void writeEntry (JarOutputStream jos, JarEntry entry, JarFile2 file)
throws IOException throws IOException
{ {
writeEntry(jos, entry, file.getJarFile().getInputStream(entry)); try (InputStream data = file.getJarFile().getInputStream(entry)) {
writeEntry(jos, entry, data);
}
} }
private static void writeEntry (JarOutputStream jos, JarEntry entry, InputStream data) private static void writeEntry (JarOutputStream jos, JarEntry entry, InputStream data)
@@ -290,30 +293,19 @@ public class JarDiff implements JarDiffCodes
{ {
jos.putNextEntry(entry); jos.putNextEntry(entry);
try { // Read the entry
// Read the entry int size = data.read(newBytes);
int size = data.read(newBytes);
while (size != -1) {
jos.write(newBytes, 0, size);
size = data.read(newBytes);
}
} catch(IOException ioE) {
throw ioE;
} finally {
try {
data.close();
} catch(IOException e){
//Ignore
}
while (size != -1) {
jos.write(newBytes, 0, size);
size = data.read(newBytes);
} }
} }
/** /**
* JarFile2 wraps a JarFile providing some convenience methods. * JarFile2 wraps a JarFile providing some convenience methods.
*/ */
private static class JarFile2 implements Iterable<JarEntry> private static class JarFile2 implements Iterable<JarEntry>, Closeable
{ {
private JarFile _jar; private JarFile _jar;
private List<JarEntry> _entries; private List<JarEntry> _entries;
@@ -330,6 +322,7 @@ public class JarDiff implements JarDiffCodes
} }
// from interface Iterable<JarEntry> // from interface Iterable<JarEntry>
@Override
public Iterator<JarEntry> iterator () { public Iterator<JarEntry> iterator () {
return _entries.iterator(); return _entries.iterator();
} }
@@ -347,52 +340,38 @@ public class JarDiff implements JarDiffCodes
int total = 0; int total = 0;
boolean retVal = false; boolean retVal = false;
try{ while (newSize != -1) {
while (newSize != -1) { newSize = newIS.read(newBytes);
newSize = newIS.read(newBytes); oldSize = oldIS.read(oldBytes);
oldSize = oldIS.read(oldBytes);
if (newSize != oldSize) { if (newSize != oldSize) {
if (_debug) { if (_debug) {
System.out.println("\tread sizes differ: " + newSize + System.out.println("\tread sizes differ: " + newSize +
" " + oldSize + " total " + total); " " + oldSize + " total " + total);
}
retVal = true;
break;
} }
if (newSize > 0) { retVal = true;
while (--newSize >= 0) { break;
total++; }
if (newBytes[newSize] != oldBytes[newSize]) { if (newSize > 0) {
if (_debug) { while (--newSize >= 0) {
System.out.println("\tbytes differ at " + total++;
total); if (newBytes[newSize] != oldBytes[newSize]) {
} if (_debug) {
retVal = true; System.out.println("\tbytes differ at " +
break; total);
} }
if ( retVal ) { retVal = true;
//Jump out break;
break;
}
newSize = 0;
} }
if ( retVal ) {
//Jump out
break;
}
newSize = 0;
} }
} }
} catch(IOException ioE){
throw ioE;
} finally {
try {
oldIS.close();
} catch(IOException e){
//Ignore
}
try {
newIS.close();
} catch(IOException e){
//Ignore
}
} }
return retVal; return retVal;
} }
@@ -419,11 +398,10 @@ public class JarDiff implements JarDiffCodes
return false; return false;
// Check contents - if no match - return false // Check contents - if no match - return false
InputStream oldIS = getJarFile().getInputStream(thisEntry); try (InputStream oldIS = getJarFile().getInputStream(thisEntry);
InputStream newIS = f.getJarFile().getInputStream(e); InputStream newIS = f.getJarFile().getInputStream(e)) {
boolean retValue = differs(oldIS, newIS); return !differs(oldIS, newIS);
}
return !retValue;
} }
public String hasSameContent (JarFile2 file, JarEntry entry) throws IOException { public String hasSameContent (JarFile2 file, JarEntry entry) throws IOException {
@@ -438,11 +416,12 @@ public class JarDiff implements JarDiffCodes
while (li.hasNext()) { while (li.hasNext()) {
JarEntry thisEntry = li.next(); JarEntry thisEntry = li.next();
// check for content match // check for content match
InputStream oldIS = getJarFile().getInputStream(thisEntry); try (InputStream oldIS = getJarFile().getInputStream(thisEntry);
InputStream newIS = file.getJarFile().getInputStream(entry); InputStream newIS = file.getJarFile().getInputStream(entry)) {
if (!differs(oldIS, newIS)) { if (!differs(oldIS, newIS)) {
thisName = thisEntry.getName(); thisName = thisEntry.getName();
return thisName; return thisName;
}
} }
} }
} }
@@ -486,5 +465,10 @@ public class JarDiff implements JarDiffCodes
} }
} }
} }
@Override
public void close() throws IOException {
_jar.close();
}
} }
} }
@@ -25,7 +25,6 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import com.samskivert.io.StreamUtil;
import com.threerings.getdown.util.ProgressObserver; import com.threerings.getdown.util.ProgressObserver;
/** /**
@@ -48,14 +47,13 @@ public class JarDiffPatcher implements JarDiffCodes
throws IOException throws IOException
{ {
File oldFile = new File(jarPath), diffFile = new File(diffPath); File oldFile = new File(jarPath), diffFile = new File(diffPath);
JarOutputStream jos = null;
JarFile oldJar = null, jarDiff = null;
try {
jos = new JarOutputStream(new FileOutputStream(target));
oldJar = new JarFile(oldFile);
jarDiff = new JarFile(diffFile);
Set<String> ignoreSet = new HashSet<>();
try (JarFile oldJar = new JarFile(oldFile);
JarFile jarDiff = new JarFile(diffFile);
FileOutputStream fos = new FileOutputStream(target);
JarOutputStream jos = new JarOutputStream(fos)) {
Set<String> ignoreSet = new HashSet<>();
Map<String, String> renameMap = new HashMap<>(); Map<String, String> renameMap = new HashMap<>();
determineNameMapping(jarDiff, ignoreSet, renameMap); determineNameMapping(jarDiff, ignoreSet, renameMap);
@@ -135,7 +133,9 @@ public class JarDiffPatcher implements JarDiffCodes
updateObserver(observer, currentEntry, size); updateObserver(observer, currentEntry, size);
currentEntry++; currentEntry++;
writeEntry(jos, newEntry, oldJar.getInputStream(oldEntry)); try (InputStream data = oldJar.getInputStream(oldEntry)) {
writeEntry(jos, newEntry, data);
}
// Remove entry from oldjarNames since no implicit move is needed // Remove entry from oldjarNames since no implicit move is needed
boolean wasInOld = oldjarNames.remove(oldName); boolean wasInOld = oldjarNames.remove(oldName);
@@ -159,11 +159,6 @@ public class JarDiffPatcher implements JarDiffCodes
} }
} }
updateObserver(observer, currentEntry, size); updateObserver(observer, currentEntry, size);
} finally {
StreamUtil.close(jos);
closeFile(oldJar);
closeFile(jarDiff);
} }
} }
@@ -268,7 +263,9 @@ public class JarDiffPatcher implements JarDiffCodes
JarOutputStream jos, JarEntry entry, JarFile file) JarOutputStream jos, JarEntry entry, JarFile file)
throws IOException throws IOException
{ {
writeEntry(jos, entry, file.getInputStream(entry)); try (InputStream data = file.getInputStream(entry)) {
writeEntry(jos, entry, data);
}
} }
protected void writeEntry ( protected void writeEntry (
@@ -283,17 +280,6 @@ public class JarDiffPatcher implements JarDiffCodes
jos.write(newBytes, 0, size); jos.write(newBytes, 0, size);
size = data.read(newBytes); size = data.read(newBytes);
} }
data.close();
}
private static void closeFile (JarFile jar) {
if (jar != null) {
try {
jar.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
} }
protected static final int DEFAULT_READ_SIZE = 2048; protected static final int DEFAULT_READ_SIZE = 2048;
@@ -56,40 +56,40 @@ public class Patcher
_obs = obs; _obs = obs;
_plength = patch.length(); _plength = patch.length();
JarFile file = new JarFile(patch); try (JarFile file = new JarFile(patch)) {
Enumeration<JarEntry> entries = file.entries(); // old skool! Enumeration<JarEntry> entries = file.entries(); // old skool!
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement(); JarEntry entry = entries.nextElement();
String path = entry.getName(); String path = entry.getName();
long elength = entry.getCompressedSize(); long elength = entry.getCompressedSize();
// depending on the suffix, we do The Right Thing (tm) // depending on the suffix, we do The Right Thing (tm)
if (path.endsWith(CREATE)) { if (path.endsWith(CREATE)) {
path = strip(path, CREATE); path = strip(path, CREATE);
System.out.println("Creating " + path + "..."); System.out.println("Creating " + path + "...");
createFile(file, entry, new File(appdir, path)); createFile(file, entry, new File(appdir, path));
} else if (path.endsWith(PATCH)) { } else if (path.endsWith(PATCH)) {
path = strip(path, PATCH); path = strip(path, PATCH);
System.out.println("Patching " + path + "..."); System.out.println("Patching " + path + "...");
patchFile(file, entry, appdir, path); patchFile(file, entry, appdir, path);
} else if (path.endsWith(DELETE)) { } else if (path.endsWith(DELETE)) {
path = strip(path, DELETE); path = strip(path, DELETE);
System.out.println("Removing " + path + "..."); System.out.println("Removing " + path + "...");
File target = new File(appdir, path); File target = new File(appdir, path);
if (!target.delete()) { if (!target.delete()) {
System.err.println("Failure deleting '" + target + "'."); System.err.println("Failure deleting '" + target + "'.");
}
} else {
System.err.println("Skipping bogus patch file entry: " + path);
} }
} else { // note that we've completed this entry
System.err.println("Skipping bogus patch file entry: " + path); _complete += elength;
} }
// note that we've completed this entry
_complete += elength;
} }
file.close();
} }
protected String strip (String path, String suffix) protected String strip (String path, String suffix)
@@ -110,11 +110,9 @@ public class Patcher
log.warning("Failed to create parent for '" + target + "'."); log.warning("Failed to create parent for '" + target + "'.");
} }
InputStream in = null; try (InputStream in = file.getInputStream(entry);
FileOutputStream fout = null; FileOutputStream fout = new FileOutputStream(target)) {
try {
in = file.getInputStream(entry);
fout = new FileOutputStream(target);
int total = 0, read; int total = 0, read;
while ((read = in.read(_buffer)) != -1) { while ((read = in.read(_buffer)) != -1) {
total += read; total += read;
@@ -124,10 +122,6 @@ public class Patcher
} catch (IOException ioe) { } catch (IOException ioe) {
System.err.println("Error creating '" + target + "': " + ioe); System.err.println("Error creating '" + target + "': " + ioe);
} finally {
StreamUtil.close(in);
StreamUtil.close(fout);
} }
} }
@@ -143,12 +137,11 @@ public class Patcher
otarget.delete(); otarget.delete();
// pipe the contents of the patch into a file // pipe the contents of the patch into a file
InputStream in = null; try (InputStream in = file.getInputStream(entry);
FileOutputStream fout = null; FileOutputStream fout = new FileOutputStream(patch)) {
try {
StreamUtil.copy(in = file.getInputStream(entry), fout = new FileOutputStream(patch)); StreamUtil.copy(in, fout);
StreamUtil.close(fout); 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)) {
@@ -176,8 +169,6 @@ public class Patcher
} }
} finally { } finally {
StreamUtil.close(fout);
StreamUtil.close(in);
// clean up our temporary files // clean up our temporary files
if (!patch.delete()) { if (!patch.delete()) {
patch.deleteOnExit(); patch.deleteOnExit();
@@ -5,7 +5,14 @@
package com.threerings.getdown.util; package com.threerings.getdown.util;
import java.io.*; 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.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -58,15 +65,13 @@ public class FileUtil
} }
// as a last resort, try copying the old data over the new // as a last resort, try copying the old data over the new
FileInputStream fin = null; try (FileInputStream fin = new FileInputStream(source);
FileOutputStream fout = null; FileOutputStream fout = new FileOutputStream(dest)) {
try {
fin = new FileInputStream(source);
fout = new FileOutputStream(dest);
StreamUtil.copy(fin, fout); StreamUtil.copy(fin, fout);
// close the input stream now so we can delete 'source' // close the input stream now so we can delete 'source'
fin.close(); fin.close();
fin = null;
if (!deleteHarder(source)) { if (!deleteHarder(source)) {
log.warning("Failed to delete " + source + log.warning("Failed to delete " + source +
" after brute force copy to " + dest + "."); " after brute force copy to " + dest + ".");
@@ -76,10 +81,6 @@ public class FileUtil
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failed to copy " + source + " to " + dest + ": " + ioe); log.warning("Failed to copy " + source + " to " + dest + ": " + ioe);
return false; return false;
} finally {
StreamUtil.close(fin);
StreamUtil.close(fout);
} }
} }
@@ -103,63 +104,45 @@ public class FileUtil
throws IOException throws IOException
{ {
List<String> lines = new ArrayList<>(); List<String> lines = new ArrayList<>();
try { try (BufferedReader bin = new BufferedReader(in)) {
BufferedReader bin = new BufferedReader(in);
for (String line = null; (line = bin.readLine()) != null; lines.add(line)) {} for (String line = null; (line = bin.readLine()) != null; lines.add(line)) {}
} finally {
StreamUtil.close(in);
} }
return lines; return lines;
} }
/** /**
* Unpacks the specified jar file intto the specified target directory. * Unpacks the specified jar file into the specified target directory.
*/ */
public static void unpackJar (JarFile jar, File target) throws IOException public static void unpackJar (JarFile jar, File target) throws IOException
{ {
try { Enumeration<?> entries = jar.entries();
Enumeration<?> entries = jar.entries(); while (entries.hasMoreElements()) {
while (entries.hasMoreElements()) { JarEntry entry = (JarEntry)entries.nextElement();
JarEntry entry = (JarEntry)entries.nextElement(); File efile = new File(target, entry.getName());
File efile = new File(target, entry.getName());
// if we're unpacking a normal jar file, it will have special path // if we're unpacking a normal jar file, it will have special path
// entries that allow us to create our directories first // entries that allow us to create our directories first
if (entry.isDirectory()) { if (entry.isDirectory()) {
if (!efile.exists() && !efile.mkdir()) { if (!efile.exists() && !efile.mkdir()) {
log.warning("Failed to create jar entry path", "jar", jar, "entry", entry); log.warning("Failed to create jar entry path", "jar", jar, "entry", entry);
}
continue;
}
// but some do not, so we want to ensure that our directories exist
// prior to getting down and funky
File parent = new File(efile.getParent());
if (!parent.exists() && !parent.mkdirs()) {
log.warning("Failed to create jar entry parent", "jar", jar, "parent", parent);
continue;
}
BufferedOutputStream fout = null;
InputStream jin = null;
try {
fout = new BufferedOutputStream(new FileOutputStream(efile));
jin = jar.getInputStream(entry);
StreamUtil.copy(jin, fout);
} catch (Exception e) {
throw new IOException(
Logger.format("Failure unpacking", "jar", jar, "entry", efile), e);
} finally {
StreamUtil.close(jin);
StreamUtil.close(fout);
} }
continue;
} }
} finally { // but some do not, so we want to ensure that our directories exist
try { // prior to getting down and funky
jar.close(); File parent = new File(efile.getParent());
if (!parent.exists() && !parent.mkdirs()) {
log.warning("Failed to create jar entry parent", "jar", jar, "parent", parent);
continue;
}
try (BufferedOutputStream fout = new BufferedOutputStream(new FileOutputStream(efile));
InputStream jin = jar.getInputStream(entry)) {
StreamUtil.copy(jin, fout);
} catch (Exception e) { } catch (Exception e) {
log.warning("Failed to close jar file", "jar", jar, "error", e); throw new IOException(
Logger.format("Failure unpacking", "jar", jar, "entry", efile), e);
} }
} }
} }
@@ -170,23 +153,14 @@ public class FileUtil
*/ */
public static void unpackPacked200Jar (File packedJar, File target) throws IOException public static void unpackPacked200Jar (File packedJar, File target) throws IOException
{ {
InputStream packedJarIn = null; try (InputStream packedJarIn = new FileInputStream(packedJar);
FileOutputStream extractedJarFileOut = null; FileOutputStream extractedJarFileOut = new FileOutputStream(target);
JarOutputStream jarOutputStream = null; JarOutputStream jarOutputStream = new JarOutputStream(extractedJarFileOut)) {
try { boolean gz = (packedJar.getName().endsWith(".gz") || packedJar.getName().endsWith(".gz_new"));
extractedJarFileOut = new FileOutputStream(target); try (InputStream packedJarIn2 = (gz ? new GZIPInputStream(packedJarIn) : packedJarIn)) {
jarOutputStream = new JarOutputStream(extractedJarFileOut); Pack200.Unpacker unpacker = Pack200.newUnpacker();
packedJarIn = new FileInputStream(packedJar); unpacker.unpack(packedJarIn2, jarOutputStream);
if (packedJar.getName().endsWith(".gz") || packedJar.getName().endsWith(".gz_new")) {
packedJarIn = new GZIPInputStream(packedJarIn);
} }
Pack200.Unpacker unpacker = Pack200.newUnpacker();
unpacker.unpack(packedJarIn, jarOutputStream);
} finally {
StreamUtil.close(jarOutputStream);
StreamUtil.close(extractedJarFileOut);
StreamUtil.close(packedJarIn);
} }
} }
@@ -194,15 +168,9 @@ public class FileUtil
* Copies the given {@code source} file to the given {@code target}. * Copies the given {@code source} file to the given {@code target}.
*/ */
public static void copy (File source, File target) throws IOException { public static void copy (File source, File target) throws IOException {
FileInputStream in = null; try (FileInputStream in = new FileInputStream(source);
FileOutputStream out = null; FileOutputStream out = new FileOutputStream(target)) {
try {
in = new FileInputStream(source);
out = new FileOutputStream(target);
StreamUtil.copy(in, out); StreamUtil.copy(in, out);
} finally {
StreamUtil.close(in);
StreamUtil.close(out);
} }
} }
@@ -6,7 +6,6 @@
package com.threerings.getdown.util; package com.threerings.getdown.util;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
@@ -52,9 +51,10 @@ public class LaunchUtil
{ {
// create the file that instructs Getdown to upgrade // create the file that instructs Getdown to upgrade
File vfile = new File(appdir, "version.txt"); File vfile = new File(appdir, "version.txt");
PrintStream ps = new PrintStream(new FileOutputStream(vfile)); try (FileOutputStream fos = new FileOutputStream(vfile);
ps.println(newVersion); PrintStream ps = new PrintStream(fos)) {
ps.close(); ps.println(newVersion);
}
// make sure that we can find our getdown.jar file and can safely launch children // make sure that we can find our getdown.jar file and can safely launch children
File pro = new File(appdir, getdownJarName); File pro = new File(appdir, getdownJarName);
@@ -16,7 +16,6 @@ import java.io.PrintStream;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.samskivert.io.StreamUtil;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.getdown.data.SysProps; import com.threerings.getdown.data.SysProps;
@@ -33,17 +32,15 @@ public class VersionUtil
public static long readVersion (File vfile) public static long readVersion (File vfile)
{ {
long fileVersion = -1; long fileVersion = -1;
BufferedReader bin = null; try (FileInputStream fis = new FileInputStream(vfile);
try { InputStreamReader reader = new InputStreamReader(fis);
bin = new BufferedReader(new InputStreamReader(new FileInputStream(vfile))); BufferedReader bin = new BufferedReader(reader)) {
String vstr = bin.readLine(); String vstr = bin.readLine();
if (!StringUtil.isBlank(vstr)) { if (!StringUtil.isBlank(vstr)) {
fileVersion = Long.parseLong(vstr); fileVersion = Long.parseLong(vstr);
} }
} 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 {
StreamUtil.close(bin);
} }
return fileVersion; return fileVersion;
@@ -54,13 +51,11 @@ public class VersionUtil
*/ */
public static void writeVersion (File vfile, long version) throws IOException public static void writeVersion (File vfile, long version) throws IOException
{ {
PrintStream out = new PrintStream(new FileOutputStream(vfile)); try (FileOutputStream fos = new FileOutputStream(vfile);
try { PrintStream out = new PrintStream(fos)) {
out.println(version); out.println(version);
} catch (Exception e) { } catch (Exception e) {
log.warning("Unable to write version file: " + e.getMessage()); log.warning("Unable to write version file: " + e.getMessage());
} finally {
StreamUtil.close(out);
} }
} }
@@ -88,9 +83,9 @@ public class VersionUtil
*/ */
public static long readReleaseVersion (File relfile, String versRegex) public static long readReleaseVersion (File relfile, String versRegex)
{ {
BufferedReader in = null; try (FileReader reader = new FileReader(relfile);
try { BufferedReader in = new BufferedReader(reader)) {
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=")) {
@@ -107,8 +102,6 @@ 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);
} }
} }