mergepath.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 730 行 · 第 1/2 页
JAVA
730 行
/* * 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.DynamicClassLoader;import com.caucho.make.DependencyList;import com.caucho.server.util.CauchoSystem;import java.io.IOException;import java.util.ArrayList;import java.util.Map;/** * A merging of several Paths used like a CLASSPATH. When the MergePath * is opened for read, the first path in the list which contains the file will * be the opened file. When the MergePath is opened for write, the first path * in the list is used for the write. * * <p>In the following example, "first" has priority over "second". * If test.xml exists in both "first" and "second", the open will * return "first/test.xml". * * <code><pre> * MergePage merge = new MergePath(); * merge.addMergePath(Vfs.lookup("first"); * merge.addMergePath(Vfs.lookup("second"); * * Path path = merge.lookup("test.xml"); * ReadStream is = path.openRead(); * </pre></code> * * <p>MergePath corresponds to the "merge:" Vfs schema * <code><pre> Path path = Vfs.lookup("merge:(../custom-foo;foo)"); * </pre></code> * * @since Resin 1.2 * @since Resin 3.0.10 merge: schema */public class MergePath extends FilesystemPath { private ArrayList<Path> _pathList; private Path _bestPath; /** * Creates a new merge path. */ public MergePath() { super(null, "/", "/"); _root = this; _pathList = new ArrayList<Path>(); } /** * @param path canonical path */ private MergePath(MergePath root, String userPath, Map<String,Object> attributes, String path) { super(root, userPath, path); } /** * schemeWalk is called by Path for a scheme lookup like file:/tmp/foo * * @param userPath the user's lookup() path * @param attributes the user's attributes * @param filePath the actual lookup() path * @param offset offset into filePath */ protected Path schemeWalk(String userPath, Map<String,Object> attributes, String filePath, int offset) { int length = filePath.length(); if (length <= offset || filePath.charAt(offset) != '(') return super.schemeWalk(userPath, attributes, filePath, offset); MergePath mergePath = new MergePath(); mergePath.setUserPath(userPath); int head = ++offset; int tail = head; while (tail < length) { int ch = filePath.charAt(tail); if (ch == ')') { if (head + 1 != tail) { String subPath = filePath.substring(head, tail); if (subPath.startsWith("(") && subPath.endsWith(")")) subPath = subPath.substring(1, subPath.length() - 1); mergePath.addMergePath(Vfs.lookup(subPath)); } if (tail + 1 == length) return mergePath; else return mergePath.fsWalk(userPath, attributes, filePath.substring(tail + 1)); } else if (ch == ';') { String subPath = filePath.substring(head, tail); if (subPath.startsWith("(") && subPath.endsWith(")")) subPath = subPath.substring(1, subPath.length() - 1); mergePath.addMergePath(Vfs.lookup(subPath)); head = ++tail; } else if (ch == '(') { int depth = 1; for (tail++; tail < length; tail++) { if (filePath.charAt(tail) == '(') depth++; else if (filePath.charAt(tail) == ')') { tail++; depth--; if (depth == 0) break; } } if (depth != 0) return new NotFoundPath(filePath); } else tail++; } return new NotFoundPath(filePath); } /** * Adds a new path to the end of the merge path. * * @param path the new path to search */ public void addMergePath(Path path) { if (! (path instanceof MergePath)) { // Need to normalize so directory paths ends with a "./" // XXX: //if (path.isDirectory()) // path = path.lookup("./"); ArrayList<Path> pathList = ((MergePath) _root)._pathList; if (! pathList.contains(path)) pathList.add(path); } else if (((MergePath) path)._root == _root) return; else { MergePath mergePath = (MergePath) path; ArrayList<Path> subPaths = mergePath.getMergePaths(); String pathName = "./" + mergePath._pathname + "/"; for (int i = 0; i < subPaths.size(); i++) { Path subPath = subPaths.get(i); addMergePath(subPath.lookup(pathName)); } } } /** * Adds the classpath as paths in the MergePath. */ public void addClassPath() { addClassPath(Thread.currentThread().getContextClassLoader()); } /** * Adds the classpath for the loader as paths in the MergePath. * * @param loader class loader whose classpath should be used to search. */ public void addClassPath(ClassLoader loader) { String classpath = null; if (loader instanceof DynamicClassLoader) classpath = ((DynamicClassLoader) loader).getClassPath(); else classpath = CauchoSystem.getClassPath(); addClassPath(classpath); } /** * Adds the classpath for the loader as paths in the MergePath. * * @param loader class loader whose classpath should be used to search. */ public void addResourceClassPath(ClassLoader loader) { String classpath = null; if (loader instanceof DynamicClassLoader) classpath = ((DynamicClassLoader) loader).getResourcePathSpecificFirst(); else classpath = CauchoSystem.getClassPath(); addClassPath(classpath); } /** * Adds the classpath as paths in the MergePath. */ public void addLocalClassPath() { addLocalClassPath(Thread.currentThread().getContextClassLoader()); } /** * Adds the classpath for the loader as paths in the MergePath. * * @param loader class loader whose classpath should be used to search. */ public void addLocalClassPath(ClassLoader loader) { String classpath = null; if (loader instanceof DynamicClassLoader) classpath = ((DynamicClassLoader) loader).getLocalClassPath(); else classpath = System.getProperty("java.class.path"); addClassPath(classpath); } /** * Adds the classpath for the loader as paths in the MergePath. * * @param classpath class loader whose classpath should be used to search. */ public void addClassPath(String classpath) { char sep = CauchoSystem.getPathSeparatorChar(); int head = 0; int tail = 0; while (head < classpath.length()) { tail = classpath.indexOf(sep, head); String segment = null; if (tail < 0) { segment = classpath.substring(head); head = classpath.length(); } else { segment = classpath.substring(head, tail); head = tail + 1; } if (segment.equals("")) continue; else if (segment.endsWith(".jar") || segment.endsWith(".zip")) addMergePath(JarPath.create(Vfs.lookup(segment))); else addMergePath(Vfs.lookup(segment)); } } /** * Return the list of paths searched in the merge path. */ public ArrayList<Path> getMergePaths() { return ((MergePath) _root)._pathList; } /** * Walking down the path just extends the path. It won't be evaluated * until opening. */ public Path fsWalk(String userPath, Map<String,Object> attributes, String path) { ArrayList<Path> pathList = getMergePaths(); if (! userPath.startsWith("/") || pathList.size() == 0) return new MergePath((MergePath) _root, userPath, attributes, path); String bestPrefix = null; for (int i = 0; i < pathList.size(); i++) { Path subPath = pathList.get(i); String prefix = subPath.getPath(); if (path.startsWith(prefix) && (bestPrefix == null || bestPrefix.length() < prefix.length())) { bestPrefix = prefix; } } if (bestPrefix != null) { path = path.substring(bestPrefix.length()); if (! path.startsWith("/")) path = "/" + path; return new MergePath((MergePath) _root, userPath, attributes, path); } return pathList.get(0).lookup(userPath, attributes); } /** * Returns the scheme of the best path. */ public String getScheme() { return getBestPath().getScheme(); } /** * Returns the full path name of the best path. */ public String getFullPath() { Path path = getBestPath(); return path.getFullPath(); } /** * Returns the full native path name of the best path. */ public String getNativePath() {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?