path.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,564 行 · 第 1/3 页

JAVA
1,564
字号
/* * 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.util.CharBuffer;import com.caucho.util.Crc64;import com.caucho.util.L10N;import com.caucho.util.LruCache;import com.caucho.util.RandomUtil;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.security.cert.Certificate;import java.util.ArrayList;import java.util.Iterator;import java.util.Map;/** * A virtual filesystem path, essentially represented by a URL. * Its API resembles a combination of  the JDK File object and the URL object. * * <p>Paths are, in general, given with the canonical file separator of * forward slash, '/'.  The filesystems will take care of any necessary * translation. * * <p>Currently available filesystems: * <dl> * <dt>file:/path/to/file<dd>Java file * <dt>http://host:port/path/name?query<dd>HTTP request * <dt>tcp://host:port<dd>Raw TCP connection * <dt>mailto:user@host?subject=foo&cc=user2<dd>Mail to a user. * <dt>log:/group/subgroup/item<dd>Logging based on the configuration file. * <dt>stdout:<dd>System.out * <dt>stderr:<dd>System.err * <dt>null:<dd>The equivalent of /dev/null * </dl> */public abstract class Path {  protected final static L10N L = new L10N(Path.class);  private static final Integer LOCK = new Integer(0);  private static final LruCache<PathKey,Path> _pathLookupCache    = new LruCache<PathKey,Path>(8192);  private static boolean _isTestWindows;  protected static char _separatorChar = File.separatorChar;  protected static char _pathSeparatorChar = File.pathSeparatorChar;  private static String _newline;  private static final PathKey _key = new PathKey();  private static final SchemeMap DEFAULT_SCHEME_MAP = new SchemeMap();  private static SchemeMap _defaultSchemeMap;  protected SchemeMap _schemeMap = _defaultSchemeMap;  /**   * Creates a new Path object.   *   * @param root the new Path root.   */  protected Path(Path root)  {    if (root != null)      _schemeMap = root._schemeMap;    else if (_defaultSchemeMap != null)      _schemeMap = _defaultSchemeMap;    else      _schemeMap = DEFAULT_SCHEME_MAP;  }  /**   * Looks up a new path based on the old path.   *   * @param name relative url to the new path   * @return The new path.   */  public final Path lookup(String name)  {    return lookup(name, null);  }  /**   * Returns a new path relative to the current one.   *   * <p>Path only handles scheme:xxx.  Subclasses of Path will specialize   * the xxx.   *   * @param userPath relative or absolute path, essentially any url.   * @param newAttributes attributes for the new path.   *   * @return the new path or null if the scheme doesn't exist   */  public Path lookup(String userPath, Map<String,Object> newAttributes)  {    if (newAttributes != null)      return lookupImpl(userPath, newAttributes);    else if (userPath == null)      return this;    if (isPathCacheable()) {      synchronized (_key) {	_key.init(this, userPath);	Path path = _pathLookupCache.get(_key);	if (path != null) {	  return path.cacheCopy();	}      }    }    Path path = lookupImpl(userPath, null);    if (_startTime == 0)      _startTime = System.currentTimeMillis();    /*    if (System.currentTimeMillis() > 15000) {      if (path.getPath().endsWith("UIRepeat.class")) {	Thread.dumpStack();	System.out.println("PATH: " + path);      }    }    */    if (isPathCacheable()) {      synchronized (_key) {	Path copy = path.cacheCopy();	if (copy != null) {	  _pathLookupCache.putIfNew(new PathKey(this, userPath), copy);	}      }    }    return path;  }  static long _startTime;  /**   * Returns true if the path itself is cacheable   */  protected boolean isPathCacheable()  {    return false;  }  /**   * Returns a new path relative to the current one.   *   * <p>Path only handles scheme:xxx.  Subclasses of Path will specialize   * the xxx.   *   * @param userPath relative or absolute path, essentially any url.   * @param newAttributes attributes for the new path.   *   * @return the new path or null if the scheme doesn't exist   */  public Path lookupImpl(String userPath, Map<String,Object> newAttributes)  {    if (userPath == null)      return lookupImpl(getPath(), newAttributes);    String scheme = scanScheme(userPath);    if (scheme == null)      return schemeWalk(userPath, newAttributes, userPath, 0);    Path path;    SchemeMap schemeMap = _schemeMap;    // Special case to handle the windows special schemes    // c:xxx -> file:/c:xxx    if (isWindows()) {      int length = scheme.length();      int ch;      if (length == 1          && ('a' <= (ch = scheme.charAt(0)) && ch <= 'z'              || 'A' <= ch && ch <= 'Z')) {        if (_isTestWindows)          return schemeWalk(userPath, newAttributes, "/" + userPath, 0);        path = schemeMap.get("file");        if (path != null)          return path.schemeWalk(userPath, newAttributes, "/" + userPath, 0);        else          return schemeWalk(userPath, newAttributes, "/" + userPath, 0);      }    }    path = schemeMap.get(scheme);    // assume the foo:bar is a subfile    if (path == null)      return schemeWalk(userPath, newAttributes, userPath, 0);    return path.schemeWalk(userPath, newAttributes,                           userPath, scheme.length() + 1);  }  /**   * Looks up a path using the local filesystem conventions. e.g. on   * Windows, a name of 'd:\foo\bar\baz.html' will look up the baz.html   * on drive d.   *   * @param name relative url using local filesystem separators.   */  public final Path lookupNative(String name)  {    return lookupNative(name, null);  }  /**   * Looks up a native path, adding attributes.   */  public Path lookupNative(String name, Map<String,Object> attributes)  {    return lookup(name, attributes);  }  /**   * Returns a native path relative to this native path if the passed path   * is relative to this path, or an absolute path if the passed path is not   * relative to this path.   */  public String lookupRelativeNativePath(Path path)  {    String thisNative = getNativePath();    String pathNative = path.getNativePath();    if (pathNative.startsWith(thisNative)) {      int i = thisNative.length();      while (i < pathNative.length()) {        if (pathNative.charAt(i) != getFileSeparatorChar())          break;        i++;      }      return i == pathNative.length() ? "" : pathNative.substring(i);    }    else      return pathNative;  }  /**   * Looks up all the resources matching a name.  (Generally only useful   * with MergePath.   */  public ArrayList<Path> getResources(String name)  {    ArrayList<Path> list = new ArrayList<Path>();    Path path = lookup(name);    if (path.exists())      list.add(path);    return list;  }  /**   * Looks up all the existing resources.  (Generally only useful   * with MergePath.   */  public ArrayList<Path> getResources()  {    ArrayList<Path> list = new ArrayList<Path>();    //if (exists())    list.add(this);    return list;  }  /**   * Returns the parent path.   */  public Path getParent()  {    return this;  }  /**   * Returns the scheme portion of a uri.  Since schemes are case-insensitive,   * normalize them to lower case.   */  protected String scanScheme(String uri)  {    int i = 0;    if (uri == null)      return null;    int length = uri.length();    if (length == 0)      return null;    int ch = uri.charAt(0);    if (ch >= 'a' && ch <= 'z' ||        ch >= 'A' && ch <= 'Z') {      for (i = 1; i < length; i++) {        ch = uri.charAt(i);        if (ch == ':')          return uri.substring(0, i).toLowerCase();        if (! (ch >= 'a' && ch <= 'z' ||               ch >= 'A' && ch <= 'Z' ||               ch >= '0' && ch <= '0' ||               ch == '+' || ch == '-' || ch == '.'))          break;      }    }    return null;  }  /**   * Path-specific lookup.  Path implementations will override this.   *   * @param userPath the user's lookup() path.   * @param newAttributes the attributes for the new path.   * @param newPath the lookup() path   * @param offset offset into newPath to start lookup.   *   * @return the found path   */  abstract protected Path schemeWalk(String userPath,                                     Map<String,Object> newAttributes,                                     String newPath, int offset);  /**   * Returns the full url for the given path.   */  public String getURL()  {    return escapeURL(getScheme() + ":" + getFullPath());  }  /**   * Returns the url scheme   */  public abstract String getScheme();    /**   * Returns the hostname   */  public String getHost()  {    throw new UnsupportedOperationException();  }  /**   * Returns the port.   */  public int getPort()  {    throw new UnsupportedOperationException();  }  /**   * Returns the path.  e.g. for HTTP, returns the part after the   * host and port.   */  public abstract String getPath();  /**   * Returns the last segment of the path.   *   * <p>e.g. for http://www.caucho.com/products/index.html, getTail()   * returns 'index.html'   */  public String getTail()  {    return "";  }  /**   * Returns the query string of the path.   */  public String getQuery()  {    throw new UnsupportedOperationException();  }  /**   * Returns the native representation of the path.   *   * On Windows, getNativePath() returns 'd:\\foo\bar.html',   * getPath() returns '/d:/foo/bar.html'   */  public String getNativePath()  {    return getFullPath();  }  /**   * Returns the last string used as a lookup, if available.  This allows   * parsers to give intelligent error messages, with the user's path   * instead of the whole path.   *   * The following will print '../test.html':   * <code><pre>   * Path path = Pwd.lookup("/some/dir").lookup("../test.html");   * System.out.println(path.getUserPath());   * </pre></code>   *   */  public String getUserPath()  {    return getPath();  }  /**   * Sets the user path.  Useful for temporary files caching another   * URL.   */  public void setUserPath(String userPath)  {  }  /**   * Returns the full path, including the restricted root.   *   * <p>For the following, path.getPath() returns '/file.html', while   * path.getFullPath() returns '/chroot/file.html'.   * <code><pre>   * Path chroot = Pwd.lookup("/chroot").createRoot();   * Path path = chroot.lookup("/file.html");   * </pre></code>   */  public String getFullPath()  {    return getPath();  }  /**   * For union paths like MergePath, return the relative path into   * that path.   */  public String getRelativePath()  {    return getPath();  }  /**   * Returns true for windows security issues.   */  public boolean isWindowsInsecure()  {    String lower = getPath().toLowerCase();    int lastCh;    if ((lastCh = lower.charAt(lower.length() - 1)) == '.'	|| lastCh == ' ' || lastCh == '*' || lastCh == '?'	|| ((lastCh == '/' || lastCh == '\\') && ! isDirectory())	|| lower.endsWith("::$data")	|| isWindowsSpecial(lower, "/con")	|| isWindowsSpecial(lower, "/aux")	|| isWindowsSpecial(lower, "/prn")	|| isWindowsSpecial(lower, "/nul")	|| isWindowsSpecial(lower, "/com1")	|| isWindowsSpecial(lower, "/com2")	|| isWindowsSpecial(lower, "/com3")	|| isWindowsSpecial(lower, "/com4")	|| isWindowsSpecial(lower, "/lpt1")	|| isWindowsSpecial(lower, "/lpt2")	|| isWindowsSpecial(lower, "/lpt3")) {      return true;    }    return false;  }  private boolean isWindowsSpecial(String lower, String test)  {    int p = lower.indexOf(test);    if (p < 0)      return false;    int lowerLen = lower.length();    int testLen = test.length();    char ch;    if (lowerLen == p + testLen        || (ch = lower.charAt(p + testLen)) == '/' || ch == '.')      return true;    else      return false;  }

⌨️ 快捷键说明

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