/* * @(#)JarDiffPatcher.java 1.7 05/11/17 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */ package jnlp.sample.jardiff; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.OutputStream; 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.MissingResourceException; import java.util.ResourceBundle; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * JarDiff is able to create a jar file containing the delta between two jar * files (old and new). The delta jar file can then be applied to the old jar * file to reconstruct the new jar file. *
* Refer to the JNLP spec for details on how this is done.
*
* @version 1.11, 06/26/03
*/
@SuppressWarnings({ "unchecked", "unused", "rawtypes" })
public class JarDiffPatcher implements JarDiffConstants, Patcher {
private final static Logger logger = LoggerFactory
.getLogger(JarDiffPatcher.class);
private static final int DEFAULT_READ_SIZE = 2048;
private static byte[] newBytes = new byte[DEFAULT_READ_SIZE];
private static byte[] oldBytes = new byte[DEFAULT_READ_SIZE];
private static ResourceBundle _resources = JarDiff.getResources();
public static ResourceBundle getResources() {
return JarDiff.getResources();
}
@SuppressWarnings("resource")
@Override
public void applyPatch(Patcher.PatchDelegate delegate, String oldJarPath,
String jarDiffPath, OutputStream result) throws IOException {
File oldFile = new File(oldJarPath);
File diffFile = new File(jarDiffPath);
JarOutputStream jos = new JarOutputStream(result);
JarFile oldJar = new JarFile(oldFile);
JarFile jarDiff = new JarFile(diffFile);
Set ignoreSet = new HashSet();
Map renameMap = new HashMap();
determineNameMapping(jarDiff, ignoreSet, renameMap);
// get all keys in renameMap
Object[] keys = renameMap.keySet().toArray();
// Files to implicit move
Set oldjarNames = new HashSet();
Enumeration oldEntries = oldJar.entries();
if (oldEntries != null) {
while (oldEntries.hasMoreElements()) {
oldjarNames
.add(((JarEntry) oldEntries.nextElement()).getName());
}
}
// size depends on the three parameters below, which is
// basically the counter for each loop that do the actual
// writes to the output file
// since oldjarNames.size() changes in the first two loop
// below, we need to adjust the size accordingly also when
// oldjarNames.size() changes
double size = oldjarNames.size() + keys.length + jarDiff.size();
double currentEntry = 0;
// Handle all remove commands
oldjarNames.removeAll(ignoreSet);
size -= ignoreSet.size();
// Add content from JARDiff
Enumeration entries = jarDiff.entries();
if (entries != null) {
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
if (!INDEX_NAME.equals(entry.getName())) {
updateDelegate(delegate, currentEntry, size);
currentEntry++;
writeEntry(jos, entry, jarDiff);
// Remove entry from oldjarNames since no implicit
// move is needed
boolean wasInOld = oldjarNames.remove(entry.getName());
// Update progress counters. If it was in old, we do
// not need an implicit move, so adjust total size.
if (wasInOld)
size--;
} else {
// no write is done, decrement size
size--;
}
}
}
// go through the renameMap and apply move for each entry
for (int j = 0; j < keys.length; j++) {
// Apply move