Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FilePathUtils.joinZipPathSegments error on windows #1609

Merged
merged 6 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions core/src/main/java/de/jplag/reporting/FilePathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

public final class FilePathUtil {
private static final String ZIP_PATH_SEPARATOR = "/"; // Paths in zip files are always separated by a slash
private static final String WINDOWS_PATH_SEPARATOR = "\\";

private FilePathUtil() {
// private constructor to prevent instantiation
Expand All @@ -28,23 +27,26 @@ public static String getRelativeSubmissionPath(File file, Submission submission,
return Path.of(submissionToIdFunction.apply(submission), submission.getRoot().toPath().relativize(file.toPath()).toString()).toString();
}

/**
* Joins logical paths using a slash. This method ensures, that no duplicate slashes are created in between.
* @param left The left path segment
* @param right The right path segment
* @return The joined paths
*/
public static String joinZipPathSegments(String left, String right) {
String rightStripped = right;
while (rightStripped.startsWith(ZIP_PATH_SEPARATOR) || rightStripped.startsWith(WINDOWS_PATH_SEPARATOR)) {
rightStripped = rightStripped.substring(1);
public static Path forceRelativePath(Path path) {
TwoOfTwelve marked this conversation as resolved.
Show resolved Hide resolved
if (path.isAbsolute()) {
return Path.of("/").relativize(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the explicit backslash intentional? Is it another concept or why is the constant with the same value not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The slash here is intentional, as we simply need a path that represents a root. It does not matter which, but in my opinion a UNIX root is the simplest. It does not use the constant, because the divider for zip paths is something else than a root. If you prefer it, I can change it to use the constant or a new one instead.

}
return path;
}

String leftStripped = left;
while (leftStripped.endsWith(ZIP_PATH_SEPARATOR) || leftStripped.startsWith(WINDOWS_PATH_SEPARATOR)) {
leftStripped = leftStripped.substring(0, leftStripped.length() - 1);
}
public static Path createRelativePath(String path) {
TwoOfTwelve marked this conversation as resolved.
Show resolved Hide resolved
return forceRelativePath(Path.of(path));
}
TwoOfTwelve marked this conversation as resolved.
Show resolved Hide resolved

return leftStripped + ZIP_PATH_SEPARATOR + rightStripped;
public static String pathAsZipPath(Path path) {
TwoOfTwelve marked this conversation as resolved.
Show resolved Hide resolved
Path real = forceRelativePath(path);
TwoOfTwelve marked this conversation as resolved.
Show resolved Hide resolved
StringBuilder builder = new StringBuilder();
for (int i = 0; i < real.getNameCount(); i++) {
if (i != 0) {
builder.append(ZIP_PATH_SEPARATOR);
}
builder.append(real.getName(i));
}
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.jplag.reporting.jsonfactory;

import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -58,7 +59,7 @@ private void writeComparisons(List<JPlagComparison> comparisons) {
var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId,
Map.of(SimilarityMetric.AVG.name(), comparison.similarity(), SimilarityMetric.MAX.name(), comparison.maximalSimilarity()),
convertMatchesToReportMatches(comparison), comparison.similarityOfFirst(), comparison.similarityOfSecond());
resultWriter.addJsonEntry(comparisonReport, fileName);
resultWriter.addJsonEntry(comparisonReport, Path.of(fileName));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
Expand Down Expand Up @@ -41,17 +42,17 @@
public class ReportObjectFactory {
private static final Logger logger = LoggerFactory.getLogger(ReportObjectFactory.class);

public static final String OVERVIEW_FILE_NAME = "overview.json";
public static final Path OVERVIEW_FILE_NAME = Path.of("overview.json");

public static final String README_FILE_NAME = "README.txt";
public static final String OPTIONS_FILE_NAME = "options.json";
public static final Path README_FILE_NAME = Path.of("README.txt");
public static final Path OPTIONS_FILE_NAME = Path.of("options.json");
private static final String[] README_CONTENT = new String[] {"This is a software plagiarism report generated by JPlag.",
"To view the report go to https://jplag.github.io/JPlag/ and drag the generated zip file onto the page."};

public static final String SUBMISSION_FILE_INDEX_FILE_NAME = "submissionFileIndex.json";
public static final Path SUBMISSION_FILE_INDEX_FILE_NAME = Path.of("submissionFileIndex.json");
public static final Version REPORT_VIEWER_VERSION = JPlag.JPLAG_VERSION;

private static final String SUBMISSIONS_ROOT_PATH = "files/";
private static final Path SUBMISSIONS_ROOT_PATH = Path.of("files");

private Map<String, String> submissionNameToIdMap;
private Function<Submission, String> submissionToIdFunction;
Expand Down Expand Up @@ -106,13 +107,13 @@ private void copySubmissionFilesToReport(JPlagResult result) {
Set<Submission> submissions = getSubmissions(comparisons);
Language language = result.getOptions().language();
for (Submission submission : submissions) {
String submissionRootPath = SUBMISSIONS_ROOT_PATH + submissionToIdFunction.apply(submission);
Path submissionRootPath = SUBMISSIONS_ROOT_PATH.resolve(FilePathUtil.createRelativePath(submissionToIdFunction.apply(submission)));
for (File file : submission.getFiles()) {
String relativeFilePath = file.getAbsolutePath().substring(submission.getRoot().getAbsolutePath().length());
if (relativeFilePath.isEmpty()) {
relativeFilePath = file.getName();
Path relativeFilePath = Path.of(submission.getRoot().getAbsolutePath()).relativize(Path.of(file.getAbsolutePath()));
if (relativeFilePath.getNameCount() == 0 || relativeFilePath.equals(Path.of(""))) {
relativeFilePath = Path.of(file.getName());
}
String zipPath = FilePathUtil.joinZipPathSegments(submissionRootPath, relativeFilePath);
Path zipPath = submissionRootPath.resolve(relativeFilePath);

File fileToCopy = getFileToCopy(language, file);
this.resultWriter.addFileContentEntry(zipPath, fileToCopy);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.jplag.reporting.reportobject.writer;

import java.io.File;
import java.nio.file.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -16,17 +17,17 @@ public class DummyResultWriter implements JPlagResultWriter {
private static final String MESSAGE_CLOSE = "DummyWriter closed.";

@Override
public void addJsonEntry(Object jsonContent, String path) {
public void addJsonEntry(Object jsonContent, Path path) {
logger.info(MESSAGE_JSON, jsonContent, path);
}

@Override
public void addFileContentEntry(String path, File original) {
public void addFileContentEntry(Path path, File original) {
logger.info(MESSAGE_FILE, original.getAbsolutePath(), path);
}

@Override
public void writeStringEntry(String entry, String path) {
public void writeStringEntry(String entry, Path path) {
logger.info(MESSAGE_STRING, entry, path);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.jplag.reporting.reportobject.writer;

import java.io.File;
import java.nio.file.Path;

/**
* Writer for JPlag result data. The way paths are resolved depends on the implementation
Expand All @@ -11,21 +12,21 @@ public interface JPlagResultWriter {
* @param jsonContent The json content
* @param path The path to write to
*/
void addJsonEntry(Object jsonContent, String path);
void addJsonEntry(Object jsonContent, Path path);

/**
* Writes data from a file
* @param path The path to write to
* @param original The original file
*/
void addFileContentEntry(String path, File original);
void addFileContentEntry(Path path, File original);

/**
* Writes data from a string
* @param entry The string to write
* @param path The path to write to
*/
void writeStringEntry(String entry, String path);
void writeStringEntry(String entry, Path path);

/**
* Closes the writer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.reporting.FilePathUtil;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
Expand Down Expand Up @@ -39,9 +42,9 @@ public ZipWriter(File zipFile) throws FileNotFoundException {
}

@Override
public void addJsonEntry(Object jsonContent, String path) {
public void addJsonEntry(Object jsonContent, Path path) {
try {
this.file.putNextEntry(new ZipEntry(path));
this.file.putNextEntry(new ZipEntry(FilePathUtil.pathAsZipPath(path)));
this.file.write(objectMapper.writeValueAsBytes(jsonContent));
this.file.closeEntry();
} catch (IOException e) {
Expand All @@ -50,19 +53,19 @@ public void addJsonEntry(Object jsonContent, String path) {
}

@Override
public void addFileContentEntry(String path, File original) {
public void addFileContentEntry(Path path, File original) {
try (FileInputStream inputStream = new FileInputStream(original)) {
this.file.putNextEntry(new ZipEntry(path));
this.file.putNextEntry(new ZipEntry(FilePathUtil.pathAsZipPath(path)));
inputStream.transferTo(this.file);
} catch (IOException e) {
logger.error(String.format(COPY_FILE_ERROR, original.getAbsolutePath(), path), e);
}
}

@Override
public void writeStringEntry(String entry, String path) {
public void writeStringEntry(String entry, Path path) {
try {
this.file.putNextEntry(new ZipEntry(path));
this.file.putNextEntry(new ZipEntry(FilePathUtil.pathAsZipPath(path)));
this.file.write(entry.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
logger.error(String.format(WRITE_STRING_ERROR, path), e);
Expand Down
26 changes: 0 additions & 26 deletions core/src/test/java/de/jplag/reporting/FilePathUtilTest.java

This file was deleted.