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