Source Code Cross Referenced for ZipFileIndex.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » javac » 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 com.sun » tools » com.sun.tools.javac.zip 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package com.sun.tools.javac.zip;
0002:
0003:        import java.io.*;
0004:        import java.text.MessageFormat;
0005:        import java.util.*;
0006:        import java.util.List;
0007:        import java.util.concurrent.locks.ReentrantLock;
0008:        import java.util.zip.*;
0009:
0010:        /** This class implements building of index of a zip archive and access to it's context.
0011:         *  It also uses prebuild index if available. It supports invocations where it will 
0012:         *  serialize an optimized zip index file to disk.
0013:         * 
0014:         *  In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
0015:         *  when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
0016:         * 
0017:         *  Location where to look for/generate optimized zip index files can be provided using 
0018:         *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is 
0019:         *  the value of the "java.io.tmpdir" system property.
0020:         * 
0021:         *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
0022:         *  created for each archive, used by the compiler for compilation, at location,
0023:         *  specified by "cachezipindexdir" option.
0024:         * 
0025:         * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp 
0026:         * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
0027:         * and the compiler uses the cached indexes.
0028:         */
0029:        public class ZipFileIndex {
0030:            private static final String MIN_CHAR = String
0031:                    .valueOf(Character.MIN_VALUE);
0032:            private static final String MAX_CHAR = String
0033:                    .valueOf(Character.MAX_VALUE);
0034:
0035:            public final static long NOT_MODIFIED = Long.MIN_VALUE;
0036:            private final static com.sun.tools.javac.util.List EMPTY_LIST = com.sun.tools.javac.util.List
0037:                    .nil();
0038:
0039:            private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
0040:            private static ReentrantLock lock = new ReentrantLock();
0041:
0042:            private static boolean NON_BATCH_MODE = System
0043:                    .getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
0044:
0045:            private Map<String, DirectoryEntry> directories = Collections.EMPTY_MAP;
0046:            private Set<String> allDirs = Collections.EMPTY_SET;
0047:
0048:            // ZipFileIndex data entries
0049:            private File zipFile;
0050:            private long zipFileLastModified = NOT_MODIFIED;
0051:            private RandomAccessFile zipRandomFile;
0052:            private ZipFileIndexEntry[] entries;
0053:
0054:            private boolean readFromIndex = false;
0055:            private File zipIndexFile = null;
0056:            private boolean triedToReadIndex = false;
0057:            private int symbolFilePrefixLength = 0;
0058:            private boolean hasPopulatedData = false;
0059:            private long lastReferenceTimeStamp = NOT_MODIFIED;
0060:
0061:            private boolean usePreindexedCache = false;
0062:            private String preindexedCacheLocation = null;
0063:
0064:            private boolean writeIndex = false;
0065:
0066:            /**
0067:             * Returns a list of all ZipFileIndex entries
0068:             *
0069:             * @return A list of ZipFileIndex entries, or an empty list
0070:             */
0071:            public static List<ZipFileIndex> getZipFileIndexes() {
0072:                return getZipFileIndexes(false);
0073:            }
0074:
0075:            /**
0076:             * Returns a list of all ZipFileIndex entries
0077:             *
0078:             * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
0079:             *                   all ZipFileEntry(s) are included into the list.
0080:             * @return A list of ZipFileIndex entries, or an empty list
0081:             */
0082:            public static List<ZipFileIndex> getZipFileIndexes(
0083:                    boolean openedOnly) {
0084:                List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
0085:                lock.lock();
0086:                try {
0087:                    zipFileIndexes.addAll(zipFileIndexCache.values());
0088:
0089:                    if (openedOnly) {
0090:                        for (ZipFileIndex elem : zipFileIndexes) {
0091:                            if (!elem.isOpen()) {
0092:                                zipFileIndexes.remove(elem);
0093:                            }
0094:                        }
0095:                    }
0096:                } finally {
0097:                    lock.unlock();
0098:                }
0099:                return zipFileIndexes;
0100:            }
0101:
0102:            public boolean isOpen() {
0103:                lock.lock();
0104:                try {
0105:                    return zipRandomFile != null;
0106:                } finally {
0107:                    lock.unlock();
0108:                }
0109:            }
0110:
0111:            public static ZipFileIndex getZipFileIndex(File zipFile,
0112:                    int symbolFilePrefixLen, boolean useCache,
0113:                    String cacheLocation, boolean writeIndex)
0114:                    throws IOException {
0115:                ZipFileIndex zi = null;
0116:                lock.lock();
0117:                try {
0118:                    zi = getExistingZipIndex(zipFile);
0119:
0120:                    if (zi == null
0121:                            || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
0122:                        zi = new ZipFileIndex(zipFile);
0123:                        zi.writeIndex = writeIndex;
0124:                        zi.symbolFilePrefixLength = symbolFilePrefixLen;
0125:                        zi.usePreindexedCache = useCache;
0126:                        zi.preindexedCacheLocation = cacheLocation;
0127:                        zipFileIndexCache.put(zipFile, zi);
0128:                    }
0129:                } finally {
0130:                    lock.unlock();
0131:                }
0132:                return zi;
0133:            }
0134:
0135:            public static ZipFileIndex getExistingZipIndex(File zipFile) {
0136:                lock.lock();
0137:                try {
0138:                    return zipFileIndexCache.get(zipFile);
0139:                } finally {
0140:                    lock.unlock();
0141:                }
0142:            }
0143:
0144:            public static void clearCache() {
0145:                lock.lock();
0146:                try {
0147:                    zipFileIndexCache.clear();
0148:                } finally {
0149:                    lock.unlock();
0150:                }
0151:            }
0152:
0153:            public static void clearCache(long timeNotUsed) {
0154:                lock.lock();
0155:                try {
0156:                    Iterator<File> cachedFileIterator = zipFileIndexCache
0157:                            .keySet().iterator();
0158:                    while (cachedFileIterator.hasNext()) {
0159:                        File cachedFile = cachedFileIterator.next();
0160:                        ZipFileIndex cachedZipIndex = zipFileIndexCache
0161:                                .get(cachedFile);
0162:                        if (cachedZipIndex != null) {
0163:                            long timeToTest = cachedZipIndex.lastReferenceTimeStamp
0164:                                    + timeNotUsed;
0165:                            if (timeToTest < cachedZipIndex.lastReferenceTimeStamp
0166:                                    || // Overflow...
0167:                                    System.currentTimeMillis() > timeToTest) {
0168:                                zipFileIndexCache.remove(cachedFile);
0169:                            }
0170:                        }
0171:                    }
0172:                } finally {
0173:                    lock.unlock();
0174:                }
0175:            }
0176:
0177:            public static void removeFromCache(File file) {
0178:                lock.lock();
0179:                try {
0180:                    zipFileIndexCache.remove(file);
0181:                } finally {
0182:                    lock.unlock();
0183:                }
0184:            }
0185:
0186:            /** Sets already opened list of ZipFileIndexes from an outside client
0187:             * of the compiler. This functionality should be used in a non-batch clients of the compiler.
0188:             */
0189:            public static void setOpenedIndexes(List<ZipFileIndex> indexes)
0190:                    throws IllegalStateException {
0191:                lock.lock();
0192:                try {
0193:                    if (zipFileIndexCache.isEmpty()) {
0194:                        throw new IllegalStateException(
0195:                                "Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
0196:                    }
0197:
0198:                    for (ZipFileIndex zfi : indexes) {
0199:                        zipFileIndexCache.put(zfi.zipFile, zfi);
0200:                    }
0201:                } finally {
0202:                    lock.unlock();
0203:                }
0204:            }
0205:
0206:            private ZipFileIndex(File zipFile) {
0207:                this .zipFile = zipFile;
0208:                if (zipFile != null) {
0209:                    this .zipFileLastModified = zipFile.lastModified();
0210:                }
0211:            }
0212:
0213:            public String toString() {
0214:                return "ZipFileIndex of file:(" + zipFile + ")";
0215:            }
0216:
0217:            // Just in case...
0218:            protected void finalize() {
0219:                closeFile();
0220:            }
0221:
0222:            private boolean isUpToDate() {
0223:                if (zipFile != null
0224:                        && ((!NON_BATCH_MODE) || zipFileLastModified == zipFile
0225:                                .lastModified()) && hasPopulatedData) {
0226:                    return true;
0227:                }
0228:
0229:                return false;
0230:            }
0231:
0232:            /**
0233:             * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
0234:             * if its the same as the one at the time the index was build we don't need to reopen anything.
0235:             */
0236:            private void checkIndex() {
0237:                boolean isUpToDate = true;
0238:                if (!isUpToDate()) {
0239:                    closeFile();
0240:                    isUpToDate = false;
0241:                }
0242:
0243:                if (zipRandomFile != null || isUpToDate) {
0244:                    lastReferenceTimeStamp = System.currentTimeMillis();
0245:                    return;
0246:                }
0247:
0248:                hasPopulatedData = true;
0249:
0250:                if (readIndex()) {
0251:                    lastReferenceTimeStamp = System.currentTimeMillis();
0252:                    return;
0253:                }
0254:
0255:                directories = Collections.EMPTY_MAP;
0256:                allDirs = Collections.EMPTY_SET;
0257:
0258:                try {
0259:                    openFile();
0260:                    long totalLength = zipRandomFile.length();
0261:                    ZipDirectory directory = new ZipDirectory(zipRandomFile,
0262:                            0L, totalLength, this );
0263:                    directory.buildIndex();
0264:                } catch (IOException ex) {
0265:                } finally {
0266:                    if (zipRandomFile != null) {
0267:                        closeFile();
0268:                    }
0269:                }
0270:
0271:                lastReferenceTimeStamp = System.currentTimeMillis();
0272:            }
0273:
0274:            private void openFile() throws FileNotFoundException {
0275:                if (zipRandomFile == null && zipFile != null) {
0276:                    zipRandomFile = new RandomAccessFile(zipFile, "r");
0277:                }
0278:            }
0279:
0280:            private void cleanupState() {
0281:                // Make sure there is a valid but empty index if the file doesn't exist
0282:                entries = ZipFileIndexEntry.EMPTY_ARRAY;
0283:                directories = Collections.EMPTY_MAP;
0284:                zipFileLastModified = NOT_MODIFIED;
0285:                allDirs = Collections.EMPTY_SET;
0286:            }
0287:
0288:            public void close() {
0289:                lock.lock();
0290:                try {
0291:                    writeIndex();
0292:                    closeFile();
0293:                } finally {
0294:                    lock.unlock();
0295:                }
0296:            }
0297:
0298:            private void closeFile() {
0299:                if (zipRandomFile != null) {
0300:                    try {
0301:                        zipRandomFile.close();
0302:                    } catch (IOException ex) {
0303:                    }
0304:                    zipRandomFile = null;
0305:                }
0306:            }
0307:
0308:            /**
0309:             * Returns the ZipFileIndexEntry for an absolute path, if there is one.
0310:             */
0311:            public ZipFileIndexEntry getZipIndexEntry(String path) {
0312:                if (File.separatorChar != '/') {
0313:                    path = path.replace('/', File.separatorChar);
0314:                }
0315:                lock.lock();
0316:                try {
0317:                    checkIndex();
0318:                    String lookFor = "";
0319:                    int lastSepIndex = path.lastIndexOf(File.separatorChar);
0320:                    boolean noSeparator = false;
0321:                    if (lastSepIndex == -1) {
0322:                        noSeparator = true;
0323:                    }
0324:
0325:                    DirectoryEntry de = directories.get(noSeparator ? "" : path
0326:                            .substring(0, lastSepIndex));
0327:
0328:                    lookFor = path
0329:                            .substring(noSeparator ? 0 : lastSepIndex + 1);
0330:
0331:                    return de == null ? null : de.getEntry(lookFor);
0332:                } finally {
0333:                    lock.unlock();
0334:                }
0335:            }
0336:
0337:            /**
0338:             * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
0339:             */
0340:            public com.sun.tools.javac.util.List<String> getFiles(String path) {
0341:                if (File.separatorChar != '/') {
0342:                    path = path.replace('/', File.separatorChar);
0343:                }
0344:
0345:                lock.lock();
0346:                try {
0347:                    checkIndex();
0348:
0349:                    DirectoryEntry de = directories.get(path);
0350:                    com.sun.tools.javac.util.List<String> ret = de == null ? null
0351:                            : de.getFiles();
0352:
0353:                    if (ret == null) {
0354:                        return EMPTY_LIST;
0355:                    }
0356:                    return ret;
0357:                } finally {
0358:                    lock.unlock();
0359:                }
0360:            }
0361:
0362:            public List<String> getAllDirectories(String path) {
0363:
0364:                if (File.separatorChar != '/') {
0365:                    path = path.replace('/', File.separatorChar);
0366:                }
0367:
0368:                lock.lock();
0369:                try {
0370:                    checkIndex();
0371:                    path = path.intern();
0372:
0373:                    DirectoryEntry de = directories.get(path);
0374:                    com.sun.tools.javac.util.List<String> ret = de == null ? null
0375:                            : de.getDirectories();
0376:
0377:                    if (ret == null) {
0378:                        return EMPTY_LIST;
0379:                    }
0380:
0381:                    return ret;
0382:                } finally {
0383:                    lock.unlock();
0384:                }
0385:            }
0386:
0387:            public Set<String> getAllDirectories() {
0388:                lock.lock();
0389:                try {
0390:                    checkIndex();
0391:                    if (allDirs == Collections.EMPTY_SET) {
0392:                        Set<String> alldirs = new HashSet<String>();
0393:                        Iterator<String> dirsIter = directories.keySet()
0394:                                .iterator();
0395:                        while (dirsIter.hasNext()) {
0396:                            alldirs.add(new String(dirsIter.next()));
0397:                        }
0398:
0399:                        allDirs = alldirs;
0400:                    }
0401:
0402:                    return allDirs;
0403:                } finally {
0404:                    lock.unlock();
0405:                }
0406:            }
0407:
0408:            /**
0409:             * Tests if a specific path exists in the zip.  This method will return true
0410:             * for file entries and directories.
0411:             *
0412:             * @param path A path within the zip.
0413:             * @return True if the path is a file or dir, false otherwise.
0414:             */
0415:            public boolean contains(String path) {
0416:                lock.lock();
0417:                try {
0418:                    checkIndex();
0419:                    return getZipIndexEntry(path) != null;
0420:                } finally {
0421:                    lock.unlock();
0422:                }
0423:            }
0424:
0425:            public boolean isDirectory(String path) {
0426:                lock.lock();
0427:                try {
0428:                    // The top level in a zip file is always a directory.
0429:                    if (path.length() == 0) {
0430:                        lastReferenceTimeStamp = System.currentTimeMillis();
0431:                        return true;
0432:                    }
0433:
0434:                    if (File.separatorChar != '/')
0435:                        path = path.replace('/', File.separatorChar);
0436:                    checkIndex();
0437:                    return directories.get(path) != null;
0438:                } finally {
0439:                    lock.unlock();
0440:                }
0441:            }
0442:
0443:            public long getLastModified(String path) throws IOException {
0444:                lock.lock();
0445:                try {
0446:                    ZipFileIndexEntry entry = getZipIndexEntry(path);
0447:                    if (entry == null)
0448:                        throw new FileNotFoundException();
0449:                    return entry.getLastModified();
0450:                } finally {
0451:                    lock.unlock();
0452:                }
0453:            }
0454:
0455:            public int length(String path) throws IOException {
0456:                lock.lock();
0457:                try {
0458:                    ZipFileIndexEntry entry = getZipIndexEntry(path);
0459:                    if (entry == null)
0460:                        throw new FileNotFoundException();
0461:
0462:                    if (entry.isDir) {
0463:                        return 0;
0464:                    }
0465:
0466:                    byte[] header = getHeader(entry);
0467:                    // entry is not compressed?
0468:                    if (get2ByteLittleEndian(header, 8) == 0) {
0469:                        return entry.compressedSize;
0470:                    } else {
0471:                        return entry.size;
0472:                    }
0473:                } finally {
0474:                    lock.unlock();
0475:                }
0476:            }
0477:
0478:            public byte[] read(String path) throws IOException {
0479:                lock.lock();
0480:                try {
0481:                    ZipFileIndexEntry entry = getZipIndexEntry(path);
0482:                    if (entry == null)
0483:                        throw new FileNotFoundException(MessageFormat.format(
0484:                                "Path not found in ZIP: {0}", path));
0485:                    return read(entry);
0486:                } finally {
0487:                    lock.unlock();
0488:                }
0489:            }
0490:
0491:            public byte[] read(ZipFileIndexEntry entry) throws IOException {
0492:                lock.lock();
0493:                try {
0494:                    openFile();
0495:                    byte[] result = readBytes(entry);
0496:                    closeFile();
0497:                    return result;
0498:                } finally {
0499:                    lock.unlock();
0500:                }
0501:            }
0502:
0503:            public int read(String path, byte[] buffer) throws IOException {
0504:                lock.lock();
0505:                try {
0506:                    ZipFileIndexEntry entry = getZipIndexEntry(path);
0507:                    if (entry == null)
0508:                        throw new FileNotFoundException();
0509:                    return read(entry, buffer);
0510:                } finally {
0511:                    lock.unlock();
0512:                }
0513:            }
0514:
0515:            public int read(ZipFileIndexEntry entry, byte[] buffer)
0516:                    throws IOException {
0517:                lock.lock();
0518:                try {
0519:                    int result = readBytes(entry, buffer);
0520:                    return result;
0521:                } finally {
0522:                    lock.unlock();
0523:                }
0524:            }
0525:
0526:            private byte[] readBytes(ZipFileIndexEntry entry)
0527:                    throws IOException {
0528:                byte[] header = getHeader(entry);
0529:                int csize = entry.compressedSize;
0530:                byte[] cbuf = new byte[csize];
0531:                zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26)
0532:                        + get2ByteLittleEndian(header, 28));
0533:                zipRandomFile.readFully(cbuf, 0, csize);
0534:
0535:                // is this compressed - offset 8 in the ZipEntry header
0536:                if (get2ByteLittleEndian(header, 8) == 0)
0537:                    return cbuf;
0538:
0539:                int size = entry.size;
0540:                byte[] buf = new byte[size];
0541:                if (inflate(cbuf, buf) != size)
0542:                    throw new IOException("zip file is corrupted");
0543:
0544:                return buf;
0545:            }
0546:
0547:            /**
0548:             *
0549:             */
0550:            private int readBytes(ZipFileIndexEntry entry, byte[] buffer)
0551:                    throws IOException {
0552:                byte[] header = getHeader(entry);
0553:
0554:                // entry is not compressed?
0555:                if (get2ByteLittleEndian(header, 8) == 0) {
0556:                    zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26)
0557:                            + get2ByteLittleEndian(header, 28));
0558:                    int offset = 0;
0559:                    int size = buffer.length;
0560:                    while (offset < size) {
0561:                        int count = zipRandomFile.read(buffer, offset, size
0562:                                - offset);
0563:                        if (count == -1)
0564:                            break;
0565:                        offset += count;
0566:                    }
0567:                    return entry.size;
0568:                }
0569:
0570:                int csize = entry.compressedSize;
0571:                byte[] cbuf = new byte[csize];
0572:                zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26)
0573:                        + get2ByteLittleEndian(header, 28));
0574:                zipRandomFile.readFully(cbuf, 0, csize);
0575:
0576:                int count = inflate(cbuf, buffer);
0577:                if (count == -1)
0578:                    throw new IOException("zip file is corrupted");
0579:                return entry.size;
0580:            }
0581:
0582:            //----------------------------------------------------------------------------
0583:            // Zip utilities
0584:            //----------------------------------------------------------------------------
0585:
0586:            private byte[] getHeader(ZipFileIndexEntry entry)
0587:                    throws IOException {
0588:                zipRandomFile.seek(entry.offset);
0589:                byte[] header = new byte[30];
0590:                zipRandomFile.readFully(header);
0591:                if (get4ByteLittleEndian(header, 0) != 0x04034b50)
0592:                    throw new IOException("zip file is corrupted");
0593:                if ((get2ByteLittleEndian(header, 6) & 1) != 0)
0594:                    throw new IOException("zip file is encrypted"); // offset 6 in the header of the ZipFileEntry
0595:                return header;
0596:            }
0597:
0598:            /*
0599:             * Inflate using the java.util.zip.Inflater class
0600:             */
0601:            private static Inflater inflater;
0602:
0603:            private int inflate(byte[] src, byte[] dest) {
0604:
0605:                // construct the inflater object or reuse an existing one
0606:                if (inflater == null)
0607:                    inflater = new Inflater(true);
0608:
0609:                synchronized (inflater) {
0610:                    inflater.reset();
0611:                    inflater.setInput(src);
0612:                    try {
0613:                        return inflater.inflate(dest);
0614:                    } catch (DataFormatException ex) {
0615:                        return -1;
0616:                    }
0617:                }
0618:            }
0619:
0620:            /**
0621:             * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
0622:             * endian format.
0623:             */
0624:            private static int get2ByteLittleEndian(byte[] buf, int pos) {
0625:                return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8);
0626:            }
0627:
0628:            /**
0629:             * return the 4 bytes buf[i..i+3] as an integer in little endian format.
0630:             */
0631:            private static int get4ByteLittleEndian(byte[] buf, int pos) {
0632:                return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8)
0633:                        + ((buf[pos + 2] & 0xFF) << 16)
0634:                        + ((buf[pos + 3] & 0xFF) << 24);
0635:            }
0636:
0637:            /* ----------------------------------------------------------------------------
0638:             * ZipDirectory
0639:             * ----------------------------------------------------------------------------*/
0640:
0641:            private class ZipDirectory {
0642:                private String lastDir;
0643:                private int lastStart;
0644:                private int lastLen;
0645:
0646:                byte[] zipDir;
0647:                RandomAccessFile zipRandomFile = null;
0648:                ZipFileIndex zipFileIndex = null;
0649:
0650:                public ZipDirectory(RandomAccessFile zipRandomFile, long start,
0651:                        long end, ZipFileIndex index) throws IOException {
0652:                    this .zipRandomFile = zipRandomFile;
0653:                    this .zipFileIndex = index;
0654:
0655:                    findCENRecord(start, end);
0656:                }
0657:
0658:                /*
0659:                 * Reads zip file central directory.
0660:                 * For more details see readCEN in zip_util.c from the JDK sources.
0661:                 * This is a Java port of that function.
0662:                 */
0663:                private void findCENRecord(long start, long end)
0664:                        throws IOException {
0665:                    long totalLength = end - start;
0666:                    int endbuflen = 1024;
0667:                    byte[] endbuf = new byte[endbuflen];
0668:                    long endbufend = end - start;
0669:
0670:                    // There is a variable-length field after the dir offset record. We need to do consequential search.
0671:                    while (endbufend >= 22) {
0672:                        if (endbufend < endbuflen)
0673:                            endbuflen = (int) endbufend;
0674:                        long endbufpos = endbufend - endbuflen;
0675:                        zipRandomFile.seek(start + endbufpos);
0676:                        zipRandomFile.readFully(endbuf, 0, endbuflen);
0677:                        int i = endbuflen - 22;
0678:                        while (i >= 0
0679:                                && !(endbuf[i] == 0x50 && endbuf[i + 1] == 0x4b
0680:                                        && endbuf[i + 2] == 0x05
0681:                                        && endbuf[i + 3] == 0x06 && endbufpos
0682:                                        + i + 22
0683:                                        + get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
0684:                            i--;
0685:                        }
0686:
0687:                        if (i >= 0) {
0688:                            zipDir = new byte[get4ByteLittleEndian(endbuf,
0689:                                    i + 12) + 2];
0690:                            zipDir[0] = endbuf[i + 10];
0691:                            zipDir[1] = endbuf[i + 11];
0692:                            zipRandomFile.seek(start
0693:                                    + get4ByteLittleEndian(endbuf, i + 16));
0694:                            zipRandomFile.readFully(zipDir, 2,
0695:                                    zipDir.length - 2);
0696:                            return;
0697:                        } else {
0698:                            endbufend = endbufpos + 21;
0699:                        }
0700:                    }
0701:                    throw new IOException("bad zip file");
0702:                }
0703:
0704:                private void buildIndex() throws IOException {
0705:                    int entryCount = get2ByteLittleEndian(zipDir, 0);
0706:
0707:                    entries = new ZipFileIndexEntry[entryCount];
0708:                    // Add each of the files
0709:                    if (entryCount > 0) {
0710:                        directories = new HashMap();
0711:                        ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
0712:                        int pos = 2;
0713:                        for (int i = 0; i < entryCount; i++) {
0714:                            pos = readEntry(pos, entryList, directories);
0715:                        }
0716:
0717:                        // Add the accumulated dirs into the same list
0718:                        Iterator i = directories.keySet().iterator();
0719:                        while (i.hasNext()) {
0720:                            ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry(
0721:                                    (String) i.next());
0722:                            zipFileIndexEntry.isDir = true;
0723:                            entryList.add(zipFileIndexEntry);
0724:                        }
0725:
0726:                        entries = entryList
0727:                                .toArray(new ZipFileIndexEntry[entryList.size()]);
0728:                        Arrays.sort(entries);
0729:                    } else {
0730:                        cleanupState();
0731:                    }
0732:                }
0733:
0734:                private int readEntry(int pos, List entryList, Map directories)
0735:                        throws IOException {
0736:                    if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
0737:                        throw new IOException("bad folder entry");
0738:                    }
0739:
0740:                    int dirStart = pos + 46;
0741:                    int fileStart = dirStart;
0742:                    int fileEnd = fileStart
0743:                            + get2ByteLittleEndian(zipDir, pos + 28);
0744:
0745:                    if (zipFileIndex.symbolFilePrefixLength != 0
0746:                            && ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
0747:                        dirStart += zipFileIndex.symbolFilePrefixLength;
0748:                        fileStart += zipFileIndex.symbolFilePrefixLength;
0749:                    }
0750:
0751:                    // Use the OS's path separator. Keep the position of the last one.
0752:                    for (int index = fileStart; index < fileEnd; index++) {
0753:                        byte nextByte = zipDir[index];
0754:                        if (nextByte == (byte) '\\' || nextByte == (byte) '/') {
0755:                            zipDir[index] = (byte) File.separatorChar;
0756:                            fileStart = index + 1;
0757:                        }
0758:                    }
0759:
0760:                    String directory = null;
0761:                    if (fileStart == dirStart)
0762:                        directory = "";
0763:                    else if (lastDir != null
0764:                            && lastLen == fileStart - dirStart - 1) {
0765:                        int index = lastLen - 1;
0766:                        while (zipDir[lastStart + index] == zipDir[dirStart
0767:                                + index]) {
0768:                            if (index == 0) {
0769:                                directory = lastDir;
0770:                                break;
0771:                            }
0772:                            index--;
0773:                        }
0774:                    }
0775:
0776:                    // Sub directories
0777:                    if (directory == null) {
0778:                        lastStart = dirStart;
0779:                        lastLen = fileStart - dirStart - 1;
0780:
0781:                        directory = new String(zipDir, dirStart, lastLen,
0782:                                "UTF-8").intern();
0783:                        lastDir = directory;
0784:
0785:                        // Enter also all the parent directories
0786:                        String tempDirectory = directory;
0787:
0788:                        while (directories.get(tempDirectory) == null) {
0789:                            directories.put(tempDirectory, new DirectoryEntry(
0790:                                    tempDirectory, zipFileIndex));
0791:                            int separator = tempDirectory
0792:                                    .lastIndexOf(File.separatorChar);
0793:                            if (separator == -1)
0794:                                break;
0795:                            tempDirectory = tempDirectory.substring(0,
0796:                                    separator);
0797:                        }
0798:                    } else {
0799:                        directory = directory.intern();
0800:                        if (directories.get(directory) == null) {
0801:                            directories.put(directory, new DirectoryEntry(
0802:                                    directory, zipFileIndex));
0803:                        }
0804:                    }
0805:
0806:                    // For each dir create also a file
0807:                    if (fileStart != fileEnd) {
0808:                        ZipFileIndexEntry entry = new ZipFileIndexEntry(
0809:                                directory, new String(zipDir, fileStart,
0810:                                        fileEnd - fileStart, "UTF-8"));
0811:
0812:                        entry.setNativeTime(get4ByteLittleEndian(zipDir,
0813:                                pos + 12));
0814:                        entry.compressedSize = get4ByteLittleEndian(zipDir,
0815:                                pos + 20);
0816:                        entry.size = get4ByteLittleEndian(zipDir, pos + 24);
0817:                        entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
0818:                        entryList.add(entry);
0819:                    }
0820:
0821:                    return pos + 46 + get2ByteLittleEndian(zipDir, pos + 28)
0822:                            + get2ByteLittleEndian(zipDir, pos + 30)
0823:                            + get2ByteLittleEndian(zipDir, pos + 32);
0824:                }
0825:            }
0826:
0827:            /**
0828:             * Returns the last modified timestamp of a zip file.
0829:             * @return long
0830:             */
0831:            public long getZipFileLastModified() {
0832:                lock.lock();
0833:                try {
0834:                    checkIndex();
0835:                    return zipFileLastModified;
0836:                } finally {
0837:                    lock.unlock();
0838:                }
0839:            }
0840:
0841:            /** ------------------------------------------------------------------------
0842:             *  DirectoryEntry class
0843:             * -------------------------------------------------------------------------*/
0844:            static class DirectoryEntry {
0845:                private boolean filesInited;
0846:                private boolean directoriesInited;
0847:                private boolean zipFileEntriesInited;
0848:                private boolean entriesInited;
0849:
0850:                private long writtenOffsetOffset = 0;
0851:
0852:                private String dirName;
0853:
0854:                private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = ZipFileIndex.EMPTY_LIST;
0855:                private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = ZipFileIndex.EMPTY_LIST;
0856:                private com.sun.tools.javac.util.List<ZipFileIndexEntry> zipFileEntries = ZipFileIndex.EMPTY_LIST;
0857:
0858:                private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
0859:
0860:                private ZipFileIndex zipFileIndex;
0861:
0862:                private int numEntries;
0863:
0864:                DirectoryEntry(String dirName, ZipFileIndex index) {
0865:                    filesInited = false;
0866:                    directoriesInited = false;
0867:                    entriesInited = false;
0868:
0869:                    if (File.separatorChar == '/') {
0870:                        dirName.replace('\\', '/');
0871:                    } else {
0872:                        dirName.replace('/', '\\');
0873:                    }
0874:
0875:                    this .dirName = dirName.intern();
0876:                    this .zipFileIndex = index;
0877:                }
0878:
0879:                private com.sun.tools.javac.util.List<String> getFiles() {
0880:                    if (filesInited) {
0881:                        return zipFileEntriesFiles;
0882:                    }
0883:
0884:                    initEntries();
0885:
0886:                    for (ZipFileIndexEntry e : entries) {
0887:                        if (!e.isDir) {
0888:                            zipFileEntriesFiles = zipFileEntriesFiles
0889:                                    .append(e.name);
0890:                        }
0891:                    }
0892:                    filesInited = true;
0893:                    return zipFileEntriesFiles;
0894:                }
0895:
0896:                private com.sun.tools.javac.util.List<String> getDirectories() {
0897:                    if (directoriesInited) {
0898:                        return zipFileEntriesFiles;
0899:                    }
0900:
0901:                    initEntries();
0902:
0903:                    for (ZipFileIndexEntry e : entries) {
0904:                        if (e.isDir) {
0905:                            zipFileEntriesDirectories = zipFileEntriesDirectories
0906:                                    .append(e.name);
0907:                        }
0908:                    }
0909:
0910:                    directoriesInited = true;
0911:
0912:                    return zipFileEntriesDirectories;
0913:                }
0914:
0915:                private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
0916:                    if (zipFileEntriesInited) {
0917:                        return zipFileEntries;
0918:                    }
0919:
0920:                    initEntries();
0921:
0922:                    zipFileEntries = com.sun.tools.javac.util.List.nil();
0923:                    for (ZipFileIndexEntry zfie : entries) {
0924:                        zipFileEntries = zipFileEntries.append(zfie);
0925:                    }
0926:
0927:                    zipFileEntriesInited = true;
0928:
0929:                    return zipFileEntries;
0930:                }
0931:
0932:                private ZipFileIndexEntry getEntry(String rootName) {
0933:                    initEntries();
0934:                    int index = Collections.binarySearch(entries,
0935:                            new ZipFileIndexEntry(dirName, rootName));
0936:                    if (index < 0) {
0937:                        return null;
0938:                    }
0939:
0940:                    return entries.get(index);
0941:                }
0942:
0943:                private void initEntries() {
0944:                    if (entriesInited) {
0945:                        return;
0946:                    }
0947:
0948:                    if (!zipFileIndex.readFromIndex) {
0949:                        int from = -Arrays.binarySearch(zipFileIndex.entries,
0950:                                new ZipFileIndexEntry(dirName,
0951:                                        ZipFileIndex.MIN_CHAR)) - 1;
0952:                        int to = -Arrays.binarySearch(zipFileIndex.entries,
0953:                                new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
0954:
0955:                        boolean emptyList = false;
0956:
0957:                        for (int i = from; i < to; i++) {
0958:                            entries.add(zipFileIndex.entries[i]);
0959:                        }
0960:                    } else {
0961:                        File indexFile = zipFileIndex.getIndexFile();
0962:                        if (indexFile != null) {
0963:                            RandomAccessFile raf = null;
0964:                            try {
0965:                                raf = new RandomAccessFile(indexFile, "r");
0966:                                raf.seek(writtenOffsetOffset);
0967:
0968:                                for (int nFiles = 0; nFiles < numEntries; nFiles++) {
0969:                                    // Read the name bytes
0970:                                    int zfieNameBytesLen = raf.readInt();
0971:                                    byte[] zfieNameBytes = new byte[zfieNameBytesLen];
0972:                                    raf.read(zfieNameBytes);
0973:                                    String eName = new String(zfieNameBytes,
0974:                                            "UTF-8");
0975:
0976:                                    // Read isDir
0977:                                    boolean eIsDir = raf.readByte() == (byte) 0 ? false
0978:                                            : true;
0979:
0980:                                    // Read offset of bytes in the real Jar/Zip file
0981:                                    int eOffset = raf.readInt();
0982:
0983:                                    // Read size of the file in the real Jar/Zip file
0984:                                    int eSize = raf.readInt();
0985:
0986:                                    // Read compressed size of the file in the real Jar/Zip file
0987:                                    int eCsize = raf.readInt();
0988:
0989:                                    // Read java time stamp of the file in the real Jar/Zip file
0990:                                    long eJavaTimestamp = raf.readLong();
0991:
0992:                                    ZipFileIndexEntry rfie = new ZipFileIndexEntry(
0993:                                            dirName, eName);
0994:                                    rfie.isDir = eIsDir;
0995:                                    rfie.offset = eOffset;
0996:                                    rfie.size = eSize;
0997:                                    rfie.compressedSize = eCsize;
0998:                                    rfie.javatime = eJavaTimestamp;
0999:                                    entries.add(rfie);
1000:                                }
1001:                            } catch (Throwable t) {
1002:                                // Do nothing
1003:                            } finally {
1004:                                try {
1005:                                    if (raf == null) {
1006:                                        raf.close();
1007:                                    }
1008:                                } catch (Throwable t) {
1009:                                    // Do nothing
1010:                                }
1011:                            }
1012:                        }
1013:                    }
1014:
1015:                    entriesInited = true;
1016:                }
1017:
1018:                List<ZipFileIndexEntry> getEntriesAsCollection() {
1019:                    initEntries();
1020:
1021:                    return entries;
1022:                }
1023:            }
1024:
1025:            private boolean readIndex() {
1026:                if (triedToReadIndex || !usePreindexedCache) {
1027:                    return false;
1028:                }
1029:
1030:                boolean ret = false;
1031:                lock.lock();
1032:                try {
1033:                    triedToReadIndex = true;
1034:                    RandomAccessFile raf = null;
1035:                    try {
1036:                        File indexFileName = getIndexFile();
1037:                        raf = new RandomAccessFile(indexFileName, "r");
1038:
1039:                        long fileStamp = raf.readLong();
1040:                        if (zipFile.lastModified() != fileStamp) {
1041:                            ret = false;
1042:                        } else {
1043:                            directories = new HashMap<String, DirectoryEntry>();
1044:                            int numDirs = raf.readInt();
1045:                            for (int nDirs = 0; nDirs < numDirs; nDirs++) {
1046:                                int dirNameBytesLen = raf.readInt();
1047:                                byte[] dirNameBytes = new byte[dirNameBytesLen];
1048:                                raf.read(dirNameBytes);
1049:
1050:                                String dirNameStr = new String(dirNameBytes,
1051:                                        "UTF-8");
1052:                                DirectoryEntry de = new DirectoryEntry(
1053:                                        dirNameStr, this );
1054:                                de.numEntries = raf.readInt();
1055:                                de.writtenOffsetOffset = raf.readLong();
1056:                                directories.put(dirNameStr, de);
1057:                            }
1058:                            ret = true;
1059:                            zipFileLastModified = fileStamp;
1060:                        }
1061:                    } catch (Throwable t) {
1062:                        // Do nothing
1063:                    } finally {
1064:                        if (raf != null) {
1065:                            try {
1066:                                raf.close();
1067:                            } catch (Throwable tt) {
1068:                                // Do nothing
1069:                            }
1070:                        }
1071:                    }
1072:                    if (ret == true) {
1073:                        readFromIndex = true;
1074:                    }
1075:                } finally {
1076:                    lock.unlock();
1077:                }
1078:
1079:                return ret;
1080:            }
1081:
1082:            private boolean writeIndex() {
1083:                boolean ret = false;
1084:                if (readFromIndex || !usePreindexedCache) {
1085:                    return true;
1086:                }
1087:
1088:                if (!writeIndex) {
1089:                    return true;
1090:                }
1091:
1092:                File indexFile = getIndexFile();
1093:                if (indexFile == null) {
1094:                    return false;
1095:                }
1096:
1097:                RandomAccessFile raf = null;
1098:                long writtenSoFar = 0;
1099:                try {
1100:                    raf = new RandomAccessFile(indexFile, "rw");
1101:
1102:                    raf.writeLong(zipFileLastModified);
1103:                    writtenSoFar += 8;
1104:
1105:                    Iterator<String> iterDirName = directories.keySet()
1106:                            .iterator();
1107:                    List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
1108:                    Map<String, Long> offsets = new HashMap<String, Long>();
1109:                    raf.writeInt(directories.keySet().size());
1110:                    writtenSoFar += 4;
1111:
1112:                    while (iterDirName.hasNext()) {
1113:                        String dirName = iterDirName.next();
1114:                        DirectoryEntry dirEntry = directories.get(dirName);
1115:
1116:                        directoriesToWrite.add(dirEntry);
1117:
1118:                        // Write the dir name bytes
1119:                        byte[] dirNameBytes = dirName.getBytes("UTF-8");
1120:                        int dirNameBytesLen = dirNameBytes.length;
1121:                        raf.writeInt(dirNameBytesLen);
1122:                        writtenSoFar += 4;
1123:
1124:                        raf.write(dirNameBytes);
1125:                        writtenSoFar += dirNameBytesLen;
1126:
1127:                        // Write the number of files in the dir
1128:                        List dirEntries = dirEntry.getEntriesAsCollection();
1129:                        raf.writeInt(dirEntries.size());
1130:                        writtenSoFar += 4;
1131:
1132:                        offsets.put(dirName, new Long(writtenSoFar));
1133:
1134:                        // Write the offset of the file's data in the dir
1135:                        dirEntry.writtenOffsetOffset = 0L;
1136:                        raf.writeLong(0L);
1137:                        writtenSoFar += 8;
1138:                    }
1139:
1140:                    for (DirectoryEntry de : directoriesToWrite) {
1141:                        // Fix up the offset in the directory table
1142:                        long currFP = raf.getFilePointer();
1143:
1144:                        long offsetOffset = offsets.get(de.dirName).longValue();
1145:                        raf.seek(offsetOffset);
1146:                        raf.writeLong(writtenSoFar);
1147:
1148:                        raf.seek(currFP);
1149:
1150:                        // Now write each of the files in the DirectoryEntry
1151:                        List<ZipFileIndexEntry> entries = de
1152:                                .getEntriesAsCollection();
1153:                        for (ZipFileIndexEntry zfie : entries) {
1154:                            // Write the name bytes
1155:                            byte[] zfieNameBytes = zfie.name.getBytes("UTF-8");
1156:                            int zfieNameBytesLen = zfieNameBytes.length;
1157:                            raf.writeInt(zfieNameBytesLen);
1158:                            writtenSoFar += 4;
1159:                            raf.write(zfieNameBytes);
1160:                            writtenSoFar += zfieNameBytesLen;
1161:
1162:                            // Write isDir
1163:                            raf.writeByte(zfie.isDir ? (byte) 1 : (byte) 0);
1164:                            writtenSoFar += 1;
1165:
1166:                            // Write offset of bytes in the real Jar/Zip file
1167:                            raf.writeInt(zfie.offset);
1168:                            writtenSoFar += 4;
1169:
1170:                            // Write size of the file in the real Jar/Zip file
1171:                            raf.writeInt(zfie.size);
1172:                            writtenSoFar += 4;
1173:
1174:                            // Write compressed size of the file in the real Jar/Zip file
1175:                            raf.writeInt(zfie.compressedSize);
1176:                            writtenSoFar += 4;
1177:
1178:                            // Write java time stamp of the file in the real Jar/Zip file
1179:                            raf.writeLong(zfie.getLastModified());
1180:                            writtenSoFar += 8;
1181:                        }
1182:                    }
1183:                } catch (Throwable t) {
1184:                    // Do nothing
1185:                } finally {
1186:                    try {
1187:                        if (raf != null) {
1188:                            raf.close();
1189:                        }
1190:                    } catch (IOException ioe) {
1191:                        // Do nothing
1192:                    }
1193:                }
1194:
1195:                return ret;
1196:            }
1197:
1198:            public boolean writeZipIndex() {
1199:                lock.lock();
1200:                try {
1201:                    return writeIndex();
1202:                } finally {
1203:                    lock.unlock();
1204:                }
1205:            }
1206:
1207:            private File getIndexFile() {
1208:                if (zipIndexFile == null) {
1209:                    if (zipFile == null) {
1210:                        return null;
1211:                    }
1212:
1213:                    zipIndexFile = new File(
1214:                            (preindexedCacheLocation == null ? ""
1215:                                    : preindexedCacheLocation)
1216:                                    + zipFile.getName() + ".index");
1217:                }
1218:
1219:                return zipIndexFile;
1220:            }
1221:
1222:            public File getZipFile() {
1223:                return zipFile;
1224:            }
1225:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.