org.power.commons.io.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.power.commons.io.FileUtils.java

Source

/*
 *    Copyright (c) 2015 Power Group.
 *     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 org.power.commons.io;

import org.apache.commons.lang3.StringUtils;
import org.power.commons.lang.util.IllegalPathException;

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

/**
 * ???
 *
 * @author Geiger
 */
public class FileUtils {

    // ==========================================================================
    // 
    // ==========================================================================

    private static final Pattern schemePrefixPattern = Pattern
            .compile("(file:/*[a-z]:)|(\\w+://.+?/)|((jar|zip):.+!/)|(\\w+:)", Pattern.CASE_INSENSITIVE);

    /**
     * ?
     * <p>
     * <code>/</code>???
     * </p>
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>?"/"?</li>
     * <li>?".."?</li>
     * </ol>
     *
     * @param path ?
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizeAbsolutePath(String path) throws IllegalPathException {
        return normalizePath(path, true, false, false);
    }

    /**
     * ?
     * <p>
     * <code>/</code>???
     * </p>
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>?"/"?<code>removeTrailingSlash==true</code></li>
     * <li>?".."?</li>
     * </ol>
     *
     * @param path                ?
     * @param removeTrailingSlash ?<code>"/"</code>
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizeAbsolutePath(String path, boolean removeTrailingSlash)
            throws IllegalPathException {
        return normalizePath(path, true, false, removeTrailingSlash);
    }

    /**
     * 
     * <p>
     * ?<code>/</code>??
     * </p>
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>""</li>
     * <li>?"/"?</li>
     * </ol>
     *
     * @param path ?
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizeRelativePath(String path) throws IllegalPathException {
        return normalizePath(path, false, true, false);
    }

    /**
     * 
     * <p>
     * ?<code>/</code>??
     * </p>
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>""</li>
     * <li>?"/"?<code>removeTrailingSlash==true</code></li>
     * </ol>
     *
     * @param path                ?
     * @param removeTrailingSlash ?<code>"/"</code>
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizeRelativePath(String path, boolean removeTrailingSlash)
            throws IllegalPathException {
        return normalizePath(path, false, true, removeTrailingSlash);
    }

    /**
     * 
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>?"/"""</li>
     * <li>?"/"?</li>
     * <li>?".."?</li>
     * </ol>
     *
     * @param path ?
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizePath(String path) throws IllegalPathException {
        return normalizePath(path, false, false, false);
    }

    /**
     * 
     * <ol>
     * <li><code>""</code></li>
     * <li>backslash("\\")?slash("/")</li>
     * <li>??"/""\\"</li>
     * <li>"."?".."?</li>
     * <li>?"/"""</li>
     * <li>?"/"?<code>removeTrailingSlash==true</code></li>
     * <li>?".."?</li>
     * </ol>
     *
     * @param path                ?
     * @param removeTrailingSlash ?<code>"/"</code>
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String normalizePath(String path, boolean removeTrailingSlash) throws IllegalPathException {
        return normalizePath(path, false, false, removeTrailingSlash);
    }

    private static String normalizePath(String path, boolean forceAbsolute, boolean forceRelative,
            boolean removeTrailingSlash) throws IllegalPathException {
        char[] pathChars = StringUtils.trimToEmpty(path).toCharArray();
        int length = pathChars.length;

        // ??path"/"
        boolean startsWithSlash = false;
        boolean endsWithSlash = false;

        if (length > 0) {
            char firstChar = pathChars[0];
            char lastChar = pathChars[length - 1];

            startsWithSlash = firstChar == '/' || firstChar == '\\';
            endsWithSlash = lastChar == '/' || lastChar == '\\';
        }

        StringBuilder buf = new StringBuilder(length);
        boolean isAbsolutePath = forceAbsolute || !forceRelative && startsWithSlash;
        int index = startsWithSlash ? 0 : -1;
        int level = 0;

        if (isAbsolutePath) {
            buf.append("/");
        }

        while (index < length) {
            // ?slash
            index = indexOfSlash(pathChars, index + 1, false);

            if (index == length) {
                break;
            }

            // ?slash index
            int nextSlashIndex = indexOfSlash(pathChars, index, true);

            String element = new String(pathChars, index, nextSlashIndex - index);
            index = nextSlashIndex;

            // "."
            if (".".equals(element)) {
                continue;
            }

            // ".."
            if ("..".equals(element)) {
                if (level == 0) {
                    // ?../??
                    // ?
                    if (isAbsolutePath) {
                        throw new IllegalPathException(path);
                    } else {
                        buf.append("../");
                    }
                } else {
                    buf.setLength(pathChars[--level]);
                }

                continue;
            }

            // path
            pathChars[level++] = (char) buf.length(); // ?charslevelindex
            buf.append(element).append('/');
        }

        // ?"/"
        if (buf.length() > 0) {
            if (!endsWithSlash || removeTrailingSlash) {
                buf.setLength(buf.length() - 1);
            }
        }

        return buf.toString();
    }

    // ==========================================================================
    // ?basedir
    // ==========================================================================

    private static int indexOfSlash(char[] chars, int beginIndex, boolean slash) {
        int i = beginIndex;

        for (; i < chars.length; i++) {
            char ch = chars[i];

            if (slash) {
                if (ch == '/' || ch == '\\') {
                    break; // if a slash
                }
            } else {
                if (ch != '/' && ch != '\\') {
                    break; // if not a slash
                }
            }
        }

        return i;
    }

    /**
     * ?????basedir
     *
     * @param basedir <code>path</code>
     * @param path    ?
     * @return ?
     * @throws IllegalPathException ?
     */
    public static String getAbsolutePathBasedOn(String basedir, String path) throws IllegalPathException {
        // path??
        boolean isAbsolutePath = false;

        path = StringUtils.trimToEmpty(path);

        if (path.length() > 0) {
            char firstChar = path.charAt(0);
            isAbsolutePath = firstChar == '/' || firstChar == '\\';
        }

        if (!isAbsolutePath) {
            // pathbasedir?
            if (path.length() > 0) {
                path = StringUtils.trimToEmpty(basedir) + "/" + path;
            } else {
                path = StringUtils.trimToEmpty(basedir);
            }
        }

        return normalizeAbsolutePath(path);
    }

    // ==========================================================================
    // ?basedir
    // ==========================================================================

    /**
     * ??
     *
     * @throws IllegalPathException basedir??
     */
    public static String getSystemDependentAbsolutePathBasedOn(String basedir, String path) {
        path = StringUtils.trimToEmpty(path);

        boolean endsWithSlash = path.endsWith("/") || path.endsWith("\\");

        File pathFile = new File(path);

        if (pathFile.isAbsolute()) {
            // path??
            path = pathFile.getAbsolutePath();
        } else {
            // ?basedir
            // ??basedir?
            basedir = StringUtils.trimToEmpty(basedir);

            File baseFile = new File(basedir);

            if (baseFile.isAbsolute()) {
                path = new File(baseFile, path).getAbsolutePath();
            } else {
                throw new IllegalPathException("Basedir is not absolute path: " + basedir);
            }
        }

        if (endsWithSlash) {
            path = path + '/';
        }

        return normalizePath(path);
    }

    // ==========================================================================
    // ????
    // ==========================================================================

    /**
     * ?
     *
     * @param basedir 
     * @param path    ?
     * @return <code>path</code><code>basedir</code>
     * <code>basedir</code>?<code>path</code>
     * @throws IllegalPathException ?
     */
    public static String getRelativePath(String basedir, String path) throws IllegalPathException {
        // ?basedir??
        basedir = normalizeAbsolutePath(basedir);

        // ?path
        path = getAbsolutePathBasedOn(basedir, path);

        // ?path"/"
        boolean endsWithSlash = path.endsWith("/");

        // "/"basedirpath
        String[] baseParts = StringUtils.split(basedir, '/');
        String[] parts = StringUtils.split(path, '/');
        StringBuilder buf = new StringBuilder();
        int i = 0;

        while (i < baseParts.length && i < parts.length && baseParts[i].equals(parts[i])) {
            i++;
        }

        if (i < baseParts.length && i < parts.length) {
            for (int j = i; j < baseParts.length; j++) {
                buf.append("..").append('/');
            }
        }

        for (; i < parts.length; i++) {
            buf.append(parts[i]);

            if (i < parts.length - 1) {
                buf.append('/');
            }
        }

        if (endsWithSlash && buf.length() > 0 && buf.charAt(buf.length() - 1) != '/') {
            buf.append('/');
        }

        return buf.toString();
    }

    /**
     * ??
     * <ul>
     * <li>?? - <code>null</code></li>
     * <li>??? - <code>null</code></li>
     * </ul>
     */
    public static String getExtension(String fileName) {
        return getExtension(fileName, null, false);
    }

    /**
     * ??
     * <ul>
     * <li>?? - <code>null</code></li>
     * <li>??? - <code>null</code></li>
     * </ul>
     */
    public static String getExtension(String fileName, boolean toLowerCase) {
        return getExtension(fileName, null, toLowerCase);
    }

    /**
     * ??
     * <ul>
     * <li>?? - <code>null</code></li>
     * <li>??? - <code>nullExt</code></li>
     * </ul>
     */
    public static String getExtension(String fileName, String nullExt) {
        return getExtension(fileName, nullExt, false);
    }

    /**
     * ??
     * <ul>
     * <li>?? - <code>null</code></li>
     * <li>??? - <code>nullExt</code></li>
     * </ul>
     */
    public static String getExtension(String fileName, String nullExt, boolean toLowerCase) {
        fileName = StringUtils.trimToNull(fileName);

        if (fileName == null) {
            return null;
        }

        fileName = fileName.replace('\\', '/');
        fileName = fileName.substring(fileName.lastIndexOf("/") + 1);

        int index = fileName.lastIndexOf(".");
        String ext = null;

        if (index >= 0) {
            ext = StringUtils.trimToNull(fileName.substring(index + 1));
        }

        if (ext == null) {
            return nullExt;
        } else {
            return toLowerCase ? ext.toLowerCase() : ext;
        }
    }

    /**
     * ????
     *
     * @param path 
     * @return ?
     */
    public static FileNameAndExtension getFileNameAndExtension(String path) {
        return getFileNameAndExtension(path, false);
    }

    /**
     * ????
     *
     * @param path 
     * @return ?
     */
    public static FileNameAndExtension getFileNameAndExtension(String path, boolean extensionToLowerCase) {
        path = StringUtils.trimToEmpty(path);

        String fileName = path;
        String extension = null;

        if (!StringUtils.isEmpty(path)) {
            // ?index >= 0extension != null?name.
            int index = path.lastIndexOf('.');

            if (index >= 0) {
                extension = StringUtils.trimToNull(StringUtils.substring(path, index + 1));

                if (!StringUtils.containsNone(extension, "/\\")) {
                    extension = null;
                    index = -1;
                }
            }

            if (index >= 0) {
                fileName = StringUtils.substring(path, 0, index);
            }
        }

        return new FileNameAndExtension(fileName, extension, extensionToLowerCase);
    }

    /**
     * ???
     * <ul>
     * <li></li>
     * <li>??</li>
     * <li><code>.</code>?</li>
     * <li>?<code>null</code></li>
     * </ul>
     */
    public static String normalizeExtension(String ext) {
        ext = StringUtils.trimToNull(ext);

        if (ext != null) {
            ext = ext.toLowerCase();

            if (ext.startsWith(".")) {
                ext = StringUtils.trimToNull(ext.substring(1));
            }
        }

        return ext;
    }

    /**
     * ?urlurl<code>URI.resolve()</code>
     * ????jarURL
     */
    public static String resolve(String url, String relativePath) {
        url = StringUtils.trimToEmpty(url);

        Matcher m = schemePrefixPattern.matcher(url);
        int index = 0;

        if (m.find()) {
            index = m.end();

            if (url.charAt(index - 1) == '/') {
                index--;
            }
        }

        return url.substring(0, index) + normalizeAbsolutePath(url.substring(index) + "/../" + relativePath);
    }

    public static class FileNameAndExtension {
        private final String fileName;
        private final String extension;

        private FileNameAndExtension(String fileName, String extension, boolean extensionToLowerCase) {
            this.fileName = fileName;
            this.extension = extensionToLowerCase ? extension.toLowerCase() : extension;
        }

        public String getFileName() {
            return fileName;
        }

        public String getExtension() {
            return extension;
        }

        @Override
        public String toString() {
            return extension == null ? fileName : fileName + "." + extension;
        }
    }
}