Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 435   Methods: 23
NCLOC: 184   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ZipEntry.java 64.3% 56.3% 78.3% 61.6%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.zip;
 56   
 
 57   
 import java.lang.reflect.InvocationTargetException;
 58   
 import java.lang.reflect.Method;
 59   
 import java.util.Vector;
 60   
 import java.util.zip.ZipException;
 61   
 
 62   
 /**
 63   
  * Extension that adds better handling of extra fields and provides
 64   
  * access to the internal and external file attributes.
 65   
  *
 66   
  * @author Stefan Bodewig
 67   
  * @version $Revision: 1.8 $
 68   
  */
 69   
 public class ZipEntry extends java.util.zip.ZipEntry {
 70   
 
 71   
     private static final int PLATFORM_UNIX = 3;
 72   
     private static final int PLATFORM_FAT  = 0;
 73   
 
 74   
     private int internalAttributes = 0;
 75   
     private int platform = PLATFORM_FAT;
 76   
     private long externalAttributes = 0;
 77   
     private Vector extraFields = new Vector();
 78   
 
 79   
     /**
 80   
      * Creates a new zip entry with the specified name.
 81   
      *
 82   
      * @since 1.1
 83   
      */
 84  1476
     public ZipEntry(String name) {
 85  1476
         super(name);
 86   
     }
 87   
 
 88   
     /**
 89   
      * Creates a new zip entry with fields taken from the specified zip entry.
 90   
      *
 91   
      * @since 1.1
 92   
      */
 93  0
     public ZipEntry(java.util.zip.ZipEntry entry) throws ZipException {
 94   
         /*
 95   
          * REVISIT: call super(entry) instead of this stuff in Ant2,
 96   
          *          "copy constructor" has not been available in JDK 1.1
 97   
          */
 98  0
         super(entry.getName());
 99   
 
 100  0
         setComment(entry.getComment());
 101  0
         setMethod(entry.getMethod());
 102  0
         setTime(entry.getTime());
 103   
 
 104  0
         long size = entry.getSize();
 105  0
         if (size > 0) {
 106  0
             setSize(size);
 107   
         }
 108  0
         long cSize = entry.getCompressedSize();
 109  0
         if (cSize > 0) {
 110  0
             setComprSize(cSize);
 111   
         }
 112  0
         long crc = entry.getCrc();
 113  0
         if (crc > 0) {
 114  0
             setCrc(crc);
 115   
         }
 116   
         
 117  0
         byte[] extra = entry.getExtra();
 118  0
         if (extra != null) {
 119  0
             setExtraFields(ExtraFieldUtils.parse(extra));
 120   
         } else {
 121   
             // initializes extra data to an empty byte array
 122  0
             setExtra();
 123   
         }
 124   
     }
 125   
 
 126   
     /**
 127   
      * Creates a new zip entry with fields taken from the specified zip entry.
 128   
      *
 129   
      * @since 1.1
 130   
      */
 131  0
     public ZipEntry(ZipEntry entry) throws ZipException {
 132  0
         this((java.util.zip.ZipEntry) entry);
 133  0
         setInternalAttributes(entry.getInternalAttributes());
 134  0
         setExternalAttributes(entry.getExternalAttributes());
 135  0
         setExtraFields(entry.getExtraFields());
 136   
     }
 137   
 
 138   
     /**
 139   
      * Overwrite clone
 140   
      *
 141   
      * @since 1.1
 142   
      */
 143  0
     public Object clone() {
 144  0
         ZipEntry e = null;
 145  0
         try {
 146  0
             e = new ZipEntry((java.util.zip.ZipEntry) super.clone());
 147   
         } catch (Exception ex) {
 148   
             // impossible as extra data is in correct format
 149  0
             ex.printStackTrace();
 150   
         }
 151  0
         e.setInternalAttributes(getInternalAttributes());
 152  0
         e.setExternalAttributes(getExternalAttributes());
 153  0
         e.setExtraFields(getExtraFields());
 154  0
         return e;
 155   
     }
 156   
 
 157   
     /**
 158   
      * Retrieves the internal file attributes.
 159   
      *
 160   
      * @since 1.1
 161   
      */
 162  1473
     public int getInternalAttributes() {
 163  1473
         return internalAttributes;
 164   
     }
 165   
 
 166   
     /**
 167   
      * Sets the internal file attributes.
 168   
      *
 169   
      * @since 1.1
 170   
      */
 171  0
     public void setInternalAttributes(int value) {
 172  0
         internalAttributes = value;
 173   
     }
 174   
 
 175   
     /**
 176   
      * Retrieves the external file attributes.
 177   
      *
 178   
      * @since 1.1
 179   
      */
 180  1481
     public long getExternalAttributes() {
 181  1481
         return externalAttributes;
 182   
     }
 183   
 
 184   
     /**
 185   
      * Sets the external file attributes.
 186   
      *
 187   
      * @since 1.1
 188   
      */
 189  1477
     public void setExternalAttributes(long value) {
 190  1477
         externalAttributes = value;
 191   
     }
 192   
 
 193   
     /**
 194   
      * Sets Unix permissions in a way that is understood by Info-Zip's
 195   
      * unzip command.
 196   
      *
 197   
      * @since Ant 1.5.2
 198   
      */
 199  1477
     public void setUnixMode(int mode) {
 200  1477
         setExternalAttributes((mode << 16)
 201   
                               // MS-DOS read-only attribute
 202   
                               | ((mode & 0200) == 0 ? 1 : 0)
 203   
                               // MS-DOS directory flag
 204   
                               | (isDirectory() ? 0x10 : 0));
 205  1477
         platform = PLATFORM_UNIX;
 206   
     }
 207   
 
 208   
     /**
 209   
      * Platform specification to put into the &quot;version made
 210   
      * by&quot; part of the central file header.
 211   
      *
 212   
      * @return 0 (MS-DOS FAT) unless {@link #setUnixMode setUnixMode}
 213   
      * has been called, in which case 3 (Unix) will be returned.
 214   
      *
 215   
      * @since Ant 1.5.2
 216   
      */
 217  1479
     public int getPlatform() {
 218  1479
         return platform;
 219   
     }
 220   
 
 221   
     /**
 222   
      * Replaces all currently attached extra fields with the new array.
 223   
      *
 224   
      * @since 1.1
 225   
      */
 226  1
     public void setExtraFields(ZipExtraField[] fields) {
 227  1
         extraFields.removeAllElements();
 228  1
         for (int i = 0; i < fields.length; i++) {
 229  2
             extraFields.addElement(fields[i]);
 230   
         }
 231  1
         setExtra();
 232   
     }
 233   
 
 234   
     /**
 235   
      * Retrieves extra fields.
 236   
      *
 237   
      * @since 1.1
 238   
      */
 239  1481
     public ZipExtraField[] getExtraFields() {
 240  1481
         ZipExtraField[] result = new ZipExtraField[extraFields.size()];
 241  1481
         extraFields.copyInto(result);
 242  1481
         return result;
 243   
     }
 244   
 
 245   
     /**
 246   
      * Adds an extra fields - replacing an already present extra field
 247   
      * of the same type.
 248   
      *
 249   
      * @since 1.1
 250   
      */
 251  2
     public void addExtraField(ZipExtraField ze) {
 252  2
         ZipShort type = ze.getHeaderId();
 253  2
         boolean done = false;
 254  2
         for (int i = 0; !done && i < extraFields.size(); i++) {
 255  4
             if (((ZipExtraField) extraFields.elementAt(i)).getHeaderId().equals(type)) {
 256  1
                 extraFields.setElementAt(ze, i);
 257  1
                 done = true;
 258   
             }
 259   
         }
 260  2
         if (!done) {
 261  1
             extraFields.addElement(ze);
 262   
         }
 263  2
         setExtra();
 264   
     }
 265   
 
 266   
     /**
 267   
      * Remove an extra fields.
 268   
      *
 269   
      * @since 1.1
 270   
      */
 271  2
     public void removeExtraField(ZipShort type) {
 272  2
         boolean done = false;
 273  2
         for (int i = 0; !done && i < extraFields.size(); i++) {
 274  4
             if (((ZipExtraField) extraFields.elementAt(i)).getHeaderId().equals(type)) {
 275  1
                 extraFields.removeElementAt(i);
 276  1
                 done = true;
 277   
             }
 278   
         }
 279  2
         if (!done) {
 280  1
             throw new java.util.NoSuchElementException();
 281   
         }
 282  1
         setExtra();
 283   
     }
 284   
 
 285   
     /**
 286   
      * Throws an Exception if extra data cannot be parsed into extra fields.
 287   
      *
 288   
      * @since 1.1
 289   
      */
 290  0
     public void setExtra(byte[] extra) throws RuntimeException {
 291  0
         try {
 292  0
             setExtraFields(ExtraFieldUtils.parse(extra));
 293   
         } catch (Exception e) {
 294  0
             throw new RuntimeException(e.getMessage());
 295   
         }
 296   
     }
 297   
 
 298   
     /**
 299   
      * Unfortunately {@link java.util.zip.ZipOutputStream
 300   
      * java.util.zip.ZipOutputStream} seems to access the extra data
 301   
      * directly, so overriding getExtra doesn't help - we need to
 302   
      * modify super's data directly.
 303   
      *
 304   
      * @since 1.1
 305   
      */
 306  4
     protected void setExtra() {
 307  4
         super.setExtra(ExtraFieldUtils.mergeLocalFileDataData(getExtraFields()));
 308   
     }
 309   
 
 310   
     /**
 311   
      * Retrieves the extra data for the local file data.
 312   
      *
 313   
      * @since 1.1
 314   
      */
 315  1473
     public byte[] getLocalFileDataExtra() {
 316  1473
         byte[] extra = getExtra();
 317  1473
         return extra != null ? extra : new byte[0];
 318   
     }
 319   
 
 320   
     /**
 321   
      * Retrieves the extra data for the central directory.
 322   
      *
 323   
      * @since 1.1
 324   
      */
 325  1473
     public byte[] getCentralDirectoryExtra() {
 326  1473
         return ExtraFieldUtils.mergeCentralDirectoryData(getExtraFields());
 327   
     }
 328   
 
 329   
     /**
 330   
      * Helper for JDK 1.1 <-> 1.2 incompatibility.
 331   
      *
 332   
      * @since 1.2
 333   
      */
 334   
     private Long compressedSize = null;
 335   
 
 336   
     /**
 337   
      * Make this class work in JDK 1.1 like a 1.2 class.
 338   
      *
 339   
      * <p>This either stores the size for later usage or invokes
 340   
      * setCompressedSize via reflection.</p>
 341   
      *
 342   
      * @since 1.2
 343   
      */
 344  1473
     public void setComprSize(long size) {
 345  1473
         if (haveSetCompressedSize()) {
 346  1473
             performSetCompressedSize(this, size);
 347   
         } else {
 348  0
             compressedSize = new Long(size);
 349   
         }
 350   
     }
 351   
 
 352   
     /**
 353   
      * Override to make this class work in JDK 1.1 like a 1.2 class.
 354   
      *
 355   
      * @since 1.2
 356   
      */
 357  3879
     public long getCompressedSize() {
 358  3879
         if (compressedSize != null) {
 359   
             // has been set explicitly and we are running in a 1.1 VM
 360  0
             return compressedSize.longValue();
 361   
         }
 362  3879
         return super.getCompressedSize();
 363   
     }
 364   
 
 365   
     /**
 366   
      * Helper for JDK 1.1
 367   
      *
 368   
      * @since 1.2
 369   
      */
 370   
     private static Method setCompressedSizeMethod = null;
 371   
     /**
 372   
      * Helper for JDK 1.1
 373   
      *
 374   
      * @since 1.2
 375   
      */
 376   
     private static Object lockReflection = new Object();
 377   
     /**
 378   
      * Helper for JDK 1.1
 379   
      *
 380   
      * @since 1.2
 381   
      */
 382   
     private static boolean triedToGetMethod = false;
 383   
 
 384   
     /**
 385   
      * Are we running JDK 1.2 or higher?
 386   
      *
 387   
      * @since 1.2
 388   
      */
 389  1473
     private static boolean haveSetCompressedSize() {
 390  1473
         checkSCS();
 391  1473
         return setCompressedSizeMethod != null;
 392   
     }
 393   
 
 394   
     /**
 395   
      * Invoke setCompressedSize via reflection.
 396   
      *
 397   
      * @since 1.2
 398   
      */
 399  1473
     private static void performSetCompressedSize(ZipEntry ze, long size) {
 400  1473
         Long[] s = {new Long(size)};
 401  1473
         try {
 402  1473
             setCompressedSizeMethod.invoke(ze, s);
 403   
         } catch (InvocationTargetException ite) {
 404  0
             Throwable nested = ite.getTargetException();
 405  0
             throw new RuntimeException("Exception setting the compressed size "
 406   
                                        + "of " + ze + ": "
 407   
                                        + nested.getMessage());
 408   
         } catch (Throwable other) {
 409  0
             throw new RuntimeException("Exception setting the compressed size "
 410   
                                        + "of " + ze + ": "
 411   
                                        + other.getMessage());
 412   
         }
 413   
     }
 414   
 
 415   
     /**
 416   
      * Try to get a handle to the setCompressedSize method.
 417   
      *
 418   
      * @since 1.2
 419   
      */
 420  1473
     private static void checkSCS() {
 421  1473
         if (!triedToGetMethod) {
 422  1
             synchronized (lockReflection) {
 423  1
                 triedToGetMethod = true;
 424  1
                 try {
 425  1
                     setCompressedSizeMethod = 
 426   
                         java.util.zip.ZipEntry.class.getMethod("setCompressedSize", 
 427   
                                                                new Class[] {Long.TYPE});
 428   
                 } catch (NoSuchMethodException nse) {
 429   
                 }
 430   
             }
 431   
         }
 432   
     }
 433   
 
 434   
 }
 435