📄 archiveclasspathentry.java
字号:
} catch (RepositoryException re) { log.warn("Cannot access JAR file " + getPath(), re); } catch (IOException ioe) { log.warn("Cannot access manifest of JAR file " + getPath(), ioe); } finally { if (zipIns != null) { try { zipIns.close(); } catch (IOException ignore) { } } } } return jarManifest; } /** * Returns the <code>JarEntry</code> for the path from the * <code>JarInputStream</code> or <code>null</code> if the path cannot * be found in the archive. * * @param zins The <code>JarInputStream</code> to search in. * @param path The path of the <code>JarEntry</code> to return. * * @return The <code>JarEntry</code> for the path or <code>null</code> * if no such entry can be found. * * @throws IOException if a problem occurrs reading from the stream. */ JarEntry findEntry(JarInputStream zins, String path) throws IOException { if (entryMap == null) { // make sure to not build the list twice synchronized (this) { /** * make sure, we still need to build the list. this * implementation surely does not cure all problems of the * double-checked-locking problem, but it surely remmedies * the main problem where the reference is already written * to the field before the constructor has finished. Also * this only assigns the field when the contents has been * filled. */ if (entryMap == null) { // prepare an empty entry map to be filled Map tmpEntryMap = new HashMap(); try { // build the name-to-index map log.debug("findEntry: Building map while searching"); JarEntry result = null; JarEntry entry = zins.getNextJarEntry(); for (int i=0; entry != null; i++) { // add the entry to the map String name = entry.getName(); Integer entryNumO = new Integer(i); tmpEntryMap.put(name, entryNumO); log.debug("findEntry: Entry {} ==> {}", name, entryNumO); // if we found our entry, keep it to be returned later if (result == null && path.equals(name)) { log.debug("findEntry: Found the entry, " + "continue indexing"); result = entry; } // on to the next entry entry = zins.getNextJarEntry(); } // invariant: path has the entry found or null // return what we found log.debug("findEntry: Indexing complete, returning {}", result); return result; } finally { /** * assign the finished tmp entryMap to the field now. * theoretically, this may still be null, which * is no issue because it will be tried to be * rebuilt - over and over again, though - by the * next call to findEntry. * in the case of build problems, the map be empty * in which case it will not be rebuilt, which is * ok, too, given that reading will still yield * problems. */ entryMap = tmpEntryMap; } } } } // invariant: entryMap is not null, but might be empty // ( in case of problems creating the tmpEntryMap above, e.g. // OutOfMemoryError, the entryMap might be null, but then we // are thrown out of the method any way ... this is no issue // here ) // map exists, lets try to get via number Number entryNumO = (Number) entryMap.get(path); if (entryNumO == null) { log.debug("findEntry: This archive does not contain {}", path); return null; } // find the indexed entry log.debug("findEntry: {} is entry #{}", path, entryNumO); int entryNum = entryNumO.intValue(); JarEntry entry = zins.getNextJarEntry(); while (entryNum > 0 && entry != null) { entry = zins.getNextJarEntry(); entryNum--; } return entry; } /** * The <code>ArchiveClassPathResource</code> extends the * {@link ClassLoaderResource} with support to extract resources from a * JAR or ZIP archive. * * @author Felix Meschberger */ private static class ArchiveClassPathResource extends ClassLoaderResource { /** * The JAR/ZIP file entry providing the name, size and modification * time information. */ private final JarEntry jarEntry; /** * Creates an instance of this resource for the given * {@link ArchiveClassPathEntry} and JAR/ZIP file entry. * * @param pathEntry The {@link ArchiveClassPathEntry} from which this * resource has been loaded. * @param jarEntry The JAR/ZIP file entry describing this resource. */ private ArchiveClassPathResource(ArchiveClassPathEntry pathEntry, JarEntry jarEntry) { super(pathEntry, jarEntry.getName(), pathEntry.getProperty()); this.jarEntry = jarEntry; } /** * Returns an URL to access this resource. * * @see ArchiveClassPathEntry#getURL(String) */ public URL getURL() { return getArchiveClassPathEntry().getURL(getName()); } /** * Returns an URL identifying the archive from which this resource is * loaded. * * @see ArchiveClassPathEntry#getCodeSourceURL() */ public URL getCodeSourceURL() { return getArchiveClassPathEntry().getCodeSourceURL(); } /** * Returns an <code>InputStream</code> to read the contents of the * resource. Calling this method actually accesses the JAR/ZIP file * and seeks through the file until the entry is found. * <p> * Clients of this method must make sure to close the stream returned * if not used anymore to prevent resource drain. * * @throws RepositoryException If an error occurrs accessing or reading * the archive. * * @see ArchiveClassPathEntry#findEntry(JarInputStream, String) */ public InputStream getInputStream() throws RepositoryException { /** * Cannot reuse the ClassPathEntry instances entry and * JarInputStream, because this is shared and has to be * closed to release the property resource. */ JarInputStream zipIns = null; JarEntry entry = null; try { zipIns = getJarInputStream(getProperty()); entry = getArchiveClassPathEntry().findEntry(zipIns, getName()); if (entry != null) { return zipIns; } // otherwise log.warn("Cannot find entry {} in the archive {} anymore!", getName(), getClassPathEntry().getPath()); return null; } catch (IOException ioe) { // log throw new RepositoryException(ioe); } finally { // if thrown during findEntry(), entry is null but // the stream is open. As we exit by an exception, // the InputStream is not returned and must be // closed to release it. if (entry == null && zipIns != null) { try { zipIns.close(); } catch (IOException ignored) { } } } } /** * Returns the value of the <code>size</code> field of the JAR/ZIP * file entry of this resource. If the size is not known to the entry, * <code>-1</code> may be returned. */ public int getContentLength() { return (int) jarEntry.getSize(); } /** * Returns the path to the property containing the archive or the * path with which the {@link ArchiveClassPathEntry} was created if the * former cannot be retrieved. */ public String getPath() { try { return getProperty().getPath(); } catch (RepositoryException re) { String archivePath = getClassPathEntry().getPath(); log.warn("Cannot access the path of the archive " + "property below " + archivePath, re); return archivePath; } } /** * Returns the value of the <code>time</code> field of the JAR/ZIP * file entry of this resource. If the time is not known to the entry, * <code>-1</code> may be returned. */ public long getLastModificationTime() { return jarEntry.getTime(); } /** * Returns the manifest of the archive from which this resource was * loaded or <code>null</code> if no such manifest exists or an error * occurrs reading the manifest. * * @see ArchiveClassPathEntry#getManifest() */ public Manifest getManifest() { return getArchiveClassPathEntry().getManifest(); } /** * Returns the {@link ArchiveClassPathEntry} from which this resource * was loaded. */ protected ArchiveClassPathEntry getArchiveClassPathEntry() { return (ArchiveClassPathEntry) getClassPathEntry(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -