public static void main(String[] args) throws Exception { Path dir1 = TestUtil.createTemporaryDirectory(); try { // Same directory testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1)); testMove(dir1, dir1, TestUtil.supportsLinks(dir1)); // Different directories. Use test.dir if possible as it might be // a different volume/file system and so improve test coverage. String testDir = System.getProperty("test.dir", "."); Path dir2 = TestUtil.createTemporaryDirectory(testDir); try { boolean testSymbolicLinks = TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2); testCopyFileToFile(dir1, dir2, testSymbolicLinks); testMove(dir1, dir2, testSymbolicLinks); } finally { TestUtil.removeAll(dir2); } // Target is location associated with custom provider Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString()); testCopyFileToFile(dir1, dir3, false); testMove(dir1, dir3, false); // Test copy(InputStream,Path) and copy(Path,OutputStream) testCopyInputStreamToFile(); testCopyFileToOuputStream(); } finally { TestUtil.removeAll(dir1); } }
// copy source to target with verification static void copyAndVerify(Path source, Path target, CopyOption... options) throws IOException { Path result = copy(source, target, options); assertTrue(result == target); // get attributes of source and target file to verify copy boolean followLinks = true; LinkOption[] linkOptions = new LinkOption[0]; boolean copyAttributes = false; for (CopyOption opt : options) { if (opt == NOFOLLOW_LINKS) { followLinks = false; linkOptions = new LinkOption[] {NOFOLLOW_LINKS}; } if (opt == COPY_ATTRIBUTES) copyAttributes = true; } BasicFileAttributes basicAttributes = readAttributes(source, BasicFileAttributes.class, linkOptions); // check hash if regular file if (basicAttributes.isRegularFile()) assertTrue(computeHash(source) == computeHash(target)); // check link target if symbolic link if (basicAttributes.isSymbolicLink()) assert (readSymbolicLink(source).equals(readSymbolicLink(target))); // check that attributes are copied if (copyAttributes && followLinks) { checkBasicAttributes( basicAttributes, readAttributes(source, BasicFileAttributes.class, linkOptions)); // verify other attributes when same provider if (source.getFileSystem().provider() == target.getFileSystem().provider()) { // check POSIX attributes are copied String os = System.getProperty("os.name"); if ((os.equals("SunOS") || os.equals("Linux")) && testPosixAttributes) { checkPosixAttributes( readAttributes(source, PosixFileAttributes.class, linkOptions), readAttributes(target, PosixFileAttributes.class, linkOptions)); } // check DOS attributes are copied if (os.startsWith("Windows")) { checkDosAttributes( readAttributes(source, DosFileAttributes.class, linkOptions), readAttributes(target, DosFileAttributes.class, linkOptions)); } // check named attributes are copied if (followLinks && getFileStore(source).supportsFileAttributeView("xattr") && getFileStore(target).supportsFileAttributeView("xattr")) { checkUserDefinedFileAttributes( readUserDefinedFileAttributes(source), readUserDefinedFileAttributes(target)); } } } }
// "randomize" the file attributes of the given file. static void randomizeAttributes(Path file) throws IOException { String os = System.getProperty("os.name"); boolean isWindows = os.startsWith("Windows"); boolean isUnix = os.equals("SunOS") || os.equals("Linux"); boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS); if (isUnix) { Set<PosixFilePermission> perms = getPosixFilePermissions(file, NOFOLLOW_LINKS); PosixFilePermission[] toChange = { PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_WRITE, PosixFilePermission.GROUP_EXECUTE, PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_WRITE, PosixFilePermission.OTHERS_EXECUTE }; for (PosixFilePermission perm : toChange) { if (heads()) { perms.add(perm); } else { perms.remove(perm); } } setPosixFilePermissions(file, perms); } if (isWindows) { DosFileAttributeView view = getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS); // only set or unset the hidden attribute view.setHidden(heads()); } boolean addUserDefinedFileAttributes = heads() && getFileStore(file).supportsFileAttributeView("xattr"); // remove this when copying a direcory copies its named streams if (isWindows && isDirectory) addUserDefinedFileAttributes = false; if (addUserDefinedFileAttributes) { UserDefinedFileAttributeView view = getFileAttributeView(file, UserDefinedFileAttributeView.class); int n = rand.nextInt(16); while (n > 0) { byte[] value = new byte[1 + rand.nextInt(100)]; view.write("user." + Integer.toString(n), ByteBuffer.wrap(value)); n--; } } }
// void processEvents() { public void run() { System.out.println("WatchDir Thread INFO: priority=" + Thread.currentThread().getPriority()); for (; ; ) { // wait for key to be signalled System.out.println("WatchDir INFO: restarting loop...acquiring new key"); WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return; } Path dir = keys.get(key); if (dir == null) { System.err.println("WatchKey not recognized!!"); continue; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind kind = event.kind(); // TBD - provide example of how OVERFLOW event is handled if (kind == OVERFLOW) { System.out.println("Encountered OVERFLOW Event - " + event); continue; } // Context for directory entry event is the file name of entry WatchEvent<Path> ev = cast(event); Path name = ev.context(); Path child = dir.resolve(name); // print out event System.out.format("[WatchDir] %s: %s\n", event.kind().name(), child); // if directory is created, and watching recursively, then // register it and its sub-directories if (recursive && (kind == ENTRY_CREATE)) { try { if (Files.isDirectory(child, NOFOLLOW_LINKS)) { registerAll(child); } } catch (IOException x) { // ignore to keep sample readbale } } long t = System.currentTimeMillis(); if (!Folder.dontWatch.contains(Folder.getInternalPath(child))) { Thread.currentThread().setPriority(Thread.NORM_PRIORITY); System.out.println( "WatchDir#" + key + " INFO: path=" + child + ", internal=" + Folder.getInternalPath(child) + " is NOT in don't watch list. Forwarding it to other peers. @" + Main.timeToString(t)); // DEBUG forwardToItopic(kind, child); } else { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); System.out.println( "WatchDir#" + key + " INFO: path=" + child + ", internal=" + Folder.getInternalPath(child) + " IS in the don't watch list. NOT forwarding. @" + Main.timeToString(t)); // DEBUG // try{ // Thread.sleep(minDelayBtwnWatchEvents); // } catch(InterruptedException ex) { // System.err.println("Exception:"+ex+" while trying to sleep WatchDir thread"); // ex.printStackTrace(); // } } } // reset key and remove from set if directory no longer accessible boolean valid = key.reset(); if (!valid) { keys.remove(key); // all directories are inaccessible if (keys.isEmpty()) { break; } } } }
/** Tests all possible ways to invoke copy to copy a file to a file */ static void testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks) throws IOException { Path source, target, link, entry; // -- regular file -- /** Test: move regular file, target does not exist */ source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target); delete(source); delete(target); /** Test: copy regular file, target exists */ source = createSourceFile(dir1); target = getTargetFile(dir2); createFile(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } delete(target); createDirectory(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } delete(source); delete(target); /** Test: copy regular file, target does not exist */ source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy regular file, target exists */ source = createSourceFile(dir1); target = getTargetFile(dir2); createFile(target); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy regular file, target exists and is empty directory */ source = createSourceFile(dir1); target = getTargetFile(dir2); createDirectory(target); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy regular file, target exists and is non-empty directory */ source = createSourceFile(dir1); target = getTargetFile(dir2); createDirectory(target); entry = target.resolve("foo"); createFile(entry); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } delete(entry); delete(source); delete(target); /** Test: copy regular file + attributes */ source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, COPY_ATTRIBUTES); delete(source); delete(target); // -- directory -- /* * Test: copy directory, target does not exist */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target); delete(source); delete(target); /** Test: copy directory, target exists */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); createFile(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } delete(target); createDirectory(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } delete(source); delete(target); /** Test: copy directory, target does not exist */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy directory, target exists */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); createFile(target); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy directory, target exists and is empty directory */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); createDirectory(target); copyAndVerify(source, target, REPLACE_EXISTING); delete(source); delete(target); /** Test: copy directory, target exists and is non-empty directory */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); createDirectory(target); entry = target.resolve("foo"); createFile(entry); try { copyAndVerify(source, target, REPLACE_EXISTING); throw new RuntimeException("DirectoryNotEmptyException expected"); } catch (DirectoryNotEmptyException x) { } delete(entry); delete(source); delete(target); /* * Test: copy directory + attributes */ source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, COPY_ATTRIBUTES); delete(source); delete(target); // -- symbolic links -- /** Test: Follow link */ if (supportsLinks) { source = createSourceFile(dir1); link = dir1.resolve("link"); createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target); delete(link); delete(source); } /** Test: Copy link (to file) */ if (supportsLinks) { source = createSourceFile(dir1); link = dir1.resolve("link"); createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); delete(link); delete(source); } /** Test: Copy link (to directory) */ if (supportsLinks) { source = dir1.resolve("mydir"); createDirectory(source); link = dir1.resolve("link"); createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); delete(link); delete(source); } /** Test: Copy broken link */ if (supportsLinks) { assertTrue(notExists(source)); link = dir1.resolve("link"); createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); delete(link); } /** Test: Copy link to UNC (Windows only) */ if (supportsLinks && System.getProperty("os.name").startsWith("Windows")) { Path unc = Paths.get("\\\\rialto\\share\\file"); link = dir1.resolve("link"); createSymbolicLink(link, unc); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); delete(link); } // -- misc. tests -- /** Test nulls */ source = createSourceFile(dir1); target = getTargetFile(dir2); try { copy(source, null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { copy(source, target, (CopyOption[]) null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { CopyOption[] opts = {REPLACE_EXISTING, null}; copy(source, target, opts); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } delete(source); /** Test UOE */ source = createSourceFile(dir1); target = getTargetFile(dir2); try { copy(source, target, new CopyOption() {}); } catch (UnsupportedOperationException x) { } try { copy(source, target, REPLACE_EXISTING, new CopyOption() {}); } catch (UnsupportedOperationException x) { } delete(source); }
// move source to target with verification static void moveAndVerify(Path source, Path target, CopyOption... options) throws IOException { // read attributes before file is moved BasicFileAttributes basicAttributes = null; PosixFileAttributes posixAttributes = null; DosFileAttributes dosAttributes = null; Map<String, ByteBuffer> namedAttributes = null; // get file attributes of source file String os = System.getProperty("os.name"); if (os.startsWith("Windows")) { dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS); basicAttributes = dosAttributes; } else { posixAttributes = readAttributes(source, PosixFileAttributes.class, NOFOLLOW_LINKS); basicAttributes = posixAttributes; } if (basicAttributes == null) basicAttributes = readAttributes(source, BasicFileAttributes.class, NOFOLLOW_LINKS); // hash file contents if regular file int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0; // record link target if symbolic link Path linkTarget = null; if (basicAttributes.isSymbolicLink()) linkTarget = readSymbolicLink(source); // read named attributes if available (and file is not a sym link) if (!basicAttributes.isSymbolicLink() && getFileStore(source).supportsFileAttributeView("xattr")) { namedAttributes = readUserDefinedFileAttributes(source); } // move file Path result = move(source, target, options); assertTrue(result == target); // verify source does not exist assertTrue(notExists(source)); // verify file contents if (basicAttributes.isRegularFile()) { if (computeHash(target) != hash) throw new RuntimeException("Failed to verify move of regular file"); } // verify link target if (basicAttributes.isSymbolicLink()) { if (!readSymbolicLink(target).equals(linkTarget)) throw new RuntimeException("Failed to verify move of symbolic link"); } // verify basic attributes checkBasicAttributes( basicAttributes, readAttributes(target, BasicFileAttributes.class, NOFOLLOW_LINKS)); // verify other attributes when same provider if (source.getFileSystem().provider() == target.getFileSystem().provider()) { // verify POSIX attributes if (posixAttributes != null && !basicAttributes.isSymbolicLink() && testPosixAttributes) { checkPosixAttributes( posixAttributes, readAttributes(target, PosixFileAttributes.class, NOFOLLOW_LINKS)); } // verify DOS attributes if (dosAttributes != null && !basicAttributes.isSymbolicLink()) { DosFileAttributes attrs = readAttributes(target, DosFileAttributes.class, NOFOLLOW_LINKS); checkDosAttributes(dosAttributes, attrs); } // verify named attributes if (namedAttributes != null && getFileStore(target).supportsFileAttributeView("xattr")) { checkUserDefinedFileAttributes(namedAttributes, readUserDefinedFileAttributes(target)); } } }
static void usage() { System.err.println("usage: java WatchDir [-r] dir"); System.exit(-1); }