| package org.apache.velocity.util; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| |
| /** |
| * This class provides some methods for dynamically |
| * invoking methods in objects, and some string |
| * manipulation methods used by torque. The string |
| * methods will soon be moved into the turbine |
| * string utilities class. |
| * |
| * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> |
| * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> |
| * @version $Id$ |
| */ |
| public class StringUtils |
| { |
| /** |
| * Line separator for the OS we are operating on. |
| */ |
| private static final String EOL = System.getProperty("line.separator"); |
| |
| /** |
| * Concatenates a list of objects as a String. |
| * |
| * @param list The list of objects to concatenate. |
| * @return A text representation of the concatenated objects. |
| */ |
| public String concat(List list) |
| { |
| StringBuffer sb = new StringBuffer(); |
| int size = list.size(); |
| |
| for (int i = 0; i < size; i++) |
| { |
| sb.append(list.get(i).toString()); |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Return a package name as a relative path name |
| * |
| * @param pckge package name to convert to a directory. |
| * @return String directory path. |
| */ |
| static public String getPackageAsPath(String pckge) |
| { |
| return pckge.replace( '.', File.separator.charAt(0) ) + File.separator; |
| } |
| |
| /** |
| * <p> |
| * Remove underscores from a string and replaces first |
| * letters with capitals. Other letters are changed to lower case. |
| * </p> |
| * |
| * <p> |
| * For example <code>foo_bar</code> becomes <code>FooBar</code> |
| * but <code>foo_barBar</code> becomes <code>FooBarbar</code>. |
| * </p> |
| * |
| * @param data string to remove underscores from. |
| * @return String |
| * @deprecated Use the org.apache.commons.util.StringUtils class |
| * instead. Using its firstLetterCaps() method in conjunction |
| * with a StringTokenizer will achieve the same result. |
| */ |
| static public String removeUnderScores (String data) |
| { |
| String temp = null; |
| StringBuffer out = new StringBuffer(); |
| temp = data; |
| |
| StringTokenizer st = new StringTokenizer(temp, "_"); |
| |
| while (st.hasMoreTokens()) |
| { |
| String element = (String) st.nextElement(); |
| out.append ( firstLetterCaps(element)); |
| } |
| |
| return out.toString(); |
| } |
| |
| /** |
| * <p> |
| * 'Camels Hump' replacement of underscores. |
| * </p> |
| * |
| * <p> |
| * Remove underscores from a string but leave the capitalization of the |
| * other letters unchanged. |
| * </p> |
| * |
| * <p> |
| * For example <code>foo_barBar</code> becomes <code>FooBarBar</code>. |
| * </p> |
| * |
| * @param data string to hump |
| * @return String |
| */ |
| static public String removeAndHump (String data) |
| { |
| return removeAndHump(data,"_"); |
| } |
| |
| /** |
| * <p> |
| * 'Camels Hump' replacement. |
| * </p> |
| * |
| * <p> |
| * Remove one string from another string but leave the capitalization of the |
| * other letters unchanged. |
| * </p> |
| * |
| * <p> |
| * For example, removing "_" from <code>foo_barBar</code> becomes <code>FooBarBar</code>. |
| * </p> |
| * |
| * @param data string to hump |
| * @param replaceThis string to be replaced |
| * @return String |
| */ |
| static public String removeAndHump (String data,String replaceThis) |
| { |
| String temp = null; |
| StringBuffer out = new StringBuffer(); |
| temp = data; |
| |
| StringTokenizer st = new StringTokenizer(temp, replaceThis); |
| |
| while (st.hasMoreTokens()) |
| { |
| String element = (String) st.nextElement(); |
| out.append ( capitalizeFirstLetter(element)); |
| }//while |
| |
| return out.toString(); |
| } |
| |
| /** |
| * <p> |
| * Makes the first letter caps and the rest lowercase. |
| * </p> |
| * |
| * <p> |
| * For example <code>fooBar</code> becomes <code>Foobar</code>. |
| * </p> |
| * |
| * @param data capitalize this |
| * @return String |
| */ |
| static public String firstLetterCaps ( String data ) |
| { |
| String firstLetter = data.substring(0,1).toUpperCase(); |
| String restLetters = data.substring(1).toLowerCase(); |
| return firstLetter + restLetters; |
| } |
| |
| /** |
| * <p> |
| * Capitalize the first letter but leave the rest as they are. |
| * </p> |
| * |
| * <p> |
| * For example <code>fooBar</code> becomes <code>FooBar</code>. |
| * </p> |
| * |
| * @param data capitalize this |
| * @return String |
| */ |
| static public String capitalizeFirstLetter ( String data ) |
| { |
| String firstLetter = data.substring(0,1).toUpperCase(); |
| String restLetters = data.substring(1); |
| return firstLetter + restLetters; |
| } |
| |
| /** |
| * Create a string array from a string separated by delim |
| * |
| * @param line the line to split |
| * @param delim the delimter to split by |
| * @return a string array of the split fields |
| */ |
| public static String [] split(String line, String delim) |
| { |
| List list = new ArrayList(); |
| StringTokenizer t = new StringTokenizer(line, delim); |
| while (t.hasMoreTokens()) |
| { |
| list.add(t.nextToken()); |
| } |
| return (String []) list.toArray(new String[list.size()]); |
| } |
| |
| /** |
| * Chop i characters off the end of a string. |
| * This method assumes that any EOL characters in String s |
| * and the platform EOL will be the same. |
| * A 2 character EOL will count as 1 character. |
| * |
| * @param s String to chop. |
| * @param i Number of characters to chop. |
| * @return String with processed answer. |
| */ |
| public static String chop(String s, int i) |
| { |
| return chop(s, i, EOL); |
| } |
| |
| /** |
| * Chop i characters off the end of a string. |
| * A 2 character EOL will count as 1 character. |
| * |
| * @param s String to chop. |
| * @param i Number of characters to chop. |
| * @param eol A String representing the EOL (end of line). |
| * @return String with processed answer. |
| */ |
| public static String chop(String s, int i, String eol) |
| { |
| if ( i == 0 || s == null || eol == null ) |
| { |
| return s; |
| } |
| |
| int length = s.length(); |
| |
| /* |
| * if it is a 2 char EOL and the string ends with |
| * it, nip it off. The EOL in this case is treated like 1 character |
| */ |
| if ( eol.length() == 2 && s.endsWith(eol )) |
| { |
| length -= 2; |
| i -= 1; |
| } |
| |
| if ( i > 0) |
| { |
| length -= i; |
| } |
| |
| if ( length < 0) |
| { |
| length = 0; |
| } |
| |
| return s.substring( 0, length); |
| } |
| |
| /** |
| * @param argStr |
| * @param vars |
| * @return Substituted String. |
| */ |
| public static StringBuffer stringSubstitution( String argStr, |
| Hashtable vars ) |
| { |
| return stringSubstitution( argStr, (Map) vars ); |
| } |
| |
| /** |
| * Perform a series of substitutions. The substitions |
| * are performed by replacing $variable in the target |
| * string with the value of provided by the key "variable" |
| * in the provided hashtable. |
| * |
| * @param argStr target string |
| * @param vars name/value pairs used for substitution |
| * @return String target string with replacements. |
| */ |
| public static StringBuffer stringSubstitution(String argStr, |
| Map vars) |
| { |
| StringBuffer argBuf = new StringBuffer(); |
| |
| for (int cIdx = 0 ; cIdx < argStr.length();) |
| { |
| char ch = argStr.charAt(cIdx); |
| |
| switch (ch) |
| { |
| case '$': |
| StringBuffer nameBuf = new StringBuffer(); |
| for (++cIdx ; cIdx < argStr.length(); ++cIdx) |
| { |
| ch = argStr.charAt(cIdx); |
| if (ch == '_' || Character.isLetterOrDigit(ch)) |
| nameBuf.append(ch); |
| else |
| break; |
| } |
| |
| if (nameBuf.length() > 0) |
| { |
| String value = |
| (String) vars.get(nameBuf.toString()); |
| |
| if (value != null) |
| { |
| argBuf.append(value); |
| } |
| } |
| break; |
| |
| default: |
| argBuf.append(ch); |
| ++cIdx; |
| break; |
| } |
| } |
| |
| return argBuf; |
| } |
| |
| /** |
| * Read the contents of a file and place them in |
| * a string object. |
| * |
| * @param file path to file. |
| * @return String contents of the file. |
| */ |
| public static String fileContentsToString(String file) |
| { |
| String contents = ""; |
| |
| File f = null; |
| try |
| { |
| f = new File(file); |
| |
| if (f.exists()) |
| { |
| FileReader fr = null; |
| try |
| { |
| fr = new FileReader(f); |
| char[] template = new char[(int) f.length()]; |
| fr.read(template); |
| contents = new String(template); |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| finally |
| { |
| if (fr != null) |
| { |
| fr.close(); |
| } |
| } |
| } |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| return contents; |
| } |
| |
| /** |
| * Remove/collapse multiple newline characters. |
| * |
| * @param argStr string to collapse newlines in. |
| * @return String |
| */ |
| public static String collapseNewlines(String argStr) |
| { |
| char last = argStr.charAt(0); |
| StringBuffer argBuf = new StringBuffer(); |
| |
| for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++) |
| { |
| char ch = argStr.charAt(cIdx); |
| if (ch != '\n' || last != '\n') |
| { |
| argBuf.append(ch); |
| last = ch; |
| } |
| } |
| |
| return argBuf.toString(); |
| } |
| |
| /** |
| * Remove/collapse multiple spaces. |
| * |
| * @param argStr string to remove multiple spaces from. |
| * @return String |
| */ |
| public static String collapseSpaces(String argStr) |
| { |
| char last = argStr.charAt(0); |
| StringBuffer argBuf = new StringBuffer(); |
| |
| for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++) |
| { |
| char ch = argStr.charAt(cIdx); |
| if (ch != ' ' || last != ' ') |
| { |
| argBuf.append(ch); |
| last = ch; |
| } |
| } |
| |
| return argBuf.toString(); |
| } |
| |
| /** |
| * Replaces all instances of oldString with newString in line. |
| * Taken from the Jive forum package. |
| * |
| * @param line original string. |
| * @param oldString string in line to replace. |
| * @param newString replace oldString with this. |
| * @return String string with replacements. |
| */ |
| public static final String sub(String line, String oldString, |
| String newString) |
| { |
| int i = 0; |
| if ((i = line.indexOf(oldString, i)) >= 0) |
| { |
| char [] line2 = line.toCharArray(); |
| char [] newString2 = newString.toCharArray(); |
| int oLength = oldString.length(); |
| StringBuffer buf = new StringBuffer(line2.length); |
| buf.append(line2, 0, i).append(newString2); |
| i += oLength; |
| int j = i; |
| while ((i = line.indexOf(oldString, i)) > 0) |
| { |
| buf.append(line2, j, i - j).append(newString2); |
| i += oLength; |
| j = i; |
| } |
| buf.append(line2, j, line2.length - j); |
| return buf.toString(); |
| } |
| return line; |
| } |
| |
| /** |
| * Returns the output of printStackTrace as a String. |
| * |
| * @param e A Throwable. |
| * @return A String. |
| */ |
| public static final String stackTrace(Throwable e) |
| { |
| String foo = null; |
| try |
| { |
| // And show the Error Screen. |
| ByteArrayOutputStream ostr = new ByteArrayOutputStream(); |
| e.printStackTrace( new PrintWriter(ostr,true) ); |
| foo = ostr.toString(); |
| } |
| catch (Exception f) |
| { |
| // Do nothing. |
| } |
| return foo; |
| } |
| |
| /** |
| * Return a context-relative path, beginning with a "/", that represents |
| * the canonical version of the specified path after ".." and "." elements |
| * are resolved out. If the specified path attempts to go outside the |
| * boundaries of the current context (i.e. too many ".." path elements |
| * are present), return <code>null</code> instead. |
| * |
| * @param path Path to be normalized |
| * @return String normalized path |
| */ |
| public static final String normalizePath(String path) |
| { |
| // Normalize the slashes and add leading slash if necessary |
| String normalized = path; |
| if (normalized.indexOf('\\') >= 0) |
| { |
| normalized = normalized.replace('\\', '/'); |
| } |
| |
| if (!normalized.startsWith("/")) |
| { |
| normalized = "/" + normalized; |
| } |
| |
| // Resolve occurrences of "//" in the normalized path |
| while (true) |
| { |
| int index = normalized.indexOf("//"); |
| if (index < 0) |
| break; |
| normalized = normalized.substring(0, index) + |
| normalized.substring(index + 1); |
| } |
| |
| // Resolve occurrences of "%20" in the normalized path |
| while (true) |
| { |
| int index = normalized.indexOf("%20"); |
| if (index < 0) |
| break; |
| normalized = normalized.substring(0, index) + " " + |
| normalized.substring(index + 3); |
| } |
| |
| // Resolve occurrences of "/./" in the normalized path |
| while (true) |
| { |
| int index = normalized.indexOf("/./"); |
| if (index < 0) |
| break; |
| normalized = normalized.substring(0, index) + |
| normalized.substring(index + 2); |
| } |
| |
| // Resolve occurrences of "/../" in the normalized path |
| while (true) |
| { |
| int index = normalized.indexOf("/../"); |
| if (index < 0) |
| break; |
| if (index == 0) |
| return (null); // Trying to go outside our context |
| int index2 = normalized.lastIndexOf('/', index - 1); |
| normalized = normalized.substring(0, index2) + |
| normalized.substring(index + 3); |
| } |
| |
| // Return the normalized path that we have completed |
| return (normalized); |
| } |
| |
| /** |
| * If state is true then return the trueString, else |
| * return the falseString. |
| * |
| * @param state |
| * @param trueString |
| * @param falseString |
| * @return Selected result. |
| */ |
| public String select(boolean state, String trueString, String falseString) |
| { |
| if (state) |
| { |
| return trueString; |
| } |
| else |
| { |
| return falseString; |
| } |
| } |
| |
| /** |
| * Check to see if all the string objects passed |
| * in are empty. |
| * |
| * @param list A list of {@link java.lang.String} objects. |
| * @return Whether all strings are empty. |
| */ |
| public boolean allEmpty(List list) |
| { |
| int size = list.size(); |
| |
| for (int i = 0; i < size; i++) |
| { |
| if (list.get(i) != null && list.get(i).toString().length() > 0) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Trim all strings in a List. Changes the strings in the existing list. |
| * @param list |
| * @return List of trimmed strings. |
| * @since 1.5 |
| */ |
| public static List trimStrings(List list) |
| { |
| if (list == null) |
| return null; |
| |
| int sz = list.size(); |
| for (int i = 0; i < sz; i++) |
| list.set(i,nullTrim((String) list.get(i))); |
| return list; |
| } |
| |
| /** |
| * Trim the string, but pass a null through. |
| * @param s |
| * @return List of trimmed Strings. |
| * @since 1.5 |
| */ |
| public static String nullTrim(String s) |
| { |
| if (s == null) |
| { |
| return null; |
| } |
| else |
| { |
| return s.trim(); |
| } |
| } |
| } |