Source Code Cross Referenced for ZipOutputStream.java in  » Test-Coverage » GroboUtils » net » sourceforge » groboutils » codecoverage » v2 » ant » 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 » Test Coverage » GroboUtils » net.sourceforge.groboutils.codecoverage.v2.ant.zip 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright  2001-2004 The Apache Software Foundation
003:         *
004:         *  Licensed under the Apache License, Version 2.0 (the "License");
005:         *  you may not use this file except in compliance with the License.
006:         *  You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         *  Unless required by applicable law or agreed to in writing, software
011:         *  distributed under the License is distributed on an "AS IS" BASIS,
012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         *  See the License for the specific language governing permissions and
014:         *  limitations under the License.
015:         *
016:         */
017:
018:        package net.sourceforge.groboutils.codecoverage.v2.ant.zip;
019:
020:        import java.io.File;
021:        import java.io.FileOutputStream;
022:        import java.io.FilterOutputStream;
023:        import java.io.IOException;
024:        import java.io.OutputStream;
025:        import java.io.RandomAccessFile;
026:        import java.io.UnsupportedEncodingException;
027:        import java.util.Date;
028:        import java.util.Hashtable;
029:        import java.util.Vector;
030:        import java.util.zip.CRC32;
031:        import java.util.zip.Deflater;
032:        import java.util.zip.ZipException;
033:
034:        /**
035:         * Reimplementation of {@link java.util.zip.ZipOutputStream
036:         * java.util.zip.ZipOutputStream} that does handle the extended
037:         * functionality of this package, especially internal/external file
038:         * attributes and extra fields with different layouts for local file
039:         * data and central directory entries.
040:         *
041:         * <p>This class will try to use {@link java.io.RandomAccessFile
042:         * RandomAccessFile} when you know that the output is going to go to a
043:         * file.</p>
044:         *
045:         * <p>If RandomAccessFile cannot be used, this implementation will use
046:         * a Data Descriptor to store size and CRC information for {@link
047:         * #DEFLATED DEFLATED} entries, this means, you don't need to
048:         * calculate them yourself.  Unfortunately this is not possible for
049:         * the {@link #STORED STORED} method, here setting the CRC and
050:         * uncompressed size information is required before {@link
051:         * #putNextEntry putNextEntry} can be called.</p>
052:         *
053:         * @author Stefan Bodewig
054:         * @author Richard Evans
055:         * @version $Revision: 1.1 $
056:         */
057:        public class ZipOutputStream extends FilterOutputStream {
058:
059:            /**
060:             * Current entry.
061:             *
062:             * @since 1.1
063:             */
064:            private ZipEntry entry;
065:
066:            /**
067:             * The file comment.
068:             *
069:             * @since 1.1
070:             */
071:            private String comment = "";
072:
073:            /**
074:             * Compression level for next entry.
075:             *
076:             * @since 1.1
077:             */
078:            private int level = Deflater.DEFAULT_COMPRESSION;
079:
080:            /**
081:             * Has the compression level changed when compared to the last
082:             * entry?
083:             *
084:             * @since 1.5
085:             */
086:            private boolean hasCompressionLevelChanged = false;
087:
088:            /**
089:             * Default compression method for next entry.
090:             *
091:             * @since 1.1
092:             */
093:            private int method = DEFLATED;
094:
095:            /**
096:             * List of ZipEntries written so far.
097:             *
098:             * @since 1.1
099:             */
100:            private Vector entries = new Vector();
101:
102:            /**
103:             * CRC instance to avoid parsing DEFLATED data twice.
104:             *
105:             * @since 1.1
106:             */
107:            private CRC32 crc = new CRC32();
108:
109:            /**
110:             * Count the bytes written to out.
111:             *
112:             * @since 1.1
113:             */
114:            private long written = 0;
115:
116:            /**
117:             * Data for local header data
118:             *
119:             * @since 1.1
120:             */
121:            private long dataStart = 0;
122:
123:            /**
124:             * Offset for CRC entry in the local file header data for the
125:             * current entry starts here.
126:             *
127:             * @since 1.15
128:             */
129:            private long localDataStart = 0;
130:
131:            /**
132:             * Start of central directory.
133:             *
134:             * @since 1.1
135:             */
136:            private ZipLong cdOffset = new ZipLong(0);
137:
138:            /**
139:             * Length of central directory.
140:             *
141:             * @since 1.1
142:             */
143:            private ZipLong cdLength = new ZipLong(0);
144:
145:            /**
146:             * Helper, a 0 as ZipShort.
147:             *
148:             * @since 1.1
149:             */
150:            private static final byte[] ZERO = { 0, 0 };
151:
152:            /**
153:             * Helper, a 0 as ZipLong.
154:             *
155:             * @since 1.1
156:             */
157:            private static final byte[] LZERO = { 0, 0, 0, 0 };
158:
159:            /**
160:             * Holds the offsets of the LFH starts for each entry
161:             *
162:             * @since 1.1
163:             */
164:            private Hashtable offsets = new Hashtable();
165:
166:            /**
167:             * The encoding to use for filenames and the file comment.
168:             *
169:             * <p>For a list of possible values see <a
170:             * 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>.
171:             * Defaults to the platform's default character encoding.</p>
172:             *
173:             * @since 1.3
174:             */
175:            private String encoding = null;
176:
177:            /**
178:             * Deflater object for output
179:             *
180:             * <p>This attribute is only protected to provide a level of API
181:             * backwards compatibility.  This class used to extend {@link
182:             * java.util.zip.DeflaterOutputStream DeflaterOutputStream} up to
183:             * Revision 1.13.</p>
184:             *
185:             * @since 1.14
186:             */
187:            protected Deflater def = new Deflater(Deflater.DEFAULT_COMPRESSION,
188:                    true);
189:
190:            /**
191:             * Deflater buffer
192:             *
193:             * <p>This attribute is only protected to provide a level of API
194:             * backwards compatibility.  This class used to extend {@link
195:             * java.util.zip.DeflaterOutputStream DeflaterOutputStream} up to
196:             * Revision 1.13.</p>
197:             *
198:             * @since 1.14
199:             */
200:            protected byte[] buf = new byte[512];
201:
202:            /**
203:             * Optional random access output
204:             *
205:             * @since 1.14
206:             */
207:            private RandomAccessFile raf = null;
208:
209:            /**
210:             * Compression method for deflated entries.
211:             *
212:             * @since 1.1
213:             */
214:            public static final int DEFLATED = ZipEntry.DEFLATED;
215:
216:            /**
217:             * Compression method for deflated entries.
218:             *
219:             * @since 1.1
220:             */
221:            public static final int STORED = ZipEntry.STORED;
222:
223:            /**
224:             * Creates a new ZIP OutputStream filtering the underlying stream.
225:             *
226:             * @since 1.1
227:             */
228:            public ZipOutputStream(OutputStream out) {
229:                super (out);
230:            }
231:
232:            /**
233:             * Creates a new ZIP OutputStream writing to a File.  Will use
234:             * random access if possible.
235:             *
236:             * @since 1.14
237:             */
238:            public ZipOutputStream(File file) throws IOException {
239:                super (null);
240:
241:                try {
242:                    raf = new RandomAccessFile(file, "rw");
243:                    raf.setLength(0);
244:                } catch (IOException e) {
245:                    if (raf != null) {
246:                        try {
247:                            raf.close();
248:                        } catch (IOException inner) {
249:                            // ignore
250:                        }
251:                        raf = null;
252:                    }
253:                    out = new FileOutputStream(file);
254:                }
255:            }
256:
257:            /**
258:             * Is this archive writing to a seekable stream (i.e. a random
259:             * access file)?
260:             *
261:             * <p>For seekable streams, you don't need to calculate the CRC or
262:             * uncompressed size for {@link #STORED STORED} entries before
263:             * invoking {@link #putEntry putEntry}.
264:             *
265:             * @since 1.17
266:             */
267:            public boolean isSeekable() {
268:                return raf != null;
269:            }
270:
271:            /**
272:             * The encoding to use for filenames and the file comment.
273:             *
274:             * <p>For a list of possible values see <a
275:             * 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>.
276:             * Defaults to the platform's default character encoding.</p>
277:             *
278:             * @since 1.3
279:             */
280:            public void setEncoding(String encoding) {
281:                this .encoding = encoding;
282:            }
283:
284:            /**
285:             * The encoding to use for filenames and the file comment.
286:             *
287:             * @return null if using the platform's default character encoding.
288:             *
289:             * @since 1.3
290:             */
291:            public String getEncoding() {
292:                return encoding;
293:            }
294:
295:            /**
296:             * Finishs writing the contents and closes this as well as the
297:             * underlying stream.
298:             *
299:             * @since 1.1
300:             */
301:            public void finish() throws IOException {
302:                closeEntry();
303:                cdOffset = new ZipLong(written);
304:                for (int i = 0; i < entries.size(); i++) {
305:                    writeCentralFileHeader((ZipEntry) entries.elementAt(i));
306:                }
307:                cdLength = new ZipLong(written - cdOffset.getValue());
308:                writeCentralDirectoryEnd();
309:                offsets.clear();
310:                entries.removeAllElements();
311:            }
312:
313:            /**
314:             * Writes all necessary data for this entry.
315:             *
316:             * @since 1.1
317:             */
318:            public void closeEntry() throws IOException {
319:                if (entry == null) {
320:                    return;
321:                }
322:
323:                long realCrc = crc.getValue();
324:                crc.reset();
325:
326:                if (entry.getMethod() == DEFLATED) {
327:                    def.finish();
328:                    while (!def.finished()) {
329:                        deflate();
330:                    }
331:
332:                    entry.setSize(def.getTotalIn());
333:                    entry.setComprSize(def.getTotalOut());
334:                    entry.setCrc(realCrc);
335:
336:                    def.reset();
337:
338:                    written += entry.getCompressedSize();
339:                } else if (raf == null) {
340:                    if (entry.getCrc() != realCrc) {
341:                        throw new ZipException("bad CRC checksum for entry "
342:                                + entry.getName() + ": "
343:                                + Long.toHexString(entry.getCrc())
344:                                + " instead of " + Long.toHexString(realCrc));
345:                    }
346:
347:                    if (entry.getSize() != written - dataStart) {
348:                        throw new ZipException("bad size for entry "
349:                                + entry.getName() + ": " + entry.getSize()
350:                                + " instead of " + (written - dataStart));
351:                    }
352:                } else { /* method is STORED and we used RandomAccessFile */
353:                    long size = written - dataStart;
354:
355:                    entry.setSize(size);
356:                    entry.setComprSize(size);
357:                    entry.setCrc(realCrc);
358:                }
359:
360:                // If random access output, write the local file header containing
361:                // the correct CRC and compressed/uncompressed sizes
362:                if (raf != null) {
363:                    long save = raf.getFilePointer();
364:
365:                    raf.seek(localDataStart);
366:                    writeOut((new ZipLong(entry.getCrc())).getBytes());
367:                    writeOut((new ZipLong(entry.getCompressedSize()))
368:                            .getBytes());
369:                    writeOut((new ZipLong(entry.getSize())).getBytes());
370:                    raf.seek(save);
371:                }
372:
373:                writeDataDescriptor(entry);
374:                entry = null;
375:            }
376:
377:            /**
378:             * Begin writing next entry.
379:             *
380:             * @since 1.1
381:             */
382:            public void putNextEntry(ZipEntry ze) throws IOException {
383:                closeEntry();
384:
385:                entry = ze;
386:                entries.addElement(entry);
387:
388:                if (entry.getMethod() == -1) { // not specified
389:                    entry.setMethod(method);
390:                }
391:
392:                if (entry.getTime() == -1) { // not specified
393:                    entry.setTime(System.currentTimeMillis());
394:                }
395:
396:                // Size/CRC not required if RandomAccessFile is used
397:                if (entry.getMethod() == STORED && raf == null) {
398:                    if (entry.getSize() == -1) {
399:                        throw new ZipException(
400:                                "uncompressed size is required for"
401:                                        + " STORED method when not writing to a"
402:                                        + " file");
403:                    }
404:                    if (entry.getCrc() == -1) {
405:                        throw new ZipException(
406:                                "crc checksum is required for STORED"
407:                                        + " method when not writing to a file");
408:                    }
409:                    entry.setComprSize(entry.getSize());
410:                }
411:
412:                if (entry.getMethod() == DEFLATED && hasCompressionLevelChanged) {
413:                    def.setLevel(level);
414:                    hasCompressionLevelChanged = false;
415:                }
416:                writeLocalFileHeader(entry);
417:            }
418:
419:            /**
420:             * Set the file comment.
421:             *
422:             * @since 1.1
423:             */
424:            public void setComment(String comment) {
425:                this .comment = comment;
426:            }
427:
428:            /**
429:             * Sets the compression level for subsequent entries.
430:             *
431:             * <p>Default is Deflater.DEFAULT_COMPRESSION.</p>
432:             *
433:             * @since 1.1
434:             */
435:            public void setLevel(int level) {
436:                hasCompressionLevelChanged = (this .level != level);
437:                this .level = level;
438:            }
439:
440:            /**
441:             * Sets the default compression method for subsequent entries.
442:             *
443:             * <p>Default is DEFLATED.</p>
444:             *
445:             * @since 1.1
446:             */
447:            public void setMethod(int method) {
448:                this .method = method;
449:            }
450:
451:            /**
452:             * Writes bytes to ZIP entry.
453:             */
454:            public void write(byte[] b, int offset, int length)
455:                    throws IOException {
456:                if (entry.getMethod() == DEFLATED) {
457:                    if (length > 0) {
458:                        if (!def.finished()) {
459:                            def.setInput(b, offset, length);
460:                            while (!def.needsInput()) {
461:                                deflate();
462:                            }
463:                        }
464:                    }
465:                } else {
466:                    writeOut(b, offset, length);
467:                    written += length;
468:                }
469:                crc.update(b, offset, length);
470:            }
471:
472:            /**
473:             * Writes a single byte to ZIP entry.
474:             *
475:             * <p>Delegates to the three arg method.</p>
476:             *
477:             * @since 1.14
478:             */
479:            public void write(int b) throws IOException {
480:                byte[] buf = new byte[1];
481:                buf[0] = (byte) (b & 0xff);
482:                write(buf, 0, 1);
483:            }
484:
485:            /**
486:             * Closes this output stream and releases any system resources
487:             * associated with the stream.
488:             *
489:             * @exception  IOException  if an I/O error occurs.
490:             * @since 1.14
491:             */
492:            public void close() throws IOException {
493:                finish();
494:
495:                if (raf != null) {
496:                    raf.close();
497:                }
498:                if (out != null) {
499:                    out.close();
500:                }
501:            }
502:
503:            /**
504:             * Flushes this output stream and forces any buffered output bytes
505:             * to be written out to the stream.
506:             *
507:             * @exception  IOException  if an I/O error occurs.
508:             * @since 1.14
509:             */
510:            public void flush() throws IOException {
511:                if (out == null) {
512:                    out.flush();
513:                }
514:            }
515:
516:            /*
517:             * Various ZIP constants
518:             */
519:            /**
520:             * local file header signature
521:             *
522:             * @since 1.1
523:             */
524:            protected static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
525:            /**
526:             * data descriptor signature
527:             *
528:             * @since 1.1
529:             */
530:            protected static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
531:            /**
532:             * central file header signature
533:             *
534:             * @since 1.1
535:             */
536:            protected static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
537:            /**
538:             * end of central dir signature
539:             *
540:             * @since 1.1
541:             */
542:            protected static final ZipLong EOCD_SIG = new ZipLong(0X06054B50L);
543:
544:            /**
545:             * Writes next block of compressed data to the output stream.
546:             *
547:             * @since 1.14
548:             */
549:            protected final void deflate() throws IOException {
550:                int len = def.deflate(buf, 0, buf.length);
551:                if (len > 0) {
552:                    writeOut(buf, 0, len);
553:                }
554:            }
555:
556:            /**
557:             * Writes the local file header entry
558:             *
559:             * @since 1.1
560:             */
561:            protected void writeLocalFileHeader(ZipEntry ze) throws IOException {
562:                offsets.put(ze, new ZipLong(written));
563:
564:                writeOut(LFH_SIG.getBytes());
565:                written += 4;
566:
567:                // version needed to extract
568:                // general purpose bit flag
569:                if (ze.getMethod() == DEFLATED && raf == null) {
570:                    // requires version 2 as we are going to store length info
571:                    // in the data descriptor
572:                    writeOut((new ZipShort(20)).getBytes());
573:
574:                    // bit3 set to signal, we use a data descriptor
575:                    writeOut((new ZipShort(8)).getBytes());
576:                } else {
577:                    writeOut((new ZipShort(10)).getBytes());
578:                    writeOut(ZERO);
579:                }
580:                written += 4;
581:
582:                // compression method
583:                writeOut((new ZipShort(ze.getMethod())).getBytes());
584:                written += 2;
585:
586:                // last mod. time and date
587:                writeOut(toDosTime(new Date(ze.getTime())).getBytes());
588:                written += 4;
589:
590:                // CRC
591:                // compressed length
592:                // uncompressed length
593:                localDataStart = written;
594:                if (ze.getMethod() == DEFLATED || raf != null) {
595:                    writeOut(LZERO);
596:                    writeOut(LZERO);
597:                    writeOut(LZERO);
598:                } else {
599:                    writeOut((new ZipLong(ze.getCrc())).getBytes());
600:                    writeOut((new ZipLong(ze.getSize())).getBytes());
601:                    writeOut((new ZipLong(ze.getSize())).getBytes());
602:                }
603:                written += 12;
604:
605:                // file name length
606:                byte[] name = getBytes(ze.getName());
607:                writeOut((new ZipShort(name.length)).getBytes());
608:                written += 2;
609:
610:                // extra field length
611:                byte[] extra = ze.getLocalFileDataExtra();
612:                writeOut((new ZipShort(extra.length)).getBytes());
613:                written += 2;
614:
615:                // file name
616:                writeOut(name);
617:                written += name.length;
618:
619:                // extra field
620:                writeOut(extra);
621:                written += extra.length;
622:
623:                dataStart = written;
624:            }
625:
626:            /**
627:             * Writes the data descriptor entry
628:             *
629:             * @since 1.1
630:             */
631:            protected void writeDataDescriptor(ZipEntry ze) throws IOException {
632:                if (ze.getMethod() != DEFLATED || raf != null) {
633:                    return;
634:                }
635:                writeOut(DD_SIG.getBytes());
636:                writeOut((new ZipLong(entry.getCrc())).getBytes());
637:                writeOut((new ZipLong(entry.getCompressedSize())).getBytes());
638:                writeOut((new ZipLong(entry.getSize())).getBytes());
639:                written += 16;
640:            }
641:
642:            /**
643:             * Writes the central file header entry
644:             *
645:             * @since 1.1
646:             */
647:            protected void writeCentralFileHeader(ZipEntry ze)
648:                    throws IOException {
649:                writeOut(CFH_SIG.getBytes());
650:                written += 4;
651:
652:                // version made by
653:                writeOut((new ZipShort((ze.getPlatform() << 8) | 20))
654:                        .getBytes());
655:                written += 2;
656:
657:                // version needed to extract
658:                // general purpose bit flag
659:                if (ze.getMethod() == DEFLATED && raf == null) {
660:                    // requires version 2 as we are going to store length info
661:                    // in the data descriptor
662:                    writeOut((new ZipShort(20)).getBytes());
663:
664:                    // bit3 set to signal, we use a data descriptor
665:                    writeOut((new ZipShort(8)).getBytes());
666:                } else {
667:                    writeOut((new ZipShort(10)).getBytes());
668:                    writeOut(ZERO);
669:                }
670:                written += 4;
671:
672:                // compression method
673:                writeOut((new ZipShort(ze.getMethod())).getBytes());
674:                written += 2;
675:
676:                // last mod. time and date
677:                writeOut(toDosTime(new Date(ze.getTime())).getBytes());
678:                written += 4;
679:
680:                // CRC
681:                // compressed length
682:                // uncompressed length
683:                writeOut((new ZipLong(ze.getCrc())).getBytes());
684:                writeOut((new ZipLong(ze.getCompressedSize())).getBytes());
685:                writeOut((new ZipLong(ze.getSize())).getBytes());
686:                written += 12;
687:
688:                // file name length
689:                byte[] name = getBytes(ze.getName());
690:                writeOut((new ZipShort(name.length)).getBytes());
691:                written += 2;
692:
693:                // extra field length
694:                byte[] extra = ze.getCentralDirectoryExtra();
695:                writeOut((new ZipShort(extra.length)).getBytes());
696:                written += 2;
697:
698:                // file comment length
699:                String comm = ze.getComment();
700:                if (comm == null) {
701:                    comm = "";
702:                }
703:                byte[] comment = getBytes(comm);
704:                writeOut((new ZipShort(comment.length)).getBytes());
705:                written += 2;
706:
707:                // disk number start
708:                writeOut(ZERO);
709:                written += 2;
710:
711:                // internal file attributes
712:                writeOut((new ZipShort(ze.getInternalAttributes())).getBytes());
713:                written += 2;
714:
715:                // external file attributes
716:                writeOut((new ZipLong(ze.getExternalAttributes())).getBytes());
717:                written += 4;
718:
719:                // relative offset of LFH
720:                writeOut(((ZipLong) offsets.get(ze)).getBytes());
721:                written += 4;
722:
723:                // file name
724:                writeOut(name);
725:                written += name.length;
726:
727:                // extra field
728:                writeOut(extra);
729:                written += extra.length;
730:
731:                // file comment
732:                writeOut(comment);
733:                written += comment.length;
734:            }
735:
736:            /**
737:             * Writes the &quot;End of central dir record&quot;
738:             *
739:             * @since 1.1
740:             */
741:            protected void writeCentralDirectoryEnd() throws IOException {
742:                writeOut(EOCD_SIG.getBytes());
743:
744:                // disk numbers
745:                writeOut(ZERO);
746:                writeOut(ZERO);
747:
748:                // number of entries
749:                byte[] num = (new ZipShort(entries.size())).getBytes();
750:                writeOut(num);
751:                writeOut(num);
752:
753:                // length and location of CD
754:                writeOut(cdLength.getBytes());
755:                writeOut(cdOffset.getBytes());
756:
757:                // ZIP file comment
758:                byte[] data = getBytes(comment);
759:                writeOut((new ZipShort(data.length)).getBytes());
760:                writeOut(data);
761:            }
762:
763:            /**
764:             * Smallest date/time ZIP can handle.
765:             *
766:             * @since 1.1
767:             */
768:            private static final ZipLong DOS_TIME_MIN = new ZipLong(0x00002100L);
769:
770:            /**
771:             * Convert a Date object to a DOS date/time field.
772:             *
773:             * <p>Stolen from InfoZip's <code>fileio.c</code></p>
774:             *
775:             * @since 1.1
776:             */
777:            protected static ZipLong toDosTime(Date time) {
778:                int year = time.getYear() + 1900;
779:                int month = time.getMonth() + 1;
780:                if (year < 1980) {
781:                    return DOS_TIME_MIN;
782:                }
783:                long value = ((year - 1980) << 25) | (month << 21)
784:                        | (time.getDate() << 16) | (time.getHours() << 11)
785:                        | (time.getMinutes() << 5) | (time.getSeconds() >> 1);
786:
787:                byte[] result = new byte[4];
788:                result[0] = (byte) ((value & 0xFF));
789:                result[1] = (byte) ((value & 0xFF00) >> 8);
790:                result[2] = (byte) ((value & 0xFF0000) >> 16);
791:                result[3] = (byte) ((value & 0xFF000000L) >> 24);
792:                return new ZipLong(result);
793:            }
794:
795:            /**
796:             * Retrieve the bytes for the given String in the encoding set for
797:             * this Stream.
798:             *
799:             * @since 1.3
800:             */
801:            protected byte[] getBytes(String name) throws ZipException {
802:                if (encoding == null) {
803:                    return name.getBytes();
804:                } else {
805:                    try {
806:                        return name.getBytes(encoding);
807:                    } catch (UnsupportedEncodingException uee) {
808:                        throw new ZipException(uee.getMessage());
809:                    }
810:                }
811:            }
812:
813:            /**
814:             * Write bytes to output or random access file
815:             *
816:             * @since 1.14
817:             */
818:            protected final void writeOut(byte[] data) throws IOException {
819:                writeOut(data, 0, data.length);
820:            }
821:
822:            /**
823:             * Write bytes to output or random access file
824:             *
825:             * @since 1.14
826:             */
827:            protected final void writeOut(byte[] data, int offset, int length)
828:                    throws IOException {
829:                if (raf != null) {
830:                    raf.write(data, offset, length);
831:                } else {
832:                    out.write(data, offset, length);
833:                }
834:            }
835:        }
w_ww_._j___a___v_a_2___s__.__c__o__m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.