001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    
022    import java.io.IOException;
023    import java.io.InputStream;
024    import java.io.InputStreamReader;
025    
026    import java.net.URL;
027    
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.Enumeration;
031    import java.util.List;
032    import java.util.Map;
033    import java.util.StringTokenizer;
034    import java.util.regex.Matcher;
035    import java.util.regex.Pattern;
036    
037    /**
038     * @author Brian Wing Shun Chan
039     * @author Sandeep Soni
040     * @author Ganesh Ram
041     */
042    public class StringUtil {
043    
044            public static String add(String s, String add) {
045                    return add(s, add, StringPool.COMMA);
046            }
047    
048            public static String add(String s, String add, String delimiter) {
049                    return add(s, add, delimiter, false);
050            }
051    
052            public static String add(
053                    String s, String add, String delimiter, boolean allowDuplicates) {
054    
055                    if ((add == null) || (delimiter == null)) {
056                            return null;
057                    }
058    
059                    if (s == null) {
060                            s = StringPool.BLANK;
061                    }
062    
063                    if (allowDuplicates || !contains(s, add, delimiter)) {
064                            StringBundler sb = new StringBundler();
065    
066                            sb.append(s);
067    
068                            if (Validator.isNull(s) || s.endsWith(delimiter)) {
069                                    sb.append(add);
070                                    sb.append(delimiter);
071                            }
072                            else {
073                                    sb.append(delimiter);
074                                    sb.append(add);
075                                    sb.append(delimiter);
076                            }
077    
078                            s = sb.toString();
079                    }
080    
081                    return s;
082            }
083    
084            public static String bytesToHexString(byte[] bytes) {
085                    StringBuilder sb = new StringBuilder(bytes.length * 2);
086    
087                    for (byte b : bytes) {
088                            String hex = Integer.toHexString(
089                                    0x0100 + (b & 0x00FF)).substring(1);
090    
091                            if (hex.length() < 2) {
092                                    sb.append("0");
093                            }
094    
095                            sb.append(hex);
096                    }
097    
098                    return sb.toString();
099            }
100    
101            public static boolean contains(String s, String text) {
102                    return contains(s, text, StringPool.COMMA);
103            }
104    
105            public static boolean contains(String s, String text, String delimiter) {
106                    if ((s == null) || (text == null) || (delimiter == null)) {
107                            return false;
108                    }
109    
110                    if (!s.endsWith(delimiter)) {
111                            s = s.concat(delimiter);
112                    }
113    
114                    String dtd = delimiter.concat(text).concat(delimiter);
115    
116                    int pos = s.indexOf(dtd);
117    
118                    if (pos == -1) {
119                            String td = text.concat(delimiter);
120    
121                            if (s.startsWith(td)) {
122                                    return true;
123                            }
124    
125                            return false;
126                    }
127    
128                    return true;
129            }
130    
131            public static int count(String s, String text) {
132                    if ((s == null) || (text == null)) {
133                            return 0;
134                    }
135    
136                    int count = 0;
137    
138                    int pos = s.indexOf(text);
139    
140                    while (pos != -1) {
141                            pos = s.indexOf(text, pos + text.length());
142    
143                            count++;
144                    }
145    
146                    return count;
147            }
148    
149            public static boolean endsWith(String s, char end) {
150                    return endsWith(s, (new Character(end)).toString());
151            }
152    
153            public static boolean endsWith(String s, String end) {
154                    if ((s == null) || (end == null)) {
155                            return false;
156                    }
157    
158                    if (end.length() > s.length()) {
159                            return false;
160                    }
161    
162                    String temp = s.substring(s.length() - end.length(), s.length());
163    
164                    if (temp.equalsIgnoreCase(end)) {
165                            return true;
166                    }
167                    else {
168                            return false;
169                    }
170            }
171    
172            public static String extractChars(String s) {
173                    if (s == null) {
174                            return StringPool.BLANK;
175                    }
176    
177                    StringBuilder sb = new StringBuilder();
178    
179                    char[] chars = s.toCharArray();
180    
181                    for (char c : chars) {
182                            if (Validator.isChar(c)) {
183                                    sb.append(c);
184                            }
185                    }
186    
187                    return sb.toString();
188            }
189    
190            public static String extractDigits(String s) {
191                    if (s == null) {
192                            return StringPool.BLANK;
193                    }
194    
195                    StringBuilder sb = new StringBuilder();
196    
197                    char[] chars = s.toCharArray();
198    
199                    for (char c : chars) {
200                            if (Validator.isDigit(c)) {
201                                    sb.append(c);
202                            }
203                    }
204    
205                    return sb.toString();
206            }
207    
208            public static String extractFirst(String s, String delimiter) {
209                    if (s == null) {
210                            return null;
211                    }
212                    else {
213                            String[] array = split(s, delimiter);
214    
215                            if (array.length > 0) {
216                                    return array[0];
217                            }
218                            else {
219                                    return null;
220                            }
221                    }
222            }
223    
224            public static String extractLast(String s, String delimiter) {
225                    if (s == null) {
226                            return null;
227                    }
228                    else {
229                            String[] array = split(s, delimiter);
230    
231                            if (array.length > 0) {
232                                    return array[array.length - 1];
233                            }
234                            else {
235                                    return null;
236                            }
237                    }
238            }
239    
240            /**
241             * @deprecated
242             */
243            public static String highlight(String s, String keywords) {
244                    return highlight(s, keywords, "<span class=\"highlight\">", "</span>");
245            }
246    
247            /**
248             * @deprecated
249             */
250            public static String highlight(
251                    String s, String keywords, String highlight1, String highlight2) {
252    
253                    if (Validator.isNull(s) || Validator.isNull(keywords)) {
254                            return s;
255                    }
256    
257                    Pattern pattern = Pattern.compile(
258                            Pattern.quote(keywords), Pattern.CASE_INSENSITIVE);
259    
260                    return _highlight(s, pattern, highlight1, highlight2);
261            }
262    
263            public static String highlight(String s, String[] queryTerms) {
264                    return highlight(
265                            s, queryTerms, "<span class=\"highlight\">", "</span>");
266            }
267    
268            public static String highlight(
269                    String s, String[] queryTerms, String highlight1, String highlight2) {
270    
271                    if (Validator.isNull(s) || Validator.isNull(queryTerms)) {
272                            return s;
273                    }
274    
275                    StringBundler sb = null;
276    
277                    if (queryTerms.length == 0) {
278                            sb = new StringBundler();
279                    }
280                    else {
281                            sb = new StringBundler(2 * queryTerms.length - 1);
282                    }
283    
284                    for (int i = 0; i < queryTerms.length; i++) {
285                            sb.append(Pattern.quote(queryTerms[i].trim()));
286    
287                            if ((i + 1) < queryTerms.length) {
288                                    sb.append(StringPool.PIPE);
289                            }
290                    }
291    
292                    int flags =
293                            Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
294    
295                    Pattern pattern = Pattern.compile(sb.toString(), flags);
296    
297                    return _highlight(s, pattern, highlight1, highlight2);
298            }
299    
300            public static String insert(String s, String insert, int offset) {
301                    if (s == null) {
302                            return null;
303                    }
304    
305                    if (insert == null) {
306                            return s;
307                    }
308    
309                    if (offset > s.length()) {
310                            offset = s.length();
311                    }
312    
313                    StringBuilder sb = new StringBuilder(s);
314    
315                    sb.insert(offset, insert);
316    
317                    return sb.toString();
318            }
319    
320            public static String lowerCase(String s) {
321                    if (s == null) {
322                            return null;
323                    }
324                    else {
325                            return s.toLowerCase();
326                    }
327            }
328    
329            public static boolean matches(String s, String pattern) {
330                    String[] array = pattern.split("\\*");
331    
332                    for (String element : array) {
333                            int pos = s.indexOf(element);
334    
335                            if (pos == -1) {
336                                    return false;
337                            }
338    
339                            s = s.substring(pos + element.length());
340                    }
341    
342                    return true;
343            }
344    
345            public static boolean matchesIgnoreCase(String s, String pattern) {
346                    return matches(lowerCase(s), lowerCase(pattern));
347            }
348    
349            public static String merge(boolean[] array) {
350                    return merge(array, StringPool.COMMA);
351            }
352    
353            public static String merge(boolean[] array, String delimiter) {
354                    if (array == null) {
355                            return null;
356                    }
357    
358                    StringBundler sb = null;
359    
360                    if (array.length == 0) {
361                            sb = new StringBundler();
362                    }
363                    else {
364                            sb = new StringBundler(2 * array.length - 1);
365                    }
366    
367                    for (int i = 0; i < array.length; i++) {
368                            sb.append(String.valueOf(array[i]).trim());
369    
370                            if ((i + 1) != array.length) {
371                                    sb.append(delimiter);
372                            }
373                    }
374    
375                    return sb.toString();
376            }
377    
378            public static String merge(Collection<?> col) {
379                    return merge(col, StringPool.COMMA);
380            }
381    
382            public static String merge(Collection<?> col, String delimiter) {
383                    if (col == null) {
384                            return null;
385                    }
386    
387                    return merge(col.toArray(new Object[col.size()]), delimiter);
388            }
389    
390            public static String merge(double[] array) {
391                    return merge(array, StringPool.COMMA);
392            }
393    
394            public static String merge(double[] array, String delimiter) {
395                    if (array == null) {
396                            return null;
397                    }
398    
399                    StringBundler sb = null;
400    
401                    if (array.length == 0) {
402                            sb = new StringBundler();
403                    }
404                    else {
405                            sb = new StringBundler(2 * array.length - 1);
406                    }
407    
408                    for (int i = 0; i < array.length; i++) {
409                            sb.append(String.valueOf(array[i]).trim());
410    
411                            if ((i + 1) != array.length) {
412                                    sb.append(delimiter);
413                            }
414                    }
415    
416                    return sb.toString();
417            }
418    
419            public static String merge(float[] array) {
420                    return merge(array, StringPool.COMMA);
421            }
422    
423            public static String merge(float[] array, String delimiter) {
424                    if (array == null) {
425                            return null;
426                    }
427    
428                    StringBundler sb = null;
429    
430                    if (array.length == 0) {
431                            sb = new StringBundler();
432                    }
433                    else {
434                            sb = new StringBundler(2 * array.length - 1);
435                    }
436    
437                    for (int i = 0; i < array.length; i++) {
438                            sb.append(String.valueOf(array[i]).trim());
439    
440                            if ((i + 1) != array.length) {
441                                    sb.append(delimiter);
442                            }
443                    }
444    
445                    return sb.toString();
446            }
447    
448            public static String merge(int[] array) {
449                    return merge(array, StringPool.COMMA);
450            }
451    
452            public static String merge(int[] array, String delimiter) {
453                    if (array == null) {
454                            return null;
455                    }
456    
457                    StringBundler sb = null;
458    
459                    if (array.length == 0) {
460                            sb = new StringBundler();
461                    }
462                    else {
463                            sb = new StringBundler(2 * array.length - 1);
464                    }
465    
466                    for (int i = 0; i < array.length; i++) {
467                            sb.append(String.valueOf(array[i]).trim());
468    
469                            if ((i + 1) != array.length) {
470                                    sb.append(delimiter);
471                            }
472                    }
473    
474                    return sb.toString();
475            }
476    
477            public static String merge(long[] array) {
478                    return merge(array, StringPool.COMMA);
479            }
480    
481            public static String merge(long[] array, String delimiter) {
482                    if (array == null) {
483                            return null;
484                    }
485    
486                    StringBundler sb = null;
487    
488                    if (array.length == 0) {
489                            sb = new StringBundler();
490                    }
491                    else {
492                            sb = new StringBundler(2 * array.length - 1);
493                    }
494    
495                    for (int i = 0; i < array.length; i++) {
496                            sb.append(String.valueOf(array[i]).trim());
497    
498                            if ((i + 1) != array.length) {
499                                    sb.append(delimiter);
500                            }
501                    }
502    
503                    return sb.toString();
504            }
505    
506            public static String merge(Object[] array) {
507                    return merge(array, StringPool.COMMA);
508            }
509    
510            public static String merge(Object[] array, String delimiter) {
511                    if (array == null) {
512                            return null;
513                    }
514    
515                    StringBundler sb = null;
516    
517                    if (array.length == 0) {
518                            sb = new StringBundler();
519                    }
520                    else {
521                            sb = new StringBundler(2 * array.length - 1);
522                    }
523    
524                    for (int i = 0; i < array.length; i++) {
525                            sb.append(String.valueOf(array[i]).trim());
526    
527                            if ((i + 1) != array.length) {
528                                    sb.append(delimiter);
529                            }
530                    }
531    
532                    return sb.toString();
533            }
534    
535            public static String merge(short[] array) {
536                    return merge(array, StringPool.COMMA);
537            }
538    
539            public static String merge(short[] array, String delimiter) {
540                    if (array == null) {
541                            return null;
542                    }
543    
544                    StringBundler sb = null;
545    
546                    if (array.length == 0) {
547                            sb = new StringBundler();
548                    }
549                    else {
550                            sb = new StringBundler(2 * array.length - 1);
551                    }
552    
553                    for (int i = 0; i < array.length; i++) {
554                            sb.append(String.valueOf(array[i]).trim());
555    
556                            if ((i + 1) != array.length) {
557                                    sb.append(delimiter);
558                            }
559                    }
560    
561                    return sb.toString();
562            }
563    
564            public static String quote(String s) {
565                    return quote(s, CharPool.APOSTROPHE);
566            }
567    
568            public static String quote(String s, char quote) {
569                    if (s == null) {
570                            return null;
571                    }
572    
573                    return quote(s, String.valueOf(quote));
574            }
575    
576            public static String quote(String s, String quote) {
577                    if (s == null) {
578                            return null;
579                    }
580    
581                    return quote.concat(s).concat(quote);
582            }
583    
584            public static String randomize(String s) {
585                    return Randomizer.getInstance().randomize(s);
586            }
587    
588            public static String read(ClassLoader classLoader, String name)
589                    throws IOException {
590    
591                    return read(classLoader, name, false);
592            }
593    
594            public static String read(ClassLoader classLoader, String name, boolean all)
595                    throws IOException {
596    
597                    if (all) {
598                            StringBundler sb = new StringBundler();
599    
600                            Enumeration<URL> enu = classLoader.getResources(name);
601    
602                            while (enu.hasMoreElements()) {
603                                    URL url = enu.nextElement();
604    
605                                    InputStream is = url.openStream();
606    
607                                    if (is == null) {
608                                            throw new IOException(
609                                                    "Unable to open resource at " + url.toString());
610                                    }
611    
612                                    String s = read(is);
613    
614                                    if (s != null) {
615                                            sb.append(s);
616                                            sb.append(StringPool.NEW_LINE);
617                                    }
618    
619                                    is.close();
620                            }
621    
622                            return sb.toString().trim();
623                    }
624                    else {
625                            InputStream is = classLoader.getResourceAsStream(name);
626    
627                            if (is == null) {
628                                    throw new IOException(
629                                            "Unable to open resource in class loader " + name);
630                            }
631    
632                            String s = read(is);
633    
634                            is.close();
635    
636                            return s;
637                    }
638            }
639    
640            public static String read(InputStream is) throws IOException {
641                    StringBundler sb = new StringBundler();
642    
643                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
644                            new InputStreamReader(is));
645    
646                    String line = null;
647    
648                    while ((line = unsyncBufferedReader.readLine()) != null) {
649                            sb.append(line);
650                            sb.append(CharPool.NEW_LINE);
651                    }
652    
653                    unsyncBufferedReader.close();
654    
655                    return sb.toString().trim();
656            }
657    
658            public static void readLines(InputStream is, Collection<String> lines)
659                    throws IOException {
660    
661                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
662                            new InputStreamReader(is));
663    
664                    String line = null;
665    
666                    while ((line = unsyncBufferedReader.readLine()) != null) {
667                            lines.add(line);
668                    }
669    
670                    unsyncBufferedReader.close();
671            }
672    
673            public static String remove(String s, String remove) {
674                    return remove(s, remove, StringPool.COMMA);
675            }
676    
677            public static String remove(String s, String remove, String delimiter) {
678                    if ((s == null) || (remove == null) || (delimiter == null)) {
679                            return null;
680                    }
681    
682                    if (Validator.isNotNull(s) && !s.endsWith(delimiter)) {
683                            s += delimiter;
684                    }
685    
686                    String drd = delimiter.concat(remove).concat(delimiter);
687    
688                    String rd = remove.concat(delimiter);
689    
690                    while (contains(s, remove, delimiter)) {
691                            int pos = s.indexOf(drd);
692    
693                            if (pos == -1) {
694                                    if (s.startsWith(rd)) {
695                                            int x = remove.length() + delimiter.length();
696                                            int y = s.length();
697    
698                                            s = s.substring(x, y);
699                                    }
700                            }
701                            else {
702                                    int x = pos + remove.length() + delimiter.length();
703                                    int y = s.length();
704    
705                                    String temp = s.substring(0, pos);
706    
707                                    s = temp.concat(s.substring(x, y));
708                            }
709                    }
710    
711                    return s;
712            }
713    
714            public static String replace(String s, char oldSub, char newSub) {
715                    if (s == null) {
716                            return null;
717                    }
718    
719                    return s.replace(oldSub, newSub);
720            }
721    
722            public static String replace(String s, char oldSub, String newSub) {
723                    if ((s == null) || (newSub == null)) {
724                            return null;
725                    }
726    
727                    // The number 5 is arbitrary and is used as extra padding to reduce
728                    // buffer expansion
729    
730                    StringBuilder sb = new StringBuilder(s.length() + 5 * newSub.length());
731    
732                    char[] chars = s.toCharArray();
733    
734                    for (char c : chars) {
735                            if (c == oldSub) {
736                                    sb.append(newSub);
737                            }
738                            else {
739                                    sb.append(c);
740                            }
741                    }
742    
743                    return sb.toString();
744            }
745    
746            public static String replace(String s, String oldSub, String newSub) {
747                    return replace(s, oldSub, newSub, 0);
748            }
749    
750            public static String replace(
751                    String s, String oldSub, String newSub, int fromIndex) {
752    
753                    if (s == null) {
754                            return null;
755                    }
756    
757                    if ((oldSub == null) || oldSub.equals(StringPool.BLANK)) {
758                            return s;
759                    }
760    
761                    if (newSub == null) {
762                            newSub = StringPool.BLANK;
763                    }
764    
765                    int y = s.indexOf(oldSub, fromIndex);
766    
767                    if (y >= 0) {
768                            StringBundler sb = new StringBundler();
769    
770                            int length = oldSub.length();
771                            int x = 0;
772    
773                            while (x <= y) {
774                                    sb.append(s.substring(x, y));
775                                    sb.append(newSub);
776    
777                                    x = y + length;
778                                    y = s.indexOf(oldSub, x);
779                            }
780    
781                            sb.append(s.substring(x));
782    
783                            return sb.toString();
784                    }
785                    else {
786                            return s;
787                    }
788            }
789    
790            public static String replace(
791                    String s, String begin, String end, Map<String, String> values) {
792    
793                    StringBundler sb = replaceToStringBundler(s, begin, end, values);
794    
795                    return sb.toString();
796            }
797    
798            public static String replace(String s, String[] oldSubs, String[] newSubs) {
799                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
800                            return null;
801                    }
802    
803                    if (oldSubs.length != newSubs.length) {
804                            return s;
805                    }
806    
807                    for (int i = 0; i < oldSubs.length; i++) {
808                            s = replace(s, oldSubs[i], newSubs[i]);
809                    }
810    
811                    return s;
812            }
813    
814            public static String replace(
815                    String s, String[] oldSubs, String[] newSubs, boolean exactMatch) {
816    
817                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
818                            return null;
819                    }
820    
821                    if (oldSubs.length != newSubs.length) {
822                            return s;
823                    }
824    
825                    if (!exactMatch) {
826                            replace(s, oldSubs, newSubs);
827                    }
828                    else {
829                            for (int i = 0; i < oldSubs.length; i++) {
830                                    s = s.replaceAll("\\b" + oldSubs[i] + "\\b" , newSubs[i]);
831                            }
832                    }
833    
834                    return s;
835            }
836    
837            public static String replaceFirst(String s, char oldSub, char newSub) {
838                    if (s == null) {
839                            return null;
840                    }
841    
842                    return replaceFirst(s, String.valueOf(oldSub), String.valueOf(newSub));
843            }
844    
845            public static String replaceFirst(String s, char oldSub, String newSub) {
846                    if ((s == null) || (newSub == null)) {
847                            return null;
848                    }
849    
850                    return replaceFirst(s, String.valueOf(oldSub), newSub);
851            }
852    
853            public static String replaceFirst(String s, String oldSub, String newSub) {
854                    if ((s == null) || (oldSub == null) || (newSub == null)) {
855                            return null;
856                    }
857    
858                    if (oldSub.equals(newSub)) {
859                            return s;
860                    }
861    
862                    int y = s.indexOf(oldSub);
863    
864                    if (y >= 0) {
865                            return s.substring(0, y).concat(newSub).concat(
866                                    s.substring(y + oldSub.length()));
867                    }
868                    else {
869                            return s;
870                    }
871            }
872    
873            public static String replaceFirst(
874                    String s, String[] oldSubs, String[] newSubs) {
875    
876                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
877                            return null;
878                    }
879    
880                    if (oldSubs.length != newSubs.length) {
881                            return s;
882                    }
883    
884                    for (int i = 0; i < oldSubs.length; i++) {
885                            s = replaceFirst(s, oldSubs[i], newSubs[i]);
886                    }
887    
888                    return s;
889            }
890    
891            public static String replaceLast(String s, char oldSub, char newSub) {
892                    if (s == null) {
893                            return null;
894                    }
895    
896                    return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub));
897            }
898    
899            public static String replaceLast(String s, char oldSub, String newSub) {
900                    if ((s == null) || (newSub == null)) {
901                            return null;
902                    }
903    
904                    return replaceLast(s, String.valueOf(oldSub), newSub);
905            }
906    
907            public static String replaceLast(String s, String oldSub, String newSub) {
908                    if ((s == null) || (oldSub == null) || (newSub == null)) {
909                            return null;
910                    }
911    
912                    if (oldSub.equals(newSub)) {
913                            return s;
914                    }
915    
916                    int y = s.lastIndexOf(oldSub);
917    
918                    if (y >= 0) {
919                            return s.substring(0, y).concat(newSub).concat(
920                                    s.substring(y + oldSub.length()));
921                    }
922                    else {
923                            return s;
924                    }
925            }
926    
927            public static String replaceLast(
928                    String s, String[] oldSubs, String[] newSubs) {
929    
930                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
931                            return null;
932                    }
933    
934                    if (oldSubs.length != newSubs.length) {
935                            return s;
936                    }
937    
938                    for (int i = 0; i < oldSubs.length; i++) {
939                            s = replaceLast(s, oldSubs[i], newSubs[i]);
940                    }
941    
942                    return s;
943            }
944    
945            public static StringBundler replaceToStringBundler(
946                    String s, String begin, String end, Map<String, String> values) {
947    
948                    if ((s == null) || (begin == null) || (end == null) ||
949                            (values == null) || (values.size() == 0)) {
950    
951                            return new StringBundler(s);
952                    }
953    
954                    StringBundler sb = new StringBundler(values.size() * 2 + 1);
955    
956                    int pos = 0;
957    
958                    while (true) {
959                            int x = s.indexOf(begin, pos);
960                            int y = s.indexOf(end, x + begin.length());
961    
962                            if ((x == -1) || (y == -1)) {
963                                    sb.append(s.substring(pos, s.length()));
964    
965                                    break;
966                            }
967                            else {
968                                    sb.append(s.substring(pos, x));
969    
970                                    String oldValue = s.substring(x + begin.length(), y);
971    
972                                    String newValue = values.get(oldValue);
973    
974                                    if (newValue == null) {
975                                            newValue = oldValue;
976                                    }
977    
978                                    sb.append(newValue);
979    
980                                    pos = y + end.length();
981                            }
982                    }
983    
984                    return sb;
985            }
986    
987            public static StringBundler replaceWithStringBundler(
988                    String s, String begin, String end, Map<String, StringBundler> values) {
989    
990                    if ((s == null) || (begin == null) || (end == null) ||
991                            (values == null) || (values.size() == 0)) {
992    
993                            return new StringBundler(s);
994                    }
995    
996                    int size = values.size() + 1;
997    
998                    for (StringBundler valueSB : values.values()) {
999                            size += valueSB.index();
1000                    }
1001    
1002                    StringBundler sb = new StringBundler(size);
1003    
1004                    int pos = 0;
1005    
1006                    while (true) {
1007                            int x = s.indexOf(begin, pos);
1008                            int y = s.indexOf(end, x + begin.length());
1009    
1010                            if ((x == -1) || (y == -1)) {
1011                                    sb.append(s.substring(pos, s.length()));
1012    
1013                                    break;
1014                            }
1015                            else {
1016                                    sb.append(s.substring(pos, x));
1017    
1018                                    String oldValue = s.substring(x + begin.length(), y);
1019    
1020                                    StringBundler newValue = values.get(oldValue);
1021    
1022                                    if (newValue == null) {
1023                                            sb.append(oldValue);
1024                                    }
1025                                    else {
1026                                            sb.append(newValue);
1027                                    }
1028    
1029                                    pos = y + end.length();
1030                            }
1031                    }
1032    
1033                    return sb;
1034            }
1035    
1036            public static String reverse(String s) {
1037                    if (s == null) {
1038                            return null;
1039                    }
1040    
1041                    char[] chars = s.toCharArray();
1042                    char[] reverse = new char[chars.length];
1043    
1044                    for (int i = 0; i < chars.length; i++) {
1045                            reverse[i] = chars[chars.length - i - 1];
1046                    }
1047    
1048                    return new String(reverse);
1049            }
1050    
1051            public static String safePath(String path) {
1052                    return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH);
1053            }
1054    
1055            public static String shorten(String s) {
1056                    return shorten(s, 20);
1057            }
1058    
1059            public static String shorten(String s, int length) {
1060                    return shorten(s, length, "...");
1061            }
1062    
1063            public static String shorten(String s, int length, String suffix) {
1064                    if ((s == null) || (suffix == null)) {
1065                            return null;
1066                    }
1067    
1068                    if (s.length() > length) {
1069                            for (int j = length; j >= 0; j--) {
1070                                    if (Character.isWhitespace(s.charAt(j))) {
1071                                            length = j;
1072    
1073                                            break;
1074                                    }
1075                            }
1076    
1077                            String temp = s.substring(0, length);
1078    
1079                            s = temp.concat(suffix);
1080                    }
1081    
1082                    return s;
1083            }
1084    
1085            public static String shorten(String s, String suffix) {
1086                    return shorten(s, 20, suffix);
1087            }
1088    
1089            public static String[] split(String s) {
1090                    return split(s, StringPool.COMMA);
1091            }
1092    
1093            public static boolean[] split(String s, boolean x) {
1094                    return split(s, StringPool.COMMA, x);
1095            }
1096    
1097            public static double[] split(String s, double x) {
1098                    return split(s, StringPool.COMMA, x);
1099            }
1100    
1101            public static float[] split(String s, float x) {
1102                    return split(s, StringPool.COMMA, x);
1103            }
1104    
1105            public static int[] split(String s, int x) {
1106                    return split(s, StringPool.COMMA, x);
1107            }
1108    
1109            public static long[] split(String s, long x) {
1110                    return split(s, StringPool.COMMA, x);
1111            }
1112    
1113            public static short[] split(String s, short x) {
1114                    return split(s, StringPool.COMMA, x);
1115            }
1116    
1117            public static String[] split(String s, String delimiter) {
1118                    if ((Validator.isNull(s)) || (delimiter == null) ||
1119                            (delimiter.equals(StringPool.BLANK))) {
1120    
1121                            return new String[0];
1122                    }
1123    
1124                    s = s.trim();
1125    
1126                    if (s.equals(delimiter)) {
1127                            return new String[0];
1128                    }
1129    
1130                    List<String> nodeValues = new ArrayList<String>();
1131    
1132                    if (delimiter.equals(StringPool.NEW_LINE) ||
1133                            delimiter.equals(StringPool.RETURN)) {
1134    
1135                            try {
1136                                    UnsyncBufferedReader unsyncBufferedReader =
1137                                            new UnsyncBufferedReader(new UnsyncStringReader(s));
1138    
1139                                    String line = null;
1140    
1141                                    while ((line = unsyncBufferedReader.readLine()) != null) {
1142                                            nodeValues.add(line);
1143                                    }
1144    
1145                                    unsyncBufferedReader.close();
1146                            }
1147                            catch (IOException ioe) {
1148                                    _log.error(ioe.getMessage());
1149                            }
1150                    }
1151                    else {
1152                            int offset = 0;
1153                            int pos = s.indexOf(delimiter, offset);
1154    
1155                            while (pos != -1) {
1156                                    nodeValues.add(s.substring(offset, pos));
1157    
1158                                    offset = pos + delimiter.length();
1159                                    pos = s.indexOf(delimiter, offset);
1160                            }
1161    
1162                            if (offset < s.length()) {
1163                                    nodeValues.add(s.substring(offset));
1164                            }
1165                    }
1166    
1167                    return nodeValues.toArray(new String[nodeValues.size()]);
1168            }
1169    
1170            public static boolean[] split(String s, String delimiter, boolean x) {
1171                    String[] array = split(s, delimiter);
1172                    boolean[] newArray = new boolean[array.length];
1173    
1174                    for (int i = 0; i < array.length; i++) {
1175                            boolean value = x;
1176    
1177                            try {
1178                                    value = Boolean.valueOf(array[i]).booleanValue();
1179                            }
1180                            catch (Exception e) {
1181                            }
1182    
1183                            newArray[i] = value;
1184                    }
1185    
1186                    return newArray;
1187            }
1188    
1189            public static double[] split(String s, String delimiter, double x) {
1190                    String[] array = split(s, delimiter);
1191                    double[] newArray = new double[array.length];
1192    
1193                    for (int i = 0; i < array.length; i++) {
1194                            double value = x;
1195    
1196                            try {
1197                                    value = Double.parseDouble(array[i]);
1198                            }
1199                            catch (Exception e) {
1200                            }
1201    
1202                            newArray[i] = value;
1203                    }
1204    
1205                    return newArray;
1206            }
1207    
1208            public static float[] split(String s, String delimiter, float x) {
1209                    String[] array = split(s, delimiter);
1210                    float[] newArray = new float[array.length];
1211    
1212                    for (int i = 0; i < array.length; i++) {
1213                            float value = x;
1214    
1215                            try {
1216                                    value = Float.parseFloat(array[i]);
1217                            }
1218                            catch (Exception e) {
1219                            }
1220    
1221                            newArray[i] = value;
1222                    }
1223    
1224                    return newArray;
1225            }
1226    
1227            public static int[] split(String s, String delimiter, int x) {
1228                    String[] array = split(s, delimiter);
1229                    int[] newArray = new int[array.length];
1230    
1231                    for (int i = 0; i < array.length; i++) {
1232                            int value = x;
1233    
1234                            try {
1235                                    value = Integer.parseInt(array[i]);
1236                            }
1237                            catch (Exception e) {
1238                            }
1239    
1240                            newArray[i] = value;
1241                    }
1242    
1243                    return newArray;
1244            }
1245    
1246            public static long[] split(String s, String delimiter, long x) {
1247                    String[] array = split(s, delimiter);
1248                    long[] newArray = new long[array.length];
1249    
1250                    for (int i = 0; i < array.length; i++) {
1251                            long value = x;
1252    
1253                            try {
1254                                    value = Long.parseLong(array[i]);
1255                            }
1256                            catch (Exception e) {
1257                            }
1258    
1259                            newArray[i] = value;
1260                    }
1261    
1262                    return newArray;
1263            }
1264    
1265            public static short[] split(String s, String delimiter, short x) {
1266                    String[] array = split(s, delimiter);
1267                    short[] newArray = new short[array.length];
1268    
1269                    for (int i = 0; i < array.length; i++) {
1270                            short value = x;
1271    
1272                            try {
1273                                    value = Short.parseShort(array[i]);
1274                            }
1275                            catch (Exception e) {
1276                            }
1277    
1278                            newArray[i] = value;
1279                    }
1280    
1281                    return newArray;
1282            }
1283    
1284            public static boolean startsWith(String s, char begin) {
1285                    return startsWith(s, (new Character(begin)).toString());
1286            }
1287    
1288            public static boolean startsWith(String s, String start) {
1289                    if ((s == null) || (start == null)) {
1290                            return false;
1291                    }
1292    
1293                    if (start.length() > s.length()) {
1294                            return false;
1295                    }
1296    
1297                    String temp = s.substring(0, start.length());
1298    
1299                    if (temp.equalsIgnoreCase(start)) {
1300                            return true;
1301                    }
1302                    else {
1303                            return false;
1304                    }
1305            }
1306    
1307            /**
1308             * Return the number of starting letters that s1 and s2 have in common
1309             * before they deviate.
1310             *
1311             * @return the number of starting letters that s1 and s2 have in common
1312             *         before they deviate
1313             */
1314            public static int startsWithWeight(String s1, String s2) {
1315                    if ((s1 == null) || (s2 == null)) {
1316                            return 0;
1317                    }
1318    
1319                    char[] chars1 = s1.toCharArray();
1320                    char[] chars2 = s2.toCharArray();
1321    
1322                    int i = 0;
1323    
1324                    for (; (i < chars1.length) && (i < chars2.length); i++) {
1325                            if (chars1[i] != chars2[i]) {
1326                                    break;
1327                            }
1328                    }
1329    
1330                    return i;
1331            }
1332    
1333            public static String strip(String s, char remove) {
1334                    if (s == null) {
1335                            return null;
1336                    }
1337    
1338                    int x = s.indexOf(remove);
1339    
1340                    if (x < 0) {
1341                            return s;
1342                    }
1343    
1344                    int y = 0;
1345    
1346                    StringBuilder sb = new StringBuilder(s.length());
1347    
1348                    while (x >= 0) {
1349                            sb.append(s.subSequence(y, x));
1350    
1351                            y = x + 1;
1352    
1353                            x = s.indexOf(remove, y);
1354                    }
1355    
1356                    sb.append(s.substring(y));
1357    
1358                    return sb.toString();
1359            }
1360    
1361            public static String stripBetween(String s, String begin, String end) {
1362                    if ((s == null) || (begin == null) || (end == null)) {
1363                            return s;
1364                    }
1365    
1366                    StringBuilder sb = new StringBuilder(s.length());
1367    
1368                    int pos = 0;
1369    
1370                    while (true) {
1371                            int x = s.indexOf(begin, pos);
1372                            int y = s.indexOf(end, x + begin.length());
1373    
1374                            if ((x == -1) || (y == -1)) {
1375                                    sb.append(s.substring(pos, s.length()));
1376    
1377                                    break;
1378                            }
1379                            else {
1380                                    sb.append(s.substring(pos, x));
1381    
1382                                    pos = y + end.length();
1383                            }
1384                    }
1385    
1386                    return sb.toString();
1387            }
1388    
1389            public static String toCharCode(String s) {
1390                    StringBundler sb = new StringBundler(s.length());
1391    
1392                    for (int i = 0; i < s.length(); i++) {
1393                            sb.append(s.codePointAt(i));
1394                    }
1395    
1396                    return sb.toString();
1397            }
1398    
1399            public static String toHexString(int i) {
1400                    char[] buffer = new char[8];
1401    
1402                    int index = 8;
1403    
1404                    do {
1405                            buffer[--index] = _HEX_DIGITS[i & 15];
1406    
1407                            i >>>= 4;
1408                    }
1409                    while (i != 0);
1410    
1411                    return new String(buffer, index, 8 - index);
1412            }
1413    
1414            public static String toHexString(long l) {
1415                    char[] buffer = new char[16];
1416    
1417                    int index = 16;
1418    
1419                    do {
1420                            buffer[--index] = _HEX_DIGITS[(int) (l & 15)];
1421    
1422                            l >>>= 4;
1423                    }
1424                    while (l != 0);
1425    
1426                    return new String(buffer, index, 16 - index);
1427            }
1428    
1429            public static String toHexString(Object obj) {
1430                    if (obj instanceof Integer) {
1431                            return toHexString(((Integer)obj).intValue());
1432                    }
1433                    else if (obj instanceof Long) {
1434                            return toHexString(((Long)obj).longValue());
1435                    }
1436                    else {
1437                            return String.valueOf(obj);
1438                    }
1439            }
1440    
1441            public static String trim(String s) {
1442                    return trim(s, null);
1443            }
1444    
1445            public static String trim(String s, char c) {
1446                    return trim(s, new char[] {c});
1447            }
1448    
1449            public static String trim(String s, char[] exceptions) {
1450                    if (s == null) {
1451                            return null;
1452                    }
1453    
1454                    char[] chars = s.toCharArray();
1455    
1456                    int len = chars.length;
1457    
1458                    int x = 0;
1459                    int y = chars.length;
1460    
1461                    for (int i = 0; i < len; i++) {
1462                            char c = chars[i];
1463    
1464                            if (_isTrimable(c, exceptions)) {
1465                                    x = i + 1;
1466                            }
1467                            else {
1468                                    break;
1469                            }
1470                    }
1471    
1472                    for (int i = len - 1; i >= 0; i--) {
1473                            char c = chars[i];
1474    
1475                            if (_isTrimable(c, exceptions)) {
1476                                    y = i;
1477                            }
1478                            else {
1479                                    break;
1480                            }
1481                    }
1482    
1483                    if ((x != 0) || (y != len)) {
1484                            return s.substring(x, y);
1485                    }
1486                    else {
1487                            return s;
1488                    }
1489            }
1490    
1491            public static String trimLeading(String s) {
1492                    return trimLeading(s, null);
1493            }
1494    
1495            public static String trimLeading(String s, char c) {
1496                    return trimLeading(s, new char[] {c});
1497            }
1498    
1499            public static String trimLeading(String s, char[] exceptions) {
1500                    if (s == null) {
1501                            return null;
1502                    }
1503    
1504                    char[] chars = s.toCharArray();
1505    
1506                    int len = chars.length;
1507    
1508                    int x = 0;
1509                    int y = chars.length;
1510    
1511                    for (int i = 0; i < len; i++) {
1512                            char c = chars[i];
1513    
1514                            if (_isTrimable(c, exceptions)) {
1515                                    x = i + 1;
1516                            }
1517                            else {
1518                                    break;
1519                            }
1520                    }
1521    
1522                    if ((x != 0) || (y != len)) {
1523                            return s.substring(x, y);
1524                    }
1525                    else {
1526                            return s;
1527                    }
1528            }
1529    
1530            public static String trimTrailing(String s) {
1531                    return trimTrailing(s, null);
1532            }
1533    
1534            public static String trimTrailing(String s, char c) {
1535                    return trimTrailing(s, new char[] {c});
1536            }
1537    
1538            public static String trimTrailing(String s, char[] exceptions) {
1539                    if (s == null) {
1540                            return null;
1541                    }
1542    
1543                    char[] chars = s.toCharArray();
1544    
1545                    int len = chars.length;
1546    
1547                    int x = 0;
1548                    int y = chars.length;
1549    
1550                    for (int i = len - 1; i >= 0; i--) {
1551                            char c = chars[i];
1552    
1553                            if (_isTrimable(c, exceptions)) {
1554                                    y = i;
1555                            }
1556                            else {
1557                                    break;
1558                            }
1559                    }
1560    
1561                    if ((x != 0) || (y != len)) {
1562                            return s.substring(x, y);
1563                    }
1564                    else {
1565                            return s;
1566                    }
1567            }
1568    
1569            public static String unquote(String s) {
1570                    if (Validator.isNull(s)) {
1571                            return s;
1572                    }
1573    
1574                    if ((s.charAt(0) == CharPool.APOSTROPHE) &&
1575                            (s.charAt(s.length() - 1) == CharPool.APOSTROPHE)) {
1576    
1577                            return s.substring(1, s.length() - 1);
1578                    }
1579                    else if ((s.charAt(0) == CharPool.QUOTE) &&
1580                                     (s.charAt(s.length() - 1) == CharPool.QUOTE)) {
1581    
1582                            return s.substring(1, s.length() - 1);
1583                    }
1584    
1585                    return s;
1586            }
1587    
1588            public static String upperCase(String s) {
1589                    if (s == null) {
1590                            return null;
1591                    }
1592                    else {
1593                            return s.toUpperCase();
1594                    }
1595            }
1596    
1597            public static String upperCaseFirstLetter(String s) {
1598                    char[] chars = s.toCharArray();
1599    
1600                    if ((chars[0] >= 97) && (chars[0] <= 122)) {
1601                            chars[0] = (char)(chars[0] - 32);
1602                    }
1603    
1604                    return new String(chars);
1605            }
1606    
1607            public static String valueOf(Object obj) {
1608                    return String.valueOf(obj);
1609            }
1610    
1611            public static String wrap(String text) {
1612                    return wrap(text, 80, StringPool.NEW_LINE);
1613            }
1614    
1615            public static String wrap(String text, int width, String lineSeparator) {
1616                    try {
1617                            return _wrap(text, width, lineSeparator);
1618                    }
1619                    catch (IOException ioe) {
1620                            _log.error(ioe.getMessage());
1621    
1622                            return text;
1623                    }
1624            }
1625    
1626            private static String _highlight(
1627                    String s, Pattern pattern, String highlight1, String highlight2) {
1628    
1629                    StringTokenizer st = new StringTokenizer(s);
1630    
1631                    StringBundler sb = null;
1632    
1633                    if (st.countTokens() == 0) {
1634                            sb = new StringBundler();
1635                    }
1636                    else {
1637                            sb = new StringBundler(2 * st.countTokens() - 1);
1638                    }
1639    
1640                    while (st.hasMoreTokens()) {
1641                            String token = st.nextToken();
1642    
1643                            Matcher matcher = pattern.matcher(token);
1644    
1645                            if (matcher.find()) {
1646                                    StringBuffer hightlighted = new StringBuffer();
1647    
1648                                    do {
1649                                            matcher.appendReplacement(
1650                                                    hightlighted, highlight1 + matcher.group() +
1651                                                    highlight2);
1652                                    }
1653                                    while (matcher.find());
1654    
1655                                    matcher.appendTail(hightlighted);
1656    
1657                                    sb.append(hightlighted);
1658                            }
1659                            else {
1660                                    sb.append(token);
1661                            }
1662    
1663                            if (st.hasMoreTokens()) {
1664                                    sb.append(StringPool.SPACE);
1665                            }
1666                    }
1667    
1668                    return sb.toString();
1669            }
1670    
1671            private static boolean _isTrimable(char c, char[] exceptions) {
1672                    if ((exceptions != null) && (exceptions.length > 0)) {
1673                            for (char exception : exceptions) {
1674                                    if (c == exception) {
1675                                            return false;
1676                                    }
1677                            }
1678                    }
1679    
1680                    return Character.isWhitespace(c);
1681            }
1682    
1683            private static String _wrap(String text, int width, String lineSeparator)
1684                    throws IOException {
1685    
1686                    if (text == null) {
1687                            return null;
1688                    }
1689    
1690                    StringBundler sb = new StringBundler();
1691    
1692                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1693                            new UnsyncStringReader(text));
1694    
1695                    String s = StringPool.BLANK;
1696    
1697                    while ((s = unsyncBufferedReader.readLine()) != null) {
1698                            if (s.length() == 0) {
1699                                    sb.append(lineSeparator);
1700    
1701                                    continue;
1702                            }
1703    
1704                            int lineLength = 0;
1705    
1706                            String[] tokens = s.split(StringPool.SPACE);
1707    
1708                            for (String token : tokens) {
1709                                    if ((lineLength + token.length() + 1) > width) {
1710                                            if (lineLength > 0) {
1711                                                    sb.append(lineSeparator);
1712                                            }
1713    
1714                                            if (token.length() > width) {
1715                                                    int pos = token.indexOf(CharPool.OPEN_PARENTHESIS);
1716    
1717                                                    if (pos != -1) {
1718                                                            sb.append(token.substring(0, pos + 1));
1719                                                            sb.append(lineSeparator);
1720    
1721                                                            token = token.substring(pos + 1);
1722    
1723                                                            sb.append(token);
1724    
1725                                                            lineLength = token.length();
1726                                                    }
1727                                                    else {
1728                                                            sb.append(token);
1729    
1730                                                            lineLength = token.length();
1731                                                    }
1732                                            }
1733                                            else {
1734                                                    sb.append(token);
1735    
1736                                                    lineLength = token.length();
1737                                            }
1738                                    }
1739                                    else {
1740                                            if (lineLength > 0) {
1741                                                    sb.append(StringPool.SPACE);
1742    
1743                                                    lineLength++;
1744                                            }
1745    
1746                                            sb.append(token);
1747    
1748                                            lineLength += token.length();
1749                                    }
1750                            }
1751    
1752                            sb.append(lineSeparator);
1753                    }
1754    
1755                    return sb.toString();
1756            }
1757    
1758            private static final char[] _HEX_DIGITS = {
1759                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
1760                    'e', 'f'
1761            };
1762    
1763            private static Log _log = LogFactoryUtil.getLog(StringUtil.class);
1764    
1765    }