Source Code Cross Referenced for ZipOutputStream.java in  » Apache-Harmony-Java-SE » java-package » java » util » zip » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » java package » java.util.zip 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* 
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         * 
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        package java.util.zip;
019:
020:        import java.io.ByteArrayOutputStream;
021:        import java.io.IOException;
022:        import java.io.OutputStream;
023:        import java.util.Vector;
024:
025:        import org.apache.harmony.archive.internal.nls.Messages;
026:
027:        /**
028:         * ZipOutputStream is used to write ZipEntries to the underlying stream. Output
029:         * from ZipOutputStream conforms to the ZipFile file format.
030:         * 
031:         * @see ZipInputStream
032:         * @see ZipEntry
033:         */
034:        public class ZipOutputStream extends DeflaterOutputStream implements 
035:                ZipConstants {
036:
037:            /** Method for compressed entries */
038:            public static final int DEFLATED = 8;
039:
040:            /** Method for uncompressed entries */
041:            public static final int STORED = 0;
042:
043:            static final int ZIPDataDescriptorFlag = 8;
044:
045:            static final int ZIPLocalHeaderVersionNeeded = 20;
046:
047:            private String comment;
048:
049:            private final Vector<String> entries = new Vector<String>();
050:
051:            private int compressMethod = DEFLATED;
052:
053:            private int compressLevel = Deflater.DEFAULT_COMPRESSION;
054:
055:            private ByteArrayOutputStream cDir = new ByteArrayOutputStream();
056:
057:            private ZipEntry currentEntry;
058:
059:            private final CRC32 crc = new CRC32();
060:
061:            private int offset = 0, curOffset = 0, nameLength;
062:
063:            private byte[] nameBytes;
064:
065:            /**
066:             * Constructs a new ZipOutputStream on p1
067:             * 
068:             * @param p1
069:             *            OutputStream The InputStream to output to
070:             */
071:            public ZipOutputStream(OutputStream p1) {
072:                super (p1, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
073:            }
074:
075:            /**
076:             * Closes the current ZipEntry if any. Closes the underlying output stream.
077:             * If the stream is already closed this method does nothing.
078:             * 
079:             * @exception IOException
080:             *                If an error occurs closing the stream
081:             */
082:            @Override
083:            public void close() throws IOException {
084:                if (out != null) {
085:                    finish();
086:                    out.close();
087:                    out = null;
088:                }
089:            }
090:
091:            /**
092:             * Closes the current ZipEntry. Any entry terminal data is written to the
093:             * underlying stream.
094:             * 
095:             * @exception IOException
096:             *                If an error occurs closing the entry
097:             */
098:            public void closeEntry() throws IOException {
099:                if (cDir == null) {
100:                    throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
101:                }
102:                if (currentEntry == null) {
103:                    return;
104:                }
105:                if (currentEntry.getMethod() == DEFLATED) {
106:                    super .finish();
107:                }
108:
109:                // Verify values for STORED types
110:                if (currentEntry.getMethod() == STORED) {
111:                    if (crc.getValue() != currentEntry.crc) {
112:                        throw new ZipException(Messages.getString("archive.20")); //$NON-NLS-1$
113:                    }
114:                    if (currentEntry.size != crc.tbytes) {
115:                        throw new ZipException(Messages.getString("archive.21")); //$NON-NLS-1$
116:                    }
117:                }
118:                curOffset = LOCHDR;
119:
120:                // Write the DataDescriptor
121:                if (currentEntry.getMethod() != STORED) {
122:                    curOffset += EXTHDR;
123:                    writeLong(out, EXTSIG);
124:                    writeLong(out, currentEntry.crc = crc.getValue());
125:                    writeLong(out, currentEntry.compressedSize = def
126:                            .getTotalOut());
127:                    writeLong(out, currentEntry.size = def.getTotalIn());
128:                }
129:                // Update the CentralDirectory
130:                writeLong(cDir, CENSIG);
131:                writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created
132:                writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract
133:                writeShort(cDir, currentEntry.getMethod() == STORED ? 0
134:                        : ZIPDataDescriptorFlag);
135:                writeShort(cDir, currentEntry.getMethod());
136:                writeShort(cDir, currentEntry.time);
137:                writeShort(cDir, currentEntry.modDate);
138:                writeLong(cDir, crc.getValue());
139:                if (currentEntry.getMethod() == DEFLATED) {
140:                    curOffset += writeLong(cDir, def.getTotalOut());
141:                    writeLong(cDir, def.getTotalIn());
142:                } else {
143:                    curOffset += writeLong(cDir, crc.tbytes);
144:                    writeLong(cDir, crc.tbytes);
145:                }
146:                curOffset += writeShort(cDir, nameLength);
147:                if (currentEntry.extra != null) {
148:                    curOffset += writeShort(cDir, currentEntry.extra.length);
149:                } else {
150:                    writeShort(cDir, 0);
151:                }
152:                String c;
153:                if ((c = currentEntry.getComment()) != null) {
154:                    writeShort(cDir, c.length());
155:                } else {
156:                    writeShort(cDir, 0);
157:                }
158:                writeShort(cDir, 0); // Disk Start
159:                writeShort(cDir, 0); // Internal File Attributes
160:                writeLong(cDir, 0); // External File Attributes
161:                writeLong(cDir, offset);
162:                cDir.write(nameBytes);
163:                nameBytes = null;
164:                if (currentEntry.extra != null) {
165:                    cDir.write(currentEntry.extra);
166:                }
167:                offset += curOffset;
168:                if (c != null) {
169:                    cDir.write(c.getBytes());
170:                }
171:                currentEntry = null;
172:                crc.reset();
173:                def.reset();
174:                done = false;
175:            }
176:
177:            /**
178:             * Indicates that all entries have been written to the stream. Any terminal
179:             * ZipFile information is written to the underlying stream.
180:             * 
181:             * @exception IOException
182:             *                If an error occurs while finishing
183:             */
184:            @Override
185:            public void finish() throws IOException {
186:                if (out == null) {
187:                    throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
188:                }
189:                if (cDir == null) {
190:                    return;
191:                }
192:                if (entries.size() == 0) {
193:                    throw new ZipException(Messages.getString("archive.28")); //$NON-NLS-1$;
194:                }
195:                if (currentEntry != null) {
196:                    closeEntry();
197:                }
198:                int cdirSize = cDir.size();
199:                // Write Central Dir End
200:                writeLong(cDir, ENDSIG);
201:                writeShort(cDir, 0); // Disk Number
202:                writeShort(cDir, 0); // Start Disk
203:                writeShort(cDir, entries.size()); // Number of entries
204:                writeShort(cDir, entries.size()); // Number of entries
205:                writeLong(cDir, cdirSize); // Size of central dir
206:                writeLong(cDir, offset); // Offset of central dir
207:                if (comment != null) {
208:                    writeShort(cDir, comment.length());
209:                    cDir.write(comment.getBytes());
210:                } else {
211:                    writeShort(cDir, 0);
212:                }
213:                // Write the central dir
214:                out.write(cDir.toByteArray());
215:                cDir = null;
216:
217:            }
218:
219:            /**
220:             * Writes entry information for ze to the underlying stream. Data associated
221:             * with the entry can then be written using write(). After data is written
222:             * closeEntry() must be called to complete the storing of ze on the
223:             * underlying stream.
224:             * 
225:             * @param ze
226:             *            ZipEntry to store
227:             * @exception IOException
228:             *                If an error occurs storing the entry
229:             * @see #write
230:             */
231:            public void putNextEntry(ZipEntry ze) throws java.io.IOException {
232:                if (currentEntry != null) {
233:                    closeEntry();
234:                }
235:                if (ze.getMethod() == STORED
236:                        || (compressMethod == STORED && ze.getMethod() == -1)) {
237:                    if (ze.crc == -1) {
238:                        /* [MSG "archive.20", "Crc mismatch"] */
239:                        throw new ZipException(Messages.getString("archive.20")); //$NON-NLS-1$
240:                    }
241:                    if (ze.size == -1 && ze.compressedSize == -1) {
242:                        /* [MSG "archive.21", "Size mismatch"] */
243:                        throw new ZipException(Messages.getString("archive.21")); //$NON-NLS-1$
244:                    }
245:                    if (ze.size != ze.compressedSize && ze.compressedSize != -1
246:                            && ze.size != -1) {
247:                        /* [MSG "archive.21", "Size mismatch"] */
248:                        throw new ZipException(Messages.getString("archive.21")); //$NON-NLS-1$
249:                    }
250:                }
251:                /* [MSG "archive.1E", "Stream is closed"] */
252:                if (cDir == null) {
253:                    throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
254:                }
255:                if (entries.contains(ze.name)) {
256:                    /* [MSG "archive.29", "Entry already exists: {0}"] */
257:                    throw new ZipException(Messages.getString(
258:                            "archive.29", ze.name)); //$NON-NLS-1$
259:                }
260:                nameLength = utf8Count(ze.name);
261:                if (nameLength > 0xffff) {
262:                    /* [MSG "archive.2A", "Name too long: {0}"] */
263:                    throw new IllegalArgumentException(Messages.getString(
264:                            "archive.2A", ze.name)); //$NON-NLS-1$
265:                }
266:
267:                def.setLevel(compressLevel);
268:                currentEntry = ze;
269:                entries.add(currentEntry.name);
270:                if (currentEntry.getMethod() == -1) {
271:                    currentEntry.setMethod(compressMethod);
272:                }
273:                writeLong(out, LOCSIG); // Entry header
274:                writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version
275:                writeShort(out, currentEntry.getMethod() == STORED ? 0
276:                        : ZIPDataDescriptorFlag);
277:                writeShort(out, currentEntry.getMethod());
278:                if (currentEntry.getTime() == -1) {
279:                    currentEntry.setTime(System.currentTimeMillis());
280:                }
281:                writeShort(out, currentEntry.time);
282:                writeShort(out, currentEntry.modDate);
283:
284:                if (currentEntry.getMethod() == STORED) {
285:                    if (currentEntry.size == -1) {
286:                        currentEntry.size = currentEntry.compressedSize;
287:                    } else if (currentEntry.compressedSize == -1) {
288:                        currentEntry.compressedSize = currentEntry.size;
289:                    }
290:                    writeLong(out, currentEntry.crc);
291:                    writeLong(out, currentEntry.size);
292:                    writeLong(out, currentEntry.size);
293:                } else {
294:                    writeLong(out, 0);
295:                    writeLong(out, 0);
296:                    writeLong(out, 0);
297:                }
298:                writeShort(out, nameLength);
299:                if (currentEntry.extra != null) {
300:                    writeShort(out, currentEntry.extra.length);
301:                } else {
302:                    writeShort(out, 0);
303:                }
304:                nameBytes = toUTF8Bytes(currentEntry.name, nameLength);
305:                out.write(nameBytes);
306:                if (currentEntry.extra != null) {
307:                    out.write(currentEntry.extra);
308:                }
309:            }
310:
311:            /**
312:             * Sets the ZipFile comment associated with the file being written.
313:             * 
314:             * @param comment
315:             *            the file comment
316:             */
317:            public void setComment(String comment) {
318:                if (comment.length() > 0xFFFF) {
319:                    throw new IllegalArgumentException(Messages
320:                            .getString("archive.2B")); //$NON-NLS-1$
321:                }
322:                this .comment = comment;
323:            }
324:
325:            /**
326:             * Sets the compression level to be used for writing entry data. This level
327:             * may be set on a per entry basis.
328:             * 
329:             * @param level
330:             *            the compression level, must have a value between 0 and 10.
331:             */
332:            public void setLevel(int level) {
333:                if (level < Deflater.DEFAULT_COMPRESSION
334:                        || level > Deflater.BEST_COMPRESSION) {
335:                    throw new IllegalArgumentException();
336:                }
337:                compressLevel = level;
338:            }
339:
340:            /**
341:             * Sets the compression method to be used when compressing entry data.
342:             * method must be one of STORED or DEFLATED.
343:             * 
344:             * @param method
345:             *            Compression method to use
346:             */
347:            public void setMethod(int method) {
348:                if (method != STORED && method != DEFLATED) {
349:                    throw new IllegalArgumentException();
350:                }
351:                compressMethod = method;
352:
353:            }
354:
355:            private long writeLong(OutputStream os, long i)
356:                    throws java.io.IOException {
357:                // Write out the long value as an unsigned int
358:                os.write((int) (i & 0xFF));
359:                os.write((int) (i >> 8) & 0xFF);
360:                os.write((int) (i >> 16) & 0xFF);
361:                os.write((int) (i >> 24) & 0xFF);
362:                return i;
363:            }
364:
365:            private int writeShort(OutputStream os, int i)
366:                    throws java.io.IOException {
367:                os.write(i & 0xFF);
368:                os.write((i >> 8) & 0xFF);
369:                return i;
370:
371:            }
372:
373:            /**
374:             * Writes data for the current entry to the underlying stream.
375:             * 
376:             * @exception IOException
377:             *                If an error occurs writing to the stream
378:             */
379:            @Override
380:            public void write(byte[] buffer, int off, int nbytes)
381:                    throws java.io.IOException {
382:                // avoid int overflow, check null buf
383:                if ((off < 0 || (nbytes < 0) || off > buffer.length)
384:                        || (buffer.length - off < nbytes)) {
385:                    throw new IndexOutOfBoundsException();
386:                }
387:
388:                if (currentEntry == null) {
389:                    /* [MSG "archive.2C", "No active entry"] */
390:                    throw new ZipException(Messages.getString("archive.2C")); //$NON-NLS-1$
391:                }
392:
393:                if (currentEntry.getMethod() == STORED) {
394:                    out.write(buffer, off, nbytes);
395:                } else {
396:                    super .write(buffer, off, nbytes);
397:                }
398:                crc.update(buffer, off, nbytes);
399:            }
400:
401:            static int utf8Count(String value) {
402:                int total = 0;
403:                for (int i = value.length(); --i >= 0;) {
404:                    char ch = value.charAt(i);
405:                    if (ch < 0x80) {
406:                        total++;
407:                    } else if (ch < 0x800) {
408:                        total += 2;
409:                    } else {
410:                        total += 3;
411:                    }
412:                }
413:                return total;
414:            }
415:
416:            static byte[] toUTF8Bytes(String value, int length) {
417:                byte[] result = new byte[length];
418:                int pos = result.length;
419:                for (int i = value.length(); --i >= 0;) {
420:                    char ch = value.charAt(i);
421:                    if (ch < 0x80) {
422:                        result[--pos] = (byte) ch;
423:                    } else if (ch < 0x800) {
424:                        result[--pos] = (byte) (0x80 | (ch & 0x3f));
425:                        result[--pos] = (byte) (0xc0 | (ch >> 6));
426:                    } else {
427:                        result[--pos] = (byte) (0x80 | (ch & 0x3f));
428:                        result[--pos] = (byte) (0x80 | ((ch >> 6) & 0x3f));
429:                        result[--pos] = (byte) (0xe0 | (ch >> 12));
430:                    }
431:                }
432:                return result;
433:            }
434:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.