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