/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2003 - 2007 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package com.funambol.util;
import java.util.Vector;
/**
* Utility class useful when dealing with string objects.
* This class is a collection of static functions, and the usage is:
*
* StringUtil.method()
*
* it is not allowed to create instances of this class
*/
public class StringUtil {
private static final String HT = "\t";
private static final String CRLF = "\r\n";
// This class cannot be instantiated
private StringUtil() { }
/**
* Split the string into an array of strings using one of the separator
* in 'sep'.
*
* @param s the string to tokenize
* @param sep a list of separator to use
*
* @return the array of tokens (an array of size 1 with the original
* string if no separator found)
*/
public static String[] split(String s, String sep) {
// Create the list of separators
String sepArray[] = new String[sep.length()];
for(int i=0;i<sep.length();++i) {
sepArray[i] = new String(""+sep.charAt(i));
}
return split(s, sepArray);
}
/**
* Split the string into an array of strings using one of the separator
* in 'sep'.
*
* @param s the string to tokenize
* @param sep a list of separators (strings, not chars) to use
*
* @return the array of tokens (an array of size 1 with the original
* string if no separator found)
*/
public static String[] split(String s, String[] sepArray) {
// convert a String s to an Array, the elements
// are delimited by sep
Vector tokenIndex = new Vector(10);
Vector tokenSep = new Vector(10);
int len = s.length();
int i;
// Find all characters in string matching one of the separators in 'sep'
for (i = 0; i < sepArray.length; ++i) {
String sep = sepArray[i];
int index = s.indexOf(sep);
while (index >= 0) {
tokenIndex.addElement(new Integer(index));
tokenSep.addElement(sep);
index = s.indexOf(sep, index + sep.length());
}
}
int size = tokenIndex.size();
// tokenIndex is expected to be ordered
for(i=0;i<size;++i) {
int tokenI = ((Integer)tokenIndex.elementAt(i)).intValue();
for(int j=i+1;j<size;++j) {
int tokenJ = ((Integer)tokenIndex.elementAt(j)).intValue();
if (tokenJ < tokenI) {
// Swap
Object temp = tokenIndex.elementAt(i);
tokenIndex.setElementAt(tokenIndex.elementAt(j), i);
tokenIndex.setElementAt(temp, j);
}
}
}
// Finally split
String[] elements = new String[size+1];
// No separators: return the string as the first element
if(size == 0) {
elements[0] = s;
}
else {
// Init indexes
int start = 0;
int end = ((Integer)tokenIndex.elementAt(0)).intValue();
// Get the first token
elements[0] = s.substring(start, end);
String sep;
// Get the mid tokens
for (i=1; i<size; i++) {
// update indexes
sep = (String)tokenSep.elementAt(i-1);
start = ((Integer)tokenIndex.elementAt(i-1)).intValue()+sep.length();
end = ((Integer)tokenIndex.elementAt(i)).intValue();
elements[i] = s.substring(start, end);
}
// Get last token
sep = (String)tokenSep.elementAt(i-1);
start = ((Integer)tokenIndex.elementAt(i-1)).intValue()+sep.length();
elements[i] = (start < s.length()) ? s.substring(start) : "";
}
return elements;
}
/**
* Join the given strings into a single string using sep as separator for
* individual values.
*
* @param list the string array to join
* @param sep the separator to use
*
* @return the joined string
*/
public static String join(String[] list, String sep) {
StringBuffer buffer = new StringBuffer(list[0]);
int len = list.length;
for (int i = 1; i < len; i++) {
buffer.append(sep).append(list[i]);
}
return buffer.toString();
}
/**
* Returns the string array
* @param stringVec the Vecrot of tring to convert
* @return String []
*/
public static String[] getStringArray(Vector stringVec){
if(stringVec==null){
return null;
}
String[] stringArray=new String[stringVec.size()];
for(int i=0;i<stringVec.size();i++){
stringArray[i]=(String) stringVec.elementAt(i);
}
return stringArray;
}
/**
* create a vector filled with the elements of the given array
*
* @param array
* @return a vector with the elements from the given array
*/
public static Vector getVectorFromArray(Object[] array) {
Vector v = new Vector(array.length);
for (int i=0; i<array.length; i++) {
v.addElement(array[i]);
}
return v;
}
/**
* Find two consecutive newlines in a string.
* @param s - The string to search
* @return int: the position of the empty line
*/
public static int findEmptyLine(String s){
int ret = 0;
// Find a newline
while( (ret = s.indexOf("\n", ret)) != -1 ){
// Skip carriage returns, if any
while(s.charAt(ret) == '\r'){
ret++;
}
if(s.charAt(ret) == '\n'){
// Okay, it was empty
ret ++;
break;
}
}
return ret;
}
/**
* Removes unwanted blank characters
* @param content
* @return String
*/
public static String removeBlanks(String content){
return removeChar(content, ' ');
}
/**
* Removes unwanted backslashes characters
*
* @param content The string containing the backslashes to be removed
* @return the content without backslashes
*/
public static String removeBackslashes(String content){
return removeChar(content, '\\');
}
/**
* Removes unwanted characters
*
* @param content The string containing the backslashes to be removed
* @param ch the character to be removed
* @return the content without backslashes
*/
public static String removeChar(String content, char ch){
if (content == null) {
return null;
}
StringBuffer buff = new StringBuffer();
buff.append(content);
int len = buff.length();
for (int i = len - 1; i >= 0; i--) {
if (ch == buff.charAt(i)) {
buff.deleteCharAt(i);
}
}
return buff.toString();
}
/**
* Builds a list of the recipients email addresses each on a different line,
* starting just from the second line with an HT ("\t") separator at the
* head of the line. This is an implementation of the 'folding' concept from
* the RFC 2822 (par. 2.2.3)
*
* @param recipients
* A string containing all recipients comma-separated
* @return A string containing the email list of the recipients spread over
* more lines, ended by CRLF and beginning from the second with the
* WSP defined in the RFC 2822
*/
public static String fold(String recipients) {
String[] list = StringUtil.split(recipients, ",");
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < list.length; i++) {
String address = list[i] + (i != list.length - 1 ? "," : "");
buffer.append(i == 0 ? address + CRLF : HT + address + CRLF);
}
return buffer.toString();
}
/**
* This method is missing in CLDC 1.0 String implementation
*/
public static boolean equalsIgnoreCase(String string1, String string2) {
// Strings are both null, return true
if (string1 == null && string2 == null) {
return true;
}
// One of the two is null, return false
if (string1 == null || string2 == null) {
return false;
}
// Both are not null, compare the lowercase strings
if ((string1.toLowerCase()).equals(string2.toLowerCase())) {
return true;
} else {
return false;
}
}
/**
* Util method for retrieve a boolean primitive type from a String.
* Implemented because Boolean class doesn't provide
* parseBoolean() method.
* Returns true if the input string is equal to "true" (case
* insensitive) false otherwise
*/
public static boolean getBooleanValue(String string) {
if ((string == null) || string.equals("")) {
return false;
} else {
if (StringUtil.equalsIgnoreCase(string, "true")) {
return true;
} else {
return false;
}
}
}
/**
* Removes characters 'c' from the beginning and the end of the string
*/
public static String trim(String s, char c) {
if (s == null) {
return null;
}
if (s.length() == 0) {
return "";
}
int start = 0;
int end = s.length()-1;
while(s.charAt(start) == c) {
if(++start >= end) {
// The string is made by c only
return "";
}
}
while(s.charAt(end) == c) {
if(--end <= start) {
return "";
}
}
return s.substring(start, end+1);
}
/**
* Returns true if the given string is null or empty.
*/
public static boolean isNullOrEmpty(String str) {
if (str==null) {
return true;
}
if (str.trim().equals("")) {
return true;
}
return false;
}
/**
* This method extracts from address the protocol port and resources
* @param url eg. http://127.0.0.1:8080/sync
* @param protocol http
* @return 127.0.0.1
*/
public static String extractAddressFromUrl(String url, String protocol) {
String prefix = protocol + "://";
if (url.startsWith(prefix)) {
url = url.substring(prefix.length(), url.length());
}
// If we have port number in the address we strip everything
// after the port number
int pos = url.indexOf(':');
if (pos >= 0) {
url = url.substring(0, pos);
}
// If we have resource location in the address then we strip
// everything after the '/'
pos = url.indexOf('/');
if (pos >= 0) {
url = url.substring(0, pos);
}
// If we have ? in the address then we strip
// everything after the '?'
pos = url.indexOf('?');
if (pos >= 0) {
url = url.substring(0, pos);
}
return url;
}
/**
* This method extracts from address the resources
* @param url eg. http://127.0.0.1:8080/sync
* @return http://127.0.0.1:8080
*/
public static String extractAddressFromUrl(String url) {
int start = 0;
if(url.startsWith("https://")){
start = 8;
} else if(url.startsWith("http://")){
start = 7;
}
// If we have resource location in the address then we strip
// everything after the '/'
int pos = (url.substring(start)).indexOf('/');
if (pos >= 0) {
url = url.substring(0, pos+start);
}
return url;
}
public static String removePortFromUrl(String url, String protocol) {
String prefix = protocol + "://";
int beginning = 0;
if (url.startsWith(prefix)) {
beginning = protocol.length() + 3;
}
int pos = url.indexOf(':', beginning);
if (pos >= 0) {
int slash = url.indexOf('/', pos);
url = url.substring(0, pos) + url.substring(slash);
}
return url;
}
/**
* This method removes the protocol from a URI
* @param url eg. http://127.0.0.1:8080/sync
* @return 127.0.0.1:8080
*/
public static String removeProtocolFromUrl(String url) {
int idx = url.indexOf("://");
if (idx != -1) {
url = url.substring(idx + 3);
}
return url;
}
/**
* This method retrieves the protocol used in the given url.
*
* @param url eg. http://127.0.0.1:8080/sync
* @return the url protocol (e.g. http). Return null if the protocol is
* not found.
*/
public static String getProtocolFromUrl(String url) {
int protocolEndIndex = url.indexOf("://");
if(protocolEndIndex>0) {
return url.substring(0, protocolEndIndex);
}
return null;
}
/**
* This method check if the protocol used in the given url is valid.
*
* @param url eg. http://127.0.0.1:8080/sync
* @return the url protocol (e.g. http). Return null if the protocol is
* not found.
*/
public static boolean isValidProtocol(String url) {
String protocol = getProtocolFromUrl(url);
if(protocol == null){
return false;
}else if (protocol.equals("http") || protocol.equals("https")){
return true;
}else{
return false;
}
}
/**
* This method check if a string ends with the specified suffix
* ignoring the case.
*
* @param str - string to check
* suffix - the suffix to find
* @return true if the character sequence represented by the argument is a suffix of the
* character sequence represented by this object; false otherwise.
*/
public static boolean endsWithIgnoreCase(String str, String suffix){
return (str.toLowerCase()).endsWith(suffix.toLowerCase());
}
/**
* Replace all characters c1 with c2
* @param s the String to be manipulated
* @param c1 the char to be replaced
* @param c2 the char to put in place of c1
* @return the new string
*/
public static String replaceAll(String s, char c1, char c2) {
StringBuffer sb = new StringBuffer(s);
for (int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i);
if (c == c1) {
sb.setCharAt(i, c2);
}
}
return sb.toString();
}
/**
* Replace any occurrence of one string with another one
* @param s the String to be manipulated
* @param src the string to be replaced
* @param tgt the replacement string
* @return the replaced string (newly allocated). If src is not found the
* method returns a string identical to the original one
*/
public static String replaceAll(String s, String src, String tgt) {
StringBuffer sb = new StringBuffer();
int pos = s.indexOf(src);
int start = 0;
while(pos != -1) {
String portion = s.substring(start, pos);
sb.append(portion);
sb.append(tgt);
if (pos + src.length() < s.length()) {
// Get ready for another round
start = pos + src.length();
pos = s.indexOf(src, pos + src.length());
} else {
pos = -1;
start = s.length();
}
}
// Append the last chunk
if (start < s.length()) {
sb.append(s.substring(start));
}
return sb.toString();
}
public static int lastIndexOf(String s, char ch) {
if (s == null) {
return -1;
}
for(int i=s.length() - 1;i>=0;--i) {
if (s.charAt(i) == ch) {
return i;
}
}
return -1;
}
public static String simplifyFileName(String fileName) {
String parts[] = StringUtil.split(fileName, "/");
Vector res = new Vector();
for(int i=0;i<parts.length;++i) {
String part = parts[i];
if (".".equals(part)) {
// Ignore this
} else if ("..".equals(part)) {
res.removeElementAt(res.size()-1);
} else {
res.addElement(part);
}
}
StringBuffer r = new StringBuffer();
for(int i=0;i<res.size();++i) {
if (i > 0) {
r.append("/");
}
r.append((String)res.elementAt(i));
}
return r.toString();
}
}