package it.digione.dg1cloud.service;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.FileNotFoundException;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.net.URL;
|
import java.nio.charset.StandardCharsets;
|
import java.security.NoSuchAlgorithmException;
|
import java.time.LocalDate;
|
import java.time.ZoneId;
|
|
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FilenameUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import com.fasterxml.jackson.core.JsonParseException;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
import it.digione.dg1cloud.config.AppConfig;
|
import it.digione.dg1cloud.model.RegDocument;
|
import it.digione.dg1cloud.pojo.UploadedFileDescriptor;
|
import it.digione.dg1cloud.pojo.UploadedFileDescriptorOk;
|
import it.digione.dg1cloud.repository.RegDocumentRepository;
|
|
@Service("cloudService")
|
public class CloudService {
|
|
private static final Logger logger = LoggerFactory.getLogger(CloudService.class);
|
|
@Autowired private AppConfig appConfig;
|
@Autowired private Utils utils;
|
@Autowired private RegDocumentRepository regDocumentRepository;
|
|
public void scannAccountHomeDirs() throws JsonParseException, JsonMappingException, NoSuchAlgorithmException, IOException {
|
|
String repositoryPath = appConfig.getRepositoryBaseUploadPath();
|
File basePath = new File(repositoryPath);
|
|
if ( basePath.exists() == false || basePath.isDirectory() == false )
|
throw new RuntimeException("La directory '" + basePath.getAbsolutePath() + "' non esiste oppure non e' una directory");
|
|
for ( File folder : basePath.listFiles(File::isDirectory)) {
|
for ( File descriptor : folder.listFiles(
|
(dir, name) -> {
|
return name.toLowerCase().endsWith(".dg1cloud");
|
}))
|
{
|
boolean checkFile = false;
|
try {
|
checkFile = checkFile(descriptor.getAbsolutePath());
|
} catch (Exception e ) {
|
logger.error("Errore durante la fase di verifica del file", e);
|
writeKoFile(descriptor.getAbsolutePath(), "Errore durante la fase di verifica del file\n" + e.getMessage());
|
continue;
|
}
|
|
if ( checkFile == true ) {
|
logger.debug("Controllo file descrittore completato con successo");
|
try {
|
storeFile(descriptor.getAbsolutePath());
|
} catch (Exception e) {
|
writeKoFile(descriptor.getAbsolutePath(), "Errore duranto la memorizzazione del file nello store\n" + e.getMessage());
|
}
|
} else {
|
logger.debug("Il file non ha passato le verifiche");
|
}
|
}
|
}
|
}
|
|
public boolean checkFile(String cloudFileDescriptorPath) throws IOException, NoSuchAlgorithmException {
|
logger.debug("Controllo il file {}", cloudFileDescriptorPath);
|
|
TypeReference<UploadedFileDescriptor> typeReference = new TypeReference<UploadedFileDescriptor>() {};
|
File cloudFileDescriptor = new File(cloudFileDescriptorPath);
|
|
String koMessage = null;
|
|
if ( cloudFileDescriptor.exists() == false ) {
|
koMessage = "Il file descrittore inviato '" + cloudFileDescriptor + "' non esiste";
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
if ( cloudFileDescriptor.isFile() == false ) {
|
koMessage = "Il file descrittore inviato '" + cloudFileDescriptor + "' non e' di tipo file";
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
InputStream is = new FileInputStream(cloudFileDescriptor);
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
UploadedFileDescriptor uploadedFileDescriptor;
|
try {
|
uploadedFileDescriptor = mapper.readValue(is, typeReference);
|
} catch (IOException e) {
|
koMessage = "Il file descrittore non conforme:\n" + e.getMessage();
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
is.close();
|
|
File uploadedFile = new File(cloudFileDescriptor.getParentFile(), uploadedFileDescriptor.getFileName());
|
if ( uploadedFile.exists() == false ) {
|
koMessage = "Il file inviato '" + uploadedFile + "' non esiste";
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
if ( uploadedFile.isFile() == false ) {
|
koMessage = "Il file inviato '" + uploadedFile + "' non e' di tipo file";
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
FileInputStream fis = new FileInputStream(uploadedFile);
|
String hash = DigestUtils.sha256Hex(fis);
|
fis.close();
|
|
if ( hash.equalsIgnoreCase(uploadedFileDescriptor.getSha256()) == false ) {
|
koMessage = "L'hash del file inviato non corrisponde con l'hash dichiarato nel descrittore del file:\n\t" +
|
"hash file inviato: " + hash + "\n\t" +
|
"hash dichiarato nel descrittore: " + uploadedFileDescriptor.getSha256();
|
writeKoFile(cloudFileDescriptorPath, koMessage);
|
return false;
|
}
|
|
return true;
|
}
|
|
public void storeFile(String cloudFileDescriptorPath) {
|
logger.debug("Avvio processo di memorizzazione file nello store");
|
TypeReference<UploadedFileDescriptor> typeReference = new TypeReference<UploadedFileDescriptor>() {};
|
File cloudFileDescriptor = new File(cloudFileDescriptorPath);
|
|
InputStream is;
|
try {
|
is = new FileInputStream(cloudFileDescriptor);
|
} catch (FileNotFoundException e) {
|
throw new RuntimeException("Errore apertura stream file descrittore", e);
|
}
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
UploadedFileDescriptor uploadedFileDescriptor;
|
try {
|
uploadedFileDescriptor = mapper.readValue(is, typeReference);
|
} catch (IOException e) {
|
throw new RuntimeException("Errore caricamento classe dal json del descrittore", e);
|
}
|
|
logger.debug("Controllo esistenza file sul db");
|
RegDocument regDocument = regDocumentRepository.findOneByHashAndName(uploadedFileDescriptor.getSha256(), uploadedFileDescriptor.getFileName());
|
|
String userName = cloudFileDescriptor.getParentFile().getName();
|
|
File uploadedFile = new File(getUploadedFilePath(cloudFileDescriptorPath));
|
|
if ( regDocument == null ) {
|
|
logger.debug("Creazione nuovo record per il documento da conservare");
|
regDocument = new RegDocument();
|
regDocument.setCreatedBy(userName);
|
regDocument.setModifiedBy(userName);
|
regDocument.setFileHash(uploadedFileDescriptor.getSha256());
|
regDocument.setFileName(uploadedFileDescriptor.getFileName());
|
regDocument.setFileSize(uploadedFile.length());
|
regDocument.setDueDate(uploadedFileDescriptor.getDueDate());
|
regDocument.setFilePath("");
|
regDocument.setSecretKey(uploadedFileDescriptor.getSecretKey());
|
|
regDocumentRepository.save(regDocument);
|
|
} else {
|
logger.debug("Trovato 1 record per il documento da memorizzare");
|
}
|
|
try {
|
moveUploadedFileToStorage(uploadedFile.getAbsolutePath(), regDocument);
|
} catch (Exception e) {
|
try {
|
writeKoFile(cloudFileDescriptorPath, e.getMessage());
|
} finally {
|
logger.debug("Rimozione regDocument");
|
regDocumentRepository.delete(regDocument);
|
}
|
}
|
try {
|
createOkFile(cloudFileDescriptorPath, regDocument);
|
} catch (Exception e) {
|
try {
|
writeKoFile(cloudFileDescriptorPath, e.getMessage());
|
} finally {
|
logger.debug("Rimozione regDocument");
|
regDocumentRepository.delete(regDocument);
|
}
|
}
|
}
|
|
private void moveUploadedFileToStorage( String source, RegDocument regDocument ) throws IOException {
|
logger.debug("Spostamento file nello storage");
|
|
String sha256Descriptor = regDocument.getFileHash();
|
|
File sourceFile = new File(source);
|
File destinationFile = new File(generateStoragePath(regDocument));
|
|
if ( destinationFile.exists() == false ) {
|
logger.debug("Creazione alberatura directory: " + destinationFile.getParent());
|
FileUtils.forceMkdirParent(destinationFile);
|
FileUtils.copyFile(sourceFile, destinationFile);
|
} else {
|
logger.debug("Il file risulta gia' presente nello storage. Verifico l'integrita'");
|
FileInputStream fis = new FileInputStream(destinationFile);
|
String hash = DigestUtils.sha256Hex(fis);
|
fis.close();
|
if ( sha256Descriptor.equalsIgnoreCase(hash) == false ) {
|
throw new IllegalStateException("L'hash del file nello storage non corrisponde con l'hash dichiarato nel descrittore del file:\n\t" +
|
"hash file inviato: " + hash + "\n\t" +
|
"hash dichiarato nel descrittore: " + sha256Descriptor);
|
}
|
}
|
|
regDocument.setFilePath(destinationFile.getAbsolutePath());
|
logger.debug("Salvo il path nel regDocument: {}", regDocument.getFilePath());
|
regDocumentRepository.save(regDocument);
|
}
|
|
private void createOkFile( String cloudFileDescriptorPath, RegDocument regDocument ) throws IOException {
|
logger.debug("Creazione file di OK");
|
|
File fileDescriptor = new File(cloudFileDescriptorPath);
|
File okFile = new File(fileDescriptor.getParentFile(), fileDescriptor.getName() + ".ok");
|
|
ObjectMapper mapper = new ObjectMapper();
|
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
|
UploadedFileDescriptorOk uploadedFileDescriptorOk = new UploadedFileDescriptorOk();
|
|
uploadedFileDescriptorOk.setFileName(regDocument.getFileName());
|
|
URL url = utils.generateUrl(regDocument);
|
|
uploadedFileDescriptorOk.setUrl(url.toExternalForm());
|
|
try {
|
String json = mapper.writeValueAsString(uploadedFileDescriptorOk);
|
logger.debug("Scrittura json di ok:\n{}", json);
|
FileUtils.writeStringToFile(okFile, json, StandardCharsets.UTF_8);
|
} catch (IOException e) {
|
throw new RuntimeException("Errore nella scrittura del file di OK", e);
|
}
|
|
File cloudFile = new File( getUploadedFilePath(cloudFileDescriptorPath) );
|
if (cloudFile.exists() == true )
|
FileUtils.deleteQuietly(cloudFile);
|
|
try {
|
FileUtils.forceDelete(fileDescriptor);
|
} catch (IOException e) {
|
throw new RuntimeException("Errore rimozione del file descrittore", e);
|
}
|
}
|
|
public void writeKoFile( String cloudFileDescriptorPath, String errorMessage ) {
|
logger.debug("Si e' verificato il seguente errore nella verifica tramite {}: {}", cloudFileDescriptorPath, errorMessage);
|
|
File fileDescriptor = new File(cloudFileDescriptorPath);
|
File koFile = new File(fileDescriptor.getParentFile(), fileDescriptor.getName() + ".ko");
|
|
try {
|
FileUtils.writeStringToFile(koFile, errorMessage, StandardCharsets.UTF_8);
|
} catch (IOException e) {
|
throw new RuntimeException("Errore nella scrittura del file di KO", e);
|
}
|
|
File cloudFile = new File( getUploadedFilePath(cloudFileDescriptorPath) );
|
if (cloudFile.exists() == true )
|
FileUtils.deleteQuietly(cloudFile);
|
|
try {
|
FileUtils.forceDelete(fileDescriptor);
|
} catch (IOException e) {
|
throw new RuntimeException("Errore rimozione del file descrittore", e);
|
}
|
}
|
|
public String getUploadedFilePath( String cloudFileDescriptorPath ) {
|
File fileDescriptor = new File(cloudFileDescriptorPath);
|
return fileDescriptor.getParentFile().getAbsolutePath() + File.separator + FilenameUtils.getBaseName(fileDescriptor.getName());
|
}
|
|
private String generateStoragePath( RegDocument regDocument ) {
|
|
if ( regDocument.getCreated() == null )
|
throw new IllegalStateException("La data di creazione del RegDocument non e' valorizzata");
|
|
LocalDate localDate = regDocument.getCreated().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
int year = localDate.getYear();
|
int month = localDate.getMonthValue();
|
int day = localDate.getDayOfMonth();
|
|
StringBuffer sb = new StringBuffer();
|
sb.append(appConfig.getRepositoryBaseStoragePath());
|
sb.append(File.separator);
|
sb.append(regDocument.getCreatedBy());
|
sb.append(File.separator);
|
sb.append(year);
|
sb.append(File.separator);
|
sb.append(month);
|
sb.append(File.separator);
|
sb.append(day);
|
sb.append(File.separator);
|
sb.append(regDocument.getDocumentId());
|
sb.append(File.separator);
|
sb.append(regDocument.getFileName());
|
|
return sb.toString();
|
}
|
}
|