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 org.apache.camel.RuntimeCamelException; 020 import org.apache.camel.converter.ObjectConverter; 021 import org.apache.commons.logging.Log; 022 import org.apache.commons.logging.LogFactory; 023 024 import java.lang.annotation.Annotation; 025 import java.lang.reflect.InvocationTargetException; 026 import java.lang.reflect.Method; 027 import java.nio.charset.Charset; 028 import java.util.ArrayList; 029 import java.util.Collection; 030 import java.util.Iterator; 031 import java.util.List; 032 033 /** 034 * A number of useful helper methods for working with Objects 035 * 036 * @version $Revision: 564168 $ 037 */ 038 public class ObjectHelper { 039 private static final transient Log LOG = LogFactory.getLog(ObjectHelper.class); 040 041 /** 042 * Utility classes should not have a public constructor. 043 */ 044 private ObjectHelper() { 045 } 046 047 /** 048 * A helper method for comparing objects for equality while handling nulls 049 */ 050 public static boolean equals(Object a, Object b) { 051 if (a == b) { 052 return true; 053 } 054 return a != null && b != null && a.equals(b); 055 } 056 057 /** 058 * Returns true if the given object is equal to any of the expected value 059 * 060 * @param expression 061 * @param s 062 * @param s1 063 * @return 064 */ 065 public static boolean isEqualToAny(Object object, Object... values) { 066 for (Object value : values) { 067 if (equals(object, value)) { 068 return true; 069 } 070 } 071 return false; 072 } 073 074 /** 075 * A helper method for performing an ordered comparsion on the objects 076 * handling nulls and objects which do not handle sorting gracefully 077 */ 078 public static int compare(Object a, Object b) { 079 if (a == b) { 080 return 0; 081 } 082 if (a == null) { 083 return -1; 084 } 085 if (b == null) { 086 return 1; 087 } 088 if (a instanceof Comparable) { 089 Comparable comparable = (Comparable)a; 090 return comparable.compareTo(b); 091 } else { 092 int answer = a.getClass().getName().compareTo(b.getClass().getName()); 093 if (answer == 0) { 094 answer = a.hashCode() - b.hashCode(); 095 } 096 return answer; 097 } 098 } 099 100 public static void notNull(Object value, String name) { 101 if (value == null) { 102 throw new IllegalArgumentException("No " + name + " specified"); 103 } 104 } 105 106 public static String[] splitOnCharacter(String value, String needle, int count) { 107 String rc[] = new String[count]; 108 rc[0] = value; 109 for (int i = 1; i < count; i++) { 110 String v = rc[i - 1]; 111 int p = v.indexOf(needle); 112 if (p < 0) { 113 return rc; 114 } 115 rc[i - 1] = v.substring(0, p); 116 rc[i] = v.substring(p + 1); 117 } 118 return rc; 119 } 120 121 /** 122 * Removes any starting characters on the given text which match the given 123 * character 124 * 125 * @param text the string 126 * @param ch the initial characters to remove 127 * @return either the original string or the new substring 128 */ 129 public static String removeStartingCharacters(String text, char ch) { 130 int idx = 0; 131 while (text.charAt(idx) == ch) { 132 idx++; 133 } 134 if (idx > 0) { 135 return text.substring(idx); 136 } 137 return text; 138 } 139 140 /** 141 * Returns true if the collection contains the specified value 142 */ 143 public static boolean contains(Object collectionOrArray, Object value) { 144 if (collectionOrArray instanceof Collection) { 145 Collection collection = (Collection)collectionOrArray; 146 return collection.contains(value); 147 } else { 148 Iterator iter = ObjectConverter.iterator(value); 149 while (iter.hasNext()) { 150 if (equals(value, iter.next())) { 151 return true; 152 } 153 } 154 return false; 155 } 156 } 157 158 /** 159 * Returns the predicate matching boolean on a {@link List} result set where 160 * if the first element is a boolean its value is used otherwise this method 161 * returns true if the collection is not empty 162 * 163 * @returns true if the first element is a boolean and its value is true or 164 * if the list is non empty 165 */ 166 public static boolean matches(List list) { 167 if (!list.isEmpty()) { 168 Object value = list.get(0); 169 if (value instanceof Boolean) { 170 Boolean flag = (Boolean)value; 171 return flag.booleanValue(); 172 } else { 173 // lets assume non-empty results are true 174 return true; 175 } 176 } 177 return false; 178 } 179 180 public static boolean isNotNullAndNonEmpty(String text) { 181 return text != null && text.trim().length() > 0; 182 } 183 184 public static boolean isNullOrBlank(String text) { 185 return text == null || text.trim().length() <= 0; 186 } 187 188 /** 189 * A helper method to access a system property, catching any security 190 * exceptions 191 * 192 * @param name the name of the system property required 193 * @param defaultValue the default value to use if the property is not 194 * available or a security exception prevents access 195 * @return the system property value or the default value if the property is 196 * not available or security does not allow its access 197 */ 198 public static String getSystemProperty(String name, String defaultValue) { 199 try { 200 return System.getProperty(name, defaultValue); 201 } catch (Exception e) { 202 if (LOG.isDebugEnabled()) { 203 LOG.debug("Caught security exception accessing system property: " + name + ". Reason: " + e, 204 e); 205 } 206 return defaultValue; 207 } 208 } 209 210 /** 211 * Returns the type name of the given type or null if the type variable is 212 * null 213 */ 214 public static String name(Class type) { 215 return type != null ? type.getName() : null; 216 } 217 218 /** 219 * Returns the type name of the given value 220 */ 221 public static String className(Object value) { 222 return name(value != null ? value.getClass() : null); 223 } 224 225 /** 226 * Attempts to load the given class name using the thread context class 227 * loader or the class loader used to load this class 228 * 229 * @param name the name of the class to load 230 * @return the class or null if it could not be loaded 231 */ 232 public static Class<?> loadClass(String name) { 233 return loadClass(name, ObjectHelper.class.getClassLoader()); 234 } 235 236 /** 237 * Attempts to load the given class name using the thread context class 238 * loader or the given class loader 239 * 240 * @param name the name of the class to load 241 * @param loader the class loader to use after the thread context class 242 * loader 243 * @return the class or null if it could not be loaded 244 */ 245 public static Class<?> loadClass(String name, ClassLoader loader) { 246 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 247 if (contextClassLoader != null) { 248 try { 249 return contextClassLoader.loadClass(name); 250 } catch (ClassNotFoundException e) { 251 try { 252 return loader.loadClass(name); 253 } catch (ClassNotFoundException e1) { 254 LOG.debug("Could not find class: " + name + ". Reason: " + e); 255 } 256 } 257 } 258 return null; 259 } 260 261 /** 262 * A helper method to invoke a method via reflection and wrap any exceptions 263 * as {@link RuntimeCamelException} instances 264 * 265 * @param method the method to invoke 266 * @param instance the object instance (or null for static methods) 267 * @param parameters the parameters to the method 268 * @return the result of the method invocation 269 */ 270 public static Object invokeMethod(Method method, Object instance, Object... parameters) { 271 try { 272 return method.invoke(instance, parameters); 273 } catch (IllegalAccessException e) { 274 throw new RuntimeCamelException(e); 275 } catch (InvocationTargetException e) { 276 throw new RuntimeCamelException(e.getCause()); 277 } 278 } 279 280 /** 281 * Returns a list of methods which are annotated with the given annotation 282 * 283 * @param type the type to reflect on 284 * @param annotationType the annotation type 285 * @return a list of the methods found 286 */ 287 public static List<Method> findMethodsWithAnnotation(Class<?> type, 288 Class<? extends Annotation> annotationType) { 289 List<Method> answer = new ArrayList<Method>(); 290 do { 291 Method[] methods = type.getDeclaredMethods(); 292 for (Method method : methods) { 293 if (method.getAnnotation(annotationType) != null) { 294 answer.add(method); 295 } 296 } 297 type = type.getSuperclass(); 298 } while (type != null); 299 return answer; 300 } 301 302 /** 303 * Turns the given object arrays into a meaningful string 304 * 305 * @param objects an array of objects or null 306 * @return a meaningful string 307 */ 308 public static String asString(Object[] objects) { 309 if (objects == null) { 310 return "null"; 311 } else { 312 StringBuffer buffer = new StringBuffer("{"); 313 int counter = 0; 314 for (Object object : objects) { 315 if (counter++ > 0) { 316 buffer.append(", "); 317 } 318 String text = (object == null) ? "null" : object.toString(); 319 buffer.append(text); 320 } 321 buffer.append("}"); 322 return buffer.toString(); 323 } 324 } 325 326 /** 327 * Returns true if a class is assignable from another class like the 328 * {@link Class#isAssignableFrom(Class)} method but which also includes 329 * coercion between primitive types to deal with Java 5 primitive type 330 * wrapping 331 */ 332 public static boolean isAssignableFrom(Class a, Class b) { 333 a = convertPrimitiveTypeToWrapperType(a); 334 b = convertPrimitiveTypeToWrapperType(b); 335 return a.isAssignableFrom(b); 336 } 337 338 /** 339 * Converts primitive types such as int to its wrapper type like 340 * {@link Integer} 341 */ 342 public static Class convertPrimitiveTypeToWrapperType(Class type) { 343 Class rc = type; 344 if (type.isPrimitive()) { 345 if (type == int.class) { 346 rc = Integer.class; 347 } else if (type == long.class) { 348 rc = Long.class; 349 } else if (type == double.class) { 350 rc = Double.class; 351 } else if (type == float.class) { 352 rc = Float.class; 353 } else if (type == short.class) { 354 rc = Short.class; 355 } else if (type == byte.class) { 356 rc = Byte.class; 357 } 358 } 359 return rc; 360 } 361 362 /** 363 * Helper method to return the default character set name 364 */ 365 public static String getDefaultCharacterSet() { 366 return Charset.defaultCharset().name(); 367 } 368 }