OSDN Git Service

Add new source files
[armadillo/armadillo1.git] / src / jp / sfjp / armadillo / archive / zip / ZipOutputStream.java
1 package jp.sfjp.armadillo.archive.zip;
2
3 import java.io.*;
4 import java.util.zip.*;
5 import jp.sfjp.armadillo.archive.*;
6
7 public final class ZipOutputStream extends ArchiveOutputStream {
8
9     private ZipHeader header;
10     private Deflater deflater;
11     private CRC32 crc;
12     private ZipEntry ongoingEntry;
13
14     public ZipOutputStream(OutputStream os) {
15         super(os);
16         this.header = new ZipHeader();
17         this.deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
18         this.crc = new CRC32();
19         frontStream = os;
20     }
21
22     public void putNextEntry(ZipEntry entry) throws IOException {
23         ensureOpen();
24         if (ongoingEntry != null)
25             closeEntry();
26         assert entry.method != -1;
27         assert entry.uncompsize >= 0;
28         if (entry.isDirectory()) {
29             entry.version = 10;
30             entry.flags &= 0xFFF7;
31             entry.compsize = 0;
32             entry.uncompsize = 0;
33             entry.crc = 0;
34         }
35         else if (entry.method == ZipEntry.STORED) {
36             final int size = (entry.uncompsize >= 0) ? entry.uncompsize : entry.compsize;
37             entry.version = 10;
38             entry.compsize = size;
39             entry.uncompsize = size;
40         }
41         else if (entry.method == ZipEntry.DEFLATED) {
42             entry.version = 20;
43             if (entry.isOnePassMode())
44                 entry.flags |= 0x08; // EXT
45             if (!entry.isDirectory())
46                 frontStream = new DeflaterOutputStream(out, deflater);
47         }
48         else
49             throw new ZipException("unsupported compression method: " + entry.method);
50         ongoingEntry = entry;
51         header.write(out, entry);
52     }
53
54     public void closeEntry() throws IOException {
55         ensureOpen();
56         flush();
57         if (frontStream instanceof DeflaterOutputStream) {
58             DeflaterOutputStream deflaterOutputStream = (DeflaterOutputStream)frontStream;
59             deflaterOutputStream.finish();
60             deflaterOutputStream.flush();
61             frontStream = out;
62         }
63         final int crc32 = (int)(crc.getValue() & 0xFFFFFFFF);
64         ongoingEntry.crc = crc32;
65         if (!ongoingEntry.isDirectory())
66             if (ongoingEntry.hasEXT()) {
67                 ongoingEntry.compsize = deflater.getTotalOut();
68                 ongoingEntry.uncompsize = deflater.getTotalIn();
69                 header.writeEXT(out, ongoingEntry);
70             }
71             else if (ongoingEntry.method == ZipEntry.DEFLATED)
72                 if (deflater.getTotalOut() != ongoingEntry.compsize
73                     || deflater.getTotalIn() != ongoingEntry.uncompsize)
74                     throw new ZipException("invalid header info");
75         deflater.reset();
76         crc.reset();
77         ongoingEntry = null;
78     }
79
80     @Override
81     public void write(int b) throws IOException {
82         super.write(b);
83         crc.update(b);
84     }
85
86     @Override
87     public void write(byte[] b, int off, int len) throws IOException {
88         super.write(b, off, len);
89         crc.update(b, off, len);
90     }
91
92     @Override
93     public void close() throws IOException {
94         try {
95             flush();
96             header.writeEND(out);
97             deflater.end();
98         }
99         finally {
100             header = null;
101             deflater = null;
102             crc = null;
103             ongoingEntry = null;
104             super.close();
105         }
106     }
107
108 }