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