jar.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 953 行 · 第 1/2 页

JAVA
953
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.vfs;import com.caucho.loader.EnvironmentLocal;import com.caucho.make.CachedDependency;import com.caucho.util.Alarm;import com.caucho.util.CacheListener;import com.caucho.util.Log;import com.caucho.util.LruCache;import com.caucho.util.L10N;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.lang.ref.SoftReference;import java.security.cert.Certificate;import java.util.*;import java.util.jar.*;import java.util.logging.Level;import java.util.logging.Logger;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.zip.ZipInputStream;/** * Jar is a cache around a jar file to avoid scanning through the whole * file on each request. * * <p>When the Jar is created, it scans the file and builds a directory * of the Jar entries. */public class Jar implements CacheListener {  private static final Logger log = Log.open(Jar.class);  private static final L10N L = new L10N(Jar.class);    private static LruCache<Path,Jar> _jarCache;  private static EnvironmentLocal<Integer> _jarSize    = new EnvironmentLocal<Integer>("caucho.vfs.jar-size");    private Path _backing;  private boolean _backingIsFile;  private JarDepend _depend;    // saved last modified time  private long _lastModified;  // saved length  private long _length;  // last time the file was checked  private long _lastTime;  // cached zip file to read jar entries  private SoftReference<JarFile> _jarFileRef;  // last time the zip file was modified  private long _jarLastModified;  private long _jarLength;  private Boolean _isSigned;  // file to be closed  private SoftReference<JarFile> _closeJarFileRef;  /**   * Creates a new Jar.   *   * @param path canonical path   */  private Jar(Path backing)  {    if (backing instanceof JarPath)      throw new IllegalStateException();        _backing = backing;        _backingIsFile = (_backing.getScheme().equals("file")                      && _backing.canRead());  }  /**   * Return a Jar for the path.  If the backing already exists, return   * the old jar.   */  static Jar create(Path backing)  {    if (_jarCache == null) {      int size = 256;      Integer iSize = _jarSize.get();      if (iSize != null)        size = iSize.intValue();            _jarCache = new LruCache<Path,Jar>(size);    }        Jar jar = _jarCache.get(backing);    if (jar == null) {      jar = new Jar(backing);      jar = _jarCache.putIfNew(backing, jar);    }        return jar;  }  /**   * Return a Jar for the path.  If the backing already exists, return   * the old jar.   */  static Jar getJar(Path backing)  {    if (_jarCache != null) {      Jar jar = _jarCache.get(backing);      return jar;    }    return null;  }  /**   * Return a Jar for the path.  If the backing already exists, return   * the old jar.   */  public static PersistentDependency createDepend(Path backing)  {    Jar jar = create(backing);    return jar.getDepend();  }  /**   * Return a Jar for the path.  If the backing already exists, return   * the old jar.   */  public static PersistentDependency createDepend(Path backing, long digest)  {    Jar jar = create(backing);    return new JarDigestDepend(jar.getJarDepend(), digest);  }  /**   * Returns the backing path.   */  Path getBacking()  {    return _backing;  }  /**   * Returns the dependency.   */  public PersistentDependency getDepend()  {    return getJarDepend();  }  /**   * Returns the dependency.   */  private JarDepend getJarDepend()  {    if (_depend == null || _depend.isModified())      _depend = new JarDepend(new Depend(getBacking()));    return _depend;  }  private boolean isSigned()  {    Boolean isSigned = _isSigned;    if (isSigned != null)      return isSigned;    try {      Manifest manifest = getManifest();      if (manifest == null) {        _isSigned = Boolean.FALSE;        return false;      }      Map<String,Attributes> entries = manifest.getEntries();      if (entries == null) {        _isSigned = Boolean.FALSE;        return false;      }            for (Attributes attr : entries.values()) {        for (Object key : attr.keySet()) {          String keyString = String.valueOf(key);          if (keyString.contains("Digest")) {            _isSigned = Boolean.TRUE;            return true;          }        }      }    } catch (IOException e) {      log.log(Level.FINE, e.toString(), e);    }    _isSigned = Boolean.FALSE;        return false;  }  /**   * Returns true if the entry is a file in the jar.   *   * @param path the path name inside the jar.   */  public Manifest getManifest()    throws IOException  {    Manifest manifest;    synchronized (this) {      JarFile jarFile = getJarFile();      if (jarFile == null)	manifest = null;      else	manifest = jarFile.getManifest();    }    closeJarFile();    return manifest;  }  /**   * Returns any certificates.   */  public Certificate []getCertificates(String path)  {    if (! isSigned())      return null;        if (path.length() > 0 && path.charAt(0) == '/')      path = path.substring(1);    try {      if (! _backing.canRead())	return null;            JarFile jarFile = new JarFile(_backing.getNativePath());      JarEntry entry;      InputStream is = null;      try {	entry = jarFile.getJarEntry(path);	if (entry != null) {	  is = jarFile.getInputStream(entry);	  while (is.skip(65536) > 0) {	  }	  is.close();	  return entry.getCertificates();	}      } finally {	jarFile.close();      }    } catch (IOException e) {      log.log(Level.FINE, e.toString(), e);      return null;    }    return null;  }  /**   * Returns true if the entry exists in the jar.   *   * @param path the path name inside the jar.   */  public boolean exists(String path)  {    // server/249f, server/249g    // XXX: facelets vs issue of meta-inf (i.e. lower case)    boolean result = false;        synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null;      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);      }    }    closeJarFile();    return result;  }  /**   * Returns true if the entry is a directory in the jar.   *   * @param path the path name inside the jar.   */  public boolean isDirectory(String path)  {    boolean result = false;        synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null && entry.isDirectory();      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);      }    }    closeJarFile();    return result;  }  /**   * Returns true if the entry is a file in the jar.   *   * @param path the path name inside the jar.   */  public boolean isFile(String path)  {    boolean result = false;        synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null && ! entry.isDirectory();      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);      }    }    closeJarFile();    return result;  }  /**   * Returns the length of the entry in the jar file.   *   * @param path full path to the jar entry   * @return the length of the entry   */  public long getLastModified(String path)  {    long result = -1;    synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null ? entry.getTime() : -1;      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);      }    }    closeJarFile();    return result;  }  /**   * Returns the length of the entry in the jar file.   *   * @param path full path to the jar entry   * @return the length of the entry   */  public long getLength(String path)  {    long result = -1;        synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null ? entry.getSize() : -1;      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);      }    }    closeJarFile();    return result;  }  /**   * Readable if the jar is readable and the path refers to a file.   */  public boolean canRead(String path)  {    boolean result = false;        synchronized (this) {      try {	ZipEntry entry = getJarEntry(path);	result = entry != null && ! entry.isDirectory();      } catch (IOException e) {	log.log(Level.FINE, e.toString(), e);		return false;      }    }    closeJarFile();    return result;  }  /**   * Can't write to jars.   */  public boolean canWrite(String path)  {    return false;  }  /**   * Lists all the files in this directory.   */  public String []list(String path) throws IOException  {    // XXX:        return new String[0];  }  /**   * Opens a stream to an entry in the jar.   *   * @param path relative path into the jar.   */

⌨️ 快捷键说明

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