jnlp.sample.jardiff.JarDiff Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webstart-jnlp-servlet Show documentation
Show all versions of webstart-jnlp-servlet Show documentation
JNLP Sample servlet that supports pack200 protocol. Taken from Sun's JDK sample/jnlp directory thanks to
its permissive license.
The newest version!
/*
* @(#)JarDiff.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.*;
import java.util.*;
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). 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.13, 06/26/03
*/
public class JarDiff
implements JarDiffConstants
{
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 = null;
// The JARDiff.java is the stand-along jardiff.jar tool. Thus, we do not
// depend on Globals.java and other stuff here. Instead, we use an explicit
// _debug flag.
private static boolean _debug;
public static ResourceBundle getResources()
{
if ( _resources == null )
{
_resources = ResourceBundle.getBundle( "jnlp/sample/jardiff/resources/strings" );
}
return _resources;
}
/**
* Creates a patch from the two passed in files, writing the result
* to os
.
*/
public static void createPatch( String oldPath, String newPath, OutputStream os, boolean minimal )
throws IOException
{
JarFile2 oldJar = new JarFile2( oldPath );
JarFile2 newJar = new JarFile2( newPath );
try
{
Iterator entries;
HashMap moved = new HashMap();
HashSet visited = new HashSet();
HashSet implicit = new HashSet();
HashSet moveSrc = new HashSet();
HashSet newEntries = new HashSet();
// FIRST PASS
// Go through the entries in new jar and
// determine which files are candidates for implicit moves
// ( files that has the same filename and same content in old.jar
// and new.jar )
// and for files that cannot be implicitly moved, we will either
// find out whether it is moved or new (modified)
entries = newJar.getJarEntries();
if ( entries != null )
{
while ( entries.hasNext() )
{
JarEntry newEntry = (JarEntry) entries.next();
String newname = newEntry.getName();
// Return best match of contents, will return a name match if possible
String oldname = oldJar.getBestMatch( newJar, newEntry );
if ( oldname == null )
{
// New or modified entry
if ( _debug )
{
System.out.println( "NEW: " + newname );
}
newEntries.add( newname );
}
else
{
// Content already exist - need to do a move
// Should do implicit move? Yes, if names are the same, and
// no move command already exist from oldJar
if ( oldname.equals( newname ) && !moveSrc.contains( oldname ) )
{
if ( _debug )
{
System.out.println( newname + " added to implicit set!" );
}
implicit.add( newname );
}
else
{
// The 1.0.1/1.0 JarDiffPatcher cannot handle
// multiple MOVE command with same src.
// The work around here is if we are going to generate
// a MOVE command with duplicate src, we will
// instead add the target as a new file. This way
// the jardiff can be applied by 1.0.1/1.0
// JarDiffPatcher also.
if ( !minimal && ( implicit.contains( oldname ) || moveSrc.contains( oldname ) ) )
{
// generate non-minimal jardiff
// for backward compatibility
if ( _debug )
{
System.out.println( "NEW: " + newname );
}
newEntries.add( newname );
}
else
{
// Use newname as key, since they are unique
if ( _debug )
{
System.err.println( "moved.put " + newname + " " + oldname );
}
moved.put( newname, oldname );
moveSrc.add( oldname );
}
// Check if this disables an implicit 'move '
if ( implicit.contains( oldname ) && minimal )
{
if ( _debug )
{
System.err.println( "implicit.remove " + oldname );
System.err.println( "moved.put " + oldname + " " + oldname );
}
implicit.remove( oldname );
moved.put( oldname, oldname );
moveSrc.add( oldname );
}
}
}
}
} //if (entries != null)
// SECOND PASS: = - -
//