mirror of https://github.com/apache/lucene.git
LUCENE-6424: DirectoryStream doesn't wrap with FilterPath
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1673720 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
63073a01c2
commit
d71933415d
|
@ -94,6 +94,9 @@ Bug Fixes
|
||||||
* LUCENE-6409: Fixed integer overflow in LongBitSet.ensureCapacity.
|
* LUCENE-6409: Fixed integer overflow in LongBitSet.ensureCapacity.
|
||||||
(Luc Vanlerberghe via Adrien Grand)
|
(Luc Vanlerberghe via Adrien Grand)
|
||||||
|
|
||||||
|
* LUCENE-6424: Fix many bugs with mockfs filesystems in the test-framework:
|
||||||
|
always consistently wrap Path, fix buggy behavior for globs, etc. (Ryan Ernst)
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
|
|
||||||
* LUCENE-6377: SearcherFactory#newSearcher now accepts the previous reader
|
* LUCENE-6377: SearcherFactory#newSearcher now accepts the previous reader
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.net.URI;
|
||||||
import java.nio.channels.AsynchronousFileChannel;
|
import java.nio.channels.AsynchronousFileChannel;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
|
@ -260,4 +261,84 @@ public class TestMockFilesystems extends LuceneTestCase {
|
||||||
|
|
||||||
IOUtils.close(toClose);
|
IOUtils.close(toClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDirectoryStreamFiltered() throws IOException {
|
||||||
|
Path dir = FilterPath.unwrap(createTempDir());
|
||||||
|
FileSystem fs = new FilterFileSystemProvider("test://", dir.getFileSystem()).getFileSystem(URI.create("file:///"));
|
||||||
|
Path wrapped = new FilterPath(dir, fs);
|
||||||
|
|
||||||
|
OutputStream file = Files.newOutputStream(wrapped.resolve("file1"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(wrapped)) {
|
||||||
|
int count = 0;
|
||||||
|
for (Path path : stream) {
|
||||||
|
assertTrue(path instanceof FilterPath);
|
||||||
|
if (!path.getFileName().toString().startsWith("extra")) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertEquals(1, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check with LeakFS, a subclass of HandleTrackingFS which mucks with newDirectoryStream
|
||||||
|
dir = FilterPath.unwrap(createTempDir());
|
||||||
|
fs = new LeakFS(dir.getFileSystem()).getFileSystem(URI.create("file:///"));
|
||||||
|
wrapped = new FilterPath(dir, fs);
|
||||||
|
|
||||||
|
file = Files.newOutputStream(wrapped.resolve("file1"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(wrapped)) {
|
||||||
|
int count = 0;
|
||||||
|
for (Path path : stream) {
|
||||||
|
assertTrue(path instanceof FilterPath);
|
||||||
|
if (!path.getFileName().toString().startsWith("extra")) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertEquals(1, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDirectoryStreamGlobFiltered() throws IOException {
|
||||||
|
Path dir = FilterPath.unwrap(createTempDir());
|
||||||
|
FileSystem fs = new FilterFileSystemProvider("test://", dir.getFileSystem()).getFileSystem(URI.create("file:///"));
|
||||||
|
Path wrapped = new FilterPath(dir, fs);
|
||||||
|
|
||||||
|
OutputStream file = Files.newOutputStream(wrapped.resolve("foo"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
file = Files.newOutputStream(wrapped.resolve("bar"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(wrapped, "f*")) {
|
||||||
|
int count = 0;
|
||||||
|
for (Path path : stream) {
|
||||||
|
assertTrue(path instanceof FilterPath);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
assertEquals(1, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check with LeakFS, a subclass of HandleTrackingFS which mucks with newDirectoryStream
|
||||||
|
dir = FilterPath.unwrap(createTempDir());
|
||||||
|
fs = new LeakFS(dir.getFileSystem()).getFileSystem(URI.create("file:///"));
|
||||||
|
wrapped = new FilterPath(dir, fs);
|
||||||
|
|
||||||
|
file = Files.newOutputStream(wrapped.resolve("foo"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
file = Files.newOutputStream(wrapped.resolve("bar"));
|
||||||
|
file.write(5);
|
||||||
|
file.close();
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(wrapped, "f*")) {
|
||||||
|
int count = 0;
|
||||||
|
for (Path path : stream) {
|
||||||
|
assertTrue(path instanceof FilterPath);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
assertEquals(1, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,12 @@ package org.apache.lucene.util;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.AccessMode;
|
|
||||||
import java.nio.file.FileStore;
|
import java.nio.file.FileStore;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.LinkOption;
|
import java.nio.file.LinkOption;
|
||||||
import java.nio.file.OpenOption;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -165,7 +162,6 @@ public class TestIOUtils extends LuceneTestCase {
|
||||||
* it will chroot /dev and /sys requests to root, so you can mock those too.
|
* it will chroot /dev and /sys requests to root, so you can mock those too.
|
||||||
* <p>
|
* <p>
|
||||||
* It is hacky by definition, so don't try putting it around a complex chain or anything.
|
* It is hacky by definition, so don't try putting it around a complex chain or anything.
|
||||||
* Use FilterPath.unwrap
|
|
||||||
*/
|
*/
|
||||||
static class MockLinuxFileSystemProvider extends FilterFileSystemProvider {
|
static class MockLinuxFileSystemProvider extends FilterFileSystemProvider {
|
||||||
final Map<String,FileStore> filesToStore;
|
final Map<String,FileStore> filesToStore;
|
||||||
|
@ -182,11 +178,11 @@ public class TestIOUtils extends LuceneTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path getPath(String first, String... more) {
|
public Path getPath(String first, String... more) {
|
||||||
return new MockLinuxPath(super.getPath(first, more), this);
|
return new MockLinuxPath(delegateInstance.getPath(first, more), this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.filesToStore = filesToStore;
|
this.filesToStore = filesToStore;
|
||||||
this.root = root;
|
this.root = new MockLinuxPath(root, this.fileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -213,14 +209,8 @@ public class TestIOUtils extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkAccess(Path path, AccessMode... modes) throws IOException {
|
protected Path toDelegate(Path path) {
|
||||||
// TODO: kinda screwed up how we do this, but it's easy to get lost. just unravel completely.
|
return super.toDelegate(maybeChroot(path));
|
||||||
delegate.checkAccess(maybeChroot(FilterPath.unwrap(path)), modes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream newInputStream(Path path, OpenOption... options) throws IOException {
|
|
||||||
return super.newInputStream(maybeChroot(path), options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockLinuxPath extends FilterPath {
|
class MockLinuxPath extends FilterPath {
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.lucene.mockfile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.DirectoryStream;
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -28,12 +30,17 @@ import java.util.Objects;
|
||||||
* source of data, possibly transforming the data along the
|
* source of data, possibly transforming the data along the
|
||||||
* way or providing additional functionality.
|
* way or providing additional functionality.
|
||||||
*/
|
*/
|
||||||
public class FilterDirectoryStream<T> implements DirectoryStream<T> {
|
public class FilterDirectoryStream implements DirectoryStream<Path> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The underlying {@code DirectoryStream} instance.
|
* The underlying {@code DirectoryStream} instance.
|
||||||
*/
|
*/
|
||||||
protected final DirectoryStream<T> delegate;
|
protected final DirectoryStream<Path> delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlying {@code FileSystem} instance.
|
||||||
|
*/
|
||||||
|
protected final FileSystem fileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a {@code FilterDirectoryStream} based on
|
* Construct a {@code FilterDirectoryStream} based on
|
||||||
|
@ -42,8 +49,9 @@ public class FilterDirectoryStream<T> implements DirectoryStream<T> {
|
||||||
* Note that base stream is closed if this stream is closed.
|
* Note that base stream is closed if this stream is closed.
|
||||||
* @param delegate specified base stream.
|
* @param delegate specified base stream.
|
||||||
*/
|
*/
|
||||||
public FilterDirectoryStream(DirectoryStream<T> delegate) {
|
public FilterDirectoryStream(DirectoryStream<Path> delegate, FileSystem fileSystem) {
|
||||||
this.delegate = Objects.requireNonNull(delegate);
|
this.delegate = Objects.requireNonNull(delegate);
|
||||||
|
this.fileSystem = Objects.requireNonNull(fileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,7 +60,21 @@ public class FilterDirectoryStream<T> implements DirectoryStream<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<T> iterator() {
|
public Iterator<Path> iterator() {
|
||||||
return delegate.iterator();
|
final Iterator<Path> delegateIterator = delegate.iterator();
|
||||||
|
return new Iterator<Path>() {
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return delegateIterator.hasNext();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Path next() {
|
||||||
|
return new FilterPath(delegateIterator.next(), fileSystem);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
delegateIterator.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.nio.file.FileSystem;
|
||||||
import java.nio.file.LinkOption;
|
import java.nio.file.LinkOption;
|
||||||
import java.nio.file.OpenOption;
|
import java.nio.file.OpenOption;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.ProviderMismatchException;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.nio.file.attribute.FileAttribute;
|
import java.nio.file.attribute.FileAttribute;
|
||||||
import java.nio.file.attribute.FileAttributeView;
|
import java.nio.file.attribute.FileAttributeView;
|
||||||
|
@ -215,8 +216,14 @@ public class FilterFileSystemProvider extends FileSystemProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
|
public DirectoryStream<Path> newDirectoryStream(Path dir, final Filter<? super Path> filter) throws IOException {
|
||||||
return delegate.newDirectoryStream(toDelegate(dir), filter);
|
Filter<Path> wrappedFilter = new Filter<Path>() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(Path entry) throws IOException {
|
||||||
|
return filter.accept(new FilterPath(entry, fileSystem));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new FilterDirectoryStream(delegate.newDirectoryStream(toDelegate(dir), wrappedFilter), fileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -239,11 +246,16 @@ public class FilterFileSystemProvider extends FileSystemProvider {
|
||||||
return delegate.readSymbolicLink(toDelegate(link));
|
return delegate.readSymbolicLink(toDelegate(link));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path toDelegate(Path path) {
|
protected Path toDelegate(Path path) {
|
||||||
if (path instanceof FilterPath) {
|
if (path instanceof FilterPath) {
|
||||||
return ((FilterPath) path).delegate;
|
FilterPath fp = (FilterPath) path;
|
||||||
|
if (fp.fileSystem != fileSystem) {
|
||||||
|
throw new ProviderMismatchException("mismatch, expected: " + fileSystem.provider().getClass() + ", got: " + fp.fileSystem.provider().getClass());
|
||||||
|
}
|
||||||
|
return fp.delegate;
|
||||||
|
} else {
|
||||||
|
throw new ProviderMismatchException("mismatch, expected: FilterPath, got: " + path.getClass());
|
||||||
}
|
}
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI toDelegate(URI uri) {
|
private URI toDelegate(URI uri) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.net.URI;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.LinkOption;
|
import java.nio.file.LinkOption;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.ProviderMismatchException;
|
||||||
import java.nio.file.WatchEvent.Kind;
|
import java.nio.file.WatchEvent.Kind;
|
||||||
import java.nio.file.WatchEvent.Modifier;
|
import java.nio.file.WatchEvent.Modifier;
|
||||||
import java.nio.file.WatchKey;
|
import java.nio.file.WatchKey;
|
||||||
|
@ -120,11 +121,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startsWith(Path other) {
|
public boolean startsWith(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return delegate.startsWith(toDelegate(other));
|
||||||
FilterPath f = (FilterPath) other;
|
|
||||||
return fileSystem == f.fileSystem && delegate.startsWith(f.delegate);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,11 +131,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endsWith(Path other) {
|
public boolean endsWith(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return delegate.endsWith(toDelegate(other));
|
||||||
FilterPath f = (FilterPath) other;
|
|
||||||
return fileSystem == f.fileSystem && delegate.endsWith(f.delegate);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -153,10 +146,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path resolve(Path other) {
|
public Path resolve(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return wrap(delegate.resolve(toDelegate(other)));
|
||||||
other = ((FilterPath)other).delegate;
|
|
||||||
}
|
|
||||||
return wrap(delegate.resolve(other));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -166,10 +156,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path resolveSibling(Path other) {
|
public Path resolveSibling(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return wrap(delegate.resolveSibling(toDelegate(other)));
|
||||||
other = ((FilterPath)other).delegate;
|
|
||||||
}
|
|
||||||
return wrap(delegate.resolveSibling(other));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -179,10 +166,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path relativize(Path other) {
|
public Path relativize(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return wrap(delegate.relativize(toDelegate(other)));
|
||||||
other = ((FilterPath)other).delegate;
|
|
||||||
}
|
|
||||||
return wrap(delegate.relativize(other));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should these methods not expose delegate result directly?
|
// TODO: should these methods not expose delegate result directly?
|
||||||
|
@ -247,10 +231,7 @@ public class FilterPath implements Path {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Path other) {
|
public int compareTo(Path other) {
|
||||||
if (other instanceof FilterPath) {
|
return delegate.compareTo(toDelegate(other));
|
||||||
other = ((FilterPath)other).delegate;
|
|
||||||
}
|
|
||||||
return delegate.compareTo(other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -273,4 +254,19 @@ public class FilterPath implements Path {
|
||||||
protected Path wrap(Path other) {
|
protected Path wrap(Path other) {
|
||||||
return new FilterPath(other, fileSystem);
|
return new FilterPath(other, fileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Override this to customize the unboxing of Path
|
||||||
|
* from various operations
|
||||||
|
*/
|
||||||
|
protected Path toDelegate(Path path) {
|
||||||
|
if (path instanceof FilterPath) {
|
||||||
|
FilterPath fp = (FilterPath) path;
|
||||||
|
if (fp.fileSystem != fileSystem) {
|
||||||
|
throw new ProviderMismatchException("mismatch, expected: " + fileSystem.provider().getClass() + ", got: " + fp.fileSystem.provider().getClass());
|
||||||
|
}
|
||||||
|
return fp.delegate;
|
||||||
|
} else {
|
||||||
|
throw new ProviderMismatchException("mismatch, expected: FilterPath, got: " + path.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
package org.apache.lucene.mockfile;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.channels.SeekableByteChannel;
|
|
||||||
import java.nio.file.LinkOption;
|
|
||||||
import java.nio.file.OpenOption;
|
|
||||||
import java.nio.file.SecureDirectoryStream;
|
|
||||||
import java.nio.file.attribute.FileAttribute;
|
|
||||||
import java.nio.file.attribute.FileAttributeView;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@code FilterSecureDirectoryStream} contains another
|
|
||||||
* {@code SecureDirectoryStream}, which it uses as its basic
|
|
||||||
* source of data, possibly transforming the data along the
|
|
||||||
* way or providing additional functionality.
|
|
||||||
*/
|
|
||||||
public class FilterSecureDirectoryStream<T> implements SecureDirectoryStream<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The underlying {@code SecureDirectoryStream} instance.
|
|
||||||
*/
|
|
||||||
protected final SecureDirectoryStream<T> delegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a {@code FilterSecureDirectoryStream} based on
|
|
||||||
* the specified base stream.
|
|
||||||
* <p>
|
|
||||||
* Note that base stream is closed if this stream is closed.
|
|
||||||
* @param delegate specified base stream.
|
|
||||||
*/
|
|
||||||
public FilterSecureDirectoryStream(SecureDirectoryStream<T> delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return delegate.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
delegate.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecureDirectoryStream<T> newDirectoryStream(T path, LinkOption... options) throws IOException {
|
|
||||||
return delegate.newDirectoryStream(path, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SeekableByteChannel newByteChannel(T path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
|
||||||
return delegate.newByteChannel(path, options, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteFile(T path) throws IOException {
|
|
||||||
delegate.deleteFile(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteDirectory(T path) throws IOException {
|
|
||||||
delegate.deleteDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(T srcpath, SecureDirectoryStream<T> targetdir, T targetpath) throws IOException {
|
|
||||||
delegate.move(srcpath, targetdir, targetpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <V extends FileAttributeView> V getFileAttributeView(Class<V> type) {
|
|
||||||
return delegate.getFileAttributeView(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <V extends FileAttributeView> V getFileAttributeView(T path, Class<V> type, LinkOption... options) {
|
|
||||||
return delegate.getFileAttributeView(path, type, options);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,10 +26,8 @@ import java.nio.channels.FileChannel;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.DirectoryStream;
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.LinkOption;
|
|
||||||
import java.nio.file.OpenOption;
|
import java.nio.file.OpenOption;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SecureDirectoryStream;
|
|
||||||
import java.nio.file.DirectoryStream.Filter;
|
import java.nio.file.DirectoryStream.Filter;
|
||||||
import java.nio.file.attribute.FileAttribute;
|
import java.nio.file.attribute.FileAttribute;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -126,7 +124,7 @@ public abstract class HandleTrackingFS extends FilterFileSystemProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream newOutputStream(final Path path, OpenOption... options) throws IOException {
|
public OutputStream newOutputStream(final Path path, OpenOption... options) throws IOException {
|
||||||
OutputStream stream = new FilterOutputStream2(super.newOutputStream(path, options)) {
|
OutputStream stream = new FilterOutputStream2(delegate.newOutputStream(toDelegate(path), options)) {
|
||||||
|
|
||||||
boolean closed;
|
boolean closed;
|
||||||
|
|
||||||
|
@ -160,7 +158,7 @@ public abstract class HandleTrackingFS extends FilterFileSystemProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
||||||
FileChannel channel = new FilterFileChannel(super.newFileChannel(path, options, attrs)) {
|
FileChannel channel = new FilterFileChannel(delegate.newFileChannel(toDelegate(path), options, attrs)) {
|
||||||
|
|
||||||
boolean closed;
|
boolean closed;
|
||||||
|
|
||||||
|
@ -262,117 +260,42 @@ public abstract class HandleTrackingFS extends FilterFileSystemProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
|
public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
|
||||||
DirectoryStream<Path> stream = super.newDirectoryStream(dir, filter);
|
Filter<Path> wrappedFilter = new Filter<Path>() {
|
||||||
if (stream instanceof SecureDirectoryStream) {
|
@Override
|
||||||
stream = new TrackingSecureDirectoryStream((SecureDirectoryStream<Path>)stream, dir);
|
public boolean accept(Path entry) throws IOException {
|
||||||
} else {
|
return filter.accept(new FilterPath(entry, fileSystem));
|
||||||
stream = new FilterDirectoryStream<Path>(stream) {
|
}
|
||||||
|
};
|
||||||
|
DirectoryStream<Path> stream = delegate.newDirectoryStream(toDelegate(dir), wrappedFilter);
|
||||||
|
stream = new FilterDirectoryStream(stream, fileSystem) {
|
||||||
|
|
||||||
boolean closed;
|
boolean closed;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
closed = true;
|
closed = true;
|
||||||
onClose(dir, this);
|
onClose(dir, this);
|
||||||
}
|
|
||||||
super.close();
|
|
||||||
}
|
}
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DirectoryStream(" + dir + ")";
|
return "DirectoryStream(" + dir + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return System.identityHashCode(this);
|
return System.identityHashCode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return this == obj;
|
return this == obj;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
callOpenHook(dir, stream);
|
callOpenHook(dir, stream);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** You can also open various things from SecureDirectoryStream, so we ensure we track those */
|
|
||||||
class TrackingSecureDirectoryStream extends FilterSecureDirectoryStream<Path> {
|
|
||||||
final Path dir;
|
|
||||||
|
|
||||||
TrackingSecureDirectoryStream(SecureDirectoryStream<Path> delegate, Path dir) {
|
|
||||||
super(delegate);
|
|
||||||
this.dir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean closed;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (!closed) {
|
|
||||||
closed = true;
|
|
||||||
onClose(dir, this);
|
|
||||||
}
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SecureDirectoryStream(" + dir + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return System.identityHashCode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return this == obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecureDirectoryStream<Path> newDirectoryStream(Path path, LinkOption... options) throws IOException {
|
|
||||||
SecureDirectoryStream<Path> stream = new TrackingSecureDirectoryStream(super.newDirectoryStream(path, options), path);
|
|
||||||
callOpenHook(path, stream);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
|
||||||
SeekableByteChannel channel = new FilterSeekableByteChannel(super.newByteChannel(path, options, attrs)) {
|
|
||||||
|
|
||||||
boolean closed;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (!closed) {
|
|
||||||
closed = true;
|
|
||||||
onClose(path, this);
|
|
||||||
}
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SeekableByteChannel(" + path.toString() + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return System.identityHashCode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return this == obj;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
callOpenHook(path, channel);
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,10 @@ import java.nio.channels.AsynchronousFileChannel;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.CopyOption;
|
import java.nio.file.CopyOption;
|
||||||
import java.nio.file.DirectoryStream;
|
|
||||||
import java.nio.file.DirectoryStream.Filter;
|
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.LinkOption;
|
import java.nio.file.LinkOption;
|
||||||
import java.nio.file.OpenOption;
|
import java.nio.file.OpenOption;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SecureDirectoryStream;
|
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.nio.file.attribute.FileAttribute;
|
import java.nio.file.attribute.FileAttribute;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -244,80 +241,4 @@ public class VerboseFS extends FilterFileSystemProvider {
|
||||||
}
|
}
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
|
|
||||||
DirectoryStream<Path> stream = super.newDirectoryStream(dir, filter);
|
|
||||||
if (stream instanceof SecureDirectoryStream) {
|
|
||||||
stream = new VerboseSecureDirectoryStream((SecureDirectoryStream<Path>)stream, dir);
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
class VerboseSecureDirectoryStream extends FilterSecureDirectoryStream<Path> {
|
|
||||||
final Path dir;
|
|
||||||
|
|
||||||
VerboseSecureDirectoryStream(SecureDirectoryStream<Path> delegate, Path dir) {
|
|
||||||
super(delegate);
|
|
||||||
this.dir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecureDirectoryStream<Path> newDirectoryStream(Path path, LinkOption... options) throws IOException {
|
|
||||||
return new VerboseSecureDirectoryStream(super.newDirectoryStream(path, options), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
|
||||||
Throwable exception = null;
|
|
||||||
try {
|
|
||||||
return super.newByteChannel(path, options, attrs);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
exception = t;
|
|
||||||
} finally {
|
|
||||||
if (containsDestructive(options)) {
|
|
||||||
sop("newByteChannel[SECURE]" + options + ": " + path(path), exception);
|
|
||||||
} else {
|
|
||||||
IOUtils.reThrow(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteFile(Path path) throws IOException {
|
|
||||||
Throwable exception = null;
|
|
||||||
try {
|
|
||||||
super.deleteFile(path);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
exception = t;
|
|
||||||
} finally {
|
|
||||||
sop("deleteFile[SECURE]: " + path(path), exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteDirectory(Path path) throws IOException {
|
|
||||||
Throwable exception = null;
|
|
||||||
try {
|
|
||||||
super.deleteDirectory(path);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
exception = t;
|
|
||||||
} finally {
|
|
||||||
sop("deleteDirectory[SECURE]: " + path(path), exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(Path srcpath, SecureDirectoryStream<Path> targetdir, Path targetpath) throws IOException {
|
|
||||||
Throwable exception = null;
|
|
||||||
try {
|
|
||||||
super.move(srcpath, targetdir, targetpath);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
exception = t;
|
|
||||||
} finally {
|
|
||||||
sop("move[SECURE]: " + path(srcpath) + " -> " + path(targetpath), exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue