org.geoserver.backuprestore.utils.BackupUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.backuprestore.utils.BackupUtils.java

Source

/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.backuprestore.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.vfs2.AllFileSelector;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import org.codehaus.plexus.util.FileUtils;
import org.geoserver.config.GeoServerDataDirectory;
import org.geoserver.platform.resource.Files;
import org.geoserver.platform.resource.Paths;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resource.Type;
import org.geoserver.platform.resource.Resources;
import org.geoserver.util.IOUtils;
import org.geotools.util.logging.Logging;

/**
 * Utility to work with compressed files
 * 
 * Based on Importer {@link VFSWorker} by Gabriel Roldan
 * 
 * @author groldan
 * @autho Alessio Fabiani, GeoSolutions
 */
public class BackupUtils {

    private static final Logger LOGGER = Logging.getLogger(BackupUtils.class);

    /**
     * Returns a random temp folder Resource inside the System Temp Directory.
     * 
     * @return
     * @throws IOException
     */
    public static Resource tmpDir() throws IOException {
        String tempPath = null;
        try {
            tempPath = System.getProperty("java.io.tmpdir");
            if (tempPath == null) {
                tempPath = IOUtils.createTempDirectory("backuputils").getAbsolutePath();
                LOGGER.warning(
                        "It was not possible to create a temporary folder into the System 'java.io.tmpdir'. Falling back to default TEMP ["
                                + tempPath + "].");
            }
        } catch (Exception e) {
            tempPath = null;
            LOGGER.log(Level.SEVERE,
                    "It was not possible to create a temporary folder! In order to fix the problem, please check the System 'java.io.tmpdir' point to a valid folder.",
                    e);
            throw new IOException(
                    "It was not possible to create a temporary folder! In order to fix the problem, please check the System 'java.io.tmpdir' point to a valid folder.",
                    e);
        }

        if (tempPath == null) {
            LOGGER.log(Level.SEVERE,
                    "It was not possible to create or find a suitable temporary folder. 'tempPath' is NULL! In order to fix the problem, please check the System 'java.io.tmpdir' point to a valid folder.");
            throw new IOException(
                    "It was not possible to create or find a suitable temporary folder. 'tempPath' is NULL! In order to fix the problem, please check the System 'java.io.tmpdir' point to a valid folder.");
        }

        return createRandomResource(tempPath);
    }

    /**
     * Returns a random temp folder Resource inside the GeoServer Temp Directory.
     * 
     * @param geoServerDataDirectory
     * @return
     * @throws IOException 
     */
    public static Resource geoServerTmpDir(GeoServerDataDirectory geoServerDataDirectory) throws IOException {
        String tempPath = geoServerDataDirectory.findOrCreateDir("temp").getAbsolutePath();

        return createRandomResource(tempPath);
    }

    /**
     * @param tempPath
     * @return
     * @throws IOException
     */
    private static Resource createRandomResource(String tempPath) throws IOException {
        Resource root = Resources.fromPath(tempPath);
        Resource directory = Resources.createRandom("tmp", "", root);

        do {
            FileUtils.forceDelete(directory.dir());
        } while (Resources.exists(directory));

        FileUtils.forceMkdir(directory.dir());

        return Files.asResource(directory.dir());
    }

    /**
     * Extracts the archive file {@code archiveFile} to {@code targetFolder}; both shall previously exist.
     *
     * @param archiveFile
     * @param targetFolder
     * @throws IOException
     */
    public static void extractTo(Resource archiveFile, Resource targetFolder) throws IOException {
        FileSystemManager manager = VFS.getManager();
        String sourceURI = resolveArchiveURI(archiveFile);

        FileObject source = manager.resolveFile(sourceURI);
        if (manager.canCreateFileSystem(source)) {
            source = manager.createFileSystem(source);
        }
        FileObject target = manager
                .createVirtualFileSystem(manager.resolveFile(targetFolder.dir().getAbsolutePath()));

        FileSelector selector = new AllFileSelector() {
            @Override
            public boolean includeFile(FileSelectInfo fileInfo) {
                LOGGER.fine("Uncompressing " + fileInfo.getFile().getName().getFriendlyURI());
                return true;
            }
        };
        target.copyFrom(source, selector);
        source.close();
        target.close();
        manager.closeFileSystem(source.getFileSystem());
    }

    /**
     * Compress {@code sourceFolder} to the archive file {@code archiveFile}; both shall previously exist.
     * 
     * @param sourceFolder
     * @param archiveFile
     * @throws IOException
     */
    public static void compressTo(Resource sourceFolder, Resource archiveFile) throws IOException {
        // See https://commons.apache.org/proper/commons-vfs/filesystems.html
        // for the supported filesystems

        FileSystemManager manager = VFS.getManager();

        FileObject sourceDir = manager
                .createVirtualFileSystem(manager.resolveFile(sourceFolder.dir().getAbsolutePath()));

        try {
            if ("zip".equalsIgnoreCase(FileUtils.getExtension(archiveFile.path()))) {
                // apache VFS does not support ZIP as writable FileSystem

                OutputStream fos = archiveFile.out();

                // Create access to zip.
                ZipOutputStream zos = new ZipOutputStream(fos);

                // add entry/-ies.
                for (FileObject sourceFile : sourceDir.getChildren()) {
                    writeEntry(zos, sourceFile, null);
                }

                // Close streams
                zos.flush();
                zos.close();
                fos.close();
            } else {
                // Create access to archive.
                FileObject zipFile = manager.resolveFile(resolveArchiveURI(archiveFile));
                zipFile.createFile();
                ZipOutputStream zos = new ZipOutputStream(zipFile.getContent().getOutputStream());

                // add entry/-ies.
                for (FileObject sourceFile : sourceDir.getChildren()) {
                    writeEntry(zos, sourceFile, null);
                }

                // Close streams
                zos.flush();
                zos.close();
                zipFile.close();
                manager.closeFileSystem(zipFile.getFileSystem());
            }
        } finally {
            manager.closeFileSystem(sourceDir.getFileSystem());
        }
    }

    /**
     * @param zos
     * @param sourceFile
     * @throws FileSystemException
     * @throws IOException
     */
    private static void writeEntry(ZipOutputStream zos, FileObject sourceFile, String baseDir)
            throws FileSystemException, IOException {
        if (sourceFile.getType() == FileType.FOLDER) {
            // add entry/-ies.
            for (FileObject file : sourceFile.getChildren()) {
                writeEntry(zos, file, Paths.path(baseDir, sourceFile.getName().getBaseName()));
            }
        } else {
            String fileName = (baseDir != null ? Paths.path(baseDir, sourceFile.getName().getBaseName())
                    : sourceFile.getName().getBaseName());
            ZipEntry zipEntry = new ZipEntry(fileName);
            InputStream is = sourceFile.getContent().getInputStream();

            // Write to zip.
            byte[] buf = new byte[1024];
            zos.putNextEntry(zipEntry);
            for (int readNum; (readNum = is.read(buf)) != -1;) {
                zos.write(buf, 0, readNum);
            }
            zos.closeEntry();
            is.close();
        }
    }

    /**
     * 
     * @param archiveFile
     * @return
     */
    public static String resolveArchiveURI(final Resource archiveFile) {
        String archivePrefix = getArchiveURLProtocol(archiveFile);
        String absolutePath = archivePrefix + archiveFile.file().getAbsolutePath();
        return absolutePath;
    }

    /**
     * 
     * @param file
     * @return
     */
    public static String getArchiveURLProtocol(final Resource file) {
        if (file.getType() == Type.DIRECTORY) {
            return "file://";
        }
        String name = file.name().toLowerCase();
        if (name.endsWith(".zip") || name.endsWith(".kmz")) {
            return "zip://";
        }
        if (name.endsWith(".tar")) {
            return "tar://";
        }
        if (name.endsWith(".tgz") || name.endsWith(".tar.gz")) {
            return "tgz://";
        }
        if (name.endsWith(".tbz2") || name.endsWith(".tar.bzip2") || name.endsWith(".tar.bz2")) {
            return "tbz2://";
        }
        if (name.endsWith(".gz")) {
            return "gz://";
        }
        if (name.endsWith(".bz2")) {
            return "bz2://";
        }
        if (name.endsWith(".jar")) {
            return "jar://";
        }
        return null;
    }

    /**
     * 
     * @param baseDir
     * @param subDir
     * @return
     */
    public static Resource dir(Resource baseDir, String subDir) {
        final Resource targetPath = Resources.fromPath(subDir, baseDir);
        return Resources.fromPath(Resources.directory(targetPath, !Resources.exists(targetPath)).getAbsolutePath());
    }

}