
org.codehaus.plexus.util.PathTool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plexus-utils Show documentation
Show all versions of plexus-utils Show documentation
A collection of various utility classes to ease working with strings, files, command lines, XML and more.
package org.codehaus.plexus.util;
/* ====================================================================
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
/**
* Path tool contains static methods to assist in determining path-related
* information such as relative paths.
*
* @author Pete Kazmier
* @author Vincent Massol
* @version $Id: PathTool.java 5958 2007-02-28 10:29:55Z olamy $
*/
public class PathTool
{
/**
* Determines the relative path of a filename from a base directory.
* This method is useful in building relative links within pages of
* a web site. It provides similar functionality to Anakia's
* $relativePath
context variable. The arguments to
* this method may contain either forward or backward slashes as
* file separators. The relative path returned is formed using
* forward slashes as it is expected this path is to be used as a
* link in a web page (again mimicking Anakia's behavior).
*
* This method is thread-safe.
*
* @param basedir The base directory.
* @param filename The filename that is relative to the base
* directory.
* @return The relative path of the filename from the base
* directory. This value is not terminated with a forward slash.
* A zero-length string is returned if: the filename is not relative to
* the base directory, basedir
is null or zero-length,
* or filename
is null or zero-length.
*/
public static final String getRelativePath( String basedir, String filename )
{
basedir = uppercaseDrive(basedir);
filename = uppercaseDrive(filename);
/*
* Verify the arguments and make sure the filename is relative
* to the base directory.
*/
if ( basedir == null || basedir.length() == 0 || filename == null
|| filename.length() == 0 || !filename.startsWith( basedir ) )
{
return "";
}
/*
* Normalize the arguments. First, determine the file separator
* that is being used, then strip that off the end of both the
* base directory and filename.
*/
String separator = determineSeparator( filename );
basedir = StringUtils.chompLast( basedir, separator );
filename = StringUtils.chompLast( filename, separator );
/*
* Remove the base directory from the filename to end up with a
* relative filename (relative to the base directory). This
* filename is then used to determine the relative path.
*/
String relativeFilename = filename.substring( basedir.length() );
return determineRelativePath( relativeFilename, separator );
}
/**
* Determines the relative path of a filename. This method is
* useful in building relative links within pages of a web site. It
* provides similar functionality to Anakia's
* $relativePath
context variable. The argument to
* this method may contain either forward or backward slashes as
* file separators. The relative path returned is formed using
* forward slashes as it is expected this path is to be used as a
* link in a web page (again mimicking Anakia's behavior).
*
* This method is thread-safe.
*
* @param filename The filename to be parsed.
* @return The relative path of the filename. This value is not
* terminated with a forward slash. A zero-length string is
* returned if: filename
is null or zero-length.
*/
public static final String getRelativePath( String filename )
{
filename = uppercaseDrive(filename);
if ( filename == null || filename.length() == 0 )
{
return "";
}
/*
* Normalize the argument. First, determine the file separator
* that is being used, then strip that off the end of the
* filename. Then, if the filename doesn't begin with a
* separator, add one.
*/
String separator = determineSeparator( filename );
filename = StringUtils.chompLast( filename, separator );
if ( !filename.startsWith( separator ) )
{
filename = separator + filename;
}
return determineRelativePath( filename, separator );
}
/**
* Determines the directory component of a filename. This is useful
* within DVSL templates when used in conjunction with the DVSL's
* $context.getAppValue("infilename")
to get the
* current directory that is currently being processed.
*
* This method is thread-safe.
*
* @param filename The filename to be parsed.
* @return The directory portion of the filename
. If
* the filename does not contain a directory component, "." is
* returned.
*/
public static final String getDirectoryComponent( String filename )
{
if ( filename == null || filename.length() == 0 )
{
return "";
}
String separator = determineSeparator( filename );
String directory = StringUtils.chomp( filename, separator );
if ( filename.equals( directory ) )
{
return ".";
}
else
{
return directory;
}
}
/**
* Determines the relative path of a filename. For each separator
* within the filename (except the leading if present), append the
* "../" string to the return value.
*
* @param filename The filename to parse.
* @param separator The separator used within the filename.
* @return The relative path of the filename. This value is not
* terminated with a forward slash. A zero-length string is
* returned if: the filename is zero-length.
*/
private static final String determineRelativePath( String filename,
String separator )
{
if ( filename.length() == 0 )
{
return "";
}
/*
* Count the slashes in the relative filename, but exclude the
* leading slash. If the path has no slashes, then the filename
* is relative to the current directory.
*/
int slashCount = StringUtils.countMatches( filename, separator ) - 1;
if ( slashCount <= 0 )
{
return ".";
}
/*
* The relative filename contains one or more slashes indicating
* that the file is within one or more directories. Thus, each
* slash represents a "../" in the relative path.
*/
StringBuffer sb = new StringBuffer();
for ( int i = 0; i < slashCount; i++ )
{
sb.append( "../" );
}
/*
* Finally, return the relative path but strip the trailing
* slash to mimic Anakia's behavior.
*/
return StringUtils.chop( sb.toString() );
}
/**
* Helper method to determine the file separator (forward or
* backward slash) used in a filename. The slash that occurs more
* often is returned as the separator.
*
* @param filename The filename parsed to determine the file
* separator.
* @return The file separator used within filename
.
* This value is either a forward or backward slash.
*/
private static final String determineSeparator( String filename )
{
int forwardCount = StringUtils.countMatches( filename, "/" );
int backwardCount = StringUtils.countMatches( filename, "\\" );
return forwardCount >= backwardCount ? "/" : "\\";
}
/**
* Cygwin prefers lowercase drive letters, but other parts of maven use uppercase
* @param path
* @return String
*/
static final String uppercaseDrive(String path)
{
if (path == null)
{
return null;
}
if (path.length() >= 2 && path.charAt(1) == ':')
{
path = path.substring(0, 1).toUpperCase() + path.substring(1);
}
return path;
}
/**
* Calculates the appropriate link given the preferred link and the relativePath of the document
* @param link
* @param relativePath
* @return String
*/
public static final String calculateLink(String link, String relativePath)
{
//This must be some historical feature
if (link.startsWith("/site/"))
{
return link.substring(5);
}
//Allows absolute links in nav-bars etc
if (link.startsWith("/absolute/"))
{
return link.substring(10);
}
// This traps urls like http://
if (link.indexOf(":") >= 0)
{
return link;
}
//If relativepath is current directory, just pass the link through
if (relativePath.equals("."))
{
if (link.startsWith("/"))
{
return link.substring(1);
}
else
{
return link;
}
}
//If we don't do this, you can end up with ..//bob.html rather than ../bob.html
if (relativePath.endsWith("/") && link.startsWith("/"))
{
return relativePath + "." + link.substring(1);
}
if (relativePath.endsWith("/") || link.startsWith("/"))
{
return relativePath + link;
}
return relativePath + "/" + link;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy