Java tutorial
/* * Data Hub Service (DHuS) - For Space data distribution. * Copyright (C) 2013,2014,2015 GAEL Systems * * This file is part of DHuS software sources. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package fr.gael.dhus.datastore; import fr.gael.dhus.database.object.Product; import fr.gael.dhus.datastore.exception.DataStoreException; import fr.gael.dhus.system.config.ConfigurationManager; import fr.gael.dhus.util.UnZip; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * Manages binaries of Product on the local file system. */ @Component public class FileSystemDataStore implements DataStore<Product> { private static final Logger LOGGER = LogManager.getLogger(FileSystemDataStore.class); private final int BUFFER_SIZE = 1024; @Autowired private ConfigurationManager cfgManager; @Autowired private IncomingManager incomingManager; // Getters & Setters public ConfigurationManager getCfgManager() { return cfgManager; } public void setCfgManager(ConfigurationManager cfgManager) { this.cfgManager = cfgManager; } public IncomingManager getIncomingManager() { return incomingManager; } public void setIncomingManager(IncomingManager incomingManager) { this.incomingManager = incomingManager; } @Override public void add(Product product) { throw new UnsupportedOperationException("No supported yet !"); } @Override public void remove(Product product, Destination destination) { if (product == null) { throw new DataStoreException("Cannot remove a null product"); } if (product.getLocked()) { throw new DataStoreException("Cannot remove product: " + product + ", it is locked by the system"); } if (!isRemovable(product)) { LOGGER.warn("Cannot delete product :" + product); } switch (destination) { case TRASH: moveProduct(product, cfgManager.getArchiveConfiguration().getEvictionConfiguration().getTrashPath()); break; case ERROR: moveProduct(product, cfgManager.getArchiveConfiguration().getIncomingConfiguration().getErrorPath()); break; case NONE: break; default: LOGGER.warn("Unknown destination the product will be deleted"); } removeFiles(product); } /** * Deletes all binaries of the given product. * * @param product product to delete */ private void removeFiles(Product product) { try { // Delete product file from path String prodPath = product.getPath().toString(); if (!prodPath.equals(product.getOrigin())) { prodPath = prodPath.replaceAll("file://?", "/"); deleteIncomingFolder(prodPath); } // Delete product file from download path deleteIncomingFolder(product.getDownloadablePath()); // Delete product thumbnail if (product.getThumbnailFlag()) { deleteIncomingFolder(product.getThumbnailPath()); } // Delete product quick-look if (product.getQuicklookFlag()) { deleteIncomingFolder(product.getQuicklookPath()); } } catch (Exception e) { LOGGER.error("There was an error while removing processed files for" + " product '" + product.getIdentifier() + "'", e); } } /** * Delete a file or a directory via it path. * * @param path path of file to delete. * @throws IOException in case deletion is unsuccessful. */ private void deleteIncomingFolder(String path) throws IOException { if (path == null) { return; } File container = new File(path); if (!container.exists() || !incomingManager.isInIncoming(container)) { return; } if (IncomingManager.INCOMING_PRODUCT_DIR.equals(container.getParentFile().getName())) { container = container.getParentFile(); } if (HierarchicalDirectoryBuilder.DHUS_ENTRY_NAME.equals(container.getParentFile().getName())) { container = container.getParentFile(); } if (container != null) { FileUtils.forceDelete(container); } } /** * Returns true if binaries of product are in the file system storage defined * in configuration. * * @param product product to check for deletion. * @return true if product is present in file system storage. */ private boolean isRemovable(Product product) { String a_path = cfgManager.getArchiveConfiguration().getIncomingConfiguration().getPath(); if (a_path.startsWith("file:/")) { a_path = a_path.substring(6); } File a_file = new File(a_path); if (a_file.exists() && a_file.isDirectory()) { a_path = a_file.getAbsolutePath(); String p_file = product.getPath().getPath(); return p_file.startsWith(a_path) && !product.getLocked(); } return false; } /** * Moves product download zip into the given destination. * <p><b>Note:</b> generates the zip of product if necessary.</p> * * @param product product to move. * @param destination destination of product */ private void moveProduct(Product product, String destination) { if (destination == null || destination.trim().isEmpty()) { return; } Path zip_destination = Paths.get(destination); String download_path = product.getDownloadablePath(); try { if (download_path != null) { File product_zip_file = Paths.get(download_path).toFile(); FileUtils.moveFileToDirectory(product_zip_file, zip_destination.toFile(), true); } else { Path product_path = Paths.get(product.getPath().getPath()); if (UnZip.supported(product_path.toAbsolutePath().toString())) { FileUtils.moveFileToDirectory(product_path.toFile(), zip_destination.toFile(), true); } else { zip_destination.resolve(product_path.getFileName()); generateZip(product_path.toFile(), zip_destination.toFile()); } } } catch (IOException e) { LOGGER.error("Cannot move product: " + product.getPath() + " into " + destination, e); } } /** * Generates a zip file. * * @param source source file or directory to compress. * @param destination destination of zipped file. * @return the zipped file. */ private void generateZip(File source, File destination) throws IOException { if (source == null || !source.exists()) { throw new IllegalArgumentException("source file should exist"); } if (destination == null) { throw new IllegalArgumentException("destination file should be not null"); } FileOutputStream output = new FileOutputStream(destination); ZipOutputStream zip_out = new ZipOutputStream(output); zip_out.setLevel(cfgManager.getDownloadConfiguration().getCompressionLevel()); List<QualifiedFile> file_list = getFileList(source); byte[] buffer = new byte[BUFFER_SIZE]; for (QualifiedFile qualified_file : file_list) { ZipEntry entry = new ZipEntry(qualified_file.getQualifier()); InputStream input = new FileInputStream(qualified_file.getFile()); int read; zip_out.putNextEntry(entry); while ((read = input.read(buffer)) != -1) { zip_out.write(buffer, 0, read); } input.close(); zip_out.closeEntry(); } zip_out.close(); output.close(); } /** * Computes all normal files present in a file. * @param src * @return a list of {@link QualifiedFile} */ private List<QualifiedFile> getFileList(File src) { ArrayList<QualifiedFile> result = new ArrayList<>(); getFileList(src, null, result); return result; } /** * Internal method of {@link FileSystemDataStore#getFileList(File)} */ private void getFileList(File src, String prefix_folder, ArrayList<QualifiedFile> files) { String qualifier; if (prefix_folder == null) { qualifier = src.getName(); } else { qualifier = prefix_folder + File.separator + src.getName(); } if (src.isFile()) { files.add(new QualifiedFile(src, qualifier)); } else if (src.isDirectory()) { for (File file : src.listFiles()) { getFileList(file, qualifier, files); } } } /** * Represent a {@link File} with a qualifier name. */ private static class QualifiedFile { private final File file; private final String qualifier; public QualifiedFile(File file, String qualifier) { this.qualifier = qualifier; this.file = file; } public String getQualifier() { return qualifier; } public File getFile() { return file; } @Override public String toString() { return file.getAbsolutePath() + " --> " + qualifier; } } }