package org.alien4cloud.tosca.catalog.repository;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.alien4cloud.tosca.editor.EditionContextManager;
import org.alien4cloud.tosca.model.Csar;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.FileSystemUtils;
import alien4cloud.component.repository.exception.CSARDirectoryCreationFailureException;
import alien4cloud.component.repository.exception.CSARStorageFailureException;
import alien4cloud.exception.NotFoundException;
import alien4cloud.utils.DirectoryJSonWalker;
import alien4cloud.utils.FileUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
/**
* CSAR Repository implementation<br/>
*
* Implements {@link ICsarRepositry}
*
* @author 'Igor Ngouagna'
*/
@Slf4j
@Getter
@Setter
@Component
public class CsarFileRepository implements ICsarRepositry {
public static final String CSAR_EXTENSION = "csar";
private static final String EXPANDED = "expanded";
private Path rootPath;
@Required
@Value("${directories.alien}/${directories.csar_repository}")
public void setRootPath(String path) {
this.rootPath = Paths.get(path).toAbsolutePath();
if (!Files.isDirectory(rootPath)) {
try {
Files.createDirectories(rootPath);
log.info("Alien Repository folder set to " + rootPath.toAbsolutePath());
} catch (IOException e) {
throw new CSARDirectoryCreationFailureException(
"Error while trying to create the CSAR repository <" + rootPath.toString() + ">. " + e.getMessage(), e);
}
} else {
log.info("Alien Repository folder already created! " + rootPath.toAbsolutePath());
}
}
@Override
public synchronized void storeCSAR(Csar csar, String yaml) {
Path csarDirectoryPath = rootPath.resolve(csar.getName()).resolve(csar.getVersion());
String realName = csar.getName().concat("-").concat(csar.getVersion()).concat("." + CSAR_EXTENSION);
createCSARDirectory(csarDirectoryPath, realName);
Path csarExpandedDirectoryPath = csarDirectoryPath.resolve(EXPANDED);
try {
Files.createDirectories(csarExpandedDirectoryPath);
Path targetPath = csarExpandedDirectoryPath.resolve(csar.getYamlFilePath());
try (BufferedWriter writer = Files.newBufferedWriter(targetPath)) {
writer.write(yaml);
}
} catch (IOException e) {
throw new CSARDirectoryCreationFailureException(
"Error while trying to create the CSAR directory <" + csarDirectoryPath.toString() + ">. " + e.getMessage(), e);
}
}
@Override
public synchronized void storeCSAR(Csar csar, Path tmpPath) {
// check the tmpPath.
if (!Files.isReadable(tmpPath)) {
throw new CSARStorageFailureException("CSAR temp location <" + tmpPath.toString() + "> not found or not readable!");
}
Path csarDirectoryPath = rootPath.resolve(csar.getName()).resolve(csar.getVersion());
String realName = csar.getName().concat("-").concat(csar.getVersion()).concat("." + CSAR_EXTENSION);
// create the storage directory
createCSARDirectory(csarDirectoryPath, realName);
// move the archive
try {
if (log.isDebugEnabled()) {
log.debug("tmp: " + tmpPath);
log.debug(" Dest: " + csarDirectoryPath.resolve(realName));
}
Path csarTargetPath = csarDirectoryPath.resolve(realName);
Path expandedPath = csarDirectoryPath.resolve("expanded");
if (Files.isRegularFile(tmpPath)) {
Files.copy(tmpPath, csarTargetPath);
FileUtil.unzip(csarTargetPath, expandedPath);
} else {
FileUtil.copy(tmpPath, expandedPath, StandardCopyOption.REPLACE_EXISTING);
}
DirectoryJSonWalker.directoryJson(expandedPath, csarDirectoryPath.resolve("content.json"));
} catch (IOException e) {
throw new CSARStorageFailureException(
"Error while trying to store the CSAR: " + csar.getName() + ", Version: " + csar.getVersion() + "...." + e.getMessage(), e);
}
}
@Override
public synchronized void updateFromExpanded(String name, String version) {
Path csarDirectoryPath = rootPath.resolve(name).resolve(version);
Path expandedPath = csarDirectoryPath.resolve("expanded");
String realName = name.concat("-").concat(version).concat("." + CSAR_EXTENSION);
Path csarTargetPath = csarDirectoryPath.resolve(realName);
// Update the content.json file for archive browsing.
Path archiveDirectoryPath = EditionContextManager.get().getLocalGitPath().getParent();
try {
DirectoryJSonWalker.directoryJson(expandedPath, csarDirectoryPath.resolve("content.json"));
FileUtil.zip(expandedPath, csarTargetPath);
EditionContextManager.get().refreshContentTree();
} catch (IOException e) {
throw new CSARStorageFailureException("Error while trying to update the CSAR archive: " + name + ", Version: " + version + "...." + e.getMessage(),
e);
}
}
private void createCSARDirectory(Path csarDirectoryPath, String realName) {
if (Files.exists(csarDirectoryPath.resolve(realName))) {
log.info("Overriding CSAR with new one.");
try {
FileUtil.delete(csarDirectoryPath);
} catch (IOException e) {
throw new CSARDirectoryCreationFailureException(
"Error while trying to delete the CSAR directory <" + csarDirectoryPath.toString() + ">. " + e.getMessage(), e);
}
}
try {
Files.createDirectories(csarDirectoryPath);
} catch (IOException e) {
throw new CSARDirectoryCreationFailureException(
"Error while trying to create the CSAR directory <" + csarDirectoryPath.toString() + ">. " + e.getMessage(), e);
}
}
@Override
public Path getCSAR(String name, String version) {
Path csarDir = rootPath.resolve(name).resolve(version);
Path expandedPath = csarDir.resolve("expanded");
Path zippedPath = csarDir.resolve(name.concat("-").concat(version).concat("." + CSAR_EXTENSION));
if (Files.exists(zippedPath)) {
return zippedPath;
} else if (Files.exists(expandedPath)) {
// the csar wasn't stored as a zip file. Zip the expanded dir then
try {
FileUtil.zip(expandedPath, zippedPath);
return zippedPath;
} catch (IOException e) {
log.error("Failed to zip directory " + expandedPath, e);
throw new NotFoundException("CSAR: " + name + ", Version: " + version + " not found in the repository.");
}
}
throw new NotFoundException("CSAR: " + name + ", Version: " + version + " not found in the repository.");
}
@Override
public Path getExpandedCSAR(String name, String version) {
Path csarDir = rootPath.resolve(name).resolve(version);
Path expandedPath = csarDir.resolve("expanded");
if (Files.exists(expandedPath)) {
return expandedPath;
}
throw new NotFoundException("CSAR: " + name + ", Version: " + version + " not found in the repository.");
}
@Override
public void removeCSAR(String name, String version) {
Path csarDirectoryPathOfVersion = rootPath.resolve(name).resolve(version);
if (Files.isDirectory(csarDirectoryPathOfVersion)) {
FileSystemUtils.deleteRecursively(csarDirectoryPathOfVersion.toFile());
}
// If the csar has no version, delete csar folder
File csarRootFolder = new File(rootPath.resolve(name).toUri());
if (csarRootFolder.isDirectory() && csarRootFolder.list().length == 0) {
FileSystemUtils.deleteRecursively(csarRootFolder);
}
}
}