aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/depend/DirectoryIterator.java
blob: ebf244a55197be44c6f9c1f2307453cc6adfcd1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.taskdefs.optional.depend;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;

/**
 * An iterator which iterates through the contents of a java directory. The
 * iterator should be created with the directory at the root of the Java
 * namespace.
 *
 */
public class DirectoryIterator implements ClassFileIterator {

    /**
     * This is a stack of current iterators supporting the depth first
     * traversal of the directory tree.
     */
    private Stack enumStack;

    /**
     * The current directory iterator. As directories encounter lower level
     * directories, the current iterator is pushed onto the iterator stack
     * and a new iterator over the sub directory becomes the current
     * directory. This implements a depth first traversal of the directory
     * namespace.
     */
    private Enumeration currentEnum;

    /**
     * Creates a directory iterator. The directory iterator is created to
     * scan the root directory. If the changeInto flag is given, then the
     * entries returned will be relative to this directory and not the
     * current directory.
     *
     * @param rootDirectory the root if the directory namespace which is to
     *      be iterated over
     * @param changeInto if true then the returned entries will be relative
     *      to the rootDirectory and not the current directory.
     * @exception IOException if there is a problem reading the directory
     *      information.
     */
    public DirectoryIterator(File rootDirectory, boolean changeInto)
         throws IOException {
        super();

        enumStack = new Stack();

        Vector filesInRoot = getDirectoryEntries(rootDirectory);

        currentEnum = filesInRoot.elements();
    }

    /**
     * Get a vector covering all the entries (files and subdirectories in a
     * directory).
     *
     * @param directory the directory to be scanned.
     * @return a vector containing File objects for each entry in the
     *      directory.
     */
    private Vector getDirectoryEntries(File directory) {
        Vector files = new Vector();

        // File[] filesInDir = directory.listFiles();
        String[] filesInDir = directory.list();

        if (filesInDir != null) {
            int length = filesInDir.length;

            for (int i = 0; i < length; ++i) {
                files.addElement(new File(directory, filesInDir[i]));
            }
        }

        return files;
    }

    /**
     * Template method to allow subclasses to supply elements for the
     * iteration. The directory iterator maintains a stack of iterators
     * covering each level in the directory hierarchy. The current iterator
     * covers the current directory being scanned. If the next entry in that
     * directory is a subdirectory, the current iterator is pushed onto the
     * stack and a new iterator is created for the subdirectory. If the
     * entry is a file, it is returned as the next element and the iterator
     * remains valid. If there are no more entries in the current directory,
     * the topmost iterator on the stack is popped off to become the
     * current iterator.
     *
     * @return the next ClassFile in the iteration.
     */
    public ClassFile getNextClassFile() {
        ClassFile nextElement = null;

        try {
            while (nextElement == null) {
                if (currentEnum.hasMoreElements()) {
                    File element = (File) currentEnum.nextElement();

                    if (element.isDirectory()) {

                        // push the current iterator onto the stack and then
                        // iterate through this directory.
                        enumStack.push(currentEnum);

                        Vector files = getDirectoryEntries(element);

                        currentEnum = files.elements();
                    } else {

                        // we have a file. create a stream for it
                        FileInputStream inFileStream
                            = new FileInputStream(element);

                        if (element.getName().endsWith(".class")) {

                            // create a data input stream from the jar
                            // input stream
                            ClassFile javaClass = new ClassFile();

                            javaClass.read(inFileStream);

                            nextElement = javaClass;
                        }
                    }
                } else {
                    // this iterator is exhausted. Can we pop one off the stack
                    if (enumStack.empty()) {
                        break;
                    } else {
                        currentEnum = (Enumeration) enumStack.pop();
                    }
                }
            }
        } catch (IOException e) {
            nextElement = null;
        }

        return nextElement;
    }

}