1 /* 2 * Copyright (c) 2010, 2011, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.nio.file.*; 25 import java.nio.file.attribute.*; 26 import java.nio.file.spi.FileSystemProvider; 27 import java.nio.channels.SeekableByteChannel; 28 import java.net.URI; 29 import java.util.*; 30 import java.io.*; 31 32 /** 33 * A "pass through" file system implementation that passes through, or delegates, 34 * everything to the default file system. 35 */ 36 37 class PassThroughFileSystem extends FileSystem { 38 private final FileSystemProvider provider; 39 private final FileSystem delegate; 40 41 PassThroughFileSystem(FileSystemProvider provider, FileSystem delegate) { 42 this.provider = provider; 43 this.delegate = delegate; 44 } 45 46 /** 47 * Creates a new "pass through" file system. Useful for test environments 48 * where the provider might not be deployed. 49 */ 50 static FileSystem create() throws IOException { 51 FileSystemProvider provider = new PassThroughProvider(); 52 Map<String,?> env = Collections.emptyMap(); 53 URI uri = URI.create("pass:///"); 54 return provider.newFileSystem(uri, env); 55 } 56 57 static Path unwrap(Path wrapper) { 58 if (wrapper == null) 59 throw new NullPointerException(); 60 if (!(wrapper instanceof PassThroughPath)) 61 throw new ProviderMismatchException(); 62 return ((PassThroughPath)wrapper).delegate; 63 } 64 65 @Override 66 public FileSystemProvider provider() { 67 return provider; 68 } 69 70 @Override 71 public void close() throws IOException { 72 delegate.close(); 73 } 74 75 @Override 76 public boolean isOpen() { 77 return delegate.isOpen(); 78 } 79 80 @Override 81 public boolean isReadOnly() { 82 return delegate.isReadOnly(); 83 } 84 85 @Override 86 public String getSeparator() { 87 return delegate.getSeparator(); 88 } 89 90 @Override 91 public Iterable<Path> getRootDirectories() { 92 final Iterable<Path> roots = delegate.getRootDirectories(); 93 return new Iterable<Path>() { 94 @Override 95 public Iterator<Path> iterator() { 96 final Iterator<Path> itr = roots.iterator(); 97 return new Iterator<Path>() { 98 @Override 99 public boolean hasNext() { 100 return itr.hasNext(); 101 } 102 @Override 103 public Path next() { 104 return new PassThroughPath(delegate, itr.next()); 105 } 106 @Override 107 public void remove() { 108 itr.remove(); 109 } 110 }; 111 } 112 }; 113 } 114 115 @Override 116 public Iterable<FileStore> getFileStores() { 117 // assume that unwrapped objects aren't exposed 118 return delegate.getFileStores(); 119 } 120 121 @Override 122 public Set<String> supportedFileAttributeViews() { 123 // assume that unwrapped objects aren't exposed 124 return delegate.supportedFileAttributeViews(); 125 } 126 127 @Override 128 public Path getPath(String first, String... more) { 129 return new PassThroughPath(this, delegate.getPath(first, more)); 130 } 131 132 @Override 133 public PathMatcher getPathMatcher(String syntaxAndPattern) { 134 final PathMatcher matcher = delegate.getPathMatcher(syntaxAndPattern); 135 return new PathMatcher() { 136 @Override 137 public boolean matches(Path path) { 138 return matcher.matches(unwrap(path)); 139 } 140 }; 141 } 142 143 @Override 144 public UserPrincipalLookupService getUserPrincipalLookupService() { 145 // assume that unwrapped objects aren't exposed 146 return delegate.getUserPrincipalLookupService(); 147 } 148 149 @Override 150 public WatchService newWatchService() throws IOException { 151 // to keep it simple 152 throw new UnsupportedOperationException(); 153 } 154 155 static class PassThroughProvider extends FileSystemProvider { 156 private static final String SCHEME = "pass"; 157 private static volatile PassThroughFileSystem delegate; 158 159 public PassThroughProvider() { } 160 161 @Override 162 public String getScheme() { 163 return SCHEME; 164 } 165 166 private void checkScheme(URI uri) { 167 if (!uri.getScheme().equalsIgnoreCase(SCHEME)) 168 throw new IllegalArgumentException(); 169 } 170 171 private void checkUri(URI uri) { 172 checkScheme(uri); 173 if (!uri.getSchemeSpecificPart().equals("///")) 174 throw new IllegalArgumentException(); 175 } 176 177 @Override 178 public FileSystem newFileSystem(URI uri, Map<String,?> env) 179 throws IOException 180 { 181 checkUri(uri); 182 synchronized (PassThroughProvider.class) { 183 if (delegate != null) 184 throw new FileSystemAlreadyExistsException(); 185 PassThroughFileSystem result = 186 new PassThroughFileSystem(this, FileSystems.getDefault()); 187 delegate = result; 188 return result; 189 } 190 } 191 192 @Override 193 public FileSystem getFileSystem(URI uri) { 194 checkUri(uri); 195 FileSystem result = delegate; 196 if (result == null) 197 throw new FileSystemNotFoundException(); 198 return result; 199 } 200 201 @Override 202 public Path getPath(URI uri) { 203 checkScheme(uri); 204 if (delegate == null) 205 throw new FileSystemNotFoundException(); 206 uri = URI.create(delegate.provider().getScheme() + ":" + 207 uri.getSchemeSpecificPart()); 208 return new PassThroughPath(delegate, delegate.provider().getPath(uri)); 209 } 210 211 @Override 212 public void setAttribute(Path file, String attribute, Object value, LinkOption... options) 213 throws IOException 214 { 215 Files.setAttribute(unwrap(file), attribute, value, options); 216 } 217 218 @Override 219 public Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options) 220 throws IOException 221 { 222 return Files.readAttributes(unwrap(file), attributes, options); 223 } 224 225 @Override 226 public <V extends FileAttributeView> V getFileAttributeView(Path file, 227 Class<V> type, 228 LinkOption... options) 229 { 230 return Files.getFileAttributeView(unwrap(file), type, options); 231 } 232 233 @Override 234 public <A extends BasicFileAttributes> A readAttributes(Path file, 235 Class<A> type, 236 LinkOption... options) 237 throws IOException 238 { 239 return Files.readAttributes(unwrap(file), type, options); 240 } 241 242 @Override 243 public void delete(Path file) throws IOException { 244 Files.delete(unwrap(file)); 245 } 246 247 @Override 248 public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) 249 throws IOException 250 { 251 Files.createSymbolicLink(unwrap(link), unwrap(target), attrs); 252 } 253 254 @Override 255 public void createLink(Path link, Path existing) throws IOException { 256 Files.createLink(unwrap(link), unwrap(existing)); 257 } 258 259 @Override 260 public Path readSymbolicLink(Path link) throws IOException { 261 Path target = Files.readSymbolicLink(unwrap(link)); 262 return new PassThroughPath(delegate, target); 263 } 264 265 266 @Override 267 public void copy(Path source, Path target, CopyOption... options) throws IOException { 268 Files.copy(unwrap(source), unwrap(target), options); 269 } 270 271 @Override 272 public void move(Path source, Path target, CopyOption... options) throws IOException { 273 Files.move(unwrap(source), unwrap(target), options); 274 } 275 276 private DirectoryStream<Path> wrap(final DirectoryStream<Path> stream) { 277 return new DirectoryStream<Path>() { 278 @Override 279 public Iterator<Path> iterator() { 280 final Iterator<Path> itr = stream.iterator(); 281 return new Iterator<Path>() { 282 @Override 283 public boolean hasNext() { 284 return itr.hasNext(); 285 } 286 @Override 287 public Path next() { 288 return new PassThroughPath(delegate, itr.next()); 289 } 290 @Override 291 public void remove() { 292 itr.remove(); 293 } 294 }; 295 } 296 @Override 297 public void close() throws IOException { 298 stream.close(); 299 } 300 }; 301 } 302 303 @Override 304 public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) 305 throws IOException 306 { 307 return wrap(Files.newDirectoryStream(dir, filter)); 308 } 309 310 @Override 311 public void createDirectory(Path dir, FileAttribute<?>... attrs) 312 throws IOException 313 { 314 Files.createDirectory(unwrap(dir), attrs); 315 } 316 317 @Override 318 public SeekableByteChannel newByteChannel(Path file, 319 Set<? extends OpenOption> options, 320 FileAttribute<?>... attrs) 321 throws IOException 322 { 323 return Files.newByteChannel(unwrap(file), options, attrs); 324 } 325 326 327 @Override 328 public boolean isHidden(Path file) throws IOException { 329 return Files.isHidden(unwrap(file)); 330 } 331 332 @Override 333 public FileStore getFileStore(Path file) throws IOException { 334 return Files.getFileStore(unwrap(file)); 335 } 336 337 @Override 338 public boolean isSameFile(Path file, Path other) throws IOException { 339 return Files.isSameFile(unwrap(file), unwrap(other)); 340 } 341 342 @Override 343 public void checkAccess(Path file, AccessMode... modes) 344 throws IOException 345 { 346 // hack 347 if (modes.length == 0) { 348 if (Files.exists(unwrap(file))) 349 return; 350 else 351 throw new NoSuchFileException(file.toString()); 352 } 353 throw new RuntimeException("not implemented yet"); 354 } 355 } 356 357 static class PassThroughPath implements Path { 358 private final FileSystem fs; 359 private final Path delegate; 360 361 PassThroughPath(FileSystem fs, Path delegate) { 362 this.fs = fs; 363 this.delegate = delegate; 364 } 365 366 private Path wrap(Path path) { 367 return (path != null) ? new PassThroughPath(fs, path) : null; 368 } 369 370 @Override 371 public FileSystem getFileSystem() { 372 return fs; 373 } 374 375 @Override 376 public boolean isAbsolute() { 377 return delegate.isAbsolute(); 378 } 379 380 @Override 381 public Path getRoot() { 382 return wrap(delegate.getRoot()); 383 } 384 385 @Override 386 public Path getParent() { 387 return wrap(delegate.getParent()); 388 } 389 390 @Override 391 public int getNameCount() { 392 return delegate.getNameCount(); 393 } 394 395 @Override 396 public Path getFileName() { 397 return wrap(delegate.getFileName()); 398 } 399 400 @Override 401 public Path getName(int index) { 402 return wrap(delegate.getName(index)); 403 } 404 405 @Override 406 public Path subpath(int beginIndex, int endIndex) { 407 return wrap(delegate.subpath(beginIndex, endIndex)); 408 } 409 410 @Override 411 public boolean startsWith(Path other) { 412 return delegate.startsWith(unwrap(other)); 413 } 414 415 @Override 416 public boolean startsWith(String other) { 417 return delegate.startsWith(other); 418 } 419 420 @Override 421 public boolean endsWith(Path other) { 422 return delegate.endsWith(unwrap(other)); 423 } 424 425 @Override 426 public boolean endsWith(String other) { 427 return delegate.endsWith(other); 428 } 429 430 @Override 431 public Path normalize() { 432 return wrap(delegate.normalize()); 433 } 434 435 @Override 436 public Path resolve(Path other) { 437 return wrap(delegate.resolve(unwrap(other))); 438 } 439 440 @Override 441 public Path resolve(String other) { 442 return wrap(delegate.resolve(other)); 443 } 444 445 @Override 446 public Path resolveSibling(Path other) { 447 return wrap(delegate.resolveSibling(unwrap(other))); 448 } 449 450 @Override 451 public Path resolveSibling(String other) { 452 return wrap(delegate.resolveSibling(other)); 453 } 454 455 @Override 456 public Path relativize(Path other) { 457 return wrap(delegate.relativize(unwrap(other))); 458 } 459 460 @Override 461 public boolean equals(Object other) { 462 if (!(other instanceof PassThroughPath)) 463 return false; 464 return delegate.equals(unwrap((PassThroughPath)other)); 465 } 466 467 @Override 468 public int hashCode() { 469 return delegate.hashCode(); 470 } 471 472 @Override 473 public String toString() { 474 return delegate.toString(); 475 } 476 477 @Override 478 public URI toUri() { 479 String ssp = delegate.toUri().getSchemeSpecificPart(); 480 return URI.create(fs.provider().getScheme() + ":" + ssp); 481 } 482 483 @Override 484 public Path toAbsolutePath() { 485 return wrap(delegate.toAbsolutePath()); 486 } 487 488 @Override 489 public Path toRealPath(LinkOption... options) throws IOException { 490 return wrap(delegate.toRealPath(options)); 491 } 492 493 @Override 494 public File toFile() { 495 return delegate.toFile(); 496 } 497 498 @Override 499 public Iterator<Path> iterator() { 500 final Iterator<Path> itr = delegate.iterator(); 501 return new Iterator<Path>() { 502 @Override 503 public boolean hasNext() { 504 return itr.hasNext(); 505 } 506 @Override 507 public Path next() { 508 return wrap(itr.next()); 509 } 510 @Override 511 public void remove() { 512 itr.remove(); 513 } 514 }; 515 } 516 517 @Override 518 public int compareTo(Path other) { 519 return delegate.compareTo(unwrap(other)); 520 } 521 522 @Override 523 public WatchKey register(WatchService watcher, 524 WatchEvent.Kind<?>[] events, 525 WatchEvent.Modifier... modifiers) 526 { 527 throw new UnsupportedOperationException(); 528 } 529 530 @Override 531 public WatchKey register(WatchService watcher, 532 WatchEvent.Kind<?>... events) 533 { 534 throw new UnsupportedOperationException(); 535 } 536 } 537 }