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

webit.script.util.UnixStyleFileNameUtil Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
// Copyright (c) 2013, Webit Team. All Rights Reserved.
package webit.script.util;

/**
 *
 * @author Zqq
 */
public class UnixStyleFileNameUtil {

    private static final char UNIX_SEPARATOR = '/';
    private static final char WINDOWS_SEPARATOR = '\\';
    //

    private static boolean isSeparator(char ch) {
        return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR);
    }

    // ---------------------------------------------------------------- normalization
    public static String normalize(String filename) {
        return doNormalize(filename, true);
    }

    public static String normalizeNoEndSeparator(String filename) {
        return doNormalize(filename, false);
    }

    public static String getPath(String filename) {
        if (filename != null) {
            int index;
            return (index = filename.lastIndexOf(UNIX_SEPARATOR)) >= 0
                    ? filename.substring(0, index + 1)
                    : StringPool.EMPTY;
        } else {
            return null;
        }
    }

    public static String concat(String basePath, String fullFilenameToAdd) {
        int prefix;
        int len;
        if (basePath != null) {
            if ((prefix = getPrefixLength(fullFilenameToAdd)) == 0 && (len = basePath.length()) != 0) {
                if (isSeparator(basePath.charAt(len - 1))) {
                    return doNormalize(basePath.concat(fullFilenameToAdd), true);
                } else {
                    return doNormalize(StringUtil.concat(basePath, "/", fullFilenameToAdd), true);
                }
            } else if (prefix > 0) {
                return doNormalize(fullFilenameToAdd, true);
            } else {
                return null;
            }
        }
        return null;
    }

    /**
     * Internal method to perform the normalization.
     *
     * @param filename file name
     * @param separator separator character to use
     * @param keepSeparator true to keep the final separator
     * @return normalized filename
     */
    private static String doNormalize(String filename, boolean keepSeparator) {
        if (filename == null) {
            return null;
        }
        int size = filename.length();
        if (size == 0) {
            return filename;
        }
        int prefix = getPrefixLength(filename);
        if (prefix < 0) {
            return null;
        }

        char[] array = new char[size + 2];  // +1 for possible extra slash, +2 for arraycopy
        filename.getChars(0, filename.length(), array, 0);

        // fix separators throughout
        for (int i = 0; i < array.length; i++) {
            if (array[i] == WINDOWS_SEPARATOR) {
                array[i] = UNIX_SEPARATOR;
            }
        }

        // add extra separator on the end to simplify code below
        boolean lastIsDirectory = true;
        if (array[size - 1] != UNIX_SEPARATOR) {
            array[size++] = UNIX_SEPARATOR;
            lastIsDirectory = false;
        }

        // adjoining slashes
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == UNIX_SEPARATOR && array[i - 1] == UNIX_SEPARATOR) {
                System.arraycopy(array, i, array, i - 1, size - i);
                size--;
                i--;
            }
        }

        // dot slash
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == UNIX_SEPARATOR && array[i - 1] == '.'
                    && (i == prefix + 1 || array[i - 2] == UNIX_SEPARATOR)) {
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                System.arraycopy(array, i + 1, array, i - 1, size - i);
                size -= 2;
                i--;
            }
        }

        // double dot slash
        outer:
        for (int i = prefix + 2; i < size; i++) {
            if (array[i] == UNIX_SEPARATOR && array[i - 1] == '.' && array[i - 2] == '.'
                    && (i == prefix + 2 || array[i - 3] == UNIX_SEPARATOR)) {
                if (i == prefix + 2) {
                    return null;
                }
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                int j;
                for (j = i - 4; j >= prefix; j--) {
                    if (array[j] == UNIX_SEPARATOR) {
                        // remove b/../ from a/b/../c
                        System.arraycopy(array, i + 1, array, j + 1, size - i);
                        size -= (i - j);
                        i = j + 1;
                        continue outer;
                    }
                }
                // remove a/../ from a/../c
                System.arraycopy(array, i + 1, array, prefix, size - i);
                size -= (i + 1 - prefix);
                i = prefix + 1;
            }
        }

        if (size <= 0) {  // should never be less than 0
            return "";
        }
        if (size <= prefix) {  // should never be less than prefix
            return new String(array, 0, size);
        }
        if (lastIsDirectory && keepSeparator) {
            return new String(array, 0, size);  // keep trailing separator
        }
        return new String(array, 0, size - 1);  // lose trailing separator
    }

    // ---------------------------------------------------------------- prefix
    /**
     * Returns the length of the filename prefix, such as C:/ or
     * ~/.
     * 

* This method will handle a file in either Unix or Windows format. *

* The prefix length includes the first slash in the full filename if * applicable. Thus, it is possible that the length returned is greater than * the length of the input string. *

     * Windows:
     * a\b\c.txt           --> ""          --> relative
     * \a\b\c.txt          --> "\"         --> current drive absolute
     * C:a\b\c.txt         --> "C:"        --> drive relative
     * C:\a\b\c.txt        --> "C:\"       --> absolute
     * \\server\a\b\c.txt  --> "\\server\" --> UNC
     *
     * Unix:
     * a/b/c.txt           --> ""          --> relative
     * /a/b/c.txt          --> "/"         --> absolute
     * ~/a/b/c.txt         --> "~/"        --> current user
     * ~                   --> "~/"        --> current user (slash added)
     * ~user/a/b/c.txt     --> "~user/"    --> named user
     * ~user               --> "~user/"    --> named user (slash added)
     * 
*

* The output will be the same irrespective of the machine that the code is * running on. ie. both Unix and Windows prefixes are matched regardless. * * @param filename the filename to find the prefix in, null returns -1 * @return the length of the prefix, -1 if invalid or null */ public static int getPrefixLength(String filename) { if (filename == null) { return -1; } int len; if ((len = filename.length()) == 0) { return 0; } char ch0; if ((ch0 = filename.charAt(0)) == ':') { return -1; } if (len == 1) { // if (ch0 == '~') { // return 2; // return a length greater than the input // } return (isSeparator(ch0) ? 1 : (ch0 == '~' ? 2 : 0)); } else { char ch1; if (ch0 == '~') { int posUnix = filename.indexOf(UNIX_SEPARATOR, 1); int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1); if (posUnix == -1 && posWin == -1) { return len + 1; // return a length greater than the input } posUnix = (posUnix == -1 ? posWin : posUnix); posWin = (posWin == -1 ? posUnix : posWin); return Math.min(posUnix, posWin) + 1; } else if ((ch1 = filename.charAt(1)) == ':') { if ((ch0 >= 'A' && ch0 <= 'Z') || (ch0 >= 'a' && ch0 <= 'z')) { if (len == 2 || isSeparator(filename.charAt(2)) == false) { return 2; } return 3; } return -1; } else if (isSeparator(ch0) && isSeparator(ch1)) { int posUnix = filename.indexOf(UNIX_SEPARATOR, 2); int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2); if ((posUnix == -1 && posWin == -1) || posUnix == 2 || posWin == 2) { return -1; } posUnix = (posUnix == -1 ? posWin : posUnix); posWin = (posWin == -1 ? posUnix : posWin); return Math.min(posUnix, posWin) + 1; } else { return (isSeparator(ch0) ? 1 : 0); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy