org.jboss.as.forge.util.Files.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.as.forge.util.Files.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.forge.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Enumeration;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;

/**
 * Utility for {@link java.io.File files}.
 *
 * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
 */
public class Files {
    static final String TMP_DIR_PROPERTY = "java.io.tmpdir";

    /**
     * Creates a file from the base with each path element.
     *
     * @param base  the parent directory
     * @param paths the paths to create
     *
     * @return a new file
     */
    public static File createFile(final File base, final String... paths) {
        final StringBuilder sb = new StringBuilder();
        int count = 0;
        for (String path : paths) {
            sb.append(path);
            if (!path.endsWith(File.separator) && (++count < paths.length)) {
                sb.append(File.separator);
            }
        }
        return new File(base, sb.toString());
    }

    /**
     * Creates a new file based on the path elements.
     *
     * @param paths the path elements
     *
     * @return a new file
     */
    public static String createPath(final String... paths) {
        final StringBuilder sb = new StringBuilder();
        int count = 0;
        for (String path : paths) {
            sb.append(path);
            if (!path.endsWith(File.separator) && (++count < paths.length)) {
                sb.append(File.separator);
            }
        }
        return sb.toString();
    }

    /**
     * Returns the temporary directory.
     *
     * @return the temporary directory
     */
    public static File getTempDirectory() {
        return new File(getProperty(TMP_DIR_PROPERTY));
    }

    public static boolean extractAppServer(final String zipPath, final File target) throws IOException {
        return extractAppServer(zipPath, target, false);
    }

    public static boolean extractAppServer(final String zipPath, final File target, final boolean overwrite)
            throws IOException {
        if (target.exists() && !overwrite) {
            throw new IllegalStateException(Messages.INSTANCE.getMessage("files.not.empty.directory"));
        }
        // Create a temporary directory
        final File tmpDir = new File(getTempDirectory(), "jboss-as-" + zipPath.hashCode());
        if (tmpDir.exists()) {
            deleteRecursively(tmpDir);
        }
        try {
            final byte buff[] = new byte[1024];
            ZipFile file = null;
            try {
                file = new ZipFile(zipPath);
                final Enumeration<ZipArchiveEntry> entries = file.getEntries();
                while (entries.hasMoreElements()) {
                    final ZipArchiveEntry entry = entries.nextElement();
                    // Create the extraction target
                    final File extractTarget = new File(tmpDir, entry.getName());
                    if (entry.isDirectory()) {
                        extractTarget.mkdirs();
                    } else {
                        final File parent = new File(extractTarget.getParent());
                        parent.mkdirs();
                        final BufferedInputStream in = new BufferedInputStream(file.getInputStream(entry));
                        try {
                            final BufferedOutputStream out = new BufferedOutputStream(
                                    new FileOutputStream(extractTarget));
                            try {
                                int read;
                                while ((read = in.read(buff)) != -1) {
                                    out.write(buff, 0, read);
                                }
                            } finally {
                                Streams.safeClose(out);
                            }
                        } finally {
                            Streams.safeClose(in);
                        }
                        // Set the file permissions
                        if (entry.getUnixMode() > 0) {
                            setPermissions(extractTarget, FilePermissions.of(entry.getUnixMode()));
                        }
                    }
                }
            } catch (IOException e) {
                throw new IOException(Messages.INSTANCE.getMessage("files.extraction.error", file), e);
            } finally {
                ZipFile.closeQuietly(file);
                // Streams.safeClose(file);
            }
            // If the target exists, remove then rename
            if (target.exists()) {
                deleteRecursively(target);
            }
            // First child should be a directory and there should only be one child
            final File[] children = tmpDir.listFiles();
            if (children != null && children.length == 1) {
                return moveDirectory(children[0], target);
            }
            return moveDirectory(tmpDir, target);

        } finally {
            deleteRecursively(tmpDir);
        }
    }

    /**
     * Checks to see if a directory is empty.
     *
     * @param dir the directory to check
     *
     * @return {@code true} if the directory is empty, otherwise {@code false}
     *
     * @throws IllegalArgumentException if the parameter in is not a directory
     */
    public static boolean isEmptyDirectory(final File dir) {
        if (!dir.exists())
            return true;
        if (dir.isDirectory()) {
            final String[] files = dir.list();
            return files == null || files.length == 0;
        }
        throw new IllegalArgumentException(Messages.INSTANCE.getMessage("files.not.directory", dir));
    }

    /**
     * Recursively deletes all files and directories within the directory as well as the directory itself.
     * <p/>
     * On a failure this does not preserve files that have been deleted.
     *
     * @param dir the directory to delete
     *
     * @return {@code true} if the directory and all it's contents were deleted, otherwise {@code false}
     */
    public static boolean deleteRecursively(final File dir) {
        if (dir.isDirectory()) {
            final File[] files = dir.listFiles();
            if (files != null) {
                for (final File f : files) {
                    if (f.isDirectory()) {
                        if (!deleteRecursively(f)) {
                            return false;
                        }
                    } else if (!f.delete()) {
                        return false;
                    }
                }
            }
        }
        return dir.delete();
    }

    /**
     * Recursively copies a directories contents to the target directory then deletes the source directory.
     * <p/>
     * If a non-fatal failure occurs the {@code srcDir} might be partially deleted if the failure occurred during the
     * delete, otherwise it should be left as is. The {@code targetDir} may or may not have been created and may or may
     * not contain some or all of the contents from the {@code srcDir}.
     *
     * @param srcDir    the source directory
     * @param targetDir the target directory
     *
     * @return {@code true} if the contents were successfully copied, {@code false} if the contents were not copied or
     *         partially copied but a failure occurred
     *
     * @throws IOException if an IO error occurs copying a file or creating directories
     */
    public static boolean moveDirectory(final File srcDir, final File targetDir) throws IOException {
        boolean result = srcDir.renameTo(targetDir);
        // First try rename
        if (!result) {
            result = copyDirectory(srcDir, targetDir) && deleteRecursively(srcDir);
        }
        return result;
    }

    /**
     * Recursively copies a directories contents to the target directory.
     *
     * @param srcDir    the source directory
     * @param targetDir the target directory
     *
     * @return {@code true} if the contents were successfully copied, {@code false} if the contents were not copied or
     *         partially copied but a failure occurred
     *
     * @throws IOException if an IO error occurs copying a file or creating directories
     */
    public static boolean copyDirectory(final File srcDir, final File targetDir) throws IOException {
        final File[] contents = srcDir.listFiles();
        for (File file : contents != null ? contents : new File[0]) {
            final File target = new File(targetDir, file.getName());
            if (file.isDirectory()) {
                target.mkdirs();
                if (!copyDirectory(file, target)) {
                    return false;
                }
            } else {
                target.getParentFile().mkdirs();
                if (!copyFile(file, target)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Copies the source file to the destination file.
     *
     * @param srcFile    the file to copy
     * @param targetFile the target file
     *
     * @return {@code true} if the file was successfully copied, {@code false} if the copy failed or was incomplete
     *
     * @throws IOException if an IO error occurs copying the file
     */
    public static boolean copyFile(final File srcFile, final File targetFile) throws IOException {
        FileInputStream in = null;
        FileOutputStream out = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            in = new FileInputStream(srcFile);
            inChannel = in.getChannel();
            out = new FileOutputStream(targetFile);
            outChannel = out.getChannel();
            long bytesTransferred = 0;
            while (bytesTransferred < inChannel.size()) {
                bytesTransferred += inChannel.transferTo(0, inChannel.size(), outChannel);
            }
        } finally {
            Streams.safeClose(outChannel);
            Streams.safeClose(out);
            Streams.safeClose(inChannel);
            Streams.safeClose(in);
        }
        return srcFile.length() == targetFile.length();
    }

    /**
     * Sets the permissions on the file.
     *
     * @param file        the file
     * @param permissions the permissions to set
     */
    public static void setPermissions(final File file, final FilePermissions permissions) {
        file.setExecutable(permissions.owner().canExecute(),
                !(permissions.group().canExecute() && permissions.pub().canExecute()));
        file.setReadable(permissions.owner().canWrite(),
                !(permissions.group().canWrite() && permissions.pub().canWrite()));
        file.setWritable(permissions.owner().canWrite(),
                !(permissions.group().canWrite() && permissions.pub().canWrite()));
    }

    static String getProperty(final String key) {
        if (System.getSecurityManager() == null) {
            return System.getProperty(key);
        }
        return AccessController.doPrivileged(new PrivilegedAction<String>() {
            @Override
            public String run() {
                return System.getProperty(key);
            }
        });
    }
}