Skip to content
This repository was archived by the owner on Apr 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# windsurf rules
.windsurfrules
java/src/test/resources/
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
"java.configuration.updateBuildConfiguration": "automatic"
}
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: docker-test-perf build up clean compile update
.PHONY: docker-test-perf build up clean compile update test

build:
docker-compose build
Expand All @@ -14,10 +14,13 @@ compile:
docker-compose exec app mvn clean package -f /source/pom.xml

update:
docker-compose exec app mvn clean package -f /source/pom.xml && \
docker-compose exec app mvn clean package -DskipTests -f /source/pom.xml && \
docker-compose exec app cp /source/target/GoofyFiles-0.0.1-SNAPSHOT.jar /app/app.jar && \
docker-compose restart app

# Exécuter les tests de performance
docker-test-perf:
docker-compose exec app mvn test -f /source/pom.xml -Dtest=ChunkingPerformanceTest

test:
docker-compose exec app mvn test -f /source/pom.xml
5 changes: 4 additions & 1 deletion java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
Expand All @@ -44,7 +48,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.goofy.GoofyFiles.controller.api;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.goofy.GoofyFiles.duplication.DuplicationService;
import com.goofy.GoofyFiles.duplication.HashingAlgorithm;

@RestController
@RequestMapping("api/duplication")
public class DuplicationController {

private final DuplicationService duplicationService;

public DuplicationController(DuplicationService duplicationService) {
this.duplicationService = duplicationService;
}

@PostMapping("/analyze")
public ResponseEntity<?> analyzeFile(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "algorithm", defaultValue = "SHA256") HashingAlgorithm algorithm) {
try {
File tempFile = File.createTempFile("upload-", "-" + file.getOriginalFilename());
file.transferTo(tempFile);

Map<String, Object> result = duplicationService.analyzeFile(tempFile, algorithm);

tempFile.delete();
return ResponseEntity.ok(result);
} catch (IOException e) {
return ResponseEntity.internalServerError()
.body(Map.of("error", "Échec du traitement du fichier: " + e.getMessage()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.goofy.GoofyFiles.duplication;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.Blake3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.goofy.GoofyFiles.chunking.Chunk;
import com.goofy.GoofyFiles.chunking.ChunkingService;
import com.google.common.hash.Hashing;

@Service
public class DuplicationService {

private static final Logger logger = LoggerFactory.getLogger(DuplicationService.class);
private final ChunkingService chunkingService;

public DuplicationService(ChunkingService chunkingService) {
this.chunkingService = chunkingService;
}

public Map<String, Object> analyzeFile(File file, HashingAlgorithm algorithm) throws IOException {
List<Chunk> chunks = chunkingService.chunkFile(file);
Map<String, Integer> duplicates = new HashMap<>();

for (Chunk chunk : chunks) {
String hash = calculateHash(chunk.getData(), algorithm);
duplicates.merge(hash, 1, Integer::sum);
logger.debug("Chunk at position {} with size {} bytes has hash: {}",
chunk.getPosition(), chunk.getData().length, hash);
}

// Filtrer les chunks qui apparaissent plus d'une fois (vous pouvez logguer ou utiliser ce résultat)
duplicates.entrySet().stream()
.filter(e -> e.getValue() > 1);

long uniqueChunks = duplicates.size();
long totalChunks = chunks.size();
long duplicatedChunks = duplicates.entrySet().stream()
.filter(e -> e.getValue() > 1)
.count();

return Map.of(
"fileName", file.getName(),
"totalChunks", totalChunks,
"uniqueChunks", uniqueChunks,
"duplicatedChunks", duplicatedChunks,
"algorithm", algorithm.name(),
"duplicateDetails", duplicates.entrySet().stream()
.filter(e -> e.getValue() > 1)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
))
);
}

private String calculateHash(byte[] data, HashingAlgorithm algorithm) {
try {
switch (algorithm) {
case SHA1:
return Hashing.sha1().hashBytes(data).toString();
case SHA256:
return Hashing.sha256().hashBytes(data).toString();
case BLAKE3:
// Utilisation de Apache Commons Codec pour BLAKE3
byte[] hashBytes = Blake3.hash(data);
return Hex.encodeHexString(hashBytes);
default:
throw new IllegalArgumentException("Algorithme de hachage non supporté: " + algorithm);
}
} catch (Exception e) {
throw new RuntimeException("Erreur lors du calcul du hash", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.goofy.GoofyFiles.duplication;

public enum HashingAlgorithm {
SHA1("SHA-1"),
SHA256("SHA-256"),
BLAKE3("BLAKE3");

private final String algorithmName;

HashingAlgorithm(String algorithmName) {
this.algorithmName = algorithmName;
}

public String getAlgorithmName() {
return algorithmName;
}
}
Loading