1 /*
2  * Copyright (c) 2013, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.nio.file;
27 
28 import java.io.Closeable;
29 import java.io.IOException;
30 import java.io.UncheckedIOException;
31 import java.util.Arrays;
32 import java.util.Iterator;
33 import java.util.NoSuchElementException;
34 import java.nio.file.FileTreeWalker.Event;
35 
36 /**
37  * An {@code Iterator} to iterate over the nodes of a file tree.
38  *
39  * <pre>{@code
40  *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
41  *         while (iterator.hasNext()) {
42  *             Event ev = iterator.next();
43  *             Path path = ev.file();
44  *             BasicFileAttributes attrs = ev.attributes();
45  *         }
46  *     }
47  * }</pre>
48  */
49 
50 class FileTreeIterator implements Iterator<Event>, Closeable {
51     private final FileTreeWalker walker;
52     private Event next;
53 
54     /**
55      * Creates a new iterator to walk the file tree starting at the given file.
56      *
57      * @throws  IllegalArgumentException
58      *          if {@code maxDepth} is negative
59      * @throws  IOException
60      *          if an I/O errors occurs opening the starting file
61      * @throws  SecurityException
62      *          if the security manager denies access to the starting file
63      * @throws  NullPointerException
64      *          if {@code start} or {@code options} is {@code null} or
65      *          the options array contains a {@code null} element
66      */
FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)67     FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
68         throws IOException
69     {
70         this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
71         this.next = walker.walk(start);
72         assert next.type() == FileTreeWalker.EventType.ENTRY ||
73                next.type() == FileTreeWalker.EventType.START_DIRECTORY;
74 
75         // IOException if there a problem accessing the starting file
76         IOException ioe = next.ioeException();
77         if (ioe != null)
78             throw ioe;
79     }
80 
fetchNextIfNeeded()81     private void fetchNextIfNeeded() {
82         if (next == null) {
83             FileTreeWalker.Event ev = walker.next();
84             while (ev != null) {
85                 IOException ioe = ev.ioeException();
86                 if (ioe != null)
87                     throw new UncheckedIOException(ioe);
88 
89                 // END_DIRECTORY events are ignored
90                 if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
91                     next = ev;
92                     return;
93                 }
94                 ev = walker.next();
95             }
96         }
97     }
98 
99     @Override
hasNext()100     public boolean hasNext() {
101         if (!walker.isOpen())
102             throw new IllegalStateException();
103         fetchNextIfNeeded();
104         return next != null;
105     }
106 
107     @Override
next()108     public Event next() {
109         if (!walker.isOpen())
110             throw new IllegalStateException();
111         fetchNextIfNeeded();
112         if (next == null)
113             throw new NoSuchElementException();
114         Event result = next;
115         next = null;
116         return result;
117     }
118 
119     @Override
close()120     public void close() {
121         walker.close();
122     }
123 }
124