Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 685   Methods: 16
NCLOC: 273   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ZipOutputStream.java 77.5% 91% 81.2% 87.8%
 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.io.OutputStream;
 58   
 import java.io.IOException;
 59   
 import java.io.UnsupportedEncodingException;
 60   
 import java.util.Date;
 61   
 import java.util.Hashtable;
 62   
 import java.util.Vector;
 63   
 import java.util.zip.CRC32;
 64   
 import java.util.zip.Deflater;
 65   
 import java.util.zip.DeflaterOutputStream;
 66   
 import java.util.zip.ZipException;
 67   
 
 68   
 /**
 69   
  * Reimplementation of {@link java.util.zip.ZipOutputStream
 70   
  * java.util.zip.ZipOutputStream} that does handle the extended
 71   
  * functionality of this package, especially internal/external file
 72   
  * attributes and extra fields with different layouts for local file
 73   
  * data and central directory entries.
 74   
  *
 75   
  * <p>This implementation will use a Data Descriptor to store size and
 76   
  * CRC information for DEFLATED entries, this means, you don't need to
 77   
  * calculate them yourself.  Unfortunately this is not possible for
 78   
  * the STORED method, here setting the CRC and uncompressed size
 79   
  * information is required before {@link #putNextEntry putNextEntry}
 80   
  * will be called.</p>
 81   
  *
 82   
  * @author Stefan Bodewig
 83   
  * @version $Revision: 1.13 $
 84   
  */
 85   
 public class ZipOutputStream extends DeflaterOutputStream {
 86   
 
 87   
     /**
 88   
      * Current entry.
 89   
      *
 90   
      * @since 1.1
 91   
      */
 92   
     private ZipEntry entry;
 93   
 
 94   
     /**
 95   
      * The file comment.
 96   
      *
 97   
      * @since 1.1
 98   
      */
 99   
     private String comment = "";
 100   
 
 101   
     /**
 102   
      * Compression level for next entry.
 103   
      *
 104   
      * @since 1.1
 105   
      */
 106   
     private int level = Deflater.DEFAULT_COMPRESSION;
 107   
 
 108   
     /**
 109   
      * Has the compression level changed when compared to the last
 110   
      * entry?
 111   
      *
 112   
      * @since 1.5
 113   
      */
 114   
     private boolean hasCompressionLevelChanged = false;
 115   
 
 116   
     /**
 117   
      * Default compression method for next entry.
 118   
      *
 119   
      * @since 1.1
 120   
      */
 121   
     private int method = DEFLATED;
 122   
 
 123   
     /**
 124   
      * List of ZipEntries written so far.
 125   
      *
 126   
      * @since 1.1
 127   
      */
 128   
     private Vector entries = new Vector();
 129   
 
 130   
     /**
 131   
      * CRC instance to avoid parsing DEFLATED data twice.
 132   
      *
 133   
      * @since 1.1
 134   
      */
 135   
     private CRC32 crc = new CRC32();
 136   
 
 137   
     /**
 138   
      * Count the bytes written to out.
 139   
      *
 140   
      * @since 1.1
 141   
      */
 142   
     private long written = 0;
 143   
 
 144   
     /**
 145   
      * Data for current entry started here.
 146   
      *
 147   
      * @since 1.1
 148   
      */
 149   
     private long dataStart = 0;
 150   
 
 151   
     /**
 152   
      * Start of central directory.
 153   
      *
 154   
      * @since 1.1
 155   
      */
 156   
     private ZipLong cdOffset = new ZipLong(0);
 157   
 
 158   
     /**
 159   
      * Length of central directory.
 160   
      *
 161   
      * @since 1.1
 162   
      */
 163   
     private ZipLong cdLength = new ZipLong(0);
 164   
 
 165   
     /**
 166   
      * Helper, a 0 as ZipShort.
 167   
      *
 168   
      * @since 1.1
 169   
      */
 170   
     private static final byte[] ZERO = {0, 0};
 171   
 
 172   
     /**
 173   
      * Helper, a 0 as ZipLong.
 174   
      *
 175   
      * @since 1.1
 176   
      */
 177   
     private static final byte[] LZERO = {0, 0, 0, 0};
 178   
 
 179   
     /**
 180   
      * Holds the offsets of the LFH starts for each entry
 181   
      *
 182   
      * @since 1.1
 183   
      */
 184   
     private Hashtable offsets = new Hashtable();
 185   
 
 186   
     /**
 187   
      * The encoding to use for filenames and the file comment.
 188   
      *
 189   
      * <p>For a list of possible values see <a
 190   
      * 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>.
 191   
      * Defaults to the platform's default character encoding.</p>
 192   
      *
 193   
      * @since 1.3
 194   
      */
 195   
     private String encoding = null;
 196   
 
 197   
     /**
 198   
      * Compression method for deflated entries.
 199   
      *
 200   
      * @since 1.1
 201   
      */
 202   
     public static final int DEFLATED = ZipEntry.DEFLATED;
 203   
 
 204   
     /**
 205   
      * Compression method for deflated entries.
 206   
      *
 207   
      * @since 1.1
 208   
      */
 209   
     public static final int STORED = ZipEntry.STORED;
 210   
 
 211   
     /**
 212   
      * Creates a new ZIP OutputStream filtering the underlying stream.
 213   
      *
 214   
      * @since 1.1
 215   
      */
 216  79
     public ZipOutputStream(OutputStream out) {
 217  79
         super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
 218   
     }
 219   
 
 220   
     /**
 221   
      * The encoding to use for filenames and the file comment.
 222   
      *
 223   
      * <p>For a list of possible values see <a
 224   
      * 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>.
 225   
      * Defaults to the platform's default character encoding.</p>
 226   
      *
 227   
      * @since 1.3
 228   
      */
 229  79
     public void setEncoding(String encoding) {
 230  79
         this.encoding = encoding;
 231   
     }
 232   
 
 233   
     /**
 234   
      * The encoding to use for filenames and the file comment.
 235   
      *
 236   
      * @return null if using the platform's default character encoding.
 237   
      * 
 238   
      * @since 1.3
 239   
      */
 240  0
     public String getEncoding() {
 241  0
         return encoding;
 242   
     }
 243   
 
 244   
     /*
 245   
      * Found out by experiment, that DeflaterOutputStream.close()
 246   
      * will call finish() - so we don't need to override close
 247   
      * ourselves.
 248   
      */
 249   
 
 250   
     /**
 251   
      * Finishs writing the contents and closes this as well as the
 252   
      * underlying stream.
 253   
      *
 254   
      * @since 1.1
 255   
      */
 256  79
     public void finish() throws IOException {
 257  79
         closeEntry();
 258  79
         cdOffset = new ZipLong(written);
 259  79
         for (int i = 0; i < entries.size(); i++) {
 260  1473
             writeCentralFileHeader((ZipEntry) entries.elementAt(i));
 261   
         }
 262  79
         cdLength = new ZipLong(written - cdOffset.getValue());
 263  79
         writeCentralDirectoryEnd();
 264  79
         offsets.clear();
 265  79
         entries.removeAllElements();
 266   
     }
 267   
 
 268   
     /**
 269   
      * Writes all necessary data for this entry.
 270   
      *
 271   
      * @since 1.1
 272   
      */
 273  1552
     public void closeEntry() throws IOException {
 274  1552
         if (entry == null) {
 275  79
             return;
 276   
         }
 277   
 
 278  1473
         long realCrc = crc.getValue();
 279  1473
         crc.reset();
 280   
 
 281  1473
         if (entry.getMethod() == DEFLATED) {
 282  1203
             def.finish();
 283  1203
             while (!def.finished()) {
 284  2424
                 deflate();
 285   
             }
 286   
 
 287  1203
             entry.setSize(def.getTotalIn());
 288  1203
             entry.setComprSize(def.getTotalOut());
 289  1203
             entry.setCrc(realCrc);
 290   
 
 291  1203
             def.reset();
 292   
 
 293  1203
             written += entry.getCompressedSize();
 294   
         } else {
 295  270
             if (entry.getCrc() != realCrc) {
 296  0
                 throw new ZipException("bad CRC checksum for entry "
 297   
                                        + entry.getName() + ": " 
 298   
                                        + Long.toHexString(entry.getCrc())
 299   
                                        + " instead of " 
 300   
                                        + Long.toHexString(realCrc));
 301   
             }
 302   
 
 303  270
             if (entry.getSize() != written - dataStart) {
 304  0
                 throw new ZipException("bad size for entry "
 305   
                                        + entry.getName() + ": " 
 306   
                                        + entry.getSize()
 307   
                                        + " instead of " 
 308   
                                        + (written - dataStart));
 309   
             }
 310   
 
 311   
         }
 312   
 
 313  1473
         writeDataDescriptor(entry);
 314  1473
         entry = null;
 315   
    }
 316   
 
 317   
     /**
 318   
      * Begin writing next entry.
 319   
      *
 320   
      * @since 1.1
 321   
      */
 322  1473
     public void putNextEntry(ZipEntry ze) throws IOException {
 323  1473
         closeEntry();
 324   
 
 325  1473
         entry = ze;
 326  1473
         entries.addElement(entry);
 327   
 
 328  1473
         if (entry.getMethod() == -1) { // not specified
 329  1203
             entry.setMethod(method);
 330   
         }
 331   
         
 332  1473
         if (entry.getTime() == -1) { // not specified
 333  0
             entry.setTime(System.currentTimeMillis());
 334   
         }
 335   
 
 336  1473
         if (entry.getMethod() == STORED) {
 337  270
             if (entry.getSize() == -1) {
 338  0
                 throw new ZipException("uncompressed size is required for STORED method");
 339   
             }
 340  270
             if (entry.getCrc() == -1) {
 341  0
                 throw new ZipException("crc checksum is required for STORED method");
 342   
             }
 343  270
             entry.setComprSize(entry.getSize());
 344  1203
         } else if (hasCompressionLevelChanged) {
 345  0
             def.setLevel(level);
 346  0
             hasCompressionLevelChanged = false;
 347   
         }        
 348  1473
         writeLocalFileHeader(entry);
 349   
     }
 350   
 
 351   
     /**
 352   
      * Set the file comment.
 353   
      *
 354   
      * @since 1.1
 355   
      */
 356  0
     public void setComment(String comment) {
 357  0
         this.comment = comment;
 358   
     }
 359   
 
 360   
     /**
 361   
      * Sets the compression level for subsequent entries.
 362   
      *
 363   
      * <p>Default is Deflater.DEFAULT_COMPRESSION.</p>
 364   
      *
 365   
      * @since 1.1
 366   
      */
 367  0
     public void setLevel(int level) {
 368  0
         hasCompressionLevelChanged = (this.level != level);
 369  0
         this.level = level;
 370   
     }
 371   
 
 372   
     /**
 373   
      * Sets the default compression method for subsequent entries.
 374   
      *
 375   
      * <p>Default is DEFLATED.</p>
 376   
      *
 377   
      * @since 1.1
 378   
      */
 379  79
     public void setMethod(int method) {
 380  79
         this.method = method;
 381   
     }
 382   
 
 383   
     /**
 384   
      * Writes bytes to ZIP entry.
 385   
      *
 386   
      * <p>Override is necessary to support STORED entries, as well as
 387   
      * calculationg CRC automatically for DEFLATED entries.</p>
 388   
      */
 389  4607
     public void write(byte[] b, int offset, int length) throws IOException {
 390  4607
         if (entry.getMethod() == DEFLATED) {
 391  4607
             super.write(b, offset, length);
 392   
         } else {
 393  0
             out.write(b, offset, length);
 394  0
             written += length;
 395   
         }
 396  4607
         crc.update(b, offset, length);
 397   
     }
 398   
 
 399   
     /*
 400   
      * Various ZIP constants
 401   
      */
 402   
     /**
 403   
      * local file header signature
 404   
      *
 405   
      * @since 1.1
 406   
      */
 407   
     protected static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
 408   
     /**
 409   
      * data descriptor signature
 410   
      *
 411   
      * @since 1.1
 412   
      */
 413   
     protected static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
 414   
     /**
 415   
      * central file header signature
 416   
      *
 417   
      * @since 1.1
 418   
      */
 419   
     protected static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
 420   
     /**
 421   
      * end of central dir signature
 422   
      *
 423   
      * @since 1.1
 424   
      */
 425   
     protected static final ZipLong EOCD_SIG = new ZipLong(0X06054B50L);
 426   
 
 427   
     /**
 428   
      * Writes the local file header entry
 429   
      *
 430   
      * @since 1.1
 431   
      */
 432  1473
     protected void writeLocalFileHeader(ZipEntry ze) throws IOException {
 433  1473
         offsets.put(ze, new ZipLong(written));
 434   
 
 435  1473
         out.write(LFH_SIG.getBytes());
 436  1473
         written += 4;
 437   
 
 438   
         // version needed to extract
 439   
         // general purpose bit flag
 440  1473
         if (ze.getMethod() == DEFLATED) {
 441   
             // requires version 2 as we are going to store length info
 442   
             // in the data descriptor
 443  1203
             out.write((new ZipShort(20)).getBytes());
 444   
 
 445   
             // bit3 set to signal, we use a data descriptor
 446  1203
             out.write((new ZipShort(8)).getBytes());
 447   
         } else {
 448  270
             out.write((new ZipShort(10)).getBytes());
 449  270
             out.write(ZERO);
 450   
         }
 451  1473
         written += 4;
 452   
 
 453   
         // compression method
 454  1473
         out.write((new ZipShort(ze.getMethod())).getBytes());
 455  1473
         written += 2;
 456   
 
 457   
         // last mod. time and date
 458  1473
         out.write(toDosTime(new Date(ze.getTime())).getBytes());
 459  1473
         written += 4;
 460   
 
 461   
         // CRC
 462   
         // compressed length
 463   
         // uncompressed length
 464  1473
         if (ze.getMethod() == DEFLATED) {
 465  1203
             out.write(LZERO);
 466  1203
             out.write(LZERO);
 467  1203
             out.write(LZERO);
 468   
         } else {
 469  270
             out.write((new ZipLong(ze.getCrc())).getBytes());
 470  270
             out.write((new ZipLong(ze.getSize())).getBytes());
 471  270
             out.write((new ZipLong(ze.getSize())).getBytes());
 472   
         }
 473  1473
         written += 12;
 474   
         
 475   
         // file name length
 476  1473
         byte[] name = getBytes(ze.getName());
 477  1473
         out.write((new ZipShort(name.length)).getBytes());
 478  1473
         written += 2;
 479   
         
 480   
         // extra field length
 481  1473
         byte[] extra = ze.getLocalFileDataExtra();
 482  1473
         out.write((new ZipShort(extra.length)).getBytes());
 483  1473
         written += 2;
 484   
 
 485   
         // file name
 486  1473
         out.write(name);
 487  1473
         written += name.length;
 488   
 
 489   
         // extra field
 490  1473
         out.write(extra);
 491  1473
         written += extra.length;
 492   
 
 493  1473
         dataStart = written;
 494   
     }
 495   
 
 496   
     /**
 497   
      * Writes the data descriptor entry
 498   
      *
 499   
      * @since 1.1
 500   
      */
 501  1473
     protected void writeDataDescriptor(ZipEntry ze) throws IOException {
 502  1473
         if (ze.getMethod() != DEFLATED) {
 503  270
             return;
 504   
         }
 505  1203
         out.write(DD_SIG.getBytes());
 506  1203
         out.write((new ZipLong(entry.getCrc())).getBytes());
 507  1203
         out.write((new ZipLong(entry.getCompressedSize())).getBytes());
 508  1203
         out.write((new ZipLong(entry.getSize())).getBytes());
 509  1203
         written += 16;
 510   
     }
 511   
 
 512   
     /**
 513   
      * Writes the central file header entry
 514   
      *
 515   
      * @since 1.1
 516   
      */
 517  1473
     protected void writeCentralFileHeader(ZipEntry ze) throws IOException {
 518  1473
         out.write(CFH_SIG.getBytes());
 519  1473
         written += 4;
 520   
 
 521   
         // version made by
 522  1473
         out.write((new ZipShort((ze.getPlatform() << 8) | 20)).getBytes());
 523  1473
         written += 2;
 524   
 
 525   
         // version needed to extract
 526   
         // general purpose bit flag
 527  1473
         if (ze.getMethod() == DEFLATED) {
 528   
             // requires version 2 as we are going to store length info
 529   
             // in the data descriptor
 530  1203
             out.write((new ZipShort(20)).getBytes());
 531   
 
 532   
             // bit3 set to signal, we use a data descriptor
 533  1203
             out.write((new ZipShort(8)).getBytes());
 534   
         } else {
 535  270
             out.write((new ZipShort(10)).getBytes());
 536  270
             out.write(ZERO);
 537   
         }
 538  1473
         written += 4;
 539   
 
 540   
         // compression method
 541  1473
         out.write((new ZipShort(ze.getMethod())).getBytes());
 542  1473
         written += 2;
 543   
 
 544   
         // last mod. time and date
 545  1473
         out.write(toDosTime(new Date(ze.getTime())).getBytes());
 546  1473
         written += 4;
 547   
 
 548   
         // CRC
 549   
         // compressed length
 550   
         // uncompressed length
 551  1473
         out.write((new ZipLong(ze.getCrc())).getBytes());
 552  1473
         out.write((new ZipLong(ze.getCompressedSize())).getBytes());
 553  1473
         out.write((new ZipLong(ze.getSize())).getBytes());
 554  1473
         written += 12;
 555   
         
 556   
         // file name length
 557  1473
         byte[] name = getBytes(ze.getName());
 558  1473
         out.write((new ZipShort(name.length)).getBytes());
 559  1473
         written += 2;
 560   
         
 561   
         // extra field length
 562  1473
         byte[] extra = ze.getCentralDirectoryExtra();
 563  1473
         out.write((new ZipShort(extra.length)).getBytes());
 564  1473
         written += 2;
 565   
 
 566   
         // file comment length
 567  1473
         String comm = ze.getComment();
 568  1473
         if (comm == null) {
 569  1473
             comm = "";
 570   
         }
 571  1473
         byte[] comment = getBytes(comm);
 572  1473
         out.write((new ZipShort(comment.length)).getBytes());
 573  1473
         written += 2;
 574   
         
 575   
         // disk number start
 576  1473
         out.write(ZERO);
 577  1473
         written += 2;
 578   
 
 579   
         // internal file attributes
 580  1473
         out.write((new ZipShort(ze.getInternalAttributes())).getBytes());
 581  1473
         written += 2;
 582   
 
 583   
         // external file attributes
 584  1473
         out.write((new ZipLong(ze.getExternalAttributes())).getBytes());
 585  1473
         written += 4;
 586   
 
 587   
         // relative offset of LFH
 588  1473
         out.write(((ZipLong) offsets.get(ze)).getBytes());
 589  1473
         written += 4;
 590   
 
 591   
         // file name
 592  1473
         out.write(name);
 593  1473
         written += name.length;
 594   
 
 595   
         // extra field
 596  1473
         out.write(extra);
 597  1473
         written += extra.length;
 598   
 
 599   
         // file comment
 600  1473
         out.write(comment);
 601  1473
         written += comment.length;
 602   
     }
 603   
 
 604   
     /**
 605   
      * Writes the &quot;End of central dir record&quot;
 606   
      *
 607   
      * @since 1.1
 608   
      */
 609  79
     protected void writeCentralDirectoryEnd() throws IOException {
 610  79
         out.write(EOCD_SIG.getBytes());
 611   
         
 612   
         // disk numbers
 613  79
         out.write(ZERO);
 614  79
         out.write(ZERO);
 615   
 
 616   
         // number of entries
 617  79
         byte[] num = (new ZipShort(entries.size())).getBytes();
 618  79
         out.write(num);
 619  79
         out.write(num);
 620   
 
 621   
         // length and location of CD
 622  79
         out.write(cdLength.getBytes());
 623  79
         out.write(cdOffset.getBytes());
 624   
 
 625   
         // ZIP file comment
 626  79
         byte[] data = getBytes(comment);
 627  79
         out.write((new ZipShort(data.length)).getBytes());
 628  79
         out.write(data);
 629   
     }
 630   
 
 631   
     /**
 632   
      * Smallest date/time ZIP can handle.
 633   
      *
 634   
      * @since 1.1
 635   
      */
 636   
     private static final ZipLong DOS_TIME_MIN = new ZipLong(0x00002100L);
 637   
 
 638   
     /**
 639   
      * Convert a Date object to a DOS date/time field.
 640   
      *
 641   
      * <p>Stolen from InfoZip's <code>fileio.c</code></p>
 642   
      *
 643   
      * @since 1.1
 644   
      */
 645  2946
     protected static ZipLong toDosTime(Date time) {
 646  2946
         int year = time.getYear() + 1900;
 647  2946
         int month = time.getMonth() + 1;
 648  2946
         if (year < 1980) {
 649  0
             return DOS_TIME_MIN;
 650   
         }
 651  2946
         long value =  ((year - 1980) << 25)
 652   
             |         (month << 21)
 653   
             |         (time.getDate() << 16)
 654   
             |         (time.getHours() << 11)
 655   
             |         (time.getMinutes() << 5)
 656   
             |         (time.getSeconds() >> 1);
 657   
         
 658  2946
         byte[] result = new byte[4];
 659  2946
         result[0] = (byte) ((value & 0xFF));
 660  2946
         result[1] = (byte) ((value & 0xFF00) >> 8);
 661  2946
         result[2] = (byte) ((value & 0xFF0000) >> 16);
 662  2946
         result[3] = (byte) ((value & 0xFF000000l) >> 24);
 663  2946
         return new ZipLong(result);
 664   
     }
 665   
 
 666   
     /**
 667   
      * Retrieve the bytes for the given String in the encoding set for
 668   
      * this Stream.
 669   
      *
 670   
      * @since 1.3
 671   
      */
 672  4498
     protected byte[] getBytes(String name) throws ZipException {
 673  4498
         if (encoding == null) {
 674  3626
             return name.getBytes();
 675   
         } else {
 676  872
             try {
 677  872
                 return name.getBytes(encoding);
 678   
             } catch (UnsupportedEncodingException uee) {
 679  0
                 throw new ZipException(uee.getMessage());
 680   
             }
 681   
         }
 682   
     }
 683   
 
 684   
 }
 685