avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dona...@apache.org
Subject cvs commit: jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test AsiExtraFieldTestCase.java ExtraFieldUtilsTestCase.java ZipEntryTestCase.java ZipLongTestCase.java ZipShortTestCase.java
Date Fri, 22 Mar 2002 12:16:11 GMT
donaldp     02/03/22 04:16:11

  Added:       zip      .cvsignore BUILDING.txt README.txt
                        ant.properties.sample build.xml project.properties
               zip/src/java/org/apache/avalon/excalibur/zip
                        AsiExtraField.java ExtraFieldUtils.java
                        UnixStat.java UnrecognizedExtraField.java
                        ZipEntry.java ZipExtraField.java ZipLong.java
                        ZipOutputStream.java ZipShort.java
               zip/src/test/org/apache/avalon/excalibur/zip/test
                        AsiExtraFieldTestCase.java
                        ExtraFieldUtilsTestCase.java ZipEntryTestCase.java
                        ZipLongTestCase.java ZipShortTestCase.java
  Log:
  Copy across the extended zip tools from ant
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/zip/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  ant.properties
  build
  checkstyle.cache
  distributions
  dist
  excalibur-*
  *.el
  *.ipr
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/BUILDING.txt
  
  Index: BUILDING.txt
  ===================================================================
  
                 Building The Component
                 ======================
  
  In order to build a binary distribution version of the component from a 
  source  distribution,  you must have  a Java Development Kit (JDK)  for 
  version  1.1 (or  later)  downloaded  and  installed  (version  1.3.1 
  recommended), and do the following:
  
  (0) Download and Install a Java Development Kit
  
  * Download a Java Development Kit (JDK) release (version 1.1 or later) 
    from:
  
      http://java.sun.com/j2se/
  
  * Install the JDK according to the instructions included with the release.
  
  * Set an environment variable JAVA_HOME to the pathname of the directory
    into which you installed the JDK release.
  
  
  (1) Download and Install the Ant Binary Distribution
  
  * Download a binary distribution of Ant 1.4.1 from:
  
      http://jakarta.apache.org/builds/jakarta-ant/release/v1.4.1/bin/
  
    On a Windows platform, you will need:
      jakarta-ant-1.4.1-bin.zip
      jakarta-ant-1.4.1-optional.jar
  
    On a Unix platform, you will need:
      jakarta-ant-1.4.1-bin.tar.gz
      jakarta-ant-1.4.1-optional.jar
  
  * Unpack the binary distribution into a convenient location so that the
    Ant release resides in its own directory (conventionally named
    "jakarta-ant-1.4.1").  For the purposes of the remainder of this document,
    the symbolic name "${ant.home}" is used to refer to the full pathname of
    the release directory.
  
  * Copy the file "jakarta-ant-1.4.1-optional.jar", downloaded above, into
    the directory "${ant.home}/lib".  This makes available several Ant
    extension commands that are commonly required when building Jakarta
    based projects.
  
  * Modify the PATH environment variable to include directory
    "${ant.home}/bin" in its list.  This makes the "ant" command line script
    available, which will be used to actually perform the build.
  
  (2) Download and Install the JUnit Testing Package (OPTIONAL)
  
  NOTE: This is only required if you wish to run the unit tests for 
  this component
  
  * Download the JUnit unit test package (version 3.7 or later) from:
  
      http://www.junit.org/
  
  * Unpack the package into a convenient location so that it resides in its
    own subdirectory.
  
  * Copy the file "junit.jar", downloaded above, into the directory 
    "${ant.home}/lib".  This makes available the unit testing tasks that are 
    commonly required when building Jakarta based projects.
  
  (3) Download and Install the JDepend 2.2, Dependency Analysis Package (OPTIONAL)
  
  NOTE: This is only required if you wish to run dependency analysis for 
  this component. 
  
  * Download the JDepend package (version 2.2 or later) from:
  
      http://www.clarkware.com/software/JDepend.html
  
  * Unpack the package into a convenient location so that it resides in its
    own subdirectory.
  
  * Copy the file "jdepend.jar", downloaded above, into the directory 
    "${ant.home}/lib".  This makes available the dependency analysis tasks.
  
  
  (4) Download and Install Checkstyle, 2.1 or later (OPTIONAL)
  
  NOTE: This is only required if you wish to generate reports regarding code style.
  
  * Download the Checkstyle package (version 2.1 or later) from:
  
      http://checkstyle.sourceforge.net/
  
  * Unpack the package into a convenient location so that it resides in its
    own subdirectory.
  
  (5) Download and Install the Xalan, XSLT engine (OPTIONAL)
  
  NOTE: This is only required if you wish to generate reports for the dependency 
  analysis, checkstyle and unit testing results.
  
  * Download the Xalan package (version 2.3.1 or later) from:
  
      http://xml.apache.org/xalan-j/
  
  * Unpack the package into a convenient location so that it resides in its
    own subdirectory.
  
  * Copy the files "xalan.jar", and "xml-apis.jar", downloaded above, into 
    the directory "${ant.home}/lib".  This makes available the XSLT reporting
    capabilities.
  
  (6) Customize Build Properties For This Subproject
  
  Most Jakarta subprojects allow you to customize Ant properties (with default
  values defined in the "build.xml" file.  This is done by creating a text file
  named "ant.properties" in the source distribution directory (for property
  definitions local to this subproject) and/or your user home directory (for
  property definitions shared across subprojects).  You can use the included
  "ant.properties.sample" file as a starting point for this.
  
  External dependencies are satisfied by configuring appropriate values in your 
  ant.properties file.  The easiest way to satisfy these dependencies is to copy 
  the "ant.properties.sample" file (in the top-level directory) to "ant.properties", 
  and then edit it to suit your environment.  On Unix, this would be done as:
  
    cd @dist.name@
    cp ant.properties.sample ant.properties
    emacs ant.properties
  
  NOTE:  Be *sure* that you do not check "ant.properties" in to the CVS
  repository.  This file is local to your own development environment, and
  each developer will have their own version.
  
  (7) Build A Binary Distribution
  
  Open a command line shell, and issue the following commands:
  
    cd @dist.name@
    ant -projecthelp
  
  If everything is installed correctly, you should see a list of the Ant
  "targets" that represent different commands you might wish to build.  By
  convention, the "jar" target creates the jar of the component. To execute 
  it, type the following commands:
  
    cd @dist.name@
    ant jar
  
  This will create a jar in the @dist.name@/build/lib directory that contains 
  the component.
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/README.txt
  
  Index: README.txt
  ===================================================================
                    Avalons Excalibur Zip
                    ---------------------
  
  This is an enhanced set of Zip classes that are more capable of
  handling adding unix-specifc requirements in the "extra field"
  part of a ZipEntry.
  
  Getting Started:
  ----------------
  
  If you downloaded a source release of the component then you
  will need to build the component. Directions for building the
  component are located in BUILDING.txt
  
  If you downloaded a binary release, or a release with both binary
  and source then it is recomended you look over the documentation
  in docs/index.html - and then look into the examples/ directory
  for examples of the component in action.
  
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/ant.properties.sample
  
  Index: ant.properties.sample
  ===================================================================
  # -----------------------------------------------------------------------------
  # ant.properties.sample
  #
  # This is an example "ant.properties" file, used to customize building component
  # for your local environment.  It defines the location of all external
  # modules that the component depends on.  Copy this file to "ant.properties"
  # in the top-level source directory, and customize it as needed.
  #
  # $Id: ant.properties.sample,v 1.1 2002/03/22 12:16:10 donaldp Exp $
  # -----------------------------------------------------------------------------
  
  
  # ----- Compile Control Flags -----
  build.debug=on
  build.optimize=off
  build.deprecation=off
  
  # ----- Base Directory in which all the packages are stored -----
  base.path=/opt
  
  # --------------------------------------------------
  #                REQUIRED LIBRARIES
  # --------------------------------------------------
  
  
  # ----- JUnit Unit Test Suite, version 3.7 or later -----
  junit.home=${base.path}/junit3.7
  junit.lib=${junit.home}
  junit.jar=${junit.lib}/junit.jar
  
  
  # ----- Checkstyle, version 2.1 or later -----
  checkstyle.home=${base.path}/checkstyle-2.1
  checkstyle.lib=${checkstyle.home}
  checkstyle.jar=${checkstyle.lib}/checkstyle-all-2.1.jar
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/build.xml
  
  Index: build.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <project name="Excalibur Zip" default="main" basedir=".">
  
      <!-- load per-project properties -->
      <property file="project.properties"/>
  
      <!--
        Give user a chance to override without editing this file
        (and without typing -D each time he compiles it)
      -->
      <property file="ant.properties"/>
      <property file="../ant.properties"/>
      <property file="${user.home}/.ant.properties"/>
  
      <!-- Settings used to configure compile environment -->
      <property name="build.debug" value="on"/>
      <property name="build.optimize" value="off"/>
      <property name="build.deprecation" value="off"/>
      <property name="build.compress" value="false"/>
      <property name="junit.failonerror" value="false"/>
  
      <!-- location of intermediate products -->
      <property name="build.dir" value="build"/>
      <property name="build.lib" value="${build.dir}/lib"/>
      <property name="build.classes" value="${build.dir}/classes"/>
      <property name="build.tests" value="${build.dir}/tests"/>
      <property name="build.reports" value="${build.dir}/reports"/>
  
      <!-- Set the properties for source directories -->
      <property name="src.dir" value="src"/>
      <property name="java.dir" value="${src.dir}/java"/>
      <property name="test.dir" value="${src.dir}/test"/>
  
      <!-- Set the properties for distribution directories -->
      <property name="dist.dir" value="dist"/>
      <property name="dist.javadocs" value="${dist.dir}/docs/api"/>
  
      <!-- property to specify name of zip/jar files -->
      <property name="dist.name" value="excalibur-${name}-${version}"/>
  
      <!-- property indicating directory where all distribution archives are placed -->
      <property name="dist.base" value="distributions"/>
  
      <!-- Classpath for product -->
      <path id="project.class.path">
          <pathelement path="${java.class.path}"/>
          <pathelement location="${build.classes}"/>
          <pathelement location="${junit.jar}"/>
          <pathelement location="${checkstyle.jar}"/>
      </path>
  
      <target name="main" depends="dist" description="Build the project"/>
      <target name="rebuild" depends="clean,main" description="Rebuild the project"/>
  
      <!-- Compiles the source code -->
      <target name="compile" description="Compiles the source code">
  
          <mkdir dir="${build.classes}"/>
  
          <!-- Compile all classes including the tests. -->
          <javac srcdir="${java.dir}"
              destdir="${build.classes}"
              debug="${build.debug}"
              optimize="${build.optimize}"
              deprecation="${build.deprecation}"
              target="1.2">
              <classpath refid="project.class.path" />
              <src path="${test.dir}"/>
              <include name="**/*.java"/>
          </javac>
  
          <!-- copy resources to same location as .class files -->
          <copy todir="${build.classes}">
              <fileset dir="${java.dir}">
                  <exclude name="**/*.java"/>
              </fileset>
          </copy>
  
          <copy todir="${build.classes}">
              <fileset dir="${test.dir}">
                  <exclude name="**/*.java"/>
              </fileset>
          </copy>
  
      </target>
  
      <!-- Creates all the .jar file -->
      <target name="jar" depends="compile" description="Generates the jar files">
  
          <mkdir dir="${build.lib}"/>
  
          <jar jarfile="${build.lib}/${dist.name}.jar"
              basedir="${build.classes}"
              compress="${build.compress}">
              <exclude name="**/test/**"/>
              <zipfileset dir=".." prefix="META-INF/">
                  <include name="LICENSE.txt"/>
              </zipfileset>
          </jar>
      </target>
  
      <!-- Creates all the Javadocs -->
      <target name="javadocs" depends="compile" description="Generates the javadocs">
  
          <mkdir dir="${dist.javadocs}"/>
          <javadoc packagenames="org.apache.*"
              sourcepath="${java.dir}"
              destdir="${dist.javadocs}">
              <classpath refid="project.class.path" />
              <doclet name="com.sun.tools.doclets.standard.Standard">
                  <param name="-author"/>
                  <param name="-version"/>
                  <param name="-doctitle" value="${Name}"/>
                  <param name="-windowtitle" value="${Name} API"/>
                  <param name="-link" value="http://java.sun.com/j2se/1.4/docs/api/"/>
                  <param name="-link" value="http://java.sun.com/j2ee/sdk_1.3/techdocs/api/"/>
                  <param name="-link" value="http://jakarta.apache.org/avalon/api/"/>
                  <param name="-bottom"
                      value="&quot;Copyright &#169; ${year} Apache Jakarta Project. All Rights Reserved.&quot;"/>
              </doclet>
          </javadoc>
      </target>
  
      <target name="test" depends="compile" description="Perform the unit tests">
  
          <echo message="Performing Unit Tests" />
  
          <mkdir dir="${build.tests}"/>
  
          <junit fork="true"
              haltonfailure="${junit.failonerror}"
              printsummary="yes"
              dir="${build.tests}">
              <classpath refid="project.class.path"/>
  
              <formatter type="xml"/>    <!-- xml reports for junitreport -->
              <formatter type="plain"/>  <!-- text reports for humans     -->
  
              <batchtest todir="${build.tests}">
                  <fileset dir="${build.classes}">
                      <include name="**/test/*TestCase.class"/>
                      <exclude name="**/Abstract*"/>
                  </fileset>
              </batchtest>
          </junit>
  
      </target>
  
      <target name="test-reports" depends="test" description="Generate Reports for the unit tests">
  
          <mkdir dir="${build.reports}/junit"/>
  
          <junitreport todir="${build.reports}/junit">
              <fileset dir="${build.tests}">
                  <include name="TEST-*.xml"/>
              </fileset>
              <report format="frames" todir="${build.reports}/junit"/>
          </junitreport>
  
          <!-- Clean up the xml reports used by the junitreport task -->
          <!--
          <delete>
              <fileset dir="${build.tests}" includes="TEST-*.xml"/>
              <fileset dir="${build.tests}" includes="TESTS-*.xml"/>
          </delete>
          -->
  
      </target>
  
      <target name="jdepend" if="do.jdepend" description="Generate Dependency Analysis Report">
  
          <!-- this invocation of jdepend requires the CVS version of ant for the xml format -->
          <!-- thats why you are required to define do.jdepend property to generate the report -->
          <jdepend outputfile="${build.dir}/jdepend-results.xml" format="xml" fork="yes">
              <classpath refid="project.class.path"/>
              <sourcespath>
                  <pathelement location="src/java" />
              </sourcespath>
          </jdepend>
  
          <mkdir dir="${build.reports}/jdepend"/>
          <style in="${build.dir}/jdepend-results.xml"
              processor="trax"
              out="${build.reports}/jdepend/delete-me.txt"
              style="${ant.home}/etc/jdepend-frames.xsl"/>
      </target>
  
      <target name="checkstyle" if="do.checkstyle" description="Checkstyle">
  
          <!-- this invocation of checkstyle requires that checkstyle be downloaded and setup -->
          <!-- thats why you are required to define do.checkstyle property to generate the report -->
          <taskdef name="checkstyle"
              classname="com.puppycrawl.tools.checkstyle.CheckStyleTask">
              <classpath refid="project.class.path"/>
          </taskdef>
          <checkstyle
              lcurlyType="nl"
              lcurlyMethod="nl"
              lcurlyOther="nl"
              rcurly="ignore"
              allowProtected="false"
              allowPackage="false"
              allowNoAuthor="false"
              maxLineLen="100"
              maxMethodLen="100"
              maxConstructorLen="100"
              memberPattern="^m_[a-z][a-zA-Z0-9]*$"
              staticPattern="^c_[a-z][a-zA-Z0-9]*$"
              constPattern="(^c_[a-z][a-zA-Z0-9]*$)|([A-Z_]*$)"
              ignoreImportLen="true"
              allowTabs="false"
              javadocScope="protected"
              ignoreWhitespace="true"
              cacheFile="checkstyle.cache"
              failOnViolation="false"
              ignoreCastWhitespace="true">
              <fileset dir="${java.dir}">
                  <include name="**/*.java"/>
              </fileset>
              <formatter type="plain"/>
              <formatter type="xml" toFile="build/checkstyle-results.xml"/>
          </checkstyle>
      </target>
  
      <target name="checkstyle-report"
          depends="checkstyle"
          if="do.checkstyle"
          description="Generate Checkstyle Report">
  
          <mkdir dir="${build.reports}/checkstyle"/>
          <style style="../tools/etc/checkstyle-frames.xsl" in="build/checkstyle-results.xml"
              out="${build.reports}/checkstyle/delete-me.html"/>
  
      </target>
  
      <!-- Creates the distribution -->
      <target name="dist"
          depends="jar, test-reports, jdepend, checkstyle-report, javadocs"
          description="Generates the jar files">
  
          <mkdir dir="${dist.dir}"/>
          <copy file="${build.lib}/${dist.name}.jar" todir="${dist.dir}"/>
          <copy file="../LICENSE.txt" todir="${dist.dir}"/>
          <copy file="../KEYS" todir="${dist.dir}"/>
          <copy file="README.txt" todir="${dist.dir}"/>
  
          <mkdir dir="${dist.base}"/>
  
          <zip zipfile="${dist.base}/${dist.name}-bin.zip" compress="true">
              <zipfileset dir="${dist.dir}" prefix="${dist.name}"/>
          </zip>
  
          <!--
            Not supported by released ant but when it is we should enable this across
            all of the products
          <tar longfile="gnu" tarfile="${dist.base}/${dist.name}-bin.tar">
            <tarfileset dir="${dist.dir}"
                        prefix="${dist.name}"
                        username="avalon"
                        group="avalon"/>
          </tar>
  
          <gzip zipfile="${dist.base}/${dist.name}-bin.tar.gz"
                src="${dist.name}-bin.tar"/>
          <bzip2 zipfile="${dist.base}/${dist.name}-bin.tar.gz"
                 src="${dist.name}-bin.tar"/>
  
          <delete file="${dist.base}/${dist.name}-bin.tar"/>
  
          <checksum fileext=".md5">
            <fileset dir="${dist.base}" />
          </checksum>
          -->
          <delete dir="${dist.dir}" />
  
      </target>
  
      <!-- Cleans up build and distribution directories -->
      <target name="clean" description="Cleans up the project">
          <delete file="checkstyle.cache"/>
          <delete dir="${build.dir}" />
          <delete dir="${dist.dir}" />
          <delete dir="test" /> <!-- unit testing output directory -->
          <delete>
              <fileset dir="." includes="**/*~" defaultexcludes="no"/>
          </delete>
      </target>
  
      <target name="real-clean" depends="clean" description="Cleans up the project, including distributions">
          <delete dir="${dist.base}" />
      </target>
  
  </project>
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/project.properties
  
  Index: project.properties
  ===================================================================
  name=zip
  Name=Zip
  version=1.0
  year=2000-2002
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/AsiExtraField.java
  
  Index: AsiExtraField.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  import java.util.zip.CRC32;
  import java.util.zip.ZipException;
  
  /**
   * Adds Unix file permission and UID/GID fields as well as symbolic link
   * handling. <p>
   *
   * This class uses the ASi extra field in the format: <pre>
   *         Value         Size            Description
   *         -----         ----            -----------
   * (Unix3) 0x756e        Short           tag for this extra block type
   *         TSize         Short           total data size for this block
   *         CRC           Long            CRC-32 of the remaining data
   *         Mode          Short           file permissions
   *         SizDev        Long            symlink'd size OR major/minor dev num
   *         UID           Short           user ID
   *         GID           Short           group ID
   *         (var.)        variable        symbolic link filename
   * </pre> taken from appnote.iz (Info-ZIP note, 981119) found at <a
   * href="ftp://ftp.uu.net/pub/archiving/zip/doc/">
   * ftp://ftp.uu.net/pub/archiving/zip/doc/</a> </p> <p>
   *
   * Short is two bytes and Long is four bytes in big endian byte and word order,
   * device numbers are currently not supported.</p>
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class AsiExtraField
      implements ZipExtraField, UnixStat, Cloneable
  {
      private static final ZipShort HEADER_ID = new ZipShort( 0x756E );
  
      /**
       * Standard Unix stat(2) file mode.
       *
       * @since 1.1
       */
      private int m_mode = 0;
      /**
       * User ID.
       *
       * @since 1.1
       */
      private int m_uid = 0;
  
      /**
       * Group ID.
       *
       * @since 1.1
       */
      private int m_gid = 0;
  
      /**
       * File this entry points to, if it is a symbolic link. <p>
       *
       * empty string - if entry is not a symbolic link.</p>
       *
       * @since 1.1
       */
      private String m_link = "";
  
      /**
       * Is this an entry for a directory?
       *
       * @since 1.1
       */
      private boolean m_dirFlag;
  
      /**
       * Instance used to calculate checksums.
       *
       * @since 1.1
       */
      private CRC32 m_crc = new CRC32();
  
      /**
       * Indicate whether this entry is a directory.
       *
       * @param dirFlag The new Directory value
       * @since 1.1
       */
      public void setDirectory( final boolean dirFlag )
      {
          m_dirFlag = dirFlag;
          m_mode = getMode( m_mode );
      }
  
      /**
       * Set the group id.
       *
       * @param gid The new GroupId value
       * @since 1.1
       */
      public void setGroupId( int gid )
      {
          m_gid = gid;
      }
  
      /**
       * Indicate that this entry is a symbolic link to the given filename.
       *
       * @param name Name of the file this entry links to, empty String if it is
       *      not a symbolic link.
       * @since 1.1
       */
      public void setLinkedFile( final String name )
      {
          m_link = name;
          m_mode = getMode( m_mode );
      }
  
      /**
       * File mode of this file.
       *
       * @param mode The new Mode value
       * @since 1.1
       */
      public void setMode( final int mode )
      {
          m_mode = getMode( mode );
      }
  
      /**
       * Set the user id.
       *
       * @param uid The new UserId value
       * @since 1.1
       * @deprecated Use setUserID(int)
       * @see #setUserID(int)
       */
      public void setUserId( final int uid )
      {
          m_uid = uid;
      }
  
      /**
       * Set the user id.
       *
       * @param uid The new UserId value
       */
      public void setUserID( final int uid )
      {
          m_uid = uid;
      }
  
      /**
       * Delegate to local file data.
       *
       * @return The CentralDirectoryData value
       * @since 1.1
       */
      public byte[] getCentralDirectoryData()
      {
          return getLocalFileDataData();
      }
  
      /**
       * Delegate to local file data.
       *
       * @return The CentralDirectoryLength value
       * @since 1.1
       */
      public ZipShort getCentralDirectoryLength()
      {
          return getLocalFileDataLength();
      }
  
      /**
       * Get the group id.
       *
       * @return The GroupId value
       * @since 1.1
       */
      public int getGroupId()
      {
          return m_gid;
      }
  
      /**
       * The Header-ID.
       *
       * @return The HeaderId value
       * @since 1.1
       */
      public ZipShort getHeaderId()
      {
          return HEADER_ID;
      }
  
      /**
       * Name of linked file
       *
       * @return name of the file this entry links to if it is a symbolic link,
       *      the empty string otherwise.
       * @since 1.1
       */
      public String getLinkedFile()
      {
          return m_link;
      }
  
      /**
       * The actual data to put into local file data - without Header-ID or length
       * specifier.
       *
       * @return The LocalFileDataData value
       * @since 1.1
       */
      public byte[] getLocalFileDataData()
      {
          // CRC will be added later
          byte[] data = new byte[ getLocalFileDataLength().getValue() - 4 ];
          System.arraycopy( ( new ZipShort( getMode() ) ).getBytes(), 0, data, 0, 2 );
  
          byte[] linkArray = getLinkedFile().getBytes();
          System.arraycopy( ( new ZipLong( linkArray.length ) ).getBytes(),
                            0, data, 2, 4 );
  
          System.arraycopy( ( new ZipShort( getUserId() ) ).getBytes(),
                            0, data, 6, 2 );
          System.arraycopy( ( new ZipShort( getGroupId() ) ).getBytes(),
                            0, data, 8, 2 );
  
          System.arraycopy( linkArray, 0, data, 10, linkArray.length );
  
          m_crc.reset();
          m_crc.update( data );
          long checksum = m_crc.getValue();
  
          byte[] result = new byte[ data.length + 4 ];
          System.arraycopy( ( new ZipLong( checksum ) ).getBytes(), 0, result, 0, 4 );
          System.arraycopy( data, 0, result, 4, data.length );
          return result;
      }
  
      /**
       * Length of the extra field in the local file data - without Header-ID or
       * length specifier.
       *
       * @return The LocalFileDataLength value
       * @since 1.1
       */
      public ZipShort getLocalFileDataLength()
      {
          return new ZipShort( 4 +// CRC
                               2 +// Mode
                               4 +// SizDev
                               2 +// UID
                               2 +// GID
                               getLinkedFile().getBytes().length );
      }
  
      /**
       * File mode of this file.
       *
       * @return The Mode value
       * @since 1.1
       */
      public int getMode()
      {
          return m_mode;
      }
  
      /**
       * Get the user id.
       *
       * @return The UserId value
       * @since 1.1
       * @deprecated Use getUserID()
       * @see #getUserID()
       */
      public int getUserId()
      {
          return m_uid;
      }
  
      /**
       * Get the user id.
       *
       * @return The UserID value
       */
      public int getUserID()
      {
          return m_uid;
      }
  
      /**
       * Is this entry a directory?
       *
       * @return The Directory value
       * @since 1.1
       */
      public boolean isDirectory()
      {
          return m_dirFlag && !isLink();
      }
  
      /**
       * Is this entry a symbolic link?
       *
       * @return The Link value
       * @since 1.1
       */
      public boolean isLink()
      {
          return getLinkedFile().length() != 0;
      }
  
      /**
       * Populate data from this array as if it was in local file data.
       *
       * @param buffer the buffer
       * @param offset the offset into buffer
       * @param length the length of data in buffer
       * @throws ZipException on error
       * @since 1.1
       */
      public void parseFromLocalFileData( final byte[] buffer,
                                          final int offset,
                                          final int length )
          throws ZipException
      {
  
          long givenChecksum = ( new ZipLong( buffer, offset ) ).getValue();
          byte[] tmp = new byte[ length - 4 ];
          System.arraycopy( buffer, offset + 4, tmp, 0, length - 4 );
          m_crc.reset();
          m_crc.update( tmp );
          long realChecksum = m_crc.getValue();
          if( givenChecksum != realChecksum )
          {
              throw new ZipException( "bad CRC checksum " + Long.toHexString( givenChecksum ) +
                                      " instead of " + Long.toHexString( realChecksum ) );
          }
  
          int newMode = ( new ZipShort( tmp, 0 ) ).getValue();
          byte[] linkArray = new byte[ (int)( new ZipLong( tmp, 2 ) ).getValue() ];
          m_uid = ( new ZipShort( tmp, 6 ) ).getValue();
          m_gid = ( new ZipShort( tmp, 8 ) ).getValue();
  
          if( linkArray.length == 0 )
          {
              m_link = "";
          }
          else
          {
              System.arraycopy( tmp, 10, linkArray, 0, linkArray.length );
              m_link = new String( linkArray );
          }
          setDirectory( ( newMode & DIR_FLAG ) != 0 );
          setMode( newMode );
      }
  
      /**
       * Get the file mode for given permissions with the correct file type.
       *
       * @param mode Description of Parameter
       * @return The Mode value
       * @since 1.1
       */
      protected int getMode( final int mode )
      {
          int type = FILE_FLAG;
          if( isLink() )
          {
              type = LINK_FLAG;
          }
          else if( isDirectory() )
          {
              type = DIR_FLAG;
          }
          return type | ( mode & PERM_MASK );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ExtraFieldUtils.java
  
  Index: ExtraFieldUtils.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.zip.ZipException;
  
  /**
   * ZipExtraField related methods
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class ExtraFieldUtils
  {
      /**
       * Static registry of known extra fields.
       *
       * @since 1.1
       */
      private static final Hashtable c_implementations;
  
      static
      {
          c_implementations = new Hashtable();
          register( AsiExtraField.class );
      }
  
      /**
       * Create an instance of the approriate ExtraField, falls back to {@link
       * UnrecognizedExtraField UnrecognizedExtraField}.
       *
       * Throws java.lang.IllegalAccessException if cant create implementation.
       *
       * @param headerID the header ID
       * @return the extra field implementation
       * @throws InstantiationException if cant create implementation
       * @throws IllegalAccessException if cant create implementation
       * @since 1.1
       */
      public static ZipExtraField createExtraField( final ZipShort headerID )
          throws InstantiationException, IllegalAccessException
      {
          final Class clazz =
              (Class)c_implementations.get( headerID );
          if( clazz != null )
          {
              return (ZipExtraField)clazz.newInstance();
          }
          final UnrecognizedExtraField unrecognized = new UnrecognizedExtraField();
          unrecognized.setHeaderId( headerID );
          return unrecognized;
      }
  
      /**
       * Merges the central directory fields of the given ZipExtraFields.
       *
       * @param data the central directory data
       * @return the merged data
       * @since 1.1
       */
      public static byte[] mergeCentralDirectoryData( final ZipExtraField[] data )
      {
          int sum = 4 * data.length;
          for( int i = 0; i < data.length; i++ )
          {
              sum += data[ i ].getCentralDirectoryLength().getValue();
          }
          byte[] result = new byte[ sum ];
          int start = 0;
          for( int i = 0; i < data.length; i++ )
          {
              System.arraycopy( data[ i ].getHeaderId().getBytes(),
                                0, result, start, 2 );
              System.arraycopy( data[ i ].getCentralDirectoryLength().getBytes(),
                                0, result, start + 2, 2 );
              byte[] local = data[ i ].getCentralDirectoryData();
              System.arraycopy( local, 0, result, start + 4, local.length );
              start += ( local.length + 4 );
          }
          return result;
      }
  
      /**
       * Merges the local file data fields of the given ZipExtraFields.
       *
       * @param data the data
       * @return the merged data
       * @since 1.1
       */
      public static byte[] mergeLocalFileDataData( final ZipExtraField[] data )
      {
          int sum = 4 * data.length;
          for( int i = 0; i < data.length; i++ )
          {
              sum += data[ i ].getLocalFileDataLength().getValue();
          }
          byte[] result = new byte[ sum ];
          int start = 0;
          for( int i = 0; i < data.length; i++ )
          {
              System.arraycopy( data[ i ].getHeaderId().getBytes(),
                                0, result, start, 2 );
              System.arraycopy( data[ i ].getLocalFileDataLength().getBytes(),
                                0, result, start + 2, 2 );
              byte[] local = data[ i ].getLocalFileDataData();
              System.arraycopy( local, 0, result, start + 4, local.length );
              start += ( local.length + 4 );
          }
          return result;
      }
  
      /**
       * Split the array into ExtraFields and populate them with the give data.
       *
       * @param data the data to parse
       * @return the parsed fields
       * @exception ZipException on error
       * @since 1.1
       */
      public static ZipExtraField[] parse( final byte[] data )
          throws ZipException
      {
          ArrayList v = new ArrayList();
          int start = 0;
          while( start <= data.length - 4 )
          {
              final ZipShort headerID = new ZipShort( data, start );
              int length = ( new ZipShort( data, start + 2 ) ).getValue();
              if( start + 4 + length > data.length )
              {
                  throw new ZipException( "data starting at " + start + " is in unknown format" );
              }
              try
              {
                  ZipExtraField ze = createExtraField( headerID );
                  ze.parseFromLocalFileData( data, start + 4, length );
                  v.add( ze );
              }
              catch( InstantiationException ie )
              {
                  throw new ZipException( ie.getMessage() );
              }
              catch( IllegalAccessException iae )
              {
                  throw new ZipException( iae.getMessage() );
              }
              start += ( length + 4 );
          }
          if( start != data.length )
          {// array not exhausted
              throw new ZipException( "data starting at " + start + " is in unknown format" );
          }
  
          final ZipExtraField[] result = new ZipExtraField[ v.size() ];
          return (ZipExtraField[])v.toArray( result );
      }
  
      /**
       * Register a ZipExtraField implementation. <p>
       *
       * The given class must have a no-arg constructor and implement the {@link
       * ZipExtraField ZipExtraField interface}.</p>
       *
       * @param clazz The Class for particular implementation
       * @since 1.1
       */
      public static void register( final Class clazz )
      {
          try
          {
              ZipExtraField ze = (ZipExtraField)clazz.newInstance();
              c_implementations.put( ze.getHeaderId(), clazz );
          }
          catch( ClassCastException cc )
          {
              throw new RuntimeException( clazz +
                                          " doesn\'t implement ZipExtraField" );
          }
          catch( InstantiationException ie )
          {
              throw new RuntimeException( clazz + " is not a concrete class" );
          }
          catch( IllegalAccessException ie )
          {
              throw new RuntimeException( clazz +
                                          "\'s no-arg constructor is not public" );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/UnixStat.java
  
  Index: UnixStat.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  /**
   * Constants from stat.h on Unix systems.
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public interface UnixStat
  {
      /**
       * Bits used for permissions (and sticky bit)
       *
       * @since 1.1
       */
      int PERM_MASK = 07777;
      /**
       * Indicates symbolic links.
       *
       * @since 1.1
       */
      int LINK_FLAG = 0120000;
      /**
       * Indicates plain files.
       *
       * @since 1.1
       */
      int FILE_FLAG = 0100000;
      /**
       * Indicates directories.
       *
       * @since 1.1
       */
      int DIR_FLAG = 040000;
  
      // ----------------------------------------------------------
      // somewhat arbitrary choices that are quite common for shared
      // installations
      // -----------------------------------------------------------
  
      /**
       * Default permissions for symbolic links.
       *
       * @since 1.1
       */
      int DEFAULT_LINK_PERM = 0777;
  
      /**
       * Default permissions for directories.
       *
       * @since 1.1
       */
      int DEFAULT_DIR_PERM = 0755;
  
      /**
       * Default permissions for plain files.
       *
       * @since 1.1
       */
      int DEFAULT_FILE_PERM = 0644;
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/UnrecognizedExtraField.java
  
  Index: UnrecognizedExtraField.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  /**
   * Simple placeholder for all those extra fields we don't want to deal with. <p>
   *
   * Assumes local file data and central directory entries are identical - unless
   * told the opposite.</p>
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class UnrecognizedExtraField
      implements ZipExtraField
  {
      /**
       * Extra field data in central directory - without Header-ID or length
       * specifier.
       *
       * @since 1.1
       */
      private byte[] m_centralData;
  
      /**
       * The Header-ID.
       *
       * @since 1.1
       */
      private ZipShort m_headerID;
  
      /**
       * Extra field data in local file data - without Header-ID or length
       * specifier.
       *
       * @since 1.1
       */
      private byte[] m_localData;
  
      /**
       * Set the central directory data
       *
       * @param centralData the central directory data
       */
      public void setCentralDirectoryData( final byte[] centralData )
      {
          m_centralData = centralData;
      }
  
      /**
       * Set the header ID.
       *
       * @param headerID the header ID
       * @deprecated Use setHeaderID() instead
       * @see #setHeaderID(ZipShort)
       */
      public void setHeaderId( final ZipShort headerID )
      {
          setHeaderID( headerID );
      }
  
      /**
       * Set the header ID.
       *
       * @param headerID the header ID
       */
      public void setHeaderID( final ZipShort headerID )
      {
          m_headerID = headerID;
      }
  
      /**
       * Set the local file data.
       *
       * @param localData the local file data
       */
      public void setLocalFileDataData( final byte[] localData )
      {
          m_localData = localData;
      }
  
      /**
       * Get the central directory data.
       *
       * @return the central directory data.
       */
      public byte[] getCentralDirectoryData()
      {
          if( m_centralData != null )
          {
              return m_centralData;
          }
          return getLocalFileDataData();
      }
  
      /**
       * Get the length of the central directory in bytes.
       *
       * @return the length of the central directory in bytes.
       */
      public ZipShort getCentralDirectoryLength()
      {
          if( m_centralData != null )
          {
              return new ZipShort( m_centralData.length );
          }
          return getLocalFileDataLength();
      }
  
      /**
       * Get the HeaderID.
       *
       * @return the HeaderID
       * @deprecated Use getHeaderID() instead
       * @see #getHeaderID()
       */
      public ZipShort getHeaderId()
      {
          return m_headerID;
      }
  
      /**
       * Get the HeaderID.
       *
       * @return the HeaderID
       */
      public ZipShort getHeaderID()
      {
          return m_headerID;
      }
  
      /**
       * Get the local file data.
       *
       * @return the local file data
       */
      public byte[] getLocalFileDataData()
      {
          return m_localData;
      }
  
      /**
       * Get the length of local file data in bytes.
       *
       * @return the length of local file data in bytes
       */
      public ZipShort getLocalFileDataLength()
      {
          return new ZipShort( m_localData.length );
      }
  
      /**
       * Parse LocalFiledata out of supplied buffer.
       *
       * @param buffer the buffer to use
       * @param offset the offset into buffer
       * @param length then length of data
       */
      public void parseFromLocalFileData( final byte[] buffer,
                                          final int offset,
                                          final int length )
      {
          final byte[] fileData = new byte[ length ];
          System.arraycopy( buffer, offset, fileData, 0, length );
          setLocalFileDataData( fileData );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ZipEntry.java
  
  Index: ZipEntry.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.zip.ZipException;
  
  /**
   * Extension that adds better handling of extra fields and provides access to
   * the internal and external file attributes.
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class ZipEntry
      extends java.util.zip.ZipEntry
  {
      /**
       * Helper for JDK 1.1
       *
       * @since 1.2
       */
      private static Method c_setCompressedSizeMethod;
  
      /**
       * Helper for JDK 1.1
       *
       * @since 1.2
       */
      private static final Object c_lockReflection = new Object();
  
      /**
       * Helper for JDK 1.1
       *
       * @since 1.2
       */
      private static boolean c_triedToGetMethod;
  
      private final ArrayList m_extraFields = new ArrayList();
  
      private int m_internalAttributes;
      private long m_externalAttributes;
  
      /**
       * Helper for JDK 1.1 <-> 1.2 incompatibility.
       *
       * @since 1.2
       */
      private Long m_compressedSize;
  
      /**
       * Creates a new zip entry with the specified name.
       *
       * @param name the name of entry
       * @since 1.1
       */
      public ZipEntry( final String name )
      {
          super( name );
      }
  
      /**
       * Creates a new zip entry with fields taken from the specified zip entry.
       *
       * @param entry the JDK ZipEntry to adapt
       * @exception ZipException if can not create entry
       * @since 1.1
       */
      public ZipEntry( java.util.zip.ZipEntry entry )
          throws ZipException
      {
          /*
           * REVISIT: call super(entry) instead of this stuff in Ant2,
           * "copy constructor" has not been available in JDK 1.1
           */
          super( entry.getName() );
  
          setComment( entry.getComment() );
          setMethod( entry.getMethod() );
          setTime( entry.getTime() );
  
          final long size = entry.getSize();
          if( size > 0 )
          {
              setSize( size );
          }
  
          final long cSize = entry.getCompressedSize();
          if( cSize > 0 )
          {
              setComprSize( cSize );
          }
  
          final long crc = entry.getCrc();
          if( crc > 0 )
          {
              setCrc( crc );
          }
  
          final byte[] extra = entry.getExtra();
          if( extra != null )
          {
              setExtraFields( ExtraFieldUtils.parse( extra ) );
          }
          else
          {
              // initializes extra data to an empty byte array
              setExtra();
          }
      }
  
      /**
       * Creates a new zip entry with fields taken from the specified zip entry.
       *
       * @param entry the entry to adapt
       * @exception ZipException if can not create entry
       * @since 1.1
       */
      public ZipEntry( final ZipEntry entry )
          throws ZipException
      {
          this( (java.util.zip.ZipEntry)entry );
          setInternalAttributes( entry.getInternalAttributes() );
          setExternalAttributes( entry.getExternalAttributes() );
          setExtraFields( entry.getExtraFields() );
      }
  
      /**
       * Try to get a handle to the setCompressedSize method.
       *
       * @since 1.2
       */
      private static void checkSCS()
      {
          if( !c_triedToGetMethod )
          {
              synchronized( c_lockReflection )
              {
                  c_triedToGetMethod = true;
                  try
                  {
                      c_setCompressedSizeMethod =
                          java.util.zip.ZipEntry.class.getMethod( "setCompressedSize",
                                                                  new Class[]{Long.TYPE} );
                  }
                  catch( NoSuchMethodException nse )
                  {
                  }
              }
          }
      }
  
      /**
       * Are we running JDK 1.2 or higher?
       *
       * @return Description of the Returned Value
       * @since 1.2
       */
      private static boolean haveSetCompressedSize()
      {
          checkSCS();
          return c_setCompressedSizeMethod != null;
      }
  
      /**
       * Invoke setCompressedSize via reflection.
       *
       * @param entry Description of Parameter
       * @param size Description of Parameter
       * @since 1.2
       */
      private static void performSetCompressedSize( final ZipEntry entry,
                                                    final long size )
      {
          final Long[] s = {new Long( size )};
          try
          {
              c_setCompressedSizeMethod.invoke( entry, s );
          }
          catch( final InvocationTargetException ite )
          {
              final Throwable nested = ite.getTargetException();
              final String message = "Exception setting the compressed size " +
                  "of " + entry + ": " + nested.getMessage();
              throw new RuntimeException( message );
          }
          catch( final Throwable t )
          {
              final String message = "Exception setting the compressed size " +
                  "of " + entry + ": " + t.getMessage();
              throw new RuntimeException( message );
          }
      }
  
      /**
       * Make this class work in JDK 1.1 like a 1.2 class. <p>
       *
       * This either stores the size for later usage or invokes setCompressedSize
       * via reflection.</p>
       *
       * @param size The new ComprSize value
       * @since 1.2
       */
      public void setComprSize( final long size )
      {
          if( haveSetCompressedSize() )
          {
              performSetCompressedSize( this, size );
          }
          else
          {
              m_compressedSize = new Long( size );
          }
      }
  
      /**
       * Sets the external file attributes.
       *
       * @param externalAttributes The new ExternalAttributes value
       * @since 1.1
       */
      public void setExternalAttributes( final long externalAttributes )
      {
          m_externalAttributes = externalAttributes;
      }
  
      /**
       * Throws an Exception if extra data cannot be parsed into extra fields.
       *
       * @param extra The new Extra value
       * @throws RuntimeException if fail to set extra data
       * @since 1.1
       */
      public void setExtra( final byte[] extra )
          throws RuntimeException
      {
          try
          {
              setExtraFields( ExtraFieldUtils.parse( extra ) );
          }
          catch( final Exception e )
          {
              throw new RuntimeException( e.getMessage() );
          }
      }
  
      /**
       * Replaces all currently attached extra fields with the new array.
       *
       * @param fields The new ExtraFields value
       * @since 1.1
       */
      public void setExtraFields( final ZipExtraField[] fields )
      {
          m_extraFields.clear();
          for( int i = 0; i < fields.length; i++ )
          {
              m_extraFields.add( fields[ i ] );
          }
          setExtra();
      }
  
      /**
       * Sets the internal file attributes.
       *
       * @param value The new InternalAttributes value
       * @since 1.1
       */
      public void setInternalAttributes( final int value )
      {
          m_internalAttributes = value;
      }
  
      /**
       * Retrieves the extra data for the central directory.
       *
       * @return The CentralDirectoryExtra value
       * @since 1.1
       */
      public byte[] getCentralDirectoryExtra()
      {
          return ExtraFieldUtils.mergeCentralDirectoryData( getExtraFields() );
      }
  
      /**
       * Override to make this class work in JDK 1.1 like a 1.2 class.
       *
       * @return The CompressedSize value
       * @since 1.2
       */
      public long getCompressedSize()
      {
          if( m_compressedSize != null )
          {
              // has been set explicitly and we are running in a 1.1 VM
              return m_compressedSize.longValue();
          }
          return super.getCompressedSize();
      }
  
      /**
       * Retrieves the external file attributes.
       *
       * @return The ExternalAttributes value
       * @since 1.1
       */
      public long getExternalAttributes()
      {
          return m_externalAttributes;
      }
  
      /**
       * Retrieves extra fields.
       *
       * @return The ExtraFields value
       * @since 1.1
       */
      public ZipExtraField[] getExtraFields()
      {
          final ZipExtraField[] result = new ZipExtraField[ m_extraFields.size() ];
          return (ZipExtraField[])m_extraFields.toArray( result );
      }
  
      /**
       * Retrieves the internal file attributes.
       *
       * @return The InternalAttributes value
       * @since 1.1
       */
      public int getInternalAttributes()
      {
          return m_internalAttributes;
      }
  
      /**
       * Retrieves the extra data for the local file data.
       *
       * @return The LocalFileDataExtra value
       * @since 1.1
       */
      public byte[] getLocalFileDataExtra()
      {
          byte[] extra = getExtra();
          return extra != null ? extra : new byte[ 0 ];
      }
  
      /**
       * Adds an extra fields - replacing an already present extra field of the
       * same type.
       *
       * @param extraField The feature to be added to the ExtraField attribute
       * @since 1.1
       */
      public void addExtraField( final ZipExtraField extraField )
      {
          final ZipShort type = extraField.getHeaderId();
          boolean done = false;
          for( int i = 0; !done && i < m_extraFields.size(); i++ )
          {
              final ZipExtraField other = (ZipExtraField)m_extraFields.get( i );
              if( other.getHeaderId().equals( type ) )
              {
                  m_extraFields.set( i, extraField );
                  done = true;
              }
          }
          if( !done )
          {
              m_extraFields.add( extraField );
          }
          setExtra();
      }
  
      /**
       * Overwrite clone
       *
       * @return Description of the Returned Value
       * @since 1.1
       */
      public Object clone()
      {
          ZipEntry e = null;
          try
          {
              e = new ZipEntry( (java.util.zip.ZipEntry)super.clone() );
          }
          catch( Exception ex )
          {
              // impossible as extra data is in correct format
              ex.printStackTrace();
          }
          e.setInternalAttributes( getInternalAttributes() );
          e.setExternalAttributes( getExternalAttributes() );
          e.setExtraFields( getExtraFields() );
          return e;
      }
  
      /**
       * Remove an extra fields.
       *
       * @param type Description of Parameter
       * @since 1.1
       */
      public void removeExtraField( final ZipShort type )
      {
          boolean done = false;
          for( int i = 0; !done && i < m_extraFields.size(); i++ )
          {
              if( ( (ZipExtraField)m_extraFields.get( i ) ).getHeaderId().equals( type ) )
              {
                  m_extraFields.remove( i );
                  done = true;
              }
          }
          if( !done )
          {
              throw new java.util.NoSuchElementException();
          }
          setExtra();
      }
  
      /**
       * Unfortunately {@link java.util.zip.ZipOutputStream
       * java.util.zip.ZipOutputStream} seems to access the extra data directly,
       * so overriding getExtra doesn't help - we need to modify super's data
       * directly.
       *
       * @since 1.1
       */
      protected void setExtra()
      {
          super.setExtra( ExtraFieldUtils.mergeLocalFileDataData( getExtraFields() ) );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ZipExtraField.java
  
  Index: ZipExtraField.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  import java.util.zip.ZipException;
  
  /**
   * General format of extra field data. <p>
   *
   * Extra fields usually appear twice per file, once in the local file data and
   * once in the central directory. Usually they are the same, but they don't have
   * to be. {@link java.util.zip.ZipOutputStream java.util.zip.ZipOutputStream}
   * will only use the local file data in both places.</p>
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public interface ZipExtraField
  {
      /**
       * The Header-ID.
       *
       * @return The HeaderId value
       * @since 1.1
       */
      ZipShort getHeaderId();
  
      /**
       * Length of the extra field in the local file data - without Header-ID or
       * length specifier.
       *
       * @return The LocalFileDataLength value
       * @since 1.1
       */
      ZipShort getLocalFileDataLength();
  
      /**
       * Length of the extra field in the central directory - without Header-ID or
       * length specifier.
       *
       * @return The CentralDirectoryLength value
       * @since 1.1
       */
      ZipShort getCentralDirectoryLength();
  
      /**
       * The actual data to put into local file data - without Header-ID or length
       * specifier.
       *
       * @return The LocalFileDataData value
       * @since 1.1
       */
      byte[] getLocalFileDataData();
  
      /**
       * The actual data to put central directory - without Header-ID or length
       * specifier.
       *
       * @return The CentralDirectoryData value
       * @since 1.1
       */
      byte[] getCentralDirectoryData();
  
      /**
       * Populate data from this array as if it was in local file data.
       *
       * @param buffer the buffer to read data from
       * @param offset offset into buffer to read data
       * @param length the length of data
       * @exception ZipException on error
       * @since 1.1
       */
      void parseFromLocalFileData( byte[] buffer, int offset, int length )
          throws ZipException;
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ZipLong.java
  
  Index: ZipLong.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  /**
   * Utility class that represents a four byte integer with conversion rules for
   * the big endian byte order of ZIP files.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class ZipLong
      implements Cloneable
  {
      private long m_value;
  
      /**
       * Create instance from a number.
       *
       * @param value the value
       * @since 1.1
       */
      public ZipLong( final long value )
      {
          m_value = value;
      }
  
      /**
       * Create instance from bytes.
       *
       * @param buffer the buffer to read data from
       * @since 1.1
       */
      public ZipLong( final byte[] buffer )
      {
          this( buffer, 0 );
      }
  
      /**
       * Create instance from the four bytes starting at offset.
       *
       * @param buffer buffer to read data from
       * @param offset offset into buffer
       * @since 1.1
       */
      public ZipLong( final byte[] buffer, final int offset )
      {
          m_value = ( buffer[ offset + 3 ] << 24 ) & 0xFF000000l;
          m_value += ( buffer[ offset + 2 ] << 16 ) & 0xFF0000;
          m_value += ( buffer[ offset + 1 ] << 8 ) & 0xFF00;
          m_value += ( buffer[ offset ] & 0xFF );
      }
  
      /**
       * Get value as two bytes in big endian byte order.
       *
       * @return The value as bytes
       * @since 1.1
       */
      public byte[] getBytes()
      {
          byte[] result = new byte[ 4 ];
          result[ 0 ] = (byte)( ( m_value & 0xFF ) );
          result[ 1 ] = (byte)( ( m_value & 0xFF00 ) >> 8 );
          result[ 2 ] = (byte)( ( m_value & 0xFF0000 ) >> 16 );
          result[ 3 ] = (byte)( ( m_value & 0xFF000000l ) >> 24 );
          return result;
      }
  
      /**
       * Get value as Java int.
       *
       * @return The value
       * @since 1.1
       */
      public long getValue()
      {
          return m_value;
      }
  
      /**
       * Override to make two instances with same value equal.
       *
       * @param o the object to compare against
       * @return true if equyal, false otherwise
       * @since 1.1
       */
      public boolean equals( final Object o )
      {
          if( o == null || !( o instanceof ZipLong ) )
          {
              return false;
          }
          return m_value == ( (ZipLong)o ).getValue();
      }
  
      /**
       * Override to make two instances with same value equal.
       *
       * @return the hashcode
       * @since 1.1
       */
      public int hashCode()
      {
          return (int)m_value;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ZipOutputStream.java
  
  Index: ZipOutputStream.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.Hashtable;
  import java.util.zip.CRC32;
  import java.util.zip.Deflater;
  import java.util.zip.DeflaterOutputStream;
  import java.util.zip.ZipException;
  
  /**
   * Reimplementation of {@link java.util.zip.ZipOutputStream
   * java.util.zip.ZipOutputStream} that does handle the extended functionality of
   * this package, especially internal/external file attributes and extra fields
   * with different layouts for local file data and central directory entries. <p>
   *
   * This implementation will use a Data Descriptor to store size and CRC
   * information for DEFLATED entries, this means, you don't need to calculate
   * them yourself. Unfortunately this is not possible for the STORED method, here
   * setting the CRC and uncompressed size information is required before {@link
   * #putNextEntry putNextEntry} will be called.</p>
   *
   * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class ZipOutputStream
      extends DeflaterOutputStream
  {
      /**
       * Helper, a 0 as ZipShort.
       *
       * @since 1.1
       */
      private static final byte[] ZERO = {0, 0};
  
      /**
       * Helper, a 0 as ZipLong.
       *
       * @since 1.1
       */
      private static final byte[] LZERO = {0, 0, 0, 0};
  
      /**
       * Compression method for deflated entries.
       *
       * @since 1.1
       */
      public static final int DEFLATED = ZipEntry.DEFLATED;
  
      /**
       * Compression method for deflated entries.
       *
       * @since 1.1
       */
      public static final int STORED = ZipEntry.STORED;
  
      /*
       * Various ZIP constants
       */
      /**
       * local file header signature
       *
       * @since 1.1
       */
      protected static final ZipLong LFH_SIG = new ZipLong( 0X04034B50L );
      /**
       * data descriptor signature
       *
       * @since 1.1
       */
      protected static final ZipLong DD_SIG = new ZipLong( 0X08074B50L );
      /**
       * central file header signature
       *
       * @since 1.1
       */
      protected static final ZipLong CFH_SIG = new ZipLong( 0X02014B50L );
      /**
       * end of central dir signature
       *
       * @since 1.1
       */
      protected static final ZipLong EOCD_SIG = new ZipLong( 0X06054B50L );
  
      /**
       * Smallest date/time ZIP can handle.
       *
       * @since 1.1
       */
      private static final ZipLong DOS_TIME_MIN = new ZipLong( 0x00002100L );
  
      /**
       * The file comment.
       *
       * @since 1.1
       */
      private String m_comment = "";
  
      /**
       * Compression level for next entry.
       *
       * @since 1.1
       */
      private int m_level = Deflater.DEFAULT_COMPRESSION;
  
      /**
       * Default compression method for next entry.
       *
       * @since 1.1
       */
      private int m_method = DEFLATED;
  
      /**
       * List of ZipEntries written so far.
       *
       * @since 1.1
       */
      private final ArrayList m_entries = new ArrayList();
  
      /**
       * CRC instance to avoid parsing DEFLATED data twice.
       *
       * @since 1.1
       */
      private final CRC32 m_crc = new CRC32();
  
      /**
       * Count the bytes written to out.
       *
       * @since 1.1
       */
      private long m_written;
  
      /**
       * Data for current entry started here.
       *
       * @since 1.1
       */
      private long m_dataStart;
  
      /**
       * Start of central directory.
       *
       * @since 1.1
       */
      private ZipLong m_cdOffset = new ZipLong( 0 );
  
      /**
       * Length of central directory.
       *
       * @since 1.1
       */
      private ZipLong m_cdLength = new ZipLong( 0 );
  
      /**
       * Holds the offsets of the LFH starts for each entry
       *
       * @since 1.1
       */
      private final Hashtable m_offsets = new Hashtable();
  
      /**
       * The encoding to use for filenames and the file comment. <p>
       *
       * For a list of possible values see <a
       * href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">
       * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html
       * </a>. Defaults to the platform's default character encoding.</p>
       *
       * @since 1.3
       */
      private String m_encoding;
  
      /**
       * Current entry.
       *
       * @since 1.1
       */
      private ZipEntry m_entry;
  
      /**
       * Creates a new ZIP OutputStream filtering the underlying stream.
       *
       * @param output the output stream to write to
       * @since 1.1
       */
      public ZipOutputStream( final OutputStream output )
      {
          super( output, new Deflater( Deflater.DEFAULT_COMPRESSION, true ) );
      }
  
      /**
       * Convert a Date object to a DOS date/time field. <p>
       *
       * Stolen from InfoZip's <code>fileio.c</code></p>
       *
       * @param time Description of Parameter
       * @return Description of the Returned Value
       * @since 1.1
       */
      protected static ZipLong toDosTime( Date time )
      {
          int year = time.getYear() + 1900;
          int month = time.getMonth() + 1;
          if( year < 1980 )
          {
              return DOS_TIME_MIN;
          }
          long value = ( ( year - 1980 ) << 25 )
              | ( month << 21 )
              | ( time.getDate() << 16 )
              | ( time.getHours() << 11 )
              | ( time.getMinutes() << 5 )
              | ( time.getSeconds() >> 1 );
  
          byte[] result = new byte[ 4 ];
          result[ 0 ] = (byte)( ( value & 0xFF ) );
          result[ 1 ] = (byte)( ( value & 0xFF00 ) >> 8 );
          result[ 2 ] = (byte)( ( value & 0xFF0000 ) >> 16 );
          result[ 3 ] = (byte)( ( value & 0xFF000000l ) >> 24 );
          return new ZipLong( result );
      }
  
      /**
       * Set the file comment.
       *
       * @param comment The new Comment value
       * @since 1.1
       */
      public void setComment( String comment )
      {
          m_comment = comment;
      }
  
      /**
       * The encoding to use for filenames and the file comment. <p>
       *
       * For a list of possible values see <a
       * href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">
       * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html
       * </a>. Defaults to the platform's default character encoding.</p>
       *
       * @param encoding The new Encoding value
       * @since 1.3
       */
      public void setEncoding( String encoding )
      {
          m_encoding = encoding;
      }
  
      /**
       * Sets the compression level for subsequent entries. <p>
       *
       * Default is Deflater.DEFAULT_COMPRESSION.</p>
       *
       * @param level The new Level value
       * @since 1.1
       */
      public void setLevel( int level )
      {
          m_level = level;
      }
  
      /**
       * Sets the default compression method for subsequent entries. <p>
       *
       * Default is DEFLATED.</p>
       *
       * @param method The new Method value
       * @since 1.1
       */
      public void setMethod( final int method )
      {
          m_method = method;
      }
  
      /**
       * The encoding to use for filenames and the file comment.
       *
       * @return null if using the platform's default character encoding.
       * @since 1.3
       */
      public String getEncoding()
      {
          return m_encoding;
      }
  
      /**
       * Writes all necessary data for this entry.
       *
       * @throws IOException if an IO failure causes operation to fail
       * @since 1.1
       */
      public void closeEntry()
          throws IOException
      {
          if( m_entry == null )
          {
              return;
          }
  
          long realCrc = m_crc.getValue();
          m_crc.reset();
  
          if( m_entry.getMethod() == DEFLATED )
          {
              def.finish();
              while( !def.finished() )
              {
                  deflate();
              }
  
              m_entry.setSize( def.getTotalIn() );
              m_entry.setComprSize( def.getTotalOut() );
              m_entry.setCrc( realCrc );
  
              def.reset();
  
              m_written += m_entry.getCompressedSize();
          }
          else
          {
              if( m_entry.getCrc() != realCrc )
              {
                  throw new ZipException( "bad CRC checksum for entry "
                                          + m_entry.getName() + ": "
                                          + Long.toHexString( m_entry.getCrc() )
                                          + " instead of "
                                          + Long.toHexString( realCrc ) );
              }
  
              if( m_entry.getSize() != m_written - m_dataStart )
              {
                  throw new ZipException( "bad size for entry "
                                          + m_entry.getName() + ": "
                                          + m_entry.getSize()
                                          + " instead of "
                                          + ( m_written - m_dataStart ) );
              }
  
          }
  
          writeDataDescriptor( m_entry );
          m_entry = null;
      }
  
      /*
       * Found out by experiment, that DeflaterOutputStream.close()
       * will call finish() - so we don't need to override close
       * ourselves.
       */
      /**
       * Finishs writing the contents and closes this as well as the underlying
       * stream.
       *
       * @throws IOException if an IO failure causes operation to fail
       * @since 1.1
       */
      public void finish()
          throws IOException
      {
          closeEntry();
          m_cdOffset = new ZipLong( m_written );
          final int size = m_entries.size();
          for( int i = 0; i < size; i++ )
          {
              final ZipEntry entry = (ZipEntry)m_entries.get( i );
              writeCentralFileHeader( entry );
          }
          m_cdLength = new ZipLong( m_written - m_cdOffset.getValue() );
          writeCentralDirectoryEnd();
          m_offsets.clear();
          m_entries.clear();
      }
  
      /**
       * Begin writing next entry.
       *
       * @param entry the entry
       * @throws IOException if an IO failure causes operation to fail
       * @since 1.1
       */
      public void putNextEntry( final ZipEntry entry )
          throws IOException
      {
          closeEntry();
  
          m_entry = entry;
          m_entries.add( m_entry );
  
          if( m_entry.getMethod() == -1 )
          {// not specified
              m_entry.setMethod( m_method );
          }
  
          if( m_entry.getTime() == -1 )
          {// not specified
              m_entry.setTime( System.currentTimeMillis() );
          }
  
          if( m_entry.getMethod() == STORED )
          {
              if( m_entry.getSize() == -1 )
              {
                  throw new ZipException( "uncompressed size is required for STORED method" );
              }
              if( m_entry.getCrc() == -1 )
              {
                  throw new ZipException( "crc checksum is required for STORED method" );
              }
              m_entry.setComprSize( m_entry.getSize() );
          }
          else
          {
              def.setLevel( m_level );
          }
          writeLocalFileHeader( m_entry );
      }
  
      /**
       * Writes bytes to ZIP entry. <p>
       *
       * Override is necessary to support STORED entries, as well as calculationg
       * CRC automatically for DEFLATED entries.</p>
       *
       * @param buffer the buffer to write to
       * @param offset the offset to write to
       * @param length the length of data to write
       * @exception IOException if an IO error causes operation to fail
       */
      public void write( final byte[] buffer,
                         final int offset,
                         final int length )
          throws IOException
      {
          if( m_entry.getMethod() == DEFLATED )
          {
              super.write( buffer, offset, length );
          }
          else
          {
              out.write( buffer, offset, length );
              m_written += length;
          }
          m_crc.update( buffer, offset, length );
      }
  
      /**
       * Retrieve the bytes for the given String in the encoding set for this
       * Stream.
       *
       * @param name the name to decode
       * @return the bytes for string
       * @exception ZipException if fail to retrieve bytes for specified string
       * @since 1.3
       */
      protected byte[] getBytes( String name )
          throws ZipException
      {
          if( m_encoding == null )
          {
              return name.getBytes();
          }
          else
          {
              try
              {
                  return name.getBytes( m_encoding );
              }
              catch( UnsupportedEncodingException uee )
              {
                  throw new ZipException( uee.getMessage() );
              }
          }
      }
  
      /**
       * Writes the &quot;End of central dir record&quot;
       *
       * @exception IOException when an IO erro causes operation to fail
       * @since 1.1
       */
      protected void writeCentralDirectoryEnd()
          throws IOException
      {
          out.write( EOCD_SIG.getBytes() );
  
          // disk numbers
          out.write( ZERO );
          out.write( ZERO );
  
          // number of entries
          byte[] num = ( new ZipShort( m_entries.size() ) ).getBytes();
          out.write( num );
          out.write( num );
  
          // length and location of CD
          out.write( m_cdLength.getBytes() );
          out.write( m_cdOffset.getBytes() );
  
          // ZIP file comment
          byte[] data = getBytes( m_comment );
          out.write( ( new ZipShort( data.length ) ).getBytes() );
          out.write( data );
      }
  
      /**
       * Writes the central file header entry
       *
       * @param entry the zip entry
       * @throws IOException when an IO error causes operation to fail
       * @since 1.1
       */
      protected void writeCentralFileHeader( final ZipEntry entry )
          throws IOException
      {
          out.write( CFH_SIG.getBytes() );
          m_written += 4;
  
          // version made by
          out.write( ( new ZipShort( 20 ) ).getBytes() );
          m_written += 2;
  
          // version needed to extract
          // general purpose bit flag
          if( entry.getMethod() == DEFLATED )
          {
              // requires version 2 as we are going to store length info
              // in the data descriptor
              out.write( ( new ZipShort( 20 ) ).getBytes() );
  
              // bit3 set to signal, we use a data descriptor
              out.write( ( new ZipShort( 8 ) ).getBytes() );
          }
          else
          {
              out.write( ( new ZipShort( 10 ) ).getBytes() );
              out.write( ZERO );
          }
          m_written += 4;
  
          // compression method
          out.write( ( new ZipShort( entry.getMethod() ) ).getBytes() );
          m_written += 2;
  
          // last mod. time and date
          out.write( toDosTime( new Date( entry.getTime() ) ).getBytes() );
          m_written += 4;
  
          // CRC
          // compressed length
          // uncompressed length
          out.write( ( new ZipLong( entry.getCrc() ) ).getBytes() );
          out.write( ( new ZipLong( entry.getCompressedSize() ) ).getBytes() );
          out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
          m_written += 12;
  
          // file name length
          byte[] name = getBytes( entry.getName() );
          out.write( ( new ZipShort( name.length ) ).getBytes() );
          m_written += 2;
  
          // extra field length
          byte[] extra = entry.getCentralDirectoryExtra();
          out.write( ( new ZipShort( extra.length ) ).getBytes() );
          m_written += 2;
  
          // file comment length
          String comm = entry.getComment();
          if( comm == null )
          {
              comm = "";
          }
          byte[] comment = getBytes( comm );
          out.write( ( new ZipShort( comment.length ) ).getBytes() );
          m_written += 2;
  
          // disk number start
          out.write( ZERO );
          m_written += 2;
  
          // internal file attributes
          out.write( ( new ZipShort( entry.getInternalAttributes() ) ).getBytes() );
          m_written += 2;
  
          // external file attributes
          out.write( ( new ZipLong( entry.getExternalAttributes() ) ).getBytes() );
          m_written += 4;
  
          // relative offset of LFH
          out.write( ( (ZipLong)m_offsets.get( entry ) ).getBytes() );
          m_written += 4;
  
          // file name
          out.write( name );
          m_written += name.length;
  
          // extra field
          out.write( extra );
          m_written += extra.length;
  
          // file comment
          out.write( comment );
          m_written += comment.length;
      }
  
      /**
       * Writes the data descriptor entry
       *
       * @param ze Description of Parameter
       * @throws IOException if an IO failure causes operation to fail
       * @since 1.1
       */
      protected void writeDataDescriptor( ZipEntry ze )
          throws IOException
      {
          if( ze.getMethod() != DEFLATED )
          {
              return;
          }
          out.write( DD_SIG.getBytes() );
          out.write( ( new ZipLong( m_entry.getCrc() ) ).getBytes() );
          out.write( ( new ZipLong( m_entry.getCompressedSize() ) ).getBytes() );
          out.write( ( new ZipLong( m_entry.getSize() ) ).getBytes() );
          m_written += 16;
      }
  
      /**
       * Writes the local file header entry
       *
       * @param entry the zip entry
       * @exception IOException when an IO error causes operation to fail
       * @since 1.1
       */
      protected void writeLocalFileHeader( final ZipEntry entry )
          throws IOException
      {
          m_offsets.put( entry, new ZipLong( m_written ) );
  
          out.write( LFH_SIG.getBytes() );
          m_written += 4;
  
          // version needed to extract
          // general purpose bit flag
          if( entry.getMethod() == DEFLATED )
          {
              // requires version 2 as we are going to store length info
              // in the data descriptor
              out.write( ( new ZipShort( 20 ) ).getBytes() );
  
              // bit3 set to signal, we use a data descriptor
              out.write( ( new ZipShort( 8 ) ).getBytes() );
          }
          else
          {
              out.write( ( new ZipShort( 10 ) ).getBytes() );
              out.write( ZERO );
          }
          m_written += 4;
  
          // compression method
          out.write( ( new ZipShort( entry.getMethod() ) ).getBytes() );
          m_written += 2;
  
          // last mod. time and date
          out.write( toDosTime( new Date( entry.getTime() ) ).getBytes() );
          m_written += 4;
  
          // CRC
          // compressed length
          // uncompressed length
          if( entry.getMethod() == DEFLATED )
          {
              out.write( LZERO );
              out.write( LZERO );
              out.write( LZERO );
          }
          else
          {
              out.write( ( new ZipLong( entry.getCrc() ) ).getBytes() );
              out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
              out.write( ( new ZipLong( entry.getSize() ) ).getBytes() );
          }
          m_written += 12;
  
          // file name length
          byte[] name = getBytes( entry.getName() );
          out.write( ( new ZipShort( name.length ) ).getBytes() );
          m_written += 2;
  
          // extra field length
          byte[] extra = entry.getLocalFileDataExtra();
          out.write( ( new ZipShort( extra.length ) ).getBytes() );
          m_written += 2;
  
          // file name
          out.write( name );
          m_written += name.length;
  
          // extra field
          out.write( extra );
          m_written += extra.length;
  
          m_dataStart = m_written;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/java/org/apache/avalon/excalibur/zip/ZipShort.java
  
  Index: ZipShort.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip;
  
  /**
   * Utility class that represents a two byte integer with conversion rules for
   * the big endian byte order of ZIP files.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @version $Revision: 1.1 $
   */
  public class ZipShort
      implements Cloneable
  {
      private int m_value;
  
      /**
       * Create instance from a number.
       *
       * @param value Description of Parameter
       * @since 1.1
       */
      public ZipShort( int value )
      {
          this.m_value = value;
      }
  
      /**
       * Create instance from bytes.
       *
       * @param bytes Description of Parameter
       * @since 1.1
       */
      public ZipShort( byte[] bytes )
      {
          this( bytes, 0 );
      }
  
      /**
       * Create instance from the two bytes starting at offset.
       *
       * @param bytes Description of Parameter
       * @param offset Description of Parameter
       * @since 1.1
       */
      public ZipShort( byte[] bytes, int offset )
      {
          m_value = ( bytes[ offset + 1 ] << 8 ) & 0xFF00;
          m_value += ( bytes[ offset ] & 0xFF );
      }
  
      /**
       * Get value as two bytes in big endian byte order.
       *
       * @return The Bytes value
       * @since 1.1
       */
      public byte[] getBytes()
      {
          byte[] result = new byte[ 2 ];
          result[ 0 ] = (byte)( m_value & 0xFF );
          result[ 1 ] = (byte)( ( m_value & 0xFF00 ) >> 8 );
          return result;
      }
  
      /**
       * Get value as Java int.
       *
       * @return The Value value
       * @since 1.1
       */
      public int getValue()
      {
          return m_value;
      }
  
      /**
       * Override to make two instances with same value equal.
       *
       * @param o Description of Parameter
       * @return Description of the Returned Value
       * @since 1.1
       */
      public boolean equals( Object o )
      {
          if( o == null || !( o instanceof ZipShort ) )
          {
              return false;
          }
          return m_value == ( (ZipShort)o ).getValue();
      }
  
      /**
       * Override to make two instances with same value equal.
       *
       * @return Description of the Returned Value
       * @since 1.1
       */
      public int hashCode()
      {
          return m_value;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test/AsiExtraFieldTestCase.java
  
  Index: AsiExtraFieldTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip.test;
  
  import java.util.zip.ZipException;
  import junit.framework.TestCase;
  import org.apache.avalon.excalibur.zip.UnixStat;
  import org.apache.avalon.excalibur.zip.AsiExtraField;
  
  /**
   * JUnit testcases AsiExtraField.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  public class AsiExtraFieldTestCase
      extends TestCase
      implements UnixStat
  {
      public AsiExtraFieldTestCase( final String name )
      {
          super( name );
      }
  
      /**
       * Test file mode magic.
       */
      public void testModes()
      {
          final AsiExtraField field = new AsiExtraField();
          field.setMode( 0123 );
          assertEquals( "plain file", 0100123, field.getMode() );
          field.setDirectory( true );
          assertEquals( "directory", 040123, field.getMode() );
          field.setLinkedFile( "test" );
          assertEquals( "symbolic link", 0120123, field.getMode() );
      }
  
      private AsiExtraField createField()
      {
          final AsiExtraField field = new AsiExtraField();
          field.setMode( 0123 );
          field.setUserId( 5 );
          field.setGroupId( 6 );
          return field;
      }
  
      public void testContent1()
      {
          final AsiExtraField field = createField();
          final byte[] data = field.getLocalFileDataData();
  
          // CRC manually calculated, sorry
          final byte[] expect = {(byte)0xC6, 0x02, 0x78, (byte)0xB6, // CRC
                                 0123, (byte)0x80, // mode
                                 0, 0, 0, 0, // link length
                                 5, 0, 6, 0};                        // uid, gid
          assertEquals( "no link", expect.length, data.length );
          for( int i = 0; i < expect.length; i++ )
          {
              assertEquals( "no link, byte " + i, expect[ i ], data[ i ] );
          }
  
          field.setLinkedFile( "test" );
      }
  
      public void testContent2()
      {
          final AsiExtraField field = createField();
          field.setLinkedFile( "test" );
  
          final byte[] data = field.getLocalFileDataData();
          final byte[] expect = new byte[]{0x75, (byte)0x8E, 0x41, (byte)0xFD, // CRC
                                           0123, (byte)0xA0, // mode
                                           4, 0, 0, 0, // link length
                                           5, 0, 6, 0, // uid, gid
                                           (byte)'t', (byte)'e', (byte)'s', (byte)'t'};
          assertEquals( "no link", expect.length, data.length );
          for( int i = 0; i < expect.length; i++ )
          {
              assertEquals( "no link, byte " + i, expect[ i ], data[ i ] );
          }
  
      }
  
      public void testReparse1()
          throws ZipException
      {
          // CRC manually calculated, sorry
          final byte[] data = {(byte)0xC6, 0x02, 0x78, (byte)0xB6, // CRC
                               0123, (byte)0x80, // mode
                               0, 0, 0, 0, // link length
                               5, 0, 6, 0};                        // uid, gid
          final AsiExtraField field = new AsiExtraField();
          field.parseFromLocalFileData( data, 0, data.length );
  
          assertEquals( "length plain file", data.length,
                        field.getLocalFileDataLength().getValue() );
          assertTrue( "plain file, no link", !field.isLink() );
          assertTrue( "plain file, no dir", !field.isDirectory() );
          assertEquals( "mode plain file", FILE_FLAG | 0123, field.getMode() );
          assertEquals( "uid plain file", 5, field.getUserId() );
          assertEquals( "gid plain file", 6, field.getGroupId() );
      }
  
      public void testReparse2()
          throws ZipException
      {
          final byte[] data = new byte[]{0x75, (byte)0x8E, 0x41, (byte)0xFD, // CRC
                                         0123, (byte)0xA0, // mode
                                         4, 0, 0, 0, // link length
                                         5, 0, 6, 0, // uid, gid
                                         (byte)'t', (byte)'e', (byte)'s', (byte)'t'};
          final AsiExtraField field = new AsiExtraField();
          field.parseFromLocalFileData( data, 0, data.length );
          assertEquals( "length link", data.length,
                        field.getLocalFileDataLength().getValue() );
          assertTrue( "link, is link", field.isLink() );
          assertTrue( "link, no dir", !field.isDirectory() );
          assertEquals( "mode link", LINK_FLAG | 0123, field.getMode() );
          assertEquals( "uid link", 5, field.getUserId() );
          assertEquals( "gid link", 6, field.getGroupId() );
          assertEquals( "test", field.getLinkedFile() );
      }
  
      public void testReparse3()
          throws ZipException
      {
          final byte[] data = new byte[]{(byte)0x8E, 0x01, (byte)0xBF, (byte)0x0E, // CRC
                                         0123, (byte)0x40, // mode
                                         0, 0, 0, 0, // link
                                         5, 0, 6, 0};                          // uid, gid
          final AsiExtraField field = new AsiExtraField();
          field.parseFromLocalFileData( data, 0, data.length );
          assertEquals( "length dir", data.length,
                        field.getLocalFileDataLength().getValue() );
          assertTrue( "dir, no link", !field.isLink() );
          assertTrue( "dir, is dir", field.isDirectory() );
          assertEquals( "mode dir", DIR_FLAG | 0123, field.getMode() );
          assertEquals( "uid dir", 5, field.getUserId() );
          assertEquals( "gid dir", 6, field.getGroupId() );
      }
  
      public void testReparse4()
          throws Exception
      {
          final byte[] data = new byte[]{0, 0, 0, 0, // bad CRC
                                         0123, (byte)0x40, // mode
                                         0, 0, 0, 0, // link
                                         5, 0, 6, 0};                          // uid, gid
          final AsiExtraField field = new AsiExtraField();
          try
          {
              field.parseFromLocalFileData( data, 0, data.length );
              fail( "should raise bad CRC exception" );
          }
          catch( Exception e )
          {
              assertEquals( "bad CRC checksum 0 instead of ebf018e",
                            e.getMessage() );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test/ExtraFieldUtilsTestCase.java
  
  Index: ExtraFieldUtilsTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip.test;
  
  import junit.framework.TestCase;
  import org.apache.avalon.excalibur.zip.UnixStat;
  import org.apache.avalon.excalibur.zip.AsiExtraField;
  import org.apache.avalon.excalibur.zip.UnrecognizedExtraField;
  import org.apache.avalon.excalibur.zip.ZipShort;
  import org.apache.avalon.excalibur.zip.ZipExtraField;
  import org.apache.avalon.excalibur.zip.ExtraFieldUtils;
  
  /**
   * JUnit testcases ExtraFieldUtils.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  public class ExtraFieldUtilsTestCase
      extends TestCase
      implements UnixStat
  {
      private AsiExtraField m_field;
      private UnrecognizedExtraField m_dummy;
      private byte[] m_data;
      private byte[] m_local;
  
      public ExtraFieldUtilsTestCase( final String name )
      {
          super( name );
      }
  
      public void setUp()
      {
          m_field = new AsiExtraField();
          m_field.setMode( 0755 );
          m_field.setDirectory( true );
          m_dummy = new UnrecognizedExtraField();
          m_dummy.setHeaderId( new ZipShort( 1 ) );
          m_dummy.setLocalFileDataData( new byte[ 0 ] );
          m_dummy.setCentralDirectoryData( new byte[]{0} );
  
          m_local = m_field.getLocalFileDataData();
          final byte[] dummyLocal = m_dummy.getLocalFileDataData();
          m_data = new byte[ 4 + m_local.length + 4 + dummyLocal.length ];
          System.arraycopy( m_field.getHeaderId().getBytes(), 0, m_data, 0, 2 );
          System.arraycopy( m_field.getLocalFileDataLength().getBytes(), 0, m_data, 2, 2 );
          System.arraycopy( m_local, 0, m_data, 4, m_local.length );
          System.arraycopy( m_dummy.getHeaderId().getBytes(), 0, m_data,
                            4 + m_local.length, 2 );
          System.arraycopy( m_dummy.getLocalFileDataLength().getBytes(), 0, m_data,
                            4 + m_local.length + 2, 2 );
          System.arraycopy( dummyLocal, 0, m_data,
                            4 + m_local.length + 4, dummyLocal.length );
  
      }
  
      /**
       * test parser.
       */
      public void testParse() throws Exception
      {
          final ZipExtraField[] extraField = ExtraFieldUtils.parse( m_data );
          assertEquals( "number of fields", 2, extraField.length );
          assertTrue( "type field 1", extraField[ 0 ] instanceof AsiExtraField );
          assertEquals( "mode field 1", 040755,
                        ( (AsiExtraField)extraField[ 0 ] ).getMode() );
          assertTrue( "type field 2", extraField[ 1 ] instanceof UnrecognizedExtraField );
          assertEquals( "data length field 2", 0,
                        extraField[ 1 ].getLocalFileDataLength().getValue() );
  
          final byte[] data2 = new byte[ m_data.length - 1 ];
          System.arraycopy( m_data, 0, data2, 0, data2.length );
          try
          {
              ExtraFieldUtils.parse( data2 );
              fail( "data should be invalid" );
          }
          catch( Exception e )
          {
              assertEquals( "message",
                            "data starting at " + ( 4 + m_local.length ) + " is in unknown format",
                            e.getMessage() );
          }
      }
  
      /**
       * Test merge methods
       */
      public void testMerge()
      {
          final byte[] local =
              ExtraFieldUtils.mergeLocalFileDataData( new ZipExtraField[]{m_field, m_dummy} );
          assertEquals( "local length", m_data.length, local.length );
          for( int i = 0; i < local.length; i++ )
          {
              assertEquals( "local byte " + i, m_data[ i ], local[ i ] );
          }
  
          final byte[] dummyCentral = m_dummy.getCentralDirectoryData();
          final byte[] data2 = new byte[ 4 + m_local.length + 4 + dummyCentral.length ];
          System.arraycopy( m_data, 0, data2, 0, 4 + m_local.length + 2 );
          System.arraycopy( m_dummy.getCentralDirectoryLength().getBytes(), 0,
                            data2, 4 + m_local.length + 2, 2 );
          System.arraycopy( dummyCentral, 0, data2,
                            4 + m_local.length + 4, dummyCentral.length );
  
          final byte[] central =
              ExtraFieldUtils.mergeCentralDirectoryData( new ZipExtraField[]{m_field, m_dummy} );
          assertEquals( "central length", data2.length, central.length );
          for( int i = 0; i < central.length; i++ )
          {
              assertEquals( "central byte " + i, data2[ i ], central[ i ] );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test/ZipEntryTestCase.java
  
  Index: ZipEntryTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip.test;
  
  import java.util.NoSuchElementException;
  import junit.framework.TestCase;
  import org.apache.avalon.excalibur.zip.AsiExtraField;
  import org.apache.avalon.excalibur.zip.UnrecognizedExtraField;
  import org.apache.avalon.excalibur.zip.ZipEntry;
  import org.apache.avalon.excalibur.zip.ZipExtraField;
  import org.apache.avalon.excalibur.zip.ZipShort;
  
  /**
   * JUnit testcases ZipEntry.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  public class ZipEntryTestCase
      extends TestCase
  {
      public ZipEntryTestCase( final String name )
      {
          super( name );
      }
  
      /**
       * test handling of extra fields
       */
      public void testExtraFields()
      {
          final AsiExtraField field = createField();
          final UnrecognizedExtraField extraField = createExtraField();
  
          final ZipEntry entry = new ZipEntry( "test/" );
          entry.setExtraFields( new ZipExtraField[]{field, extraField} );
          final byte[] data1 = entry.getExtra();
          ZipExtraField[] result = entry.getExtraFields();
          assertEquals( "first pass", 2, result.length );
          assertSame( field, result[ 0 ] );
          assertSame( extraField, result[ 1 ] );
  
          UnrecognizedExtraField u2 = new UnrecognizedExtraField();
          u2.setHeaderId( new ZipShort( 1 ) );
          u2.setLocalFileDataData( new byte[]{1} );
  
          entry.addExtraField( u2 );
          byte[] data2 = entry.getExtra();
          result = entry.getExtraFields();
          assertEquals( "second pass", 2, result.length );
          assertSame( field, result[ 0 ] );
          assertSame( u2, result[ 1 ] );
          assertEquals( "length second pass", data1.length + 1, data2.length );
  
          UnrecognizedExtraField u3 = new UnrecognizedExtraField();
          u3.setHeaderId( new ZipShort( 2 ) );
          u3.setLocalFileDataData( new byte[]{1} );
          entry.addExtraField( u3 );
          result = entry.getExtraFields();
          assertEquals( "third pass", 3, result.length );
  
          entry.removeExtraField( new ZipShort( 1 ) );
          byte[] data3 = entry.getExtra();
          result = entry.getExtraFields();
          assertEquals( "fourth pass", 2, result.length );
          assertSame( field, result[ 0 ] );
          assertSame( u3, result[ 1 ] );
          assertEquals( "length fourth pass", data2.length, data3.length );
  
          try
          {
              entry.removeExtraField( new ZipShort( 1 ) );
              fail( "should be no such element" );
          }
          catch( final NoSuchElementException nse )
          {
          }
      }
  
      private UnrecognizedExtraField createExtraField()
      {
          UnrecognizedExtraField extraField = new UnrecognizedExtraField();
          extraField.setHeaderId( new ZipShort( 1 ) );
          extraField.setLocalFileDataData( new byte[ 0 ] );
          return extraField;
      }
  
      private AsiExtraField createField()
      {
          final AsiExtraField field = new AsiExtraField();
          field.setDirectory( true );
          field.setMode( 0755 );
          return field;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test/ZipLongTestCase.java
  
  Index: ZipLongTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip.test;
  
  import junit.framework.TestCase;
  import org.apache.avalon.excalibur.zip.ZipLong;
  
  /**
   * JUnit 3 testcases for org.apache.tools.zip.ZipLong.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  public class ZipLongTestCase
      extends TestCase
  {
  
      public ZipLongTestCase( final String name )
      {
          super( name );
      }
  
      /**
       * Test conversion to bytes.
       */
      public void testToBytes()
      {
          final ZipLong zipLong = new ZipLong( 0x12345678 );
          final byte[] result = zipLong.getBytes();
          assertEquals( "length getBytes", 4, result.length );
          assertEquals( "first byte getBytes", 0x78, result[ 0 ] );
          assertEquals( "second byte getBytes", 0x56, result[ 1 ] );
          assertEquals( "third byte getBytes", 0x34, result[ 2 ] );
          assertEquals( "fourth byte getBytes", 0x12, result[ 3 ] );
      }
  
      /**
       * Test conversion from bytes.
       */
      public void testFromBytes()
      {
          final byte[] value = new byte[]{0x78, 0x56, 0x34, 0x12};
          final ZipLong zipLong = new ZipLong( value );
          assertEquals( "value from bytes", 0x12345678, zipLong.getValue() );
      }
  
      /**
       * Test the contract of the equals method.
       */
      public void testEquals()
      {
          final ZipLong zipLong1 = new ZipLong( 0x12345678 );
          final ZipLong zipLong2 = new ZipLong( 0x12345678 );
          final ZipLong zipLong3 = new ZipLong( 0x87654321 );
  
          assertTrue( "reflexive", zipLong1.equals( zipLong1 ) );
  
          assertTrue( "works", zipLong1.equals( zipLong2 ) );
          assertTrue( "works, part two", !zipLong1.equals( zipLong3 ) );
  
          assertTrue( "symmetric", zipLong2.equals( zipLong1 ) );
  
          assertTrue( "null handling", !zipLong1.equals( null ) );
          assertTrue( "non ZipLong handling", !zipLong1.equals( new Integer( 0x1234 ) ) );
      }
  
      /**
       * Test sign handling.
       */
      public void testSign()
      {
          final ZipLong zipLong =
              new ZipLong( new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF} );
          assertEquals( 0x00000000FFFFFFFFl, zipLong.getValue() );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/zip/src/test/org/apache/avalon/excalibur/zip/test/ZipShortTestCase.java
  
  Index: ZipShortTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.zip.test;
  
  import junit.framework.TestCase;
  import org.apache.avalon.excalibur.zip.ZipShort;
  
  /**
   * JUnit 3 testcases for org.apache.tools.zip.ZipShort.
   *
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  public class ZipShortTestCase
      extends TestCase
  {
      public ZipShortTestCase( String name )
      {
          super( name );
      }
  
      /**
       * Test conversion to bytes.
       */
      public void testToBytes()
      {
          final ZipShort zipShort = new ZipShort( 0x1234 );
          byte[] result = zipShort.getBytes();
          assertEquals( "length getBytes", 2, result.length );
          assertEquals( "first byte getBytes", 0x34, result[ 0 ] );
          assertEquals( "second byte getBytes", 0x12, result[ 1 ] );
      }
  
      /**
       * Test conversion from bytes.
       */
      public void testFromBytes()
      {
          byte[] val = new byte[]{0x34, 0x12};
          final ZipShort zipShort = new ZipShort( val );
          assertEquals( "value from bytes", 0x1234, zipShort.getValue() );
      }
  
      /**
       * Test the contract of the equals method.
       */
      public void testEquals()
      {
          final ZipShort zipShort = new ZipShort( 0x1234 );
          final ZipShort zipShort2 = new ZipShort( 0x1234 );
          final ZipShort zipShort3 = new ZipShort( 0x5678 );
  
          assertTrue( "reflexive", zipShort.equals( zipShort ) );
  
          assertTrue( "works", zipShort.equals( zipShort2 ) );
          assertTrue( "works, part two", !zipShort.equals( zipShort3 ) );
  
          assertTrue( "symmetric", zipShort2.equals( zipShort ) );
  
          assertTrue( "null handling", !zipShort.equals( null ) );
          assertTrue( "non ZipShort handling", !zipShort.equals( new Integer( 0x1234 ) ) );
      }
  
      /**
       * Test sign handling.
       */
      public void testSign()
      {
          final ZipShort zipShort = new ZipShort( new byte[]{(byte)0xFF, (byte)0xFF} );
          assertEquals( 0x0000FFFF, zipShort.getValue() );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:avalon-cvs-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-cvs-help@jakarta.apache.org>


Mime
View raw message