1/*
2 * Copyright (c) 2014, 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 */
25package jdk.internal.jrtfs;
26
27import java.nio.file.DirectoryStream;
28import java.nio.file.ClosedDirectoryStreamException;
29import java.nio.file.DirectoryIteratorException;
30import java.nio.file.NotDirectoryException;
31import java.nio.file.Path;
32import java.util.Iterator;
33import java.util.Objects;
34import java.util.NoSuchElementException;
35import java.io.IOException;
36
37/**
38 * DirectoryStream implementation for jrt file system implementations.
39 *
40 * @implNote This class needs to maintain JDK 8 source compatibility.
41 *
42 * It is used internally in the JDK to implement jimage/jrtfs access,
43 * but also compiled and delivered as part of the jrtfs.jar to support access
44 * to the jimage file provided by the shipped JDK by tools running on JDK 8.
45 */
46final class JrtDirectoryStream implements DirectoryStream<Path> {
47
48    private final JrtPath dir;
49    private final DirectoryStream.Filter<? super Path> filter;
50    private boolean isClosed;
51    private Iterator<Path> itr;
52
53    JrtDirectoryStream(JrtPath dir,
54            DirectoryStream.Filter<? super java.nio.file.Path> filter)
55            throws IOException
56    {
57        this.dir = dir;
58        if (!dir.jrtfs.isDirectory(dir, true)) {  // sanity check
59            throw new NotDirectoryException(dir.toString());
60        }
61        this.filter = filter;
62    }
63
64    @Override
65    public synchronized Iterator<Path> iterator() {
66        if (isClosed)
67            throw new ClosedDirectoryStreamException();
68        if (itr != null)
69            throw new IllegalStateException("Iterator has already been returned");
70        try {
71            itr = dir.jrtfs.iteratorOf(dir, filter);
72        } catch (IOException e) {
73            throw new IllegalStateException(e);
74        }
75        return new Iterator<Path>() {
76            @Override
77            public boolean hasNext() {
78                synchronized (JrtDirectoryStream.this) {
79                    if (isClosed)
80                        return false;
81                    return itr.hasNext();
82                }
83            }
84
85            @Override
86            public Path next() {
87                synchronized (JrtDirectoryStream.this) {
88                    if (isClosed)
89                        throw new NoSuchElementException();
90                    return itr.next();
91                }
92            }
93        };
94    }
95
96    @Override
97    public synchronized void close() throws IOException {
98        isClosed = true;
99    }
100}
101