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