⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zipfileindex.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package com.sun.tools.javac.zip;

import java.io.*;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.*;

/** This class implements building of index of a zip archive and access to it's context.
 *  It also uses prebuild index if available. It supports invocations where it will 
 *  serialize an optimized zip index file to disk.
 * 
 *  In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
 *  when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
 * 
 *  Location where to look for/generate optimized zip index files can be provided using 
 *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is 
 *  the value of the "java.io.tmpdir" system property.
 * 
 *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
 *  created for each archive, used by the compiler for compilation, at location,
 *  specified by "cachezipindexdir" option.
 * 
 * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp 
 * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
 * and the compiler uses the cached indexes.
 */
public class ZipFileIndex {
    private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
    
    public final static long NOT_MODIFIED = Long.MIN_VALUE;
    private final static com.sun.tools.javac.util.List EMPTY_LIST = com.sun.tools.javac.util.List.nil();
    
    private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
    private static ReentrantLock lock = new ReentrantLock();
    
    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
    
    private Map<String, DirectoryEntry> directories = Collections.EMPTY_MAP;
    private Set<String> allDirs = Collections.EMPTY_SET;
    
    // ZipFileIndex data entries
    private File zipFile;
    private long zipFileLastModified = NOT_MODIFIED;
    private RandomAccessFile zipRandomFile;
    private ZipFileIndexEntry[] entries;
    
    private boolean readFromIndex = false;
    private File zipIndexFile = null;
    private boolean triedToReadIndex = false;
    private int symbolFilePrefixLength = 0;
    private boolean hasPopulatedData = false;
    private long lastReferenceTimeStamp = NOT_MODIFIED;
    
    private boolean usePreindexedCache = false;
    private String preindexedCacheLocation = null;
    
    private boolean writeIndex = false;
    
    /**
     * Returns a list of all ZipFileIndex entries
     *
     * @return A list of ZipFileIndex entries, or an empty list
     */
    public static List<ZipFileIndex> getZipFileIndexes() {
        return getZipFileIndexes(false);
    }
    
    /**
     * Returns a list of all ZipFileIndex entries
     *
     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
     *                   all ZipFileEntry(s) are included into the list.
     * @return A list of ZipFileIndex entries, or an empty list
     */
    public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
        lock.lock();
        try {
            zipFileIndexes.addAll(zipFileIndexCache.values());

            if (openedOnly) {
                for(ZipFileIndex elem : zipFileIndexes) {
                    if (!elem.isOpen()) {
                        zipFileIndexes.remove(elem);
                    }
                }
            }
        }
        finally {
            lock.unlock();
        }
        return zipFileIndexes;
    }
    
    public boolean isOpen() {
        lock.lock();
        try {
            return zipRandomFile != null;
        }
        finally {
            lock.unlock();
        }
    }
    
    public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
        ZipFileIndex zi = null;
        lock.lock();
        try {
            zi = getExistingZipIndex(zipFile);

            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
                zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
                        useCache, cacheLocation);
                zipFileIndexCache.put(zipFile, zi);
            }
        }
        finally {
            lock.unlock();
        }
        return zi;
    }
    
    public static ZipFileIndex getExistingZipIndex(File zipFile) {
        lock.lock();
        try {
            return zipFileIndexCache.get(zipFile);
        }
        finally {
            lock.unlock();
        }
    }
    
    public static void clearCache() {
        lock.lock();
        try {
            zipFileIndexCache.clear();
        }
        finally {
            lock.unlock();
        }
    }
    
    public static void clearCache(long timeNotUsed) {
        lock.lock();
        try {
            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
            while (cachedFileIterator.hasNext()) {                
                File cachedFile = cachedFileIterator.next();
                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
                if (cachedZipIndex != null) {
                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
                            System.currentTimeMillis() > timeToTest) {
                        zipFileIndexCache.remove(cachedFile);
                    }
                }
            }
        }
        finally {
            lock.unlock();
        }
    }
    
    public static void removeFromCache(File file) {
        lock.lock();
        try {
            zipFileIndexCache.remove(file);
        }
        finally {
            lock.unlock();
        }
    }
    
    /** Sets already opened list of ZipFileIndexes from an outside client
      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
      */
    public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
        lock.lock();
        try {
            if (zipFileIndexCache.isEmpty()) {
                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
            }

            for (ZipFileIndex zfi : indexes) {
                zipFileIndexCache.put(zfi.zipFile, zfi);
            }
        }
        finally {
            lock.unlock();
        }
    }
    
    private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
            boolean useCache, String cacheLocation) throws IOException {
        this.zipFile = zipFile;
        this.symbolFilePrefixLength = symbolFilePrefixLen;
        this.writeIndex = writeIndex;
        this.usePreindexedCache = useCache;
        this.preindexedCacheLocation = cacheLocation;

        if (zipFile != null) {
            this.zipFileLastModified = zipFile.lastModified();
        }
        
        // Validate integrity of the zip file
        checkIndex();
    }
    
    public String toString() {
        return "ZipFileIndex of file:(" + zipFile + ")";
    }
    
    // Just in case...
    protected void finalize() {
        closeFile();
    }
    
    private boolean isUpToDate() {
        if (zipFile != null &&
                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
                hasPopulatedData) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
     * if its the same as the one at the time the index was build we don't need to reopen anything.
     */
    private void checkIndex() throws IOException {
        boolean isUpToDate = true;
        if (!isUpToDate()) {
            closeFile();
            isUpToDate = false;
        }
        
        if (zipRandomFile != null || isUpToDate) {
            lastReferenceTimeStamp = System.currentTimeMillis();
            return;
        }
        
        hasPopulatedData = true;
        
        if (readIndex()) {
            lastReferenceTimeStamp = System.currentTimeMillis();
            return;
        }
        
        directories = Collections.EMPTY_MAP;
        allDirs = Collections.EMPTY_SET;
        
        try {
            openFile();
            long totalLength = zipRandomFile.length();
            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
            directory.buildIndex();
        } finally {
            if (zipRandomFile != null) {
                closeFile();
            }
        }
        
        lastReferenceTimeStamp = System.currentTimeMillis();
    }
    
    private void openFile() throws FileNotFoundException {
        if (zipRandomFile == null && zipFile != null) {
            zipRandomFile = new RandomAccessFile(zipFile, "r");
        }
    }
    
    private void cleanupState() {
        // Make sure there is a valid but empty index if the file doesn't exist
        entries = ZipFileIndexEntry.EMPTY_ARRAY;
        directories = Collections.EMPTY_MAP;
        zipFileLastModified = NOT_MODIFIED;
        allDirs = Collections.EMPTY_SET;
    }
    
    public void close() {
        lock.lock();
        try {
            writeIndex();
            closeFile();
        }
        finally {
            lock.unlock();
        }
    }
    
    private void closeFile() {
        if (zipRandomFile != null) {
            try {
                zipRandomFile.close();
            } catch (IOException ex) {
            }
            zipRandomFile = null;
        }
    }
    
    /**
     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
     */
    public ZipFileIndexEntry getZipIndexEntry(String path) {
        if (File.separatorChar != '/') {
            path = path.replace('/', File.separatorChar);
        }
        lock.lock();
        try {
            checkIndex();
            String lookFor = "";
            int lastSepIndex = path.lastIndexOf(File.separatorChar);
            boolean noSeparator = false;
            if (lastSepIndex == -1) {
                noSeparator = true;
            }

            DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));

            lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);

            return de == null ? null : de.getEntry(lookFor);
        }
        catch (IOException e) {
            return null;
        }
        finally {
            lock.unlock();
        }
    }
    
    /**
     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
     */
    public com.sun.tools.javac.util.List<String> getFiles(String path) {
        if (File.separatorChar != '/') {
            path = path.replace('/', File.separatorChar);
        }

        lock.lock();
        try {
            checkIndex();

            DirectoryEntry de = directories.get(path);
            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();

            if (ret == null) {
                return EMPTY_LIST;
            }
            return ret;
        }
        catch (IOException e) {
            return EMPTY_LIST;
        }
        finally {
            lock.unlock();
        }
    }
    
    public List<String> getAllDirectories(String path) {
        
        if (File.separatorChar != '/') {
            path = path.replace('/', File.separatorChar);
        }
                
        lock.lock();
        try {
            checkIndex();
            path = path.intern();

            DirectoryEntry de = directories.get(path);
            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();

            if (ret == null) {
                return EMPTY_LIST;
            }

            return ret;
        }
        catch (IOException e) {
            return EMPTY_LIST;
        }
        finally {
            lock.unlock();
        }
    }
    
    public Set<String> getAllDirectories() {     
        lock.lock();
        try {
            checkIndex();
            if (allDirs == Collections.EMPTY_SET) {
                Set<String> alldirs = new HashSet<String>();
                Iterator<String> dirsIter = directories.keySet().iterator();
                while (dirsIter.hasNext()) {
                    alldirs.add(new String(dirsIter.next()));
                }

                allDirs = alldirs;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -