Repacking jar files...

Discussion in 'Java' started by Simon Brooke, May 14, 2004.

  1. Simon Brooke

    Simon Brooke Guest

    To configure webapps for delivery, I'm working on a configurer which

    1: makes a copy of the distribution war file and unpacks it
    2: makes substitutions in key configuration files, usually WEB-INF/web.xml
    3: repacks the war file.

    Unfortunately I'm having problems with repacking the war file. Quick reminder
    - a war file is essentially a jar file containing a webapp, so if you've
    exerience of repacking jar files you can probably help.

    The symproms of the problem are

    I do create a file, but

    * When unpacked with ark (the KDE archiver) v2.1.9 all the contents can
    be read and the archive appears perfect.

    * When unpacked with jar as distributed in Sun j2sdk1.4.0, nothing is
    unpacked and I get

    java.util.zip.ZipException: missing entry name
    at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:223)
    at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:72)
    at sun.tools.jar.Main.extract(Main.java:676)
    at sun.tools.jar.Main.run(Main.java:190)
    at sun.tools.jar.Main.main(Main.java:904)

    * When unpacked with Info-ZIP's zip v2.3, it seems to unpack alright but
    things which should be directories come out as empty files.

    * When unpacked with Win-ZIP

    * When installed into tomcat 4, things in the root directory of the
    webapp can be accessed, but nothing else can be, so I'm assuming that
    it's doing very much the same thing as Info-ZIP is doing.

    Anyone got any helpful insights? I can't see anything in the API which
    allows me to mark a JarEntry as a directory, and I can't account for the
    'missing entry name' problem.

    The code I am using to repack the war file is as follows:

    /**
    * repack the contents of the specified directory into a WAR archive file
    *
    * @param dir the directory to pack
    *
    * @throws IOException if anything goes wrong
    */
    protected void repack( Context context, File dir )
    throws IOException
    {
    File oldMeta =
    new File( dir, "META-INF" /* is this JarFile.MANIFEST_NAME? */ );

    if ( oldMeta.exists( ) )
    {
    // TODO: should we do aything to carry forward the contents of oldMeta? If so what?
    deleteDir( oldMeta );
    }

    File pack =
    new File( dir.getParent( ), context.get( APPNAMETOKEN ) + ".war" );

    JarOutputStream jout =
    new JarOutputStream( new FileOutputStream( pack ) );

    Stack toWrite = new Stack( );

    toWrite.push( dir );

    while ( !toWrite.empty( ) )
    {
    File current = (File) toWrite.pop( );

    jout.putNextEntry( new JarEntry( getRelativePath( current, dir ) ) );

    if ( current.isDirectory( ) )
    {
    /** push all my files and subdirs onto the stack */
    String[] children = current.list( );

    for ( int child = 0; child < children.length; child++ )
    {
    toWrite.push( new File( current, children[child] ) );
    }
    }
    else
    {
    /** write contents of file to stream */
    InputStream in =
    new BufferedInputStream( new FileInputStream( current ) );

    for ( int i = in.read( ); i > -1; i = in.read( ) )
    jout.write( i );
    }
    }

    jout.flush( );
    jout.close( );

    /* compute the URL of the newly created delivery package and cache
    * it in the context. There must be a better way of doing this. */
    HttpServletRequest req =
    (HttpServletRequest) context.get( REQUESTMAGICTOKEN );
    ServletContext sc = getServletContext( );

    URL requrl = new URL( req.getRequestURL( ).toString( ) );
    File root = new File( sc.getRealPath( "" ) );

    context.put( DELIVERYPACKAGEURLTOKEN,
    new URL( requrl.getProtocol( ), requrl.getHost( ),
    requrl.getPort( ),
    sc.getServletContextName( ) + File.separator +
    getRelativePath( pack, root ) ) );
    }

    /**
    * get the relative path of file, presumed to be contained within dir or
    * some subdirectory of dir, from dir
    *
    * @param file a file
    * @param dir a directory which encloses it
    *
    * @return the relative path, or (for the time being) the canonical path
    * if file is not within dir.
    */
    private String getRelativePath( File file, File dir )
    throws IOException
    {
    String result = file.getCanonicalPath( );

    /*
    * OK, we need the relative pathname of current with respect to dir
    * this is a hack. TODO: find a guaranteed safe way to do this
    */
    String dirCanonical = dir.getCanonicalPath( );
    String currentCanonical = file.getCanonicalPath( );

    if ( currentCanonical.indexOf( dirCanonical ) == 0 )
    {
    /* i.e. if the canonical name of the current file starts with
    * the canonical name of the directory we're packing - which
    * it should */
    result = currentCanonical.substring( dirCanonical.length( ) );
    }

    if ( result.startsWith( File.separator ) )
    {
    result = result.substring( 1 );
    }

    return result;
    }


    --
    (Simon Brooke) http://www.jasmine.org.uk/~simon/

    For office use only. Please do not write or type below this line.
    Simon Brooke, May 14, 2004
    #1
    1. Advertising

  2. On Fri, 14 May 2004 14:35:01 GMT, Simon Brooke wrote:

    (problems with .WAR)
    > * When unpacked with ark (the KDE archiver) v2.1.9 all the contents can
    > be read and the archive appears perfect.


    *

    > * When unpacked with jar as distributed in Sun j2sdk1.4.0, nothing is
    > unpacked and I get
    >
    > java.util.zip.ZipException: missing entry name
    > at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:223)

    ....
    > * When unpacked with Info-ZIP's zip v2.3, it seems to unpack alright but
    > things which should be directories come out as empty files.


    Those last two result make it sound like the Jar's
    TOC is corrupt. For further info. on Zip
    ToC's, see in this recent thread..
    <http://google.com/groups?threadm=srSdndHRtf9jzRPdRVn-sQ%40nildram.net&rnum=25>
    (Check especially Chris Uppal's detailed explanation).

    * From that it seems KDE Archiver is utterly
    ignoring the ToC and reading each file out
    in order. I would say use it to extract the
    bad file.

    Just a thought.

    --
    Andrew Thompson
    http://www.PhySci.org/ Open-source software suite
    http://www.PhySci.org/codes/ Web & IT Help
    http://www.1point1C.org/ Science & Technology
    Andrew Thompson, May 14, 2004
    #2
    1. Advertising

  3. Simon Brooke

    Chris Uppal Guest

    Simon Brooke wrote:

    > if you've
    > exerience of repacking jar files you can probably help.


    I'm not sure that will is address the problem you are seeing. But I've seen no
    other replies, so...

    It might be that you are generating a malformed "Zip" file by attempting to
    create directory entries.

    The most common convention (there doesn't seem to be a standard) is not to
    include entries for any directories at all. So it's up to the decoding
    application to infer their existence from the names of any files that are "in"
    them.

    A second convention is to create entries with a trailing '/' in their names,
    and no contents. This is more likely to work (not confuse other zip
    applications) if you also set the so-called "internal attributes" to the MSDOS
    directory marker, however the Java API's provide no access to that. Note that
    writing 0 bytes to the contents is NOT the same thing as having no contents if
    the entry is compressed, since compressing a 0-length string produces a couple
    of bytes.

    So I suggest you don't generate directory entries at all, or -- if that doesn't
    work for some reason -- then you fall back to creating them *uncompressed* and
    with a trailing '/' to the name.

    -- chris
    Chris Uppal, May 17, 2004
    #3
  4. On Mon, 17 May 2004 10:00:45 +0100, Chris Uppal wrote:
    ...
    > ...But I've seen no
    > other replies, so...


    Something wrong with news server I suspect..
    <http://google.com/groups?th=fc9bffd97194785a>

    And the follow-up (on a different thread)
    <http://google.com/groups?th=415f433921f6c827>

    --
    Andrew Thompson
    http://www.PhySci.org/ Open-source software suite
    http://www.PhySci.org/codes/ Web & IT Help
    http://www.1point1C.org/ Science & Technology
    Andrew Thompson, May 17, 2004
    #4
  5. Simon Brooke

    Roedy Green Guest

    On Mon, 17 May 2004 10:00:45 +0100, "Chris Uppal"
    <-THIS.org> wrote or quoted :

    >It might be that you are generating a malformed "Zip" file by attempting to
    >create directory entries.


    The decoder thinks they are files and creates them. That prevents it
    from creating directories later of that same name.

    Check the zip spec to see if there is a directory attribute bit.

    Anyway,just leave out the directories. Every decoder automatically
    creates them as needed.

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
    Roedy Green, May 17, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Simon Brooke

    Repacking jar files: solution

    Simon Brooke, May 17, 2004, in forum: Java
    Replies:
    0
    Views:
    434
    Simon Brooke
    May 17, 2004
  2. Arnold Peters
    Replies:
    0
    Views:
    554
    Arnold Peters
    Jan 5, 2005
  3. muttley
    Replies:
    0
    Views:
    2,688
    muttley
    Oct 20, 2005
  4. Magnus Warker

    security exceptions after jar repacking

    Magnus Warker, Apr 17, 2007, in forum: Java
    Replies:
    15
    Views:
    4,627
    Andrew Thompson
    Apr 19, 2007
  5. Kaps Lok

    Repacking an array of arrays

    Kaps Lok, Jul 10, 2007, in forum: Ruby
    Replies:
    11
    Views:
    193
    Kaps Lok
    Jul 10, 2007
Loading...

Share This Page