View Javadoc

1   /*
2    * Copyright 2003,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /* 
17  
18   */
19  
20  package org.apache.pluto.util;
21  
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.Map;
25  
26  /***
27   ** <CODE>StringUtils</CODE> hosts a couple of utility methods around
28   ** strings.
29   **/
30  
31  public class StringUtils
32  {
33  
34      static java.util.BitSet dontNeedEncoding;
35      static final int caseDiff = ('a' - 'A');
36  
37      /* The list of characters that are not encoded have been determined by
38         referencing O'Reilly's "HTML: The Definitive Guide" (page 164). */
39  
40      static {
41          dontNeedEncoding = new java.util.BitSet(256);
42          int i;
43          for (i = 'a'; i <= 'z'; i++)
44          {
45              dontNeedEncoding.set(i);
46          }
47          for (i = 'A'; i <= 'Z'; i++)
48          {
49              dontNeedEncoding.set(i);
50          }
51          for (i = '0'; i <= '9'; i++)
52          {
53              dontNeedEncoding.set(i);
54          }
55          dontNeedEncoding.set('-');
56          dontNeedEncoding.set('_');
57          dontNeedEncoding.set('.');
58          dontNeedEncoding.set('*');
59      }
60  
61      /***
62       ** The operating system's line separator ('\n' on UNIX, '\r\n' on Windows)
63       **/
64  
65      public static final String lineSeparator = System.getProperty("line.separator");
66  
67      /***
68       ** Returns the name of the package of the specified class.
69       ** The package will not include the common (short) name of the
70       ** class or the file extension.
71       **
72       ** @param   aClass
73       **          a class object
74       **
75       ** @return   its package
76       **/
77  
78      publicong> static String packageOf (Class aClass)
79      {
80          if (aClass == null)
81          {
82              throw (new IllegalArgumentException ("StringUtils: Argument \"aClass\" cannot be null."));
83          }
84  
85          String result = "";
86  
87          int index = aClass.getName ().lastIndexOf (".");
88  
89          if (index >= 0)
90          {
91              result = aClass.getName ().substring (0, index);
92          }
93  
94          return(result);
95      }
96  
97      /***
98       * Returns the short name of the specified class.
99       * The name will not include the package name or file extension.
100      *
101      * @param   aClass
102      *          a class object
103      *
104      * @return   its name
105      */
106 
107     public static String nameOf (Class aClass)
108     {
109         if (aClass == null)
110         {
111             throw new IllegalArgumentException ("StringUtils: Argument \"aClass\" cannot be null.");
112         }
113 
114         String className = aClass.getName ();
115 
116         int index = className.lastIndexOf (".");
117 
118         if (index >= 0)
119         {
120             className = className.substring (index + 1);
121         }
122 
123         return(className);
124     }
125 
126     /***
127      * Returns a combination of two paths, inserting slashes as appropriate.
128      *
129      * @param   aRoot
130      *          a root path
131      * @param   aPath
132      *          a path
133      *
134      * @return   the path
135      */
136 
137     public static String pathOf (String aRoot, String aPath)
138     {
139         if (aPath == null)
140         {
141             throw new IllegalArgumentException ("StringUtils: Argument \"aPath\" cannot be null.");
142         }
143 
144         String result = null;
145 
146         if (aPath.startsWith ("/")  ||
147             aPath.startsWith ("//") ||
148             (aPath.length () >= 2 && aPath.charAt (1) == ':'))
149         {
150             result = aPath;
151         }
152         else
153         {
154             if (aRoot == null)
155             {
156                 throw new IllegalArgumentException ("StringUtils: Argument \"aRoot\" cannot be null.");
157             }
158 
159             StringBuffer temp = new StringBuffer (aRoot);
160 
161             if (! aRoot.endsWith ("/") &&
162                 ! aRoot.endsWith ("//"))
163             {
164                 temp.append ('/');
165             }
166 
167             temp.append (aPath);
168 
169             result = temp.toString ();
170         }
171 
172         return result.toString();
173     }
174 
175     /***
176      * Returns a <CODE>Boolean</CODE> object that corresponds the given value.
177      * A value of <CODE>true</CODE> or <CODE>yes</CODE> corresponds to
178      * <CODE>Boolean.TRUE</CODE> and a value of <CODE>false</CODE> or
179      * <CODE>no</CODE> corresponds to <CODE>Boolean.FALSE</CODE>.
180      * The comparions is case-insensitive, but for performance reasons,
181      * lower-case values of <CODE>true</CODE> and <CODE>false</CODE>
182      * should be used.
183      *
184      * @param   aValue
185      *          to value to convert
186      *
187      * @return   the boolean value
188      */
189     public static Boolean booleanOf (String aValue)
190     {
191         Boolean result = null;
192 
193         if (aValue != null)
194         {
195             if (aValue == "true" ||
196                 aValue == "yes" ||
197                 aValue.equalsIgnoreCase ("true") ||
198                 aValue.equalsIgnoreCase ("yes"))
199             {
200                 result = Boolean.TRUE;
201             }
202             else if (aValue == "false" ||
203                      aValue == "no" ||
204                      aValue.equalsIgnoreCase ("false") ||
205                      aValue.equalsIgnoreCase ("no"))
206             {
207                 result = Boolean.FALSE;
208             }
209         }
210 
211         return(result);
212     }
213 
214     /***
215      * Replace all occurrences of a pattern within a string by a replacement
216      *
217      * @param source  The string that should be searched
218      * @param pattern  The pattern that should be replaced
219      * @param replace  The replacement that should be inserted instead of the pattern
220      *
221      * @return  The updated source string
222      */
223     public static String replace(String source, String pattern, String replace)
224     {
225         if (source == null || source.length() == 0 ||
226             pattern == null || pattern.length() == 0)
227         {
228             return source;
229         }
230 
231         int k = source.indexOf(pattern);
232 
233         if (k == -1)
234         {
235             return source;
236         }
237 
238         StringBuffer out = new StringBuffer();
239         int i=0, l=pattern.length();
240 
241         while (k != -1)
242         {
243             out.append(source.substring(i,k));
244 
245             if (replace != null) {
246                 out.append(replace);
247             }
248 
249             i = k+l;
250             k = source.indexOf(pattern, i);
251         }
252         out.append(source.substring(i));
253         return out.toString();
254     }
255 
256     public static void newLine(StringBuffer buffer, int indent)
257     {
258         buffer.append(StringUtils.lineSeparator);
259         indent(buffer, indent);
260     }
261 
262     public static void indent(StringBuffer buffer, int indent)
263     {
264         for (int i=0; i<indent; i++) buffer.append(' ');
265     }
266 
267     public static String encode(String s)
268     {
269         int maxBytesPerChar = 10;
270         StringBuffer out = new StringBuffer(s.length());
271         java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream(maxBytesPerChar);
272         java.io.OutputStreamWriter writer = new java.io.OutputStreamWriter(buf);
273 
274         for (int i = 0; i < s.length(); i++)
275         {
276             int c = (int)s.charAt(i);
277             if (dontNeedEncoding.get(c))
278             {
279                 out.append((char)c);
280             }
281             else
282             {
283                 // convert to external encoding before hex conversion
284                 try
285                 {
286                     writer.write(c);
287                     writer.flush();
288                 }
289                 catch (java.io.IOException e)
290                 {
291                     buf.reset();
292                     continue;
293                 }
294                 byte[] ba = buf.toByteArray();
295                 for (int j = 0; j < ba.length; j++)
296                 {
297                     out.append('x');
298                     char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16);
299                     // converting to use uppercase letter as part of
300                     // the hex value if ch is a letter.
301                     if (Character.isLetter(ch))
302                     {
303                         ch -= caseDiff;
304                     }
305                     out.append(ch);
306                     ch = Character.forDigit(ba[j] & 0xF, 16);
307                     if (Character.isLetter(ch))
308                     {
309                         ch -= caseDiff;
310                     }
311                     out.append(ch);
312                 }
313                 buf.reset();
314             }
315         }
316 
317         return out.toString();
318     }
319 
320     public static String decode(String s)
321     {
322         StringBuffer sb = new StringBuffer();
323         for (int i=0; i<s.length(); i++)
324         {
325             char c = s.charAt(i);
326             switch (c)
327             {
328                 case '%':
329                     if (((s.charAt(i+1)>='0') && (s.charAt(i+1)<='9')) &&
330                         ((s.charAt(i+2)>='0') && (s.charAt(i+2)<='9')))
331                     {
332                         try
333                         {
334                             sb.append((char)Integer.parseInt(s.substring(i+1, i+3), 16));
335                         }
336                         catch (java.lang.NumberFormatException e)
337                         {
338                             throw new java.lang.IllegalArgumentException();
339                         }
340                         i += 2;
341                         break;
342                     }
343                 default:
344                     sb.append(c);
345                     break;
346             }
347         }
348         // Undo conversion to external encoding
349         String result = sb.toString();
350         try
351         {
352             byte[] inputBytes = result.getBytes("8859_1");
353             result = new String(inputBytes);
354         }
355         catch (java.io.UnsupportedEncodingException e)
356         {
357             // The system should always have 8859_1
358         }
359         return result;
360     }
361 
362     public static String[] copy(String[] source) 
363     {
364         if (source == null)
365             return null;
366         int length = source.length;
367         String[] result = new String[length];
368         System.arraycopy(source, 0, result, 0, length);
369         return result;    
370     }
371 
372     public static Map copyParameters(Map parameters)
373     { 
374         Map result = new HashMap(parameters);
375         for (Iterator iter = result.entrySet().iterator(); iter.hasNext();) {
376             Map.Entry entry = (Map.Entry)iter.next();
377             if (!(entry.getKey() instanceof String)) {
378                 throw new IllegalArgumentException("Parameter map keys must not be null and of type java.lang.String.");
379             }
380             try {
381                 entry.setValue(copy((String[]) entry.getValue()));
382             } catch (ClassCastException ex) {                
383                 throw new IllegalArgumentException("Parameter map values must not be null and of type java.lang.String[].");
384             }
385         }
386         return result;
387     }
388  
389 }