Skip to content

Commit

Permalink
Merge branch 'develop-iris' into iris/replace-client-deps
Browse files Browse the repository at this point in the history
  • Loading branch information
bassner authored Sep 13, 2023
2 parents 2f5a008 + 7cebe8e commit ed43475
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 78 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ jobs:
if: ${{ github.event_name == 'release' }}
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
# Build and Push to GitHub Container Registry
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ plugins {
}

group = "de.tum.in.www1.artemis"
version = "6.4.3"
version = "6.5.0"
description = "Interactive Learning with Individual Feedback"

sourceCompatibility=17
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "artemis",
"version": "6.4.3",
"version": "6.5.0",
"description": "Interactive Learning with Individual Feedback",
"private": true,
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;

import de.tum.in.www1.artemis.service.connectors.vcs.AbstractVersionControlService;
import tech.jhipster.config.JHipsterConstants;

/**
Expand Down Expand Up @@ -53,10 +54,14 @@ public void applicationPackagePointcut() {
*/
@AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
if (AbstractVersionControlService.isReadFullyShortReadOfBlockException(e)) {
// ignore
return;
}

if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) {
log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e);

}
else {
log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
Expand Down Expand Up @@ -86,7 +91,6 @@ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
}
catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());

throw e;
}
}
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/de/tum/in/www1/artemis/domain/UserGroup.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.tum.in.www1.artemis.domain;

import java.io.Serializable;
import java.util.Objects;

import javax.persistence.*;

Expand All @@ -18,12 +19,36 @@ public class UserGroup {
private String group;

@Embeddable
public class UserGroupKey implements Serializable {
public static class UserGroupKey implements Serializable {

@Column(name = "user_id")
private Long userId;

@Column(name = "`groups`")
private String group;

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

UserGroupKey that = (UserGroupKey) o;

if (!Objects.equals(userId, that.userId)) {
return false;
}
return Objects.equals(group, that.group);
}

@Override
public int hashCode() {
int result = userId != null ? userId.hashCode() : 0;
result = 31 * result + (group != null ? group.hashCode() : 0);
return result;
}
}
}
106 changes: 66 additions & 40 deletions src/main/java/de/tum/in/www1/artemis/service/FileService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package de.tum.in.www1.artemis.service;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand Down Expand Up @@ -59,6 +59,13 @@ public class FileService implements DisposableBean {

private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());

/**
* A list of common binary file extensions.
* Extensions must be lower-case without leading dots.
*/
private static final Set<String> binaryFileExtensions = Set.of("png", "jpg", "jpeg", "heic", "gif", "tiff", "psd", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "pages",
"numbers", "key", "odt", "zip", "rar", "7z", "tar", "iso", "mdb", "sqlite", "exe", "jar");

/**
* The list of file extensions that are allowed to be uploaded in a Markdown editor.
* Extensions must be lower-case without leading dots.
Expand Down Expand Up @@ -631,7 +638,7 @@ private Path getTargetPath(final Resource resource, final Path prefix, final Pat
filePath = resource.getFile().toPath();
}
else {
final String url = URLDecoder.decode(resource.getURL().toString(), StandardCharsets.UTF_8);
final String url = URLDecoder.decode(resource.getURL().toString(), UTF_8);
filePath = Path.of(url);
}

Expand Down Expand Up @@ -738,7 +745,7 @@ public void replacePlaceholderSections(String filePath, Map<String, Boolean> sec
throw new FilePathParsingException("File " + filePath + " should be updated but does not exist.");
}

try (var reader = new BufferedReader(new FileReader(file, StandardCharsets.UTF_8)); var writer = new BufferedWriter(new FileWriter(tempFile, StandardCharsets.UTF_8))) {
try (var reader = new BufferedReader(new FileReader(file, UTF_8)); var writer = new BufferedWriter(new FileWriter(tempFile, UTF_8))) {
Map.Entry<Pattern, Boolean> matchingStartPattern = null;
String line = reader.readLine();
while (line != null) {
Expand Down Expand Up @@ -856,29 +863,27 @@ public void replaceVariablesInFileName(String startPath, String targetString, St
/**
* This replaces all occurrences of the target Strings with the replacement Strings in the given file and saves the file
* <p>
* {@link #replaceVariablesInFile(String, Map) replaceVariablesInFile}
* {@link #replaceVariablesInFile(Path, Map) replaceVariablesInFile}
*
* @param startPath the path where the start directory is located
* @param replacements the replacements that should be applied
* @throws IOException if an issue occurs on file access for the replacement of the variables.
*/
public void replaceVariablesInFileRecursive(String startPath, Map<String, String> replacements) throws IOException {
public void replaceVariablesInFileRecursive(Path startPath, Map<String, String> replacements) {
replaceVariablesInFileRecursive(startPath, replacements, Collections.emptyList());
}

/**
* This replaces all occurrences of the target Strings with the replacement Strings in the given file and saves the file
* <p>
* {@link #replaceVariablesInFile(String, Map) replaceVariablesInFile}
* {@link #replaceVariablesInFile(Path, Map) replaceVariablesInFile}
*
* @param startPath the path where the start directory is located
* @param replacements the replacements that should be applied
* @param filesToIgnore the name of files for which no replacement should be done
* @throws IOException if an issue occurs on file access for the replacement of the variables.
*/
public void replaceVariablesInFileRecursive(String startPath, Map<String, String> replacements, List<String> filesToIgnore) throws IOException {
public void replaceVariablesInFileRecursive(Path startPath, Map<String, String> replacements, List<String> filesToIgnore) {
log.debug("Replacing {} in files in directory {}", replacements, startPath);
File directory = new File(startPath);
File directory = startPath.toFile();
if (!directory.exists() || !directory.isDirectory()) {
throw new RuntimeException("Files in directory " + startPath + " should be replaced but the directory does not exist.");
}
Expand All @@ -889,7 +894,7 @@ public void replaceVariablesInFileRecursive(String startPath, Map<String, String
// filter out files that should be ignored
files = Arrays.stream(files).filter(Predicate.not(filesToIgnore::contains)).toArray(String[]::new);
for (String file : files) {
replaceVariablesInFile(Path.of(directory.getAbsolutePath(), file).toString(), replacements);
replaceVariablesInFile(Path.of(directory.getAbsolutePath(), file), replacements);
}
}

Expand All @@ -901,7 +906,7 @@ public void replaceVariablesInFileRecursive(String startPath, Map<String, String
// ignore files in the '.git' folder
continue;
}
replaceVariablesInFileRecursive(Path.of(directory.getAbsolutePath(), subDirectory).toString(), replacements, filesToIgnore);
replaceVariablesInFileRecursive(Path.of(directory.getAbsolutePath(), subDirectory), replacements, filesToIgnore);
}
}
}
Expand All @@ -912,32 +917,53 @@ public void replaceVariablesInFileRecursive(String startPath, Map<String, String
*
* @param filePath the path where the file is located
* @param replacements the replacements that should be applied
* @throws IOException if an issue occurs on file access for the replacement of the variables.
*/
public void replaceVariablesInFile(String filePath, Map<String, String> replacements) throws IOException {
public void replaceVariablesInFile(Path filePath, Map<String, String> replacements) {
log.debug("Replacing {} in file {}", replacements, filePath);
// https://stackoverflow.com/questions/3935791/find-and-replace-words-lines-in-a-file
Path replaceFilePath = Path.of(filePath);
Charset charset = StandardCharsets.UTF_8;

String fileContent = Files.readString(replaceFilePath, charset);
for (Map.Entry<String, String> replacement : replacements.entrySet()) {
fileContent = fileContent.replace(replacement.getKey(), replacement.getValue());
if (isBinaryFile(filePath)) {
// do not try to read binary files with 'readString'
return;
}
try {
// Note: Java does not offer a good way to check if a file is binary or not. If the basic check above fails (e.g. due to a custom binary file from an instructor),
// but the file is still binary, we try to read it. In case the method readString fails, we only log this below, but continue, because the exception should NOT
// interrupt the ongoing process
String fileContent = Files.readString(filePath, UTF_8);
for (Map.Entry<String, String> replacement : replacements.entrySet()) {
fileContent = fileContent.replace(replacement.getKey(), replacement.getValue());
}
Files.writeString(filePath, fileContent, UTF_8);
}
Files.writeString(replaceFilePath, fileContent, charset);
catch (IOException ex) {
log.warn("Exception {} occurred when trying to replace {} in (binary) file {}", ex.getMessage(), replacements, filePath);
// continue
}
}

/**
* very simple and non-exhaustive check for the most common binary files such as images
* Unfortunately, Java cannot determine this correctly, so we need to provide typical file endings here
*
* @param filePath the path of the file
* @return whether the simple check for file endings determines the underlying file to be binary (true) or not (false)
*/
private static boolean isBinaryFile(Path filePath) {
final String fileExtension = FilenameUtils.getExtension(filePath.getFileName().toString());
return binaryFileExtensions.stream().anyMatch(fileExtension::equalsIgnoreCase);
}

/**
* This normalizes all line endings to UNIX-line-endings recursively from the startPath.
* <p>
* {@link #normalizeLineEndings(String) normalizeLineEndings}
* {@link #normalizeLineEndings(Path) normalizeLineEndings}
*
* @param startPath the path where the start directory is located
* @throws IOException if an issue occurs on file access for the normalizing of the line endings.
*/
public void normalizeLineEndingsDirectory(String startPath) throws IOException {
public void normalizeLineEndingsDirectory(Path startPath) throws IOException {
log.debug("Normalizing file endings in directory {}", startPath);
File directory = new File(startPath);
File directory = startPath.toFile();
if (!directory.exists() || !directory.isDirectory()) {
throw new RuntimeException("File endings in directory " + startPath + " should be normalized but the directory does not exist.");
}
Expand All @@ -948,7 +974,7 @@ public void normalizeLineEndingsDirectory(String startPath) throws IOException {
Collection<File> files = FileUtils.listFiles(directory, FileFilterUtils.trueFileFilter(), directoryFileFilter);

for (File file : files) {
normalizeLineEndings(file.getAbsolutePath());
normalizeLineEndings(file.toPath());
}
}

Expand All @@ -960,28 +986,29 @@ public void normalizeLineEndingsDirectory(String startPath) throws IOException {
* @param filePath the path where the file is located
* @throws IOException if an issue occurs on file access for the normalizing of the line endings.
*/
public void normalizeLineEndings(String filePath) throws IOException {
public void normalizeLineEndings(Path filePath) throws IOException {
log.debug("Normalizing line endings in file {}", filePath);
if (isBinaryFile(filePath)) {
// do not try to read binary files with 'readString'
return;
}
// https://stackoverflow.com/questions/3776923/how-can-i-normalize-the-eol-character-in-java
Path replaceFilePath = Path.of(filePath);
Charset charset = StandardCharsets.UTF_8;

String fileContent = Files.readString(replaceFilePath, charset);
String fileContent = Files.readString(filePath, UTF_8);
fileContent = fileContent.replaceAll("\\r\\n?", "\n");
Files.writeString(replaceFilePath, fileContent, charset);
Files.writeString(filePath, fileContent, UTF_8);
}

/**
* This converts all files to the UTF-8 encoding recursively from the startPath.
* <p>
* {@link #convertToUTF8(String) convertToUTF8}
* {@link #convertToUTF8(Path) convertToUTF8}
*
* @param startPath the path where the start directory is located
* @throws IOException if an issue occurs on file access when converting to UTF-8.
*/
public void convertToUTF8Directory(String startPath) throws IOException {
public void convertToUTF8Directory(Path startPath) throws IOException {
log.debug("Converting files in directory {} to UTF-8", startPath);
File directory = new File(startPath);
File directory = startPath.toFile();
if (!directory.exists() || !directory.isDirectory()) {
throw new RuntimeException("Files in directory " + startPath + " should be converted to UTF-8 but the directory does not exist.");
}
Expand All @@ -992,7 +1019,7 @@ public void convertToUTF8Directory(String startPath) throws IOException {
Collection<File> files = FileUtils.listFiles(directory, FileFilterUtils.trueFileFilter(), directoryFileFilter);

for (File file : files) {
convertToUTF8(file.getAbsolutePath());
convertToUTF8(file.toPath());
}
}

Expand All @@ -1003,17 +1030,16 @@ public void convertToUTF8Directory(String startPath) throws IOException {
* @param filePath the path where the file is located
* @throws IOException if an issue occurs on file access when converting to UTF-8.
*/
public void convertToUTF8(String filePath) throws IOException {
public void convertToUTF8(Path filePath) throws IOException {
log.debug("Converting file {} to UTF-8", filePath);
Path replaceFilePath = Path.of(filePath);
byte[] contentArray = Files.readAllBytes(replaceFilePath);
byte[] contentArray = Files.readAllBytes(filePath);

Charset charset = detectCharset(contentArray);
log.debug("Detected charset for file {} is {}", filePath, charset.name());

String fileContent = new String(contentArray, charset);

Files.writeString(replaceFilePath, fileContent, StandardCharsets.UTF_8);
Files.writeString(filePath, fileContent, UTF_8);
}

/**
Expand Down Expand Up @@ -1132,7 +1158,7 @@ public void createDirectory(Path path) {
* @return Path to the written file
*/
public Path writeStringToFile(String stringToWrite, Path path) {
try (var outStream = new OutputStreamWriter(new FileOutputStream(path.toString()), StandardCharsets.UTF_8)) {
try (var outStream = new OutputStreamWriter(new FileOutputStream(path.toString()), UTF_8)) {
outStream.write(stringToWrite);
}
catch (IOException e) {
Expand Down
Loading

0 comments on commit ed43475

Please sign in to comment.