3 import java
.io
.IOException
;
4 import java
.nio
.file
.FileVisitResult
;
5 import java
.nio
.file
.Files
;
6 import java
.nio
.file
.Path
;
7 import java
.nio
.file
.SimpleFileVisitor
;
8 import java
.nio
.file
.StandardCopyOption
;
9 import java
.nio
.file
.attribute
.BasicFileAttributes
;
10 import java
.nio
.file
.attribute
.FileTime
;
12 /** Synchronises two directory structures. */
13 public class BasicSyncFileVisitor
extends SimpleFileVisitor
<Path
> {
14 // TODO make it configurable
15 private boolean debug
= true;
17 private final Path sourceBasePath
;
18 private final Path targetBasePath
;
19 private final boolean delete
;
21 public BasicSyncFileVisitor(Path sourceBasePath
, Path targetBasePath
, boolean delete
) {
22 this.sourceBasePath
= sourceBasePath
;
23 this.targetBasePath
= targetBasePath
;
28 public FileVisitResult
preVisitDirectory(Path sourceDir
, BasicFileAttributes attrs
) throws IOException
{
29 Path targetDir
= toTargetPath(sourceDir
);
30 Files
.createDirectories(targetDir
);
31 return FileVisitResult
.CONTINUE
;
35 public FileVisitResult
postVisitDirectory(Path sourceDir
, IOException exc
) throws IOException
{
37 Path targetDir
= toTargetPath(sourceDir
);
38 for (Path targetPath
: Files
.newDirectoryStream(targetDir
)) {
39 Path sourcePath
= sourceDir
.resolve(targetPath
.getFileName());
40 if (!Files
.exists(sourcePath
)) {
42 FsUtils
.delete(targetPath
);
44 } catch (Exception e
) {
45 deleteFailed(targetPath
, exc
);
50 return FileVisitResult
.CONTINUE
;
54 public FileVisitResult
visitFile(Path sourceFile
, BasicFileAttributes attrs
) throws IOException
{
55 Path targetFile
= toTargetPath(sourceFile
);
57 if (!Files
.exists(targetFile
)) {
58 Files
.copy(sourceFile
, targetFile
);
59 copied(sourceFile
, targetFile
);
61 if (shouldOverwrite(sourceFile
, targetFile
)) {
62 Files
.copy(sourceFile
, targetFile
, StandardCopyOption
.REPLACE_EXISTING
);
65 } catch (Exception e
) {
66 copyFailed(sourceFile
, targetFile
, e
);
68 return FileVisitResult
.CONTINUE
;
71 protected boolean shouldOverwrite(Path sourceFile
, Path targetFile
) throws IOException
{
72 long sourceSize
= Files
.size(sourceFile
);
73 long targetSize
= Files
.size(targetFile
);
74 if (sourceSize
!= targetSize
) {
77 FileTime sourceLastModif
= Files
.getLastModifiedTime(sourceFile
);
78 FileTime targetLastModif
= Files
.getLastModifiedTime(targetFile
);
79 if (sourceLastModif
.compareTo(targetLastModif
) > 0)
81 return shouldOverwriteLaterSameSize(sourceFile
, targetFile
);
84 protected boolean shouldOverwriteLaterSameSize(Path sourceFile
, Path targetFile
) {
89 // public FileVisitResult visitFileFailed(Path sourceFile, IOException exc) throws IOException {
90 // error("Cannot sync " + sourceFile, exc);
91 // return FileVisitResult.CONTINUE;
94 private Path
toTargetPath(Path sourcePath
) {
95 Path relativePath
= sourceBasePath
.relativize(sourcePath
);
96 Path targetPath
= targetBasePath
.resolve(relativePath
.toString());
100 public Path
getSourceBasePath() {
101 return sourceBasePath
;
104 public Path
getTargetBasePath() {
105 return targetBasePath
;
108 protected void copied(Path sourcePath
, Path targetPath
) {
109 if (isDebugEnabled())
110 debug("Copied " + sourcePath
+ " to " + targetPath
);
113 protected void copyFailed(Path sourcePath
, Path targetPath
, Exception e
) {
114 error("Cannot copy " + sourcePath
+ " to " + targetPath
, e
);
117 protected void deleted(Path targetPath
) {
118 if (isDebugEnabled())
119 debug("Deleted " + targetPath
);
122 protected void deleteFailed(Path targetPath
, Exception e
) {
123 error("Cannot delete " + targetPath
, e
);
127 protected void error(Object obj
, Throwable e
) {
128 System
.err
.println(obj
);
132 protected boolean isDebugEnabled() {
136 protected void debug(Object obj
) {
137 System
.out
.println(obj
);