Skip to content

Commit

Permalink
Merge pull request #1 from rage/javaFileMovingPolicies
Browse files Browse the repository at this point in the history
Java file moving policies
  • Loading branch information
ljleppan committed Jun 25, 2015
2 parents 5256e0a + ce2492c commit d72a5b1
Show file tree
Hide file tree
Showing 23 changed files with 676 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fi.helsinki.cs.tmc.langs.java.testrunner;
package fi.helsinki.cs.tmc.langs;

/**
* Serializable form of an exception.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fi.helsinki.cs.tmc.langs.java.testrunner;
package fi.helsinki.cs.tmc.langs;

import org.junit.runner.notification.Failure;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
public class DefaultFileMovingPolicy implements FileMovingPolicy {

@Override
public boolean shouldMove(Path path) {
public boolean shouldMove(Path path, Path rootPath, Path target) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package fi.helsinki.cs.tmc.langs.sandbox;

import com.fasterxml.jackson.dataformat.yaml.snakeyaml.Yaml;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* An abstract {@link FileMovingPolicy} that also uses
Expand All @@ -14,22 +23,33 @@
*/
public abstract class ExtraStudentFileAwareFileMovingPolicy implements FileMovingPolicy {

private static final Path TMC_PROJECT_YML = Paths.get(".tmcproject.yml");

private List<Path> extraStudentFiles;
private Path rootPath;
private Path target;

/**
* Determines whether a file should be moved even if it is not an <tt>ExtraStudentFile</tt>.
*/
protected abstract boolean shouldMoveFile(Path path);
public abstract boolean shouldMoveFile(Path path);

@Override
public boolean shouldMove(Path path) {
public boolean shouldMove(Path path, Path rootPath, Path target) {
if (!path.toFile().exists()) {
return false;
}

if (path.toFile().isDirectory()) {
return false;
}

if (path.getFileName().equals(TMC_PROJECT_YML)) {
return false;
}

this.rootPath = rootPath;
this.target = target;

return isExtraStudentFile(path) || shouldMoveFile(path);
}
Expand Down Expand Up @@ -58,6 +78,55 @@ private boolean isExtraStudentFile(Path path) {
* and parses it for the necessary information.
*/
private void loadExtraStudentFileList() {
extraStudentFiles = new ArrayList<>();

File tmcprojectyml = this.target.toAbsolutePath().resolve(TMC_PROJECT_YML).toFile();

if (tmcprojectyml.exists()) {
parseExtraStudentFiles(tmcprojectyml);
}
}

private void parseExtraStudentFiles(File file) {
String fileContents = initFileContents(file);
Yaml yaml = new Yaml();
Object yamlSpecifications = yaml.load(fileContents);

if (!(yamlSpecifications instanceof Map)) {
return;
}

Map<?, ?> specsAsMap = (Map<?, ?>) yamlSpecifications;
Object files = specsAsMap.get("extra_student_files");
addFiles(files);
}

private void addFiles(Object files) {
addAllIfList(files);
addIfString(files);
}

private void addAllIfList(Object files) {
if (files instanceof List) {
for (Object value : (List<?>) files) {
addIfString(value);
}
}
}

private void addIfString(Object value) {
if (value instanceof String) {
Path path = this.rootPath.resolve((String) value);
extraStudentFiles.add(path);
}
}

private String initFileContents(File file) {
try {
return FileUtils.readFileToString(file);
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public interface FileMovingPolicy {
/**
* Answers whether a single file should be moved.
*/
boolean shouldMove(Path path);
boolean shouldMove(Path path, Path rootPath, Path target);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package fi.helsinki.cs.tmc.langs.sandbox;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -41,35 +44,44 @@ public SubmissionProcessor(FileMovingPolicy fileMovingPolicy) {
* moved.
* @param target Directory to which the source files are moved to.
*/
public void moveFiles(Path source, Path target) {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(source)) {
for (Path sourceFile : stream) {
if (fileMovingPolicy.shouldMove(sourceFile)) {
Path absoluteTargetPath = getAbsoluteTargetPath(source, target, sourceFile);
try {
moveFile(source, sourceFile.toAbsolutePath(), absoluteTargetPath);
} catch (IOException exception) {
public void moveFiles(final Path source, final Path target) {
try {
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (fileMovingPolicy.shouldMove(file, source, target)) {
try {
moveFile(source, file, target);
} catch (IOException exception) {
log.log(Level.WARNING, null, exception);
}
}

return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exception)
throws IOException {
if (exception == null) {
return FileVisitResult.CONTINUE;
} else {
// directory iteration failed
log.log(Level.WARNING, null, exception);
throw exception;
}
}
}
});
} catch (IOException exception) {
log.log(Level.WARNING, null, exception);
return;
}
}

protected Path getAbsoluteTargetPath(Path sourceRootPath,
Path targetRootPath,
Path sourceFilePath) {
Path relativeFilePath = sourceRootPath.relativize(sourceFilePath.toAbsolutePath());
return targetRootPath.resolve(relativeFilePath);
}

protected void moveFile(Path sourceRoot, Path sourceFile, Path target) throws IOException {
Path relative = sourceRoot.relativize(sourceFile);
Path targetFile = target.resolve(relative);
Files.createDirectories(targetFile.getParent());
Files.move(sourceFile, targetFile);
Files.move(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package fi.helsinki.cs.tmc.langs.utils;

import fi.helsinki.cs.tmc.langs.sandbox.ExtraStudentFileAwareFileMovingPolicy;

import com.google.common.base.Throwables;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
Expand All @@ -11,6 +15,7 @@
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;

public final class TestUtils {

Expand Down Expand Up @@ -71,4 +76,60 @@ public FileVisitResult postVisitDirectory(Path dir, IOException ex) throws IOExc
public static void removeDirRecursively(Class clazz, String location) throws IOException {
removeDirRecursively(getPath(clazz, location));
}

/**
* Collects a list of paths that are to be moved with the provided file moving policy.
*/
public static void collectPaths(final Path path,
final List<String> toBeMoved,
final ExtraStudentFileAwareFileMovingPolicy fileMovingPolicy)
throws IOException {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
if (fileMovingPolicy.shouldMoveFile(path.relativize(file))) {
toBeMoved.add(path.relativize(file).toString());
}

return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exception)
throws IOException {
if (exception == null) {
return FileVisitResult.CONTINUE;
} else {
// directory iteration failed
throw exception;
}
}
});
}

/**
* Initializes a temporary file with content.
*/
public static File initTempFileWithContent(String prefix, String suffix, String content)
throws IOException {
return initTempFileWithContent(prefix, suffix, null, content);
}

/**
* Initializes a temporary file in a specific directory with content.
*/
public static File initTempFileWithContent(String prefix, String suffix, File directory,
String content) throws IOException {
String suffixWithDot = "." + suffix;
File file = File.createTempFile(prefix, suffixWithDot, directory);
file.deleteOnExit();

PrintWriter pw = new PrintWriter(file, "UTF-8");
pw.println(content);
pw.flush();
pw.close();

return file;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fi.helsinki.cs.tmc.langs.java.testrunner;
package fi.helsinki.cs.tmc.langs;

import static org.junit.Assert.assertEquals;

import fi.helsinki.cs.tmc.langs.CaughtException;

import org.junit.Test;

public class CaughtExceptionTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package fi.helsinki.cs.tmc.langs.java.testrunner;
package fi.helsinki.cs.tmc.langs;

import static org.junit.Assert.assertEquals;

import fi.helsinki.cs.tmc.langs.java.testrunner.TestCase.Status;
import fi.helsinki.cs.tmc.langs.TestCase.Status;

import org.junit.Test;
import org.junit.runner.notification.Failure;
Expand Down Expand Up @@ -46,5 +46,4 @@ public void testToString() {
testCase.testFinished();
assertEquals("Method (Test) PASSED", testCase.toString());
}

}
Loading

0 comments on commit d72a5b1

Please sign in to comment.