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