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 + -
显示快捷键?