be.i8c.sag.util.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for be.i8c.sag.util.FileUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2017, i8c N.V. (Integr8 Consulting; http://www.i8c.be)
 * All Rights Reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *******************************************************************************/
package be.i8c.sag.util;

import org.apache.commons.io.IOUtils;

import java.io.*;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Misc file utilities
 */
public class FileUtils {
    /** The internal directory which contains assets that may need to be extracted */
    public static final String ASSETS_FOLDER_NAME = "assets";

    /**
     * Receives the fop.xconf stream and puts it in a temporary file.
     *
     * @param stream The stream tat will be written to the temporary file
     * @return Returns temporary file with the content of the stream
     * @throws IOException when the file couldn't be created
     */
    public static File createTempFopConf(InputStream stream) throws IOException {
        File temp;
        temp = File.createTempFile("fop", ".xconf");
        temp.deleteOnExit();
        FileOutputStream out = new FileOutputStream(temp);
        IOUtils.copy(stream, out);
        return temp;
    }

    /**
     * Get the File that represents the location of this jar.
     * 
     * Note: The file may be a directory when you are running this
     * code from your IDE or without packing it into a jar.
     *
     * @return A File that represents the location of this jar.
     */
    public static File getJarFile() {
        return getJarFile(FileUtils.class);
    }

    /**
     * Get the File that represents the location of this jar that contains the clazz.
     *
     * Note: The file may be a directory when you are running this
     * code from your IDE or without packing it into a jar.
     *
     * @param clazz A class that is located in the jar file.
     * @return A File that represents the location of the jar that contains the clazz.
     */
    public static File getJarFile(Class<?> clazz) {
        String className = clazz.getSimpleName() + ".class";
        String classPath = "/" + clazz.getName().replace('.', '/') + ".class";

        URL generatorFileUrl = clazz.getResource(className);

        // We want to remove the last instance of the internal class path
        String jarPath = new StringBuilder(new StringBuilder(generatorFileUrl.getPath()).reverse().toString()
                .replaceFirst(new StringBuilder(classPath).reverse().toString(), "")).reverse().toString();

        // Remove the file:/ and the '!' at the end of the path.
        // This only needs to be done if it's a file
        jarPath = jarPath.replaceAll("^file:/", "");
        jarPath = jarPath.replaceAll("!$", "");

        return new File(jarPath);
    }

    /**
     * Extract all files from the assets folder in the jar to the destinationDir.
     *
     * @param destinationDir The output directory
     * @throws IOException When failed to write to a file
     * @throws FileNotFoundException If a file could not be found
     */
    public static void extractAssets(File destinationDir) throws IOException {
        extractAssets(destinationDir, false);
    }

    /**
     * Extract all files from the assets folder in the jar to the destinationDir.
     * If deleteOnExit is true, all the files will be removed once the
     * application has closed.
     *
     * @param destinationDir The output directory
     * @param deleteOnExit If true, delete the files once the application has closed.
     * @throws IOException When failed to write to a file
     * @throws FileNotFoundException If a file could not be found
     */
    public static void extractAssets(File destinationDir, boolean deleteOnExit) throws IOException {
        // Find where this jar is located
        File jarFile = getJarFile();

        // Attempt to dynamically load in all files in the folder of the assets dir
        // Extract files of the code source when it's packed in a jar
        if (jarFile.isFile()) {
            extractDirectory(ASSETS_FOLDER_NAME, jarFile, destinationDir, deleteOnExit);
        }
        // Extract files of the code source when it's not packed in a jar
        // Mainly used during development
        else if (jarFile.isDirectory()) {
            File extractingDir = new File(jarFile, ASSETS_FOLDER_NAME);
            copyDirectory(extractingDir, destinationDir, deleteOnExit);
        }
    }

    /**
     * Extract files from a zipped (and jar) file
     *
     * @param internalDir The directory you want to copy
     * @param zipFile The file that contains the content you want to copy
     * @param to The directory you want to copy to
     * @param deleteOnExit If true, delete the files once the application has closed.
     * @throws IOException When failed to write to a file
     * @throws FileNotFoundException If a file could not be found
     */
    public static void extractDirectory(String internalDir, File zipFile, File to, boolean deleteOnExit)
            throws IOException {
        try (ZipInputStream zip = new ZipInputStream(new FileInputStream(zipFile))) {
            while (true) {
                ZipEntry zipEntry = zip.getNextEntry();
                if (zipEntry == null)
                    break;

                if (zipEntry.getName().startsWith(internalDir) && !zipEntry.isDirectory()) {
                    File f = createFile(new File(to, zipEntry.getName()
                            .replace((internalDir.endsWith("/") ? internalDir : internalDir + "/"), "")));
                    if (deleteOnExit)
                        f.deleteOnExit();
                    OutputStream bos = new FileOutputStream(f);
                    try {
                        IOUtils.copy(zip, bos);
                    } finally {
                        bos.flush();
                        bos.close();
                    }
                }

                zip.closeEntry();
            }
        }
    }

    /**
     * Copy a directory and it's content
     *
     * @param from The directory to copy
     * @param to Where to copy it to
     * @param deleteOnExit If true, delete the files once the application has closed.
     * @throws IOException When failed to write to a file
     * @throws FileNotFoundException If a file could not be found
     */
    public static void copyDirectory(File from, File to, boolean deleteOnExit) throws IOException {
        File[] children = from.listFiles();
        if (children != null) {
            for (File child : children) {
                // Extract the file
                InputStream in = new FileInputStream(child);
                File outputFile = createFile(new File(to, child.getName()));
                if (deleteOnExit)
                    outputFile.deleteOnExit();

                OutputStream out = new FileOutputStream(outputFile);
                try {
                    IOUtils.copy(in, out);
                } finally {
                    out.flush();
                    in.close();
                    out.close();
                }
            }
        }
    }

    /**
     * Creates the file if it doesn't exist yet
     *
     * @param file The file to create
     * @return The same file that was passed
     * @throws IOException When failed to write to a file
     */
    public static File createFile(File file) throws IOException {
        if (!file.exists()) {
            if (file.getParentFile() != null)
                file.getParentFile().mkdirs();
            file.createNewFile();
        }

        return file;
    }
}