/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.smartandroid.sa.zip.commons;
import java.io.File;
/**
* This is a class that has been made significantly smaller (deleted a bunch of
* methods) and originally is from the Apache commons-io package. All license
* and other documentation is intact.
*
* General filename and filepath manipulation utilities.
* <p>
* When dealing with filenames you can hit problems when moving from a Windows
* based development machine to a Unix based production machine. This class aims
* to help avoid those problems.
* <p>
* <b>NOTE</b>: You may be able to avoid using this class entirely simply by
* using JDK {@link java.io.File File} objects and the two argument constructor
* {@link java.io.File#File(java.io.File, java.lang.String) File(File,String)}.
* <p>
* Most methods on this class are designed to work the same on both Unix and
* Windows. Those that don't include 'System', 'Unix' or 'Windows' in their
* name.
* <p>
* Most methods recognise both separators (forward and back), and both sets of
* prefixes. See the javadoc of each method for details.
* <p>
* This class defines six components within a filename (example
* C:\dev\project\file.txt):
* <ul>
* <li>the prefix - C:\</li>
* <li>the path - dev\project\</li>
* <li>the full path - C:\dev\project\</li>
* <li>the name - file.txt</li>
* <li>the base name - file</li>
* <li>the extension - txt</li>
* </ul>
* Note that this class works best if directory filenames end with a separator.
* If you omit the last separator, it is impossible to determine if the filename
* corresponds to a file or a directory. As a result, we have chosen to say it
* corresponds to a file.
* <p>
* This class only supports Unix and Windows style names. Prefixes are matched
* as follows:
*
* <pre>
* 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)
* </pre>
*
* Both prefix styles are matched always, irrespective of the machine that you
* are currently running on.
* <p>
* Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils.
*
* @author <a href="mailto:burton@relativity.yi.org">Kevin A. Burton</A>
* @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
* @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
* @author <a href="mailto:Christoph.Reck@dlr.de">Christoph.Reck</a>
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
* @author Matthew Hawthorne
* @author Martin Cooper
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
* @author Stephen Colebourne
* @version $Id: FilenameUtils.java 609870 2008-01-08 04:46:26Z niallp $
* @since Commons IO 1.1
*/
public class FilenameUtils {
/**
* The extension separator character.
*
* @since Commons IO 1.4
*/
public static final char EXTENSION_SEPARATOR = '.';
/**
* The extension separator String.
*
* @since Commons IO 1.4
*/
public static final String EXTENSION_SEPARATOR_STR = (new Character(
EXTENSION_SEPARATOR)).toString();
/**
* The Unix separator character.
*/
private static final char UNIX_SEPARATOR = '/';
/**
* The Windows separator character.
*/
private static final char WINDOWS_SEPARATOR = '\\';
/**
* The system separator character.
*/
private static final char SYSTEM_SEPARATOR = File.separatorChar;
/**
* Instances should NOT be constructed in standard programming.
*/
public FilenameUtils() {
super();
}
// -----------------------------------------------------------------------
/**
* Determines if Windows file system is in use.
*
* @return true if the system is Windows
*/
static boolean isSystemWindows() {
return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR;
}
// -----------------------------------------------------------------------
/**
* Checks if the character is a separator.
*
* @param ch
* the character to check
* @return true if it is a separator character
*/
private static boolean isSeparator(char ch) {
return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR);
}
// -----------------------------------------------------------------------
/**
* Returns the length of the filename prefix, such as <code>C:/</code> or
* <code>~/</code>.
* <p>
* This method will handle a file in either Unix or Windows format.
* <p>
* 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.
*
* <pre>
* 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)
* </pre>
* <p>
* 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 = filename.length();
if (len == 0) {
return 0;
}
char ch0 = filename.charAt(0);
if (ch0 == ':') {
return -1;
}
if (len == 1) {
if (ch0 == '~') {
return 2; // return a length greater than the input
}
return (isSeparator(ch0) ? 1 : 0);
} else {
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;
}
char ch1 = filename.charAt(1);
if (ch1 == ':') {
ch0 = Character.toUpperCase(ch0);
if (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);
}
}
}
}