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); } } }