Create a separate digest.txt file for each "protocol version".
Right now there's only two versions of the digester protocol, so I just always generate both of them. If we evolve the protocol further, we could conceivably allow you to specify a "minimum" protocol version, once you were confident that all of your clients had upgraded to a version of Getdown that used that minimum version.
This commit is contained in:
@@ -904,7 +904,7 @@ public class Application
|
|||||||
// now re-download our control files; we download the digest first so that if it fails,
|
// now re-download our control files; we download the digest first so that if it fails,
|
||||||
// our config file will still reference the old version and re-running the updater will
|
// our config file will still reference the old version and re-running the updater will
|
||||||
// start the whole process over again
|
// start the whole process over again
|
||||||
downloadDigestFile();
|
downloadDigestFiles();
|
||||||
downloadConfigFile();
|
downloadConfigFile();
|
||||||
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@@ -1171,7 +1171,7 @@ public class Application
|
|||||||
String olddig = (_digest == null) ? "" : _digest.getMetaDigest();
|
String olddig = (_digest == null) ? "" : _digest.getMetaDigest();
|
||||||
try {
|
try {
|
||||||
status.updateStatus("m.checking");
|
status.updateStatus("m.checking");
|
||||||
downloadDigestFile();
|
downloadDigestFiles();
|
||||||
_digest = new Digest(_appdir);
|
_digest = new Digest(_appdir);
|
||||||
if (!olddig.equals(_digest.getMetaDigest())) {
|
if (!olddig.equals(_digest.getMetaDigest())) {
|
||||||
log.info("Unversioned digest changed. Revalidating...");
|
log.info("Unversioned digest changed. Revalidating...");
|
||||||
@@ -1189,7 +1189,7 @@ public class Application
|
|||||||
// exceptions to propagate up to the caller as there is nothing else we can do
|
// exceptions to propagate up to the caller as there is nothing else we can do
|
||||||
if (_digest == null) {
|
if (_digest == null) {
|
||||||
status.updateStatus("m.updating_metadata");
|
status.updateStatus("m.updating_metadata");
|
||||||
downloadDigestFile();
|
downloadDigestFiles();
|
||||||
_digest = new Digest(_appdir);
|
_digest = new Digest(_appdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,7 +1200,7 @@ public class Application
|
|||||||
// attempt to redownload both of our metadata files; again we pass errors up to our
|
// attempt to redownload both of our metadata files; again we pass errors up to our
|
||||||
// caller because there's nothing we can do to automatically recover
|
// caller because there's nothing we can do to automatically recover
|
||||||
downloadConfigFile();
|
downloadConfigFile();
|
||||||
downloadDigestFile();
|
downloadDigestFiles();
|
||||||
_digest = new Digest(_appdir);
|
_digest = new Digest(_appdir);
|
||||||
// revalidate everything if we end up downloading new metadata
|
// revalidate everything if we end up downloading new metadata
|
||||||
clearValidationMarkers();
|
clearValidationMarkers();
|
||||||
@@ -1459,13 +1459,15 @@ public class Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads a copy of Digest.DIGEST_FILE and validates its signature.
|
* Downloads the digest files and validates their signature.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
protected void downloadDigestFile ()
|
protected void downloadDigestFiles ()
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
downloadControlFile(Digest.DIGEST_FILE, true);
|
for (int version = 1; version <= Digest.VERSION; version++) {
|
||||||
|
downloadControlFile(Digest.digestFile(version), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,21 +30,80 @@ import static com.threerings.getdown.Log.log;
|
|||||||
*/
|
*/
|
||||||
public class Digest
|
public class Digest
|
||||||
{
|
{
|
||||||
/** The name of our MD5 digest file. */
|
/** The current version of the digest protocol. */
|
||||||
public static final String DIGEST_FILE = "digest.txt";
|
public static final int VERSION = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the digest file for the specified protocol version.
|
||||||
|
*/
|
||||||
|
public static String digestFile (int version) {
|
||||||
|
String infix = version > 1 ? String.valueOf(version) : "";
|
||||||
|
return FILE_NAME + infix + FILE_SUFFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a digest file at the specified location using the supplied list of resources.
|
||||||
|
* @param version the version of the digest protocol to use.
|
||||||
|
*/
|
||||||
|
public static void createDigest (int version, List<Resource> resources, File output)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
MessageDigest md = getMessageDigest();
|
||||||
|
StringBuilder data = new StringBuilder();
|
||||||
|
PrintWriter pout = null;
|
||||||
|
try {
|
||||||
|
pout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), "UTF-8"));
|
||||||
|
|
||||||
|
// compute and append the MD5 digest of each resource in the list
|
||||||
|
for (Resource rsrc : resources) {
|
||||||
|
String path = rsrc.getPath();
|
||||||
|
try {
|
||||||
|
String digest = rsrc.computeDigest(version, md, null);
|
||||||
|
note(data, path, digest);
|
||||||
|
pout.println(path + " = " + digest);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw (IOException) new IOException(
|
||||||
|
"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");
|
||||||
|
String filename = digestFile(version);
|
||||||
|
pout.println(filename + " = " + StringUtil.hexlate(md.digest(contents)));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
StreamUtil.close(pout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains an appropriate message digest instance for use by the Getdown system.
|
||||||
|
*/
|
||||||
|
public static MessageDigest getMessageDigest ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
|
throw new RuntimeException("JVM does not support MD5. Gurp!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a digest instance which will parse and validate the <code>digest.txt</code> in the
|
* Creates a digest instance which will parse and validate the <code>digest.txt</code> in the
|
||||||
* supplied application directory.
|
* supplied application directory.
|
||||||
|
* @param version the version of the digest protocol to use.
|
||||||
*/
|
*/
|
||||||
public Digest (File appdir)
|
public Digest (File appdir)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// parse and validate our digest file contents
|
// parse and validate our digest file contents
|
||||||
|
String filename = digestFile(VERSION);
|
||||||
StringBuilder data = new StringBuilder();
|
StringBuilder data = new StringBuilder();
|
||||||
File dfile = new File(appdir, DIGEST_FILE);
|
File dfile = new File(appdir, filename);
|
||||||
for (String[] pair : ConfigUtil.parsePairs(dfile, false)) {
|
for (String[] pair : ConfigUtil.parsePairs(dfile, false)) {
|
||||||
if (pair[0].equals(DIGEST_FILE)) {
|
if (pair[0].equals(filename)) {
|
||||||
_metaDigest = pair[1];
|
_metaDigest = pair[1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -80,7 +139,7 @@ public class Digest
|
|||||||
public boolean validateResource (Resource resource, ProgressObserver obs)
|
public boolean validateResource (Resource resource, ProgressObserver obs)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
String cmd5 = resource.computeDigest(getMessageDigest(), obs);
|
String cmd5 = resource.computeDigest(VERSION, getMessageDigest(), obs);
|
||||||
String emd5 = _digests.get(resource.getPath());
|
String emd5 = _digests.get(resource.getPath());
|
||||||
if (cmd5.equals(emd5)) {
|
if (cmd5.equals(emd5)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -101,53 +160,6 @@ public class Digest
|
|||||||
return _digests.get(resource.getPath());
|
return _digests.get(resource.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a digest file at the specified location using the supplied list of resources.
|
|
||||||
*/
|
|
||||||
public static void createDigest (List<Resource> resources, File output)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
MessageDigest md = getMessageDigest();
|
|
||||||
StringBuilder data = new StringBuilder();
|
|
||||||
PrintWriter pout = null;
|
|
||||||
try {
|
|
||||||
pout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), "UTF-8"));
|
|
||||||
|
|
||||||
// compute and append the MD5 digest of each resource in the list
|
|
||||||
for (Resource rsrc : resources) {
|
|
||||||
String path = rsrc.getPath();
|
|
||||||
try {
|
|
||||||
String digest = rsrc.computeDigest(md, null);
|
|
||||||
note(data, path, digest);
|
|
||||||
pout.println(path + " = " + digest);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
throw (IOException) new IOException(
|
|
||||||
"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 {
|
|
||||||
StreamUtil.close(pout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains an appropriate message digest instance for use by the Getdown system.
|
|
||||||
*/
|
|
||||||
public static MessageDigest getMessageDigest ()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return MessageDigest.getInstance("MD5");
|
|
||||||
} catch (NoSuchAlgorithmException nsae) {
|
|
||||||
throw new RuntimeException("JVM does not support MD5. Gurp!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used by {@link #createDigest} and {@link Digest}. */
|
/** Used by {@link #createDigest} and {@link Digest}. */
|
||||||
protected static void note (StringBuilder data, String path, String digest)
|
protected static void note (StringBuilder data, String path, String digest)
|
||||||
{
|
{
|
||||||
@@ -156,4 +168,7 @@ public class Digest
|
|||||||
|
|
||||||
protected HashMap<String, String> _digests = new HashMap<String, String>();
|
protected HashMap<String, String> _digests = new HashMap<String, String>();
|
||||||
protected String _metaDigest = "";
|
protected String _metaDigest = "";
|
||||||
|
|
||||||
|
protected static final String FILE_NAME = "digest";
|
||||||
|
protected static final String FILE_SUFFIX = ".txt";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,91 @@ import static com.threerings.getdown.Log.log;
|
|||||||
*/
|
*/
|
||||||
public class Resource
|
public class Resource
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Computes the MD5 hash of the supplied file.
|
||||||
|
* @param version the version of the digest protocol to use.
|
||||||
|
*/
|
||||||
|
public static String computeDigest (int version, File target, MessageDigest md,
|
||||||
|
ProgressObserver obs)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
md.reset();
|
||||||
|
byte[] buffer = new byte[DIGEST_BUFFER_SIZE];
|
||||||
|
int read;
|
||||||
|
|
||||||
|
boolean isJar = isJar(target.getPath());
|
||||||
|
boolean isPacked200Jar = isPacked200Jar(target.getPath());
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
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);
|
||||||
|
} else{
|
||||||
|
jar = new JarFile(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JarEntry> entries = Collections.list(jar.entries());
|
||||||
|
Collections.sort(entries, ENTRY_COMP);
|
||||||
|
|
||||||
|
int eidx = 0;
|
||||||
|
for (JarEntry entry : entries) {
|
||||||
|
// old versions of the digest code skipped metadata
|
||||||
|
if (version < 2) {
|
||||||
|
if (entry.getName().startsWith("META-INF")) {
|
||||||
|
updateProgress(obs, eidx, entries.size());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
in = jar.getInputStream(entry);
|
||||||
|
while ((read = in.read(buffer)) != -1) {
|
||||||
|
md.update(buffer, 0, read);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
StreamUtil.close(in);
|
||||||
|
}
|
||||||
|
updateProgress(obs, eidx, entries.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (jar != null) {
|
||||||
|
try {
|
||||||
|
jar.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
log.warning("Error closing jar", "path", target, "jar", jar, "error", ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmpJarFile != null) {
|
||||||
|
tmpJarFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
long totalSize = target.length(), position = 0L;
|
||||||
|
FileInputStream fin = null;
|
||||||
|
try {
|
||||||
|
fin = new FileInputStream(target);
|
||||||
|
while ((read = fin.read(buffer)) != -1) {
|
||||||
|
md.update(buffer, 0, read);
|
||||||
|
position += read;
|
||||||
|
updateProgress(obs, position, totalSize);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
StreamUtil.close(fin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StringUtil.hexlate(md.digest());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a resource with the supplied remote URL and local path.
|
* Creates a resource with the supplied remote URL and local path.
|
||||||
*/
|
*/
|
||||||
@@ -111,8 +196,10 @@ public class Resource
|
|||||||
/**
|
/**
|
||||||
* Computes the MD5 hash of this resource's underlying file.
|
* Computes the MD5 hash of this resource's underlying file.
|
||||||
* <em>Note:</em> This is both CPU and I/O intensive.
|
* <em>Note:</em> This is both CPU and I/O intensive.
|
||||||
|
* @param version the version of the digest protocol to use.
|
||||||
*/
|
*/
|
||||||
public String computeDigest (MessageDigest md, ProgressObserver obs) throws IOException
|
public String computeDigest (int version, MessageDigest md, ProgressObserver obs)
|
||||||
|
throws IOException
|
||||||
{
|
{
|
||||||
File file;
|
File file;
|
||||||
if (_local.toString().toLowerCase().endsWith(Application.CONFIG_FILE)) {
|
if (_local.toString().toLowerCase().endsWith(Application.CONFIG_FILE)) {
|
||||||
@@ -120,7 +207,7 @@ public class Resource
|
|||||||
} else {
|
} else {
|
||||||
file = _localNew.exists() ? _localNew : _local;
|
file = _localNew.exists() ? _localNew : _local;
|
||||||
}
|
}
|
||||||
return computeDigest(file, md, obs);
|
return computeDigest(version, file, md, obs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,81 +300,6 @@ public class Resource
|
|||||||
return _path;
|
return _path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the MD5 hash of the supplied file.
|
|
||||||
*/
|
|
||||||
public static String computeDigest (File target, MessageDigest md, ProgressObserver obs)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
md.reset();
|
|
||||||
byte[] buffer = new byte[DIGEST_BUFFER_SIZE];
|
|
||||||
int read;
|
|
||||||
|
|
||||||
boolean isJar = isJar(target.getPath());
|
|
||||||
boolean isPacked200Jar = isPacked200Jar(target.getPath());
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
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);
|
|
||||||
} else{
|
|
||||||
jar = new JarFile(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<JarEntry> entries = Collections.list(jar.entries());
|
|
||||||
Collections.sort(entries, ENTRY_COMP);
|
|
||||||
|
|
||||||
int eidx = 0;
|
|
||||||
for (JarEntry entry : entries) {
|
|
||||||
InputStream in = null;
|
|
||||||
try {
|
|
||||||
in = jar.getInputStream(entry);
|
|
||||||
while ((read = in.read(buffer)) != -1) {
|
|
||||||
md.update(buffer, 0, read);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
StreamUtil.close(in);
|
|
||||||
}
|
|
||||||
updateProgress(obs, eidx, entries.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (jar != null) {
|
|
||||||
try {
|
|
||||||
jar.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
log.warning("Error closing jar", "path", target, "jar", jar, "error", ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tmpJarFile != null) {
|
|
||||||
tmpJarFile.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
long totalSize = target.length(), position = 0L;
|
|
||||||
FileInputStream fin = null;
|
|
||||||
try {
|
|
||||||
fin = new FileInputStream(target);
|
|
||||||
while ((read = fin.read(buffer)) != -1) {
|
|
||||||
md.update(buffer, 0, read);
|
|
||||||
position += read;
|
|
||||||
updateProgress(obs, position, totalSize);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
StreamUtil.close(fin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StringUtil.hexlate(md.digest());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper function to simplify the process of reporting progress. */
|
/** Helper function to simplify the process of reporting progress. */
|
||||||
protected static void updateProgress (ProgressObserver obs, long pos, long total)
|
protected static void updateProgress (ProgressObserver obs, long pos, long total)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -107,8 +107,9 @@ public class Differ
|
|||||||
Resource orsrc = (oidx == -1) ? null : orsrcs.remove(oidx);
|
Resource orsrc = (oidx == -1) ? null : orsrcs.remove(oidx);
|
||||||
if (orsrc != null) {
|
if (orsrc != null) {
|
||||||
// first see if they are the same
|
// first see if they are the same
|
||||||
String odig = orsrc.computeDigest(md, null);
|
int version = Digest.VERSION;
|
||||||
String ndig = rsrc.computeDigest(md, null);
|
String odig = orsrc.computeDigest(version, md, null);
|
||||||
|
String ndig = rsrc.computeDigest(version, md, null);
|
||||||
if (odig.equals(ndig)) {
|
if (odig.equals(ndig)) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
System.out.println("Unchanged: " + rsrc.getPath());
|
System.out.println("Unchanged: " + rsrc.getPath());
|
||||||
|
|||||||
@@ -36,24 +36,40 @@ public class Digester
|
|||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
throws IOException, GeneralSecurityException
|
throws IOException, GeneralSecurityException
|
||||||
{
|
{
|
||||||
if (args.length != 1 && args.length != 4) {
|
switch (args.length) {
|
||||||
|
case 1:
|
||||||
|
createDigests(new File(args[0]), null, null, null);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
createDigests(new File(args[0]), new File(args[1]), args[2], args[3]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
System.err.println("Usage: Digester app_dir [keystore_path password alias]");
|
System.err.println("Usage: Digester app_dir [keystore_path password alias]");
|
||||||
System.exit(255);
|
System.exit(255);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
createDigest(new File(args[0]));
|
/**
|
||||||
if (args.length == 4) {
|
* Creates digest file(s) and optionally signs them if {@code keystore} is not null.
|
||||||
signDigest(new File(args[0]), new File(args[1]), args[2], args[3]);
|
*/
|
||||||
|
public static void createDigests (File appdir, File keystore, String password, String alias)
|
||||||
|
throws IOException, GeneralSecurityException
|
||||||
|
{
|
||||||
|
for (int version = 1; version <= Digest.VERSION; version++) {
|
||||||
|
createDigest(version, appdir);
|
||||||
|
if (keystore != null) {
|
||||||
|
signDigest(version, appdir, keystore, password, alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a digest file in the specified application directory.
|
* Creates a digest file in the specified application directory.
|
||||||
*/
|
*/
|
||||||
public static void createDigest (File appdir)
|
public static void createDigest (int version, File appdir)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
File target = new File(appdir, Digest.DIGEST_FILE);
|
File target = new File(appdir, Digest.digestFile(version));
|
||||||
System.out.println("Generating digest file '" + target + "'...");
|
System.out.println("Generating digest file '" + target + "'...");
|
||||||
|
|
||||||
// create our application and instruct it to parse its business
|
// create our application and instruct it to parse its business
|
||||||
@@ -70,17 +86,19 @@ public class Digester
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now generate the digest file
|
// now generate the digest file
|
||||||
Digest.createDigest(rsrcs, target);
|
Digest.createDigest(version, rsrcs, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a digest file in the specified application directory.
|
* Creates a digest file in the specified application directory.
|
||||||
*/
|
*/
|
||||||
public static void signDigest (File appdir, File storePath, String storePass, String storeAlias)
|
public static void signDigest (int version, File appdir,
|
||||||
|
File storePath, String storePass, String storeAlias)
|
||||||
throws IOException, GeneralSecurityException
|
throws IOException, GeneralSecurityException
|
||||||
{
|
{
|
||||||
File inputFile = new File(appdir, Digest.DIGEST_FILE);
|
String filename = Digest.digestFile(version);
|
||||||
File signatureFile = new File(appdir, Digest.DIGEST_FILE + Application.SIGNATURE_SUFFIX);
|
File inputFile = new File(appdir, filename);
|
||||||
|
File signatureFile = new File(appdir, filename + Application.SIGNATURE_SUFFIX);
|
||||||
|
|
||||||
FileInputStream storeInput = null, dataInput = null;
|
FileInputStream storeInput = null, dataInput = null;
|
||||||
FileOutputStream signatureOutput = null;
|
FileOutputStream signatureOutput = null;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import java.security.GeneralSecurityException;
|
|||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.Task;
|
import org.apache.tools.ant.Task;
|
||||||
|
|
||||||
|
import com.threerings.getdown.data.Digest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ant task used to create a <code>digest.txt</code> for a Getdown
|
* An ant task used to create a <code>digest.txt</code> for a Getdown
|
||||||
* application deployment.
|
* application deployment.
|
||||||
@@ -70,10 +72,7 @@ public class DigesterTask extends Task
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Digester.createDigest(_appdir);
|
Digester.createDigests(_appdir, _storepath, _storepass, _storealias);
|
||||||
if (_storepath != null) {
|
|
||||||
Digester.signDigest(_appdir, _storepath, _storepass, _storealias);
|
|
||||||
}
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new BuildException("Error creating digest: " + ioe.getMessage(), ioe);
|
throw new BuildException("Error creating digest: " + ioe.getMessage(), ioe);
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
|
|||||||
Reference in New Issue
Block a user