1 | /*
|
---|
2 | * Copyright 2000-2004 The Apache Software Foundation
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | *
|
---|
8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
9 | *
|
---|
10 | * Unless required by applicable law or agreed to in writing, software
|
---|
11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
13 | * See the License for the specific language governing permissions and
|
---|
14 | * limitations under the License.
|
---|
15 | *
|
---|
16 | */
|
---|
17 | package org.apache.tools.ant.taskdefs.optional.depend;
|
---|
18 |
|
---|
19 | import java.io.File;
|
---|
20 | import java.io.FileInputStream;
|
---|
21 | import java.io.IOException;
|
---|
22 | import java.util.Enumeration;
|
---|
23 | import java.util.Stack;
|
---|
24 | import java.util.Vector;
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * An iterator which iterates through the contents of a java directory. The
|
---|
28 | * iterator should be created with the directory at the root of the Java
|
---|
29 | * namespace.
|
---|
30 | *
|
---|
31 | */
|
---|
32 | public class DirectoryIterator implements ClassFileIterator {
|
---|
33 |
|
---|
34 | /**
|
---|
35 | * This is a stack of current iterators supporting the depth first
|
---|
36 | * traversal of the directory tree.
|
---|
37 | */
|
---|
38 | private Stack enumStack;
|
---|
39 |
|
---|
40 | /**
|
---|
41 | * The current directory iterator. As directories encounter lower level
|
---|
42 | * directories, the current iterator is pushed onto the iterator stack
|
---|
43 | * and a new iterator over the sub directory becomes the current
|
---|
44 | * directory. This implements a depth first traversal of the directory
|
---|
45 | * namespace.
|
---|
46 | */
|
---|
47 | private Enumeration currentEnum;
|
---|
48 |
|
---|
49 | /**
|
---|
50 | * The length of the root directory. This is used to remove the root
|
---|
51 | * directory from full paths.
|
---|
52 | */
|
---|
53 | private int rootLength;
|
---|
54 |
|
---|
55 | /**
|
---|
56 | * Creates a directory iterator. The directory iterator is created to
|
---|
57 | * scan the root directory. If the changeInto flag is given, then the
|
---|
58 | * entries returned will be relative to this directory and not the
|
---|
59 | * current directory.
|
---|
60 | *
|
---|
61 | * @param rootDirectory the root if the directory namespace which is to
|
---|
62 | * be iterated over
|
---|
63 | * @param changeInto if true then the returned entries will be relative
|
---|
64 | * to the rootDirectory and not the current directory.
|
---|
65 | * @exception IOException if there is a problem reading the directory
|
---|
66 | * information.
|
---|
67 | */
|
---|
68 | public DirectoryIterator(File rootDirectory, boolean changeInto)
|
---|
69 | throws IOException {
|
---|
70 | super();
|
---|
71 |
|
---|
72 | enumStack = new Stack();
|
---|
73 |
|
---|
74 | if (rootDirectory.isAbsolute() || changeInto) {
|
---|
75 | rootLength = rootDirectory.getPath().length() + 1;
|
---|
76 | } else {
|
---|
77 | rootLength = 0;
|
---|
78 | }
|
---|
79 |
|
---|
80 | Vector filesInRoot = getDirectoryEntries(rootDirectory);
|
---|
81 |
|
---|
82 | currentEnum = filesInRoot.elements();
|
---|
83 | }
|
---|
84 |
|
---|
85 | /**
|
---|
86 | * Get a vector covering all the entries (files and subdirectories in a
|
---|
87 | * directory).
|
---|
88 | *
|
---|
89 | * @param directory the directory to be scanned.
|
---|
90 | * @return a vector containing File objects for each entry in the
|
---|
91 | * directory.
|
---|
92 | */
|
---|
93 | private Vector getDirectoryEntries(File directory) {
|
---|
94 | Vector files = new Vector();
|
---|
95 |
|
---|
96 | // File[] filesInDir = directory.listFiles();
|
---|
97 | String[] filesInDir = directory.list();
|
---|
98 |
|
---|
99 | if (filesInDir != null) {
|
---|
100 | int length = filesInDir.length;
|
---|
101 |
|
---|
102 | for (int i = 0; i < length; ++i) {
|
---|
103 | files.addElement(new File(directory, filesInDir[i]));
|
---|
104 | }
|
---|
105 | }
|
---|
106 |
|
---|
107 | return files;
|
---|
108 | }
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Template method to allow subclasses to supply elements for the
|
---|
112 | * iteration. The directory iterator maintains a stack of iterators
|
---|
113 | * covering each level in the directory hierarchy. The current iterator
|
---|
114 | * covers the current directory being scanned. If the next entry in that
|
---|
115 | * directory is a subdirectory, the current iterator is pushed onto the
|
---|
116 | * stack and a new iterator is created for the subdirectory. If the
|
---|
117 | * entry is a file, it is returned as the next element and the iterator
|
---|
118 | * remains valid. If there are no more entries in the current directory,
|
---|
119 | * the topmost iterator on the stack is popped off to become the
|
---|
120 | * current iterator.
|
---|
121 | *
|
---|
122 | * @return the next ClassFile in the iteration.
|
---|
123 | */
|
---|
124 | public ClassFile getNextClassFile() {
|
---|
125 | ClassFile nextElement = null;
|
---|
126 |
|
---|
127 | try {
|
---|
128 | while (nextElement == null) {
|
---|
129 | if (currentEnum.hasMoreElements()) {
|
---|
130 | File element = (File) currentEnum.nextElement();
|
---|
131 |
|
---|
132 | if (element.isDirectory()) {
|
---|
133 |
|
---|
134 | // push the current iterator onto the stack and then
|
---|
135 | // iterate through this directory.
|
---|
136 | enumStack.push(currentEnum);
|
---|
137 |
|
---|
138 | Vector files = getDirectoryEntries(element);
|
---|
139 |
|
---|
140 | currentEnum = files.elements();
|
---|
141 | } else {
|
---|
142 |
|
---|
143 | // we have a file. create a stream for it
|
---|
144 | FileInputStream inFileStream
|
---|
145 | = new FileInputStream(element);
|
---|
146 |
|
---|
147 | if (element.getName().endsWith(".class")) {
|
---|
148 |
|
---|
149 | // create a data input stream from the jar
|
---|
150 | // input stream
|
---|
151 | ClassFile javaClass = new ClassFile();
|
---|
152 |
|
---|
153 | javaClass.read(inFileStream);
|
---|
154 |
|
---|
155 | nextElement = javaClass;
|
---|
156 | }
|
---|
157 | }
|
---|
158 | } else {
|
---|
159 | // this iterator is exhausted. Can we pop one off the stack
|
---|
160 | if (enumStack.empty()) {
|
---|
161 | break;
|
---|
162 | } else {
|
---|
163 | currentEnum = (Enumeration) enumStack.pop();
|
---|
164 | }
|
---|
165 | }
|
---|
166 | }
|
---|
167 | } catch (IOException e) {
|
---|
168 | nextElement = null;
|
---|
169 | }
|
---|
170 |
|
---|
171 | return nextElement;
|
---|
172 | }
|
---|
173 |
|
---|
174 | }
|
---|
175 |
|
---|