001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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 (int i = 0; i < bytes.length; i++) {
088                            String hex = Integer.toHexString(
089                                    0x0100 + (bytes[i] & 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[] charArray = s.toCharArray();
180    
181                    for (int i = 0; i < charArray.length; i++) {
182                            if (Validator.isChar(charArray[i])) {
183                                    sb.append(charArray[i]);
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[] charArray = s.toCharArray();
198    
199                    for (int i = 0; i < charArray.length; i++) {
200                            if (Validator.isDigit(charArray[i])) {
201                                    sb.append(charArray[i]);
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 (int i = 0; i < array.length; i++) {
333                            int pos = s.indexOf(array[i]);
334    
335                            if (pos == -1) {
336                                    return false;
337                            }
338    
339                            s = s.substring(pos + array[i].length());
340                    }
341    
342                    return true;
343            }
344    
345            public static String merge(boolean[] array) {
346                    return merge(array, StringPool.COMMA);
347            }
348    
349            public static String merge(boolean[] array, String delimiter) {
350                    if (array == null) {
351                            return null;
352                    }
353    
354                    StringBundler sb = null;
355    
356                    if (array.length == 0) {
357                            sb = new StringBundler();
358                    }
359                    else {
360                            sb = new StringBundler(2 * array.length - 1);
361                    }
362    
363                    for (int i = 0; i < array.length; i++) {
364                            sb.append(String.valueOf(array[i]).trim());
365    
366                            if ((i + 1) != array.length) {
367                                    sb.append(delimiter);
368                            }
369                    }
370    
371                    return sb.toString();
372            }
373    
374            public static String merge(Collection<?> col) {
375                    return merge(col, StringPool.COMMA);
376            }
377    
378            public static String merge(Collection<?> col, String delimiter) {
379                    if (col == null) {
380                            return null;
381                    }
382    
383                    return merge(col.toArray(new Object[col.size()]), delimiter);
384            }
385    
386            public static String merge(double[] array) {
387                    return merge(array, StringPool.COMMA);
388            }
389    
390            public static String merge(double[] array, String delimiter) {
391                    if (array == null) {
392                            return null;
393                    }
394    
395                    StringBundler sb = null;
396    
397                    if (array.length == 0) {
398                            sb = new StringBundler();
399                    }
400                    else {
401                            sb = new StringBundler(2 * array.length - 1);
402                    }
403    
404                    for (int i = 0; i < array.length; i++) {
405                            sb.append(String.valueOf(array[i]).trim());
406    
407                            if ((i + 1) != array.length) {
408                                    sb.append(delimiter);
409                            }
410                    }
411    
412                    return sb.toString();
413            }
414    
415            public static String merge(float[] array) {
416                    return merge(array, StringPool.COMMA);
417            }
418    
419            public static String merge(float[] array, String delimiter) {
420                    if (array == null) {
421                            return null;
422                    }
423    
424                    StringBundler sb = null;
425    
426                    if (array.length == 0) {
427                            sb = new StringBundler();
428                    }
429                    else {
430                            sb = new StringBundler(2 * array.length - 1);
431                    }
432    
433                    for (int i = 0; i < array.length; i++) {
434                            sb.append(String.valueOf(array[i]).trim());
435    
436                            if ((i + 1) != array.length) {
437                                    sb.append(delimiter);
438                            }
439                    }
440    
441                    return sb.toString();
442            }
443    
444            public static String merge(int[] array) {
445                    return merge(array, StringPool.COMMA);
446            }
447    
448            public static String merge(int[] array, String delimiter) {
449                    if (array == null) {
450                            return null;
451                    }
452    
453                    StringBundler sb = null;
454    
455                    if (array.length == 0){
456                            sb = new StringBundler();
457                    }
458                    else {
459                            sb = new StringBundler(2 * array.length - 1);
460                    }
461    
462                    for (int i = 0; i < array.length; i++) {
463                            sb.append(String.valueOf(array[i]).trim());
464    
465                            if ((i + 1) != array.length) {
466                                    sb.append(delimiter);
467                            }
468                    }
469    
470                    return sb.toString();
471            }
472    
473            public static String merge(long[] array) {
474                    return merge(array, StringPool.COMMA);
475            }
476    
477            public static String merge(long[] array, String delimiter) {
478                    if (array == null) {
479                            return null;
480                    }
481    
482                    StringBundler sb = null;
483    
484                    if (array.length == 0) {
485                            sb = new StringBundler();
486                    }
487                    else {
488                            sb = new StringBundler(2 * array.length - 1);
489                    }
490    
491                    for (int i = 0; i < array.length; i++) {
492                            sb.append(String.valueOf(array[i]).trim());
493    
494                            if ((i + 1) != array.length) {
495                                    sb.append(delimiter);
496                            }
497                    }
498    
499                    return sb.toString();
500            }
501    
502            public static String merge(Object[] array) {
503                    return merge(array, StringPool.COMMA);
504            }
505    
506            public static String merge(Object[] array, String delimiter) {
507                    if (array == null) {
508                            return null;
509                    }
510    
511                    StringBundler sb = null;
512    
513                    if (array.length == 0) {
514                            sb = new StringBundler();
515                    }
516                    else {
517                            sb = new StringBundler(2 * array.length - 1);
518                    }
519    
520                    for (int i = 0; i < array.length; i++) {
521                            sb.append(String.valueOf(array[i]).trim());
522    
523                            if ((i + 1) != array.length) {
524                                    sb.append(delimiter);
525                            }
526                    }
527    
528                    return sb.toString();
529            }
530    
531            public static String merge(short[] array) {
532                    return merge(array, StringPool.COMMA);
533            }
534    
535            public static String merge(short[] array, String delimiter) {
536                    if (array == null) {
537                            return null;
538                    }
539    
540                    StringBundler sb = null;
541    
542                    if (array.length == 0) {
543                            sb = new StringBundler();
544                    }
545                    else {
546                            sb = new StringBundler(2 * array.length - 1);
547                    }
548    
549                    for (int i = 0; i < array.length; i++) {
550                            sb.append(String.valueOf(array[i]).trim());
551    
552                            if ((i + 1) != array.length) {
553                                    sb.append(delimiter);
554                            }
555                    }
556    
557                    return sb.toString();
558            }
559    
560            public static String randomize(String s) {
561                    return Randomizer.getInstance().randomize(s);
562            }
563    
564            public static String read(ClassLoader classLoader, String name)
565                    throws IOException {
566    
567                    return read(classLoader, name, false);
568            }
569    
570            public static String read(ClassLoader classLoader, String name, boolean all)
571                    throws IOException {
572    
573                    if (all) {
574                            StringBundler sb = new StringBundler();
575    
576                            Enumeration<URL> enu = classLoader.getResources(name);
577    
578                            while (enu.hasMoreElements()) {
579                                    URL url = enu.nextElement();
580    
581                                    InputStream is = url.openStream();
582    
583                                    if (is == null) {
584                                            throw new IOException(
585                                                    "Unable to open resource at " + url.toString());
586                                    }
587    
588                                    String s = read(is);
589    
590                                    if (s != null) {
591                                            sb.append(s);
592                                            sb.append(StringPool.NEW_LINE);
593                                    }
594    
595                                    is.close();
596                            }
597    
598                            return sb.toString().trim();
599                    }
600                    else {
601                            InputStream is = classLoader.getResourceAsStream(name);
602    
603                            if (is == null) {
604                                    throw new IOException(
605                                            "Unable to open resource in class loader " + name);
606                            }
607    
608                            String s = read(is);
609    
610                            is.close();
611    
612                            return s;
613                    }
614            }
615    
616            public static String read(InputStream is) throws IOException {
617                    StringBundler sb = new StringBundler();
618    
619                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
620                            new InputStreamReader(is));
621    
622                    String line = null;
623    
624                    while ((line = unsyncBufferedReader.readLine()) != null) {
625                            sb.append(line);
626                            sb.append(CharPool.NEW_LINE);
627                    }
628    
629                    unsyncBufferedReader.close();
630    
631                    return sb.toString().trim();
632            }
633    
634            public static String remove(String s, String remove) {
635                    return remove(s, remove, StringPool.COMMA);
636            }
637    
638            public static String remove(String s, String remove, String delimiter) {
639                    if ((s == null) || (remove == null) || (delimiter == null)) {
640                            return null;
641                    }
642    
643                    if (Validator.isNotNull(s) && !s.endsWith(delimiter)) {
644                            s += delimiter;
645                    }
646    
647                    String drd = delimiter.concat(remove).concat(delimiter);
648    
649                    String rd = remove.concat(delimiter);
650    
651                    while (contains(s, remove, delimiter)) {
652                            int pos = s.indexOf(drd);
653    
654                            if (pos == -1) {
655                                    if (s.startsWith(rd)) {
656                                            int x = remove.length() + delimiter.length();
657                                            int y = s.length();
658    
659                                            s = s.substring(x, y);
660                                    }
661                            }
662                            else {
663                                    int x = pos + remove.length() + delimiter.length();
664                                    int y = s.length();
665    
666                                    String temp = s.substring(0, pos);
667    
668                                    s = temp.concat(s.substring(x, y));
669                            }
670                    }
671    
672                    return s;
673            }
674    
675            public static String replace(String s, char oldSub, char newSub) {
676                    if (s == null) {
677                            return null;
678                    }
679    
680                    return s.replace(oldSub, newSub);
681            }
682    
683            public static String replace(String s, char oldSub, String newSub) {
684                    if ((s == null) || (newSub == null)) {
685                            return null;
686                    }
687    
688                    // The number 5 is arbitrary and is used as extra padding to reduce
689                    // buffer expansion
690    
691                    StringBuilder sb = new StringBuilder(s.length() + 5 * newSub.length());
692    
693                    char[] charArray = s.toCharArray();
694    
695                    for (char c : charArray) {
696                            if (c == oldSub) {
697                                    sb.append(newSub);
698                            }
699                            else {
700                                    sb.append(c);
701                            }
702                    }
703    
704                    return sb.toString();
705            }
706    
707            public static String replace(String s, String oldSub, String newSub) {
708                    return replace(s, oldSub, newSub, 0);
709            }
710    
711            public static String replace(
712                    String s, String oldSub, String newSub, int fromIndex) {
713    
714                    if ((s == null) || (oldSub == null) || (newSub == null)) {
715                            return null;
716                    }
717    
718                    int y = s.indexOf(oldSub, fromIndex);
719    
720                    if (y >= 0) {
721                            StringBundler sb = new StringBundler();
722    
723                            int length = oldSub.length();
724                            int x = 0;
725    
726                            while (x <= y) {
727                                    sb.append(s.substring(x, y));
728                                    sb.append(newSub);
729    
730                                    x = y + length;
731                                    y = s.indexOf(oldSub, x);
732                            }
733    
734                            sb.append(s.substring(x));
735    
736                            return sb.toString();
737                    }
738                    else {
739                            return s;
740                    }
741            }
742    
743            public static String replace(
744                    String s, String begin, String end, Map<String, String> values) {
745    
746                    StringBundler sb = replaceToStringBundler(s, begin, end, values);
747    
748                    return sb.toString();
749            }
750    
751            public static String replace(String s, String[] oldSubs, String[] newSubs) {
752                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
753                            return null;
754                    }
755    
756                    if (oldSubs.length != newSubs.length) {
757                            return s;
758                    }
759    
760                    for (int i = 0; i < oldSubs.length; i++) {
761                            s = replace(s, oldSubs[i], newSubs[i]);
762                    }
763    
764                    return s;
765            }
766    
767            public static String replace(
768                    String s, String[] oldSubs, String[] newSubs, boolean exactMatch) {
769    
770                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
771                            return null;
772                    }
773    
774                    if (oldSubs.length != newSubs.length) {
775                            return s;
776                    }
777    
778                    if (!exactMatch) {
779                            replace(s, oldSubs, newSubs);
780                    }
781                    else {
782                            for (int i = 0; i < oldSubs.length; i++) {
783                                    s = s.replaceAll("\\b" + oldSubs[i] + "\\b" , newSubs[i]);
784                            }
785                    }
786    
787                    return s;
788            }
789    
790            public static String replaceFirst(String s, char oldSub, char newSub) {
791                    if (s == null) {
792                            return null;
793                    }
794    
795                    return s.replaceFirst(String.valueOf(oldSub), String.valueOf(newSub));
796            }
797    
798            public static String replaceFirst(String s, char oldSub, String newSub) {
799                    if ((s == null) || (newSub == null)) {
800                            return null;
801                    }
802    
803                    return s.replaceFirst(String.valueOf(oldSub), newSub);
804            }
805    
806            public static String replaceFirst(String s, String oldSub, String newSub) {
807                    if ((s == null) || (oldSub == null) || (newSub == null)) {
808                            return null;
809                    }
810    
811                    return s.replaceFirst(oldSub, newSub);
812            }
813    
814            public static String replaceFirst(
815                    String s, String[] oldSubs, String[] newSubs) {
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                    for (int i = 0; i < oldSubs.length; i++) {
826                            s = replaceFirst(s, oldSubs[i], newSubs[i]);
827                    }
828    
829                    return s;
830            }
831    
832            public static String replaceLast(String s, char oldSub, char newSub) {
833                    if (s == null) {
834                            return null;
835                    }
836    
837                    return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub));
838            }
839    
840            public static String replaceLast(String s, char oldSub, String newSub) {
841                    if ((s == null) || (newSub == null)) {
842                            return null;
843                    }
844    
845                    return replaceLast(s, String.valueOf(oldSub), newSub);
846            }
847    
848            public static String replaceLast(String s, String oldSub, String newSub) {
849                    if ((s == null) || (oldSub == null) || (newSub == null)) {
850                            return null;
851                    }
852    
853                    int y = s.lastIndexOf(oldSub);
854    
855                    if (y >= 0) {
856                            StringBundler sb = new StringBundler();
857    
858                            int length = oldSub.length();
859                            int x = 0;
860    
861                            while (x <= y) {
862                                    sb.append(s.substring(x, y));
863                                    sb.append(newSub);
864    
865                                    x = y + length;
866                                    y = s.indexOf(oldSub, x);
867                            }
868    
869                            sb.append(s.substring(x));
870    
871                            return sb.toString();
872                    }
873                    else {
874                            return s;
875                    }
876            }
877    
878            public static String replaceLast(
879                    String s, String[] oldSubs, String[] newSubs) {
880    
881                    if ((s == null) || (oldSubs == null) || (newSubs == null)) {
882                            return null;
883                    }
884    
885                    if (oldSubs.length != newSubs.length) {
886                            return s;
887                    }
888    
889                    for (int i = 0; i < oldSubs.length; i++) {
890                            s = replaceLast(s, oldSubs[i], newSubs[i]);
891                    }
892    
893                    return s;
894            }
895    
896            public static StringBundler replaceToStringBundler(
897                    String s, String begin, String end, Map<String, String> values) {
898    
899                    if ((s == null) || (begin == null) || (end == null) ||
900                            (values == null) || (values.size() == 0)) {
901    
902                            return new StringBundler(s);
903                    }
904    
905                    StringBundler sb = new StringBundler(values.size() * 2 + 1);
906    
907                    int pos = 0;
908    
909                    while (true) {
910                            int x = s.indexOf(begin, pos);
911                            int y = s.indexOf(end, x + begin.length());
912    
913                            if ((x == -1) || (y == -1)) {
914                                    sb.append(s.substring(pos, s.length()));
915    
916                                    break;
917                            }
918                            else {
919                                    sb.append(s.substring(pos, x));
920    
921                                    String oldValue = s.substring(x + begin.length(), y);
922    
923                                    String newValue = values.get(oldValue);
924    
925                                    if (newValue == null) {
926                                            newValue = oldValue;
927                                    }
928    
929                                    sb.append(newValue);
930    
931                                    pos = y + end.length();
932                            }
933                    }
934    
935                    return sb;
936            }
937    
938            public static StringBundler replaceWithStringBundler(
939                    String s, String begin, String end, Map<String, StringBundler> values) {
940    
941                    if ((s == null) || (begin == null) || (end == null) ||
942                            (values == null) || (values.size() == 0)) {
943    
944                            return new StringBundler(s);
945                    }
946    
947                    int size = values.size() + 1;
948    
949                    for (StringBundler valueSB : values.values()) {
950                            size += valueSB.index();
951                    }
952    
953                    StringBundler sb = new StringBundler(size);
954    
955                    int pos = 0;
956    
957                    while (true) {
958                            int x = s.indexOf(begin, pos);
959                            int y = s.indexOf(end, x + begin.length());
960    
961                            if ((x == -1) || (y == -1)) {
962                                    sb.append(s.substring(pos, s.length()));
963    
964                                    break;
965                            }
966                            else {
967                                    sb.append(s.substring(pos, x));
968    
969                                    String oldValue = s.substring(x + begin.length(), y);
970    
971                                    StringBundler newValue = values.get(oldValue);
972    
973                                    if (newValue == null) {
974                                            sb.append(oldValue);
975                                    }
976                                    else {
977                                            sb.append(newValue);
978                                    }
979    
980                                    pos = y + end.length();
981                            }
982                    }
983    
984                    return sb;
985            }
986    
987            public static String reverse(String s) {
988                    if (s == null) {
989                            return null;
990                    }
991    
992                    char[] charArray = s.toCharArray();
993                    char[] reverse = new char[charArray.length];
994    
995                    for (int i = 0; i < charArray.length; i++) {
996                            reverse[i] = charArray[charArray.length - i - 1];
997                    }
998    
999                    return new String(reverse);
1000            }
1001    
1002            public static String safePath(String path) {
1003                    return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH);
1004            }
1005    
1006            public static String shorten(String s) {
1007                    return shorten(s, 20);
1008            }
1009    
1010            public static String shorten(String s, int length) {
1011                    return shorten(s, length, "...");
1012            }
1013    
1014            public static String shorten(String s, int length, String suffix) {
1015                    if ((s == null) || (suffix == null)) {
1016                            return null;
1017                    }
1018    
1019                    if (s.length() > length) {
1020                            for (int j = length; j >= 0; j--) {
1021                                    if (Character.isWhitespace(s.charAt(j))) {
1022                                            length = j;
1023    
1024                                            break;
1025                                    }
1026                            }
1027    
1028                            String temp = s.substring(0, length);
1029    
1030                            s = temp.concat(suffix);
1031                    }
1032    
1033                    return s;
1034            }
1035    
1036            public static String shorten(String s, String suffix) {
1037                    return shorten(s, 20, suffix);
1038            }
1039    
1040            public static String[] split(String s) {
1041                    return split(s, StringPool.COMMA);
1042            }
1043    
1044            public static boolean[] split(String s, boolean x) {
1045                    return split(s, StringPool.COMMA, x);
1046            }
1047    
1048            public static double[] split(String s, double x) {
1049                    return split(s, StringPool.COMMA, x);
1050            }
1051    
1052            public static float[] split(String s, float x) {
1053                    return split(s, StringPool.COMMA, x);
1054            }
1055    
1056            public static int[] split(String s, int x) {
1057                    return split(s, StringPool.COMMA, x);
1058            }
1059    
1060            public static long[] split(String s, long x) {
1061                    return split(s, StringPool.COMMA, x);
1062            }
1063    
1064            public static short[] split(String s, short x) {
1065                    return split(s, StringPool.COMMA, x);
1066            }
1067    
1068            public static String[] split(String s, String delimiter) {
1069                    if ((Validator.isNull(s)) || (delimiter == null) ||
1070                            (delimiter.equals(StringPool.BLANK))) {
1071    
1072                            return new String[0];
1073                    }
1074    
1075                    s = s.trim();
1076    
1077                    if (s.equals(delimiter)) {
1078                            return new String[0];
1079                    }
1080    
1081                    List<String> nodeValues = new ArrayList<String>();
1082    
1083                    if (delimiter.equals(StringPool.NEW_LINE) ||
1084                            delimiter.equals(StringPool.RETURN)) {
1085    
1086                            try {
1087                                    UnsyncBufferedReader unsyncBufferedReader =
1088                                            new UnsyncBufferedReader(new UnsyncStringReader(s));
1089    
1090                                    String line = null;
1091    
1092                                    while ((line = unsyncBufferedReader.readLine()) != null) {
1093                                            nodeValues.add(line);
1094                                    }
1095    
1096                                    unsyncBufferedReader.close();
1097                            }
1098                            catch (IOException ioe) {
1099                                    _log.error(ioe.getMessage());
1100                            }
1101                    }
1102                    else {
1103                            int offset = 0;
1104                            int pos = s.indexOf(delimiter, offset);
1105    
1106                            while (pos != -1) {
1107                                    nodeValues.add(s.substring(offset, pos));
1108    
1109                                    offset = pos + delimiter.length();
1110                                    pos = s.indexOf(delimiter, offset);
1111                            }
1112    
1113                            if (offset < s.length()) {
1114                                    nodeValues.add(s.substring(offset));
1115                            }
1116                    }
1117    
1118                    return nodeValues.toArray(new String[nodeValues.size()]);
1119            }
1120    
1121            public static boolean[] split(String s, String delimiter, boolean x) {
1122                    String[] array = split(s, delimiter);
1123                    boolean[] newArray = new boolean[array.length];
1124    
1125                    for (int i = 0; i < array.length; i++) {
1126                            boolean value = x;
1127    
1128                            try {
1129                                    value = Boolean.valueOf(array[i]).booleanValue();
1130                            }
1131                            catch (Exception e) {
1132                            }
1133    
1134                            newArray[i] = value;
1135                    }
1136    
1137                    return newArray;
1138            }
1139    
1140            public static double[] split(String s, String delimiter, double x) {
1141                    String[] array = split(s, delimiter);
1142                    double[] newArray = new double[array.length];
1143    
1144                    for (int i = 0; i < array.length; i++) {
1145                            double value = x;
1146    
1147                            try {
1148                                    value = Double.parseDouble(array[i]);
1149                            }
1150                            catch (Exception e) {
1151                            }
1152    
1153                            newArray[i] = value;
1154                    }
1155    
1156                    return newArray;
1157            }
1158    
1159            public static float[] split(String s, String delimiter, float x) {
1160                    String[] array = split(s, delimiter);
1161                    float[] newArray = new float[array.length];
1162    
1163                    for (int i = 0; i < array.length; i++) {
1164                            float value = x;
1165    
1166                            try {
1167                                    value = Float.parseFloat(array[i]);
1168                            }
1169                            catch (Exception e) {
1170                            }
1171    
1172                            newArray[i] = value;
1173                    }
1174    
1175                    return newArray;
1176            }
1177    
1178            public static int[] split(String s, String delimiter, int x) {
1179                    String[] array = split(s, delimiter);
1180                    int[] newArray = new int[array.length];
1181    
1182                    for (int i = 0; i < array.length; i++) {
1183                            int value = x;
1184    
1185                            try {
1186                                    value = Integer.parseInt(array[i]);
1187                            }
1188                            catch (Exception e) {
1189                            }
1190    
1191                            newArray[i] = value;
1192                    }
1193    
1194                    return newArray;
1195            }
1196    
1197            public static long[] split(String s, String delimiter, long x) {
1198                    String[] array = split(s, delimiter);
1199                    long[] newArray = new long[array.length];
1200    
1201                    for (int i = 0; i < array.length; i++) {
1202                            long value = x;
1203    
1204                            try {
1205                                    value = Long.parseLong(array[i]);
1206                            }
1207                            catch (Exception e) {
1208                            }
1209    
1210                            newArray[i] = value;
1211                    }
1212    
1213                    return newArray;
1214            }
1215    
1216            public static short[] split(String s, String delimiter, short x) {
1217                    String[] array = split(s, delimiter);
1218                    short[] newArray = new short[array.length];
1219    
1220                    for (int i = 0; i < array.length; i++) {
1221                            short value = x;
1222    
1223                            try {
1224                                    value = Short.parseShort(array[i]);
1225                            }
1226                            catch (Exception e) {
1227                            }
1228    
1229                            newArray[i] = value;
1230                    }
1231    
1232                    return newArray;
1233            }
1234    
1235            public static boolean startsWith(String s, char begin) {
1236                    return startsWith(s, (new Character(begin)).toString());
1237            }
1238    
1239            public static boolean startsWith(String s, String start) {
1240                    if ((s == null) || (start == null)) {
1241                            return false;
1242                    }
1243    
1244                    if (start.length() > s.length()) {
1245                            return false;
1246                    }
1247    
1248                    String temp = s.substring(0, start.length());
1249    
1250                    if (temp.equalsIgnoreCase(start)) {
1251                            return true;
1252                    }
1253                    else {
1254                            return false;
1255                    }
1256            }
1257    
1258            /**
1259             * Return the number of starting letters that s1 and s2 have in common
1260             * before they deviate.
1261             *
1262             * @return the number of starting letters that s1 and s2 have in common
1263             *                 before they deviate
1264             */
1265            public static int startsWithWeight(String s1, String s2) {
1266                    if ((s1 == null) || (s2 == null)) {
1267                            return 0;
1268                    }
1269    
1270                    char[] charArray1 = s1.toCharArray();
1271                    char[] charArray2 = s2.toCharArray();
1272    
1273                    int i = 0;
1274    
1275                    for (; (i < charArray1.length) && (i < charArray2.length); i++) {
1276                            if (charArray1[i] != charArray2[i]) {
1277                                    break;
1278                            }
1279                    }
1280    
1281                    return i;
1282            }
1283    
1284            public static String stripBetween(String s, String begin, String end) {
1285                    if ((s == null) || (begin == null) || (end == null)) {
1286                            return s;
1287                    }
1288    
1289                    StringBuilder sb = new StringBuilder(s.length());
1290    
1291                    int pos = 0;
1292    
1293                    while (true) {
1294                            int x = s.indexOf(begin, pos);
1295                            int y = s.indexOf(end, x + begin.length());
1296    
1297                            if ((x == -1) || (y == -1)) {
1298                                    sb.append(s.substring(pos, s.length()));
1299    
1300                                    break;
1301                            }
1302                            else {
1303                                    sb.append(s.substring(pos, x));
1304    
1305                                    pos = y + end.length();
1306                            }
1307                    }
1308    
1309                    return sb.toString();
1310            }
1311    
1312            public static String trim(String s) {
1313                    return trim(s, null);
1314            }
1315    
1316            public static String trim(String s, char c) {
1317                    return trim(s, new char[] {c});
1318            }
1319    
1320            public static String trim(String s, char[] exceptions) {
1321                    if (s == null) {
1322                            return null;
1323                    }
1324    
1325                    char[] charArray = s.toCharArray();
1326    
1327                    int len = charArray.length;
1328    
1329                    int x = 0;
1330                    int y = charArray.length;
1331    
1332                    for (int i = 0; i < len; i++) {
1333                            char c = charArray[i];
1334    
1335                            if (_isTrimable(c, exceptions)) {
1336                                    x = i + 1;
1337                            }
1338                            else {
1339                                    break;
1340                            }
1341                    }
1342    
1343                    for (int i = len - 1; i >= 0; i--) {
1344                            char c = charArray[i];
1345    
1346                            if (_isTrimable(c, exceptions)) {
1347                                    y = i;
1348                            }
1349                            else {
1350                                    break;
1351                            }
1352                    }
1353    
1354                    if ((x != 0) || (y != len)) {
1355                            return s.substring(x, y);
1356                    }
1357                    else {
1358                            return s;
1359                    }
1360            }
1361    
1362            public static String trimLeading(String s) {
1363                    return trimLeading(s, null);
1364            }
1365    
1366            public static String trimLeading(String s, char c) {
1367                    return trimLeading(s, new char[] {c});
1368            }
1369    
1370            public static String trimLeading(String s, char[] exceptions) {
1371                    if (s == null) {
1372                            return null;
1373                    }
1374    
1375                    char[] charArray = s.toCharArray();
1376    
1377                    int len = charArray.length;
1378    
1379                    int x = 0;
1380                    int y = charArray.length;
1381    
1382                    for (int i = 0; i < len; i++) {
1383                            char c = charArray[i];
1384    
1385                            if (_isTrimable(c, exceptions)) {
1386                                    x = i + 1;
1387                            }
1388                            else {
1389                                    break;
1390                            }
1391                    }
1392    
1393                    if ((x != 0) || (y != len)) {
1394                            return s.substring(x, y);
1395                    }
1396                    else {
1397                            return s;
1398                    }
1399            }
1400    
1401            public static String trimTrailing(String s) {
1402                    return trimTrailing(s, null);
1403            }
1404    
1405            public static String trimTrailing(String s, char c) {
1406                    return trimTrailing(s, new char[] {c});
1407            }
1408    
1409            public static String trimTrailing(String s, char[] exceptions) {
1410                    if (s == null) {
1411                            return null;
1412                    }
1413    
1414                    char[] charArray = s.toCharArray();
1415    
1416                    int len = charArray.length;
1417    
1418                    int x = 0;
1419                    int y = charArray.length;
1420    
1421                    for (int i = len - 1; i >= 0; i--) {
1422                            char c = charArray[i];
1423    
1424                            if (_isTrimable(c, exceptions)) {
1425                                    y = i;
1426                            }
1427                            else {
1428                                    break;
1429                            }
1430                    }
1431    
1432                    if ((x != 0) || (y != len)) {
1433                            return s.substring(x, y);
1434                    }
1435                    else {
1436                            return s;
1437                    }
1438            }
1439    
1440            public static String unquote(String s) {
1441                    if (s == null) {
1442                            return s;
1443                    }
1444    
1445                    if (s.startsWith(StringPool.QUOTE) && s.endsWith(StringPool.QUOTE)) {
1446                            s = s.replaceAll("\"$", StringPool.BLANK);
1447                            s = s.replaceAll("^\"", StringPool.BLANK);
1448                    }
1449    
1450                    return s;
1451            }
1452    
1453            public static String upperCase(String s) {
1454                    if (s == null) {
1455                            return null;
1456                    }
1457                    else {
1458                            return s.toUpperCase();
1459                    }
1460            }
1461    
1462            public static String upperCaseFirstLetter(String s) {
1463                    char[] charArray = s.toCharArray();
1464    
1465                    if ((charArray[0] >= 97) && (charArray[0] <= 122)) {
1466                            charArray[0] = (char)(charArray[0] - 32);
1467                    }
1468    
1469                    return new String(charArray);
1470            }
1471    
1472            public static String valueOf(Object obj) {
1473                    return String.valueOf(obj);
1474            }
1475    
1476            public static String wrap(String text) {
1477                    return wrap(text, 80, StringPool.NEW_LINE);
1478            }
1479    
1480            public static String wrap(String text, int width, String lineSeparator) {
1481                    try {
1482                            return _wrap(text, width, lineSeparator);
1483                    }
1484                    catch (IOException ioe) {
1485                            _log.error(ioe.getMessage());
1486    
1487                            return text;
1488                    }
1489            }
1490    
1491            private static String _highlight(
1492                    String s, Pattern pattern, String highlight1, String highlight2) {
1493    
1494                    StringTokenizer st = new StringTokenizer(s);
1495    
1496                    StringBundler sb = null;
1497    
1498                    if (st.countTokens() == 0) {
1499                            sb = new StringBundler();
1500                    }
1501                    else {
1502                            sb = new StringBundler(2 * st.countTokens() - 1);
1503                    }
1504    
1505                    while (st.hasMoreTokens()) {
1506                            String token = st.nextToken();
1507    
1508                            Matcher matcher = pattern.matcher(token);
1509    
1510                            if (matcher.find()) {
1511                                    String highlightedToken = matcher.replaceAll(
1512                                            highlight1 + matcher.group() + highlight2);
1513    
1514                                    sb.append(highlightedToken);
1515                            }
1516                            else {
1517                                    sb.append(token);
1518                            }
1519    
1520                            if (st.hasMoreTokens()) {
1521                                    sb.append(StringPool.SPACE);
1522                            }
1523                    }
1524    
1525                    return sb.toString();
1526            }
1527    
1528            private static boolean _isTrimable(char c, char[] exceptions) {
1529                    if ((exceptions != null) && (exceptions.length > 0)) {
1530                            for (int i = 0; i < exceptions.length; i++) {
1531                                    if (c == exceptions[i]) {
1532                                            return false;
1533                                    }
1534                            }
1535                    }
1536    
1537                    return Character.isWhitespace(c);
1538            }
1539    
1540            private static String _wrap(String text, int width, String lineSeparator)
1541                    throws IOException {
1542    
1543                    if (text == null) {
1544                            return null;
1545                    }
1546    
1547                    StringBundler sb = new StringBundler();
1548    
1549                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1550                            new UnsyncStringReader(text));
1551    
1552                    String s = StringPool.BLANK;
1553    
1554                    while ((s = unsyncBufferedReader.readLine()) != null) {
1555                            if (s.length() == 0) {
1556                                    sb.append(lineSeparator);
1557    
1558                                    continue;
1559                            }
1560    
1561                            int lineLength = 0;
1562    
1563                            String[] tokens = s.split(StringPool.SPACE);
1564    
1565                            for (String token : tokens) {
1566                                    if ((lineLength + token.length() + 1) > width) {
1567                                            if (lineLength > 0) {
1568                                                    sb.append(lineSeparator);
1569                                            }
1570    
1571                                            if (token.length() > width) {
1572                                                    int pos = token.indexOf(StringPool.OPEN_PARENTHESIS);
1573    
1574                                                    if (pos != -1) {
1575                                                            sb.append(token.substring(0, pos + 1));
1576                                                            sb.append(lineSeparator);
1577    
1578                                                            token = token.substring(pos + 1);
1579    
1580                                                            sb.append(token);
1581    
1582                                                            lineLength = token.length();
1583                                                    }
1584                                                    else {
1585                                                            sb.append(token);
1586    
1587                                                            lineLength = token.length();
1588                                                    }
1589                                            }
1590                                            else {
1591                                                    sb.append(token);
1592    
1593                                                    lineLength = token.length();
1594                                            }
1595                                    }
1596                                    else {
1597                                            if (lineLength > 0) {
1598                                                    sb.append(StringPool.SPACE);
1599    
1600                                                    lineLength++;
1601                                            }
1602    
1603                                            sb.append(token);
1604    
1605                                            lineLength += token.length();
1606                                    }
1607                            }
1608    
1609                            sb.append(lineSeparator);
1610                    }
1611    
1612                    return sb.toString();
1613            }
1614    
1615            private static Log _log = LogFactoryUtil.getLog(StringUtil.class);
1616    
1617    }