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             StringBundler sb = new StringBundler();
724 
725             int length = oldSub.length();
726             int x = 0;
727 
728             while (x <= y) {
729                 sb.append(s.substring(x, y));
730                 sb.append(newSub);
731 
732                 x = y + length;
733                 y = s.indexOf(oldSub, x);
734             }
735 
736             sb.append(s.substring(x));
737 
738             return sb.toString();
739         }
740         else {
741             return s;
742         }
743     }
744 
745     public static String replace(
746         String s, String begin, String end, Map<String, String> values) {
747 
748         StringBundler sb = replaceToStringBundler(s, begin, end, values);
749 
750         return sb.toString();
751     }
752 
753     public static String replace(String s, String[] oldSubs, String[] newSubs) {
754         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
755             return null;
756         }
757 
758         if (oldSubs.length != newSubs.length) {
759             return s;
760         }
761 
762         for (int i = 0; i < oldSubs.length; i++) {
763             s = replace(s, oldSubs[i], newSubs[i]);
764         }
765 
766         return s;
767     }
768 
769     public static String replace(
770         String s, String[] oldSubs, String[] newSubs, boolean exactMatch) {
771 
772         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
773             return null;
774         }
775 
776         if (oldSubs.length != newSubs.length) {
777             return s;
778         }
779 
780         if (!exactMatch) {
781             replace(s, oldSubs, newSubs);
782         }
783         else {
784             for (int i = 0; i < oldSubs.length; i++) {
785                 s = s.replaceAll("\\b" + oldSubs[i] + "\\b" , newSubs[i]);
786             }
787         }
788 
789         return s;
790     }
791 
792     public static String replaceFirst(String s, char oldSub, char newSub) {
793         if (s == null) {
794             return null;
795         }
796 
797         return s.replaceFirst(String.valueOf(oldSub), String.valueOf(newSub));
798     }
799 
800     public static String replaceFirst(String s, char oldSub, String newSub) {
801         if ((s == null) || (newSub == null)) {
802             return null;
803         }
804 
805         return s.replaceFirst(String.valueOf(oldSub), newSub);
806     }
807 
808     public static String replaceFirst(String s, String oldSub, String newSub) {
809         if ((s == null) || (oldSub == null) || (newSub == null)) {
810             return null;
811         }
812 
813         return s.replaceFirst(oldSub, newSub);
814     }
815 
816     public static String replaceFirst(
817         String s, String[] oldSubs, String[] newSubs) {
818 
819         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
820             return null;
821         }
822 
823         if (oldSubs.length != newSubs.length) {
824             return s;
825         }
826 
827         for (int i = 0; i < oldSubs.length; i++) {
828             s = replaceFirst(s, oldSubs[i], newSubs[i]);
829         }
830 
831         return s;
832     }
833 
834     public static String replaceLast(String s, char oldSub, char newSub) {
835         if (s == null) {
836             return null;
837         }
838 
839         return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub));
840     }
841 
842     public static String replaceLast(String s, char oldSub, String newSub) {
843         if ((s == null) || (newSub == null)) {
844             return null;
845         }
846 
847         return replaceLast(s, String.valueOf(oldSub), newSub);
848     }
849 
850     public static String replaceLast(String s, String oldSub, String newSub) {
851         if ((s == null) || (oldSub == null) || (newSub == null)) {
852             return null;
853         }
854 
855         int y = s.lastIndexOf(oldSub);
856 
857         if (y >= 0) {
858             StringBundler sb = new StringBundler();
859 
860             int length = oldSub.length();
861             int x = 0;
862 
863             while (x <= y) {
864                 sb.append(s.substring(x, y));
865                 sb.append(newSub);
866 
867                 x = y + length;
868                 y = s.indexOf(oldSub, x);
869             }
870 
871             sb.append(s.substring(x));
872 
873             return sb.toString();
874         }
875         else {
876             return s;
877         }
878     }
879 
880     public static String replaceLast(
881         String s, String[] oldSubs, String[] newSubs) {
882 
883         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
884             return null;
885         }
886 
887         if (oldSubs.length != newSubs.length) {
888             return s;
889         }
890 
891         for (int i = 0; i < oldSubs.length; i++) {
892             s = replaceLast(s, oldSubs[i], newSubs[i]);
893         }
894 
895         return s;
896     }
897 
898     public static StringBundler replaceToStringBundler(
899         String s, String begin, String end, Map<String, String> values) {
900 
901         if ((s == null) || (begin == null) || (end == null) ||
902             (values == null) || (values.size() == 0)) {
903 
904             return new StringBundler(s);
905         }
906 
907         StringBundler sb = new StringBundler(values.size() * 2 + 1);
908 
909         int pos = 0;
910 
911         while (true) {
912             int x = s.indexOf(begin, pos);
913             int y = s.indexOf(end, x + begin.length());
914 
915             if ((x == -1) || (y == -1)) {
916                 sb.append(s.substring(pos, s.length()));
917 
918                 break;
919             }
920             else {
921                 sb.append(s.substring(pos, x));
922 
923                 String oldValue = s.substring(x + begin.length(), y);
924 
925                 String newValue = values.get(oldValue);
926 
927                 if (newValue == null) {
928                     newValue = oldValue;
929                 }
930 
931                 sb.append(newValue);
932 
933                 pos = y + end.length();
934             }
935         }
936 
937         return sb;
938     }
939 
940     public static StringBundler replaceWithStringBundler(
941         String s, String begin, String end, Map<String, StringBundler> values) {
942 
943         if ((s == null) || (begin == null) || (end == null) ||
944             (values == null) || (values.size() == 0)) {
945 
946             return new StringBundler(s);
947         }
948 
949         int size = values.size() + 1;
950 
951         for (StringBundler valueSB : values.values()) {
952             size += valueSB.index();
953         }
954 
955         StringBundler sb = new StringBundler(size);
956 
957         int pos = 0;
958 
959         while (true) {
960             int x = s.indexOf(begin, pos);
961             int y = s.indexOf(end, x + begin.length());
962 
963             if ((x == -1) || (y == -1)) {
964                 sb.append(s.substring(pos, s.length()));
965 
966                 break;
967             }
968             else {
969                 sb.append(s.substring(pos, x));
970 
971                 String oldValue = s.substring(x + begin.length(), y);
972 
973                 StringBundler newValue = values.get(oldValue);
974 
975                 if (newValue == null) {
976                     sb.append(oldValue);
977                 }
978                 else {
979                     sb.append(newValue);
980                 }
981 
982                 pos = y + end.length();
983             }
984         }
985 
986         return sb;
987     }
988 
989     public static String reverse(String s) {
990         if (s == null) {
991             return null;
992         }
993 
994         char[] charArray = s.toCharArray();
995         char[] reverse = new char[charArray.length];
996 
997         for (int i = 0; i < charArray.length; i++) {
998             reverse[i] = charArray[charArray.length - i - 1];
999         }
1000
1001        return new String(reverse);
1002    }
1003
1004    public static String safePath(String path) {
1005        return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH);
1006    }
1007
1008    public static String shorten(String s) {
1009        return shorten(s, 20);
1010    }
1011
1012    public static String shorten(String s, int length) {
1013        return shorten(s, length, "...");
1014    }
1015
1016    public static String shorten(String s, int length, String suffix) {
1017        if ((s == null) || (suffix == null)) {
1018            return null;
1019        }
1020
1021        if (s.length() > length) {
1022            for (int j = length; j >= 0; j--) {
1023                if (Character.isWhitespace(s.charAt(j))) {
1024                    length = j;
1025
1026                    break;
1027                }
1028            }
1029
1030            String temp = s.substring(0, length);
1031
1032            s = temp.concat(suffix);
1033        }
1034
1035        return s;
1036    }
1037
1038    public static String shorten(String s, String suffix) {
1039        return shorten(s, 20, suffix);
1040    }
1041
1042    public static String[] split(String s) {
1043        return split(s, StringPool.COMMA);
1044    }
1045
1046    public static boolean[] split(String s, boolean x) {
1047        return split(s, StringPool.COMMA, x);
1048    }
1049
1050    public static double[] split(String s, double x) {
1051        return split(s, StringPool.COMMA, x);
1052    }
1053
1054    public static float[] split(String s, float x) {
1055        return split(s, StringPool.COMMA, x);
1056    }
1057
1058    public static int[] split(String s, int x) {
1059        return split(s, StringPool.COMMA, x);
1060    }
1061
1062    public static long[] split(String s, long x) {
1063        return split(s, StringPool.COMMA, x);
1064    }
1065
1066    public static short[] split(String s, short x) {
1067        return split(s, StringPool.COMMA, x);
1068    }
1069
1070    public static String[] split(String s, String delimiter) {
1071        if ((Validator.isNull(s)) || (delimiter == null) ||
1072            (delimiter.equals(StringPool.BLANK))) {
1073
1074            return new String[0];
1075        }
1076
1077        s = s.trim();
1078
1079        if (s.equals(delimiter)) {
1080            return new String[0];
1081        }
1082
1083        List<String> nodeValues = new ArrayList<String>();
1084
1085        if (delimiter.equals(StringPool.NEW_LINE) ||
1086            delimiter.equals(StringPool.RETURN)) {
1087
1088            try {
1089                UnsyncBufferedReader unsyncBufferedReader =
1090                    new UnsyncBufferedReader(new UnsyncStringReader(s));
1091
1092                String line = null;
1093
1094                while ((line = unsyncBufferedReader.readLine()) != null) {
1095                    nodeValues.add(line);
1096                }
1097
1098                unsyncBufferedReader.close();
1099            }
1100            catch (IOException ioe) {
1101                _log.error(ioe.getMessage());
1102            }
1103        }
1104        else {
1105            int offset = 0;
1106            int pos = s.indexOf(delimiter, offset);
1107
1108            while (pos != -1) {
1109                nodeValues.add(s.substring(offset, pos));
1110
1111                offset = pos + delimiter.length();
1112                pos = s.indexOf(delimiter, offset);
1113            }
1114
1115            if (offset < s.length()) {
1116                nodeValues.add(s.substring(offset));
1117            }
1118        }
1119
1120        return nodeValues.toArray(new String[nodeValues.size()]);
1121    }
1122
1123    public static boolean[] split(String s, String delimiter, boolean x) {
1124        String[] array = split(s, delimiter);
1125        boolean[] newArray = new boolean[array.length];
1126
1127        for (int i = 0; i < array.length; i++) {
1128            boolean value = x;
1129
1130            try {
1131                value = Boolean.valueOf(array[i]).booleanValue();
1132            }
1133            catch (Exception e) {
1134            }
1135
1136            newArray[i] = value;
1137        }
1138
1139        return newArray;
1140    }
1141
1142    public static double[] split(String s, String delimiter, double x) {
1143        String[] array = split(s, delimiter);
1144        double[] newArray = new double[array.length];
1145
1146        for (int i = 0; i < array.length; i++) {
1147            double value = x;
1148
1149            try {
1150                value = Double.parseDouble(array[i]);
1151            }
1152            catch (Exception e) {
1153            }
1154
1155            newArray[i] = value;
1156        }
1157
1158        return newArray;
1159    }
1160
1161    public static float[] split(String s, String delimiter, float x) {
1162        String[] array = split(s, delimiter);
1163        float[] newArray = new float[array.length];
1164
1165        for (int i = 0; i < array.length; i++) {
1166            float value = x;
1167
1168            try {
1169                value = Float.parseFloat(array[i]);
1170            }
1171            catch (Exception e) {
1172            }
1173
1174            newArray[i] = value;
1175        }
1176
1177        return newArray;
1178    }
1179
1180    public static int[] split(String s, String delimiter, int x) {
1181        String[] array = split(s, delimiter);
1182        int[] newArray = new int[array.length];
1183
1184        for (int i = 0; i < array.length; i++) {
1185            int value = x;
1186
1187            try {
1188                value = Integer.parseInt(array[i]);
1189            }
1190            catch (Exception e) {
1191            }
1192
1193            newArray[i] = value;
1194        }
1195
1196        return newArray;
1197    }
1198
1199    public static long[] split(String s, String delimiter, long x) {
1200        String[] array = split(s, delimiter);
1201        long[] newArray = new long[array.length];
1202
1203        for (int i = 0; i < array.length; i++) {
1204            long value = x;
1205
1206            try {
1207                value = Long.parseLong(array[i]);
1208            }
1209            catch (Exception e) {
1210            }
1211
1212            newArray[i] = value;
1213        }
1214
1215        return newArray;
1216    }
1217
1218    public static short[] split(String s, String delimiter, short x) {
1219        String[] array = split(s, delimiter);
1220        short[] newArray = new short[array.length];
1221
1222        for (int i = 0; i < array.length; i++) {
1223            short value = x;
1224
1225            try {
1226                value = Short.parseShort(array[i]);
1227            }
1228            catch (Exception e) {
1229            }
1230
1231            newArray[i] = value;
1232        }
1233
1234        return newArray;
1235    }
1236
1237    public static boolean startsWith(String s, char begin) {
1238        return startsWith(s, (new Character(begin)).toString());
1239    }
1240
1241    public static boolean startsWith(String s, String start) {
1242        if ((s == null) || (start == null)) {
1243            return false;
1244        }
1245
1246        if (start.length() > s.length()) {
1247            return false;
1248        }
1249
1250        String temp = s.substring(0, start.length());
1251
1252        if (temp.equalsIgnoreCase(start)) {
1253            return true;
1254        }
1255        else {
1256            return false;
1257        }
1258    }
1259
1260    /**
1261     * Return the number of starting letters that s1 and s2 have in common
1262     * before they deviate.
1263     *
1264     * @return the number of starting letters that s1 and s2 have in common
1265     *         before they deviate
1266     */
1267    public static int startsWithWeight(String s1, String s2) {
1268        if ((s1 == null) || (s2 == null)) {
1269            return 0;
1270        }
1271
1272        char[] charArray1 = s1.toCharArray();
1273        char[] charArray2 = s2.toCharArray();
1274
1275        int i = 0;
1276
1277        for (; (i < charArray1.length) && (i < charArray2.length); i++) {
1278            if (charArray1[i] != charArray2[i]) {
1279                break;
1280            }
1281        }
1282
1283        return i;
1284    }
1285
1286    public static String stripBetween(String s, String begin, String end) {
1287        if ((s == null) || (begin == null) || (end == null)) {
1288            return s;
1289        }
1290
1291        StringBuilder sb = new StringBuilder(s.length());
1292
1293        int pos = 0;
1294
1295        while (true) {
1296            int x = s.indexOf(begin, pos);
1297            int y = s.indexOf(end, x + begin.length());
1298
1299            if ((x == -1) || (y == -1)) {
1300                sb.append(s.substring(pos, s.length()));
1301
1302                break;
1303            }
1304            else {
1305                sb.append(s.substring(pos, x));
1306
1307                pos = y + end.length();
1308            }
1309        }
1310
1311        return sb.toString();
1312    }
1313
1314    public static String trim(String s) {
1315        return trim(s, null);
1316    }
1317
1318    public static String trim(String s, char c) {
1319        return trim(s, new char[] {c});
1320    }
1321
1322    public static String trim(String s, char[] exceptions) {
1323        if (s == null) {
1324            return null;
1325        }
1326
1327        char[] charArray = s.toCharArray();
1328
1329        int len = charArray.length;
1330
1331        int x = 0;
1332        int y = charArray.length;
1333
1334        for (int i = 0; i < len; i++) {
1335            char c = charArray[i];
1336
1337            if (_isTrimable(c, exceptions)) {
1338                x = i + 1;
1339            }
1340            else {
1341                break;
1342            }
1343        }
1344
1345        for (int i = len - 1; i >= 0; i--) {
1346            char c = charArray[i];
1347
1348            if (_isTrimable(c, exceptions)) {
1349                y = i;
1350            }
1351            else {
1352                break;
1353            }
1354        }
1355
1356        if ((x != 0) || (y != len)) {
1357            return s.substring(x, y);
1358        }
1359        else {
1360            return s;
1361        }
1362    }
1363
1364    public static String trimLeading(String s) {
1365        return trimLeading(s, null);
1366    }
1367
1368    public static String trimLeading(String s, char c) {
1369        return trimLeading(s, new char[] {c});
1370    }
1371
1372    public static String trimLeading(String s, char[] exceptions) {
1373        if (s == null) {
1374            return null;
1375        }
1376
1377        char[] charArray = s.toCharArray();
1378
1379        int len = charArray.length;
1380
1381        int x = 0;
1382        int y = charArray.length;
1383
1384        for (int i = 0; i < len; i++) {
1385            char c = charArray[i];
1386
1387            if (_isTrimable(c, exceptions)) {
1388                x = i + 1;
1389            }
1390            else {
1391                break;
1392            }
1393        }
1394
1395        if ((x != 0) || (y != len)) {
1396            return s.substring(x, y);
1397        }
1398        else {
1399            return s;
1400        }
1401    }
1402
1403    public static String trimTrailing(String s) {
1404        return trimTrailing(s, null);
1405    }
1406
1407    public static String trimTrailing(String s, char c) {
1408        return trimTrailing(s, new char[] {c});
1409    }
1410
1411    public static String trimTrailing(String s, char[] exceptions) {
1412        if (s == null) {
1413            return null;
1414        }
1415
1416        char[] charArray = s.toCharArray();
1417
1418        int len = charArray.length;
1419
1420        int x = 0;
1421        int y = charArray.length;
1422
1423        for (int i = len - 1; i >= 0; i--) {
1424            char c = charArray[i];
1425
1426            if (_isTrimable(c, exceptions)) {
1427                y = i;
1428            }
1429            else {
1430                break;
1431            }
1432        }
1433
1434        if ((x != 0) || (y != len)) {
1435            return s.substring(x, y);
1436        }
1437        else {
1438            return s;
1439        }
1440    }
1441
1442    public static String upperCase(String s) {
1443        if (s == null) {
1444            return null;
1445        }
1446        else {
1447            return s.toUpperCase();
1448        }
1449    }
1450
1451    public static String upperCaseFirstLetter(String s) {
1452        char[] charArray = s.toCharArray();
1453
1454        if ((charArray[0] >= 97) && (charArray[0] <= 122)) {
1455            charArray[0] = (char)(charArray[0] - 32);
1456        }
1457
1458        return new String(charArray);
1459    }
1460
1461    public static String valueOf(Object obj) {
1462        return String.valueOf(obj);
1463    }
1464
1465    public static String wrap(String text) {
1466        return wrap(text, 80, StringPool.NEW_LINE);
1467    }
1468
1469    public static String wrap(String text, int width, String lineSeparator) {
1470        try {
1471            return _wrap(text, width, lineSeparator);
1472        }
1473        catch (IOException ioe) {
1474            _log.error(ioe.getMessage());
1475
1476            return text;
1477        }
1478    }
1479
1480    private static String _highlight(
1481        String s, Pattern pattern, String highlight1, String highlight2) {
1482
1483        StringTokenizer st = new StringTokenizer(s);
1484
1485        StringBundler sb = null;
1486
1487        if (st.countTokens() == 0) {
1488            sb = new StringBundler();
1489        }
1490        else {
1491            sb = new StringBundler(2 * st.countTokens() - 1);
1492        }
1493
1494        while (st.hasMoreTokens()) {
1495            String token = st.nextToken();
1496
1497            Matcher matcher = pattern.matcher(token);
1498
1499            if (matcher.find()) {
1500                String highlightedToken = matcher.replaceAll(
1501                    highlight1 + matcher.group() + highlight2);
1502
1503                sb.append(highlightedToken);
1504            }
1505            else {
1506                sb.append(token);
1507            }
1508
1509            if (st.hasMoreTokens()) {
1510                sb.append(StringPool.SPACE);
1511            }
1512        }
1513
1514        return sb.toString();
1515    }
1516
1517    private static boolean _isTrimable(char c, char[] exceptions) {
1518        if ((exceptions != null) && (exceptions.length > 0)) {
1519            for (int i = 0; i < exceptions.length; i++) {
1520                if (c == exceptions[i]) {
1521                    return false;
1522                }
1523            }
1524        }
1525
1526        return Character.isWhitespace(c);
1527    }
1528
1529    private static String _wrap(String text, int width, String lineSeparator)
1530        throws IOException {
1531
1532        if (text == null) {
1533            return null;
1534        }
1535
1536        StringBundler sb = new StringBundler();
1537
1538        UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
1539            new UnsyncStringReader(text));
1540
1541        String s = StringPool.BLANK;
1542
1543        while ((s = unsyncBufferedReader.readLine()) != null) {
1544            if (s.length() == 0) {
1545                sb.append(lineSeparator);
1546
1547                continue;
1548            }
1549
1550            int lineLength = 0;
1551
1552            String[] tokens = s.split(StringPool.SPACE);
1553
1554            for (String token : tokens) {
1555                if ((lineLength + token.length() + 1) > width) {
1556                    if (lineLength > 0) {
1557                        sb.append(lineSeparator);
1558                    }
1559
1560                    if (token.length() > width) {
1561                        int pos = token.indexOf(StringPool.OPEN_PARENTHESIS);
1562
1563                        if (pos != -1) {
1564                            sb.append(token.substring(0, pos + 1));
1565                            sb.append(lineSeparator);
1566
1567                            token = token.substring(pos + 1);
1568
1569                            sb.append(token);
1570
1571                            lineLength = token.length();
1572                        }
1573                        else {
1574                            sb.append(token);
1575
1576                            lineLength = token.length();
1577                        }
1578                    }
1579                    else {
1580                        sb.append(token);
1581
1582                        lineLength = token.length();
1583                    }
1584                }
1585                else {
1586                    if (lineLength > 0) {
1587                        sb.append(StringPool.SPACE);
1588
1589                        lineLength++;
1590                    }
1591
1592                    sb.append(token);
1593
1594                    lineLength += token.length();
1595                }
1596            }
1597
1598            sb.append(lineSeparator);
1599        }
1600
1601        return sb.toString();
1602    }
1603
1604    private static Log _log = LogFactoryUtil.getLog(StringUtil.class);
1605
1606}