Source Code Cross Referenced for ZipOutputStream.java in  » 6.0-JDK-Modules » j2me » 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 » 6.0 JDK Modules » j2me » java.util.zip 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)ZipOutputStream.java	1.30 06/10/10
003:         *
004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
006:         *   
007:         * This program is free software; you can redistribute it and/or  
008:         * modify it under the terms of the GNU General Public License version  
009:         * 2 only, as published by the Free Software Foundation.   
010:         *   
011:         * This program is distributed in the hope that it will be useful, but  
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
014:         * General Public License version 2 for more details (a copy is  
015:         * included at /legal/license.txt).   
016:         *   
017:         * You should have received a copy of the GNU General Public License  
018:         * version 2 along with this work; if not, write to the Free Software  
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
020:         * 02110-1301 USA   
021:         *   
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
024:         * information or have any questions. 
025:         *
026:         */
027:
028:        package java.util.zip;
029:
030:        import java.io.OutputStream;
031:        import java.io.IOException;
032:        import java.util.Vector;
033:        import java.util.Hashtable;
034:        import java.util.Enumeration;
035:
036:        /**
037:         * This class implements an output stream filter for writing files in the
038:         * ZIP file format. Includes support for both compressed and uncompressed
039:         * entries.
040:         *
041:         * @author	David Connelly
042:         * @version	1.21, 02/02/00
043:         */
044:        public class ZipOutputStream extends DeflaterOutputStream implements 
045:                ZipConstants {
046:            private ZipEntry entry;
047:            private Vector entries = new Vector();
048:            private Hashtable names = new Hashtable();
049:            private CRC32 crc = new CRC32();
050:            private long written;
051:            private long locoff = 0;
052:            private String comment;
053:            private int method = DEFLATED;
054:            private boolean finished;
055:
056:            private boolean closed = false;
057:
058:            /**
059:             * Check to make sure that this stream has not been closed
060:             */
061:            private void ensureOpen() throws IOException {
062:                if (closed) {
063:                    throw new IOException("Stream closed");
064:                }
065:            }
066:
067:            /**
068:             * Compression method for uncompressed (STORED) entries.
069:             */
070:            public static final int STORED = ZipEntry.STORED;
071:
072:            /**
073:             * Compression method for compressed (DEFLATED) entries.
074:             */
075:            public static final int DEFLATED = ZipEntry.DEFLATED;
076:
077:            /**
078:             * Creates a new ZIP output stream.
079:             * @param out the actual output stream
080:             */
081:            public ZipOutputStream(OutputStream out) {
082:                super (out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
083:                usesDefaultDeflater = true;
084:            }
085:
086:            /**
087:             * Sets the ZIP file comment.
088:             * @param comment the comment string
089:             * @exception IllegalArgumentException if the length of the specified
090:             *		  ZIP file comment is greater than 0xFFFF bytes
091:             */
092:            public void setComment(String comment) {
093:                if (comment != null && comment.length() > 0xffff / 3
094:                        && ZipEntry.getUTF8Length(comment) > 0xffff) {
095:                    throw new IllegalArgumentException(
096:                            "ZIP file comment too long.");
097:                }
098:                this .comment = comment;
099:            }
100:
101:            /**
102:             * Sets the default compression method for subsequent entries. This
103:             * default will be used whenever the compression method is not specified
104:             * for an individual ZIP file entry, and is initially set to DEFLATED.
105:             * @param method the default compression method
106:             * @exception IllegalArgumentException if the specified compression method
107:             *		  is invalid
108:             */
109:            public void setMethod(int method) {
110:                if (method != DEFLATED && method != STORED) {
111:                    throw new IllegalArgumentException(
112:                            "invalid compression method");
113:                }
114:                this .method = method;
115:            }
116:
117:            /**
118:             * Sets the compression level for subsequent entries which are DEFLATED.
119:             * The default setting is DEFAULT_COMPRESSION.
120:             * @param level the compression level (0-9)
121:             * @exception IllegalArgumentException if the compression level is invalid
122:             */
123:            public void setLevel(int level) {
124:                def.setLevel(level);
125:            }
126:
127:            /**
128:             * Begins writing a new ZIP file entry and positions the stream to the
129:             * start of the entry data. Closes the current entry if still active.
130:             * The default compression method will be used if no compression method
131:             * was specified for the entry, and the current time will be used if
132:             * the entry has no set modification time.
133:             * @param e the ZIP entry to be written
134:             * @exception ZipException if a ZIP format error has occurred
135:             * @exception IOException if an I/O error has occurred
136:             */
137:            public void putNextEntry(ZipEntry e) throws IOException {
138:                ensureOpen();
139:                if (entry != null) {
140:                    closeEntry(); // close previous entry
141:                }
142:                if (e.time == -1) {
143:                    e.setTime(System.currentTimeMillis());
144:                }
145:                if (e.method == -1) {
146:                    e.method = method; // use default method
147:                }
148:                switch (e.method) {
149:                case DEFLATED:
150:                    if (e.size == -1 || e.csize == -1 || e.crc == -1) {
151:                        // store size, compressed size, and crc-32 in data descriptor
152:                        // immediately following the compressed entry data
153:                        e.flag = 8;
154:                    } else if (e.size != -1 && e.csize != -1 && e.crc != -1) {
155:                        // store size, compressed size, and crc-32 in LOC header
156:                        e.flag = 0;
157:                    } else {
158:                        throw new ZipException(
159:                                "DEFLATED entry missing size, compressed size, or crc-32");
160:                    }
161:                    e.version = 20;
162:                    break;
163:                case STORED:
164:                    // compressed size, uncompressed size, and crc-32 must all be
165:                    // set for entries using STORED compression method
166:                    if (e.size == -1) {
167:                        e.size = e.csize;
168:                    } else if (e.csize == -1) {
169:                        e.csize = e.size;
170:                    } else if (e.size != e.csize) {
171:                        throw new ZipException(
172:                                "STORED entry where compressed != uncompressed size");
173:                    }
174:                    if (e.size == -1 || e.crc == -1) {
175:                        throw new ZipException(
176:                                "STORED entry missing size, compressed size, or crc-32");
177:                    }
178:                    e.version = 10;
179:                    e.flag = 0;
180:                    break;
181:                default:
182:                    throw new ZipException("unsupported compression method");
183:                }
184:                e.offset = written;
185:                if (names.put(e.name, e) != null) {
186:                    throw new ZipException("duplicate entry: " + e.name);
187:                }
188:                writeLOC(e);
189:                entries.addElement(e);
190:                entry = e;
191:            }
192:
193:            /**
194:             * Closes the current ZIP entry and positions the stream for writing
195:             * the next entry.
196:             * @exception ZipException if a ZIP format error has occurred
197:             * @exception IOException if an I/O error has occurred
198:             */
199:            public void closeEntry() throws IOException {
200:                ensureOpen();
201:                ZipEntry e = entry;
202:                if (e != null) {
203:                    switch (e.method) {
204:                    case DEFLATED:
205:                        def.finish();
206:                        while (!def.finished()) {
207:                            deflate();
208:                        }
209:                        if ((e.flag & 8) == 0) {
210:                            // verify size, compressed size, and crc-32 settings
211:                            if (e.size != def.getTotalIn()) {
212:                                throw new ZipException(
213:                                        "invalid entry size (expected "
214:                                                + e.size + " but got "
215:                                                + def.getTotalIn() + " bytes)");
216:                            }
217:                            if (e.csize != def.getTotalOut()) {
218:                                throw new ZipException(
219:                                        "invalid entry compressed size (expected "
220:                                                + e.csize + " but got "
221:                                                + def.getTotalOut() + " bytes)");
222:                            }
223:                            if (e.crc != crc.getValue()) {
224:                                throw new ZipException(
225:                                        "invalid entry CRC-32 (expected 0x"
226:                                                + Long.toHexString(e.crc)
227:                                                + " but got 0x"
228:                                                + Long.toHexString(crc
229:                                                        .getValue()) + ")");
230:                            }
231:                        } else {
232:                            e.size = def.getTotalIn();
233:                            e.csize = def.getTotalOut();
234:                            e.crc = crc.getValue();
235:                            writeEXT(e);
236:                        }
237:                        def.reset();
238:                        written += e.csize;
239:                        break;
240:                    case STORED:
241:                        // we already know that both e.size and e.csize are the same
242:                        if (e.size != written - locoff) {
243:                            throw new ZipException(
244:                                    "invalid entry size (expected " + e.size
245:                                            + " but got " + (written - locoff)
246:                                            + " bytes)");
247:                        }
248:                        if (e.crc != crc.getValue()) {
249:                            throw new ZipException(
250:                                    "invalid entry crc-32 (expected 0x"
251:                                            + Long.toHexString(e.crc)
252:                                            + " but got 0x"
253:                                            + Long.toHexString(crc.getValue())
254:                                            + ")");
255:                        }
256:                        break;
257:                    default:
258:                        throw new InternalError("invalid compression method");
259:                    }
260:                    crc.reset();
261:                    entry = null;
262:                }
263:            }
264:
265:            /**
266:             * Writes an array of bytes to the current ZIP entry data. This method
267:             * will block until all the bytes are written.
268:             * @param b the data to be written
269:             * @param off the start offset in the data
270:             * @param len the number of bytes that are written
271:             * @exception ZipException if a ZIP file error has occurred
272:             * @exception IOException if an I/O error has occurred
273:             */
274:            public synchronized void write(byte[] b, int off, int len)
275:                    throws IOException {
276:                ensureOpen();
277:                if (off < 0 || len < 0 || off > b.length - len) {
278:                    throw new IndexOutOfBoundsException();
279:                } else if (len == 0) {
280:                    return;
281:                }
282:
283:                if (entry == null) {
284:                    throw new ZipException("no current ZIP entry");
285:                }
286:                switch (entry.method) {
287:                case DEFLATED:
288:                    super .write(b, off, len);
289:                    break;
290:                case STORED:
291:                    written += len;
292:                    if (written - locoff > entry.size) {
293:                        throw new ZipException(
294:                                "attempt to write past end of STORED entry");
295:                    }
296:                    out.write(b, off, len);
297:                    break;
298:                default:
299:                    throw new InternalError("invalid compression method");
300:                }
301:                crc.update(b, off, len);
302:            }
303:
304:            /**
305:             * Finishes writing the contents of the ZIP output stream without closing
306:             * the underlying stream. Use this method when applying multiple filters
307:             * in succession to the same output stream.
308:             * @exception ZipException if a ZIP file error has occurred
309:             * @exception IOException if an I/O exception has occurred
310:             */
311:            public void finish() throws IOException {
312:                ensureOpen();
313:                if (finished) {
314:                    return;
315:                }
316:                if (entry != null) {
317:                    closeEntry();
318:                }
319:                if (entries.size() < 1) {
320:                    throw new ZipException(
321:                            "ZIP file must have at least one entry");
322:                }
323:                // write central directory
324:                long off = written;
325:                Enumeration e = entries.elements();
326:                while (e.hasMoreElements()) {
327:                    writeCEN((ZipEntry) e.nextElement());
328:                }
329:                writeEND(off, written - off);
330:                finished = true;
331:            }
332:
333:            /**
334:             * Closes the ZIP output stream as well as the stream being filtered.
335:             * @exception ZipException if a ZIP file error has occurred
336:             * @exception IOException if an I/O error has occurred
337:             */
338:            public void close() throws IOException {
339:                if (!closed) {
340:                    super .close();
341:                    closed = true;
342:                }
343:            }
344:
345:            /*
346:             * Writes local file (LOC) header for specified entry.
347:             */
348:            private void writeLOC(ZipEntry e) throws IOException {
349:                writeInt(LOCSIG); // LOC header signature
350:                writeShort(e.version); // version needed to extract
351:                writeShort(e.flag); // general purpose bit flag
352:                writeShort(e.method); // compression method
353:                writeInt(e.time); // last modification time
354:                if ((e.flag & 8) == 8) {
355:                    // store size, uncompressed size, and crc-32 in data descriptor
356:                    // immediately following compressed entry data
357:                    writeInt(0);
358:                    writeInt(0);
359:                    writeInt(0);
360:                } else {
361:                    writeInt(e.crc); // crc-32
362:                    writeInt(e.csize); // compressed size
363:                    writeInt(e.size); // uncompressed size
364:                }
365:                byte[] nameBytes = getUTF8Bytes(e.name);
366:                writeShort(nameBytes.length);
367:                writeShort(e.extra != null ? e.extra.length : 0);
368:                writeBytes(nameBytes, 0, nameBytes.length);
369:                if (e.extra != null) {
370:                    writeBytes(e.extra, 0, e.extra.length);
371:                }
372:                locoff = written;
373:            }
374:
375:            /*
376:             * Writes extra data descriptor (EXT) for specified entry.
377:             */
378:            private void writeEXT(ZipEntry e) throws IOException {
379:                writeInt(EXTSIG); // EXT header signature
380:                writeInt(e.crc); // crc-32
381:                writeInt(e.csize); // compressed size
382:                writeInt(e.size); // uncompressed size
383:            }
384:
385:            /*
386:             * Write central directory (CEN) header for specified entry.
387:             */
388:            private void writeCEN(ZipEntry e) throws IOException {
389:                writeInt(CENSIG); // CEN header signature
390:                writeShort(e.version); // version made by
391:                writeShort(e.version); // version needed to extract
392:                writeShort(e.flag); // general purpose bit flag
393:                writeShort(e.method); // compression method
394:                writeInt(e.time); // last modification time
395:                writeInt(e.crc); // crc-32
396:                writeInt(e.csize); // compressed size
397:                writeInt(e.size); // uncompressed size
398:                byte[] nameBytes = getUTF8Bytes(e.name);
399:                writeShort(nameBytes.length);
400:                writeShort(e.extra != null ? e.extra.length : 0);
401:                byte[] commentBytes;
402:                if (e.comment != null) {
403:                    commentBytes = getUTF8Bytes(e.comment);
404:                    writeShort(commentBytes.length);
405:                } else {
406:                    commentBytes = null;
407:                    writeShort(0);
408:                }
409:                writeShort(0); // starting disk number
410:                writeShort(0); // internal file attributes (unused)
411:                writeInt(0); // external file attributes (unused)
412:                writeInt(e.offset); // relative offset of local header
413:                writeBytes(nameBytes, 0, nameBytes.length);
414:                if (e.extra != null) {
415:                    writeBytes(e.extra, 0, e.extra.length);
416:                }
417:                if (commentBytes != null) {
418:                    writeBytes(commentBytes, 0, commentBytes.length);
419:                }
420:            }
421:
422:            /*
423:             * Writes end of central directory (END) header.
424:             */
425:            private void writeEND(long off, long len) throws IOException {
426:                writeInt(ENDSIG); // END record signature
427:                writeShort(0); // number of this disk
428:                writeShort(0); // central directory start disk
429:                writeShort(entries.size()); // number of directory entries on disk
430:                writeShort(entries.size()); // total number of directory entries
431:                writeInt(len); // length of central directory
432:                writeInt(off); // offset of central directory
433:                if (comment != null) { // zip file comment
434:                    byte[] b = getUTF8Bytes(comment);
435:                    writeShort(b.length);
436:                    writeBytes(b, 0, b.length);
437:                } else {
438:                    writeShort(0);
439:                }
440:            }
441:
442:            /*
443:             * Writes a 16-bit short to the output stream in little-endian byte order.
444:             */
445:            private void writeShort(int v) throws IOException {
446:                OutputStream out = this .out;
447:                out.write((v >>> 0) & 0xff);
448:                out.write((v >>> 8) & 0xff);
449:                written += 2;
450:            }
451:
452:            /*
453:             * Writes a 32-bit int to the output stream in little-endian byte order.
454:             */
455:            private void writeInt(long v) throws IOException {
456:                OutputStream out = this .out;
457:                out.write((int) ((v >>> 0) & 0xff));
458:                out.write((int) ((v >>> 8) & 0xff));
459:                out.write((int) ((v >>> 16) & 0xff));
460:                out.write((int) ((v >>> 24) & 0xff));
461:                written += 4;
462:            }
463:
464:            /*
465:             * Writes an array of bytes to the output stream.
466:             */
467:            private void writeBytes(byte[] b, int off, int len)
468:                    throws IOException {
469:                super .out.write(b, off, len);
470:                written += len;
471:            }
472:
473:            /*
474:             * Returns an array of bytes representing the UTF8 encoding
475:             * of the specified String.
476:             */
477:            private static byte[] getUTF8Bytes(String s) {
478:                char[] c = s.toCharArray();
479:                int len = c.length;
480:                // Count the number of encoded bytes...
481:                int count = 0;
482:                for (int i = 0; i < len; i++) {
483:                    int ch = c[i];
484:                    if (ch <= 0x7f) {
485:                        count++;
486:                    } else if (ch <= 0x7ff) {
487:                        count += 2;
488:                    } else {
489:                        count += 3;
490:                    }
491:                }
492:                // Now return the encoded bytes...
493:                byte[] b = new byte[count];
494:                int off = 0;
495:                for (int i = 0; i < len; i++) {
496:                    int ch = c[i];
497:                    if (ch <= 0x7f) {
498:                        b[off++] = (byte) ch;
499:                    } else if (ch <= 0x7ff) {
500:                        b[off++] = (byte) ((ch >> 6) | 0xc0);
501:                        b[off++] = (byte) ((ch & 0x3f) | 0x80);
502:                    } else {
503:                        b[off++] = (byte) ((ch >> 12) | 0xe0);
504:                        b[off++] = (byte) (((ch >> 6) & 0x3f) | 0x80);
505:                        b[off++] = (byte) ((ch & 0x3f) | 0x80);
506:                    }
507:                }
508:                return b;
509:            }
510:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.