/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.javac.file; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.util.Context; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** A cache for ZipFileIndex objects. */ public class ZipFileIndexCache { private final Map<File, ZipFileIndex> map = new HashMap<File, ZipFileIndex>(); /** Get a shared instance of the cache. */ private static ZipFileIndexCache sharedInstance; public synchronized static ZipFileIndexCache getSharedInstance() { if (sharedInstance == null) sharedInstance = new ZipFileIndexCache(); return sharedInstance; } /** Get a context-specific instance of a cache. */ public static ZipFileIndexCache instance(Context context) { ZipFileIndexCache instance = context.get(ZipFileIndexCache.class); if (instance == null) context.put(ZipFileIndexCache.class, instance = new ZipFileIndexCache()); return instance; } /** * Returns a list of all ZipFileIndex entries * * @return A list of ZipFileIndex entries, or an empty list */ public 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 synchronized List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) { List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>(); zipFileIndexes.addAll(map.values()); if (openedOnly) { for(ZipFileIndex elem : zipFileIndexes) { if (!elem.isOpen()) { zipFileIndexes.remove(elem); } } } return zipFileIndexes; } public synchronized ZipFileIndex getZipFileIndex(File zipFile, RelativeDirectory symbolFilePrefix, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException { ZipFileIndex zi = getExistingZipIndex(zipFile); if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) { zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex, useCache, cacheLocation); map.put(zipFile, zi); } return zi; } public synchronized ZipFileIndex getExistingZipIndex(File zipFile) { return map.get(zipFile); } public synchronized void clearCache() { map.clear(); } public synchronized void clearCache(long timeNotUsed) { Iterator<File> cachedFileIterator = map.keySet().iterator(); while (cachedFileIterator.hasNext()) { File cachedFile = cachedFileIterator.next(); ZipFileIndex cachedZipIndex = map.get(cachedFile); if (cachedZipIndex != null) { long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed; if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow... System.currentTimeMillis() > timeToTest) { map.remove(cachedFile); } } } } public synchronized void removeFromCache(File file) { map.remove(file); } /** 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 synchronized void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException { if (map.isEmpty()) { String msg = "Setting opened indexes should be called only when the ZipFileCache is empty. " + "Call JavacFileManager.flush() before calling this method."; throw new IllegalStateException(msg); } for (ZipFileIndex zfi : indexes) { map.put(zfi.zipFile, zfi); } } }