src/share/tools/MakeDeps/DirectoryTree.java

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 /** Encapsulates a notion of a directory tree. Designed to allow fast
    26     querying of full paths for unique filenames in the hierarchy. */
    28 import java.io.*;
    29 import java.util.*;
    31 public class DirectoryTree {
    33     /** The root of the read directoryTree */
    34     private Node rootNode;
    36     /** Subdirs to ignore; Vector of Strings */
    37     private Vector subdirsToIgnore;
    39     /** This maps file names to Lists of nodes. */
    40     private Hashtable nameToNodeListTable;
    42     /** Output "."'s as directories are read. Defaults to false. */
    43     private boolean verbose;
    45     public DirectoryTree() {
    46         subdirsToIgnore = new Vector();
    47         verbose = false;
    48     }
    50     /** Takes an absolute path to the root directory of this
    51         DirectoryTree. Throws IllegalArgumentException if the given
    52         string represents a plain file or nonexistent directory. */
    54     public DirectoryTree(String baseDirectory) {
    55         this();
    56         readDirectory(baseDirectory);
    57     }
    59     public void addSubdirToIgnore(String subdir) {
    60         subdirsToIgnore.add(subdir);
    61     }
    63     /** Output "."'s to System.out as directories are read. Defaults
    64         to false. */
    65     public void setVerbose(boolean newValue) {
    66         verbose = newValue;
    67     }
    69     public boolean getVerbose() {
    70         return verbose;
    71     }
    73     public String getRootNodeName() {
    74         return rootNode.getName();
    75     }
    77     /** Takes an absolute path to the root directory of this
    78         DirectoryTree. Throws IllegalArgumentException if the given
    79         string represents a plain file or nonexistent directory. */
    81     public void readDirectory(String baseDirectory)
    82         throws IllegalArgumentException {
    83         File root = new File(baseDirectory);
    84         if (!root.isDirectory()) {
    85             throw new IllegalArgumentException("baseDirectory \"" +
    86                                                baseDirectory +
    87                                                "\" does not exist or " +
    88                                                "is not a directory");
    89         }
    90         try {
    91             root = root.getCanonicalFile();
    92         }
    93         catch (IOException e) {
    94             throw new RuntimeException(e.toString());
    95         }
    96         rootNode = new Node(root);
    97         readDirectory(rootNode, root);
    98     }
   100     /** Queries the DirectoryTree for a file or directory name. Takes
   101         only the name of the file or directory itself (i.e., no parent
   102         directory information should be in the passed name). Returns a
   103         List of DirectoryTreeNodes specifying the full paths of all of
   104         the files or directories of this name in the DirectoryTree.
   105         Returns null if the directory tree has not been read from disk
   106         yet or if the file was not found in the tree. */
   107     public List findFile(String name) {
   108         if (rootNode == null) {
   109             return null;
   110         }
   112         if (nameToNodeListTable == null) {
   113             nameToNodeListTable = new Hashtable();
   114             try {
   115                 buildNameToNodeListTable(rootNode);
   116             } catch (IOException e) {
   117                 e.printStackTrace();
   118                 return null;
   119             }
   120         }
   122         return (List) nameToNodeListTable.get(name);
   123     }
   125     private void buildNameToNodeListTable(Node curNode)
   126       throws IOException {
   127         String fullName = curNode.getName();
   128         String parent = curNode.getParent();
   129         String separator = System.getProperty("file.separator");
   131         if (parent != null) {
   132           if (!fullName.startsWith(parent)) {
   133             throw new RuntimeException(
   134                 "Internal error: parent of file name \"" + fullName +
   135                 "\" does not match file name \"" + parent + "\""
   136             );
   137           }
   139           int len = parent.length();
   140           if (!parent.endsWith(separator)) {
   141             len += separator.length();
   142           }
   144           String fileName = fullName.substring(len);
   146           if (fileName == null) {
   147             throw new RuntimeException(
   148                 "Internal error: file name was empty"
   149             );
   150           }
   152           List nodeList = (List) nameToNodeListTable.get(fileName);
   153           if (nodeList == null) {
   154             nodeList = new Vector();
   155             nameToNodeListTable.put(fileName, nodeList);
   156           }
   158           nodeList.add(curNode);
   159         } else {
   160           if (curNode != rootNode) {
   161             throw new RuntimeException(
   162                 "Internal error: parent of file + \"" + fullName + "\"" +
   163                 " was null"
   164             );
   165           }
   166         }
   168         if (curNode.isDirectory()) {
   169           Iterator iter = curNode.getChildren();
   170           if (iter != null) {
   171             while (iter.hasNext()) {
   172               buildNameToNodeListTable((Node) iter.next());
   173             }
   174           }
   175         }
   176     }
   178     /** Reads all of the files in the given directory and adds them as
   179         children of the directory tree node. Requires that the passed
   180         node represents a directory. */
   182     private void readDirectory(Node parentNode, File parentDir) {
   183         File[] children = parentDir.listFiles();
   184         if (children == null)
   185             return;
   186         if (verbose) {
   187             System.out.print(".");
   188             System.out.flush();
   189         }
   190         for (int i = 0; i < children.length; i++) {
   191             File child = children[i];
   192             children[i] = null;
   193             boolean isDir = child.isDirectory();
   194             boolean mustSkip = false;
   195             if (isDir) {
   196                 for (Iterator iter = subdirsToIgnore.iterator();
   197                      iter.hasNext(); ) {
   198                     if (child.getName().equals((String) iter.next())) {
   199                         mustSkip = true;
   200                         break;
   201                     }
   202                 }
   203             }
   204             if (!mustSkip) {
   205                 Node childNode = new Node(child);
   206                 parentNode.addChild(childNode);
   207                 if (isDir) {
   208                     readDirectory(childNode, child);
   209                 }
   210             }
   211         }
   212     }
   214     private class Node implements DirectoryTreeNode {
   215         private File file;
   216         private Vector children;
   218         /** file must be a canonical file */
   219         Node(File file) {
   220             this.file = file;
   221             children = new Vector();
   222         }
   224         public boolean isFile() {
   225             return file.isFile();
   226         }
   228         public boolean isDirectory() {
   229             return file.isDirectory();
   230         }
   232         public String getName() {
   233             return file.getPath();
   234         }
   236         public String getParent() {
   237             return file.getParent();
   238         }
   240         public void addChild(Node n) {
   241             children.add(n);
   242         }
   244         public Iterator getChildren() throws IllegalArgumentException {
   245             return children.iterator();
   246         }
   248         public int getNumChildren() throws IllegalArgumentException {
   249             return children.size();
   250         }
   252         public DirectoryTreeNode getChild(int i)
   253             throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
   254             return (DirectoryTreeNode) children.get(i);
   255         }
   256     }
   257 }

mercurial