001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.util; 018 019 import static org.apache.camel.util.StringQuoteHelper.doubleQuote; 020 021 /** 022 * Helper methods for working with Strings. 023 */ 024 public final class StringHelper { 025 026 /** 027 * Constructor of utility class should be private. 028 */ 029 private StringHelper() { 030 } 031 032 /** 033 * Ensures that <code>s</code> is friendly for a URL or file system. 034 * 035 * @param s String to be sanitized. 036 * @return sanitized version of <code>s</code>. 037 * @throws NullPointerException if <code>s</code> is <code>null</code>. 038 */ 039 public static String sanitize(String s) { 040 return s 041 .replace(':', '-') 042 .replace('_', '-') 043 .replace('.', '-') 044 .replace('/', '-') 045 .replace('\\', '-'); 046 } 047 048 /** 049 * Counts the number of times the given char is in the string 050 * 051 * @param s the string 052 * @param ch the char 053 * @return number of times char is located in the string 054 */ 055 public static int countChar(String s, char ch) { 056 if (ObjectHelper.isEmpty(s)) { 057 return 0; 058 } 059 060 int matches = 0; 061 for (int i = 0; i < s.length(); i++) { 062 char c = s.charAt(i); 063 if (ch == c) { 064 matches++; 065 } 066 } 067 068 return matches; 069 } 070 071 public static String removeQuotes(String s) { 072 if (ObjectHelper.isEmpty(s)) { 073 return s; 074 } 075 076 s = s.replaceAll("'", ""); 077 s = s.replaceAll("\"", ""); 078 return s; 079 } 080 081 public static String removeLeadingAndEndingQuotes(String s) { 082 if (ObjectHelper.isEmpty(s)) { 083 return s; 084 } 085 086 String copy = s.trim(); 087 if (copy.startsWith("'") && copy.endsWith("'")) { 088 return copy.substring(1, copy.length() - 1); 089 } 090 if (copy.startsWith("\"") && copy.endsWith("\"")) { 091 return copy.substring(1, copy.length() - 1); 092 } 093 094 // no quotes, so return as-is 095 return s; 096 } 097 098 public static boolean isQuoted(String s) { 099 if (ObjectHelper.isEmpty(s)) { 100 return false; 101 } 102 103 if (s.startsWith("'") && s.endsWith("'")) { 104 return true; 105 } 106 if (s.startsWith("\"") && s.endsWith("\"")) { 107 return true; 108 } 109 110 return false; 111 } 112 113 /** 114 * Encodes the text into safe XML by replacing < > and & with XML tokens 115 * 116 * @param text the text 117 * @return the encoded text 118 */ 119 public static String xmlEncode(String text) { 120 if (text == null) { 121 return ""; 122 } 123 // must replace amp first, so we dont replace < to amp later 124 return text.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">"); 125 } 126 127 /** 128 * Determines if the string has at least one letter in upper case 129 * @param text the text 130 * @return <tt>true</tt> if at least one letter is upper case, <tt>false</tt> otherwise 131 */ 132 public static boolean hasUpperCase(String text) { 133 if (text == null) { 134 return false; 135 } 136 137 for (int i = 0; i < text.length(); i++) { 138 char ch = text.charAt(i); 139 if (Character.isUpperCase(ch)) { 140 return true; 141 } 142 } 143 144 return false; 145 } 146 147 /** 148 * Does the expression have the language start token? 149 * 150 * @param expression the expression 151 * @param language the name of the language, such as simple 152 * @return <tt>true</tt> if the expression contains the start token, <tt>false</tt> otherwise 153 */ 154 public static boolean hasStartToken(String expression, String language) { 155 if (expression == null) { 156 return false; 157 } 158 159 // for the simple language the expression start token could be "${" 160 if ("simple".equalsIgnoreCase(language) && expression.indexOf("${") >= 0) { 161 return true; 162 } 163 164 if (language != null && expression.indexOf("$" + language + "{") >= 0) { 165 return true; 166 } 167 168 return false; 169 } 170 171 /** 172 * Replaces all the from tokens in the given input string. 173 * <p/> 174 * This implementation is not recursive, not does it check for tokens in the replacement string. 175 * 176 * @param input the input string 177 * @param from the from string, must <b>not</b> be <tt>null</tt> or empty 178 * @param to the replacement string, must <b>not</b> be empty 179 * @return the replaced string, or the input string if no replacement was needed 180 * @throws IllegalArgumentException if the input arguments is invalid 181 */ 182 public static String replaceAll(String input, String from, String to) { 183 if (ObjectHelper.isEmpty(input)) { 184 return input; 185 } 186 if (from == null) { 187 throw new IllegalArgumentException("from cannot be null"); 188 } 189 if (to == null) { 190 // to can be empty, so only check for null 191 throw new IllegalArgumentException("to cannot be null"); 192 } 193 194 // fast check if there is any from at all 195 if (!input.contains(from)) { 196 return input; 197 } 198 199 final int len = from.length(); 200 final int max = input.length(); 201 StringBuilder sb = new StringBuilder(max); 202 for (int i = 0; i < max;) { 203 if (i + len <= max) { 204 String token = input.substring(i, i + len); 205 if (from.equals(token)) { 206 sb.append(to); 207 // fast forward 208 i = i + len; 209 continue; 210 } 211 } 212 213 // append single char 214 sb.append(input.charAt(i)); 215 // forward to next 216 i++; 217 } 218 return sb.toString(); 219 } 220 221 /** 222 * Creates a json tuple with the given name/value pair. 223 * 224 * @param name the name 225 * @param value the value 226 * @param isMap whether the tuple should be map 227 * @return the json 228 */ 229 public static String toJson(String name, String value, boolean isMap) { 230 if (isMap) { 231 return "{ " + doubleQuote(name) + ": " + doubleQuote(value) + " }"; 232 } else { 233 return doubleQuote(name) + ": " + doubleQuote(value); 234 } 235 } 236 237 }