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.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Iterator;
030 import java.util.List;
031
032 /**
033 * @version $Revision: 534560 $
034 */
035 public class ObjectHelper {
036 private static final transient Log log = LogFactory.getLog(ObjectHelper.class);
037
038 /**
039 * A helper method for comparing objects for equality while handling nulls
040 */
041 public static boolean equals(Object a, Object b) {
042 if (a == b) {
043 return true;
044 }
045 return a != null && b != null && a.equals(b);
046 }
047
048 /**
049 * A helper method for performing an ordered comparsion on the objects
050 * handling nulls and objects which do not
051 * handle sorting gracefully
052 */
053 public static int compare(Object a, Object b) {
054 if (a == b) {
055 return 0;
056 }
057 if (a == null) {
058 return -1;
059 }
060 if (b == null) {
061 return 1;
062 }
063 if (a instanceof Comparable) {
064 Comparable comparable = (Comparable) a;
065 return comparable.compareTo(b);
066 }
067 else {
068 int answer = a.getClass().getName().compareTo(b.getClass().getName());
069 if (answer == 0) {
070 answer = a.hashCode() - b.hashCode();
071 }
072 return answer;
073 }
074 }
075
076 public static void notNull(Object value, String name) {
077 if (value == null) {
078 throw new IllegalArgumentException("No " + name + " specified");
079 }
080 }
081
082 public static String[] splitOnCharacter(String value, String needle, int count) {
083 String rc[] = new String[count];
084 rc[0] = value;
085 for (int i = 1; i < count; i++) {
086 String v = rc[i - 1];
087 int p = v.indexOf(needle);
088 if (p < 0) {
089 return rc;
090 }
091 rc[i - 1] = v.substring(0, p);
092 rc[i] = v.substring(p + 1);
093 }
094 return rc;
095 }
096
097 /**
098 * Removes any starting characters on the given text which match the given character
099 *
100 * @param text the string
101 * @param ch the initial characters to remove
102 * @return either the original string or the new substring
103 */
104 public static String removeStartingCharacters(String text, char ch) {
105 int idx = 0;
106 while (text.charAt(idx) == ch) {
107 idx++;
108 }
109 if (idx > 0) {
110 return text.substring(idx);
111 }
112 return text;
113 }
114
115 /**
116 * Returns true if the collection contains the specified value
117 */
118 public static boolean contains(Object collectionOrArray, Object value) {
119 if (collectionOrArray instanceof Collection) {
120 Collection collection = (Collection) collectionOrArray;
121 return collection.contains(value);
122 }
123 else {
124 Iterator iter = ObjectConverter.iterator(value);
125 while (iter.hasNext()) {
126 if (equals(value, iter.next())) {
127 return true;
128 }
129 }
130 return false;
131 }
132 }
133
134 /**
135 * Returns the predicate matching boolean on a {@link List} result set
136 * where if the first element is a boolean its value is used
137 * otherwise this method returns true if the collection is not empty
138 *
139 * @returns true if the first element is a boolean and its value is true or if the list is non empty
140 */
141 public static boolean matches(List list) {
142 if (!list.isEmpty()) {
143 Object value = list.get(0);
144 if (value instanceof Boolean) {
145 Boolean flag = (Boolean) value;
146 return flag.booleanValue();
147 }
148 else {
149 // lets assume non-empty results are true
150 return true;
151 }
152 }
153 return false;
154 }
155
156 public static boolean isNotNullOrBlank(String text) {
157 return text != null && text.trim().length() > 0;
158 }
159
160 /**
161 * A helper method to access a system property, catching any security exceptions
162 *
163 * @param name the name of the system property required
164 * @param defaultValue the default value to use if the property is not available or a security exception prevents access
165 * @return the system property value or the default value if the property is not available or security does not allow its access
166 */
167 public static String getSystemProperty(String name, String defaultValue) {
168 try {
169 return System.getProperty(name, defaultValue);
170 }
171 catch (Exception e) {
172 if (log.isDebugEnabled()) {
173 log.debug("Caught security exception accessing system property: " + name + ". Reason: " + e, e);
174 }
175 return defaultValue;
176 }
177 }
178
179 /**
180 * Returns the type name of the given type or null if the type variable is null
181 */
182 public static String name(Class type) {
183 return type != null ? type.getName() : null;
184 }
185
186 /**
187 * Returns the type name of the given value
188 */
189 public static String className(Object value) {
190 return name(value != null ? value.getClass() : null);
191 }
192
193 /**
194 * Attempts to load the given class name using the thread context class loader
195 * or the class loader used to load this class
196 *
197 * @param name the name of the class to load
198 * @return the class or null if it could not be loaded
199 */
200 public static Class<?> loadClass(String name) {
201 return loadClass(name, ObjectHelper.class.getClassLoader());
202 }
203
204 /**
205 * Attempts to load the given class name using the thread context class loader or the given class loader
206 *
207 * @param name the name of the class to load
208 * @param loader the class loader to use after the thread context class loader
209 * @return the class or null if it could not be loaded
210 */
211 public static Class<?> loadClass(String name, ClassLoader loader) {
212 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
213 if (contextClassLoader != null) {
214 try {
215 return contextClassLoader.loadClass(name);
216 }
217 catch (ClassNotFoundException e) {
218 try {
219 return loader.loadClass(name);
220 }
221 catch (ClassNotFoundException e1) {
222 log.debug("Could not find class: " + name + ". Reason: " + e);
223 }
224 }
225 }
226 return null;
227 }
228
229 /**
230 * A helper method to invoke a method via reflection and wrap any exceptions
231 * as {@link RuntimeCamelException} instances
232 *
233 * @param method the method to invoke
234 * @param instance the object instance (or null for static methods)
235 * @param parameters the parameters to the method
236 * @return the result of the method invocation
237 */
238 public static Object invokeMethod(Method method, Object instance, Object... parameters) {
239 try {
240 return method.invoke(instance, parameters);
241 }
242 catch (IllegalAccessException e) {
243 throw new RuntimeCamelException(e);
244 }
245 catch (InvocationTargetException e) {
246 throw new RuntimeCamelException(e.getCause());
247 }
248 }
249
250 /**
251 * Returns a list of methods which are annotated with the given annotation
252 *
253 * @param type the type to reflect on
254 * @param annotationType the annotation type
255 * @return a list of the methods found
256 */
257 public static List<Method> findMethodsWithAnnotation(Class<?> type, Class<? extends Annotation> annotationType) {
258 List<Method> answer = new ArrayList<Method>();
259 do {
260 Method[] methods = type.getDeclaredMethods();
261 for (Method method : methods) {
262 if (method.getAnnotation(annotationType) != null) {
263 answer.add(method);
264 }
265 }
266 type = type.getSuperclass();
267 }
268 while (type != null);
269 return answer;
270 }
271
272 /**
273 * Turns the given object arrays into a meaningful string
274 *
275 * @param objects an array of objects or null
276 * @return a meaningful string
277 */
278 public static String asString(Object[] objects) {
279 if (objects == null) {
280 return "null";
281 }
282 else {
283 StringBuffer buffer = new StringBuffer("{");
284 int counter = 0;
285 for (Object object : objects) {
286 if (counter++ > 0) {
287 buffer.append(", ");
288 }
289 String text = (object == null) ? "null" : object.toString();
290 buffer.append(text);
291 }
292 buffer.append("}");
293 return buffer.toString();
294 }
295 }
296 }