OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [util/] [zip/] [ZipOutputStream.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* ZipOutputStream.java --
2
   Copyright (C) 2001, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.util.zip;
40
 
41
import java.io.IOException;
42
import java.io.OutputStream;
43
import java.io.UnsupportedEncodingException;
44
import java.util.Enumeration;
45
import java.util.Vector;
46
 
47
/**
48
 * This is a FilterOutputStream that writes the files into a zip
49
 * archive one after another.  It has a special method to start a new
50
 * zip entry.  The zip entries contains information about the file name
51
 * size, compressed size, CRC, etc.
52
 *
53
 * It includes support for STORED and DEFLATED entries.
54
 *
55
 * This class is not thread safe.
56
 *
57
 * @author Jochen Hoenicke
58
 */
59
public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants
60
{
61
  private Vector entries = new Vector();
62
  private CRC32 crc = new CRC32();
63
  private ZipEntry curEntry = null;
64
 
65
  private int curMethod;
66
  private int size;
67
  private int offset = 0;
68
 
69
  private byte[] zipComment = new byte[0];
70
  private int defaultMethod = DEFLATED;
71
 
72
  /**
73
   * Our Zip version is hard coded to 1.0 resp. 2.0
74
   */
75
  private static final int ZIP_STORED_VERSION = 10;
76
  private static final int ZIP_DEFLATED_VERSION = 20;
77
 
78
  /**
79
   * Compression method.  This method doesn't compress at all.
80
   */
81
  public static final int STORED = 0;
82
 
83
  /**
84
   * Compression method.  This method uses the Deflater.
85
   */
86
  public static final int DEFLATED = 8;
87
 
88
  /**
89
   * Creates a new Zip output stream, writing a zip archive.
90
   * @param out the output stream to which the zip archive is written.
91
   */
92
  public ZipOutputStream(OutputStream out)
93
  {
94
    super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
95
  }
96
 
97
  /**
98
   * Set the zip file comment.
99
   * @param comment the comment.
100
   * @exception IllegalArgumentException if encoding of comment is
101
   * longer than 0xffff bytes.
102
   */
103
  public void setComment(String comment)
104
  {
105
    byte[] commentBytes;
106
    try
107
      {
108
        commentBytes = comment.getBytes("UTF-8");
109
      }
110
    catch (UnsupportedEncodingException uee)
111
      {
112
        throw new AssertionError(uee);
113
      }
114
    if (commentBytes.length > 0xffff)
115
      throw new IllegalArgumentException("Comment too long.");
116
    zipComment = commentBytes;
117
  }
118
 
119
  /**
120
   * Sets default compression method.  If the Zip entry specifies
121
   * another method its method takes precedence.
122
   * @param method the method.
123
   * @exception IllegalArgumentException if method is not supported.
124
   * @see #STORED
125
   * @see #DEFLATED
126
   */
127
  public void setMethod(int method)
128
  {
129
    if (method != STORED && method != DEFLATED)
130
      throw new IllegalArgumentException("Method not supported.");
131
    defaultMethod = method;
132
  }
133
 
134
  /**
135
   * Sets default compression level.  The new level will be activated
136
   * immediately.
137
   * @exception IllegalArgumentException if level is not supported.
138
   * @see Deflater
139
   */
140
  public void setLevel(int level)
141
  {
142
    def.setLevel(level);
143
  }
144
 
145
  /**
146
   * Write an unsigned short in little endian byte order.
147
   */
148
  private void writeLeShort(int value) throws IOException
149
  {
150
    out.write(value & 0xff);
151
    out.write((value >> 8) & 0xff);
152
  }
153
 
154
  /**
155
   * Write an int in little endian byte order.
156
   */
157
  private void writeLeInt(int value) throws IOException
158
  {
159
    writeLeShort(value);
160
    writeLeShort(value >> 16);
161
  }
162
 
163
  /**
164
   * Starts a new Zip entry. It automatically closes the previous
165
   * entry if present.  If the compression method is stored, the entry
166
   * must have a valid size and crc, otherwise all elements (except
167
   * name) are optional, but must be correct if present.  If the time
168
   * is not set in the entry, the current time is used.
169
   * @param entry the entry.
170
   * @exception IOException if an I/O error occured.
171
   * @exception ZipException if stream was finished.
172
   */
173
  public void putNextEntry(ZipEntry entry) throws IOException
174
  {
175
    if (entries == null)
176
      throw new ZipException("ZipOutputStream was finished");
177
 
178
    int method = entry.getMethod();
179
    int flags = 0;
180
    if (method == -1)
181
      method = defaultMethod;
182
 
183
    if (method == STORED)
184
      {
185
        if (entry.getCompressedSize() >= 0)
186
          {
187
            if (entry.getSize() < 0)
188
              entry.setSize(entry.getCompressedSize());
189
            else if (entry.getSize() != entry.getCompressedSize())
190
              throw new ZipException
191
                ("Method STORED, but compressed size != size");
192
          }
193
        else
194
          entry.setCompressedSize(entry.getSize());
195
 
196
        if (entry.getSize() < 0)
197
          throw new ZipException("Method STORED, but size not set");
198
        if (entry.getCrc() < 0)
199
          throw new ZipException("Method STORED, but crc not set");
200
      }
201
    else if (method == DEFLATED)
202
      {
203
        if (entry.getCompressedSize() < 0
204
            || entry.getSize() < 0 || entry.getCrc() < 0)
205
          flags |= 8;
206
      }
207
 
208
    if (curEntry != null)
209
      closeEntry();
210
 
211
    if (entry.getTime() < 0)
212
      entry.setTime(System.currentTimeMillis());
213
 
214
    entry.flags = flags;
215
    entry.offset = offset;
216
    entry.setMethod(method);
217
    curMethod = method;
218
    /* Write the local file header */
219
    writeLeInt(LOCSIG);
220
    writeLeShort(method == STORED
221
                 ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
222
    writeLeShort(flags);
223
    writeLeShort(method);
224
    writeLeInt(entry.getDOSTime());
225
    if ((flags & 8) == 0)
226
      {
227
        writeLeInt((int)entry.getCrc());
228
        writeLeInt((int)entry.getCompressedSize());
229
        writeLeInt((int)entry.getSize());
230
      }
231
    else
232
      {
233
        writeLeInt(0);
234
        writeLeInt(0);
235
        writeLeInt(0);
236
      }
237
    byte[] name;
238
    try
239
      {
240
        name = entry.getName().getBytes("UTF-8");
241
      }
242
    catch (UnsupportedEncodingException uee)
243
      {
244
        throw new AssertionError(uee);
245
      }
246
    if (name.length > 0xffff)
247
      throw new ZipException("Name too long.");
248
    byte[] extra = entry.getExtra();
249
    if (extra == null)
250
      extra = new byte[0];
251
    writeLeShort(name.length);
252
    writeLeShort(extra.length);
253
    out.write(name);
254
    out.write(extra);
255
 
256
    offset += LOCHDR + name.length + extra.length;
257
 
258
    /* Activate the entry. */
259
 
260
    curEntry = entry;
261
    crc.reset();
262
    if (method == DEFLATED)
263
      def.reset();
264
    size = 0;
265
  }
266
 
267
  /**
268
   * Closes the current entry.
269
   * @exception IOException if an I/O error occured.
270
   * @exception ZipException if no entry is active.
271
   */
272
  public void closeEntry() throws IOException
273
  {
274
    if (curEntry == null)
275
      throw new ZipException("No open entry");
276
 
277
    /* First finish the deflater, if appropriate */
278
    if (curMethod == DEFLATED)
279
      super.finish();
280
 
281
    int csize = curMethod == DEFLATED ? def.getTotalOut() : size;
282
 
283
    if (curEntry.getSize() < 0)
284
      curEntry.setSize(size);
285
    else if (curEntry.getSize() != size)
286
      throw new ZipException("size was "+size
287
                             +", but I expected "+curEntry.getSize());
288
 
289
    if (curEntry.getCompressedSize() < 0)
290
      curEntry.setCompressedSize(csize);
291
    else if (curEntry.getCompressedSize() != csize)
292
      throw new ZipException("compressed size was "+csize
293
                             +", but I expected "+curEntry.getSize());
294
 
295
    if (curEntry.getCrc() < 0)
296
      curEntry.setCrc(crc.getValue());
297
    else if (curEntry.getCrc() != crc.getValue())
298
      throw new ZipException("crc was " + Long.toHexString(crc.getValue())
299
                             + ", but I expected "
300
                             + Long.toHexString(curEntry.getCrc()));
301
 
302
    offset += csize;
303
 
304
    /* Now write the data descriptor entry if needed. */
305
    if (curMethod == DEFLATED && (curEntry.flags & 8) != 0)
306
      {
307
        writeLeInt(EXTSIG);
308
        writeLeInt((int)curEntry.getCrc());
309
        writeLeInt((int)curEntry.getCompressedSize());
310
        writeLeInt((int)curEntry.getSize());
311
        offset += EXTHDR;
312
      }
313
 
314
    entries.addElement(curEntry);
315
    curEntry = null;
316
  }
317
 
318
  /**
319
   * Writes the given buffer to the current entry.
320
   * @exception IOException if an I/O error occured.
321
   * @exception ZipException if no entry is active.
322
   */
323
  public void write(byte[] b, int off, int len) throws IOException
324
  {
325
    if (curEntry == null)
326
      throw new ZipException("No open entry.");
327
 
328
    switch (curMethod)
329
      {
330
      case DEFLATED:
331
        super.write(b, off, len);
332
        break;
333
 
334
      case STORED:
335
        out.write(b, off, len);
336
        break;
337
      }
338
 
339
    crc.update(b, off, len);
340
    size += len;
341
  }
342
 
343
  /**
344
   * Finishes the stream.  This will write the central directory at the
345
   * end of the zip file and flush the stream.
346
   * @exception IOException if an I/O error occured.
347
   */
348
  public void finish() throws IOException
349
  {
350
    if (entries == null)
351
      return;
352
    if (curEntry != null)
353
      closeEntry();
354
 
355
    int numEntries = 0;
356
    int sizeEntries = 0;
357
 
358
    Enumeration e = entries.elements();
359
    while (e.hasMoreElements())
360
      {
361
        ZipEntry entry = (ZipEntry) e.nextElement();
362
 
363
        int method = entry.getMethod();
364
        writeLeInt(CENSIG);
365
        writeLeShort(method == STORED
366
                     ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
367
        writeLeShort(method == STORED
368
                     ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
369
        writeLeShort(entry.flags);
370
        writeLeShort(method);
371
        writeLeInt(entry.getDOSTime());
372
        writeLeInt((int)entry.getCrc());
373
        writeLeInt((int)entry.getCompressedSize());
374
        writeLeInt((int)entry.getSize());
375
 
376
        byte[] name;
377
        try
378
          {
379
            name = entry.getName().getBytes("UTF-8");
380
          }
381
        catch (UnsupportedEncodingException uee)
382
          {
383
            throw new AssertionError(uee);
384
          }
385
        if (name.length > 0xffff)
386
          throw new ZipException("Name too long.");
387
        byte[] extra = entry.getExtra();
388
        if (extra == null)
389
          extra = new byte[0];
390
        String str = entry.getComment();
391
        byte[] comment;
392
        try
393
          {
394
            comment = str != null ? str.getBytes("UTF-8") : new byte[0];
395
          }
396
        catch (UnsupportedEncodingException uee)
397
          {
398
            throw new AssertionError(uee);
399
          }
400
        if (comment.length > 0xffff)
401
          throw new ZipException("Comment too long.");
402
 
403
        writeLeShort(name.length);
404
        writeLeShort(extra.length);
405
        writeLeShort(comment.length);
406
        writeLeShort(0); /* disk number */
407
        writeLeShort(0); /* internal file attr */
408
        writeLeInt(0);   /* external file attr */
409
        writeLeInt(entry.offset);
410
 
411
        out.write(name);
412
        out.write(extra);
413
        out.write(comment);
414
        numEntries++;
415
        sizeEntries += CENHDR + name.length + extra.length + comment.length;
416
      }
417
 
418
    writeLeInt(ENDSIG);
419
    writeLeShort(0); /* disk number */
420
    writeLeShort(0); /* disk with start of central dir */
421
    writeLeShort(numEntries);
422
    writeLeShort(numEntries);
423
    writeLeInt(sizeEntries);
424
    writeLeInt(offset);
425
    writeLeShort(zipComment.length);
426
    out.write(zipComment);
427
    out.flush();
428
    entries = null;
429
  }
430
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.