jdk/src/share/classes/java/nio/file/FileTreeWalker.java
author henryjen
Thu, 09 May 2013 14:44:56 -0700
changeset 17696 23a863fbb6c3
parent 17170 9f33b89c7978
child 23010 6dadb192ad81
permissions -rw-r--r--
8006884: (fs) Add Files.list, lines and find Reviewed-by: briangoetz, mduigou Contributed-by: alan.bateman@oracle.com, henry.jen@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 11506
diff changeset
     2
 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     4
 *
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3847
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3847
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    10
 *
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    15
 * accompanied this code).
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    16
 *
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3847
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3847
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3847
diff changeset
    23
 * questions.
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    24
 */
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    25
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    26
package java.nio.file;
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    27
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    28
import java.nio.file.attribute.BasicFileAttributes;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    29
import java.io.Closeable;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    30
import java.io.IOException;
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    31
import java.util.ArrayDeque;
17696
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
    32
import java.util.Collection;
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    33
import java.util.Iterator;
2071
5e6af6d106cb 6808647: (file) Paths.get("C:").newDirectoryStream() iterates over Path elements with additional slash [win]
alanb
parents: 2057
diff changeset
    34
import sun.nio.fs.BasicFileAttributesHolder;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    35
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    36
/**
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    37
 * Walks a file tree, generating a sequence of events corresponding to the files
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    38
 * in the tree.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    39
 *
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    40
 * <pre>{@code
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    41
 *     Path top = ...
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    42
 *     Set<FileVisitOption> options = ...
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    43
 *     int maxDepth = ...
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    44
 *
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    45
 *     try (FileTreeWalker walker = new FileTreeWalker(options, maxDepth)) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    46
 *         FileTreeWalker.Event ev = walker.walk(top);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    47
 *         do {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    48
 *             process(ev);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    49
 *             ev = walker.next();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    50
 *         } while (ev != null);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    51
 *     }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    52
 * }</pre>
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    53
 *
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    54
 * @see Files#walkFileTree
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    55
 */
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    56
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    57
class FileTreeWalker implements Closeable {
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    58
    private final boolean followLinks;
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
    59
    private final LinkOption[] linkOptions;
3847
821abab95d38 6876541: (file) Files.walkFileTree(...): no SecurityException if read access to the starting file is denied
alanb
parents: 3065
diff changeset
    60
    private final int maxDepth;
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    61
    private final ArrayDeque<DirectoryNode> stack = new ArrayDeque<>();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    62
    private boolean closed;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    63
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    64
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    65
     * The element on the walking stack corresponding to a directory node.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    66
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    67
    private static class DirectoryNode {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    68
        private final Path dir;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    69
        private final Object key;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    70
        private final DirectoryStream<Path> stream;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    71
        private final Iterator<Path> iterator;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    72
        private boolean skipped;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    73
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    74
        DirectoryNode(Path dir, Object key, DirectoryStream<Path> stream) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    75
            this.dir = dir;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    76
            this.key = key;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    77
            this.stream = stream;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    78
            this.iterator = stream.iterator();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    79
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    80
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    81
        Path directory() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    82
            return dir;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    83
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    84
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    85
        Object key() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    86
            return key;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    87
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    88
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    89
        DirectoryStream<Path> stream() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    90
            return stream;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    91
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    92
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    93
        Iterator<Path> iterator() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    94
            return iterator;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    95
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    96
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    97
        void skip() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    98
            skipped = true;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
    99
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   100
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   101
        boolean skipped() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   102
            return skipped;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   103
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   104
    }
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   105
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   106
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   107
     * The event types.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   108
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   109
    static enum EventType {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   110
        /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   111
         * Start of a directory
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   112
         */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   113
        START_DIRECTORY,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   114
        /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   115
         * End of a directory
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   116
         */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   117
        END_DIRECTORY,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   118
        /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   119
         * An entry in a directory
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   120
         */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   121
        ENTRY;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   122
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   123
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   124
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   125
     * Events returned by the {@link #walk} and {@link #next} methods.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   126
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   127
    static class Event {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   128
        private final EventType type;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   129
        private final Path file;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   130
        private final BasicFileAttributes attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   131
        private final IOException ioe;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   132
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   133
        private Event(EventType type, Path file, BasicFileAttributes attrs, IOException ioe) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   134
            this.type = type;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   135
            this.file = file;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   136
            this.attrs = attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   137
            this.ioe = ioe;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   138
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   139
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   140
        Event(EventType type, Path file, BasicFileAttributes attrs) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   141
            this(type, file, attrs, null);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   142
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   143
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   144
        Event(EventType type, Path file, IOException ioe) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   145
            this(type, file, null, ioe);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   146
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   147
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   148
        EventType type() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   149
            return type;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   150
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   151
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   152
        Path file() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   153
            return file;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   154
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   155
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   156
        BasicFileAttributes attributes() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   157
            return attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   158
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   159
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   160
        IOException ioeException() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   161
            return ioe;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   162
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   163
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   164
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   165
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   166
     * Creates a {@code FileTreeWalker}.
17696
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   167
     *
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   168
     * @throws  IllegalArgumentException
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   169
     *          if {@code maxDepth} is negative
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   170
     * @throws  ClassCastException
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   171
     *          if (@code options} contains an element that is not a
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   172
     *          {@code FileVisitOption}
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   173
     * @throws  NullPointerException
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   174
     *          if {@code options} is {@ocde null} or the options
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   175
     *          array contains a {@code null} element
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   176
     */
17696
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   177
    FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   178
        boolean fl = false;
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   179
        for (FileVisitOption option: options) {
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   180
            // will throw NPE if options contains null
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   181
            switch (option) {
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   182
                case FOLLOW_LINKS : fl = true; break;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   183
                default:
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   184
                    throw new AssertionError("Should not get here");
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   185
            }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   186
        }
17696
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   187
        if (maxDepth < 0)
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   188
            throw new IllegalArgumentException("'maxDepth' is negative");
23a863fbb6c3 8006884: (fs) Add Files.list, lines and find
henryjen
parents: 17170
diff changeset
   189
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   190
        this.followLinks = fl;
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   191
        this.linkOptions = (fl) ? new LinkOption[0] :
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   192
            new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
3847
821abab95d38 6876541: (file) Files.walkFileTree(...): no SecurityException if read access to the starting file is denied
alanb
parents: 3065
diff changeset
   193
        this.maxDepth = maxDepth;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   194
    }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   195
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   196
    /**
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   197
     * Returns the attributes of the given file, taking into account whether
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   198
     * the walk is following sym links is not. The {@code canUseCached}
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   199
     * argument determines whether this method can use cached attributes.
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   200
     */
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   201
    private BasicFileAttributes getAttributes(Path file, boolean canUseCached)
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   202
        throws IOException
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   203
    {
2071
5e6af6d106cb 6808647: (file) Paths.get("C:").newDirectoryStream() iterates over Path elements with additional slash [win]
alanb
parents: 2057
diff changeset
   204
        // if attributes are cached then use them if possible
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   205
        if (canUseCached &&
3847
821abab95d38 6876541: (file) Files.walkFileTree(...): no SecurityException if read access to the starting file is denied
alanb
parents: 3065
diff changeset
   206
            (file instanceof BasicFileAttributesHolder) &&
821abab95d38 6876541: (file) Files.walkFileTree(...): no SecurityException if read access to the starting file is denied
alanb
parents: 3065
diff changeset
   207
            (System.getSecurityManager() == null))
821abab95d38 6876541: (file) Files.walkFileTree(...): no SecurityException if read access to the starting file is denied
alanb
parents: 3065
diff changeset
   208
        {
2071
5e6af6d106cb 6808647: (file) Paths.get("C:").newDirectoryStream() iterates over Path elements with additional slash [win]
alanb
parents: 2057
diff changeset
   209
            BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   210
            if (cached != null && (!followLinks || !cached.isSymbolicLink())) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   211
                return cached;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   212
            }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   213
        }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   214
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   215
        // attempt to get attributes of file. If fails and we are following
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   216
        // links then a link target might not exist so get attributes of link
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   217
        BasicFileAttributes attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   218
        try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   219
            attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   220
        } catch (IOException ioe) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   221
            if (!followLinks)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   222
                throw ioe;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   223
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   224
            // attempt to get attrmptes without following links
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   225
            attrs = Files.readAttributes(file,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   226
                                         BasicFileAttributes.class,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   227
                                         LinkOption.NOFOLLOW_LINKS);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   228
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   229
        return attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   230
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   231
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   232
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   233
     * Returns true if walking into the given directory would result in a
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   234
     * file system loop/cycle.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   235
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   236
    private boolean wouldLoop(Path dir, Object key) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   237
        // if this directory and ancestor has a file key then we compare
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   238
        // them; otherwise we use less efficient isSameFile test.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   239
        for (DirectoryNode ancestor: stack) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   240
            Object ancestorKey = ancestor.key();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   241
            if (key != null && ancestorKey != null) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   242
                if (key.equals(ancestorKey)) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   243
                    // cycle detected
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   244
                    return true;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   245
                }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   246
            } else {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   247
                try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   248
                    if (Files.isSameFile(dir, ancestor.directory())) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   249
                        // cycle detected
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   250
                        return true;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   251
                    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   252
                } catch (IOException | SecurityException x) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   253
                    // ignore
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   254
                }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   255
            }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   256
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   257
        return false;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   258
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   259
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   260
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   261
     * Visits the given file, returning the {@code Event} corresponding to that
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   262
     * visit.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   263
     *
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   264
     * The {@code ignoreSecurityException} parameter determines whether
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   265
     * any SecurityException should be ignored or not. If a SecurityException
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   266
     * is thrown, and is ignored, then this method returns {@code null} to
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   267
     * mean that there is no event corresponding to a visit to the file.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   268
     *
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   269
     * The {@code canUseCached} parameter determines whether cached attributes
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   270
     * for the file can be used or not.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   271
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   272
    private Event visit(Path entry, boolean ignoreSecurityException, boolean canUseCached) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   273
        // need the file attributes
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   274
        BasicFileAttributes attrs;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   275
        try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   276
            attrs = getAttributes(entry, canUseCached);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   277
        } catch (IOException ioe) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   278
            return new Event(EventType.ENTRY, entry, ioe);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   279
        } catch (SecurityException se) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   280
            if (ignoreSecurityException)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   281
                return null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   282
            throw se;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   283
        }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   284
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   285
        // at maximum depth or file is not a directory
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   286
        int depth = stack.size();
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   287
        if (depth >= maxDepth || !attrs.isDirectory()) {
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   288
            return new Event(EventType.ENTRY, entry, attrs);
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   289
        }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   290
6695
0e91810597f9 6907737: (file) FileVisitor and Files.walkFileTree issues
alanb
parents: 5506
diff changeset
   291
        // check for cycles when following links
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   292
        if (followLinks && wouldLoop(entry, attrs.fileKey())) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   293
            return new Event(EventType.ENTRY, entry,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   294
                             new FileSystemLoopException(entry.toString()));
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   295
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   296
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   297
        // file is a directory, attempt to open it
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   298
        DirectoryStream<Path> stream = null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   299
        try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   300
            stream = Files.newDirectoryStream(entry);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   301
        } catch (IOException ioe) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   302
            return new Event(EventType.ENTRY, entry, ioe);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   303
        } catch (SecurityException se) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   304
            if (ignoreSecurityException)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   305
                return null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   306
            throw se;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   307
        }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   308
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   309
        // push a directory node to the stack and return an event
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   310
        stack.push(new DirectoryNode(entry, attrs.fileKey(), stream));
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   311
        return new Event(EventType.START_DIRECTORY, entry, attrs);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   312
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   313
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   314
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   315
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   316
     * Start walking from the given file.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   317
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   318
    Event walk(Path file) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   319
        if (closed)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   320
            throw new IllegalStateException("Closed");
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   321
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   322
        Event ev = visit(file,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   323
                         false,   // ignoreSecurityException
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   324
                         false);  // canUseCached
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   325
        assert ev != null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   326
        return ev;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   327
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   328
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   329
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   330
     * Returns the next Event or {@code null} if there are no more events or
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   331
     * the walker is closed.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   332
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   333
    Event next() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   334
        DirectoryNode top = stack.peek();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   335
        if (top == null)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   336
            return null;      // stack is empty, we are done
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   337
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   338
        // continue iteration of the directory at the top of the stack
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   339
        Event ev;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   340
        do {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   341
            Path entry = null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   342
            IOException ioe = null;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   343
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   344
            // get next entry in the directory
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   345
            if (!top.skipped()) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   346
                Iterator<Path> iterator = top.iterator();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   347
                try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   348
                    if (iterator.hasNext()) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   349
                        entry = iterator.next();
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   350
                    }
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   351
                } catch (DirectoryIteratorException x) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   352
                    ioe = x.getCause();
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   353
                }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   354
            }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   355
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   356
            // no next entry so close and pop directory, creating corresponding event
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   357
            if (entry == null) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   358
                try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   359
                    top.stream().close();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   360
                } catch (IOException e) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   361
                    if (ioe != null) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   362
                        ioe = e;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   363
                    } else {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   364
                        ioe.addSuppressed(e);
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   365
                    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   366
                }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   367
                stack.pop();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   368
                return new Event(EventType.END_DIRECTORY, top.directory(), ioe);
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   369
            }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   370
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   371
            // visit the entry
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   372
            ev = visit(entry,
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   373
                       true,   // ignoreSecurityException
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   374
                       true);  // canUseCached
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   375
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   376
        } while (ev == null);
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   377
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   378
        return ev;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   379
    }
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   380
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   381
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   382
     * Pops the directory node that is the current top of the stack so that
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   383
     * there are no more events for the directory (including no END_DIRECTORY)
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   384
     * event. This method is a no-op if the stack is empty or the walker is
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   385
     * closed.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   386
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   387
    void pop() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   388
        if (!stack.isEmpty()) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   389
            DirectoryNode node = stack.pop();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   390
            try {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   391
                node.stream().close();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   392
            } catch (IOException ignore) { }
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   393
        }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   394
    }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   395
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   396
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   397
     * Skips the remaining entries in the directory at the top of the stack.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   398
     * This method is a no-op if the stack is empty or the walker is closed.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   399
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   400
    void skipRemainingSiblings() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   401
        if (!stack.isEmpty()) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   402
            stack.peek().skip();
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   403
        }
17170
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   404
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   405
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   406
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   407
     * Returns {@code true} if the walker is open.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   408
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   409
    boolean isOpen() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   410
        return !closed;
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   411
    }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   412
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   413
    /**
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   414
     * Closes/pops all directories on the stack.
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   415
     */
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   416
    @Override
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   417
    public void close() {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   418
        if (!closed) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   419
            while (!stack.isEmpty()) {
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   420
                pop();
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   421
            }
9f33b89c7978 8012930: (fs) Eliminate recursion from FileTreeWalker
alanb
parents: 14342
diff changeset
   422
            closed = true;
2057
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   423
        }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   424
    }
3acf8e5e2ca0 6781363: New I/O: Update socket-channel API to jsr203/nio2-b99
alanb
parents:
diff changeset
   425
}