14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/* 24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one or more 34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * contributor license agreements. See the NOTICE file distributed with 44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this work for additional information regarding copyright ownership. 54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The ASF licenses this file to You under the Apache License, Version 2.0 64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (the "License"); you may not use this file except in compliance with 74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the License. You may obtain a copy of the License at 84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, software 124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See the License for the specific language governing permissions and 154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * limitations under the License. 164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.commons.io; 184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.File; 204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.ArrayList; 214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.Collection; 224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.Iterator; 234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.Stack; 244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/** 264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * General filename and filepath manipulation utilities. 274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * When dealing with filenames you can hit problems when moving from a Windows 294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * based development machine to a Unix based production machine. 304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This class aims to help avoid those problems. 314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <b>NOTE</b>: You may be able to avoid using this class entirely simply by 334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * using JDK {@link java.io.File File} objects and the two argument constructor 344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * {@link java.io.File#File(java.io.File, java.lang.String) File(File,String)}. 354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Most methods on this class are designed to work the same on both Unix and Windows. 374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Those that don't include 'System', 'Unix' or 'Windows' in their name. 384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Most methods recognise both separators (forward and back), and both 404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * sets of prefixes. See the javadoc of each method for details. 414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This class defines six components within a filename 434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (example C:\dev\project\file.txt): 444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <ul> 454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the prefix - C:\</li> 464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the path - dev\project\</li> 474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the full path - C:\dev\project\</li> 484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the name - file.txt</li> 494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the base name - file</li> 504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <li>the extension - txt</li> 514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </ul> 524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Note that this class works best if directory filenames end with a separator. 534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If you omit the last separator, it is impossible to determine if the filename 544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * corresponds to a file or a directory. As a result, we have chosen to say 554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * it corresponds to a file. 564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This class only supports Unix and Windows style names. 584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Prefixes are matched as follows: 594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Windows: 614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a\b\c.txt --> "" --> relative 624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \a\b\c.txt --> "\" --> current drive absolute 634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:a\b\c.txt --> "C:" --> drive relative 644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> "C:\" --> absolute 654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \\server\a\b\c.txt --> "\\server\" --> UNC 664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unix: 684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.txt --> "" --> relative 694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /a/b/c.txt --> "/" --> absolute 704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> "~/" --> current user 714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~ --> "~/" --> current user (slash added) 724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user/a/b/c.txt --> "~user/" --> named user 734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user --> "~user/" --> named user (slash added) 744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Both prefix styles are matched always, irrespective of the machine that you are 764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * currently running on. 774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils. 794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:burton@relativity.yi.org">Kevin A. Burton</A> 814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> 824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph.Reck</a> 844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:peter@apache.org">Peter Donald</a> 854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:jefft@apache.org">Jeff Turner</a> 864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Matthew Hawthorne 874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Martin Cooper 884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> 894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Stephen Colebourne 904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: FilenameUtils.java 609870 2008-01-08 04:46:26Z niallp $ 914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.1 924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class FilenameUtils { 944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The extension separator character. 974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.4 984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static final char EXTENSION_SEPARATOR = '.'; 1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The extension separator String. 1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.4 1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static final String EXTENSION_SEPARATOR_STR = (new Character(EXTENSION_SEPARATOR)).toString(); 1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The Unix separator character. 1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final char UNIX_SEPARATOR = '/'; 1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The Windows separator character. 1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final char WINDOWS_SEPARATOR = '\\'; 1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The system separator character. 1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final char SYSTEM_SEPARATOR = File.separatorChar; 1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The separator character that is the opposite of the system separator. 1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final char OTHER_SEPARATOR; 1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy static { 1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (isSystemWindows()) { 1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy OTHER_SEPARATOR = UNIX_SEPARATOR; 1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy OTHER_SEPARATOR = WINDOWS_SEPARATOR; 1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Instances should NOT be constructed in standard programming. 1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public FilenameUtils() { 1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy super(); 1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Determines if Windows file system is in use. 1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the system is Windows 1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy static boolean isSystemWindows() { 1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR; 1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks if the character is a separator. 1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param ch the character to check 1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if it is a separator character 1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static boolean isSeparator(char ch) { 1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR); 1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Normalizes a path, removing double and single dot path steps. 1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method normalizes a path to a standard format. 1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The input may contain separators in either Unix or Windows format. 1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will contain separators in the format of the system. 1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A trailing slash will be retained. 1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A double slash will be merged to a single slash (but UNC names are handled). 1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A single dot path segment will be removed. 1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A double dot will cause that path segment and the one before to be removed. 1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If the double dot has no parent path segment to work with, <code>null</code> 1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * is returned. 1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same on both Unix and Windows except 1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * for the separator character. 1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo// --> /foo/ 1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/./ --> /foo/ 1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar --> /bar 1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar/ --> /bar/ 1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar/../baz --> /baz 1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //foo//./bar --> /foo/bar 1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /../ --> null 1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ../foo --> null 1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/bar/.. --> foo/ 1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/../../bar --> null 1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/../bar --> bar 1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //server/foo/../bar --> //server/bar 1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //server/../bar --> null 1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\foo\..\bar --> C:\bar 1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\..\bar --> null 1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/foo/../bar/ --> ~/bar/ 1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/../bar --> null 1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (Note the file separator returned will be correct for Windows/Unix) 1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to normalize, null returns null 2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the normalized filename, or null if invalid 2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String normalize(String filename) { 2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doNormalize(filename, true); 2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Normalizes a path, removing double and single dot path steps, 2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * and removing any final directory separator. 2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method normalizes a path to a standard format. 2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The input may contain separators in either Unix or Windows format. 2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will contain separators in the format of the system. 2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A trailing slash will be removed. 2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A double slash will be merged to a single slash (but UNC names are handled). 2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A single dot path segment will be removed. 2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A double dot will cause that path segment and the one before to be removed. 2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If the double dot has no parent path segment to work with, <code>null</code> 2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * is returned. 2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same on both Unix and Windows except 2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * for the separator character. 2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo// --> /foo 2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/./ --> /foo 2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar --> /bar 2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar/ --> /bar 2304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/../bar/../baz --> /baz 2314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //foo//./bar --> /foo/bar 2324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /../ --> null 2334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ../foo --> null 2344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/bar/.. --> foo 2354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/../../bar --> null 2364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo/../bar --> bar 2374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //server/foo/../bar --> //server/bar 2384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * //server/../bar --> null 2394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\foo\..\bar --> C:\bar 2404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\..\bar --> null 2414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/foo/../bar/ --> ~/bar 2424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/../bar --> null 2434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 2444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (Note the file separator returned will be correct for Windows/Unix) 2454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to normalize, null returns null 2474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the normalized filename, or null if invalid 2484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String normalizeNoEndSeparator(String filename) { 2504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doNormalize(filename, false); 2514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Internal method to perform the normalization. 2554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename 2574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param keepSeparator true to keep the final separator 2584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the normalized filename 2594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static String doNormalize(String filename, boolean keepSeparator) { 2614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 2624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 2634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int size = filename.length(); 2654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (size == 0) { 2664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename; 2674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int prefix = getPrefixLength(filename); 2694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix < 0) { 2704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 2714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy 2744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filename.getChars(0, filename.length(), array, 0); 2754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // fix separators throughout 2774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = 0; i < array.length; i++) { 2784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == OTHER_SEPARATOR) { 2794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy array[i] = SYSTEM_SEPARATOR; 2804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // add extra separator on the end to simplify code below 2844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy boolean lastIsDirectory = true; 2854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[size - 1] != SYSTEM_SEPARATOR) { 2864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy array[size++] = SYSTEM_SEPARATOR; 2874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lastIsDirectory = false; 2884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // adjoining slashes 2914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = prefix + 1; i < size; i++) { 2924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == SYSTEM_SEPARATOR) { 2934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(array, i, array, i - 1, size - i); 2944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy size--; 2954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy i--; 2964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // dot slash 3004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = prefix + 1; i < size; i++) { 3014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' && 3024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy (i == prefix + 1 || array[i - 2] == SYSTEM_SEPARATOR)) { 3034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (i == size - 1) { 3044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lastIsDirectory = true; 3054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(array, i + 1, array, i - 1, size - i); 3074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy size -=2; 3084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy i--; 3094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // double dot slash 3134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy outer: 3144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = prefix + 2; i < size; i++) { 3154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == SYSTEM_SEPARATOR && array[i - 1] == '.' && array[i - 2] == '.' && 3164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy (i == prefix + 2 || array[i - 3] == SYSTEM_SEPARATOR)) { 3174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (i == prefix + 2) { 3184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 3194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (i == size - 1) { 3214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy lastIsDirectory = true; 3224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int j; 3244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (j = i - 4 ; j >= prefix; j--) { 3254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[j] == SYSTEM_SEPARATOR) { 3264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // remove b/../ from a/b/../c 3274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(array, i + 1, array, j + 1, size - i); 3284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy size -= (i - j); 3294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy i = j + 1; 3304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy continue outer; 3314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // remove a/../ from a/../c 3344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(array, i + 1, array, prefix, size - i); 3354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy size -= (i + 1 - prefix); 3364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy i = prefix + 1; 3374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (size <= 0) { // should never be less than 0 3414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return ""; 3424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (size <= prefix) { // should never be less than prefix 3444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String(array, 0, size); 3454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (lastIsDirectory && keepSeparator) { 3474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String(array, 0, size); // keep trailing separator 3484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String(array, 0, size - 1); // lose trailing separator 3504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 3534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 3544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Concatenates a filename to a base path using normal command line style rules. 3554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 3564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The effect is equivalent to resultant directory after changing 3574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * directory to the first argument, followed by changing directory to 3584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the second argument. 3594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 3604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The first argument is the base path, the second is the path to concatenate. 3614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The returned path is always normalized via {@link #normalize(String)}, 3624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * thus <code>..</code> is handled. 3634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 3644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If <code>pathToAdd</code> is absolute (has an absolute prefix), then 3654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * it will be normalized and returned. 3664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Otherwise, the paths will be joined, normalized and returned. 3674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 3684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same on both Unix and Windows except 3694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * for the separator character. 3704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 3714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/ + bar --> /foo/bar 3724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo + bar --> /foo/bar 3734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo + /bar --> /bar 3744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo + C:/bar --> C:/bar 3754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo + C:bar --> C:bar (*) 3764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/a/ + ../bar --> foo/bar 3774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/ + ../../bar --> null 3784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/ + /bar --> /bar 3794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/.. + /bar --> /bar 3804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo + bar/c.txt --> /foo/bar/c.txt 3814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /foo/c.txt + bar --> /foo/c.txt/bar (!) 3824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 3834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (*) Note that the Windows relative drive prefix is unreliable when 3844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * used with this method. 3854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (!) Note that the first parameter must be a path. If it ends with a name, then 3864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the name will be built into the concatenated path. If this might be a problem, 3874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * use {@link #getFullPath(String)} on the base path argument. 3884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 3894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param basePath the base path to attach to, always treated as a path 3904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param fullFilenameToAdd the filename (or path) to attach to the base 3914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the concatenated path, or null if invalid 3924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String concat(String basePath, String fullFilenameToAdd) { 3944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int prefix = getPrefixLength(fullFilenameToAdd); 3954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix < 0) { 3964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 3974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix > 0) { 3994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return normalize(fullFilenameToAdd); 4004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (basePath == null) { 4024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 4034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int len = basePath.length(); 4054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len == 0) { 4064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return normalize(fullFilenameToAdd); 4074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy char ch = basePath.charAt(len - 1); 4094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (isSeparator(ch)) { 4104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return normalize(basePath + fullFilenameToAdd); 4114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 4124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return normalize(basePath + '/' + fullFilenameToAdd); 4134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 4164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 4174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 4184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Converts all separators to the Unix separator of forward slash. 4194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 4204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param path the path to be changed, null ignored 4214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the updated path 4224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 4234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String separatorsToUnix(String path) { 4244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (path == null || path.indexOf(WINDOWS_SEPARATOR) == -1) { 4254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return path; 4264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); 4284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 4304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 4314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Converts all separators to the Windows separator of backslash. 4324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 4334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param path the path to be changed, null ignored 4344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the updated path 4354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 4364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String separatorsToWindows(String path) { 4374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (path == null || path.indexOf(UNIX_SEPARATOR) == -1) { 4384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return path; 4394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return path.replace(UNIX_SEPARATOR, WINDOWS_SEPARATOR); 4414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 4434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 4444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Converts all separators to the system separator. 4454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 4464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param path the path to be changed, null ignored 4474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the updated path 4484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 4494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String separatorsToSystem(String path) { 4504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (path == null) { 4514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 4524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (isSystemWindows()) { 4544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return separatorsToWindows(path); 4554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 4564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return separatorsToUnix(path); 4574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 4604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 4614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 4624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Returns the length of the filename prefix, such as <code>C:/</code> or <code>~/</code>. 4634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 4644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 4654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 4664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The prefix length includes the first slash in the full filename 4674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * if applicable. Thus, it is possible that the length returned is greater 4684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * than the length of the input string. 4694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 4704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Windows: 4714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a\b\c.txt --> "" --> relative 4724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \a\b\c.txt --> "\" --> current drive absolute 4734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:a\b\c.txt --> "C:" --> drive relative 4744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> "C:\" --> absolute 4754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \\server\a\b\c.txt --> "\\server\" --> UNC 4764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 4774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unix: 4784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.txt --> "" --> relative 4794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /a/b/c.txt --> "/" --> absolute 4804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> "~/" --> current user 4814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~ --> "~/" --> current user (slash added) 4824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user/a/b/c.txt --> "~user/" --> named user 4834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user --> "~user/" --> named user (slash added) 4844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 4854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 4864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 4874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ie. both Unix and Windows prefixes are matched regardless. 4884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 4894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to find the prefix in, null returns -1 4904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the length of the prefix, -1 if invalid or null 4914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 4924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static int getPrefixLength(String filename) { 4934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 4944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 4954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 4964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int len = filename.length(); 4974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len == 0) { 4984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return 0; 4994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy char ch0 = filename.charAt(0); 5014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (ch0 == ':') { 5024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 5034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len == 1) { 5054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (ch0 == '~') { 5064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return 2; // return a length greater than the input 5074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (isSeparator(ch0) ? 1 : 0); 5094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 5104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (ch0 == '~') { 5114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int posUnix = filename.indexOf(UNIX_SEPARATOR, 1); 5124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1); 5134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (posUnix == -1 && posWin == -1) { 5144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return len + 1; // return a length greater than the input 5154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy posUnix = (posUnix == -1 ? posWin : posUnix); 5174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy posWin = (posWin == -1 ? posUnix : posWin); 5184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return Math.min(posUnix, posWin) + 1; 5194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy char ch1 = filename.charAt(1); 5214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (ch1 == ':') { 5224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ch0 = Character.toUpperCase(ch0); 5234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (ch0 >= 'A' && ch0 <= 'Z') { 5244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len == 2 || isSeparator(filename.charAt(2)) == false) { 5254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return 2; 5264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return 3; 5284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 5304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 5314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (isSeparator(ch0) && isSeparator(ch1)) { 5324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int posUnix = filename.indexOf(UNIX_SEPARATOR, 2); 5334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2); 5344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if ((posUnix == -1 && posWin == -1) || posUnix == 2 || posWin == 2) { 5354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 5364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy posUnix = (posUnix == -1 ? posWin : posUnix); 5384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy posWin = (posWin == -1 ? posUnix : posWin); 5394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return Math.min(posUnix, posWin) + 1; 5404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 5414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (isSeparator(ch0) ? 1 : 0); 5424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 5464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 5474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Returns the index of the last directory separator character. 5484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 5494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 5504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The position of the last forward or backslash is returned. 5514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 5524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 5534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 5544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to find the last path separator in, null returns -1 5554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the index of the last separator character, or -1 if there 5564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * is no such character 5574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 5584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static int indexOfLastSeparator(String filename) { 5594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 5604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 5614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR); 5634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR); 5644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return Math.max(lastUnixPos, lastWindowsPos); 5654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 5674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 5684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Returns the index of the last extension separator character, which is a dot. 5694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 5704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method also checks that there is no directory separator after the last dot. 5714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * To do this it uses {@link #indexOfLastSeparator(String)} which will 5724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * handle a file in either Unix or Windows format. 5734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 5744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 5754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 5764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to find the last path separator in, null returns -1 5774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the index of the last separator character, or -1 if there 5784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * is no such character 5794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 5804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static int indexOfExtension(String filename) { 5814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 5824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 5834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR); 5854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int lastSeparator = indexOfLastSeparator(filename); 5864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (lastSeparator > extensionPos ? -1 : extensionPos); 5874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 5884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 5894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 5904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 5914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the prefix from a full filename, such as <code>C:/</code> 5924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * or <code>~/</code>. 5934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 5944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 5954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The prefix includes the first slash in the full filename where applicable. 5964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 5974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Windows: 5984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a\b\c.txt --> "" --> relative 5994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \a\b\c.txt --> "\" --> current drive absolute 6004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:a\b\c.txt --> "C:" --> drive relative 6014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> "C:\" --> absolute 6024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * \\server\a\b\c.txt --> "\\server\" --> UNC 6034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 6044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unix: 6054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.txt --> "" --> relative 6064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * /a/b/c.txt --> "/" --> absolute 6074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> "~/" --> current user 6084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~ --> "~/" --> current user (slash added) 6094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user/a/b/c.txt --> "~user/" --> named user 6104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user --> "~user/" --> named user (slash added) 6114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 6124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 6144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ie. both Unix and Windows prefixes are matched regardless. 6154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 6164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 6174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the prefix of the file, null if invalid 6184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 6194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getPrefix(String filename) { 6204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 6214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 6224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int len = getPrefixLength(filename); 6244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len < 0) { 6254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 6264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (len > filename.length()) { 6284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename + UNIX_SEPARATOR; // we know this only happens for unix 6294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(0, len); 6314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 6334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 6344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the path from a full filename, which excludes the prefix. 6354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 6374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The method is entirely text based, and returns the text before and 6384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * including the last forward or backslash. 6394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 6404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> a\b\ 6414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> a/b/ 6424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> "" 6434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> a/b/ 6444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> a/b/c/ 6454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 6464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 6484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method drops the prefix from the result. 6504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See {@link #getFullPath(String)} for the method that retains the prefix. 6514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 6524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 6534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path of the file, an empty string if none exists, null if invalid 6544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 6554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getPath(String filename) { 6564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doGetPath(filename, 1); 6574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 6594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 6604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the path from a full filename, which excludes the prefix, and 6614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * also excluding the final directory separator. 6624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 6644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The method is entirely text based, and returns the text before the 6654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * last forward or backslash. 6664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 6674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> a\b 6684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> a/b 6694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> "" 6704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> a/b 6714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> a/b/c 6724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 6734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 6754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 6764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method drops the prefix from the result. 6774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix. 6784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 6794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 6804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path of the file, an empty string if none exists, null if invalid 6814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 6824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getPathNoEndSeparator(String filename) { 6834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doGetPath(filename, 0); 6844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 6864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 6874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Does the work of getting the path. 6884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 6894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename 6904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param separatorAdd 0 to omit the end separator, 1 to return it 6914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path 6924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 6934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static String doGetPath(String filename, int separatorAdd) { 6944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 6954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 6964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 6974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int prefix = getPrefixLength(filename); 6984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix < 0) { 6994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 7004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int index = indexOfLastSeparator(filename); 7024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix >= filename.length() || index < 0) { 7034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return ""; 7044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(prefix, index + separatorAdd); 7064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 7084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 7094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the full path from a full filename, which is the prefix + path. 7104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 7114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 7124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The method is entirely text based, and returns the text before and 7134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * including the last forward or backslash. 7144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 7154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> C:\a\b\ 7164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> ~/a/b/ 7174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> "" 7184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> a/b/ 7194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> a/b/c/ 7204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C: --> C: 7214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\ --> C:\ 7224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~ --> ~/ 7234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/ --> ~/ 7244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user --> ~user/ 7254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user/ --> ~user/ 7264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 7274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 7284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 7294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 7304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 7314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path of the file, an empty string if none exists, null if invalid 7324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 7334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getFullPath(String filename) { 7344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doGetFullPath(filename, true); 7354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 7374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 7384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the full path from a full filename, which is the prefix + path, 7394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * and also excluding the final directory separator. 7404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 7414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 7424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The method is entirely text based, and returns the text before the 7434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * last forward or backslash. 7444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 7454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\a\b\c.txt --> C:\a\b 7464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/a/b/c.txt --> ~/a/b 7474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> "" 7484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> a/b 7494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> a/b/c 7504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C: --> C: 7514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * C:\ --> C:\ 7524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~ --> ~ 7534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~/ --> ~ 7544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user --> ~user 7554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * ~user/ --> ~user 7564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 7574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 7584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 7594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 7604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 7614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path of the file, an empty string if none exists, null if invalid 7624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 7634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getFullPathNoEndSeparator(String filename) { 7644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return doGetFullPath(filename, false); 7654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 7674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 7684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Does the work of getting the path. 7694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 7704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename 7714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param includeSeparator true to include the end separator 7724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the path 7734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 7744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static String doGetFullPath(String filename, boolean includeSeparator) { 7754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 7764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 7774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int prefix = getPrefixLength(filename); 7794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix < 0) { 7804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 7814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (prefix >= filename.length()) { 7834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (includeSeparator) { 7844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return getPrefix(filename); // add end slash if necessary 7854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 7864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename; 7874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int index = indexOfLastSeparator(filename); 7904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (index < 0) { 7914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(0, prefix); 7924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int end = index + (includeSeparator ? 1 : 0); 7944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(0, end); 7954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 7964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 7974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 7984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the name minus the path from a full filename. 7994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 8014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The text after the last forward or backslash is returned. 8024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 8034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.txt --> c.txt 8044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> a.txt 8054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> c 8064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> "" 8074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 8084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 8104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 8114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 8124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the name of the file without the path, or an empty string if none exists 8134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 8144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getName(String filename) { 8154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 8164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 8174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int index = indexOfLastSeparator(filename); 8194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(index + 1); 8204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 8224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 8234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the base name, minus the full path and extension, from a full filename. 8244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method will handle a file in either Unix or Windows format. 8264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The text after the last forward or backslash and before the last dot is returned. 8274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 8284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.txt --> c 8294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.txt --> a 8304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> c 8314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c/ --> "" 8324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 8334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 8354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 8364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 8374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the name of the file without the path, or an empty string if none exists 8384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 8394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getBaseName(String filename) { 8404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return removeExtension(getName(filename)); 8414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 8434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 8444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the extension of a filename. 8454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method returns the textual part of the filename after the last dot. 8474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * There must be no directory separator after the dot. 8484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 8494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo.txt --> "txt" 8504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c.jpg --> "jpg" 8514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b.txt/c --> "" 8524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a/b/c --> "" 8534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 8544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 8564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 8574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to retrieve the extension of. 8584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the extension of the file or an empty string if none exists. 8594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 8604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String getExtension(String filename) { 8614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 8624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 8634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int index = indexOfExtension(filename); 8654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (index == -1) { 8664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return ""; 8674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 8684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(index + 1); 8694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 8724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 8734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 8744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Removes the extension from a filename. 8754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method returns the textual part of the filename before the last dot. 8774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * There must be no directory separator after the dot. 8784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 8794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * foo.txt --> foo 8804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a\b\c.jpg --> a\b\c 8814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a\b\c --> a\b\c 8824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a.b\c --> a.b\c 8834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 8844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 8854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The output will be the same irrespective of the machine that the code is running on. 8864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 8874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns null 8884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the filename minus the extension 8894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 8904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static String removeExtension(String filename) { 8914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 8924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return null; 8934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 8944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int index = indexOfExtension(filename); 8954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (index == -1) { 8964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename; 8974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 8984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename.substring(0, index); 8994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 9034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 9044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether two filenames are equal exactly. 9054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 9064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * No processing is performed on the filenames other than comparison, 9074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * thus this is merely a null-safe case-sensitive equals. 9084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 9094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename1 the first filename to query, may be null 9104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename2 the second filename to query, may be null 9114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filenames are equal, null equals null 9124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SENSITIVE 9134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 9144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean equals(String filename1, String filename2) { 9154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return equals(filename1, filename2, false, IOCase.SENSITIVE); 9164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 9194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether two filenames are equal using the case rules of the system. 9204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 9214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * No processing is performed on the filenames other than comparison. 9224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The check is case-sensitive on Unix and case-insensitive on Windows. 9234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 9244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename1 the first filename to query, may be null 9254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename2 the second filename to query, may be null 9264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filenames are equal, null equals null 9274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SYSTEM 9284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 9294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean equalsOnSystem(String filename1, String filename2) { 9304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return equals(filename1, filename2, false, IOCase.SYSTEM); 9314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 9344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 9354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether two filenames are equal after both have been normalized. 9364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 9374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Both filenames are first passed to {@link #normalize(String)}. 9384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The check is then performed in a case-sensitive manner. 9394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 9404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename1 the first filename to query, may be null 9414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename2 the second filename to query, may be null 9424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filenames are equal, null equals null 9434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SENSITIVE 9444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 9454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean equalsNormalized(String filename1, String filename2) { 9464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return equals(filename1, filename2, true, IOCase.SENSITIVE); 9474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 9504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether two filenames are equal after both have been normalized 9514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * and using the case rules of the system. 9524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 9534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Both filenames are first passed to {@link #normalize(String)}. 9544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The check is then performed case-sensitive on Unix and 9554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * case-insensitive on Windows. 9564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 9574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename1 the first filename to query, may be null 9584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename2 the second filename to query, may be null 9594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filenames are equal, null equals null 9604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SYSTEM 9614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 9624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean equalsNormalizedOnSystem(String filename1, String filename2) { 9634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return equals(filename1, filename2, true, IOCase.SYSTEM); 9644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 9674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether two filenames are equal, optionally normalizing and providing 9684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * control over the case-sensitivity. 9694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 9704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename1 the first filename to query, may be null 9714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename2 the second filename to query, may be null 9724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param normalized whether to normalize the filenames 9734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive 9744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filenames are equal, null equals null 9754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.3 9764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 9774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean equals( 9784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String filename1, String filename2, 9794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy boolean normalized, IOCase caseSensitivity) { 9804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename1 == null || filename2 == null) { 9824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return filename1 == filename2; 9834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (normalized) { 9854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filename1 = normalize(filename1); 9864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filename2 = normalize(filename2); 9874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename1 == null || filename2 == null) { 9884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new NullPointerException( 9894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy "Error normalizing one or both of the file names"); 9904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (caseSensitivity == null) { 9934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy caseSensitivity = IOCase.SENSITIVE; 9944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return caseSensitivity.checkEquals(filename1, filename2); 9964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 9974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 9984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 9994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 10004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether the extension of the filename is that specified. 10014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 10024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method obtains the extension as the textual part of the filename 10034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * after the last dot. There must be no directory separator after the dot. 10044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The extension check is case-sensitive on all platforms. 10054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 10064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns false 10074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param extension the extension to check for, null or empty checks for no extension 10084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename has the specified extension 10094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 10104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean isExtension(String filename, String extension) { 10114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 10124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 10134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (extension == null || extension.length() == 0) { 10154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (indexOfExtension(filename) == -1); 10164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String fileExt = getExtension(filename); 10184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return fileExt.equals(extension); 10194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 10214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 10224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether the extension of the filename is one of those specified. 10234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 10244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method obtains the extension as the textual part of the filename 10254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * after the last dot. There must be no directory separator after the dot. 10264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The extension check is case-sensitive on all platforms. 10274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 10284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns false 10294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param extensions the extensions to check for, null checks for no extension 10304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename is one of the extensions 10314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 10324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean isExtension(String filename, String[] extensions) { 10334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 10344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 10354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (extensions == null || extensions.length == 0) { 10374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (indexOfExtension(filename) == -1); 10384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String fileExt = getExtension(filename); 10404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = 0; i < extensions.length; i++) { 10414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (fileExt.equals(extensions[i])) { 10424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return true; 10434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 10464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 10484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 10494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks whether the extension of the filename is one of those specified. 10504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 10514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This method obtains the extension as the textual part of the filename 10524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * after the last dot. There must be no directory separator after the dot. 10534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The extension check is case-sensitive on all platforms. 10544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 10554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to query, null returns false 10564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param extensions the extensions to check for, null checks for no extension 10574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename is one of the extensions 10584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 10594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean isExtension(String filename, Collection<String> extensions) { 10604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null) { 10614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 10624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (extensions == null || extensions.isEmpty()) { 10644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (indexOfExtension(filename) == -1); 10654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String fileExt = getExtension(filename); 10674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (Iterator<String> it = extensions.iterator(); it.hasNext();) { 10684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (fileExt.equals(it.next())) { 10694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return true; 10704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 10734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 10744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 10754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //----------------------------------------------------------------------- 10764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 10774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks a filename to see if it matches the specified wildcard matcher, 10784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * always testing case-sensitive. 10794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 10804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The wildcard matcher uses the characters '?' and '*' to represent a 10814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * single or multiple wildcard characters. 10824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This is the same as often found on Dos/Unix command lines. 10834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The check is case-sensitive always. 10844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 10854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.txt") --> true 10864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.jpg") --> false 10874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("a/b/c.txt", "a/b/*") --> true 10884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.???") --> true 10894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.????") --> false 10904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 10914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 10924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to match on 10934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param wildcardMatcher the wildcard string to match against 10944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename matches the wilcard string 10954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SENSITIVE 10964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 10974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean wildcardMatch(String filename, String wildcardMatcher) { 10984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return wildcardMatch(filename, wildcardMatcher, IOCase.SENSITIVE); 10994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 11024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks a filename to see if it matches the specified wildcard matcher 11034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * using the case rules of the system. 11044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 11054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The wildcard matcher uses the characters '?' and '*' to represent a 11064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * single or multiple wildcard characters. 11074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This is the same as often found on Dos/Unix command lines. 11084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The check is case-sensitive on Unix and case-insensitive on Windows. 11094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre> 11104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.txt") --> true 11114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.jpg") --> false 11124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("a/b/c.txt", "a/b/*") --> true 11134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.???") --> true 11144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * wildcardMatch("c.txt", "*.????") --> false 11154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre> 11164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 11174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to match on 11184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param wildcardMatcher the wildcard string to match against 11194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename matches the wilcard string 11204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see IOCase#SYSTEM 11214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 11224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean wildcardMatchOnSystem(String filename, String wildcardMatcher) { 11234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return wildcardMatch(filename, wildcardMatcher, IOCase.SYSTEM); 11244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 11274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Checks a filename to see if it matches the specified wildcard matcher 11284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * allowing control over case-sensitivity. 11294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 11304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The wildcard matcher uses the characters '?' and '*' to represent a 11314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * single or multiple wildcard characters. 11324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 11334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param filename the filename to match on 11344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param wildcardMatcher the wildcard string to match against 11354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive 11364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return true if the filename matches the wilcard string 11374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.3 11384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 11394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public static boolean wildcardMatch(String filename, String wildcardMatcher, IOCase caseSensitivity) { 11404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null && wildcardMatcher == null) { 11414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return true; 11424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (filename == null || wildcardMatcher == null) { 11444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 11454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (caseSensitivity == null) { 11474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy caseSensitivity = IOCase.SENSITIVE; 11484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filename = caseSensitivity.convertCase(filename); 11504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy wildcardMatcher = caseSensitivity.convertCase(wildcardMatcher); 11514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy String[] wcs = splitOnTokens(wildcardMatcher); 11524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy boolean anyChars = false; 11534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int textIdx = 0; 11544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int wcsIdx = 0; 11554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy Stack<int[]> backtrack = new Stack<int[]>(); 11564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // loop around a backtrack stack, to handle complex * matching 11584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy do { 11594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (backtrack.size() > 0) { 11604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int[] array = backtrack.pop(); 11614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy wcsIdx = array[0]; 11624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy textIdx = array[1]; 11634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy anyChars = true; 11644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // loop whilst tokens and text left to process 11674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy while (wcsIdx < wcs.length) { 11684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (wcs[wcsIdx].equals("?")) { 11704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // ? so move to next text char 11714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy textIdx++; 11724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy anyChars = false; 11734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (wcs[wcsIdx].equals("*")) { 11754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // set any chars status 11764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy anyChars = true; 11774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (wcsIdx == wcs.length - 1) { 11784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy textIdx = filename.length(); 11794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 11814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 11824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // matching text token 11834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (anyChars) { 11844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // any chars then try to locate text token 11854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy textIdx = filename.indexOf(wcs[wcsIdx], textIdx); 11864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (textIdx == -1) { 11874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // token not found 11884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 11894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int repeat = filename.indexOf(wcs[wcsIdx], textIdx + 1); 11914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (repeat >= 0) { 11924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy backtrack.push(new int[] {wcsIdx, repeat}); 11934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 11944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 11954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // matching from current position 11964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (!filename.startsWith(wcs[wcsIdx], textIdx)) { 11974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // couldnt match token 11984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 11994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // matched text token, move text index to end of matched token 12034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy textIdx += wcs[wcsIdx].length(); 12044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy anyChars = false; 12054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy wcsIdx++; 12084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // full match 12114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (wcsIdx == wcs.length && textIdx == filename.length()) { 12124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return true; 12134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } while (backtrack.size() > 0); 12164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return false; 12184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 12214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Splits a string into a number of tokens. 12224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 12234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param text the text to split 12244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the tokens, never null 12254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 12264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy static String[] splitOnTokens(String text) { 12274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // used by wildcardMatch 12284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // package level so a unit test may run on this 12294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (text.indexOf("?") == -1 && text.indexOf("*") == -1) { 12314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String[] { text }; 12324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy char[] array = text.toCharArray(); 12354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ArrayList<String> list = new ArrayList<String>(); 12364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy StringBuffer buffer = new StringBuffer(); 12374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = 0; i < array.length; i++) { 12384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == '?' || array[i] == '*') { 12394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (buffer.length() != 0) { 12404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy list.add(buffer.toString()); 12414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy buffer.setLength(0); 12424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (array[i] == '?') { 12444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy list.add("?"); 12454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (list.size() == 0 || 12464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy (i > 0 && list.get(list.size() - 1).equals("*") == false)) { 12474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy list.add("*"); 12484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 12504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy buffer.append(array[i]); 12514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (buffer.length() != 0) { 12544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy list.add(buffer.toString()); 12554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return list.toArray( new String[ list.size() ] ); 12584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 12594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 12604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy} 1261