1818import java .io .File ;
1919import java .util .ArrayList ;
2020import java .util .Collection ;
21+ import java .util .Stack ;
2122
2223/**
2324 * Utility class that provides methods to manipulate filenames and filepaths.
@@ -852,63 +853,69 @@ public static boolean wildcardMatch(String filename, String wildcardMatcher) {
852853 boolean anyChars = false ;
853854 int textIdx = 0 ;
854855 int wcsIdx = 0 ;
855-
856- // loop whilst tokens and text left to process
857- while (wcsIdx < wcs .length && textIdx < filename .length ()) {
858-
859- if (wcs [wcsIdx ].equals ("?" )) {
860- // ? so move to next text char
861- textIdx ++;
862- anyChars = false ;
863-
864- } else if (wcs [wcsIdx ].equals ("*" )) {
865- // set any chars status
856+ Stack backtrack = new Stack ();
857+
858+ // loop around a backtrack stack, to handle complex * matching
859+ do {
860+ if (backtrack .size () > 0 ) {
861+ int [] array = (int []) backtrack .pop ();
862+ wcsIdx = array [0 ];
863+ textIdx = array [1 ];
866864 anyChars = true ;
867-
868- } else {
869- // matching text token
870- if (anyChars ) {
871- // any chars then try to locate text token
872- textIdx = filename .indexOf (wcs [wcsIdx ], textIdx );
873- if (textIdx == -1 ) {
874- // token not found
875- return false ;
865+ }
866+
867+ // loop whilst tokens and text left to process
868+ while (wcsIdx < wcs .length ) {
869+
870+ if (wcs [wcsIdx ].equals ("?" )) {
871+ // ? so move to next text char
872+ textIdx ++;
873+ anyChars = false ;
874+
875+ } else if (wcs [wcsIdx ].equals ("*" )) {
876+ // set any chars status
877+ anyChars = true ;
878+ if (wcsIdx == wcs .length - 1 ) {
879+ textIdx = filename .length ();
876880 }
881+
877882 } else {
878- // matching from current position
879- if (!filename .startsWith (wcs [wcsIdx ], textIdx )) {
880- // couldnt match token
881- return false ;
883+ // matching text token
884+ if (anyChars ) {
885+ // any chars then try to locate text token
886+ textIdx = filename .indexOf (wcs [wcsIdx ], textIdx );
887+ if (textIdx == -1 ) {
888+ // token not found
889+ break ;
890+ }
891+ int repeat = filename .indexOf (wcs [wcsIdx ], textIdx + 1 );
892+ if (repeat >= 0 ) {
893+ backtrack .push (new int [] {wcsIdx , repeat });
894+ }
895+ } else {
896+ // matching from current position
897+ if (!filename .startsWith (wcs [wcsIdx ], textIdx )) {
898+ // couldnt match token
899+ break ;
900+ }
882901 }
902+
903+ // matched text token, move text index to end of matched token
904+ textIdx += wcs [wcsIdx ].length ();
905+ anyChars = false ;
883906 }
884-
885- // matched text token, move text index to end of matched token
886- textIdx += wcs [wcsIdx ].length ();
887- anyChars = false ;
907+
908+ wcsIdx ++;
888909 }
889-
890- wcsIdx ++;
891- }
892-
893- // didnt match all wildcards
894- if (wcsIdx < wcs .length ) {
895- // ok if one remaining and wildcard or empty
896- if (wcsIdx + 1 != wcs .length || !(wcs [wcsIdx ].equals ("*" ) || wcs [wcsIdx ].equals ("" )) ) {
897- return false ;
910+
911+ // full match
912+ if (wcsIdx == wcs .length && textIdx == filename .length ()) {
913+ return true ;
898914 }
899- }
915+
916+ } while (backtrack .size () > 0 );
900917
901- // ran out of text chars
902- if (textIdx > filename .length ()) {
903- return false ;
904- }
905-
906- // didnt match all text chars, only ok if any chars set
907- if (textIdx < filename .length () && !anyChars ) {
908- return false ;
909- }
910-
911- return true ;
918+ return false ;
912919 }
913920
914921 // used by wildcardMatch
@@ -927,7 +934,12 @@ static String[] splitOnTokens(String text) {
927934 list .add (buffer .toString ());
928935 buffer .setLength (0 );
929936 }
930- list .add (new String (new char [] { array [i ] }));
937+ if (array [i ] == '?' ) {
938+ list .add ("?" );
939+ } else if (list .size () == 0 ||
940+ (i > 0 && list .get (list .size () - 1 ).equals ("*" ) == false )) {
941+ list .add ("*" );
942+ }
931943 } else {
932944 buffer .append (array [i ]);
933945 }
0 commit comments