View Javadoc

1   package org.apache.velocity.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.File;
24  import java.io.FileReader;
25  import java.io.PrintWriter;
26  import java.util.ArrayList;
27  import java.util.Hashtable;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.StringTokenizer;
31  
32  
33  /**
34   * This class provides some methods for dynamically
35   * invoking methods in objects, and some string
36   * manipulation methods used by torque. The string
37   * methods will soon be moved into the turbine
38   * string utilities class.
39   *
40   *  @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
41   *  @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
42   *  @version $Id: StringUtils.java 741214 2009-02-05 18:13:47Z nbubna $
43   */
44  public class StringUtils
45  {
46      /**
47       * Line separator for the OS we are operating on.
48       */
49      private static final String EOL = System.getProperty("line.separator");
50  
51      /**
52       * Concatenates a list of objects as a String.
53       *
54       * @param list The list of objects to concatenate.
55       * @return     A text representation of the concatenated objects.
56       */
57      public String concat(List list)
58      {
59          StringBuffer sb = new StringBuffer();
60          int size = list.size();
61  
62          for (int i = 0; i < size; i++)
63          {
64              sb.append(list.get(i).toString());
65          }
66          return sb.toString();
67      }
68  
69      /**
70       * Return a package name as a relative path name
71       *
72       * @param pckge package name to convert to a directory.
73       * @return String directory path.
74       */
75      static public String getPackageAsPath(String pckge)
76      {
77          return pckge.replace( '.', File.separator.charAt(0) ) + File.separator;
78      }
79  
80      /**
81       * <p>
82       *  'Camels Hump' replacement of underscores.
83       * </p>
84       *
85       * <p>
86       * Remove underscores from a string but leave the capitalization of the
87       * other letters unchanged.
88       * </p>
89       *
90       * <p>
91       * For example <code>foo_barBar</code> becomes <code>FooBarBar</code>.
92       * </p>
93       *
94       * @param data string to hump
95       * @return String
96       */
97      static public String removeAndHump (String data)
98      {
99          return removeAndHump(data,"_");
100     }
101 
102     /**
103      * <p>
104      * 'Camels Hump' replacement.
105      * </p>
106      *
107      * <p>
108      * Remove one string from another string but leave the capitalization of the
109      * other letters unchanged.
110      * </p>
111      *
112      * <p>
113      * For example, removing "_" from <code>foo_barBar</code> becomes <code>FooBarBar</code>.
114      * </p>
115      *
116      * @param data string to hump
117      * @param replaceThis string to be replaced
118      * @return String
119      */
120     static public String removeAndHump (String data,String replaceThis)
121     {
122         String temp = null;
123         StringBuffer out = new StringBuffer();
124         temp = data;
125 
126         StringTokenizer st = new StringTokenizer(temp, replaceThis);
127 
128         while (st.hasMoreTokens())
129         {
130             String element = (String) st.nextElement();
131             out.append ( capitalizeFirstLetter(element));
132         }//while
133 
134         return out.toString();
135     }
136 
137     /**
138      * <p>
139      *  Makes the first letter caps and the rest lowercase.
140      * </p>
141      *
142      * <p>
143      *  For example <code>fooBar</code> becomes <code>Foobar</code>.
144      * </p>
145      *
146      * @param data capitalize this
147      * @return String
148      */
149     static public String firstLetterCaps ( String data )
150     {
151         String firstLetter = data.substring(0,1).toUpperCase();
152         String restLetters = data.substring(1).toLowerCase();
153         return firstLetter + restLetters;
154     }
155 
156     /**
157      * <p>
158      * Capitalize the first letter but leave the rest as they are.
159      * </p>
160      *
161      * <p>
162      *  For example <code>fooBar</code> becomes <code>FooBar</code>.
163      * </p>
164      *
165      * @param data capitalize this
166      * @return String
167      */
168     static public String capitalizeFirstLetter ( String data )
169     {
170         String firstLetter = data.substring(0,1).toUpperCase();
171         String restLetters = data.substring(1);
172         return firstLetter + restLetters;
173     }
174 
175     /**
176      * Create a string array from a string separated by delim
177      *
178      * @param line the line to split
179      * @param delim the delimter to split by
180      * @return a string array of the split fields
181      */
182     public static String [] split(String line, String delim)
183     {
184         List list = new ArrayList();
185         StringTokenizer t = new StringTokenizer(line, delim);
186         while (t.hasMoreTokens())
187         {
188             list.add(t.nextToken());
189         }
190         return (String []) list.toArray(new String[list.size()]);
191     }
192 
193     /**
194      * Chop i characters off the end of a string.
195      * This method assumes that any EOL characters in String s
196      * and the platform EOL will be the same.
197      * A 2 character EOL will count as 1 character.
198      *
199      * @param s String to chop.
200      * @param i Number of characters to chop.
201      * @return String with processed answer.
202      */
203     public static String chop(String s, int i)
204     {
205         return chop(s, i, EOL);
206     }
207 
208     /**
209      * Chop i characters off the end of a string.
210      * A 2 character EOL will count as 1 character.
211      *
212      * @param s String to chop.
213      * @param i Number of characters to chop.
214      * @param eol A String representing the EOL (end of line).
215      * @return String with processed answer.
216      */
217     public static String chop(String s, int i, String eol)
218     {
219         if ( i == 0 || s == null || eol == null )
220         {
221            return s;
222         }
223 
224         int length = s.length();
225 
226         /*
227          * if it is a 2 char EOL and the string ends with
228          * it, nip it off.  The EOL in this case is treated like 1 character
229          */
230         if ( eol.length() == 2 && s.endsWith(eol ))
231         {
232             length -= 2;
233             i -= 1;
234         }
235 
236         if ( i > 0)
237         {
238             length -= i;
239         }
240 
241         if ( length < 0)
242         {
243             length = 0;
244         }
245 
246         return s.substring( 0, length);
247     }
248 
249     /**
250      * @param argStr
251      * @param vars
252      * @return Substituted String.
253      */
254     public static StringBuffer stringSubstitution( String argStr,
255                                                    Hashtable vars )
256     {
257         return stringSubstitution( argStr, (Map) vars );
258     }
259 
260     /**
261      * Perform a series of substitutions. The substitions
262      * are performed by replacing $variable in the target
263      * string with the value of provided by the key "variable"
264      * in the provided hashtable.
265      *
266      * @param argStr target string
267      * @param vars name/value pairs used for substitution
268      * @return String target string with replacements.
269      */
270     public static StringBuffer stringSubstitution(String argStr,
271             Map vars)
272     {
273         StringBuffer argBuf = new StringBuffer();
274 
275         for (int cIdx = 0 ; cIdx < argStr.length();)
276         {
277             char ch = argStr.charAt(cIdx);
278 
279             switch (ch)
280             {
281                 case '$':
282                     StringBuffer nameBuf = new StringBuffer();
283                     for (++cIdx ; cIdx < argStr.length(); ++cIdx)
284                     {
285                         ch = argStr.charAt(cIdx);
286                         if (ch == '_' || Character.isLetterOrDigit(ch))
287                             nameBuf.append(ch);
288                         else
289                             break;
290                     }
291 
292                     if (nameBuf.length() > 0)
293                     {
294                         String value =
295                                 (String) vars.get(nameBuf.toString());
296 
297                         if (value != null)
298                         {
299                             argBuf.append(value);
300                         }
301                     }
302                     break;
303 
304                 default:
305                     argBuf.append(ch);
306                     ++cIdx;
307                     break;
308             }
309         }
310 
311         return argBuf;
312     }
313 
314     /**
315      * Read the contents of a file and place them in
316      * a string object.
317      *
318      * @param file path to file.
319      * @return String contents of the file.
320      */
321     public static String fileContentsToString(String file)
322     {
323         String contents = "";
324 
325         File f = null;
326         try
327         {
328             f = new File(file);
329 
330             if (f.exists())
331             {
332                 FileReader fr = null;
333                 try
334                 {
335                     fr = new FileReader(f);
336                     char[] template = new char[(int) f.length()];
337                     fr.read(template);
338                     contents = new String(template);
339                 }
340                 catch (Exception e)
341                 {
342                     e.printStackTrace();
343                 }
344                 finally
345                 {
346                     if (fr != null)
347                     {
348                         fr.close();
349                     }
350                 }
351             }
352         }
353         catch (Exception e)
354         {
355             e.printStackTrace();
356         }
357         return contents;
358     }
359 
360     /**
361      * Remove/collapse multiple newline characters.
362      *
363      * @param argStr string to collapse newlines in.
364      * @return String
365      */
366     public static String collapseNewlines(String argStr)
367     {
368         char last = argStr.charAt(0);
369         StringBuffer argBuf = new StringBuffer();
370 
371         for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++)
372         {
373             char ch = argStr.charAt(cIdx);
374             if (ch != '\n' || last != '\n')
375             {
376                 argBuf.append(ch);
377                 last = ch;
378             }
379         }
380 
381         return argBuf.toString();
382     }
383 
384     /**
385      * Remove/collapse multiple spaces.
386      *
387      * @param argStr string to remove multiple spaces from.
388      * @return String
389      */
390     public static String collapseSpaces(String argStr)
391     {
392         char last = argStr.charAt(0);
393         StringBuffer argBuf = new StringBuffer();
394 
395         for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++)
396         {
397             char ch = argStr.charAt(cIdx);
398             if (ch != ' ' || last != ' ')
399             {
400                 argBuf.append(ch);
401                 last = ch;
402             }
403         }
404 
405         return argBuf.toString();
406     }
407 
408     /**
409       * Replaces all instances of oldString with newString in line.
410       * Taken from the Jive forum package.
411       *
412       * @param line original string.
413       * @param oldString string in line to replace.
414       * @param newString replace oldString with this.
415       * @return String string with replacements.
416       */
417     public static final String sub(String line, String oldString,
418             String newString)
419     {
420         int i = 0;
421         if ((i = line.indexOf(oldString, i)) >= 0)
422         {
423             char [] line2 = line.toCharArray();
424             char [] newString2 = newString.toCharArray();
425             int oLength = oldString.length();
426             StringBuffer buf = new StringBuffer(line2.length);
427             buf.append(line2, 0, i).append(newString2);
428             i += oLength;
429             int j = i;
430             while ((i = line.indexOf(oldString, i)) > 0)
431             {
432                 buf.append(line2, j, i - j).append(newString2);
433                 i += oLength;
434                 j = i;
435             }
436             buf.append(line2, j, line2.length - j);
437             return buf.toString();
438         }
439         return line;
440     }
441 
442     /**
443      * Returns the output of printStackTrace as a String.
444      *
445      * @param e A Throwable.
446      * @return A String.
447      */
448     public static final String stackTrace(Throwable e)
449     {
450         String foo = null;
451         try
452         {
453             // And show the Error Screen.
454             ByteArrayOutputStream ostr = new ByteArrayOutputStream();
455             e.printStackTrace( new PrintWriter(ostr,true) );
456             foo = ostr.toString();
457         }
458         catch (Exception f)
459         {
460             // Do nothing.
461         }
462         return foo;
463     }
464 
465     /**
466      * Return a context-relative path, beginning with a "/", that represents
467      * the canonical version of the specified path after ".." and "." elements
468      * are resolved out.  If the specified path attempts to go outside the
469      * boundaries of the current context (i.e. too many ".." path elements
470      * are present), return <code>null</code> instead.
471      *
472      * @param path Path to be normalized
473      * @return String normalized path
474      */
475     public static final String normalizePath(String path)
476     {
477         // Normalize the slashes and add leading slash if necessary
478         String normalized = path;
479         if (normalized.indexOf('\\') >= 0)
480         {
481             normalized = normalized.replace('\\', '/');
482         }
483 
484         if (!normalized.startsWith("/"))
485         {
486             normalized = "/" + normalized;
487         }
488 
489         // Resolve occurrences of "//" in the normalized path
490         while (true)
491         {
492             int index = normalized.indexOf("//");
493             if (index < 0)
494                 break;
495             normalized = normalized.substring(0, index) +
496             normalized.substring(index + 1);
497         }
498 
499         // Resolve occurrences of "%20" in the normalized path
500         while (true)
501         {
502             int index = normalized.indexOf("%20");
503             if (index < 0)
504                 break;
505             normalized = normalized.substring(0, index) + " " +
506             normalized.substring(index + 3);
507         }
508 
509         // Resolve occurrences of "/./" in the normalized path
510         while (true)
511         {
512             int index = normalized.indexOf("/./");
513             if (index < 0)
514                 break;
515             normalized = normalized.substring(0, index) +
516             normalized.substring(index + 2);
517         }
518 
519         // Resolve occurrences of "/../" in the normalized path
520         while (true)
521         {
522             int index = normalized.indexOf("/../");
523             if (index < 0)
524                 break;
525             if (index == 0)
526                 return (null);  // Trying to go outside our context
527             int index2 = normalized.lastIndexOf('/', index - 1);
528             normalized = normalized.substring(0, index2) +
529             normalized.substring(index + 3);
530         }
531 
532         // Return the normalized path that we have completed
533         return (normalized);
534     }
535 
536     /**
537      * If state is true then return the trueString, else
538      * return the falseString.
539      *
540      * @param state
541      * @param trueString
542      * @param falseString
543      * @return Selected result.
544      */
545     public String select(boolean state, String trueString, String falseString)
546     {
547         if (state)
548         {
549             return trueString;
550         }
551         else
552         {
553             return falseString;
554         }
555     }
556 
557     /**
558      * Check to see if all the string objects passed
559      * in are empty.
560      *
561      * @param list A list of {@link java.lang.String} objects.
562      * @return     Whether all strings are empty.
563      */
564     public boolean allEmpty(List list)
565     {
566         int size = list.size();
567 
568         for (int i = 0; i < size; i++)
569         {
570             if (list.get(i) != null && list.get(i).toString().length() > 0)
571             {
572                 return false;
573             }
574         }
575         return true;
576     }
577 
578     /**
579      * Trim all strings in a List.  Changes the strings in the existing list.
580      * @param list
581      * @return List of trimmed strings.
582      * @since 1.5
583      */
584     public static List trimStrings(List list)
585     {
586         if (list == null)
587             return null;
588 
589         int sz = list.size();
590         for (int i = 0; i < sz; i++)
591             list.set(i,nullTrim((String) list.get(i)));
592         return list;
593     }
594 
595     /**
596      * Trim the string, but pass a null through.
597      * @param s
598      * @return List of trimmed Strings.
599      * @since 1.5
600      */
601     public static String nullTrim(String s)
602     {
603         if (s == null)
604         {
605             return null;
606         }
607         else
608         {
609             return s.trim();
610         }
611     }
612 }