mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-02 17:35:18 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
640 lines
16 KiB
Java
640 lines
16 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.util;
|
|
|
|
/**
|
|
* Wildcard Utility Class.
|
|
* <p>
|
|
* The WildCard class may be used to check Strings against a wildcard pattern using the SMB/CIFS
|
|
* wildcard rules.
|
|
* <p>
|
|
* A number of static convenience methods are also provided.
|
|
*
|
|
* @author GKSpencer
|
|
*/
|
|
public final class WildCard
|
|
{
|
|
|
|
// Multiple character wildcard
|
|
|
|
public static final int MULTICHAR_WILDCARD = '*';
|
|
|
|
// Single character wildcard
|
|
|
|
public static final int SINGLECHAR_WILDCARD = '?';
|
|
|
|
// Unicode wildcards
|
|
//
|
|
// The spec states :-
|
|
// translate '?' to '>'
|
|
// translate '.' to '"' if followed by a '?' or '*'
|
|
// translate '*' to '<' if followed by a '.'
|
|
|
|
public static final int SINGLECHAR_UNICODE_WILDCARD = '>';
|
|
public static final int DOT_UNICODE_WILDCARD = '"';
|
|
public static final int MULTICHAR_UNICODE_WILDCARD = '<';
|
|
|
|
// Wildcard types
|
|
|
|
public static final int WILDCARD_NONE = 0; // no wildcard characters present in pattern
|
|
public static final int WILDCARD_ALL = 1; // '*.*' and '*'
|
|
public static final int WILDCARD_NAME = 2; // '*.ext'
|
|
public static final int WILDCARD_EXT = 3; // 'name.*'
|
|
public static final int WILDCARD_COMPLEX = 4; // complex wildcard
|
|
|
|
public static final int WILDCARD_INVALID = -1;
|
|
|
|
// Wildcard pattern and type
|
|
|
|
private String m_pattern;
|
|
private int m_type;
|
|
|
|
// Start/end string to match for name/extension matching
|
|
|
|
private String m_matchPart;
|
|
private boolean m_caseSensitive;
|
|
|
|
// Complex wildcard pattern
|
|
|
|
private char[] m_patternChars;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public WildCard()
|
|
{
|
|
setType(WILDCARD_INVALID);
|
|
}
|
|
|
|
/**
|
|
* Class constructor
|
|
*
|
|
* @param pattern String
|
|
* @param caseSensitive boolean
|
|
*/
|
|
public WildCard(String pattern, boolean caseSensitive)
|
|
{
|
|
setPattern(pattern, caseSensitive);
|
|
}
|
|
|
|
/**
|
|
* Return the wildcard pattern type
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int isType()
|
|
{
|
|
return m_type;
|
|
}
|
|
|
|
/**
|
|
* Check if case sensitive matching is enabled
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public final boolean isCaseSensitive()
|
|
{
|
|
return m_caseSensitive;
|
|
}
|
|
|
|
/**
|
|
* Return the wildcard pattern string
|
|
*
|
|
* @return String
|
|
*/
|
|
public final String getPattern()
|
|
{
|
|
return m_pattern;
|
|
}
|
|
|
|
/**
|
|
* Return the match part for wildcard name and wildcard extension type patterns
|
|
*
|
|
* @return String
|
|
*/
|
|
public final String getMatchPart()
|
|
{
|
|
return m_matchPart;
|
|
}
|
|
|
|
/**
|
|
* Determine if the string matches the wildcard pattern
|
|
*
|
|
* @param str String
|
|
* @return boolean
|
|
*/
|
|
public final boolean matchesPattern(String str)
|
|
{
|
|
|
|
// Check the pattern type and compare the string
|
|
|
|
boolean sts = false;
|
|
|
|
switch (isType())
|
|
{
|
|
|
|
// Match all wildcard
|
|
|
|
case WILDCARD_ALL:
|
|
sts = true;
|
|
break;
|
|
|
|
// Match any name
|
|
|
|
case WILDCARD_NAME:
|
|
if (isCaseSensitive())
|
|
{
|
|
|
|
// Check if the string ends with the required file extension
|
|
|
|
sts = str.endsWith(m_matchPart);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Normalize the string and compare
|
|
|
|
String upStr = str.toUpperCase();
|
|
sts = upStr.endsWith(m_matchPart);
|
|
}
|
|
break;
|
|
|
|
// Match any file extension
|
|
|
|
case WILDCARD_EXT:
|
|
if (isCaseSensitive())
|
|
{
|
|
|
|
// Check if the string starts with the required file name
|
|
|
|
sts = str.startsWith(m_matchPart);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Normalize the string and compare
|
|
|
|
String upStr = str.toUpperCase();
|
|
sts = upStr.startsWith(m_matchPart);
|
|
}
|
|
break;
|
|
|
|
// Complex wildcard matching
|
|
|
|
case WILDCARD_COMPLEX:
|
|
if (isCaseSensitive())
|
|
sts = matchComplexWildcard(str);
|
|
else
|
|
{
|
|
|
|
// Normalize the string and compare
|
|
|
|
String upStr = str.toUpperCase();
|
|
sts = matchComplexWildcard(upStr);
|
|
}
|
|
break;
|
|
|
|
// No wildcard characters in pattern, compare strings
|
|
|
|
case WILDCARD_NONE:
|
|
if (isCaseSensitive())
|
|
{
|
|
if (str.compareTo(m_pattern) == 0)
|
|
sts = true;
|
|
}
|
|
else if (str.equalsIgnoreCase(m_pattern))
|
|
sts = true;
|
|
break;
|
|
}
|
|
|
|
// Return the wildcard match status
|
|
|
|
return sts;
|
|
}
|
|
|
|
/**
|
|
* Match a complex wildcard pattern with the specified string
|
|
*
|
|
* @param str String
|
|
* @return boolean
|
|
*/
|
|
protected final boolean matchComplexWildcard(String str)
|
|
{
|
|
|
|
// Convert the string to a char array for matching
|
|
|
|
char[] strChars = str.toCharArray();
|
|
|
|
// Compare the string to the wildcard pattern
|
|
|
|
int wpos = 0;
|
|
int wlen = m_patternChars.length;
|
|
|
|
int spos = 0;
|
|
int slen = strChars.length;
|
|
|
|
char patChar;
|
|
boolean matchFailed = false;
|
|
|
|
while (matchFailed == false && wpos < m_patternChars.length)
|
|
{
|
|
|
|
// Match the current pattern character
|
|
|
|
patChar = m_patternChars[wpos++];
|
|
|
|
switch (patChar)
|
|
{
|
|
|
|
// Match single character
|
|
|
|
case SINGLECHAR_WILDCARD:
|
|
if (spos < slen)
|
|
spos++;
|
|
else
|
|
matchFailed = true;
|
|
break;
|
|
|
|
// Match zero or more characters
|
|
|
|
case MULTICHAR_WILDCARD:
|
|
|
|
// Check if there is another character in the wildcard pattern
|
|
|
|
if (wpos < wlen)
|
|
{
|
|
|
|
// Check if the character is not a wildcard character
|
|
|
|
patChar = m_patternChars[wpos];
|
|
if (patChar != SINGLECHAR_WILDCARD && patChar != MULTICHAR_WILDCARD)
|
|
{
|
|
|
|
// Find the required character in the string
|
|
|
|
while (spos < slen && strChars[spos] != patChar)
|
|
spos++;
|
|
if (spos >= slen)
|
|
matchFailed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Multi character wildcard at the end of the pattern, match all remaining
|
|
// characters
|
|
|
|
spos = slen;
|
|
}
|
|
break;
|
|
|
|
// Match the pattern and string character
|
|
|
|
default:
|
|
if (spos >= slen || strChars[spos] != patChar)
|
|
matchFailed = true;
|
|
else
|
|
spos++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check if the match was successul and return status
|
|
|
|
if (matchFailed == false && spos == slen)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set the wildcard pattern string
|
|
*
|
|
* @param pattern String
|
|
* @param caseSensitive boolean
|
|
*/
|
|
public final void setPattern(String pattern, boolean caseSensitive)
|
|
{
|
|
|
|
// Save the pattern string and case sensitive flag
|
|
|
|
m_pattern = pattern;
|
|
m_caseSensitive = caseSensitive;
|
|
|
|
setType(WILDCARD_INVALID);
|
|
|
|
// Check if the pattern string is valid
|
|
|
|
if (pattern == null || pattern.length() == 0)
|
|
return;
|
|
|
|
// Check for the match all wildcard
|
|
|
|
if (pattern.compareTo("*.*") == 0 || pattern.compareTo("*") == 0)
|
|
{
|
|
setType(WILDCARD_ALL);
|
|
return;
|
|
}
|
|
|
|
// Check for a name wildcard, ie. '*.ext'
|
|
|
|
if (pattern.startsWith("*."))
|
|
{
|
|
|
|
// Split the string to get the extension string
|
|
|
|
if (pattern.length() > 2)
|
|
m_matchPart = pattern.substring(1);
|
|
else
|
|
m_matchPart = "";
|
|
|
|
// If matching is case insensitive then normalize the string
|
|
|
|
if (isCaseSensitive() == false)
|
|
m_matchPart = m_matchPart.toUpperCase();
|
|
|
|
// If the file extension contains wildcards we will need to use a regular expression
|
|
|
|
if (containsWildcards(m_matchPart) == false)
|
|
{
|
|
setType(WILDCARD_NAME);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for a file extension wildcard
|
|
|
|
if (pattern.endsWith(".*"))
|
|
{
|
|
|
|
// Split the string to get the name string
|
|
|
|
if (pattern.length() > 2)
|
|
m_matchPart = pattern.substring(0, pattern.length() - 2);
|
|
else
|
|
m_matchPart = "";
|
|
|
|
// If matching is case insensitive then normalize the string
|
|
|
|
if (isCaseSensitive() == false)
|
|
m_matchPart = m_matchPart.toUpperCase();
|
|
|
|
// If the file name contains wildcards we will need to use a regular expression
|
|
|
|
if (containsWildcards(m_matchPart) == false)
|
|
{
|
|
setType(WILDCARD_EXT);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Save the complex wildcard pattern as a char array for later pattern matching
|
|
|
|
if (isCaseSensitive() == false)
|
|
m_patternChars = m_pattern.toUpperCase().toCharArray();
|
|
else
|
|
m_patternChars = m_pattern.toCharArray();
|
|
|
|
setType(WILDCARD_COMPLEX);
|
|
}
|
|
|
|
/**
|
|
* Set the wildcard type
|
|
*
|
|
* @param typ int
|
|
*/
|
|
private final void setType(int typ)
|
|
{
|
|
m_type = typ;
|
|
}
|
|
|
|
/**
|
|
* Return the wildcard as a string
|
|
*
|
|
* @return String
|
|
*/
|
|
public String toString()
|
|
{
|
|
StringBuffer str = new StringBuffer();
|
|
str.append("[");
|
|
str.append(getPattern());
|
|
str.append(",");
|
|
str.append(isType());
|
|
str.append(",");
|
|
|
|
if (m_matchPart != null)
|
|
str.append(m_matchPart);
|
|
|
|
if (isCaseSensitive())
|
|
str.append(",Case");
|
|
else
|
|
str.append(",NoCase");
|
|
str.append("]");
|
|
|
|
return str.toString();
|
|
}
|
|
|
|
/**
|
|
* Check if the string contains any wildcard characters.
|
|
*
|
|
* @return boolean
|
|
* @param str java.lang.String
|
|
*/
|
|
public final static boolean containsWildcards(String str)
|
|
{
|
|
|
|
// Check the string for wildcard characters
|
|
|
|
if (str.indexOf(MULTICHAR_WILDCARD) != -1)
|
|
return true;
|
|
|
|
if (str.indexOf(SINGLECHAR_WILDCARD) != -1)
|
|
return true;
|
|
|
|
// No wildcards found in the string
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if a string contains any of the Unicode wildcard characters
|
|
*
|
|
* @param str String
|
|
* @return boolean
|
|
*/
|
|
public final static boolean containsUnicodeWildcard(String str)
|
|
{
|
|
|
|
// Check if the string contains any of the Unicode wildcards
|
|
|
|
if (str.indexOf(SINGLECHAR_UNICODE_WILDCARD) != -1 || str.indexOf(MULTICHAR_UNICODE_WILDCARD) != -1
|
|
|| str.indexOf(DOT_UNICODE_WILDCARD) != -1)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Convert the Unicode wildcard string to a standard DOS wildcard string
|
|
*
|
|
* @param str String
|
|
* @return String
|
|
*/
|
|
public final static String convertUnicodeWildcardToDOS(String str)
|
|
{
|
|
|
|
// Create a buffer for the new wildcard string
|
|
|
|
StringBuffer newStr = new StringBuffer(str.length());
|
|
|
|
// Convert the Unicode wildcard string to a DOS wildcard string
|
|
|
|
for (int i = 0; i < str.length(); i++)
|
|
{
|
|
|
|
// Get the current character
|
|
|
|
char ch = str.charAt(i);
|
|
|
|
// Check for a Unicode wildcard character
|
|
|
|
if (ch == SINGLECHAR_UNICODE_WILDCARD)
|
|
{
|
|
|
|
// Translate to the DOS single character wildcard character
|
|
|
|
ch = SINGLECHAR_WILDCARD;
|
|
}
|
|
else if (ch == MULTICHAR_UNICODE_WILDCARD)
|
|
{
|
|
|
|
// Check if the current character is followed by a '.', if so then translate to the
|
|
// DOS multi character
|
|
// wildcard
|
|
|
|
if (i < (str.length() - 1) && str.charAt(i + 1) == '.')
|
|
ch = MULTICHAR_WILDCARD;
|
|
}
|
|
else if (ch == DOT_UNICODE_WILDCARD)
|
|
{
|
|
|
|
// Check if the current character is followed by a DOS single/multi character
|
|
// wildcard
|
|
|
|
if (i < (str.length() - 1))
|
|
{
|
|
char nextCh = str.charAt(i + 1);
|
|
if (nextCh == SINGLECHAR_WILDCARD || nextCh == MULTICHAR_WILDCARD
|
|
|| nextCh == SINGLECHAR_UNICODE_WILDCARD)
|
|
ch = '.';
|
|
}
|
|
}
|
|
|
|
// Append the character to the translated wildcard string
|
|
|
|
newStr.append(ch);
|
|
}
|
|
|
|
// Return the translated wildcard string
|
|
|
|
return newStr.toString();
|
|
}
|
|
|
|
/**
|
|
* Convert a wildcard string to a regular expression
|
|
*
|
|
* @param path String
|
|
* @return String
|
|
*/
|
|
public final static String convertToRegexp(String path)
|
|
{
|
|
|
|
// Convert the path to characters, check if the wildcard string ends with a single character
|
|
// wildcard
|
|
|
|
char[] smbPattern = path.toCharArray();
|
|
boolean endsWithQ = smbPattern[smbPattern.length - 1] == '?';
|
|
|
|
// Build up the regular expression
|
|
|
|
StringBuffer sb = new StringBuffer();
|
|
sb.append('^');
|
|
|
|
for (int i = 0; i < smbPattern.length; i++)
|
|
{
|
|
|
|
// Process the current character
|
|
|
|
switch (smbPattern[i])
|
|
{
|
|
|
|
// Multi character wildcard
|
|
|
|
case '*':
|
|
sb.append(".*");
|
|
break;
|
|
|
|
// Single character wildcard
|
|
|
|
case '?':
|
|
if (endsWithQ)
|
|
{
|
|
boolean restQ = true;
|
|
for (int j = i + 1; j < smbPattern.length; j++)
|
|
{
|
|
if (smbPattern[j] != '?')
|
|
{
|
|
restQ = false;
|
|
break;
|
|
}
|
|
}
|
|
if (restQ)
|
|
sb.append(".?");
|
|
else
|
|
sb.append('.');
|
|
}
|
|
else
|
|
sb.append('.');
|
|
break;
|
|
|
|
// Escape regular expression special characters
|
|
|
|
case '.':
|
|
case '+':
|
|
case '\\':
|
|
case '[':
|
|
case ']':
|
|
case '^':
|
|
case '$':
|
|
case '(':
|
|
case ')':
|
|
sb.append('\\');
|
|
sb.append(smbPattern[i]);
|
|
break;
|
|
|
|
// Normal characters, just pass through
|
|
|
|
default:
|
|
sb.append(smbPattern[i]);
|
|
break;
|
|
}
|
|
}
|
|
sb.append('$');
|
|
|
|
// Return the regular expression string
|
|
|
|
return sb.toString();
|
|
}
|
|
} |