2005-12-08 07:13:07 +00:00

626 lines
18 KiB
Java

/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.filesys.server.filesys;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;
/**
* <p>
* Provides utility methods for manipulating file names.
*/
public final class FileName
{
// DOS file name seperator
public static final char DOS_SEPERATOR = '\\';
public static final String DOS_SEPERATOR_STR = "\\";
// NTFS Stream seperator
public static final String NTFSStreamSeperator = ":";
/**
* Build a path using the specified components.
*
* @param dev java.lang.String
* @param path java.lang.String
* @param filename java.lang.String
* @param sep char
* @return java.lang.String
*/
public static String buildPath(String dev, String path, String filename, char sep)
{
// Debug.println ( "BuildPath: dev=" + dev + ", path=" + path + ",filename=" + filename);
// Build the path string
StringBuffer fullPath = new StringBuffer();
// Check for a device name
if (dev != null)
{
// Add the device name
fullPath.append(dev);
// Check if the device name has a file seperator
if (dev.length() > 0 && dev.charAt(dev.length() - 1) != sep)
fullPath.append(sep);
}
// Check for a path
if (path != null)
{
// Add the path
if (fullPath.length() > 0 && path.length() > 0
&& (path.charAt(0) == sep || path.charAt(0) == DOS_SEPERATOR))
fullPath.append(path.substring(1));
else
fullPath.append(path);
// Add a trailing seperator, if required
if (path.length() > 0 && path.charAt(path.length() - 1) != sep && filename != null)
fullPath.append(sep);
}
// Check for a file name
if (filename != null)
{
// Add the file name
if (fullPath.length() > 0 && filename.length() > 0
&& (filename.charAt(0) == sep || filename.charAt(0) == DOS_SEPERATOR))
fullPath.append(filename.substring(1));
else
fullPath.append(filename);
}
// Debug
// Debug.println ( "BuildPath: " + fullPath.toString ());
// Convert the file seperator characters in the path if we are not using the normal
// DOS file seperator character.
if (sep != DOS_SEPERATOR)
return convertSeperators(fullPath.toString(), sep);
return fullPath.toString();
}
/**
* Convert the file seperators in a path to the specified path seperator character.
*
* @param path java.lang.String
* @param sep char
* @return java.lang.String
*/
public static String convertSeperators(String path, char sep)
{
// Check if the path contains any DOS seperators
if (path.indexOf(DOS_SEPERATOR) == -1)
return path;
// Convert DOS path seperators to the specified seperator
StringBuffer newPath = new StringBuffer();
int idx = 0;
while (idx < path.length())
{
// Get the current character from the path and check if it is a DOS path
// seperator character.
char ch = path.charAt(idx++);
if (ch == DOS_SEPERATOR)
newPath.append(sep);
else
newPath.append(ch);
}
// Return the new path string
return newPath.toString();
}
/**
* Map the input path to a real path, this may require changing the case of various parts of the
* path. The base path is not checked, it is assumed to exist.
*
* @param base java.lang.String
* @param path java.lang.String
* @return java.lang.String
* @exception java.io.FileNotFoundException The path could not be mapped to a real path.
*/
public static final String mapPath(String base, String path) throws java.io.FileNotFoundException
{
// Split the path string into seperate directory components
String pathCopy = path;
if (pathCopy.length() > 0 && pathCopy.startsWith(DOS_SEPERATOR_STR))
pathCopy = pathCopy.substring(1);
StringTokenizer token = new StringTokenizer(pathCopy, "\\/");
int tokCnt = token.countTokens();
// The mapped path string, if it can be mapped
String mappedPath = null;
if (tokCnt > 0)
{
// Allocate an array to hold the directory names
String[] dirs = new String[token.countTokens()];
// Get the directory names
int idx = 0;
while (token.hasMoreTokens())
dirs[idx++] = token.nextToken();
// Check if the path ends with a directory or file name, ie. has a trailing '\' or not
int maxDir = dirs.length;
if (path.endsWith(DOS_SEPERATOR_STR) == false)
{
// Ignore the last token as it is a file name
maxDir--;
}
// Build up the path string and validate that the path exists at each stage.
StringBuffer pathStr = new StringBuffer(base);
if (base.endsWith(java.io.File.separator) == false)
pathStr.append(java.io.File.separator);
int lastPos = pathStr.length();
idx = 0;
File lastDir = null;
if (base != null && base.length() > 0)
lastDir = new File(base);
File curDir = null;
while (idx < maxDir)
{
// Append the current directory to the path
pathStr.append(dirs[idx]);
pathStr.append(java.io.File.separator);
// Check if the current path exists
curDir = new File(pathStr.toString());
if (curDir.exists() == false)
{
// Check if there is a previous directory to search
if (lastDir == null)
throw new FileNotFoundException();
// Search the current path for a matching directory, the case may be different
String[] fileList = lastDir.list();
if (fileList == null || fileList.length == 0)
throw new FileNotFoundException();
int fidx = 0;
boolean foundPath = false;
while (fidx < fileList.length && foundPath == false)
{
// Check if the current file name matches the required directory name
if (fileList[fidx].equalsIgnoreCase(dirs[idx]))
{
// Use the current directory name
pathStr.setLength(lastPos);
pathStr.append(fileList[fidx]);
pathStr.append(java.io.File.separator);
// Check if the path is valid
curDir = new File(pathStr.toString());
if (curDir.exists())
{
foundPath = true;
break;
}
}
// Update the file name index
fidx++;
}
// Check if we found the required directory
if (foundPath == false)
throw new FileNotFoundException();
}
// Set the last valid directory file
lastDir = curDir;
// Update the end of valid path location
lastPos = pathStr.length();
// Update the current directory index
idx++;
}
// Check if there is a file name to be added to the mapped path
if (path.endsWith(DOS_SEPERATOR_STR) == false)
{
// Map the file name
String[] fileList = lastDir.list();
String fileName = dirs[dirs.length - 1];
// Check if the file list is valid, if not then the path is not valid
if (fileList == null)
throw new FileNotFoundException(path);
// Search for the required file
idx = 0;
boolean foundFile = false;
while (idx < fileList.length && foundFile == false)
{
if (fileList[idx].compareTo(fileName) == 0)
foundFile = true;
else
idx++;
}
// Check if we found the file name, if not then do a case insensitive search
if (foundFile == false)
{
// Search again using a case insensitive search
idx = 0;
while (idx < fileList.length && foundFile == false)
{
if (fileList[idx].equalsIgnoreCase(fileName))
{
foundFile = true;
fileName = fileList[idx];
}
else
idx++;
}
}
// Append the file name
pathStr.append(fileName);
}
// Set the new path string
mappedPath = pathStr.toString();
}
// Return the mapped path string, if successful.
return mappedPath;
}
/**
* Remove the file name from the specified path string.
*
* @param path java.lang.String
* @return java.lang.String
*/
public final static String removeFileName(String path)
{
// Find the last path seperator
int pos = path.lastIndexOf(DOS_SEPERATOR);
if (pos != -1)
return path.substring(0, pos);
// Return an empty string, no path seperators
return "";
}
/**
* Split the path into seperate directory path and file name strings.
*
* @param path Full path string.
* @param sep Path seperator character.
* @return java.lang.String[]
*/
public static String[] splitPath(String path)
{
return splitPath(path, DOS_SEPERATOR, null);
}
/**
* Split the path into seperate directory path and file name strings.
*
* @param path Full path string.
* @param sep Path seperator character.
* @return java.lang.String[]
*/
public static String[] splitPath(String path, char sep)
{
return splitPath(path, sep, null);
}
/**
* Split the path into seperate directory path and file name strings.
*
* @param path Full path string.
* @param sep Path seperator character.
* @param list String list to return values in, or null to allocate
* @return java.lang.String[]
*/
public static String[] splitPath(String path, char sep, String[] list)
{
if (path == null)
throw new IllegalArgumentException("Path may not be null");
// Create an array of strings to hold the path and file name strings
String[] pathStr = list;
if (pathStr == null)
pathStr = new String[] {"", ""};
// Check if the path is valid
if (path.length() > 0)
{
// Check if the path has a trailing seperator, if so then there is no file name.
int pos = path.lastIndexOf(sep);
if (pos == -1 || pos == (path.length() - 1))
{
// Set the path string in the returned string array
pathStr[0] = path;
}
else
{
// Split the path into directory list and file name strings
pathStr[1] = path.substring(pos + 1);
if (pos == 0)
pathStr[0] = path.substring(0, pos + 1);
else
pathStr[0] = path.substring(0, pos);
}
}
// Return the path strings
return pathStr;
}
/**
* Split the path into all the component directories and filename
*
* @param path String
* @return String[]
*/
public static String[] splitAllPaths(String path)
{
// Check if the path is valid
if (path == null || path.length() == 0)
return null;
// Determine the number of components in the path
StringTokenizer token = new StringTokenizer(path, DOS_SEPERATOR_STR);
String[] names = new String[token.countTokens()];
// Split the path
int i = 0;
while (i < names.length && token.hasMoreTokens())
names[i++] = token.nextToken();
// Return the path components
return names;
}
/**
* Split a path string into directory path, file name and stream name components
*
* @param path Full path string.
* @return java.lang.String[]
*/
public static String[] splitPathStream(String path)
{
// Allocate the return list
String[] pathStr = new String[3];
// Split the path into directory path and file/stream name
FileName.splitPath(path, DOS_SEPERATOR, pathStr);
if (pathStr[1] == null)
return pathStr;
// Split the file name into file and stream names
int pos = pathStr[1].indexOf(NTFSStreamSeperator);
if (pos != -1)
{
// Split the file/stream name
pathStr[2] = pathStr[1].substring(pos);
pathStr[1] = pathStr[1].substring(0, pos);
}
// Return the path components list
return pathStr;
}
/**
* Test if a file name contains an NTFS stream name
*
* @param path String
* @return boolean
*/
public static boolean containsStreamName(String path)
{
// Check if the path contains the stream name seperator character
if (path.indexOf(NTFSStreamSeperator) != -1)
return true;
return false;
}
/**
* Normalize the path to uppercase the directory names and keep the case of the file name.
*
* @param path String
* @return String
*/
public final static String normalizePath(String path)
{
// Split the path into directories and file name, only uppercase the directories to
// normalize
// the path.
String normPath = path;
if (path.length() > 3)
{
// Split the path to seperate the folders/file name
int pos = path.lastIndexOf(DOS_SEPERATOR);
if (pos != -1)
{
// Get the path and file name parts, normalize the path
String pathPart = path.substring(0, pos).toUpperCase();
String namePart = path.substring(pos);
// Rebuild the path string
normPath = pathPart + namePart;
}
}
// Return the normalized path
return normPath;
}
/**
* Make a path relative to the base path for the specified path.
*
* @param basePath String
* @param fullPath String
* @return String
*/
public final static String makeRelativePath(String basePath, String fullPath)
{
// Check if the base path is the root path
if (basePath.length() == 0 || basePath.equals(DOS_SEPERATOR_STR))
{
// Return the full path, strip any leading seperator
if (fullPath.length() > 0 && fullPath.charAt(0) == DOS_SEPERATOR)
return fullPath.substring(1);
return fullPath;
}
// Split the base and full paths into seperate components
String[] baseNames = splitAllPaths(basePath);
String[] fullNames = splitAllPaths(fullPath);
// Check that the full path is actually within the base path tree
if (baseNames != null && baseNames.length > 0 && fullNames != null && fullNames.length > 0
&& baseNames[0].equalsIgnoreCase(fullNames[0]) == false)
return null;
// Match the path names
int idx = 0;
while (idx < baseNames.length && idx < fullNames.length && baseNames[idx].equalsIgnoreCase(fullNames[idx]))
idx++;
// Build the relative path
StringBuffer relPath = new StringBuffer(128);
while (idx < fullNames.length)
{
relPath.append(fullNames[idx++]);
if (idx < fullNames.length)
relPath.append(DOS_SEPERATOR);
}
// Return the relative path
return relPath.toString();
}
}