Path: blob/master/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java
41137 views
/*1* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.fs;2627import java.nio.file.*;28import java.util.Iterator;29import java.util.NoSuchElementException;30import java.util.concurrent.locks.*;31import java.io.IOException;32import static sun.nio.fs.UnixNativeDispatcher.*;3334/**35* Unix implementation of java.nio.file.DirectoryStream36*/3738class UnixDirectoryStream39implements DirectoryStream<Path>40{41// path to directory when originally opened42private final UnixPath dir;4344// directory pointer (returned by opendir)45private final long dp;4647// filter (may be null)48private final DirectoryStream.Filter<? super Path> filter;4950// used to coordinate closing of directory stream51private final ReentrantReadWriteLock streamLock =52new ReentrantReadWriteLock(true);5354// indicates if directory stream is open (synchronize on closeLock)55private volatile boolean isClosed;5657// directory iterator58private Iterator<Path> iterator;5960/**61* Initializes a new instance62*/63UnixDirectoryStream(UnixPath dir, long dp, DirectoryStream.Filter<? super Path> filter) {64this.dir = dir;65this.dp = dp;66this.filter = filter;67}6869protected final UnixPath directory() {70return dir;71}7273protected final Lock readLock() {74return streamLock.readLock();75}7677protected final Lock writeLock() {78return streamLock.writeLock();79}8081protected final boolean isOpen() {82return !isClosed;83}8485protected final boolean closeImpl() throws IOException {86if (!isClosed) {87isClosed = true;88try {89closedir(dp);90} catch (UnixException x) {91throw new IOException(x.errorString());92}93return true;94} else {95return false;96}97}9899@Override100public void close()101throws IOException102{103writeLock().lock();104try {105closeImpl();106} finally {107writeLock().unlock();108}109}110111protected final Iterator<Path> iterator(DirectoryStream<Path> ds) {112if (isClosed) {113throw new IllegalStateException("Directory stream is closed");114}115synchronized (this) {116if (iterator != null)117throw new IllegalStateException("Iterator already obtained");118iterator = new UnixDirectoryIterator();119return iterator;120}121}122123@Override124public Iterator<Path> iterator() {125return iterator(this);126}127128/**129* Iterator implementation130*/131private class UnixDirectoryIterator implements Iterator<Path> {132// true when at EOF133private boolean atEof;134135// next entry to return136private Path nextEntry;137138UnixDirectoryIterator() {139atEof = false;140}141142// Return true if file name is "." or ".."143private boolean isSelfOrParent(byte[] nameAsBytes) {144if (nameAsBytes[0] == '.') {145if ((nameAsBytes.length == 1) ||146(nameAsBytes.length == 2 && nameAsBytes[1] == '.')) {147return true;148}149}150return false;151}152153// Returns next entry (or null)154private Path readNextEntry() {155assert Thread.holdsLock(this);156157for (;;) {158byte[] nameAsBytes = null;159160// prevent close while reading161readLock().lock();162try {163if (isOpen()) {164nameAsBytes = readdir(dp);165}166} catch (UnixException x) {167IOException ioe = x.asIOException(dir);168throw new DirectoryIteratorException(ioe);169} finally {170readLock().unlock();171}172173// EOF174if (nameAsBytes == null) {175atEof = true;176return null;177}178179// ignore "." and ".."180if (!isSelfOrParent(nameAsBytes)) {181Path entry = dir.resolve(nameAsBytes);182183// return entry if no filter or filter accepts it184try {185if (filter == null || filter.accept(entry))186return entry;187} catch (IOException ioe) {188throw new DirectoryIteratorException(ioe);189}190}191}192}193194@Override195public synchronized boolean hasNext() {196if (nextEntry == null && !atEof)197nextEntry = readNextEntry();198return nextEntry != null;199}200201@Override202public synchronized Path next() {203Path result;204if (nextEntry == null && !atEof) {205result = readNextEntry();206} else {207result = nextEntry;208nextEntry = null;209}210if (result == null)211throw new NoSuchElementException();212return result;213}214215@Override216public void remove() {217throw new UnsupportedOperationException();218}219}220}221222223