1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.kernel.util;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
18  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  
26  import java.net.URL;
27  
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.Enumeration;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.StringTokenizer;
34  import java.util.regex.Matcher;
35  import java.util.regex.Pattern;
36  
37  /**
38   * <a href="StringUtil.java.html"><b><i>View Source</i></b></a>
39   *
40   * @author Brian Wing Shun Chan
41   * @author Sandeep Soni
42   * @author Ganesh Ram
43   */
44  public class StringUtil {
45  
46      public static String add(String s, String add) {
47          return add(s, add, StringPool.COMMA);
48      }
49  
50      public static String add(String s, String add, String delimiter) {
51          return add(s, add, delimiter, false);
52      }
53  
54      public static String add(
55          String s, String add, String delimiter, boolean allowDuplicates) {
56  
57          if ((add == null) || (delimiter == null)) {
58              return null;
59          }
60  
61          if (s == null) {
62              s = StringPool.BLANK;
63          }
64  
65          if (allowDuplicates || !contains(s, add, delimiter)) {
66              StringBundler sb = new StringBundler();
67  
68              sb.append(s);
69  
70              if (Validator.isNull(s) || s.endsWith(delimiter)) {
71                  sb.append(add);
72                  sb.append(delimiter);
73              }
74              else {
75                  sb.append(delimiter);
76                  sb.append(add);
77                  sb.append(delimiter);
78              }
79  
80              s = sb.toString();
81          }
82  
83          return s;
84      }
85  
86      public static String bytesToHexString(byte[] bytes) {
87          StringBuilder sb = new StringBuilder(bytes.length * 2);
88  
89          for (int i = 0; i < bytes.length; i++) {
90              String hex = Integer.toHexString(
91                  0x0100 + (bytes[i] & 0x00FF)).substring(1);
92  
93              if (hex.length() < 2) {
94                  sb.append("0");
95              }
96  
97              sb.append(hex);
98          }
99  
100         return sb.toString();
101     }
102 
103     public static boolean contains(String s, String text) {
104         return contains(s, text, StringPool.COMMA);
105     }
106 
107     public static boolean contains(String s, String text, String delimiter) {
108         if ((s == null) || (text == null) || (delimiter == null)) {
109             return false;
110         }
111 
112         if (!s.endsWith(delimiter)) {
113             s = s.concat(delimiter);
114         }
115 
116         String dtd = delimiter.concat(text).concat(delimiter);
117 
118         int pos = s.indexOf(dtd);
119 
120         if (pos == -1) {
121             String td = text.concat(delimiter);
122 
123             if (s.startsWith(td)) {
124                 return true;
125             }
126 
127             return false;
128         }
129 
130         return true;
131     }
132 
133     public static int count(String s, String text) {
134         if ((s == null) || (text == null)) {
135             return 0;
136         }
137 
138         int count = 0;
139 
140         int pos = s.indexOf(text);
141 
142         while (pos != -1) {
143             pos = s.indexOf(text, pos + text.length());
144 
145             count++;
146         }
147 
148         return count;
149     }
150 
151     public static boolean endsWith(String s, char end) {
152         return endsWith(s, (new Character(end)).toString());
153     }
154 
155     public static boolean endsWith(String s, String end) {
156         if ((s == null) || (end == null)) {
157             return false;
158         }
159 
160         if (end.length() > s.length()) {
161             return false;
162         }
163 
164         String temp = s.substring(s.length() - end.length(), s.length());
165 
166         if (temp.equalsIgnoreCase(end)) {
167             return true;
168         }
169         else {
170             return false;
171         }
172     }
173 
174     public static String extractChars(String s) {
175         if (s == null) {
176             return StringPool.BLANK;
177         }
178 
179         StringBuilder sb = new StringBuilder();
180 
181         char[] charArray = s.toCharArray();
182 
183         for (int i = 0; i < charArray.length; i++) {
184             if (Validator.isChar(charArray[i])) {
185                 sb.append(charArray[i]);
186             }
187         }
188 
189         return sb.toString();
190     }
191 
192     public static String extractDigits(String s) {
193         if (s == null) {
194             return StringPool.BLANK;
195         }
196 
197         StringBuilder sb = new StringBuilder();
198 
199         char[] charArray = s.toCharArray();
200 
201         for (int i = 0; i < charArray.length; i++) {
202             if (Validator.isDigit(charArray[i])) {
203                 sb.append(charArray[i]);
204             }
205         }
206 
207         return sb.toString();
208     }
209 
210     public static String extractFirst(String s, String delimiter) {
211         if (s == null) {
212             return null;
213         }
214         else {
215             String[] array = split(s, delimiter);
216 
217             if (array.length > 0) {
218                 return array[0];
219             }
220             else {
221                 return null;
222             }
223         }
224     }
225 
226     public static String extractLast(String s, String delimiter) {
227         if (s == null) {
228             return null;
229         }
230         else {
231             String[] array = split(s, delimiter);
232 
233             if (array.length > 0) {
234                 return array[array.length - 1];
235             }
236             else {
237                 return null;
238             }
239         }
240     }
241 
242     /**
243      * @deprecated
244      */
245     public static String highlight(String s, String keywords) {
246         return highlight(s, keywords, "<span class=\"highlight\">", "</span>");
247     }
248 
249     /**
250      * @deprecated
251      */
252     public static String highlight(
253         String s, String keywords, String highlight1, String highlight2) {
254 
255         if (Validator.isNull(s) || Validator.isNull(keywords)) {
256             return s;
257         }
258 
259         Pattern pattern = Pattern.compile(
260             Pattern.quote(keywords), Pattern.CASE_INSENSITIVE);
261 
262         return _highlight(s, pattern, highlight1, highlight2);
263     }
264 
265     public static String highlight(String s, String[] queryTerms) {
266         return highlight(
267             s, queryTerms, "<span class=\"highlight\">", "</span>");
268     }
269 
270     public static String highlight(
271         String s, String[] queryTerms, String highlight1, String highlight2) {
272 
273         if (Validator.isNull(s) || Validator.isNull(queryTerms)) {
274             return s;
275         }
276 
277         StringBundler sb = null;
278 
279         if (queryTerms.length == 0) {
280             sb = new StringBundler();
281         }
282         else {
283             sb = new StringBundler(2 * queryTerms.length - 1);
284         }
285 
286         for (int i = 0; i < queryTerms.length; i++) {
287             sb.append(Pattern.quote(queryTerms[i].trim()));
288 
289             if ((i + 1) < queryTerms.length) {
290                 sb.append(StringPool.PIPE);
291             }
292         }
293 
294         int flags =
295             Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
296 
297         Pattern pattern = Pattern.compile(sb.toString(), flags);
298 
299         return _highlight(s, pattern, highlight1, highlight2);
300     }
301 
302     public static String insert(String s, String insert, int offset) {
303         if (s == null) {
304             return null;
305         }
306 
307         if (insert == null) {
308             return s;
309         }
310 
311         if (offset > s.length()) {
312             offset = s.length();
313         }
314 
315         StringBuilder sb = new StringBuilder(s);
316 
317         sb.insert(offset, insert);
318 
319         return sb.toString();
320     }
321 
322     public static String lowerCase(String s) {
323         if (s == null) {
324             return null;
325         }
326         else {
327             return s.toLowerCase();
328         }
329     }
330 
331     public static boolean matches(String s, String pattern) {
332         String[] array = pattern.split("\\*");
333 
334         for (int i = 0; i < array.length; i++) {
335             int pos = s.indexOf(array[i]);
336 
337             if (pos == -1) {
338                 return false;
339             }
340 
341             s = s.substring(pos + array[i].length());
342         }
343 
344         return true;
345     }
346 
347     public static String merge(boolean[] array) {
348         return merge(array, StringPool.COMMA);
349     }
350 
351     public static String merge(boolean[] array, String delimiter) {
352         if (array == null) {
353             return null;
354         }
355 
356         StringBundler sb = null;
357 
358         if (array.length == 0) {
359             sb = new StringBundler();
360         }
361         else {
362             sb = new StringBundler(2 * array.length - 1);
363         }
364 
365         for (int i = 0; i < array.length; i++) {
366             sb.append(String.valueOf(array[i]).trim());
367 
368             if ((i + 1) != array.length) {
369                 sb.append(delimiter);
370             }
371         }
372 
373         return sb.toString();
374     }
375 
376     public static String merge(Collection<?> col) {
377         return merge(col, StringPool.COMMA);
378     }
379 
380     public static String merge(Collection<?> col, String delimiter) {
381         if (col == null) {
382             return null;
383         }
384 
385         return merge(col.toArray(new Object[col.size()]), delimiter);
386     }
387 
388     public static String merge(double[] array) {
389         return merge(array, StringPool.COMMA);
390     }
391 
392     public static String merge(double[] array, String delimiter) {
393         if (array == null) {
394             return null;
395         }
396 
397         StringBundler sb = null;
398 
399         if (array.length == 0) {
400             sb = new StringBundler();
401         }
402         else {
403             sb = new StringBundler(2 * array.length - 1);
404         }
405 
406         for (int i = 0; i < array.length; i++) {
407             sb.append(String.valueOf(array[i]).trim());
408 
409             if ((i + 1) != array.length) {
410                 sb.append(delimiter);
411             }
412         }
413 
414         return sb.toString();
415     }
416 
417     public static String merge(float[] array) {
418         return merge(array, StringPool.COMMA);
419     }
420 
421     public static String merge(float[] array, String delimiter) {
422         if (array == null) {
423             return null;
424         }
425 
426         StringBundler sb = null;
427 
428         if (array.length == 0) {
429             sb = new StringBundler();
430         }
431         else {
432             sb = new StringBundler(2 * array.length - 1);
433         }
434 
435         for (int i = 0; i < array.length; i++) {
436             sb.append(String.valueOf(array[i]).trim());
437 
438             if ((i + 1) != array.length) {
439                 sb.append(delimiter);
440             }
441         }
442 
443         return sb.toString();
444     }
445 
446     public static String merge(int[] array) {
447         return merge(array, StringPool.COMMA);
448     }
449 
450     public static String merge(int[] array, String delimiter) {
451         if (array == null) {
452             return null;
453         }
454 
455         StringBundler sb = null;
456 
457         if (array.length == 0){
458             sb = new StringBundler();
459         }
460         else {
461             sb = new StringBundler(2 * array.length - 1);
462         }
463 
464         for (int i = 0; i < array.length; i++) {
465             sb.append(String.valueOf(array[i]).trim());
466 
467             if ((i + 1) != array.length) {
468                 sb.append(delimiter);
469             }
470         }
471 
472         return sb.toString();
473     }
474 
475     public static String merge(long[] array) {
476         return merge(array, StringPool.COMMA);
477     }
478 
479     public static String merge(long[] array, String delimiter) {
480         if (array == null) {
481             return null;
482         }
483 
484         StringBundler sb = null;
485 
486         if (array.length == 0) {
487             sb = new StringBundler();
488         }
489         else {
490             sb = new StringBundler(2 * array.length - 1);
491         }
492 
493         for (int i = 0; i < array.length; i++) {
494             sb.append(String.valueOf(array[i]).trim());
495 
496             if ((i + 1) != array.length) {
497                 sb.append(delimiter);
498             }
499         }
500 
501         return sb.toString();
502     }
503 
504     public static String merge(Object[] array) {
505         return merge(array, StringPool.COMMA);
506     }
507 
508     public static String merge(Object[] array, String delimiter) {
509         if (array == null) {
510             return null;
511         }
512 
513         StringBundler sb = null;
514 
515         if (array.length == 0) {
516             sb = new StringBundler();
517         }
518         else {
519             sb = new StringBundler(2 * array.length - 1);
520         }
521 
522         for (int i = 0; i < array.length; i++) {
523             sb.append(String.valueOf(array[i]).trim());
524 
525             if ((i + 1) != array.length) {
526                 sb.append(delimiter);
527             }
528         }
529 
530         return sb.toString();
531     }
532 
533     public static String merge(short[] array) {
534         return merge(array, StringPool.COMMA);
535     }
536 
537     public static String merge(short[] array, String delimiter) {
538         if (array == null) {
539             return null;
540         }
541 
542         StringBundler sb = null;
543 
544         if (array.length == 0) {
545             sb = new StringBundler();
546         }
547         else {
548             sb = new StringBundler(2 * array.length - 1);
549         }
550 
551         for (int i = 0; i < array.length; i++) {
552             sb.append(String.valueOf(array[i]).trim());
553 
554             if ((i + 1) != array.length) {
555                 sb.append(delimiter);
556             }
557         }
558 
559         return sb.toString();
560     }
561 
562     public static String randomize(String s) {
563         return Randomizer.getInstance().randomize(s);
564     }
565 
566     public static String read(ClassLoader classLoader, String name)
567         throws IOException {
568 
569         return read(classLoader, name, false);
570     }
571 
572     public static String read(ClassLoader classLoader, String name, boolean all)
573         throws IOException {
574 
575         if (all) {
576             StringBundler sb = new StringBundler();
577 
578             Enumeration<URL> enu = classLoader.getResources(name);
579 
580             while (enu.hasMoreElements()) {
581                 URL url = enu.nextElement();
582 
583                 InputStream is = url.openStream();
584 
585                 if (is == null) {
586                     throw new IOException(
587                         "Unable to open resource at " + url.toString());
588                 }
589 
590                 String s = read(is);
591 
592                 if (s != null) {
593                     sb.append(s);
594                     sb.append(StringPool.NEW_LINE);
595                 }
596 
597                 is.close();
598             }
599 
600             return sb.toString().trim();
601         }
602         else {
603             InputStream is = classLoader.getResourceAsStream(name);
604 
605             if (is == null) {
606                 throw new IOException(
607                     "Unable to open resource in class loader " + name);
608             }
609 
610             String s = read(is);
611 
612             is.close();
613 
614             return s;
615         }
616     }
617 
618     public static String read(InputStream is) throws IOException {
619         StringBundler sb = new StringBundler();
620 
621         UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
622             new InputStreamReader(is));
623 
624         String line = null;
625 
626         while ((line = unsyncBufferedReader.readLine()) != null) {
627             sb.append(line);
628             sb.append(CharPool.NEW_LINE);
629         }
630 
631         unsyncBufferedReader.close();
632 
633         return sb.toString().trim();
634     }
635 
636     public static String remove(String s, String remove) {
637         return remove(s, remove, StringPool.COMMA);
638     }
639 
640     public static String remove(String s, String remove, String delimiter) {
641         if ((s == null) || (remove == null) || (delimiter == null)) {
642             return null;
643         }
644 
645         if (Validator.isNotNull(s) && !s.endsWith(delimiter)) {
646             s += delimiter;
647         }
648 
649         String drd = delimiter.concat(remove).concat(delimiter);
650 
651         String rd = remove.concat(delimiter);
652 
653         while (contains(s, remove, delimiter)) {
654             int pos = s.indexOf(drd);
655 
656             if (pos == -1) {
657                 if (s.startsWith(rd)) {
658                     int x = remove.length() + delimiter.length();
659                     int y = s.length();
660 
661                     s = s.substring(x, y);
662                 }
663             }
664             else {
665                 int x = pos + remove.length() + delimiter.length();
666                 int y = s.length();
667 
668                 String temp = s.substring(0, pos);
669 
670                 s = temp.concat(s.substring(x, y));
671             }
672         }
673 
674         return s;
675     }
676 
677     public static String replace(String s, char oldSub, char newSub) {
678         if (s == null) {
679             return null;
680         }
681 
682         return s.replace(oldSub, newSub);
683     }
684 
685     public static String replace(String s, char oldSub, String newSub) {
686         if ((s == null) || (newSub == null)) {
687             return null;
688         }
689 
690         // The number 5 is arbitrary and is used as extra padding to reduce
691         // buffer expansion
692 
693         StringBuilder sb = new StringBuilder(s.length() + 5 * newSub.length());
694 
695         char[] charArray = s.toCharArray();
696 
697         for (char c : charArray) {
698             if (c == oldSub) {
699                 sb.append(newSub);
700             }
701             else {
702                 sb.append(c);
703             }
704         }
705 
706         return sb.toString();
707     }
708 
709     public static String replace(String s, String oldSub, String newSub) {
710         return replace(s, oldSub, newSub, 0);
711     }
712 
713     public static String replace(
714         String s, String oldSub, String newSub, int fromIndex) {
715 
716         if ((s == null) || (oldSub == null) || (newSub == null)) {
717             return null;
718         }
719 
720         int y = s.indexOf(oldSub, fromIndex);
721 
722         if (y >= 0) {
723 
724             // The number 5 is arbitrary and is used as extra padding to reduce
725             // buffer expansion
726 
727             StringBuilder sb = new StringBuilder(
728                 s.length() + 5 * newSub.length());
729 
730             int length = oldSub.length();
731             int x = 0;
732 
733             while (x <= y) {
734                 sb.append(s.substring(x, y));
735                 sb.append(newSub);
736 
737                 x = y + length;
738                 y = s.indexOf(oldSub, x);
739             }
740 
741             sb.append(s.substring(x));
742 
743             return sb.toString();
744         }
745         else {
746             return s;
747         }
748     }
749 
750     public static String replace(String s, String[] oldSubs, String[] newSubs) {
751         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
752             return null;
753         }
754 
755         if (oldSubs.length != newSubs.length) {
756             return s;
757         }
758 
759         for (int i = 0; i < oldSubs.length; i++) {
760             s = replace(s, oldSubs[i], newSubs[i]);
761         }
762 
763         return s;
764     }
765 
766     public static String replace(
767         String s, String[] oldSubs, String[] newSubs, boolean exactMatch) {
768 
769         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
770             return null;
771         }
772 
773         if (oldSubs.length != newSubs.length) {
774             return s;
775         }
776 
777         if (!exactMatch) {
778             replace(s, oldSubs, newSubs);
779         }
780         else {
781             for (int i = 0; i < oldSubs.length; i++) {
782                 s = s.replaceAll("\\b" + oldSubs[i] + "\\b" , newSubs[i]);
783             }
784         }
785 
786         return s;
787     }
788 
789     public static String replaceFirst(String s, char oldSub, char newSub) {
790         if (s == null) {
791             return null;
792         }
793 
794         return s.replaceFirst(String.valueOf(oldSub), String.valueOf(newSub));
795     }
796 
797     public static String replaceFirst(String s, char oldSub, String newSub) {
798         if ((s == null) || (newSub == null)) {
799             return null;
800         }
801 
802         return s.replaceFirst(String.valueOf(oldSub), newSub);
803     }
804 
805     public static String replaceFirst(String s, String oldSub, String newSub) {
806         if ((s == null) || (oldSub == null) || (newSub == null)) {
807             return null;
808         }
809 
810         return s.replaceFirst(oldSub, newSub);
811     }
812 
813     public static String replaceFirst(
814         String s, String[] oldSubs, String[] newSubs) {
815 
816         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
817             return null;
818         }
819 
820         if (oldSubs.length != newSubs.length) {
821             return s;
822         }
823 
824         for (int i = 0; i < oldSubs.length; i++) {
825             s = replaceFirst(s, oldSubs[i], newSubs[i]);
826         }
827 
828         return s;
829     }
830 
831     public static String replaceLast(String s, char oldSub, char newSub) {
832         if (s == null) {
833             return null;
834         }
835 
836         return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub));
837     }
838 
839     public static String replaceLast(String s, char oldSub, String newSub) {
840         if ((s == null) || (newSub == null)) {
841             return null;
842         }
843 
844         return replaceLast(s, String.valueOf(oldSub), newSub);
845     }
846 
847     public static String replaceLast(String s, String oldSub, String newSub) {
848         if ((s == null) || (oldSub == null) || (newSub == null)) {
849             return null;
850         }
851 
852         int y = s.lastIndexOf(oldSub);
853 
854         if (y >= 0) {
855 
856             // The number 5 is arbitrary and is used as extra padding to reduce
857             // buffer expansion
858 
859             StringBuilder sb = new StringBuilder(
860                 s.length() + 5 * newSub.length());
861 
862             int length = oldSub.length();
863             int x = 0;
864 
865             while (x <= y) {
866                 sb.append(s.substring(x, y));
867                 sb.append(newSub);
868 
869                 x = y + length;
870                 y = s.indexOf(oldSub, x);
871             }
872 
873             sb.append(s.substring(x));
874 
875             return sb.toString();
876         }
877         else {
878             return s;
879         }
880     }
881 
882     public static String replaceLast(
883         String s, String[] oldSubs, String[] newSubs) {
884 
885         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
886             return null;
887         }
888 
889         if (oldSubs.length != newSubs.length) {
890             return s;
891         }
892 
893         for (int i = 0; i < oldSubs.length; i++) {
894             s = replaceLast(s, oldSubs[i], newSubs[i]);
895         }
896 
897         return s;
898     }
899 
900     /**
901      * Returns a string with replaced values. This method will replace all text
902      * in the given string, between the beginning and ending delimiter, with new
903      * values found in the given map. For example, if the string contained the
904      * text <code>[$HELLO$]</code>, and the beginning delimiter was
905      * <code>[$]</code>, and the ending delimiter was <code>$]</code>, and the
906      * values map had a key of <code>HELLO</code> that mapped to
907      * <code>WORLD</code>, then the replaced string will contain the text
908      * <code>[$WORLD$]</code>.
909      *
910      * @return a string with replaced values
911      */
912     public static String replaceValues(
913         String s, String begin, String end, Map<String, String> values) {
914 
915         if ((s == null) || (begin == null) || (end == null) ||
916             (values == null) || (values.size() == 0)) {
917 
918             return s;
919         }
920 
921         StringBuilder sb = new StringBuilder(s.length());
922 
923         int pos = 0;
924 
925         while (true) {
926             int x = s.indexOf(begin, pos);
927             int y = s.indexOf(end, x + begin.length());
928 
929             if ((x == -1) || (y == -1)) {
930                 sb.append(s.substring(pos, s.length()));
931 
932                 break;
933             }
934             else {
935                 sb.append(s.substring(pos, x + begin.length()));
936 
937                 String oldValue = s.substring(x + begin.length(), y);
938 
939                 String newValue = values.get(oldValue);
940 
941                 if (newValue == null) {
942                     newValue = oldValue;
943                 }
944 
945                 sb.append(newValue);
946 
947                 pos = y;
948             }
949         }
950 
951         return sb.toString();
952     }
953 
954     public static String reverse(String s) {
955         if (s == null) {
956             return null;
957         }
958 
959         char[] charArray = s.toCharArray();
960         char[] reverse = new char[charArray.length];
961 
962         for (int i = 0; i < charArray.length; i++) {
963             reverse[i] = charArray[charArray.length - i - 1];
964         }
965 
966         return new String(reverse);
967     }
968 
969     public static String safePath(String path) {
970         return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH);
971     }
972 
973     public static String shorten(String s) {
974         return shorten(s, 20);
975     }
976 
977     public static String shorten(String s, int length) {
978         return shorten(s, length, "...");
979     }
980 
981     public static String shorten(String s, int length, String suffix) {
982         if ((s == null) || (suffix == null)) {
983             return null;
984         }
985 
986         if (s.length() > length) {
987             for (int j = length; j >= 0; j--) {
988                 if (Character.isWhitespace(s.charAt(j))) {
989                     length = j;
990 
991                     break;
992                 }
993             }
994 
995             String temp = s.substring(0, length);
996 
997             s = temp.concat(suffix);
998         }
999 
1000        return s;
1001    }
1002
1003    public static String shorten(String s, String suffix) {
1004        return shorten(s, 20, suffix);
1005    }
1006
1007    public static String[] split(String s) {
1008        return split(s, StringPool.COMMA);
1009    }
1010
1011    public static boolean[] split(String s, boolean x) {
1012        return split(s, StringPool.COMMA, x);
1013    }
1014
1015    public static double[] split(String s, double x) {
1016        return split(s, StringPool.COMMA, x);
1017    }
1018
1019    public static float[] split(String s, float x) {
1020        return split(s, StringPool.COMMA, x);
1021    }
1022
1023    public static int[] split(String s, int x) {
1024        return split(s, StringPool.COMMA, x);
1025    }
1026
1027    public static long[] split(String s, long x) {
1028        return split(s, StringPool.COMMA, x);
1029    }
1030
1031    public static short[] split(String s, short x) {
1032        return split(s, StringPool.COMMA, x);
1033    }
1034
1035    public static String[] split(String s, String delimiter) {
1036        if ((Validator.isNull(s)) || (delimiter == null) ||
1037            (delimiter.equals(StringPool.BLANK))) {
1038
1039            return new String[0];
1040        }
1041
1042        s = s.trim();
1043
1044        if (s.equals(delimiter)) {
1045            return new String[0];
1046        }
1047
1048        List<String> nodeValues = new ArrayList<String>();
1049
1050        if (delimiter.equals(StringPool.NEW_LINE) ||
1051            delimiter.equals(StringPool.RETURN)) {
1052
1053            try {
1054                UnsyncBufferedReader unsyncBufferedReader =
1055                    new UnsyncBufferedReader(new UnsyncStringReader(s));
1056
1057                String line = null;
1058
1059                while ((line = unsyncBufferedReader.readLine()) != null) {
1060                    nodeValues.add(line);
1061                }
1062
1063                unsyncBufferedReader.close();
1064            }
1065            catch (IOException ioe) {
1066                _log.error(ioe.getMessage());
1067            }
1068        }
1069        else {
1070            int offset = 0;
1071            int pos = s.indexOf(delimiter, offset);
1072
1073            while (pos != -1) {
1074                nodeValues.add(s.substring(offset, pos));
1075
1076                offset = pos + delimiter.length();
1077                pos = s.indexOf(delimiter, offset);
1078            }
1079
1080            if (offset < s.length()) {
1081                nodeValues.add(s.substring(offset));
1082            }
1083        }
1084
1085        return nodeValues.toArray(new String[nodeValues.size()]);
1086    }
1087
1088    public static boolean[] split(String s, String delimiter, boolean x) {
1089        String[] array = split(s, delimiter);
1090        boolean[] newArray = new boolean[array.length];
1091
1092        for (int i = 0; i < array.length; i++) {
1093            boolean value = x;
1094
1095            try {
1096                value = Boolean.valueOf(array[i]).booleanValue();
1097            }
1098            catch (Exception e) {
1099            }
1100
1101            newArray[i] = value;
1102        }
1103
1104        return newArray;
1105    }
1106
1107    public static double[] split(String s, String delimiter, double x) {
1108        String[] array = split(s, delimiter);
1109        double[] newArray = new double[array.length];
1110
1111        for (int i = 0; i < array.length; i++) {
1112            double value = x;
1113
1114            try {
1115                value = Double.parseDouble(array[i]);
1116            }
1117            catch (Exception e) {
1118            }
1119
1120            newArray[i] = value;
1121        }
1122
1123        return newArray;
1124    }
1125
1126    public static float[] split(String s, String delimiter, float x) {
1127        String[] array = split(s, delimiter);
1128        float[] newArray = new float[array.length];
1129
1130        for (int i = 0; i < array.length; i++) {
1131            float value = x;
1132
1133            try {
1134                value = Float.parseFloat(array[i]);
1135            }
1136            catch (Exception e) {
1137            }
1138
1139            newArray[i] = value;
1140        }
1141
1142        return newArray;
1143    }
1144
1145    public static int[] split(String s, String delimiter, int x) {
1146        String[] array = split(s, delimiter);
1147        int[] newArray = new int[array.length];
1148
1149        for (int i = 0; i < array.length; i++) {
1150            int value = x;
1151
1152            try {
1153                value = Integer.parseInt(array[i]);
1154            }
1155            catch (Exception e) {
1156            }
1157
1158            newArray[i] = value;
1159        }
1160
1161        return newArray;
1162    }
1163
1164    public static long[] split(String s, String delimiter, long x) {
1165        String[] array = split(s, delimiter);
1166        long[] newArray = new long[array.length];
1167
1168        for (int i = 0; i < array.length; i++) {
1169            long value = x;
1170
1171            try {
1172                value = Long.parseLong(array[i]);
1173            }
1174            catch (Exception e) {
1175            }
1176
1177            newArray[i] = value;
1178        }
1179
1180        return newArray;
1181    }
1182
1183    public static short[] split(String s, String delimiter, short x) {
1184        String[] array = split(s, delimiter);
1185        short[] newArray = new short[array.length];
1186
1187        for (int i = 0; i < array.length; i++) {
1188            short value = x;
1189
1190            try {
1191                value = Short.parseShort(array[i]);
1192            }
1193            catch (Exception e) {
1194            }
1195
1196            newArray[i] = value;
1197        }
1198
1199        return newArray;
1200    }
1201
1202    public static boolean startsWith(String s, char begin) {
1203        return startsWith(s, (new Character(begin)).toString());
1204    }
1205
1206    public static boolean startsWith(String s, String start) {
1207        if ((s == null) || (start == null)) {
1208            return false;
1209        }
1210
1211        if (start.length() > s.length()) {
1212            return false;
1213        }
1214
1215        String temp = s.substring(0, start.length());
1216
1217        if (temp.equalsIgnoreCase(start)) {
1218            return true;
1219        }
1220        else {
1221            return false;
1222        }
1223    }
1224
1225    /**
1226     * Return the number of starting letters that s1 and s2 have in common
1227     * before they deviate.
1228     *
1229     * @return the number of starting letters that s1 and s2 have in common
1230     *         before they deviate
1231     */
1232    public static int startsWithWeight(String s1, String s2) {
1233        if ((s1 == null) || (s2 == null)) {
1234            return 0;
1235        }
1236
1237        char[] charArray1 = s1.toCharArray();
1238        char[] charArray2 = s2.toCharArray();
1239
1240        int i = 0;
1241
1242        for (; (i < charArray1.length) && (i < charArray2.length); i++) {
1243            if (charArray1[i] != charArray2[i]) {
1244                break;
1245            }
1246        }
1247
1248        return i;
1249    }
1250
1251    public static String stripBetween(String s, String begin, String end) {
1252        if ((s == null) || (begin == null) || (end == null)) {
1253            return s;
1254        }
1255
1256        StringBuilder sb = new StringBuilder(s.length());
1257
1258        int pos = 0;
1259
1260        while (true) {
1261            int x = s.indexOf(begin, pos);
1262            int y = s.indexOf(end, x + begin.length());
1263
1264            if ((x == -1) || (y == -1)) {
1265                sb.append(s.substring(pos, s.length()));
1266
1267                break;
1268            }
1269            else {
1270                sb.append(s.substring(pos, x));
1271
1272                pos = y + end.length();
1273            }
1274        }
1275
1276        return sb.toString();
1277    }
1278
1279    public static String trim(String s) {
1280        return trim(s, null);
1281    }
1282
1283    public static String trim(String s, char c) {
1284        return trim(s, new char[] {c});
1285    }
1286
1287    public static String trim(String s, char[] exceptions) {
1288        if (s == null) {
1289            return null;
1290        }
1291
1292        char[] charArray = s.toCharArray();
1293
1294        int len = charArray.length;
1295
1296        int x = 0;
1297        int y = charArray.length;
1298
1299        for (int i = 0; i < len; i++) {
1300            char c = charArray[i];
1301
1302            if (_isTrimable(c, exceptions)) {
1303                x = i + 1;
1304            }
1305            else {
1306                break;
1307            }
1308        }
1309
1310        for (int i = len - 1; i >= 0; i--) {
1311            char c = charArray[i];
1312
1313            if (_isTrimable(c, exceptions)) {
1314                y = i;
1315            }
1316            else {
1317                break;
1318            }
1319        }
1320
1321        if ((x != 0) || (y != len)) {
1322            return s.substring(x, y);
1323        }
1324        else {
1325            return s;
1326        }
1327    }
1328
1329    public static String trimLeading(String s) {
1330        return trimLeading(s, null);
1331    }
1332
1333    public static String trimLeading(String s, char c) {
1334        return trimLeading(s, new char[] {c});
1335    }
1336
1337    public static String trimLeading(String s, char[] exceptions) {
1338        if (s == null) {
1339            return null;
1340        }
1341
1342        char[] charArray = s.toCharArray();
1343
1344        int len = charArray.length;
1345
1346        int x = 0;
1347        int y = charArray.length;
1348
1349        for (int i = 0; i < len; i++) {
1350            char c = charArray[i];
1351
1352            if (_isTrimable(c, exceptions)) {
1353                x = i + 1;
1354            }
1355            else {
1356                break;
1357            }
1358        }
1359
1360        if ((x != 0) || (y != len)) {
1361            return s.substring(x, y);
1362        }
1363        else {
1364            return s;
1365        }
1366    }
1367
1368    public static String trimTrailing(String s) {
1369        return trimTrailing(s, null);
1370    }
1371
1372    public static String trimTrailing(String s, char c) {
1373        return trimTrailing(s, new char[] {c});
1374    }
1375
1376    public static String trimTrailing(String s, char[] exceptions) {
1377        if (s == null) {
1378            return null;
1379        }
1380
1381        char[] charArray = s.toCharArray();
1382
1383        int len = charArray.length;
1384
1385        int x = 0;
1386        int y = charArray.length;
1387
1388        for (int i = len - 1; i >= 0; i--) {
1389            char c = charArray[i];
1390
1391            if (_isTrimable(c, exceptions)) {
1392                y = i;
1393            }
1394            else {
1395                break;
1396            }
1397        }
1398
1399        if ((x != 0) || (y != len)) {
1400            return s.substring(x, y);
1401        }
1402        else {
1403            return s;
1404        }
1405    }
1406
1407    public static String upperCase(String s) {
1408        if (s == null) {
1409            return null;
1410        }
1411        else {
1412            return s.toUpperCase();
1413        }
1414    }
1415
1416    public static String upperCaseFirstLetter(String s) {
1417        char[] charArray = s.toCharArray();
1418
1419        if ((charArray[0] >= 97) && (charArray[0] <= 122)) {
1420            charArray[0] = (char)(charArray[0] - 32);
1421        }
1422
1423        return new String(charArray);
1424    }
1425
1426    public static String valueOf(Object obj) {
1427        return String.valueOf(obj);
1428    }
1429
1430    public static String wrap(String text) {
1431        return wrap(text, 80, StringPool.NEW_LINE);
1432    }
1433
1434    public static String wrap(String text, int width, String lineSeparator) {
1435        try {
1436            return _wrap(text, width, lineSeparator);
1437        }
1438        catch (IOException ioe) {
1439            _log.error(ioe.getMessage());
1440
1441            return text;
1442        }
1443    }
1444
1445    private static String _highlight(
1446        String s, Pattern pattern, String highlight1, String highlight2) {
1447
1448        StringTokenizer st = new StringTokenizer(s);
1449
1450        StringBundler sb = null;
1451
1452        if (st.countTokens() == 0) {
1453            sb = new StringBundler();
1454        }
1455        else {
1456            sb = new StringBundler(2 * st.countTokens() - 1);
1457        }
1458
1459        while (st.hasMoreTokens()) {
1460            String token = st.nextToken();
1461
1462            Matcher matcher = pattern.matcher(token);
1463
1464            if (matcher.find()) {
1465                String highlightedToken = matcher.replaceAll(
1466                    highlight1 + matcher.group() + highlight2);
1467
1468                sb.append(highlightedToken);
1469            }
1470            else {
1471                sb.append(token);
1472            }
1473
1474            if (st.hasMoreTokens()) {
1475                sb.append(StringPool.SPACE);
1476            }
1477        }
1478
1479        return sb.toString();
1480    }
1481
1482    private static boolean _isTrimable(char c, char[] exceptions) {
1483        if ((exceptions != null) && (exceptions.length > 0)) {
1484            for (int i = 0; i < exceptions.length; i++) {
1485                if (c == exceptions[i]) {
1486                    return false;
1487                }
1488            }
1489        }
1490
1491        return Character.isWhitespace(c);
1492    }
1493
1494    private static String _wrap(String text, int width, String lineSeparator)
1495        throws IOException {
1496
1497        if (text == null) {
1498            return null;
1499        }
1500
1501        StringBundler sb = new StringBundler();
1502
1503        UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1504            new UnsyncStringReader(text));
1505
1506        String s = StringPool.BLANK;
1507
1508        while ((s = unsyncBufferedReader.readLine()) != null) {
1509            if (s.length() == 0) {
1510                sb.append(lineSeparator);
1511
1512                continue;
1513            }
1514
1515            int lineLength = 0;
1516
1517            String[] tokens = s.split(StringPool.SPACE);
1518
1519            for (String token : tokens) {
1520                if ((lineLength + token.length() + 1) > width) {
1521                    if (lineLength > 0) {
1522                        sb.append(lineSeparator);
1523                    }
1524
1525                    if (token.length() > width) {
1526                        int pos = token.indexOf(StringPool.OPEN_PARENTHESIS);
1527
1528                        if (pos != -1) {
1529                            sb.append(token.substring(0, pos + 1));
1530                            sb.append(lineSeparator);
1531
1532                            token = token.substring(pos + 1);
1533
1534                            sb.append(token);
1535
1536                            lineLength = token.length();
1537                        }
1538                        else {
1539                            sb.append(token);
1540
1541                            lineLength = token.length();
1542                        }
1543                    }
1544                    else {
1545                        sb.append(token);
1546
1547                        lineLength = token.length();
1548                    }
1549                }
1550                else {
1551                    if (lineLength > 0) {
1552                        sb.append(StringPool.SPACE);
1553
1554                        lineLength++;
1555                    }
1556
1557                    sb.append(token);
1558
1559                    lineLength += token.length();
1560                }
1561            }
1562
1563            sb.append(lineSeparator);
1564        }
1565
1566        return sb.toString();
1567    }
1568
1569    private static Log _log = LogFactoryUtil.getLog(StringUtil.class);
1570
1571}