Path: blob/master/test/jdk/java/nio/file/Files/FaultyFileSystem.java
41153 views
/*1* Copyright (c) 2013, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.net.URI;25import java.nio.channels.SeekableByteChannel;26import java.nio.file.AccessMode;27import java.nio.file.CopyOption;28import java.nio.file.DirectoryIteratorException;29import java.nio.file.DirectoryStream;30import java.nio.file.FileStore;31import java.nio.file.FileSystem;32import java.nio.file.FileSystemAlreadyExistsException;33import java.nio.file.FileSystemNotFoundException;34import java.nio.file.Files;35import java.nio.file.LinkOption;36import java.nio.file.NoSuchFileException;37import java.nio.file.OpenOption;38import java.nio.file.Path;39import java.nio.file.PathMatcher;40import java.nio.file.WatchService;41import java.nio.file.attribute.BasicFileAttributes;42import java.nio.file.attribute.FileAttribute;43import java.nio.file.attribute.FileAttributeView;44import java.nio.file.attribute.UserPrincipalLookupService;45import java.nio.file.spi.FileSystemProvider;46import java.util.Iterator;47import java.util.Map;48import java.util.NoSuchElementException;49import java.util.Set;50import java.util.function.Supplier;5152/**53* A {@code FileSystem} that helps testing by trigger exception throwing based on filenames.54*/55class FaultyFileSystem extends FileSystem {56final Path root;57final boolean removeRootAfterClose;58final FileSystem delegate;59boolean isOpen;6061FaultyFileSystem(Path root) throws IOException {62if (root == null) {63root = Files.createTempDirectory("faultyFS");64removeRootAfterClose = true;65} else {66if (! Files.isDirectory(root)) {67throw new IllegalArgumentException("must be a directory.");68}69removeRootAfterClose = false;70}71this.root = root;72delegate = root.getFileSystem();73isOpen = true;74}7576private static Path unwrap(Path p) {77return PassThroughFileSystem.unwrap(p);78}7980Path getRoot() {81return new PassThroughFileSystem.PassThroughPath(this, root);82}8384@Override85public void close() throws IOException {86if (isOpen) {87if (removeRootAfterClose) {88TestUtil.removeAll(root);89}90isOpen = false;91}92}9394@Override95public FileSystemProvider provider() {96return FaultyFSProvider.getInstance();97}9899@Override100public boolean isOpen() {101return isOpen;102}103104@Override105public boolean isReadOnly() {106return delegate.isReadOnly();107}108109@Override110public String getSeparator() {111return delegate.getSeparator();112}113114private <T> Iterable<T> SoleIterable(final T element) {115return new Iterable<T>() {116@Override117public Iterator<T> iterator() {118return new Iterator<T>() {119private T soleElement = element;120121@Override122public boolean hasNext() {123return soleElement != null;124}125126@Override127public T next() {128try {129return soleElement;130} finally {131soleElement = null;132}133}134};135}136};137}138139@Override140public Iterable<Path> getRootDirectories() {141return SoleIterable(getRoot());142}143144@Override145public Iterable<FileStore> getFileStores() {146FileStore store;147try {148store = Files.getFileStore(root);149} catch (IOException ioe) {150store = null;151}152return SoleIterable(store);153}154155@Override156public Set<String> supportedFileAttributeViews() {157// assume that unwrapped objects aren't exposed158return delegate.supportedFileAttributeViews();159}160161@Override162public Path getPath(String first, String... more) {163return new PassThroughFileSystem.PassThroughPath(this, delegate.getPath(first, more));164}165166@Override167public PathMatcher getPathMatcher(String syntaxAndPattern) {168final PathMatcher matcher = delegate.getPathMatcher(syntaxAndPattern);169return new PathMatcher() {170@Override171public boolean matches(Path path) {172return matcher.matches(unwrap(path));173}174};175}176177@Override178public UserPrincipalLookupService getUserPrincipalLookupService() {179// assume that unwrapped objects aren't exposed180return delegate.getUserPrincipalLookupService();181}182183@Override184public WatchService newWatchService() throws IOException {185// to keep it simple186throw new UnsupportedOperationException();187}188189static class FaultyException extends IOException {190FaultyException() {191super("fault triggered.");192}193}194195static class FaultyFSProvider extends FileSystemProvider {196private static final String SCHEME = "faulty";197private static volatile FaultyFileSystem delegate;198private static FaultyFSProvider INSTANCE = new FaultyFSProvider();199private boolean enabled;200201private FaultyFSProvider() {}202203public static FaultyFSProvider getInstance() {204return INSTANCE;205}206207public void setFaultyMode(boolean enable) {208enabled = enable;209}210211private void triggerEx(String filename, String... names) throws IOException {212if (! enabled) {213return;214}215216if (filename.equals("SecurityException")) {217throw new SecurityException("FaultyFS", new FaultyException());218}219220if (filename.equals("IOException")) {221throw new FaultyException();222}223224for (String name: names) {225if (name.equals(filename)) {226throw new FaultyException();227}228}229}230231private void triggerEx(Path path, String... names) throws IOException {232triggerEx(path.getFileName().toString(), names);233}234235@Override236public String getScheme() {237return SCHEME;238}239240private void checkScheme(URI uri) {241if (!uri.getScheme().equalsIgnoreCase(SCHEME))242throw new IllegalArgumentException();243}244245private void checkUri(URI uri) {246checkScheme(uri);247if (!uri.getSchemeSpecificPart().equals("///"))248throw new IllegalArgumentException();249}250251@Override252public FileSystem newFileSystem(Path fakeRoot, Map<String,?> env)253throws IOException254{255if (env != null && env.keySet().contains("IOException")) {256triggerEx("IOException");257}258259synchronized (FaultyFSProvider.class) {260if (delegate != null && delegate.isOpen())261throw new FileSystemAlreadyExistsException();262FaultyFileSystem result = new FaultyFileSystem(fakeRoot);263delegate = result;264return result;265}266}267268@Override269public FileSystem newFileSystem(URI uri, Map<String,?> env)270throws IOException271{272if (env != null && env.keySet().contains("IOException")) {273triggerEx("IOException");274}275276checkUri(uri);277synchronized (FaultyFSProvider.class) {278if (delegate != null && delegate.isOpen())279throw new FileSystemAlreadyExistsException();280FaultyFileSystem result = new FaultyFileSystem(null);281delegate = result;282return result;283}284}285286@Override287public FileSystem getFileSystem(URI uri) {288checkUri(uri);289FileSystem result = delegate;290if (result == null)291throw new FileSystemNotFoundException();292return result;293}294295@Override296public Path getPath(URI uri) {297checkScheme(uri);298if (delegate == null)299throw new FileSystemNotFoundException();300301// only allow absolute path302String path = uri.getSchemeSpecificPart();303if (! path.startsWith("///")) {304throw new IllegalArgumentException();305}306return new PassThroughFileSystem.PassThroughPath(delegate, delegate.root.resolve(path.substring(3)));307}308309@Override310public void setAttribute(Path file, String attribute, Object value, LinkOption... options)311throws IOException312{313triggerEx(file, "setAttribute");314Files.setAttribute(unwrap(file), attribute, value, options);315}316317@Override318public Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options)319throws IOException320{321triggerEx(file, "readAttributes");322return Files.readAttributes(unwrap(file), attributes, options);323}324325@Override326public <V extends FileAttributeView> V getFileAttributeView(Path file,327Class<V> type,328LinkOption... options)329{330return Files.getFileAttributeView(unwrap(file), type, options);331}332333@Override334public <A extends BasicFileAttributes> A readAttributes(Path file,335Class<A> type,336LinkOption... options)337throws IOException338{339triggerEx(file, "readAttributes");340return Files.readAttributes(unwrap(file), type, options);341}342343@Override344public void delete(Path file) throws IOException {345triggerEx(file, "delete");346Files.delete(unwrap(file));347}348349@Override350public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)351throws IOException352{353triggerEx(target, "createSymbolicLink");354Files.createSymbolicLink(unwrap(link), unwrap(target), attrs);355}356357@Override358public void createLink(Path link, Path existing) throws IOException {359triggerEx(existing, "createLink");360Files.createLink(unwrap(link), unwrap(existing));361}362363@Override364public Path readSymbolicLink(Path link) throws IOException {365Path target = Files.readSymbolicLink(unwrap(link));366triggerEx(target, "readSymbolicLink");367return new PassThroughFileSystem.PassThroughPath(delegate, target);368}369370371@Override372public void copy(Path source, Path target, CopyOption... options) throws IOException {373triggerEx(source, "copy");374Files.copy(unwrap(source), unwrap(target), options);375}376377@Override378public void move(Path source, Path target, CopyOption... options) throws IOException {379triggerEx(source, "move");380Files.move(unwrap(source), unwrap(target), options);381}382383private DirectoryStream<Path> wrap(final DirectoryStream<Path> stream) {384return new DirectoryStream<Path>() {385@Override386public Iterator<Path> iterator() {387final Iterator<Path> itr = stream.iterator();388return new Iterator<Path>() {389private Path next = null;390@Override391public boolean hasNext() {392if (next == null) {393if (itr.hasNext()) {394next = itr.next();395} else {396return false;397}398}399if (next != null) {400try {401triggerEx(next, "DirectoryIteratorException");402} catch (IOException ioe) {403throw new DirectoryIteratorException(ioe);404} catch (SecurityException se) {405// ??? Does DS throw SecurityException during iteration?406next = null;407return hasNext();408}409}410return (next != null);411}412@Override413public Path next() {414try {415if (next != null || hasNext()) {416return new PassThroughFileSystem.PassThroughPath(delegate, next);417} else {418throw new NoSuchElementException();419}420} finally {421next = null;422}423}424425@Override426public void remove() {427itr.remove();428}429};430}431@Override432public void close() throws IOException {433stream.close();434}435};436}437438@Override439public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)440throws IOException441{442triggerEx(dir, "newDirectoryStream");443return wrap(Files.newDirectoryStream(unwrap(dir), filter));444}445446@Override447public void createDirectory(Path dir, FileAttribute<?>... attrs)448throws IOException449{450triggerEx(dir, "createDirectory");451Files.createDirectory(unwrap(dir), attrs);452}453454@Override455public SeekableByteChannel newByteChannel(Path file,456Set<? extends OpenOption> options,457FileAttribute<?>... attrs)458throws IOException459{460triggerEx(file, "newByteChannel");461return Files.newByteChannel(unwrap(file), options, attrs);462}463464465@Override466public boolean isHidden(Path file) throws IOException {467triggerEx(file, "isHidden");468return Files.isHidden(unwrap(file));469}470471@Override472public FileStore getFileStore(Path file) throws IOException {473triggerEx(file, "getFileStore");474return Files.getFileStore(unwrap(file));475}476477@Override478public boolean isSameFile(Path file, Path other) throws IOException {479triggerEx(file, "isSameFile");480return Files.isSameFile(unwrap(file), unwrap(other));481}482483@Override484public void checkAccess(Path file, AccessMode... modes)485throws IOException486{487triggerEx(file, "checkAccess");488// hack489if (modes.length == 0) {490if (Files.exists(unwrap(file)))491return;492else493throw new NoSuchFileException(file.toString());494}495throw new RuntimeException("not implemented yet");496}497}498}499500501