/** * This file Copyright (c) 2005-2008 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain other free and open source software ("FOSS") code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.core; import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import java.util.ArrayList; /** * @author Kevin Lindsey */ public class StringUtils { /** * LINE_DELIMITER */ public static final String LINE_DELIMITER = System.getProperty("line.separator", "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ /** * BULLET */ public static final String BULLET = "\u2022 "; //$NON-NLS-1$ /** * EMPTY */ public static final String EMPTY = ""; //$NON-NLS-1$ /** * TAB */ public static final String TAB = "\t"; //$NON-NLS-1$ /** * SPACE */ public static final String SPACE = " "; //$NON-NLS-1$ /** * EMPTY */ public static final String COLON = ":"; //$NON-NLS-1$ /** * Protected constructor for utility class. */ protected StringUtils() { } /** * Create a string by concatenating the elements of a string array using a delimited between each item * * @param delimiter * The text to place between each element in the array * @param items * The array of items to join * @return The resulting string */ public static String join(String delimiter, String[] items) { if (items == null) { return null; } int length = items.length; String result = StringUtils.EMPTY; if (length > 0) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < length - 1; i++) { sb.append(items[i]).append(delimiter); } sb.append(items[length - 1]); result = sb.toString(); } return result; } /** * Strips HTML tags from text * * @param text * Text to strip * @return the text, minus any tags */ public static String stripHTML(String text) { if (text == null) { return null; } String tempText = text.replaceAll("<p>", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ return tempText.replaceAll("\\<.*?\\>", StringUtils.EMPTY); //$NON-NLS-1$ } /** * Returns an empty string in place of a null value * * @param input * @return String * @since 3.0.2 */ public static String replaceNullWithEmpty(String input) { if (input == null) { return StringUtils.EMPTY; } return input; } /** * This method encodes the URL, removes the spaces from the URL and replaces the same with <code>"%20"</code>. * This method is required to fix Bug 77840. * * @param input * @return String * @since 3.0.2 */ public static String urlEncodeForSpaces(String input) { if (input == null) { return null; } return urlEncodeForSpaces(input.toCharArray()); } /** * urlEncodeKeyValuePair * * @param key * @param value * @return */ public static String urlEncodeKeyValuePair(String key, String value) { String result = null; try { result = java.net.URLEncoder.encode(key, "UTF-8") + "=" + java.net.URLEncoder.encode(value, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (UnsupportedEncodingException e) { } return result; } /** * This method encodes the URL, removes the spaces from the URL and replaces the same with <code>"%20"</code>. * This method is required to fix Bug 77840. * * @param input * @return String * @since 3.0.2 */ public static String urlEncodeForSpaces(char[] input) { if (input == null) { return null; } StringBuffer retu = new StringBuffer(input.length); for (int i = 0; i < input.length; i++) { if (input[i] == ' ') { retu.append("%20"); //$NON-NLS-1$ } else { retu.append(input[i]); } } return retu.toString(); } /** * This method encodes the URL, removes the spaces and brackets from the URL and replaces the same with * <code>"%20"</code> and <code>"%5B" and "%5D"</code> and <code>"%7B" "%7D"</code>. * * @param input * @return String * @since 3.0.2 */ public static String urlEncodeFilename(char[] input) { if (input == null) { return null; } StringBuffer retu = new StringBuffer(input.length); for (int i = 0; i < input.length; i++) { if (input[i] == ' ') { retu.append("%20"); //$NON-NLS-1$ } else if (input[i] == '[') { retu.append("%5B"); //$NON-NLS-1$ } else if (input[i] == ']') { retu.append("%5D"); //$NON-NLS-1$ } else if (input[i] == '{') { retu.append("%7B"); //$NON-NLS-1$ } else if (input[i] == '}') { retu.append("%7D"); //$NON-NLS-1$ } else if (input[i] == '`') { retu.append("%60"); //$NON-NLS-1$ } else if (input[i] == '+') { retu.append("%2B"); //$NON-NLS-1$ } else { retu.append(input[i]); } } return retu.toString(); } /** * This method encodes the URL, removes the spaces and brackets from the URL and replaces the same with * <code>"%20"</code> and <code>"%5B" and "%5D"</code> and <code>"%7B" "%7D"</code>. * * @param input * @return String * @since 3.0.2 */ public static String urlDecodeFilename(char[] input) { if (input == null) { return null; } StringBuffer retu = new StringBuffer(input.length); for (int i = 0; i < input.length; i++) { if(input[i] != '%' || i + 2 >= input.length) { retu.append(input[i]); } else { String test = new String(input, i, 3); if (test.equals("%20")) //$NON-NLS-1$ { retu.append(" "); //$NON-NLS-1$ i += 2; } else if (test.equals("%5B")) //$NON-NLS-1$ { retu.append("["); //$NON-NLS-1$ i += 2; } else if (test.equals("%5D")) //$NON-NLS-1$ { retu.append("]"); //$NON-NLS-1$ i += 2; } else if (test.equals("%7B")) //$NON-NLS-1$ { retu.append("{"); //$NON-NLS-1$ i += 2; } else if (test.equals("%7D")) //$NON-NLS-1$ { retu.append("}"); //$NON-NLS-1$ i += 2; } else if (test.equals("%60")) //$NON-NLS-1$ { retu.append("`"); //$NON-NLS-1$ i += 2; } else if (test.equals("%2B")) //$NON-NLS-1$ { retu.append("+"); //$NON-NLS-1$ i += 2; } else { retu.append(input[i]); } } } return retu.toString(); } /** * Removes all carriage returns from a string * * @param text * The string to strip of '\n' * @return The string minus the carriage returns */ public static String stripCarriageReturns(String text) { if (text == null) { return null; } return text.replaceAll("\n", StringUtils.EMPTY); //$NON-NLS-1$ } /** * Removes all extra whitespace (multiple spaces or tabs) from a string * * @param text * The string to strip of '\n' * @return The string minus the whitespace */ public static String stripWhitespace(String text) { if (text == null) { return null; } return text.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Removes the HTML, extra whitespace and carriage returns from a string * * @param text * The text to strip * @return The new text, reformatted */ public static String formatAsPlainText(String text) { String tempText = StringUtils.stripCarriageReturns(text); tempText = StringUtils.stripWhitespace(tempText); tempText = StringUtils.replace(tempText, "</li>", StringUtils.EMPTY); //$NON-NLS-1$ tempText = StringUtils.replace(tempText, "<li>", LINE_DELIMITER + "\t" + BULLET); //$NON-NLS-1$ //$NON-NLS-2$ tempText = StringUtils.replace(tempText, "<p>", LINE_DELIMITER); //$NON-NLS-1$ tempText = StringUtils.stripHTML(tempText); return tempText.trim(); } /** * Removes any leading or trailing " or ' quotes on the string. This is necessary as attribute values show as * strings from the lexer, and need to be surrounded by StringUtils.EMPTY * * @param stringToTrim * The string to trim * @return String */ public static String trimStringQuotes(String stringToTrim) { if (stringToTrim == null) { return null; } String trimmed = stringToTrim.trim(); if (trimmed.startsWith("\"") || trimmed.startsWith("'")) //$NON-NLS-1$ //$NON-NLS-2$ { trimmed = trimmed.substring(1); } if (trimmed.endsWith("\"") || trimmed.endsWith("'")) //$NON-NLS-1$ //$NON-NLS-2$ { trimmed = trimmed.substring(0, trimmed.length() - 1); } return trimmed; } /** * Removes any leading or trailing [] on the string. * * @param stringToTrim * The string to trim * @return String */ public static String trimBrackets(String stringToTrim) { if (stringToTrim == null) { return null; } String trimmed = stringToTrim.trim(); if (trimmed.startsWith("[")) //$NON-NLS-1$ { trimmed = trimmed.substring(1); } if (trimmed.endsWith("]")) //$NON-NLS-1$ { trimmed = trimmed.substring(0, trimmed.length() - 1); } return trimmed; } /** * Trims the start of the string of whitespace. This functions * identically to String.trim(), but works only at the * beginning of a string * @param stringToTrim * @return */ public static String trimStart(String stringToTrim) { if(stringToTrim == null) { return null; } char[] chars = stringToTrim.toCharArray(); int index = 0; int length = chars.length; while(index < length && chars[index] <= ' ') { index++; } if(index > 0) { return stringToTrim.substring(index); } else { return stringToTrim; } } /** * Trims the end of the string of whitespace. This functions * identically to String.trim(), but works only at the * end of a string * @param stringToTrim * @return */ public static String trimEnd(String stringToTrim) { if(stringToTrim == null) { return null; } char[] chars = stringToTrim.toCharArray(); int index = chars.length; while(index > 0 && chars[index - 1] < ' ') { index--; } if(index > 0) { return stringToTrim.substring(0, index); } else { return stringToTrim; } } /** * Replace one string with another * * @param str * @param pattern * @param replace * @return String */ public static String replace(String str, String pattern, String replace) { int s = 0; int e = 0; StringBuffer result = new StringBuffer(); while ((e = str.indexOf(pattern, s)) >= 0) { result.append(str.substring(s, e)); result.append(replace); s = e + pattern.length(); } result.append(str.substring(s)); return result.toString(); } /** * Formats the string with replacement values * * @param str * @param replacement * @return String */ public static String format(String str, long replacement) { return MessageFormat.format(str, new Object[] { Long.toString(replacement) }); } /** * Formats the string with replacement values * * @param str * @param replacement * @return String */ public static String format(String str, int replacement) { return MessageFormat.format(str, new Object[] { Integer.toString(replacement) }); } /** * Formats the string with replacement values * * @param str * @param replacement * @return String */ public static String format(String str, String replacement) { return MessageFormat.format(str, new Object[] { replacement }); } /** * Formats the string with replacement values * * @param str * @param replacement * @return String */ public static String format(String str, Object replacement) { return MessageFormat.format(str, new Object[] { replacement.toString() }); } /** * Formats the string with replacement values * * @param str * @param replacements * @return String */ public static String format(String str, Object[] replacements) { return MessageFormat.format(str, replacements); } /** * Adds an ellipsis to the end of a string, generally indicating that this string leads to another choice (like a * dialog) * * @param message * @return The ellipsif-ied string */ public static String ellipsify(String message) { return message + CoreStrings.ELLIPSIS; } /** * Adds a colon to the end of the string, as if making a form label * * @param message * @return string + colon */ public static String makeFormLabel(String message) { return message + COLON; } /** * Converts a filename extension wildcard string to a regular expression (i.e. *.js into a regular expression matching all .js file names) * @param wildcardExpression the expression to convert * @param caseInsensitive do we make the expression case-insensitive * @return The modified expression */ public static String convertWildcardExpressionToRegex(String wildcardExpression, boolean caseInsensitive) { if(wildcardExpression == null) { return null; } if(wildcardExpression.startsWith("/") && wildcardExpression.endsWith("/")) //$NON-NLS-1$//$NON-NLS-2$ { return wildcardExpression.substring(1, wildcardExpression.length() - 1); } String string = wildcardExpression.replaceAll("\\.(?=[^\\*])", "\\\\."); //$NON-NLS-1$//$NON-NLS-2$ string = string.replaceAll("\\*", ".*"); //$NON-NLS-1$ //$NON-NLS-2$ if(caseInsensitive) { string = "(?i)" + string; //$NON-NLS-1$ } return string; } /** * A string of spaces of a particular length * @param length * * @return The string of spaces, equal to the passed length; */ public static String getSpaces(int length) { String defaultIndent = " "; //$NON-NLS-1$ String indentString = defaultIndent; if (length < indentString.length()) { indentString = defaultIndent.substring(0, length); } return indentString; } /** * Returns a very specialized array. An array of strings spaces of * decreasing length, starting with a string of length "length" * @param length * @return String[] */ public static String[] getArrayOfSpaces(int length) { ArrayList prefixes = new ArrayList(); for(int i = length; i > 0; i--) { prefixes.add(StringUtils.getSpaces(i)); } return (String[])prefixes.toArray(new String[0]); } /** * Find the first non-whitespace character * @param text * @return */ public static String findStartWhitespace(String text) { if(text == null || text.length() == 0) { return text; } String[] s = text.split("\\S"); //$NON-NLS-1$ if(s.length > 0) { return s[0]; } else { return ""; //$NON-NLS-1$ } } /** * Find the last non-whitespace character * @param text * @return */ public static String findEndWhitespace(String text) { if(text == null || text.length() == 0) { return text; } String trimmed = trimEnd(text); int textLength = text.length(); if(trimmed.length() == textLength) { return ""; //$NON-NLS-1$ } else { return text.substring(trimmed.length()); } } /** * Number of new lines in source text * * @param text string * @return - number of lines */ public static int getNumberOfNewlines(String text) { if(text == null) { return 0; } int count = 0; String sourceBit = StringUtils.replace(text, "\r\n", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ sourceBit = StringUtils.replace(sourceBit, "\r", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ char[] split = sourceBit.toCharArray(); for (int i = 0; i < split.length; i++) { char c = split[i]; if (c == '\n') { count++; } } return count; } /** * Compare version strings * @param left * @param right * @return positive if left > right, zero if left == right, negative otherwise */ public static int compareVersions(String left, String right) { int result; String[] lparts = left.split("\\."); //$NON-NLS-1$ String[] rparts = right.split("\\."); //$NON-NLS-1$ for( int i = 0; i < lparts.length && i < rparts.length; ++i) { result = lparts[i].compareToIgnoreCase(rparts[i]); if(result != 0) { return result; } } return (lparts.length - rparts.length); } /** * Replaces security-sensitive information (e.g. password and credit card) with proper text. * * @param object * @return a string that hides security-sensitive information */ public static String getPublishableMessage(Object object) { if (object == null) { return "null"; //$NON-NLS-1$ } String text = object.toString(); text = text.replaceAll("password=.+,", "PASSWORD,"); //$NON-NLS-1$ //$NON-NLS-2$ text = text.replaceAll("password=.+}", "PASSWORD}"); //$NON-NLS-1$ //$NON-NLS-2$ text = text.replaceAll("<password.*>.+</password>", "<password>PASSWORD</password>"); //$NON-NLS-1$ //$NON-NLS-2$ text = text.replaceAll("<app_password.*>.+<.*>", "<app_password>PASSWORD</app_password>"); //$NON-NLS-1$ //$NON-NLS-2$ text = text.replaceAll("number=[0-9]+,", "number=XXXXXXXXXXXXXXXX"); //$NON-NLS-1$ //$NON-NLS-2$ text = text.replaceAll("<number.*>[0-9]+<.*>", "<number>XXXXXXXXXXXXXXXX</number>"); //$NON-NLS-1$ //$NON-NLS-2$ return text; } }