Skip to content

Commit

Permalink
Merge pull request #140 from emmartins/CMTOOL-173-1.0.x
Browse files Browse the repository at this point in the history
CMTOOL-174 & 175 fixes for 1.0.x
  • Loading branch information
emmartins committed Jan 29, 2018
2 parents a193a4c + a5694c1 commit d878bd4
Show file tree
Hide file tree
Showing 10 changed files with 464 additions and 215 deletions.
176 changes: 63 additions & 113 deletions core/src/main/java/org/jboss/migration/core/MigrationFiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,118 +19,87 @@

import java.io.IOException;
import java.nio.file.CopyOption;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

import static java.nio.file.FileVisitResult.CONTINUE;
import static java.nio.file.FileVisitResult.SKIP_SUBTREE;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
* The migration files.
* @author emmartins
*/
public class MigrationFiles {

private static final CopyOption[] COPY_OPTIONS = {
StandardCopyOption.REPLACE_EXISTING
};

private final Map<Path, Path> copiedFiles;

MigrationFiles() {
this.copiedFiles = new HashMap<>();
}

/**
* Copy a file.
* @param source the file's path
* @param target the file copy's path
* @throws IllegalArgumentException if the source's file does not exists
* @throws IllegalStateException if the target's path was used in a previous file copy, with a different source
* @throws ServerMigrationFailureException if the file copy failed
* Copy a path.
* @param source the source path
* @param target the target path
* @throws IllegalArgumentException if the source does not exists or any of the paths is not absolute
* @throws ServerMigrationFailureException if the path copy failed
*/
public synchronized void copy(final Path source, final Path target) throws IllegalArgumentException, ServerMigrationFailureException {
// check source file exists
if (!Files.exists(source)) {
throw ServerMigrationLogger.ROOT_LOGGER.sourceFileDoesNotExists(source);
throw new IllegalArgumentException("Source path "+source+" does not exists.");
}
final Path existentCopySource = copiedFiles.get(target);
if (existentCopySource != null) {
ServerMigrationLogger.ROOT_LOGGER.debugf("Skipping previously copied file %s", source);
} else {
try {
/*if (Files.exists(target)) {
Files.walkFileTree(target, new BackupVisitor(target, copiedFiles));
}*/
Files.createDirectories(target.getParent());
Files.walkFileTree(source, new CopyVisitor(source, target, copiedFiles));
} catch (IOException e) {
throw new ServerMigrationFailureException("File copy failed", e);
}
if (!source.isAbsolute()) {
throw new IllegalArgumentException("Source path "+source+" is not an absolute path.");
}
}

static class BackupVisitor extends SimpleFileVisitor<Path> {

private final Path source;
private final Path backup;
private final Map<Path, Path> copiedFiles;

BackupVisitor(Path source, final Map<Path, Path> copiedFiles) {
this.source = source;
this.copiedFiles = copiedFiles;
this.backup = source.resolveSibling(source.getFileName().toString()+".beforeMigration");
if (!target.isAbsolute()) {
throw new IllegalArgumentException("Target path "+target+" is not an absolute path.");
}

@Override
public FileVisitResult preVisitDirectory(Path sourcePath, BasicFileAttributes attrs) throws IOException {
boolean backup = true;
// if there is a child that was previously copied do not backup the directory
for (Path copiedTarget : copiedFiles.keySet()) {
if (copiedTarget.equals(sourcePath) || copiedTarget.startsWith(sourcePath)) {
backup = false;
break;
}
}
if (backup) {
final Path backupPath = getBackupPath(sourcePath);
Files.move(sourcePath, backupPath, COPY_OPTIONS);
return Files.newDirectoryStream(backupPath).iterator().hasNext() ? SKIP_SUBTREE : CONTINUE;
try {
Files.createDirectories(target.getParent());
if (Files.isDirectory(source)) {
copyDir(source, target, copiedFiles);
} else {
return Files.newDirectoryStream(sourcePath).iterator().hasNext() ? SKIP_SUBTREE : CONTINUE;
copyFile(source, target, copiedFiles);
}
} catch (IOException e) {
throw new ServerMigrationFailureException("Failed to copy "+source+" to "+target, e);
}
}

@Override
public FileVisitResult visitFile(Path sourcePath, BasicFileAttributes attrs) throws IOException {
final Path backupPath = getBackupPath(sourcePath);
Files.move(sourcePath, backupPath, COPY_OPTIONS);
return CONTINUE;
}
private static final CopyOption[] COPY_FILE_OPTIONS = { COPY_ATTRIBUTES, REPLACE_EXISTING };
private static final CopyOption[] BACKUP_FILE_OPTIONS = { REPLACE_EXISTING };

@Override
public FileVisitResult postVisitDirectory(Path sourcePath, IOException exc) throws IOException {
final Path backupPath = getBackupPath(sourcePath);
if (Files.exists(backupPath)) {
FileTime time = Files.getLastModifiedTime(sourcePath);
Files.setLastModifiedTime(backupPath, time);
private static void copyFile(Path source, Path target, Map<Path, Path> copiedFiles) throws IOException {
if (copiedFiles.put(target, source) == null) {
if (Files.exists(target)) {
// backup
ServerMigrationLogger.ROOT_LOGGER.tracef("Backing up target %s before copy", target);
final Path backup = target.resolveSibling(target.getFileName().toString()+".beforeMigration");
Files.move(target, backup, BACKUP_FILE_OPTIONS);
}
return CONTINUE;
}
ServerMigrationLogger.ROOT_LOGGER.tracef("Copying file %s to %s", source, target);
Files.copy(source, target, COPY_FILE_OPTIONS);
ServerMigrationLogger.ROOT_LOGGER.tracef("File %s copied to %s.", source, target);
}

private Path getBackupPath(Path sourcePath) {
return backup.resolve(source.relativize(sourcePath));
}
private static void copyDir(Path source, Path target, Map<Path, Path> copiedFiles) throws IOException {
Files.walkFileTree(source, CopyVisitor.FILE_VISITOR_OPTIONS, Integer.MAX_VALUE, new CopyVisitor(source, target, copiedFiles));
}

static class CopyVisitor extends SimpleFileVisitor<Path> {
private static class CopyVisitor extends SimpleFileVisitor<Path> {

static final EnumSet<FileVisitOption> FILE_VISITOR_OPTIONS = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
static final CopyOption[] COPY_DIR_OPTIONS = new CopyOption[] { COPY_ATTRIBUTES };

private final Map<Path, Path> copiedFiles;
private final Path source;
Expand All @@ -143,54 +112,35 @@ static class CopyVisitor extends SimpleFileVisitor<Path> {
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return copy(dir);
public FileVisitResult preVisitDirectory(Path sourceDir, BasicFileAttributes attrs) throws IOException {
Path targetDir = getTargetPath(sourceDir);
try {
Files.copy(sourceDir, targetDir, COPY_DIR_OPTIONS);
} catch (FileAlreadyExistsException e) {
if (!Files.isDirectory(targetDir)) {
throw e;
}
}
return CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
return copy(file);
}

private Path getTargetPath(Path sourceFile) {
return target.resolve(source.relativize(sourceFile));
public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
final Path targetFile = getTargetPath(sourceFile);
copyFile(sourceFile, targetFile, copiedFiles);
return CONTINUE;
}

private synchronized FileVisitResult copy(Path sourcePath) throws ServerMigrationFailureException {
final Path targetPath = getTargetPath(sourcePath);
final Path previousSourcePath = copiedFiles.put(targetPath, sourcePath);
if (previousSourcePath != null) {
if (previousSourcePath.equals(sourcePath)) {
return CONTINUE;
} else {
throw new ServerMigrationFailureException("Target "+targetPath+" previously copied and sources mismatch: new = "+sourcePath+", previous = "+previousSourcePath);
}
}
try {
if (Files.exists(targetPath)) {
if (!Files.isDirectory(targetPath)) {
// backup file to be replaced
final Path backupPath = targetPath.resolveSibling(targetPath.getFileName().toString()+".beforeMigration");
Files.move(targetPath, backupPath, COPY_OPTIONS);
} else {
// dir already exists
return CONTINUE;
}
}
ServerMigrationLogger.ROOT_LOGGER.tracef("Copying file %s", targetPath);
Files.copy(sourcePath, targetPath, COPY_OPTIONS);
} catch (IOException e) {
throw new ServerMigrationFailureException("File copy failed.", e);
}
ServerMigrationLogger.ROOT_LOGGER.debugf("File %s copied to %s.", sourcePath, targetPath);
return CONTINUE;
private Path getTargetPath(Path sourcePath) {
return target.resolve(source.relativize(sourcePath));
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
final Path targetDir = getTargetPath(dir);
FileTime time = Files.getLastModifiedTime(dir);
Files.setLastModifiedTime(targetDir, time);
public FileVisitResult postVisitDirectory(Path sourceDir, IOException e) throws IOException {
if (e == null) {
final Path targetDir = getTargetPath(sourceDir);
Files.setLastModifiedTime(targetDir, Files.getLastModifiedTime(sourceDir));
}
return CONTINUE;
}
}
Expand Down

0 comments on commit d878bd4

Please sign in to comment.