Author: niallp
Date: Fri May 30 12:12:01 2008
New Revision: 661822
URL: http://svn.apache.org/viewvc?rev=661822&view=rev
Log:
IO-167 Fix case-insensitive string handling - thanks to Benjamin Bentmann
Modified:
commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
commons/proper/io/trunk/src/java/org/apache/commons/io/IOCase.java
commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsWildcardTestCase.java
commons/proper/io/trunk/src/test/org/apache/commons/io/IOCaseTestCase.java
Modified:
commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java?rev=661822&r1=661821&r2=661822&view=diff
==============================================================================
--- commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
(original)
+++ commons/proper/io/trunk/src/java/org/apache/commons/io/FilenameUtils.java
Fri May 30 12:12:01 2008
@@ -1146,8 +1146,6 @@
if (caseSensitivity == null) {
caseSensitivity = IOCase.SENSITIVE;
}
- filename = caseSensitivity.convertCase(filename);
- wildcardMatcher = caseSensitivity.convertCase(wildcardMatcher);
String[] wcs = splitOnTokens(wildcardMatcher);
boolean anyChars = false;
int textIdx = 0;
@@ -1182,18 +1180,18 @@
// matching text token
if (anyChars) {
// any chars then try to locate text token
- textIdx = filename.indexOf(wcs[wcsIdx], textIdx);
+ textIdx = caseSensitivity.checkIndexOf(filename,
textIdx, wcs[wcsIdx]);
if (textIdx == -1) {
// token not found
break;
}
- int repeat = filename.indexOf(wcs[wcsIdx], textIdx +
1);
+ int repeat = caseSensitivity.checkIndexOf(filename,
textIdx + 1, wcs[wcsIdx]);
if (repeat >= 0) {
backtrack.push(new int[] {wcsIdx, repeat});
}
} else {
// matching from current position
- if (!filename.startsWith(wcs[wcsIdx], textIdx)) {
+ if (!caseSensitivity.checkRegionMatches(filename,
textIdx, wcs[wcsIdx])) {
// couldnt match token
break;
}
Modified: commons/proper/io/trunk/src/java/org/apache/commons/io/IOCase.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/IOCase.java?rev=661822&r1=661821&r2=661822&view=diff
==============================================================================
--- commons/proper/io/trunk/src/java/org/apache/commons/io/IOCase.java
(original)
+++ commons/proper/io/trunk/src/java/org/apache/commons/io/IOCase.java Fri May
30 12:12:01 2008
@@ -196,33 +196,46 @@
}
/**
- * Checks if one string contains another at a specific index using the
case-sensitivity rule.
+ * Checks if one string contains another starting at a specific index
using the
+ * case-sensitivity rule.
* <p>
- * This method mimics parts of [EMAIL PROTECTED]
String#regionMatches(boolean, int, String, int, int)}
+ * This method mimics parts of [EMAIL PROTECTED] String#indexOf(String,
int)}
* but takes case-sensitivity into account.
*
* @param str the string to check, not null
* @param strStartIndex the index to start at in str
* @param search the start to search for, not null
- * @return true if equal using the case rules
+ * @return the first index of the search String,
+ * -1 if no match or <code>null</code> string input
* @throws NullPointerException if either string is null
+ * @since 2.0
*/
- public boolean checkRegionMatches(String str, int strStartIndex, String
search) {
- return str.regionMatches(!sensitive, strStartIndex, search, 0,
search.length());
+ public int checkIndexOf(String str, int strStartIndex, String search) {
+ int endIndex = str.length() - search.length();
+ if (endIndex >= strStartIndex) {
+ for (int i = strStartIndex; i <= endIndex; i++) {
+ if (checkRegionMatches(str, i, search)) {
+ return i;
+ }
+ }
+ }
+ return -1;
}
/**
- * Converts the case of the input String to a standard format.
- * Subsequent operations can then use standard String methods.
+ * Checks if one string contains another at a specific index using the
case-sensitivity rule.
+ * <p>
+ * This method mimics parts of [EMAIL PROTECTED]
String#regionMatches(boolean, int, String, int, int)}
+ * but takes case-sensitivity into account.
*
- * @param str the string to convert, null returns null
- * @return the lower-case version if case-insensitive
+ * @param str the string to check, not null
+ * @param strStartIndex the index to start at in str
+ * @param search the start to search for, not null
+ * @return true if equal using the case rules
+ * @throws NullPointerException if either string is null
*/
- String convertCase(String str) {
- if (str == null) {
- return null;
- }
- return sensitive ? str : str.toLowerCase();
+ public boolean checkRegionMatches(String str, int strStartIndex, String
search) {
+ return str.regionMatches(!sensitive, strStartIndex, search, 0,
search.length());
}
//-----------------------------------------------------------------------
Modified:
commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsWildcardTestCase.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsWildcardTestCase.java?rev=661822&r1=661821&r2=661822&view=diff
==============================================================================
---
commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsWildcardTestCase.java
(original)
+++
commons/proper/io/trunk/src/test/org/apache/commons/io/FilenameUtilsWildcardTestCase.java
Fri May 30 12:12:01 2008
@@ -17,6 +17,7 @@
package org.apache.commons.io;
import java.io.File;
+import java.util.Locale;
import junit.framework.TestCase;
@@ -181,4 +182,33 @@
assertMatch("log.log.abc.log.abc.d", "*log?abc?d", true);
}
+ public void testLocaleIndependence() {
+ Locale orig = Locale.getDefault();
+
+ Locale[] locales = Locale.getAvailableLocales();
+
+ String[][] data = {
+ { "I", "i"},
+ { "i", "I"},
+ { "i", "\u0130"},
+ { "i", "\u0131"},
+ { "\u03A3", "\u03C2"},
+ { "\u03A3", "\u03C3"},
+ { "\u03C2", "\u03C3"},
+ };
+
+ try {
+ for (int i = 0; i < data.length; i++) {
+ for (int j = 0; j < locales.length; j++) {
+ Locale.setDefault(locales[j]);
+ assertTrue("Test data corrupt: " + i,
data[i][0].equalsIgnoreCase(data[i][1]));
+ boolean match = FilenameUtils.wildcardMatch(data[i][0],
data[i][1], IOCase.INSENSITIVE);
+ assertTrue(Locale.getDefault().toString() + ": " + i,
match);
+ }
+ }
+ } finally {
+ Locale.setDefault(orig);
+ }
+ }
+
}
Modified:
commons/proper/io/trunk/src/test/org/apache/commons/io/IOCaseTestCase.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/IOCaseTestCase.java?rev=661822&r1=661821&r2=661822&view=diff
==============================================================================
--- commons/proper/io/trunk/src/test/org/apache/commons/io/IOCaseTestCase.java
(original)
+++ commons/proper/io/trunk/src/test/org/apache/commons/io/IOCaseTestCase.java
Fri May 30 12:12:01 2008
@@ -246,6 +246,70 @@
}
//-----------------------------------------------------------------------
+ public void test_checkIndexOf_functionality() throws Exception {
+
+ // start
+ assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "A"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1, "A"));
+ assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"AB"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1,
"AB"));
+ assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"ABC"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1,
"ABC"));
+
+ // middle
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "D"));
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3, "D"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4, "D"));
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"DE"));
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3,
"DE"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4,
"DE"));
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"DEF"));
+ assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3,
"DEF"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4,
"DEF"));
+
+ // end
+ assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "J"));
+ assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8, "J"));
+ assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 9, "J"));
+ assertEquals(8, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"IJ"));
+ assertEquals(8, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8,
"IJ"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 9,
"IJ"));
+ assertEquals(7, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 6,
"HIJ"));
+ assertEquals(7, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 7,
"HIJ"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8,
"HIJ"));
+
+ // not found
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0,
"DED"));
+
+ // too long
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("DEF", 0,
"ABCDEFGHIJ"));
+
+ try {
+ IOCase.SENSITIVE.checkIndexOf("ABC", 0, null);
+ fail();
+ } catch (NullPointerException ex) {}
+ try {
+ IOCase.SENSITIVE.checkIndexOf(null, 0, "ABC");
+ fail();
+ } catch (NullPointerException ex) {}
+ try {
+ IOCase.SENSITIVE.checkIndexOf(null, 0, null);
+ fail();
+ } catch (NullPointerException ex) {}
+ }
+
+ public void test_checkIndexOf_case() throws Exception {
+ assertEquals(1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, "BC"));
+ assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, "Bc"));
+
+ assertEquals(1, IOCase.INSENSITIVE.checkIndexOf("ABC", 0, "BC"));
+ assertEquals(1, IOCase.INSENSITIVE.checkIndexOf("ABC", 0, "Bc"));
+
+ assertEquals(1, IOCase.SYSTEM.checkIndexOf("ABC", 0, "BC"));
+ assertEquals(WINDOWS ? 1 : -1, IOCase.SYSTEM.checkIndexOf("ABC", 0,
"Bc"));
+ }
+
+ //-----------------------------------------------------------------------
public void test_checkRegionMatches_functionality() throws Exception {
assertEquals(true, IOCase.SENSITIVE.checkRegionMatches("ABC", 0, ""));
assertEquals(true, IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "A"));