All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.util.FileUtils Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * $Id: FileUtils.java 19191 2010-08-25 21:05:23Z tcarlson $
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.util;

import org.mule.api.MuleRuntimeException;
import org.mule.config.i18n.MessageFactory;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * FileUtils contains useful methods for dealing with files &
 * directories.
 */
// @ThreadSafe
public class FileUtils extends org.apache.commons.io.FileUtils
{
    private static final Log logger = LogFactory.getLog(FileUtils.class);
    public static String DEFAULT_ENCODING = "UTF-8";
    
    public static synchronized void copyStreamToFile(InputStream input, File destination) throws IOException
    {
        if (destination.exists() && !destination.canWrite())
        {
            throw new IOException("Destination file does not exist or is not writeable");
        }

        try
        {
            FileOutputStream output = new FileOutputStream(destination);
            try
            {
                IOUtils.copy(input, output);
            }
            finally
            {
                IOUtils.closeQuietly(output);
            }
        }
        finally
        {
            IOUtils.closeQuietly(input);
        }
    }

    // TODO Document me!
    public static File createFile(String filename) throws IOException
    {
        File file = FileUtils.newFile(filename);
        if (!file.canWrite())
        {
            String dirName = file.getPath();
            int i = dirName.lastIndexOf(File.separator);
            if (i > -1)
            {
                dirName = dirName.substring(0, i);
                File dir = FileUtils.newFile(dirName);
                dir.mkdirs();
            }
            file.createNewFile();
        }
        return file;
    }

    // TODO Document me!
    public static String prepareWinFilename(String filename)
    {
        filename = filename.replaceAll("<", "(");
        filename = filename.replaceAll(">", ")");
        filename = filename.replaceAll("[/\\*?|:;\\]\\[\"]", "-");
        return filename;
    }

    // TODO Document me!
    public static File openDirectory(String directory) throws IOException
    {
        File dir = FileUtils.newFile(directory);
        if (!dir.exists())
        {
            dir.mkdirs();
        }
        if (!dir.isDirectory() || !dir.canRead())
        {
            throw new IOException("Path: " + directory + " exists but isn't a directory");
        }
        return dir;
    }

    /**
     * Reads the incoming String into a file at at the given destination.
     *
     * @param filename name and path of the file to create
     * @param data     the contents of the file
     * @return the new file.
     * @throws IOException If the creating or writing to the file stream fails
     */
    public static File stringToFile(String filename, String data) throws IOException
    {
        return stringToFile(filename, data, false);
    }

    // TODO Document me!
    public static synchronized File stringToFile(String filename, String data, boolean append)
            throws IOException
    {
        return stringToFile(filename, data, append, false);
    }

    // TODO Document me!
    public static synchronized File stringToFile(String filename, String data, boolean append, boolean newLine)
            throws IOException
    {
        File f = createFile(filename);
        BufferedWriter writer = null;
        try
        {
            writer = new BufferedWriter(new FileWriter(f, append));
            writer.write(data);
            if (newLine)
            {
                writer.newLine();
            }
        }
        finally
        {
            if (writer != null)
            {
                writer.close();
            }
        }
        return f;
    }

    // TODO Document me!
    public static String getResourcePath(String resourceName, Class callingClass) throws IOException
    {
        return getResourcePath(resourceName, callingClass, DEFAULT_ENCODING);
    }

    // TODO Document me!
    public static String getResourcePath(String resourceName, Class callingClass, String encoding)
            throws IOException
    {
        if (resourceName == null)
        {
            // no name
            return null;
        }

        URL url = IOUtils.getResourceAsUrl(resourceName, callingClass);
        if (url == null)
        {
            // not found
            return null;
        }
        return normalizeFilePath(url, encoding);
    }

    /**
     * Remove from uri to file prefix file:/
     * Add if need file separator to begin
     *
     * @param url      file uri to resource
     * @param encoding - Java encoding names
     * @return normalized file path
     * @throws UnsupportedEncodingException if encoding is unknown
     */
    public static String normalizeFilePath(URL url, String encoding) throws UnsupportedEncodingException
    {
        String resource = URLDecoder.decode(url.toExternalForm(), encoding);
        if (resource != null)
        {
            if (resource.startsWith("file:/"))
            {
                resource = resource.substring(6);

                if (!resource.startsWith(File.separator))
                {
                    resource = File.separator + resource;
                }
            }
        }
        return resource;
    }


    /**
     * Delete a file tree recursively.
     * @param dir dir to wipe out
     * @return false when the first unsuccessful attempt encountered
     */
    public static boolean deleteTree(File dir)
    {
        return deleteTree(dir, null);
    }

    /**
     * Delete a file tree recursively. This method additionally tries to be
     * gentle with specified top-level dirs. E.g. this is the case when a
     * transaction manager asynchronously handles the recovery log, and the test
     * wipes out everything, leaving the transaction manager puzzled.  
     * @param dir dir to wipe out
     * @param topLevelDirsToIgnore which top-level directories to ignore,
     *        if null or empty then ignored
     * @return false when the first unsuccessful attempt encountered
     */
    public static boolean deleteTree(File dir, final String[] topLevelDirsToIgnore)
    {
        if (dir == null || !dir.exists())
        {
            return true;
        }
        File[] files = dir.listFiles();
        if (files != null)
        {
            for (int i = 0; i < files.length; i++)
            {
                OUTER:
                if (files[i].isDirectory())
                {
                    if (topLevelDirsToIgnore != null)
                    {
                        for (int j = 0; j < topLevelDirsToIgnore.length; j++)
                        {
                            String ignored = topLevelDirsToIgnore[j];
                            if (ignored.equals(FilenameUtils.getBaseName(files[i].getName())))
                            {
                                break OUTER;
                            }
                        }
                    }
                    if (!deleteTree(files[i]))
                    {
                        return false;
                    }
                }
                else
                {
                    if (!files[i].delete())
                    {
                        return false;
                    }
                }
            }
        }
        return dir.delete();
    }

    /**
     * Unzip the specified archive to the given directory
     */
    public static void unzip(File archive, File directory) throws IOException
    {
        ZipFile zip = null;

        if (directory.exists())
        {
            if (!directory.isDirectory())
            {
                throw new IOException("Directory is not a directory: " + directory);
            }
        }
        else
        {
            if (!directory.mkdirs())
            {
                throw new IOException("Could not create directory: " + directory);
            }
        }
        try
        {
            zip = new ZipFile(archive);
            for (Enumeration entries = zip.entries(); entries.hasMoreElements();)
            {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                File f = FileUtils.newFile(directory, entry.getName());
                if (entry.isDirectory())
                {
                    if (!f.mkdirs())
                    {
                        throw new IOException("Could not create directory: " + f);
                    }
                }
                else
                {
                    InputStream is = zip.getInputStream(entry);
                    OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
                    IOUtils.copy(is, os);
                    IOUtils.closeQuietly(is);
                    IOUtils.closeQuietly(os);
                }
            }
        }
        finally
        {
            if (zip != null)
            {
                zip.close();
            }
        }
    }

    /**
     * Workaround for JDK bug 
     * 4117557. More in-context information at
     * MULE-1112
     * 

* Factory methods correspond to constructors of the java.io.File class. * No physical file created in this method. * * @see File */ public static File newFile(String pathName) { try { return new File(pathName).getCanonicalFile(); } catch (IOException e) { throw new MuleRuntimeException( MessageFactory.createStaticMessage("Unable to create a canonical file for " + pathName), e); } } /** * Workaround for JDK bug * 4117557. More in-context information at * MULE-1112 *

* Factory methods correspond to constructors of the java.io.File class. * No physical file created in this method. * * @see File */ public static File newFile(URI uri) { try { return new File(uri).getCanonicalFile(); } catch (IOException e) { throw new MuleRuntimeException( MessageFactory.createStaticMessage("Unable to create a canonical file for " + uri), e); } } /** * Workaround for JDK bug * 4117557. More in-context information at * MULE-1112 *

* Factory methods correspond to constructors of the java.io.File class. * No physical file created in this method. * * @see File */ public static File newFile(File parent, String child) { try { return new File(parent, child).getCanonicalFile(); } catch (IOException e) { throw new MuleRuntimeException( MessageFactory.createStaticMessage("Unable to create a canonical file for parent: " + parent + " and child: " + child), e); } } /** * Workaround for JDK bug * 4117557. More in-context information at * MULE-1112 *

* Factory methods correspond to constructors of the java.io.File class. * No physical file created in this method. * * @see File */ public static File newFile(String parent, String child) { try { return new File(parent, child).getCanonicalFile(); } catch (IOException e) { throw new MuleRuntimeException( MessageFactory.createStaticMessage("Unable to create a canonical file for parent: " + parent + " and child: " + child), e); } } /** * Extract the specified resource to the given directory for * remain all directory struct * * @param resourceName - full resource name * @param callingClass - classloader for this class is used * @param outputDir - extract to this directory * @param keepParentDirectory true - full structure of directories is kept; false - file - removed all directories, directory - started from resource point * @throws IOException if any errors */ public static void extractResources(String resourceName, Class callingClass, File outputDir, boolean keepParentDirectory) throws IOException { URL url = callingClass.getClassLoader().getResource(resourceName); URLConnection connection = url.openConnection(); if (connection instanceof JarURLConnection) { extractJarResources((JarURLConnection) connection, outputDir, keepParentDirectory); } else { extractFileResources(normalizeFilePath(url, DEFAULT_ENCODING), outputDir, resourceName, keepParentDirectory); } } /** * Extract resources contain in file * * @param path - path to file * @param outputDir Directory for unpack recources * @param resourceName * @param keepParentDirectory true - full structure of directories is kept; false - file - removed all directories, directory - started from resource point * @throws IOException if any error */ private static void extractFileResources(String path, File outputDir, String resourceName, boolean keepParentDirectory) throws IOException { File file = FileUtils.newFile(path); if (!file.exists()) { throw new IOException("The resource by path " + path + " "); } if (file.isDirectory()) { if (keepParentDirectory) { outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + resourceName); if (!outputDir.exists()) { outputDir.mkdirs(); } } else { outputDir = FileUtils.newFile(outputDir.getPath()); } copyDirectory(file, outputDir); } else { if (keepParentDirectory) { outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + resourceName); } else { outputDir = FileUtils.newFile(outputDir.getPath() + File.separator + file.getName()); } copyFile(file, outputDir); } } /** * Extract recources contain if jar (have to in classpath) * * @param connection JarURLConnection to jar library * @param outputDir Directory for unpack recources * @param keepParentDirectory true - full structure of directories is kept; false - file - removed all directories, directory - started from resource point * @throws IOException if any error */ private static void extractJarResources(JarURLConnection connection, File outputDir, boolean keepParentDirectory) throws IOException { JarFile jarFile = connection.getJarFile(); JarEntry jarResource = connection.getJarEntry(); Enumeration entries = jarFile.entries(); InputStream inputStream = null; OutputStream outputStream = null; int jarResourceNameLenght = jarResource.getName().length(); for (; entries.hasMoreElements();) { JarEntry entry = (JarEntry) entries.nextElement(); if (entry.getName().startsWith(jarResource.getName())) { String path = outputDir.getPath() + File.separator + entry.getName(); //remove directory struct for file and first dir for directory if (!keepParentDirectory) { if (entry.isDirectory()) { if (entry.getName().equals(jarResource.getName())) { continue; } path = outputDir.getPath() + File.separator + entry.getName().substring(jarResourceNameLenght, entry.getName().length()); } else { if (entry.getName().length() > jarResourceNameLenght) { path = outputDir.getPath() + File.separator + entry.getName().substring(jarResourceNameLenght, entry.getName().length()); } else { path = outputDir.getPath() + File.separator + entry.getName().substring(entry.getName().lastIndexOf("/"), entry.getName().length()); } } } File file = FileUtils.newFile(path); if (!file.getParentFile().exists()) { if (!file.getParentFile().mkdirs()) { throw new IOException("Could not create directory: " + file.getParentFile()); } } if (entry.isDirectory()) { if (!file.exists() && !file.mkdirs()) { throw new IOException("Could not create directory: " + file); } } else { try { inputStream = jarFile.getInputStream(entry); outputStream = new BufferedOutputStream(new FileOutputStream(file)); IOUtils.copy(inputStream, outputStream); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } } } } public static boolean renameFileHard(String srcFilePath, String destFilePath) { if (StringUtils.isNotBlank(srcFilePath) && StringUtils.isNotBlank(destFilePath)) { return renameFileHard(new File(srcFilePath), new File(destFilePath)); } else { return false; } } public static boolean renameFileHard(File srcFile, File destFile) { boolean isRenamed = false; if (srcFile != null && destFile != null) { logger.debug("Moving file " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath()); if (!destFile.exists()) { try { if (srcFile.isFile()) { logger.debug("Trying to rename file"); FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); out.getChannel().transferFrom(in.getChannel(), 0, srcFile.length()); isRenamed = true; } catch (Exception e) { logger.debug(e); } finally { if (in != null) { try { in.close(); } catch (Exception inNotClosed) { logger.debug(inNotClosed); } } if (out != null) { try { out.close(); } catch (Exception outNotClosed) { logger.debug(outNotClosed); } } } logger.debug("File renamed: " + isRenamed); if (isRenamed) { srcFile.delete(); } else { destFile.delete(); } } else { logger.debug(srcFile.getAbsolutePath() + " is not a valid file."); } } catch (Exception e) { logger.debug("Error renaming file from " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath()); } } else { logger.debug("Error renaming file " + srcFile.getAbsolutePath() + ". Destination file " + destFile.getAbsolutePath() + " already exists."); } } return isRenamed; } public static boolean renameFile(String srcFilePath, String destFilePath) { if (StringUtils.isNotBlank(srcFilePath) && StringUtils.isNotBlank(destFilePath)) { return renameFile(new File(srcFilePath), new File(destFilePath)); } else { return false; } } public static boolean renameFile(File srcFile, File destFile) { boolean isRenamed = false; if (srcFile != null && destFile != null) { logger.debug("Moving file " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath()); if (!destFile.exists()) { try { if (srcFile.isFile()) { logger.debug("Trying to rename file"); isRenamed = srcFile.renameTo(destFile); if (!isRenamed && srcFile.exists()) { logger.debug("Trying hard copy, assuming partition crossing ..."); isRenamed = renameFileHard(srcFile, destFile); } logger.debug("File renamed: " + isRenamed); } else { logger.debug(srcFile.getAbsolutePath() + " is not a valid file"); } } catch (Exception e) { logger.debug("Error moving file from " + srcFile.getAbsolutePath() + " to " + destFile.getAbsolutePath(), e); } } else { logger.debug("Error renaming file " + srcFile.getAbsolutePath() + ". Destination file " + destFile.getAbsolutePath() + " already exists."); } } else { logger.debug("Error renaming file. Source or destination file is null."); } return isRenamed; } /** * Try to move a file by renaming with backup attempt by copying/deleting via NIO */ public static boolean moveFileWithCopyFallback(File sourceFile, File destinationFile) { // try fast file-system-level move/rename first boolean success = sourceFile.renameTo(destinationFile); if (!success) { // try again using NIO copy FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(sourceFile); fos = new FileOutputStream(destinationFile); FileChannel srcChannel = fis.getChannel(); FileChannel dstChannel = fos.getChannel(); dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); srcChannel.close(); dstChannel.close(); success = sourceFile.delete(); } catch (IOException ioex) { // grr! success = false; } finally { IOUtils.closeQuietly(fis); IOUtils.closeQuietly(fos); } } return success; } /** * Copy in file to out file * * Don't use java.nio as READ_ONLY memory mapped files cannot be deleted * * @param in * @param out */ public static void safeCopyFile(File in, File out) throws IOException { try { FileInputStream fis = new FileInputStream(in); FileOutputStream fos = new FileOutputStream(out); try { byte[] buf = new byte[1024]; int i = 0; while ((i = fis.read(buf)) != -1) { fos.write(buf, 0, i); } } catch (IOException e) { throw e; } finally { try { if (fis != null) fis.close(); if (fos != null) fos.close(); } catch (IOException e) { throw e; } } } catch (FileNotFoundException e) { throw e; } } // Override the following methods to use a new version of doCopyFile(File // srcFile, File destFile, boolean preserveFileDate) that uses nio to copy file /** * Copies a file to a new location. *

* This method copies the contents of the specified source file to the specified * destination file. The directory holding the destination file is created if it * does not exist. If the destination file exists, then this method will * overwrite it. * * @param srcFile an existing file to copy, must not be null * @param destFile the new file, must not be null * @param preserveFileDate true if the file date of the copy should be the same * as the original * @throws NullPointerException if source or destination is null * @throws IOException if source or destination is invalid * @throws IOException if an IO error occurs during copying * @see #copyFileToDirectory(File, File, boolean) */ public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { if (srcFile == null) { throw new NullPointerException("Source must not be null"); } if (destFile == null) { throw new NullPointerException("Destination must not be null"); } if (srcFile.exists() == false) { throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); } if (srcFile.isDirectory()) { throw new IOException("Source '" + srcFile + "' exists but is a directory"); } if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) { throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same"); } if (destFile.getParentFile() != null && destFile.getParentFile().exists() == false) { if (destFile.getParentFile().mkdirs() == false) { throw new IOException("Destination '" + destFile + "' directory cannot be created"); } } if (destFile.exists() && destFile.canWrite() == false) { throw new IOException("Destination '" + destFile + "' exists but is read-only"); } doCopyFile(srcFile, destFile, preserveFileDate); } /** * Internal copy file method. * * @param srcFile the validated source file, must not be null * @param destFile the validated destination file, must not be null * @param preserveFileDate whether to preserve the file date * @throws IOException if an error occurs */ private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { if (destFile.exists() && destFile.isDirectory()) { throw new IOException("Destination '" + destFile + "' exists but is a directory"); } FileChannel input = new FileInputStream(srcFile).getChannel(); try { FileChannel output = new FileOutputStream(destFile).getChannel(); try { output.transferFrom(input, 0, input.size()); } finally { closeQuietly(output); } } finally { closeQuietly(input); } if (srcFile.length() != destFile.length()) { throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); } if (preserveFileDate) { destFile.setLastModified(srcFile.lastModified()); } } /** * Unconditionally close a Channel. *

* Equivalent to {@link Channel#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param channel the Channel to close, may be null or already closed */ public static void closeQuietly(Channel channel) { try { if (channel != null) { channel.close(); } } catch (IOException ioe) { // ignore } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy