0
|
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 */
|
|
24
|
|
25 /** Encapsulates a notion of a directory tree. Designed to allow fast
|
|
26 querying of full paths for unique filenames in the hierarchy. */
|
|
27
|
|
28 import java.io.*;
|
|
29 import java.util.*;
|
|
30
|
|
31 public class DirectoryTree {
|
|
32
|
|
33 /** The root of the read directoryTree */
|
|
34 private Node rootNode;
|
|
35
|
|
36 /** Subdirs to ignore; Vector of Strings */
|
|
37 private Vector subdirsToIgnore;
|
|
38
|
|
39 /** This maps file names to Lists of nodes. */
|
|
40 private Hashtable nameToNodeListTable;
|
|
41
|
|
42 /** Output "."'s as directories are read. Defaults to false. */
|
|
43 private boolean verbose;
|
|
44
|
|
45 public DirectoryTree() {
|
|
46 subdirsToIgnore = new Vector();
|
|
47 verbose = false;
|
|
48 }
|
|
49
|
|
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. */
|
|
53
|
|
54 public DirectoryTree(String baseDirectory) {
|
|
55 this();
|
|
56 readDirectory(baseDirectory);
|
|
57 }
|
|
58
|
|
59 public void addSubdirToIgnore(String subdir) {
|
|
60 subdirsToIgnore.add(subdir);
|
|
61 }
|
|
62
|
|
63 /** Output "."'s to System.out as directories are read. Defaults
|
|
64 to false. */
|
|
65 public void setVerbose(boolean newValue) {
|
|
66 verbose = newValue;
|
|
67 }
|
|
68
|
|
69 public boolean getVerbose() {
|
|
70 return verbose;
|
|
71 }
|
|
72
|
|
73 public String getRootNodeName() {
|
|
74 return rootNode.getName();
|
|
75 }
|
|
76
|
|
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. */
|
|
80
|
|
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 }
|
|
99
|
|
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 }
|
|
111
|
|
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 }
|
|
121
|
|
122 return (List) nameToNodeListTable.get(name);
|
|
123 }
|
|
124
|
|
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");
|
|
130
|
|
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 }
|
|
138
|
|
139 int len = parent.length();
|
|
140 if (!parent.endsWith(separator)) {
|
|
141 len += separator.length();
|
|
142 }
|
|
143
|
|
144 String fileName = fullName.substring(len);
|
|
145
|
|
146 if (fileName == null) {
|
|
147 throw new RuntimeException(
|
|
148 "Internal error: file name was empty"
|
|
149 );
|
|
150 }
|
|
151
|
|
152 List nodeList = (List) nameToNodeListTable.get(fileName);
|
|
153 if (nodeList == null) {
|
|
154 nodeList = new Vector();
|
|
155 nameToNodeListTable.put(fileName, nodeList);
|
|
156 }
|
|
157
|
|
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 }
|
|
167
|
|
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 }
|
|
177
|
|
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. */
|
|
181
|
|
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 }
|
|
213
|
|
214 private class Node implements DirectoryTreeNode {
|
|
215 private File file;
|
|
216 private Vector children;
|
|
217
|
|
218 /** file must be a canonical file */
|
|
219 Node(File file) {
|
|
220 this.file = file;
|
|
221 children = new Vector();
|
|
222 }
|
|
223
|
|
224 public boolean isFile() {
|
|
225 return file.isFile();
|
|
226 }
|
|
227
|
|
228 public boolean isDirectory() {
|
|
229 return file.isDirectory();
|
|
230 }
|
|
231
|
|
232 public String getName() {
|
|
233 return file.getPath();
|
|
234 }
|
|
235
|
|
236 public String getParent() {
|
|
237 return file.getParent();
|
|
238 }
|
|
239
|
|
240 public void addChild(Node n) {
|
|
241 children.add(n);
|
|
242 }
|
|
243
|
|
244 public Iterator getChildren() throws IllegalArgumentException {
|
|
245 return children.iterator();
|
|
246 }
|
|
247
|
|
248 public int getNumChildren() throws IllegalArgumentException {
|
|
249 return children.size();
|
|
250 }
|
|
251
|
|
252 public DirectoryTreeNode getChild(int i)
|
|
253 throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
|
|
254 return (DirectoryTreeNode) children.get(i);
|
|
255 }
|
|
256 }
|
|
257 }
|