memorypath.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 648 行

JAVA
648
字号
/* * 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.Alarm;import com.caucho.util.ByteBuffer;import com.caucho.util.L10N;import java.io.FileNotFoundException;import java.io.IOException;import java.util.ArrayList;import java.util.Map;public class MemoryPath extends FilesystemPath {  private static L10N L = new L10N(MemoryPath.class);  private Node _rootNode;  protected MemoryPath(FilesystemPath root,                       String userPath, Map<String,Object> attributes,                       String path)  {    super(root, userPath, path);    if (root instanceof MemoryPath)      _rootNode = ((MemoryPath) root)._rootNode;    else      _root = this;  }  public MemoryPath()  {    this(null, "/", null, "/");    _root = this;    _rootNode = new Node("", null, Node.DIR);  }  public Path fsWalk(String userPath,                     Map<String,Object> attributes,                     String path)  {    return new MemoryPath(_root, userPath, attributes, path);  }  public String getScheme()  {    return "memory";  }  public String getURL()  {    return getScheme() + ":" + getFullPath();  }  @Override  public boolean isPathCacheable()  {    return false;  }  public boolean exists()  {    synchronized (_rootNode) {      return lookupAll() != null;    }  }  private Node lookupAll()  {    String fullPath = getFullPath();    int head = 0;    Node node = _rootNode;    while (node != null && head < fullPath.length()) {      int tail = fullPath.indexOf('/', head);      if (tail == -1) {	if (head < fullPath.length())	  return node.lookup(fullPath.substring(head));	else	  return node;      }      if (head != tail)        node = node.lookup(fullPath.substring(head, tail));      head = tail + 1;    }    return node;  }  private Node lookupAllButTail()  {    String fullPath = getFullPath();    int head = 0;    Node node = this._rootNode;    while (node != null && head < fullPath.length()) {      int tail = fullPath.indexOf('/', head);      if (tail == -1 || tail == fullPath.length() - 1)        return node;      if (head != tail)        node = node.lookup(fullPath.substring(head, tail));      head = tail + 1;    }    return node;  }  public boolean isDirectory()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node != null && node.type == node.DIR;    }  }  public boolean isFile()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node != null && node.type == node.FILE;    }  }  public boolean isObject()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node != null && node.type == node.OBJECT;    }  }  public boolean setExecutable(boolean isExecutable)  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node != null && (node.type == node.FILE || node.type == node.DIR)) {        node.isExecutable = isExecutable;        return true;      }      else        return false;    }  }  public boolean isExecutable()  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node != null && (node.type == node.FILE || node.type == node.DIR))        return node.isExecutable;      else        return false;    }  }  public long getLength()  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node != null && node.type == node.FILE)        return ((ByteBuffer) node.data).length();      else        return 0;    }  }  public long getLastModified()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node == null ? 0 : node.lastModified;    }  }  public boolean canRead()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node != null;    }  }  public boolean canWrite()  {    synchronized (_rootNode) {      Node node = lookupAll();      return node != null;    }  }  public String []list()  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node == null || node.data != null)        return new String[0];      ArrayList<String> a = new ArrayList<String>();      for (Node child = node.firstChild; child != null; child = child.next) {        a.add(child.name);      }      return (String []) a.toArray(new String[a.size()]);    }  }  // XXX: could have iterator  private boolean mkdir(boolean parent)  {    synchronized (_rootNode) {      String fullPath = getFullPath();      int head = 0;      Node node = this._rootNode;      while (node != null && head < fullPath.length()) {        int tail = fullPath.indexOf('/', head);        String name;        if (tail == head) {          head = tail + 1;          continue;        }        if (tail == -1) {          name = fullPath.substring(head);          if (node.lookup(name) != null)            return false;          node.createDir(name);          return true;        }        name = fullPath.substring(head, tail);        Node next = node.lookup(name);        if (next == null && parent)          next = node.createDir(name);        if (next == null || next.type != next.DIR)          return false;        node = next;        head = tail + 1;      }      return false;    }  }  public boolean mkdir()  {    return mkdir(false);  }  public boolean mkdirs()  {    return mkdir(true);  }  public boolean remove()  {    synchronized (_rootNode) {      Node node = lookupAllButTail();      String tail = getTail();      if (node == null)        return false;      Node child = node.lookup(tail);      if (child == null || child.firstChild != null)        return false;      node.remove(tail);      return true;    }  }  public boolean renameTo(Path path)  {    synchronized (_rootNode) {      if (! (path instanceof MemoryPath))        return false;      MemoryPath file = (MemoryPath) path;      if (_rootNode != file._rootNode)        return false;      Node oldParent = lookupAllButTail();      if (oldParent == null)        return false;      Node child = oldParent.lookup(getTail());      if (child == null)        return false;      Node newParent = file.lookupAllButTail();      if (newParent == null || newParent.type != Node.DIR)        return false;      if (newParent.lookup(file.getTail()) != null)        return false;      oldParent.remove(getTail());      child.name = file.getTail();      newParent.create(child);      return true;    }  }  public StreamImpl openReadImpl() throws IOException  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node == null)        throw new FileNotFoundException(getPath());      else if (node.type != node.FILE)        throw new IOException("is directory: " + getPath());      return new MemoryStream(node, (ByteBuffer) node.data, false);    }  }  public StreamImpl openWriteImpl() throws IOException  {    return openWriteImpl(false);  }  public StreamImpl openAppendImpl() throws IOException  {    return openWriteImpl(true);  }  private StreamImpl openWriteImpl(boolean append)    throws IOException  {    synchronized (_rootNode) {      Node node = lookupAllButTail();      String tail = getTail();      if (node == null || node.type != Node.DIR)        throw new IOException(L.l("can't create file {0}", getFullPath()));      Node child = node.lookup(tail);      if (child == null)        child = node.createFile(tail, new ByteBuffer(256));      else if (! append) {        node.remove(tail);        child = node.createFile(tail, new ByteBuffer(256));      }      else if (child.type != child.FILE)        throw new IOException(L.l("can't create file {0}", getFullPath()));      return new MemoryStream(child, (ByteBuffer) child.data, true);    }  }  public Object getValue() throws IOException  {    synchronized (_rootNode) {      Node node = lookupAll();      if (node == null || node.type != node.OBJECT)        throw new IOException("no such object: " + getFullPath().toString());      return node.data;    }  }  synchronized public void setValue(Object object) throws IOException  {    synchronized (_rootNode) {      Node node = lookupAllButTail();      String tail = getTail();      if (node == null || node.type != Node.DIR)        throw new IOException(L.l("can't set object {0}", getFullPath()));      Node child = node.lookup(tail);      if (child == null)        child = node.createObject(tail, object);      else if (child.type == child.OBJECT)        child.data = object;      else        throw new IOException(L.l("can't set object {0}", getFullPath()));    }  }  public Path copyCache()  {    return null;  }  public MemoryPath copyDeep()  {    MemoryPath path = new MemoryPath();    path._rootNode = _rootNode.copy();    return path;  }  public boolean equals(Object o)  {    if (o == null || ! getClass().equals(o.getClass()))      return false;    MemoryPath mp = (MemoryPath) o;    return getURL().equals(mp.getURL()) && _rootNode == mp._rootNode;  }  private static class Node {    static final int DIR = 0;    static final int FILE = DIR + 1;    static final int OBJECT = FILE + 1;    String name;    Node next;    Node firstChild;    long lastModified;    int type;    Object data;    boolean isExecutable;    Node(String name, Object data, int type)    {      if (name == null)        throw new NullPointerException();      this.name = name;      this.data = data;      this.type = type;      this.lastModified = Alarm.getCurrentTime();    }    Node lookup(String name)    {      for (Node node = firstChild; node != null; node = node.next) {        if (node.name.equals(name)) {          return node;        }      }      return null;    }    private Node create(String name, Object data, int type)    {      for (Node node = firstChild; node != null; node = node.next) {        if (node.name.equals(name))          return null;      }      Node newNode = new Node(name, data, type);      newNode.next = firstChild;      firstChild = newNode;      lastModified = Alarm.getCurrentTime();      return newNode;    }    Node createDir(String name)    {      return create(name, null, DIR);    }    Node createFile(String name, ByteBuffer data)    {      return create(name, data, FILE);    }    Node createObject(String name, Object data)    {      return create(name, data, OBJECT);    }    Node create(Node newNode)    {      newNode.next = firstChild;      firstChild = newNode;      return newNode;    }    boolean remove(String name)    {      Node last = null;      for (Node node = firstChild; node != null; node = node.next) {        if (node.name.equals(name)) {          if (node.firstChild != null)            return false;          if (last != null)            last.next = node.next;          else            firstChild = node.next;          return true;        }        last = node;      }      return false;    }    Node copy()    {      Node newNode = new Node(name, data, type);      if (type == DIR) {        for (Node child = firstChild; child != null; child = child.next) {          Node newChild = child.copy();          newChild.next = newNode.firstChild;          newNode.firstChild = newChild;        }      }      return newNode;    }  };  public class MemoryStream extends StreamImpl {    Node _node;    ByteBuffer _bb;    int _offset;    boolean _write;    MemoryStream(Node node, ByteBuffer bb, boolean write)    {      setPath(MemoryPath.this);      _node = node;      if (write)        node.lastModified = Alarm.getCurrentTime();      _write = write;      _bb = bb;    }    public int getAvailable()    {      return _bb.length() - _offset;    }    public boolean canRead() { return true; }    public int read(byte []buf, int bufOffset, int length) throws IOException    {      synchronized (_bb) {        int sublen = _bb.length() - _offset;        if (length < sublen)          sublen = length;        if (sublen <= 0)          return -1;        System.arraycopy(_bb.getBuffer(), _offset, buf, bufOffset, sublen);        _offset += sublen;        return sublen;      }    }    public int getPosition()    {      return _offset;    }    public void seekStart(long pos)    {      _offset = (int) pos;      if (_offset < 0)        _offset = 0;      if (_offset > _bb.length())        _offset = _bb.length();    }    public boolean canWrite() { return true; }    /**     * Writes a buffer to the underlying stream.     *     * @param buffer the byte array to write.     * @param offset the offset into the byte array.     * @param length the number of bytes to write.     * @param isEnd true when the write is flushing a close.     */    public void write(byte []buf, int offset, int length, boolean isEnd)      throws IOException    {      synchronized (_bb) {        _bb.add(buf, offset, length);      }      _node.lastModified = Alarm.getCurrentTime();    }  }}

⌨️ 快捷键说明

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