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 java.io.Closeable;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.lang.annotation.Annotation;
023 import java.lang.reflect.AnnotatedElement;
024 import java.lang.reflect.InvocationTargetException;
025 import java.lang.reflect.Method;
026 import java.nio.charset.Charset;
027 import java.util.ArrayList;
028 import java.util.Arrays;
029 import java.util.Collection;
030 import java.util.Collections;
031 import java.util.Iterator;
032 import java.util.List;
033 import java.util.Scanner;
034
035 import org.w3c.dom.Node;
036 import org.w3c.dom.NodeList;
037
038 import org.apache.camel.RuntimeCamelException;
039 import org.apache.commons.logging.Log;
040 import org.apache.commons.logging.LogFactory;
041
042 /**
043 * A number of useful helper methods for working with Objects
044 *
045 * @version $Revision: 752464 $
046 */
047 public final class ObjectHelper {
048 private static final transient Log LOG = LogFactory.getLog(ObjectHelper.class);
049
050 /**
051 * Utility classes should not have a public constructor.
052 */
053 private ObjectHelper() {
054 }
055
056 /**
057 * A helper method for comparing objects for equality while handling nulls
058 */
059 public static boolean equal(Object a, Object b) {
060 if (a == b) {
061 return true;
062 }
063
064 if (a instanceof byte[] && b instanceof byte[]) {
065 return equalByteArray((byte[])a, (byte[])b);
066 }
067
068 return a != null && b != null && a.equals(b);
069 }
070
071 /**
072 * A helper method for comparing byte arrays for equality while handling
073 * nulls
074 */
075 public static boolean equalByteArray(byte[] a, byte[] b) {
076 if (a == b) {
077 return true;
078 }
079
080 // loop and compare each byte
081 if (a != null && b != null && a.length == b.length) {
082 for (int i = 0; i < a.length; i++) {
083 if (a[i] != b[i]) {
084 return false;
085 }
086 }
087 // all bytes are equal
088 return true;
089 }
090
091 return false;
092 }
093
094 /**
095 * Returns true if the given object is equal to any of the expected value
096 */
097 public static boolean isEqualToAny(Object object, Object... values) {
098 for (Object value : values) {
099 if (equal(object, value)) {
100 return true;
101 }
102 }
103 return false;
104 }
105
106 /**
107 * A helper method for performing an ordered comparison on the objects
108 * handling nulls and objects which do not handle sorting gracefully
109 */
110 public static int compare(Object a, Object b) {
111 return compare(a, b, false);
112 }
113
114 /**
115 * A helper method for performing an ordered comparison on the objects
116 * handling nulls and objects which do not handle sorting gracefully
117 *
118 * @param a the first object
119 * @param b the second object
120 * @param ignoreCase ignore case for string comparison
121 */
122 @SuppressWarnings("unchecked")
123 public static int compare(Object a, Object b, boolean ignoreCase) {
124 if (a == b) {
125 return 0;
126 }
127 if (a == null) {
128 return -1;
129 }
130 if (b == null) {
131 return 1;
132 }
133 if (ignoreCase && a instanceof String && b instanceof String) {
134 return ((String) a).compareToIgnoreCase((String) b);
135 }
136 if (a instanceof Comparable) {
137 Comparable comparable = (Comparable)a;
138 return comparable.compareTo(b);
139 } else {
140 int answer = a.getClass().getName().compareTo(b.getClass().getName());
141 if (answer == 0) {
142 answer = a.hashCode() - b.hashCode();
143 }
144 return answer;
145 }
146 }
147
148 public static Boolean toBoolean(Object value) {
149 if (value instanceof Boolean) {
150 return (Boolean)value;
151 }
152 if (value instanceof String) {
153 return "true".equalsIgnoreCase(value.toString()) ? Boolean.TRUE : Boolean.FALSE;
154 }
155 if (value instanceof Integer) {
156 return (Integer)value > 0 ? Boolean.TRUE : Boolean.FALSE;
157 }
158 return null;
159 }
160
161 /**
162 * Asserts whether the value is <b>not</b> <tt>null</tt>
163 *
164 * @param value the value to test
165 * @param name the key that resolved the value
166 * @throws IllegalArgumentException is thrown if assertion fails
167 */
168 public static void notNull(Object value, String name) {
169 if (value == null) {
170 throw new IllegalArgumentException(name + " must be specified");
171 }
172 }
173
174 /**
175 * Asserts whether the value is <b>not</b> <tt>null</tt>
176 *
177 * @param value the value to test
178 * @param on additional description to indicate where this problem occured (appended as toString())
179 * @param name the key that resolved the value
180 * @throws IllegalArgumentException is thrown if assertion fails
181 */
182 public static void notNull(Object value, String name, Object on) {
183 if (on == null) {
184 notNull(value, name);
185 } else if (value == null) {
186 throw new IllegalArgumentException(name + " must be specified on: " + on);
187 }
188 }
189
190 /**
191 * Asserts whether the string is <b>not</b> empty.
192 *
193 * @param value the string to test
194 * @param name the key that resolved the value
195 * @throws IllegalArgumentException is thrown if assertion fails
196 */
197 public static void notEmpty(String value, String name) {
198 if (isEmpty(value)) {
199 throw new IllegalArgumentException(name + " must be specified and not empty");
200 }
201 }
202
203 /**
204 * Asserts whether the string is <b>not</b> empty.
205 *
206 * @param value the string to test
207 * @param on additional description to indicate where this problem occured (appended as toString())
208 * @param name the key that resolved the value
209 * @throws IllegalArgumentException is thrown if assertion fails
210 */
211 public static void notEmpty(String value, String name, Object on) {
212 if (on == null) {
213 notNull(value, name);
214 } else if (isEmpty(value)) {
215 throw new IllegalArgumentException(name + " must be specified and not empty on: " + on);
216 }
217 }
218
219 /**
220 * Tests whether the value is <tt>null</tt> or an empty string.
221 *
222 * @param value the value, if its a String it will be tested for text length as well
223 * @return true if empty
224 */
225 public static boolean isEmpty(Object value) {
226 return !isNotEmpty(value);
227 }
228
229 /**
230 * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
231 *
232 * @param value the value, if its a String it will be tested for text length as well
233 * @return true if <b>not</b> empty
234 */
235 public static boolean isNotEmpty(Object value) {
236 if (value == null) {
237 return false;
238 } else if (value instanceof String) {
239 String text = (String) value;
240 return text.trim().length() > 0;
241 } else {
242 return true;
243 }
244 }
245
246 public static String[] splitOnCharacter(String value, String needle, int count) {
247 String rc[] = new String[count];
248 rc[0] = value;
249 for (int i = 1; i < count; i++) {
250 String v = rc[i - 1];
251 int p = v.indexOf(needle);
252 if (p < 0) {
253 return rc;
254 }
255 rc[i - 1] = v.substring(0, p);
256 rc[i] = v.substring(p + 1);
257 }
258 return rc;
259 }
260
261 /**
262 * Removes any starting characters on the given text which match the given
263 * character
264 *
265 * @param text the string
266 * @param ch the initial characters to remove
267 * @return either the original string or the new substring
268 */
269 public static String removeStartingCharacters(String text, char ch) {
270 int idx = 0;
271 while (text.charAt(idx) == ch) {
272 idx++;
273 }
274 if (idx > 0) {
275 return text.substring(idx);
276 }
277 return text;
278 }
279
280 public static String capitalize(String text) {
281 if (text == null) {
282 return null;
283 }
284 int length = text.length();
285 if (length == 0) {
286 return text;
287 }
288 String answer = text.substring(0, 1).toUpperCase();
289 if (length > 1) {
290 answer += text.substring(1, length);
291 }
292 return answer;
293 }
294
295 public static String after(String text, String after) {
296 if (!text.contains(after)) {
297 return null;
298 }
299 return text.substring(text.indexOf(after) + after.length());
300 }
301
302 public static String before(String text, String before) {
303 if (!text.contains(before)) {
304 return null;
305 }
306 return text.substring(0, text.indexOf(before));
307 }
308
309 public static String between(String text, String after, String before) {
310 text = after(text, after);
311 if (text == null) {
312 return null;
313 }
314 return before(text, before);
315 }
316
317 /**
318 * Returns true if the collection contains the specified value
319 */
320 @SuppressWarnings("unchecked")
321 public static boolean contains(Object collectionOrArray, Object value) {
322 if (collectionOrArray instanceof Collection) {
323 Collection collection = (Collection)collectionOrArray;
324 return collection.contains(value);
325 } else if (collectionOrArray instanceof String && value instanceof String) {
326 String str = (String)collectionOrArray;
327 String subStr = (String)value;
328 return str.contains(subStr);
329 } else {
330 Iterator iter = createIterator(collectionOrArray);
331 while (iter.hasNext()) {
332 if (equal(value, iter.next())) {
333 return true;
334 }
335 }
336 }
337 return false;
338 }
339
340 /**
341 * Creates an iterator over the value if the value is a collection, an
342 * Object[] or a primitive type array; otherwise to simplify the caller's
343 * code, we just create a singleton collection iterator over a single value
344 * <p/>
345 * Will default use comma for String separating String values.
346 *
347 * @param value the value
348 * @return the iterator
349 */
350 public static Iterator createIterator(Object value) {
351 return createIterator(value, ",");
352 }
353
354 /**
355 * Creates an iterator over the value if the value is a collection, an
356 * Object[] or a primitive type array; otherwise to simplify the caller's
357 * code, we just create a singleton collection iterator over a single value
358 *
359 * @param value the value
360 * @param delimiter delimiter for separating String values
361 * @return the iterator
362 */
363 @SuppressWarnings("unchecked")
364 public static Iterator createIterator(Object value, String delimiter) {
365 if (value == null) {
366 return Collections.EMPTY_LIST.iterator();
367 } else if (value instanceof Iterator) {
368 return (Iterator)value;
369 } else if (value instanceof Collection) {
370 Collection collection = (Collection)value;
371 return collection.iterator();
372 } else if (value.getClass().isArray()) {
373 // TODO we should handle primitive array types?
374 List<Object> list = Arrays.asList((Object[])value);
375 return list.iterator();
376 } else if (value instanceof NodeList) {
377 // lets iterate through DOM results after performing XPaths
378 final NodeList nodeList = (NodeList)value;
379 return new Iterator<Node>() {
380 int idx = -1;
381
382 public boolean hasNext() {
383 return ++idx < nodeList.getLength();
384 }
385
386 public Node next() {
387 return nodeList.item(idx);
388 }
389
390 public void remove() {
391 throw new UnsupportedOperationException();
392 }
393 };
394 } else if (value instanceof String) {
395 Scanner scanner = new Scanner((String)value);
396 scanner.useDelimiter(delimiter);
397 return scanner;
398 } else {
399 return Collections.singletonList(value).iterator();
400 }
401 }
402
403 /**
404 * Returns the predicate matching boolean on a {@link List} result set where
405 * if the first element is a boolean its value is used otherwise this method
406 * returns true if the collection is not empty
407 *
408 * @return <tt>true</tt> if the first element is a boolean and its value
409 * is true or if the list is non empty
410 */
411 public static boolean matches(List list) {
412 if (!list.isEmpty()) {
413 Object value = list.get(0);
414 if (value instanceof Boolean) {
415 return (Boolean)value;
416 } else {
417 // lets assume non-empty results are true
418 return true;
419 }
420 }
421 return false;
422 }
423
424 /**
425 * A helper method to access a system property, catching any security
426 * exceptions
427 *
428 * @param name the name of the system property required
429 * @param defaultValue the default value to use if the property is not
430 * available or a security exception prevents access
431 * @return the system property value or the default value if the property is
432 * not available or security does not allow its access
433 */
434 public static String getSystemProperty(String name, String defaultValue) {
435 try {
436 return System.getProperty(name, defaultValue);
437 } catch (Exception e) {
438 if (LOG.isDebugEnabled()) {
439 LOG.debug("Caught security exception accessing system property: " + name + ". Reason: " + e, e);
440 }
441 return defaultValue;
442 }
443 }
444
445 /**
446 * A helper method to access a boolean system property, catching any
447 * security exceptions
448 *
449 * @param name the name of the system property required
450 * @param defaultValue the default value to use if the property is not
451 * available or a security exception prevents access
452 * @return the boolean representation of the system property value or the
453 * default value if the property is not available or security does
454 * not allow its access
455 */
456 public static boolean getSystemProperty(String name, Boolean defaultValue) {
457 String result = getSystemProperty(name, defaultValue.toString());
458 return Boolean.parseBoolean(result);
459 }
460
461 /**
462 * Returns the type name of the given type or null if the type variable is
463 * null
464 */
465 public static String name(Class type) {
466 return type != null ? type.getName() : null;
467 }
468
469 /**
470 * Returns the type name of the given value
471 */
472 public static String className(Object value) {
473 return name(value != null ? value.getClass() : null);
474 }
475
476 /**
477 * Returns the canonical type name of the given value
478 */
479 public static String classCanonicalName(Object value) {
480 if (value != null) {
481 return value.getClass().getCanonicalName();
482 } else {
483 return null;
484 }
485 }
486
487 /**
488 * Attempts to load the given class name using the thread context class
489 * loader or the class loader used to load this class
490 *
491 * @param name the name of the class to load
492 * @return the class or null if it could not be loaded
493 */
494 public static Class<?> loadClass(String name) {
495 return loadClass(name, ObjectHelper.class.getClassLoader());
496 }
497
498 /**
499 * Attempts to load the given class name using the thread context class
500 * loader or the given class loader
501 *
502 * @param name the name of the class to load
503 * @param loader the class loader to use after the thread context class
504 * loader
505 * @return the class or null if it could not be loaded
506 */
507 public static Class<?> loadClass(String name, ClassLoader loader) {
508 // must clean the name so its pure java name, eg remoing \n or whatever people can do in the Spring XML
509 name = normalizeClassName(name);
510
511 // try context class loader first
512 Class clazz = doLoadClass(name, Thread.currentThread().getContextClassLoader());
513 if (clazz == null) {
514 // then the provided loader
515 clazz = doLoadClass(name, loader);
516 }
517 if (clazz == null) {
518 // and fallback to the loader the loaded the ObjectHelper class
519 clazz = doLoadClass(name, ObjectHelper.class.getClassLoader());
520 }
521
522 if (clazz == null) {
523 LOG.warn("Cannot find class: " + name);
524 }
525
526 return clazz;
527 }
528
529 /**
530 * Loads the given class with the provided classloader (may be null).
531 * Will ignore any class not found and return null.
532 *
533 * @param name the name of the class to load
534 * @param loader a provided loader (may be null)
535 * @return the class, or null if it could not be loaded
536 */
537 private static Class<?> doLoadClass(String name, ClassLoader loader) {
538 ObjectHelper.notEmpty(name, "name");
539 if (loader == null) {
540 return null;
541 }
542 try {
543 return loader.loadClass(name);
544 } catch (ClassNotFoundException e) {
545 if (LOG.isTraceEnabled()) {
546 LOG.trace("Cannot load class: " + name + " using classloader: " + loader, e);
547 }
548
549 }
550 return null;
551 }
552
553 /**
554 * Attempts to load the given resource as a stream using the thread context
555 * class loader or the class loader used to load this class
556 *
557 * @param name the name of the resource to load
558 * @return the stream or null if it could not be loaded
559 */
560 public static InputStream loadResourceAsStream(String name) {
561 InputStream in = null;
562
563 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
564 if (contextClassLoader != null) {
565 in = contextClassLoader.getResourceAsStream(name);
566 }
567 if (in == null) {
568 in = ObjectHelper.class.getClassLoader().getResourceAsStream(name);
569 }
570
571 return in;
572 }
573
574 /**
575 * A helper method to invoke a method via reflection and wrap any exceptions
576 * as {@link RuntimeCamelException} instances
577 *
578 * @param method the method to invoke
579 * @param instance the object instance (or null for static methods)
580 * @param parameters the parameters to the method
581 * @return the result of the method invocation
582 */
583 public static Object invokeMethod(Method method, Object instance, Object... parameters) {
584 try {
585 return method.invoke(instance, parameters);
586 } catch (IllegalAccessException e) {
587 throw new RuntimeCamelException(e);
588 } catch (InvocationTargetException e) {
589 throw new RuntimeCamelException(e.getCause());
590 }
591 }
592
593 /**
594 * Returns a list of methods which are annotated with the given annotation
595 *
596 * @param type the type to reflect on
597 * @param annotationType the annotation type
598 * @return a list of the methods found
599 */
600 public static List<Method> findMethodsWithAnnotation(Class<?> type,
601 Class<? extends Annotation> annotationType) {
602 return findMethodsWithAnnotation(type, annotationType, false);
603 }
604
605 /**
606 * Returns a list of methods which are annotated with the given annotation
607 *
608 * @param type the type to reflect on
609 * @param annotationType the annotation type
610 * @param checkMetaAnnotations check for meta annotations
611 * @return a list of the methods found
612 */
613 public static List<Method> findMethodsWithAnnotation(Class<?> type,
614 Class<? extends Annotation> annotationType,
615 boolean checkMetaAnnotations) {
616 List<Method> answer = new ArrayList<Method>();
617 do {
618 Method[] methods = type.getDeclaredMethods();
619 for (Method method : methods) {
620 if (hasAnnotation(method, annotationType, checkMetaAnnotations)) {
621 answer.add(method);
622 }
623 }
624 type = type.getSuperclass();
625 } while (type != null);
626 return answer;
627 }
628
629 /**
630 * Checks if a Class or Method are annotated with the given annotation
631 *
632 * @param elem the Class or Method to reflect on
633 * @param annotationType the annotation type
634 * @param checkMetaAnnotations check for meta annotations
635 * @return true if annotations is present
636 */
637 public static boolean hasAnnotation(AnnotatedElement elem, Class<? extends Annotation> annotationType,
638 boolean checkMetaAnnotations) {
639 if (elem.isAnnotationPresent(annotationType)) {
640 return true;
641 }
642 if (checkMetaAnnotations) {
643 for (Annotation a : elem.getAnnotations()) {
644 for (Annotation meta : a.annotationType().getAnnotations()) {
645 if (meta.annotationType().getName().equals(annotationType.getName())) {
646 return true;
647 }
648 }
649 }
650 }
651 return false;
652 }
653
654 /**
655 * Turns the given object arrays into a meaningful string
656 *
657 * @param objects an array of objects or null
658 * @return a meaningful string
659 */
660 public static String asString(Object[] objects) {
661 if (objects == null) {
662 return "null";
663 } else {
664 StringBuffer buffer = new StringBuffer("{");
665 int counter = 0;
666 for (Object object : objects) {
667 if (counter++ > 0) {
668 buffer.append(", ");
669 }
670 String text = (object == null) ? "null" : object.toString();
671 buffer.append(text);
672 }
673 buffer.append("}");
674 return buffer.toString();
675 }
676 }
677
678 /**
679 * Returns true if a class is assignable from another class like the
680 * {@link Class#isAssignableFrom(Class)} method but which also includes
681 * coercion between primitive types to deal with Java 5 primitive type
682 * wrapping
683 */
684 public static boolean isAssignableFrom(Class a, Class b) {
685 a = convertPrimitiveTypeToWrapperType(a);
686 b = convertPrimitiveTypeToWrapperType(b);
687 return a.isAssignableFrom(b);
688 }
689
690 /**
691 * Converts primitive types such as int to its wrapper type like
692 * {@link Integer}
693 */
694 public static Class convertPrimitiveTypeToWrapperType(Class type) {
695 Class rc = type;
696 if (type.isPrimitive()) {
697 if (type == int.class) {
698 rc = Integer.class;
699 } else if (type == long.class) {
700 rc = Long.class;
701 } else if (type == double.class) {
702 rc = Double.class;
703 } else if (type == float.class) {
704 rc = Float.class;
705 } else if (type == short.class) {
706 rc = Short.class;
707 } else if (type == byte.class) {
708 rc = Byte.class;
709 // TODO: Why is boolean disabled
710 /*
711 * } else if (type == boolean.class) { rc = Boolean.class;
712 */
713 }
714 }
715 return rc;
716 }
717
718 /**
719 * Helper method to return the default character set name
720 */
721 public static String getDefaultCharacterSet() {
722 return Charset.defaultCharset().name();
723 }
724
725 /**
726 * Returns the Java Bean property name of the given method, if it is a
727 * setter
728 */
729 public static String getPropertyName(Method method) {
730 String propertyName = method.getName();
731 if (propertyName.startsWith("set") && method.getParameterTypes().length == 1) {
732 propertyName = propertyName.substring(3, 4).toLowerCase() + propertyName.substring(4);
733 }
734 return propertyName;
735 }
736
737 /**
738 * Returns true if the given collection of annotations matches the given
739 * type
740 */
741 public static boolean hasAnnotation(Annotation[] annotations, Class<?> type) {
742 for (Annotation annotation : annotations) {
743 if (type.isInstance(annotation)) {
744 return true;
745 }
746 }
747 return false;
748 }
749
750 /**
751 * Closes the given resource if it is available, logging any closing
752 * exceptions to the given log
753 *
754 * @param closeable the object to close
755 * @param name the name of the resource
756 * @param log the log to use when reporting closure warnings
757 */
758 public static void close(Closeable closeable, String name, Log log) {
759 if (closeable != null) {
760 try {
761 closeable.close();
762 } catch (IOException e) {
763 if (log != null) {
764 log.warn("Cannot close: " + name + ". Reason: " + e, e);
765 }
766 }
767 }
768 }
769
770 /**
771 * Converts the given value to the required type or throw a meaningful exception
772 */
773 @SuppressWarnings("unchecked")
774 public static <T> T cast(Class<T> toType, Object value) {
775 if (toType == boolean.class) {
776 return (T)cast(Boolean.class, value);
777 } else if (toType.isPrimitive()) {
778 Class newType = convertPrimitiveTypeToWrapperType(toType);
779 if (newType != toType) {
780 return (T)cast(newType, value);
781 }
782 }
783 try {
784 return toType.cast(value);
785 } catch (ClassCastException e) {
786 throw new IllegalArgumentException("Failed to convert: " + value + " to type: "
787 + toType.getName() + " due to: " + e, e);
788 }
789 }
790
791 /**
792 * A helper method to create a new instance of a type using the default
793 * constructor arguments.
794 */
795 public static <T> T newInstance(Class<T> type) {
796 try {
797 return type.newInstance();
798 } catch (InstantiationException e) {
799 throw new RuntimeCamelException(e);
800 } catch (IllegalAccessException e) {
801 throw new RuntimeCamelException(e);
802 }
803 }
804
805 /**
806 * A helper method to create a new instance of a type using the default
807 * constructor arguments.
808 */
809 public static <T> T newInstance(Class<?> actualType, Class<T> expectedType) {
810 try {
811 Object value = actualType.newInstance();
812 return cast(expectedType, value);
813 } catch (InstantiationException e) {
814 throw new RuntimeCamelException(e);
815 } catch (IllegalAccessException e) {
816 throw new RuntimeCamelException(e);
817 }
818 }
819
820 /**
821 * Returns true if the given name is a valid java identifier
822 */
823 public static boolean isJavaIdentifier(String name) {
824 if (name == null) {
825 return false;
826 }
827 int size = name.length();
828 if (size < 1) {
829 return false;
830 }
831 if (Character.isJavaIdentifierStart(name.charAt(0))) {
832 for (int i = 1; i < size; i++) {
833 if (!Character.isJavaIdentifierPart(name.charAt(i))) {
834 return false;
835 }
836 }
837 return true;
838 }
839 return false;
840 }
841
842 /**
843 * Returns the type of the given object or null if the value is null
844 */
845 public static Object type(Object bean) {
846 return bean != null ? bean.getClass() : null;
847 }
848
849 /**
850 * Evaluate the value as a predicate which attempts to convert the value to
851 * a boolean otherwise true is returned if the value is not null
852 */
853 public static boolean evaluateValuePredicate(Object value) {
854 if (value instanceof Boolean) {
855 return (Boolean)value;
856 } else if (value instanceof String) {
857 if ("true".equals(value)) {
858 return true;
859 } else if ("false".equals(value)) {
860 return false;
861 }
862 }
863 return value != null;
864 }
865
866 /**
867 * Wraps the caused exception in a {@link RuntimeCamelException} if its not
868 * already such an exception.
869 *
870 * @param e the caused exception
871 * @return the wrapper exception
872 */
873 public static RuntimeCamelException wrapRuntimeCamelException(Throwable e) {
874 if (e instanceof RuntimeCamelException) {
875 // don't double wrap if already a RuntimeCamelException
876 return (RuntimeCamelException)e;
877 } else {
878 return new RuntimeCamelException(e);
879 }
880 }
881
882 /**
883 * Cleans the string to pure java identifier so we can use it for loading class names.
884 * <p/>
885 * Especially from Sping DSL people can have \n \t or other characters that otherwise
886 * would result in ClassNotFoundException
887 *
888 * @param name the class name
889 * @return normalized classname that can be load by a class loader.
890 */
891 public static String normalizeClassName(String name) {
892 StringBuffer sb = new StringBuffer(name.length());
893 for (char ch : name.toCharArray()) {
894 if (ch == '.' || Character.isJavaIdentifierPart(ch)) {
895 sb.append(ch);
896 }
897 }
898 return sb.toString();
899 }
900
901 }