📄 filesystemmodel2.java
字号:
package org.mozilla.javascript.tools.debugger.downloaded;/* * FileSystemModel2.java * * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * */import java.io.IOException;import java.io.File;import java.util.Date;import java.util.Stack;import javax.swing.SwingUtilities;import javax.swing.tree.TreePath;/** * FileSystemModel2 is a TreeTableModel representing a hierarchical file * system.<p> * This will recursively load all the children from the path it is * created with. The loading is done with the method reloadChildren, and * happens in another thread. The method isReloading can be invoked to check * if there are active threads. The total size of all the files are also * accumulated. * <p> * By default links are not descended. java.io.File does not have a way * to distinguish links, so a file is assumed to be a link if its canonical * path does not start with its parent path. This may not cover all cases, * but works for the time being. * <p>Reloading happens such that all the files of the directory are * loaded and immediately available. The background thread then recursively * loads all the files of each of those directories. When each directory has * finished loading all its sub files they are attached and an event is * generated in the event dispatching thread. A more ambitious approach * would be to attach each set of directories as they are loaded and generate * an event. Then, once all the direct descendants of the directory being * reloaded have finished loading, it is resorted based on total size. * <p> * While you can invoke reloadChildren as many times as you want, care * should be taken in doing this. You should not invoke reloadChildren * on a node that is already being reloaded, or going to be reloaded * (meaning its parent is reloading but it hasn't started reloading * that directory yet). If this is done odd results may * happen. FileSystemModel2 does not enforce any policy in this manner, * and it is up to the user of FileSystemModel2 to ensure it doesn't * happen. * * @version 1.12 05/12/98 * @author Philip Milne * @author Scott Violet */public class FileSystemModel2 extends AbstractTreeTableModel { // Names of the columns. static protected String[] cNames = {"Name", "Size", "Type", "Modified"}; // Types of the columns. static protected Class[] cTypes = { TreeTableModel.class, Integer.class, String.class, Date.class}; // The the returned file length for directories. public static final Integer ZERO = new Integer(0); /** An array of MergeSorter sorters, that will sort based on size. */ static Stack sorters = new Stack(); /** True if the receiver is valid, once set to false all Threads * loading files will stop. */ protected boolean isValid; /** Node currently being reloaded, this becomes somewhat muddy if * reloading is happening in multiple threads. */ protected FileNode reloadNode; /** > 0 indicates reloading some nodes. */ int reloadCount; /** Returns true if links are to be descended. */ protected boolean descendLinks; /** * Returns a MergeSort that can sort on the totalSize of a FileNode. */ protected static MergeSort getSizeSorter() { synchronized(sorters) { if (sorters.size() == 0) { return new SizeSorter(); } return (MergeSort)sorters.pop(); } } /** * Should be invoked when a MergeSort is no longer needed. */ protected static void recycleSorter(MergeSort sorter) { synchronized(sorters) { sorters.push(sorter); } } /** * Creates a FileSystemModel2 rooted at File.separator, which is usually * the root of the file system. This does not load it, you should invoke * <code>reloadChildren</code> with the root to start loading. */ public FileSystemModel2() { this(File.separator); } /** * Creates a FileSystemModel2 with the root being <code>rootPath</code>. * This does not load it, you should invoke * <code>reloadChildren</code> with the root to start loading. */ public FileSystemModel2(String rootPath) { super(null); isValid = true; root = new FileNode(new File(rootPath)); } // // The TreeModel interface // /** * Returns the number of children of <code>node</code>. */ public int getChildCount(Object node) { Object[] children = getChildren(node); return (children == null) ? 0 : children.length; } /** * Returns the child of <code>node</code> at index <code>i</code>. */ public Object getChild(Object node, int i) { return getChildren(node)[i]; } /** * Returns true if the passed in object represents a leaf, false * otherwise. */ public boolean isLeaf(Object node) { return ((FileNode)node).isLeaf(); } // // The TreeTableNode interface. // /** * Returns the number of columns. */ public int getColumnCount() { return cNames.length; } /** * Returns the name for a particular column. */ public String getColumnName(int column) { return cNames[column]; } /** * Returns the class for the particular column. */ public Class getColumnClass(int column) { return cTypes[column]; } /** * Returns the value of the particular column. */ public Object getValueAt(Object node, int column) { FileNode fn = (FileNode)node; try { switch(column) { case 0: return fn.getFile().getName(); case 1: if (fn.isTotalSizeValid()) { return new Integer((int)((FileNode)node).totalSize()); } return null; case 2: return fn.isLeaf() ? "File" : "Directory"; case 3: return fn.lastModified(); } } catch (SecurityException se) { } return null; } // // Some convenience methods. // /** * Reloads the children of the specified node. */ public void reloadChildren(Object node) { FileNode fn = (FileNode)node; synchronized(this) { reloadCount++; } fn.resetSize(); new Thread(new FileNodeLoader((FileNode)node)).start(); } /** * Stops and waits for all threads to finish loading. */ public void stopLoading() { isValid = false; synchronized(this) { while (reloadCount > 0) { try { wait(); } catch (InterruptedException ie) {} } } isValid = true; } /** * If <code>newValue</code> is true, links are descended. Odd results * may happen if you set this while other threads are loading. */ public void setDescendsLinks(boolean newValue) { descendLinks = newValue; } /** * Returns true if links are to be automatically descended. */ public boolean getDescendsLinks() { return descendLinks; } /** * Returns the path <code>node</code> represents. */ public String getPath(Object node) { return ((FileNode)node).getFile().getPath(); } /** * Returns the total size of the receiver. */ public long getTotalSize(Object node) { return ((FileNode)node).totalSize(); } /** * Returns true if the receiver is loading any children. */ public boolean isReloading() { return (reloadCount > 0); } /** * Returns the path to the node that is being loaded. */ public TreePath getPathLoading() { FileNode rn = reloadNode; if (rn != null) { return new TreePath(rn.getPath()); } return null; } /** * Returns the node being loaded. */ public Object getNodeLoading() { return reloadNode; } protected File getFile(Object node) { FileNode fileNode = ((FileNode)node); return fileNode.getFile(); } protected Object[] getChildren(Object node) { FileNode fileNode = ((FileNode)node); return fileNode.getChildren(); } protected static FileNode[] EMPTY_CHILDREN = new FileNode[0]; // Used to sort the file names. static private MergeSort fileMS = new MergeSort() { public int compareElementsAt(int beginLoc, int endLoc) { return ((String)toSort[beginLoc]).compareTo ((String)toSort[endLoc]); } }; /** * A FileNode is a derivative of the File class - though we delegate to * the File object rather than subclassing it. It is used to maintain a * cache of a directory's children and therefore avoid repeated access * to the underlying file system during rendering. */ class FileNode { /** java.io.File the receiver represents. */ protected File file; /** Parent FileNode of the receiver. */ private FileNode parent; /** Children of the receiver. */ protected FileNode[] children; /** Size of the receiver and all its children. */ protected long totalSize; /** Valid if the totalSize has finished being calced. */ protected boolean totalSizeValid; /** Path of the receiver. */ protected String canonicalPath; /** True if the canonicalPath of this instance does not start with * the canonical path of the parent. */ protected boolean isLink; /** Date last modified. */ protected Date lastModified; protected FileNode(File file) { this(null, file); } protected FileNode(FileNode parent, File file) { this.parent = parent; this.file = file; try { canonicalPath = file.getCanonicalPath(); } catch (IOException ioe) { canonicalPath = ""; } if (parent != null) { isLink = !canonicalPath.startsWith(parent.getCanonicalPath()); } else { isLink = false; } if (isLeaf()) { totalSize = file.length(); totalSizeValid = true; } } /** * Returns the date the receiver was last modified. */ public Date lastModified() { if (lastModified == null && file != null) { lastModified = new Date(file.lastModified()); } return lastModified; } /** * Returns the the string to be used to display this leaf in the JTree.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -