org.eclim.util.file.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.eclim.util.file.FileUtils.java

Source

/**
 * Copyright (C) 2005 - 2013  Eric Van Dewoestine
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.eclim.util.file;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.util.Enumeration;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.CompositeName;

import org.apache.commons.lang.StringUtils;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.VFS;

import org.eclim.util.IOUtils;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;

/**
 * Utilities for working w/ files and commons vfs.
 *
 * @author Eric Van Dewoestine
 */
public class FileUtils {
    public static final String JAR_PREFIX = "jar://";
    public static final String ZIP_PREFIX = "zip://";
    public static final String JAR_EXT = ".jar";
    public static final String ZIP_EXT = ".zip";
    public static final char UNIX_SEPARATOR = '/';
    public static final char WINDOWS_SEPARATOR = '\\';
    public static final String UTF8 = "utf-8";

    /**
     * Converts the supplied byte offset in the specified file to the
     * corresponding char offset for that file using the supplied file encoding.
     *
     * @param filename The absolute path to the file.
     * @param byteOffset The byte offset to be converted.
     * @param encoding The encoding of the file.  If null, defaults to utf-8.
     *
     * @return The char offset.
     */
    public static int byteOffsetToCharOffset(String filename, int byteOffset, String encoding) throws Exception {
        FileSystemManager fsManager = VFS.getManager();
        FileObject file = fsManager.resolveFile(filename);

        return byteOffsetToCharOffset(file.getContent().getInputStream(), byteOffset, encoding);
    }

    /**
     * Converts the supplied byte offset in the specified file to the
     * corresponding char offset for that file using the supplied file encoding.
     *
     * @param in InputStream for the file contents.
     * @param byteOffset The byte offset to be converted.
     * @param encoding The encoding of the file.  If null, defaults to utf-8.
     *
     * @return The char offset.
     */
    public static int byteOffsetToCharOffset(InputStream in, int byteOffset, String encoding) throws Exception {
        if (encoding == null) {
            encoding = UTF8;
        }

        BufferedInputStream bin = null;
        try {
            byte[] bytes = new byte[byteOffset];
            bin = new BufferedInputStream(in);
            bin.read(bytes, 0, bytes.length);
            String value = new String(bytes, encoding);

            return value.length();
        } finally {
            IOUtils.closeQuietly(bin);
        }
    }

    /**
     * Converts the supplied char offset into an int array where the first element
     * is the line number and the second is the column number.
     *
     * @param filename The file to translate the offset for.
     * @param offset The offset.
     * @return The line and column int array.
     */
    public static int[] offsetToLineColumn(String filename, int offset) throws Exception {
        FileOffsets offsets = FileOffsets.compile(filename);
        return offsets.offsetToLineColumn(offset);
    }

    /**
     * Converts the supplied char offset into an int array where the first element
     * is the line number and the second is the column number.
     *
     * @param in The InputStream to compile a list of offsets for.
     * @param offset The offset.
     * @return The line and column int array.
     */
    public static int[] offsetToLineColumn(InputStream in, int offset) throws Exception {
        FileOffsets offsets = FileOffsets.compile(in);
        return offsets.offsetToLineColumn(offset);
    }

    /**
     * Obtains a matcher to run the supplied pattern on the specified file.
     *
     * @param pattern The regex pattern
     * @param file The path to the file.
     * @return The Matcher.
     */
    public static Matcher matcher(Pattern pattern, String file) throws Exception {
        FileInputStream is = null;
        try {
            is = new FileInputStream(file);
            String contents = IOUtils.toString(is);
            return pattern.matcher(contents);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    /**
     * Translates a file name that does not conform to the standard url file
     * format.
     * <p/>
     * Main purpose is to convert paths like:<br/>
     * <code>/opt/sun-jdk-1.5.0.05/src.zip/javax/swing/Spring.java</code><br/>
     * to<br/>
     * <code>zip:file:///opt/sun-jdk-1.5.0.05/src.zip!/javax/swing/Spring.java</code>
     *
     * @param file The file to translate.
     * @return The translated file.
     */
    public static String toUrl(String file) {
        file = file.replace('\\', '/');

        // if the path points to a real file, return it.
        if (new File(file).exists()) {
            return file;
        }

        // already an url.
        if (file.startsWith(JAR_PREFIX) || file.startsWith(ZIP_PREFIX)) {
            return file;
        }

        // otherwise do some conversion.
        StringBuffer buffer = new StringBuffer();
        try {
            CompositeName fileName = new CompositeName(file);
            Enumeration<String> names = fileName.getAll();
            while (names.hasMoreElements()) {
                String name = names.nextElement();
                if (name.indexOf("$") != -1) {
                    name = name.substring(0, name.indexOf("$")) + '.' + getExtension(name);
                }
                if (name.length() != 0) {
                    buffer.append('/').append(name);

                    if (!new File(buffer.toString()).exists()) {
                        String path = getFullPath(buffer.toString());
                        if (path.endsWith("/") || path.endsWith("\\")) {
                            path = path.substring(0, path.length() - 1);
                        }
                        if (path.endsWith(JAR_EXT)) {
                            buffer = new StringBuffer(JAR_PREFIX).append(path).append('!').append('/').append(name);
                        } else if (path.endsWith(ZIP_EXT)) {
                            buffer = new StringBuffer(ZIP_PREFIX).append(path).append('!').append('/').append(name);
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return buffer.toString();
    }

    /**
     * Concatenates the given head path with the supplied tail path to form a new
     * path.
     *
     * @param head The head path.
     * @param parts The path parts to concat.
     * @return The concatenated paths.
     */
    public static String concat(String head, String... parts) {
        IPath path = Path.fromOSString(head);
        for (String part : parts) {
            path = path.append(part);
        }
        return path.toOSString().replace('\\', '/');
    }

    /**
     * Gets the base name of the supplied path.
     * <pre>
     * FileUtils.getBaseName("/a/b/c/") :  "c"
     * FileUtils.getBaseName("/a/b/c") :  "c"
     * FileUtils.getBaseName("/a/b/c.txt") :  "c.txt"
     * </pre>
     *
     * @param path The path.
     * @return The base name of the path.
     */
    public static String getBaseName(String path) {
        IPath p = Path.fromOSString(path);
        return p.segment(p.segmentCount() - 1);
    }

    /**
     * Gets the file extension from the supplied path.
     * <pre>
     * FileUtils.getExtension("/a/b/c/") :  ""
     * FileUtils.getExtension("/a/b/c") :  ""
     * FileUtils.getExtension("/a/b/c.txt") :  "txt"
     * </pre>
     *
     * @param path The path.
     * @return The file extension.
     */
    public static String getExtension(String path) {
        String ext = Path.fromOSString(path).getFileExtension();
        if (ext == null) {
            return StringUtils.EMPTY;
        }
        return ext;
    }

    /**
     *
     */
    public static String getPath(String path) {
        IPath p = null;
        int index = path.indexOf(':');
        if (index != -1) {
            p = new Path(path.substring(index + 1));
        } else {
            p = new Path(path);
        }
        if (!p.hasTrailingSeparator()) {
            p = p.uptoSegment(p.segmentCount() - 1);
        }
        return p.makeRelative().addTrailingSeparator().toOSString();
    }

    /**
     * Gets the full path from the supplied path by removing any trailing path
     * segments that do not have a trailing separator.
     * <pre>
     * FileUtils.getFullPath("/a/b/c/") :  "/a/b/c/"
     * FileUtils.getFullPath("/a/b/c") :  "/a/b/"
     * FileUtils.getFullPath("/a/b/c.txt") :  "/a/b/"
     * </pre>
     *
     * @param path The path.
     * @return The full path.
     */
    public static String getFullPath(String path) {
        IPath p = Path.fromOSString(path);
        if (!p.hasTrailingSeparator()) {
            p = p.uptoSegment(p.segmentCount() - 1);
        }
        return p.addTrailingSeparator().toOSString();
    }

    /**
     * Gets the directory path from the supplied path by removing the last path
     * segment.
     * <pre>
     * FileUtils.getDirName("/a/b/c/") :  "/a/b/"
     * FileUtils.getDirName("/a/b/c") :  "/a/b/"
     * FileUtils.getDirName("/a/b/c.txt") :  "/a/b/"
     * </pre>
     *
     * @param path The path.
     * @return The full path.
     */
    public static String getDirName(String path) {
        IPath p = Path.fromOSString(path);
        p = p.uptoSegment(p.segmentCount() - 1);
        return p.addTrailingSeparator().toOSString();
    }

    /**
     * Gets the file name minus the extension from the supplied path.
     * <pre>
     * FileUtils.getFileName("/a/b/c/") :  ""
     * FileUtils.getFileName("/a/b/c") :  "c"
     * FileUtils.getFileName("/a/b/c.txt") :  "c"
     * </pre>
     *
     * @param path The path.
     * @return The file name without the extension.
     */
    public static String getFileName(String path) {
        IPath p = Path.fromOSString(path);
        if (p.hasTrailingSeparator()) {
            return StringUtils.EMPTY;
        }
        return p.removeFileExtension().segment(p.segmentCount() - 1);
    }

    /**
     * Removes the extension from the supplied file name.
     * <pre>
     * FileUtils.removeExtension("/a/b/c/") :  "/a/b/c/"
     * FileUtils.removeExtension("/a/b/c") :  "/a/b/c"
     * FileUtils.removeExtension("/a/b/c.txt") :  "/a/b/c"
     * </pre>
     *
     * @param path The path.
     * @return The path with the extension removed.
     */
    public static String removeExtension(String path) {
        return Path.fromOSString(path).removeFileExtension().toOSString();
    }

    /**
     * Adds the trailing slash if it doesn't exists.
     * <pre>
     * FileUtils.addTrailingSlash("/a/b/c/") :  "/a/b/c/"
     * FileUtils.addTrailingSlash("/a/b/c") :  "/a/b/c/"
     * </pre>
     *
     * @param path The path.
     * @return The path with a trailing slash.
     */
    public static String addTrailingSlash(String path) {
        if (!path.endsWith("/")) {
            return path += '/';
        }
        return path;
    }

    /**
     * Removes the trailing slash if it exists.
     * <pre>
     * FileUtils.removeTrailingSlash("/a/b/c/") :  "/a/b/c"
     * FileUtils.removeTrailingSlash("/a/b/c") :  "/a/b/c"
     * </pre>
     *
     * @param path The path.
     * @return The path with any trialing slash removed.
     */
    public static String removeTrailingSlash(String path) {
        if (path.endsWith("/")) {
            return path.substring(0, path.length() - 1);
        }
        return path;
    }

    /**
     * Convert all path separators for the given path to unix style separators.
     *
     * @param path The path.
     * @return The updated path.
     */
    public static String separatorsToUnix(String path) {
        if (path == null || path.indexOf(WINDOWS_SEPARATOR) == -1) {
            return path;
        }
        return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR);
    }

    /**
     * Deletes a directory and all of its contents.
     *
     * @param dir The directory to delete.
     */
    public static void deleteDirectory(File dir) {
        if (!dir.exists()) {
            return;
        }

        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                deleteDirectory(f);
            } else {
                f.delete();
            }
        }
        dir.delete();
    }
}