Skip to content

Commit 745375d

Browse files
author
Stephen Colebourne
committed
Make FilenameUtils equals methods case-sensitive, with some optional system case matching
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@160343 13f79535-47bb-0310-9956-ffa450edef68
1 parent d108068 commit 745375d

3 files changed

Lines changed: 187 additions & 90 deletions

File tree

src/java/org/apache/commons/io/FilenameUtils.java

Lines changed: 125 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.io.File;
1919
import java.util.ArrayList;
2020
import java.util.Collection;
21+
import java.util.Iterator;
2122
import java.util.Stack;
2223

2324
/**
@@ -28,10 +29,10 @@
2829
* This class aims to help avoid those problems.
2930
* <p>
3031
* Most methods on this class are designed to work the same on both Unix and Windows.
31-
* Both separators (forward and back) are recognised, and both sets of prefixes.
32-
* The comparison methods do differ by machine however, comparing case insensitive
33-
* on Windows and case sensitive on Unix.
34-
* See the javadoc of each method for details.
32+
* Those that don't include 'System', 'Unix' or 'Windows' in their name.
33+
* <p>
34+
* Most methods recognise both separators (forward and back), and both
35+
* sets of prefixes. See the javadoc of each method for details.
3536
* <p>
3637
* This class defines six components within a filename (example C:\dev\project\file.txt):
3738
* <ul>
@@ -680,51 +681,91 @@ public static String removeExtension(String filename) {
680681
}
681682

682683
//-----------------------------------------------------------------------
684+
/**
685+
* Checks whether two filenames are equal exactly.
686+
* <p>
687+
* No processing is performed on the filenames other than comparison,
688+
* thus this is merely a null-safe case-sensitive equals.
689+
*
690+
* @param filename1 the first filename to query, may be null
691+
* @param filename2 the second filename to query, may be null
692+
* @return true if the filenames are equal, null equals null
693+
*/
694+
public static boolean equals(String filename1, String filename2) {
695+
return equals(filename1, filename2, false, false);
696+
}
697+
683698
/**
684699
* Checks whether two filenames are equal using the case rules of the system.
685700
* <p>
686701
* No processing is performed on the filenames other than comparison.
687-
* The check is case sensitive on Unix and case insensitive on Windows.
702+
* The check is case-sensitive on Unix and case-insensitive on Windows.
688703
*
689704
* @param filename1 the first filename to query, may be null
690705
* @param filename2 the second filename to query, may be null
691706
* @return true if the filenames are equal, null equals null
692707
*/
693-
public static boolean equals(String filename1, String filename2) {
694-
if (filename1 == filename2) {
695-
return true;
696-
}
697-
if (filename1 == null || filename2 == null) {
698-
return false;
699-
}
700-
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
701-
return filename1.equalsIgnoreCase(filename2);
702-
} else {
703-
return filename1.equals(filename2);
704-
}
708+
public static boolean equalsOnSystem(String filename1, String filename2) {
709+
return equals(filename1, filename2, true, false);
710+
}
711+
712+
//-----------------------------------------------------------------------
713+
/**
714+
* Checks whether two filenames are equal after both have been normalized.
715+
* <p>
716+
* Both filenames are first passed to {@link #normalize(String)}.
717+
* The check is then performed in a case-sensitive manner.
718+
*
719+
* @param filename1 the first filename to query, may be null
720+
* @param filename2 the second filename to query, may be null
721+
* @return true if the filenames are equal, null equals null
722+
*/
723+
public static boolean equalsNormalized(String filename1, String filename2) {
724+
return equals(filename1, filename2, false, true);
705725
}
706726

707727
/**
708728
* Checks whether two filenames are equal after both have been normalized
709729
* and using the case rules of the system.
710730
* <p>
711731
* Both filenames are first passed to {@link #normalize(String)}.
712-
* The check is then performed case sensitive on Unix and case insensitive on Windows.
732+
* The check is then performed case-sensitive on Unix and
733+
* case-insensitive on Windows.
713734
*
714735
* @param filename1 the first filename to query, may be null
715736
* @param filename2 the second filename to query, may be null
716737
* @return true if the filenames are equal, null equals null
717738
*/
718-
public static boolean equalsNormalized(String filename1, String filename2) {
739+
public static boolean equalsNormalizedOnSystem(String filename1, String filename2) {
740+
return equals(filename1, filename2, true, true);
741+
}
742+
743+
/**
744+
* Checks whether two filenames are equal after both have been normalized
745+
* and optionally using the case rules of the system.
746+
* <p>
747+
* Both filenames are first passed to {@link #normalize(String)}.
748+
*
749+
* @param filename1 the first filename to query, may be null
750+
* @param filename2 the second filename to query, may be null
751+
* @param system whether to use the system (windows or unix)
752+
* @param normalized whether to normalize the filenames
753+
* @return true if the filenames are equal, null equals null
754+
*/
755+
private static boolean equals(
756+
String filename1, String filename2,
757+
boolean system, boolean normalized) {
719758
if (filename1 == filename2) {
720759
return true;
721760
}
722761
if (filename1 == null || filename2 == null) {
723762
return false;
724763
}
725-
filename1 = normalize(filename1);
726-
filename2 = normalize(filename2);
727-
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
764+
if (normalized) {
765+
filename1 = normalize(filename1);
766+
filename2 = normalize(filename2);
767+
}
768+
if (system && (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR)) {
728769
return filename1.equalsIgnoreCase(filename2);
729770
} else {
730771
return filename1.equals(filename2);
@@ -733,12 +774,11 @@ public static boolean equalsNormalized(String filename1, String filename2) {
733774

734775
//-----------------------------------------------------------------------
735776
/**
736-
* Checks whether the extension of the filename is that specified
737-
* using the case rules of the system.
777+
* Checks whether the extension of the filename is that specified.
738778
* <p>
739779
* This method obtains the extension as the textual part of the filename
740780
* after the last dot. There must be no directory separator after the dot.
741-
* The extension check is case sensitive on Unix and case insensitive on Windows.
781+
* The extension check is case-sensitive on all platforms.
742782
*
743783
* @param filename the filename to query, null returns false
744784
* @param extension the extension to check for, null or empty checks for no extension
@@ -752,20 +792,15 @@ public static boolean isExtension(String filename, String extension) {
752792
return (indexOfExtension(filename) == -1);
753793
}
754794
String fileExt = getExtension(filename);
755-
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
756-
return fileExt.equalsIgnoreCase(extension);
757-
} else {
758-
return fileExt.equals(extension);
759-
}
795+
return fileExt.equals(extension);
760796
}
761797

762798
/**
763-
* Checks whether the extension of the filename is one of those specified
764-
* using the case rules of the system.
799+
* Checks whether the extension of the filename is one of those specified.
765800
* <p>
766801
* This method obtains the extension as the textual part of the filename
767802
* after the last dot. There must be no directory separator after the dot.
768-
* The extension check is case sensitive on Unix and case insensitive on Windows.
803+
* The extension check is case-sensitive on all platforms.
769804
*
770805
* @param filename the filename to query, null returns false
771806
* @param extensions the extensions to check for, null checks for no extension
@@ -775,33 +810,24 @@ public static boolean isExtension(String filename, String[] extensions) {
775810
if (filename == null) {
776811
return false;
777812
}
778-
if (extensions == null) {
813+
if (extensions == null || extensions.length == 0) {
779814
return (indexOfExtension(filename) == -1);
780815
}
781816
String fileExt = getExtension(filename);
782-
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
783-
for (int i = 0; i < extensions.length; i++) {
784-
if (fileExt.equalsIgnoreCase(extensions[i])) {
785-
return true;
786-
}
787-
}
788-
} else {
789-
for (int i = 0; i < extensions.length; i++) {
790-
if (fileExt.equals(extensions[i])) {
791-
return true;
792-
}
817+
for (int i = 0; i < extensions.length; i++) {
818+
if (fileExt.equals(extensions[i])) {
819+
return true;
793820
}
794821
}
795822
return false;
796823
}
797824

798825
/**
799-
* Checks whether the extension of the filename is one of those specified
800-
* using the case rules of the system.
826+
* Checks whether the extension of the filename is one of those specified.
801827
* <p>
802828
* This method obtains the extension as the textual part of the filename
803829
* after the last dot. There must be no directory separator after the dot.
804-
* The extension check is case sensitive on Unix and case insensitive on Windows.
830+
* The extension check is case-sensitive on all platforms.
805831
*
806832
* @param filename the filename to query, null returns false
807833
* @param extensions the extensions to check for, null checks for no extension
@@ -811,21 +837,27 @@ public static boolean isExtension(String filename, Collection extensions) {
811837
if (filename == null) {
812838
return false;
813839
}
814-
if (extensions == null) {
840+
if (extensions == null || extensions.isEmpty()) {
815841
return (indexOfExtension(filename) == -1);
816842
}
817-
String[] array = (String[]) extensions.toArray(new String[extensions.size()]);
818-
return isExtension(filename, array);
843+
String fileExt = getExtension(filename);
844+
for (Iterator it = extensions.iterator(); it.hasNext();) {
845+
if (fileExt.equals(it.next())) {
846+
return true;
847+
}
848+
}
849+
return false;
819850
}
820851

821852
//-----------------------------------------------------------------------
822853
/**
823-
* Checks a filename to see if it matches the specified wildcard matcher.
854+
* Checks a filename to see if it matches the specified wildcard matcher,
855+
* always testing case-sensitive.
824856
* <p>
825857
* The wildcard matcher uses the characters '?' and '*' to represent a
826858
* single or multiple wildcard characters.
827859
* This is the same as often found on Dos/Unix command lines.
828-
* The extension check is case sensitive on Unix and case insensitive on Windows.
860+
* The extension check is case-sensitive.
829861
* <pre>
830862
* wildcardMatch("c.txt", "*.txt") --> true
831863
* wildcardMatch("c.txt", "*.jpg") --> false
@@ -839,13 +871,52 @@ public static boolean isExtension(String filename, Collection extensions) {
839871
* @return true if the filename matches the wilcard string
840872
*/
841873
public static boolean wildcardMatch(String filename, String wildcardMatcher) {
874+
return wildcardMatch(filename, wildcardMatcher, false);
875+
}
876+
877+
/**
878+
* Checks a filename to see if it matches the specified wildcard matcher
879+
* using the case rules of the system.
880+
* <p>
881+
* The wildcard matcher uses the characters '?' and '*' to represent a
882+
* single or multiple wildcard characters.
883+
* This is the same as often found on Dos/Unix command lines.
884+
* The check is case-sensitive on Unix and case-insensitive on Windows.
885+
* <pre>
886+
* wildcardMatch("c.txt", "*.txt") --> true
887+
* wildcardMatch("c.txt", "*.jpg") --> false
888+
* wildcardMatch("a/b/c.txt", "a/b/*") --> true
889+
* wildcardMatch("c.txt", "*.???") --> true
890+
* wildcardMatch("c.txt", "*.????") --> false
891+
* </pre>
892+
*
893+
* @param filename the filename to match on
894+
* @param wildcardMatcher the wildcard string to match against
895+
* @return true if the filename matches the wilcard string
896+
*/
897+
public static boolean wildcardMatchOnSystem(String filename, String wildcardMatcher) {
898+
return wildcardMatch(filename, wildcardMatcher, true);
899+
}
900+
901+
/**
902+
* Checks a filename to see if it matches the specified wildcard matcher.
903+
* <p>
904+
* The wildcard matcher uses the characters '?' and '*' to represent a
905+
* single or multiple wildcard characters.
906+
*
907+
* @param filename the filename to match on
908+
* @param wildcardMatcher the wildcard string to match against
909+
* @param system whether to use the system (windows or unix)
910+
* @return true if the filename matches the wilcard string
911+
*/
912+
private static boolean wildcardMatch(String filename, String wildcardMatcher, boolean system) {
842913
if (filename == null && wildcardMatcher == null) {
843914
return true;
844915
}
845916
if (filename == null || wildcardMatcher == null) {
846917
return false;
847918
}
848-
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
919+
if (system && (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR)) {
849920
filename = filename.toLowerCase();
850921
wildcardMatcher = wildcardMatcher.toLowerCase();
851922
}

src/test/org/apache/commons/io/FilenameUtilsTestCase.java

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -457,21 +457,43 @@ public void testEquals() {
457457
assertEquals(false, FilenameUtils.equals("", null));
458458
assertEquals(true, FilenameUtils.equals("", ""));
459459
assertEquals(true, FilenameUtils.equals("file.txt", "file.txt"));
460-
assertEquals(WINDOWS, FilenameUtils.equals("file.txt", "FILE.TXT"));
460+
assertEquals(false, FilenameUtils.equals("file.txt", "FILE.TXT"));
461461
assertEquals(false, FilenameUtils.equals("a\\b\\file.txt", "a/b/file.txt"));
462462
}
463463

464+
public void testEqualsOnSystem() {
465+
assertEquals(true, FilenameUtils.equalsOnSystem(null, null));
466+
assertEquals(false, FilenameUtils.equalsOnSystem(null, ""));
467+
assertEquals(false, FilenameUtils.equalsOnSystem("", null));
468+
assertEquals(true, FilenameUtils.equalsOnSystem("", ""));
469+
assertEquals(true, FilenameUtils.equalsOnSystem("file.txt", "file.txt"));
470+
assertEquals(WINDOWS, FilenameUtils.equalsOnSystem("file.txt", "FILE.TXT"));
471+
assertEquals(false, FilenameUtils.equalsOnSystem("a\\b\\file.txt", "a/b/file.txt"));
472+
}
473+
474+
//-----------------------------------------------------------------------
464475
public void testEqualsNormalized() {
465476
assertEquals(true, FilenameUtils.equalsNormalized(null, null));
466477
assertEquals(false, FilenameUtils.equalsNormalized(null, ""));
467478
assertEquals(false, FilenameUtils.equalsNormalized("", null));
468479
assertEquals(true, FilenameUtils.equalsNormalized("", ""));
469480
assertEquals(true, FilenameUtils.equalsNormalized("file.txt", "file.txt"));
470-
assertEquals(WINDOWS, FilenameUtils.equalsNormalized("file.txt", "FILE.TXT"));
481+
assertEquals(false, FilenameUtils.equalsNormalized("file.txt", "FILE.TXT"));
471482
assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\file.txt", "a/b/file.txt"));
472483
assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\", "a/b"));
473484
}
474485

486+
public void testEqualsNormalizedOnSystem() {
487+
assertEquals(true, FilenameUtils.equalsNormalizedOnSystem(null, null));
488+
assertEquals(false, FilenameUtils.equalsNormalizedOnSystem(null, ""));
489+
assertEquals(false, FilenameUtils.equalsNormalizedOnSystem("", null));
490+
assertEquals(true, FilenameUtils.equalsNormalizedOnSystem("", ""));
491+
assertEquals(true, FilenameUtils.equalsNormalizedOnSystem("file.txt", "file.txt"));
492+
assertEquals(WINDOWS, FilenameUtils.equalsNormalizedOnSystem("file.txt", "FILE.TXT"));
493+
assertEquals(true, FilenameUtils.equalsNormalizedOnSystem("a\\b\\file.txt", "a/b/file.txt"));
494+
assertEquals(true, FilenameUtils.equalsNormalizedOnSystem("a\\b\\", "a/b"));
495+
}
496+
475497
//-----------------------------------------------------------------------
476498
public void testIsExtension() {
477499
assertEquals(false, FilenameUtils.isExtension(null, (String) null));
@@ -502,11 +524,7 @@ public void testIsExtension() {
502524
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", "txt"));
503525
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", "rtf"));
504526

505-
if (WINDOWS) {
506-
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", "TXT"));
507-
} else {
508-
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", "TXT"));
509-
}
527+
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", "TXT"));
510528
}
511529

512530
public void testIsExtensionArray() {
@@ -543,13 +561,8 @@ public void testIsExtensionArray() {
543561
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"rtf"}));
544562
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"rtf", "txt"}));
545563

546-
if (WINDOWS) {
547-
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT"}));
548-
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT", "RTF"}));
549-
} else {
550-
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT"}));
551-
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT", "RTF"}));
552-
}
564+
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT"}));
565+
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new String[] {"TXT", "RTF"}));
553566
}
554567

555568
public void testIsExtensionCollection() {
@@ -586,13 +599,8 @@ public void testIsExtensionCollection() {
586599
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"rtf"}))));
587600
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"rtf", "txt"}))));
588601

589-
if (WINDOWS) {
590-
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT"}))));
591-
assertEquals(true, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT", "RTF"}))));
592-
} else {
593-
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT"}))));
594-
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT", "RTF"}))));
595-
}
602+
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT"}))));
603+
assertEquals(false, FilenameUtils.isExtension("a.b\\file.txt", new ArrayList(Arrays.asList(new String[] {"TXT", "RTF"}))));
596604
}
597605

598606
}

0 commit comments

Comments
 (0)