1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.runtime;
47
48 import groovy.lang.Closure;
49 import groovy.lang.GroovyObject;
50 import groovy.lang.GroovyRuntimeException;
51 import groovy.lang.MetaClass;
52 import groovy.lang.MetaClassRegistry;
53 import groovy.lang.MissingMethodException;
54 import groovy.lang.Range;
55 import groovy.lang.SpreadList;
56 import groovy.lang.Tuple;
57 import groovy.lang.GroovyInterceptable;
58 import org.apache.xml.serialize.OutputFormat;
59 import org.apache.xml.serialize.XMLSerializer;
60 import org.w3c.dom.Element;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63
64 import java.io.File;
65 import java.io.IOException;
66 import java.io.StringWriter;
67 import java.lang.reflect.Array;
68 import java.lang.reflect.Method;
69 import java.math.BigDecimal;
70 import java.security.AccessController;
71 import java.security.PrivilegedAction;
72 import java.util.ArrayList;
73 import java.util.Arrays;
74 import java.util.Collection;
75 import java.util.Collections;
76 import java.util.Enumeration;
77 import java.util.Iterator;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.NoSuchElementException;
81 import java.util.regex.Matcher;
82 import java.util.regex.Pattern;
83
84 /***
85 * A helper class to invoke methods or extract properties on arbitrary Java objects dynamically
86 *
87 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
88 * @version $Revision: 1.87 $
89 */
90 public class Invoker {
91
92 protected static final Object[] EMPTY_ARGUMENTS = {
93 };
94 protected static final Class[] EMPTY_TYPES = {
95 };
96
97 public MetaClassRegistry getMetaRegistry() {
98 return metaRegistry;
99 }
100
101 private MetaClassRegistry metaRegistry = new MetaClassRegistry();
102
103 public MetaClass getMetaClass(Object object) {
104 return metaRegistry.getMetaClass(object.getClass());
105 }
106
107 /***
108 * Invokes the given method on the object.
109 *
110 * @param object
111 * @param methodName
112 * @param arguments
113 * @return
114 */
115 public Object invokeMethod(Object object, String methodName, Object arguments) {
116
117
118
119
120
121
122
123
124
125
126
127
128 if (object == null) {
129 throw new NullPointerException("Cannot invoke method " + methodName + "() on null object");
130 }
131
132
133 if (object instanceof Class) {
134 Class theClass = (Class) object;
135 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
136 return metaClass.invokeStaticMethod(object, methodName, asArray(arguments));
137 }
138 else
139 {
140
141 if (!(object instanceof GroovyObject)) {
142 Class theClass = object.getClass();
143 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
144 return metaClass.invokeMethod(object, methodName, asArray(arguments));
145 }
146
147 else {
148 GroovyObject groovy = (GroovyObject) object;
149 try {
150
151 if (groovy instanceof GroovyInterceptable) {
152 return groovy.invokeMethod(methodName, asArray(arguments));
153 }
154
155 else {
156 return groovy.getMetaClass().invokeMethod(object, methodName, asArray(arguments));
157 }
158 } catch (MissingMethodException e) {
159 if (e.getMethod().equals(methodName) && object.getClass() == e.getType()) {
160
161 return groovy.invokeMethod(methodName, asArray(arguments));
162 } else {
163 throw e;
164 }
165 }
166 }
167 }
168 }
169
170 public Object invokeSuperMethod(Object object, String methodName, Object arguments) {
171 if (object == null) {
172 throw new NullPointerException("Cannot invoke method " + methodName + "() on null object");
173 }
174
175 Class theClass = object.getClass();
176
177 MetaClass metaClass = metaRegistry.getMetaClass(theClass.getSuperclass());
178 return metaClass.invokeMethod(object, methodName, asArray(arguments));
179 }
180
181 public Object invokeStaticMethod(String type, String method, Object arguments) {
182 MetaClass metaClass = metaRegistry.getMetaClass(loadClass(type));
183 List argumentList = asList(arguments);
184 return metaClass.invokeStaticMethod(null, method, asArray(arguments));
185 }
186
187 public Object invokeConstructorAt(Class at, Class type, Object arguments) {
188 MetaClass metaClass = metaRegistry.getMetaClass(type);
189 return metaClass.invokeConstructorAt(at, asArray(arguments));
190 }
191
192 public Object invokeConstructorAt(Class at, String type, Object arguments) {
193 return invokeConstructorAt(at, loadClass(type), arguments);
194 }
195
196 public Object invokeConstructorOf(Class type, Object arguments) {
197 MetaClass metaClass = metaRegistry.getMetaClass(type);
198 return metaClass.invokeConstructor(asArray(arguments));
199 }
200
201 public Object invokeConstructorOf(String type, Object arguments) {
202 return invokeConstructorOf(loadClass(type), arguments);
203 }
204
205 /***
206 * Converts the given object into an array; if its an array then just
207 * cast otherwise wrap it in an array
208 */
209 public Object[] asArray(Object arguments) {
210 if (arguments == null) {
211 return EMPTY_ARGUMENTS;
212 }
213 else if ((arguments instanceof Object[]) && ((Object[]) arguments).length == 0) {
214 return (Object[]) arguments;
215 }
216 else if (arguments instanceof Tuple) {
217 Tuple tuple = (Tuple) arguments;
218 Object[] objects = tuple.toArray();
219 ArrayList array = new ArrayList();
220 for (int i = 0; i < objects.length; i++) {
221 if (objects[i] instanceof SpreadList) {
222 SpreadList slist = (SpreadList) objects[i];
223 for (int j = 0; j < slist.size(); j++) {
224 array.add(slist.get(j));
225 }
226 }
227 else {
228 array.add(objects[i]);
229 }
230 }
231 return array.toArray();
232 }
233 else if (arguments instanceof Object[]) {
234 Object[] objects = (Object[]) arguments;
235 ArrayList array = new ArrayList();
236 for (int i = 0; i < objects.length; i++) {
237 if (objects[i] instanceof SpreadList) {
238 SpreadList slist = (SpreadList) objects[i];
239 for (int j = 0; j < slist.size(); j++) {
240 array.add(slist.get(j));
241 }
242 }
243 else {
244 array.add(objects[i]);
245 }
246 }
247 return array.toArray();
248 }
249 else if (arguments instanceof SpreadList) {
250 ArrayList array = new ArrayList();
251 SpreadList slist = (SpreadList) arguments;
252 for (int j = 0; j < slist.size(); j++) {
253 array.add(slist.get(j));
254 }
255 return array.toArray();
256 }
257 else {
258 return new Object[]{arguments};
259 }
260 }
261
262 public List asList(Object value) {
263 if (value == null) {
264 return Collections.EMPTY_LIST;
265 }
266 else if (value instanceof List) {
267 return (List) value;
268 }
269 else if (value.getClass().isArray()) {
270 return Arrays.asList((Object[]) value);
271 }
272 else if (value instanceof Enumeration) {
273 List answer = new ArrayList();
274 for (Enumeration e = (Enumeration) value; e.hasMoreElements();) {
275 answer.add(e.nextElement());
276 }
277 return answer;
278 }
279 else {
280
281 return Collections.singletonList(value);
282 }
283 }
284
285 /***
286 * Converts the value parameter into a <code>Collection</code>.
287 *
288 * @param value value to convert
289 * @return a Collection
290 */
291 public Collection asCollection(Object value) {
292 if (value == null) {
293 return Collections.EMPTY_LIST;
294 }
295 else if (value instanceof Collection) {
296 return (Collection) value;
297 }
298 else if (value instanceof Map) {
299 Map map = (Map) value;
300 return map.entrySet();
301 }
302 else if (value.getClass().isArray()) {
303 if (value.getClass().getComponentType().isPrimitive()) {
304 return InvokerHelper.primitiveArrayToList(value);
305 }
306 return Arrays.asList((Object[]) value);
307 }
308 else if (value instanceof MethodClosure) {
309 MethodClosure method = (MethodClosure) value;
310 IteratorClosureAdapter adapter = new IteratorClosureAdapter(method.getDelegate());
311 method.call(adapter);
312 return adapter.asList();
313 }
314 else if (value instanceof String) {
315 return DefaultGroovyMethods.toList((String) value);
316 }
317 else if (value instanceof File) {
318 try {
319 return DefaultGroovyMethods.readLines((File) value);
320 }
321 catch (IOException e) {
322 throw new GroovyRuntimeException("Error reading file: " + value, e);
323 }
324 }
325 else {
326
327 return Collections.singletonList(value);
328 }
329 }
330
331 public Iterator asIterator(Object value) {
332 if (value == null) {
333 return Collections.EMPTY_LIST.iterator();
334 }
335 if (value instanceof Iterator) {
336 return (Iterator) value;
337 }
338 if (value instanceof NodeList) {
339 final NodeList nodeList = (NodeList) value;
340 return new Iterator() {
341 private int current = 0;
342
343 public boolean hasNext() {
344 return current < nodeList.getLength();
345 }
346
347 public Object next() {
348 Node node = nodeList.item(current++);
349 return node;
350 }
351
352 public void remove() {
353 throw new UnsupportedOperationException("Cannot remove() from an Enumeration");
354 }
355 };
356 }
357 else if (value instanceof Enumeration) {
358 final Enumeration enumeration = (Enumeration) value;
359 return new Iterator() {
360 private Object last;
361
362 public boolean hasNext() {
363 return enumeration.hasMoreElements();
364 }
365
366 public Object next() {
367 last = enumeration.nextElement();
368 return last;
369 }
370
371 public void remove() {
372 throw new UnsupportedOperationException("Cannot remove() from an Enumeration");
373 }
374 };
375 }
376 else if (value instanceof Matcher) {
377 final Matcher matcher = (Matcher) value;
378 return new Iterator() {
379 private boolean found = false;
380 private boolean done = false;
381
382 public boolean hasNext() {
383 if (done) {
384 return false;
385 }
386 if (!found) {
387 found = matcher.find();
388 if (!found) {
389 done = true;
390 }
391 }
392 return found;
393 }
394
395 public Object next() {
396 if (!found) {
397 if (!hasNext()) {
398 throw new NoSuchElementException();
399 }
400 }
401 found = false;
402 return matcher.group();
403 }
404
405 public void remove() {
406 throw new UnsupportedOperationException();
407 }
408 };
409 }
410 else {
411 try {
412
413 final Method method = value.getClass().getMethod("iterator", EMPTY_TYPES);
414
415 if (method != null) {
416 AccessController.doPrivileged(new PrivilegedAction() {
417 public Object run() {
418 method.setAccessible(true);
419 return null;
420 }
421 });
422
423 return (Iterator) method.invoke(value, EMPTY_ARGUMENTS);
424 }
425 }
426 catch (Exception e) {
427
428 }
429 }
430 return asCollection(value).iterator();
431 }
432
433 /***
434 * @return true if the two objects are null or the objects are equal
435 */
436 public boolean objectsEqual(Object left, Object right) {
437 if (left == right) {
438 return true;
439 }
440 if (left != null) {
441 if (right == null) {
442 return false;
443 }
444 if (left instanceof Comparable) {
445 return compareTo(left, right) == 0;
446 }
447 else if (left instanceof List && right instanceof List) {
448 return DefaultGroovyMethods.equals((List) left, (List) right);
449 }
450 else {
451 return left.equals(right);
452 }
453 }
454 return false;
455 }
456
457 public String inspect(Object self) {
458 return format(self, true);
459 }
460
461 /***
462 * Compares the two objects handling nulls gracefully and performing numeric type coercion if required
463 */
464 public int compareTo(Object left, Object right) {
465
466 if (left == right) {
467 return 0;
468 }
469 if (left == null) {
470 return -1;
471 }
472 else if (right == null) {
473 return 1;
474 }
475 if (left instanceof Comparable) {
476 if (left instanceof Number) {
477 if (isValidCharacterString(right)) {
478 return asCharacter((Number) left).compareTo(asCharacter((String) right));
479 }
480 return DefaultGroovyMethods.compareTo((Number) left, asNumber(right));
481 }
482 else if (left instanceof Character) {
483 if (isValidCharacterString(right)) {
484 return ((Character) left).compareTo(asCharacter((String) right));
485 }
486 else if (right instanceof Number) {
487 return ((Character) left).compareTo(asCharacter((Number) right));
488 }
489 }
490 else if (right instanceof Number) {
491 if (isValidCharacterString(left)) {
492 return asCharacter((String) left).compareTo(asCharacter((Number) right));
493 }
494 return DefaultGroovyMethods.compareTo(asNumber(left), (Number) right);
495 }
496 else if (left instanceof String && right instanceof Character) {
497 return ((String) left).compareTo(right.toString());
498 }
499 Comparable comparable = (Comparable) left;
500 return comparable.compareTo(right);
501 }
502
503 if (left.getClass().isArray()) {
504 Collection leftList = asCollection(left);
505 if (right.getClass().isArray()) {
506 right = asCollection(right);
507 }
508 return ((Comparable) leftList).compareTo(right);
509 }
510 /*** todo we might wanna do some type conversion here */
511 throw new GroovyRuntimeException("Cannot compare values: " + left + " and " + right);
512 }
513
514 /***
515 * A helper method to provide some better toString() behaviour such as turning arrays
516 * into tuples
517 */
518 public String toString(Object arguments) {
519 if (arguments instanceof Object[])
520 return toArrayString((Object[]) arguments);
521 else if (arguments instanceof Map)
522 return toMapString((Map) arguments);
523 else if (arguments instanceof Collection)
524 return format(arguments, true);
525 else
526 return format(arguments, false);
527 }
528
529 /***
530 * A helper method to format the arguments types as a comma-separated list
531 */
532 public String toTypeString(Object[] arguments) {
533 if (arguments == null) {
534 return "null";
535 }
536 StringBuffer argBuf = new StringBuffer();
537 for (int i = 0; i < arguments.length; i++) {
538 if (i > 0) {
539 argBuf.append(", ");
540 }
541 argBuf.append(arguments[i] != null ? arguments[i].getClass().getName() : "null");
542 }
543 return argBuf.toString();
544 }
545
546 /***
547 * A helper method to return the string representation of a map with bracket boundaries "[" and "]".
548 */
549 public String toMapString(Map arg) {
550 if (arg == null) {
551 return "null";
552 }
553 if (arg.isEmpty()) {
554 return "[:]";
555 }
556 String sbdry = "[";
557 String ebdry = "]";
558 StringBuffer buffer = new StringBuffer(sbdry);
559 boolean first = true;
560 for (Iterator iter = arg.entrySet().iterator(); iter.hasNext();) {
561 if (first)
562 first = false;
563 else
564 buffer.append(", ");
565 Map.Entry entry = (Map.Entry) iter.next();
566 buffer.append(format(entry.getKey(), true));
567 buffer.append(":");
568 buffer.append(format(entry.getValue(), true));
569 }
570 buffer.append(ebdry);
571 return buffer.toString();
572 }
573
574 /***
575 * A helper method to return the string representation of a list with bracket boundaries "[" and "]".
576 */
577 public String toListString(Collection arg) {
578 if (arg == null) {
579 return "null";
580 }
581 if (arg.isEmpty()) {
582 return "[]";
583 }
584 String sbdry = "[";
585 String ebdry = "]";
586 StringBuffer buffer = new StringBuffer(sbdry);
587 boolean first = true;
588 for (Iterator iter = arg.iterator(); iter.hasNext();) {
589 if (first)
590 first = false;
591 else
592 buffer.append(", ");
593 Object elem = iter.next();
594 buffer.append(format(elem, true));
595 }
596 buffer.append(ebdry);
597 return buffer.toString();
598 }
599
600 /***
601 * A helper method to return the string representation of an arrray of objects
602 * with brace boundaries "{" and "}".
603 */
604 public String toArrayString(Object[] arguments) {
605 if (arguments == null) {
606 return "null";
607 }
608 String sbdry = "{";
609 String ebdry = "}";
610 StringBuffer argBuf = new StringBuffer(sbdry);
611 for (int i = 0; i < arguments.length; i++) {
612 if (i > 0) {
613 argBuf.append(", ");
614 }
615 argBuf.append(format(arguments[i], true));
616 }
617 argBuf.append(ebdry);
618 return argBuf.toString();
619 }
620
621 protected String format(Object arguments, boolean verbose) {
622 if (arguments == null) {
623 return "null";
624 }
625 else if (arguments.getClass().isArray()) {
626 return format(asCollection(arguments), verbose);
627 }
628 else if (arguments instanceof Range) {
629 Range range = (Range) arguments;
630 if (verbose) {
631 return range.inspect();
632 }
633 else {
634 return range.toString();
635 }
636 }
637 else if (arguments instanceof List) {
638 List list = (List) arguments;
639 StringBuffer buffer = new StringBuffer("[");
640 boolean first = true;
641 for (Iterator iter = list.iterator(); iter.hasNext();) {
642 if (first) {
643 first = false;
644 }
645 else {
646 buffer.append(", ");
647 }
648 buffer.append(format(iter.next(), verbose));
649 }
650 buffer.append("]");
651 return buffer.toString();
652 }
653 else if (arguments instanceof Map) {
654 Map map = (Map) arguments;
655 if (map.isEmpty()) {
656 return "[:]";
657 }
658 StringBuffer buffer = new StringBuffer("[");
659 boolean first = true;
660 for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
661 if (first) {
662 first = false;
663 }
664 else {
665 buffer.append(", ");
666 }
667 Map.Entry entry = (Map.Entry) iter.next();
668 buffer.append(format(entry.getKey(), verbose));
669 buffer.append(":");
670 buffer.append(format(entry.getValue(), verbose));
671 }
672 buffer.append("]");
673 return buffer.toString();
674 }
675 else if (arguments instanceof Element) {
676 Element node = (Element) arguments;
677 OutputFormat format = new OutputFormat(node.getOwnerDocument());
678 format.setOmitXMLDeclaration(true);
679 format.setIndenting(true);
680 format.setLineWidth(0);
681 format.setPreserveSpace(true);
682 StringWriter sw = new StringWriter();
683 XMLSerializer serializer = new XMLSerializer(sw, format);
684 try {
685 serializer.asDOMSerializer();
686 serializer.serialize(node);
687 }
688 catch (IOException e) {
689 }
690 return sw.toString();
691 }
692 else if (arguments instanceof String) {
693 if (verbose) {
694 String arg = ((String)arguments).replaceAll("//n", "////n");
695 arg = arg.replaceAll("//r", "////r");
696 arg = arg.replaceAll("//t", "////t");
697 arg = arg.replaceAll("//f", "////f");
698 arg = arg.replaceAll("//\"", "////\"");
699 arg = arg.replaceAll("////", "////");
700 return "\"" + arg + "\"";
701 }
702 else {
703 return (String) arguments;
704 }
705 }
706 else {
707 return arguments.toString();
708 }
709 }
710
711 /***
712 * Looks up the given property of the given object
713 */
714 public Object getProperty(Object object, String property) {
715 if (object == null) {
716 throw new NullPointerException("Cannot get property: " + property + " on null object");
717 }
718 else if (object instanceof GroovyObject) {
719 GroovyObject pogo = (GroovyObject) object;
720 return pogo.getProperty(property);
721 }
722 else if (object instanceof Map) {
723 Map map = (Map) object;
724 return map.get(property);
725 }
726 else {
727 return metaRegistry.getMetaClass(object.getClass()).getProperty(object, property);
728 }
729 }
730
731 /***
732 * Sets the property on the given object
733 */
734 public void setProperty(Object object, String property, Object newValue) {
735 if (object == null) {
736 throw new GroovyRuntimeException("Cannot set property on null object");
737 }
738 else if (object instanceof GroovyObject) {
739 GroovyObject pogo = (GroovyObject) object;
740 pogo.setProperty(property, newValue);
741 }
742 else if (object instanceof Map) {
743 Map map = (Map) object;
744 map.put(property, newValue);
745 }
746 else {
747 if (object instanceof Class)
748 metaRegistry.getMetaClass((Class) object).setProperty((Class) object, property, newValue);
749 else
750 metaRegistry.getMetaClass(object.getClass()).setProperty(object, property, newValue);
751 }
752 }
753
754 /***
755 * Looks up the given attribute (field) on the given object
756 */
757 public Object getAttribute(Object object, String attribute) {
758 if (object == null) {
759 throw new NullPointerException("Cannot get attribute: " + attribute + " on null object");
760
761 /***
762 } else if (object instanceof GroovyObject) {
763 GroovyObject pogo = (GroovyObject) object;
764 return pogo.getAttribute(attribute);
765 } else if (object instanceof Map) {
766 Map map = (Map) object;
767 return map.get(attribute);
768 */
769 }
770 else {
771 if (object instanceof Class) {
772 return metaRegistry.getMetaClass((Class) object).getAttribute(object, attribute);
773 } else if (object instanceof GroovyObject) {
774 return ((GroovyObject)object).getMetaClass().getAttribute(object, attribute);
775 } else {
776 return metaRegistry.getMetaClass(object.getClass()).getAttribute(object, attribute);
777 }
778 }
779 }
780
781 /***
782 * Sets the given attribute (field) on the given object
783 */
784 public void setAttribute(Object object, String attribute, Object newValue) {
785 if (object == null) {
786 throw new GroovyRuntimeException("Cannot set attribute on null object");
787
788
789
790
791
792
793
794
795 }
796 else {
797 if (object instanceof Class) {
798 metaRegistry.getMetaClass((Class) object).setAttribute(object, attribute, newValue);
799 } else if (object instanceof GroovyObject) {
800 ((GroovyObject)object).getMetaClass().setAttribute(object, attribute, newValue);
801 } else {
802 metaRegistry.getMetaClass(object.getClass()).setAttribute(object, attribute, newValue);
803 }
804 }
805 }
806
807 /***
808 * Returns the method pointer for the given object name
809 */
810 public Closure getMethodPointer(Object object, String methodName) {
811 if (object == null) {
812 throw new NullPointerException("Cannot access method pointer for '" + methodName + "' on null object");
813 }
814 return MetaClassHelper.getMethodPointer(object, methodName);
815 }
816
817
818 /***
819 * Attempts to load the given class via name using the current class loader
820 * for this code or the thread context class loader
821 */
822 protected Class loadClass(String type) {
823 try {
824 return getClass().getClassLoader().loadClass(type);
825 }
826 catch (ClassNotFoundException e) {
827 try {
828 return Thread.currentThread().getContextClassLoader().loadClass(type);
829 }
830 catch (ClassNotFoundException e2) {
831 try {
832 return Class.forName(type);
833 }
834 catch (ClassNotFoundException e3) {
835 }
836 }
837 throw new GroovyRuntimeException("Could not load type: " + type, e);
838 }
839 }
840
841 /***
842 * Find the right hand regex within the left hand string and return a matcher.
843 *
844 * @param left string to compare
845 * @param right regular expression to compare the string to
846 * @return
847 */
848 public Matcher objectFindRegex(Object left, Object right) {
849 String stringToCompare;
850 if (left instanceof String) {
851 stringToCompare = (String) left;
852 }
853 else {
854 stringToCompare = toString(left);
855 }
856 String regexToCompareTo;
857 if (right instanceof String) {
858 regexToCompareTo = (String) right;
859 }
860 else if (right instanceof Pattern) {
861 Pattern pattern = (Pattern) right;
862 return pattern.matcher(stringToCompare);
863 }
864 else {
865 regexToCompareTo = toString(right);
866 }
867 Matcher matcher = Pattern.compile(regexToCompareTo).matcher(stringToCompare);
868 return matcher;
869 }
870
871 /***
872 * Find the right hand regex within the left hand string and return a matcher.
873 *
874 * @param left string to compare
875 * @param right regular expression to compare the string to
876 * @return
877 */
878 public boolean objectMatchRegex(Object left, Object right) {
879 Pattern pattern;
880 if (right instanceof Pattern) {
881 pattern = (Pattern) right;
882 }
883 else {
884 pattern = Pattern.compile(toString(right));
885 }
886 String stringToCompare = toString(left);
887 Matcher matcher = pattern.matcher(stringToCompare);
888 RegexSupport.setLastMatcher(matcher);
889 return matcher.matches();
890 }
891
892 /***
893 * Compile a regular expression from a string.
894 *
895 * @param regex
896 * @return
897 */
898 public Pattern regexPattern(Object regex) {
899 return Pattern.compile(regex.toString());
900 }
901
902 public Object asType(Object object, Class type) {
903 if (object == null) {
904 return null;
905 }
906
907
908 if (type.isArray()) {
909 return asArray(object, type);
910
911 }
912 if (type.isInstance(object)) {
913 return object;
914 }
915 if (type.isAssignableFrom(Collection.class)) {
916 if (object.getClass().isArray()) {
917
918
919 Collection answer = null;
920 try {
921 answer = (Collection) type.newInstance();
922 }
923 catch (Exception e) {
924 throw new ClassCastException("Could not instantiate instance of: " + type.getName() + ". Reason: " + e);
925 }
926
927
928 int length = Array.getLength(object);
929 for (int i = 0; i < length; i++) {
930 Object element = Array.get(object, i);
931 answer.add(element);
932 }
933 return answer;
934 }
935 }
936 if (type.equals(String.class)) {
937 return object.toString();
938 }
939 if (type.equals(Character.class)) {
940 if (object instanceof Number) {
941 return asCharacter((Number) object);
942 }
943 else {
944 String text = object.toString();
945 if (text.length() == 1) {
946 return new Character(text.charAt(0));
947 }
948 else {
949 throw new ClassCastException("Cannot cast: " + text + " to a Character");
950 }
951 }
952 }
953 if (Number.class.isAssignableFrom(type)) {
954 if (object instanceof Character) {
955 return new Integer(((Character) object).charValue());
956 }
957 else if (object instanceof String) {
958 String c = (String) object;
959 if (c.length() == 1) {
960 return new Integer(c.charAt(0));
961 }
962 else {
963 throw new ClassCastException("Cannot cast: '" + c + "' to an Integer");
964 }
965 }
966 }
967 if (object instanceof Number) {
968 Number n = (Number) object;
969 if (type.isPrimitive()) {
970 if (type == byte.class) {
971 return new Byte(n.byteValue());
972 }
973 if (type == char.class) {
974 return new Character((char) n.intValue());
975 }
976 if (type == short.class) {
977 return new Short(n.shortValue());
978 }
979 if (type == int.class) {
980 return new Integer(n.intValue());
981 }
982 if (type == long.class) {
983 return new Long(n.longValue());
984 }
985 if (type == float.class) {
986 return new Float(n.floatValue());
987 }
988 if (type == double.class) {
989 Double answer = new Double(n.doubleValue());
990
991 if (!(n instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
992 || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
993 throw new GroovyRuntimeException("Automatic coercion of " + n.getClass().getName()
994 + " value " + n + " to double failed. Value is out of range.");
995 }
996 return answer;
997 }
998 }
999 else {
1000 if (Number.class.isAssignableFrom(type)) {
1001 if (type == Byte.class) {
1002 return new Byte(n.byteValue());
1003 }
1004 if (type == Character.class) {
1005 return new Character((char) n.intValue());
1006 }
1007 if (type == Short.class) {
1008 return new Short(n.shortValue());
1009 }
1010 if (type == Integer.class) {
1011 return new Integer(n.intValue());
1012 }
1013 if (type == Long.class) {
1014 return new Long(n.longValue());
1015 }
1016 if (type == Float.class) {
1017 return new Float(n.floatValue());
1018 }
1019 if (type == Double.class) {
1020 Double answer = new Double(n.doubleValue());
1021
1022 if (!(n instanceof Double) && (answer.doubleValue() == Double.NEGATIVE_INFINITY
1023 || answer.doubleValue() == Double.POSITIVE_INFINITY)) {
1024 throw new GroovyRuntimeException("Automatic coercion of " + n.getClass().getName()
1025 + " value " + n + " to double failed. Value is out of range.");
1026 }
1027 return answer;
1028 }
1029
1030 }
1031 }
1032 }
1033 if (type == Boolean.class) {
1034 return asBool(object) ? Boolean.TRUE : Boolean.FALSE;
1035 }
1036 Object[] args = null;
1037 if (object instanceof Collection) {
1038 Collection list = (Collection) object;
1039 args = list.toArray();
1040 }
1041 else if (object instanceof Object[]) {
1042 args = (Object[]) object;
1043 }
1044 if (args != null) {
1045
1046
1047 try {
1048 return invokeConstructorOf(type, args);
1049 }
1050 catch (Exception e) {
1051
1052
1053
1054 }
1055
1056 }
1057 return object;
1058 }
1059
1060 public Object asArray(Object object, Class type) {
1061 Collection list = asCollection(object);
1062 int size = list.size();
1063 Class elementType = type.getComponentType();
1064 Object array = Array.newInstance(elementType, size);
1065 int idx = 0;
1066
1067 if (boolean.class.equals(elementType)) {
1068 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1069 Object element = iter.next();
1070 Array.setBoolean(array, idx, asBool(element));
1071 }
1072 }
1073 else if (byte.class.equals(elementType)) {
1074 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1075 Object element = iter.next();
1076 Array.setByte(array, idx, asByte(element));
1077 }
1078 }
1079 else if (char.class.equals(elementType)) {
1080 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1081 Object element = iter.next();
1082 Array.setChar(array, idx, asChar(element));
1083 }
1084 }
1085 else if (double.class.equals(elementType)) {
1086 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1087 Object element = iter.next();
1088 Array.setDouble(array, idx, asDouble(element));
1089 }
1090 }
1091 else if (float.class.equals(elementType)) {
1092 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1093 Object element = iter.next();
1094 Array.setFloat(array, idx, asFloat(element));
1095 }
1096 }
1097 else if (int.class.equals(elementType)) {
1098 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1099 Object element = iter.next();
1100 Array.setInt(array, idx, asInt(element));
1101 }
1102 }
1103 else if (long.class.equals(elementType)) {
1104 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1105 Object element = iter.next();
1106 Array.setLong(array, idx, asLong(element));
1107 }
1108 }
1109 else if (short.class.equals(elementType)) {
1110 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1111 Object element = iter.next();
1112 Array.setShort(array, idx, asShort(element));
1113 }
1114 }
1115 else {
1116 for (Iterator iter = list.iterator(); iter.hasNext(); idx++) {
1117 Object element = iter.next();
1118 Object coercedElement = asType(element, elementType);
1119 Array.set(array, idx, coercedElement);
1120 }
1121 }
1122 return array;
1123 }
1124
1125 public Number asNumber(Object value) {
1126 if (value instanceof Number) {
1127 return (Number) value;
1128 }
1129 else if (value instanceof String) {
1130 String s = (String) value;
1131
1132 if (s.length() == 1) {
1133 return new Integer(s.charAt(0));
1134 }
1135 else {
1136 return new BigDecimal(s);
1137 }
1138 }
1139 else if (value instanceof Character) {
1140 return new Integer(((Character) value).charValue());
1141 }
1142 else {
1143 throw new GroovyRuntimeException("Could not convert object: " + value + " into a Number");
1144 }
1145 }
1146
1147 public byte asByte(Object element) {
1148 return asNumber(element).byteValue();
1149 }
1150
1151 public char asChar(Object element) {
1152 if (element instanceof String) {
1153 return asCharacter((String) element).charValue();
1154 }
1155 return asCharacter(asNumber(element)).charValue();
1156 }
1157
1158 public float asFloat(Object element) {
1159 return asNumber(element).floatValue();
1160 }
1161
1162 public double asDouble(Object element) {
1163 return asNumber(element).doubleValue();
1164 }
1165
1166 public short asShort(Object element) {
1167 return asNumber(element).shortValue();
1168 }
1169
1170 public int asInt(Object element) {
1171 return asNumber(element).intValue();
1172 }
1173
1174 public long asLong(Object element) {
1175 return asNumber(element).longValue();
1176 }
1177
1178 public boolean asBool(Object object) {
1179 if (object instanceof Boolean) {
1180 Boolean booleanValue = (Boolean) object;
1181 return booleanValue.booleanValue();
1182 }
1183 else if (object instanceof Matcher) {
1184 Matcher matcher = (Matcher) object;
1185 RegexSupport.setLastMatcher(matcher);
1186 return matcher.find();
1187 }
1188 else if (object instanceof Collection) {
1189 Collection collection = (Collection) object;
1190 return !collection.isEmpty();
1191 }
1192 else if (object instanceof Map) {
1193 Map map = (Map) object;
1194 return !map.isEmpty();
1195 }
1196 else if (object instanceof String) {
1197 String string = (String) object;
1198 return string.length() > 0;
1199 }
1200 else if (object instanceof Number) {
1201 Number n = (Number) object;
1202 return n.doubleValue() != 0;
1203 }
1204 else {
1205 return object != null;
1206 }
1207 }
1208
1209 protected Character asCharacter(Number value) {
1210 return new Character((char) value.intValue());
1211 }
1212
1213 protected Character asCharacter(String text) {
1214 return new Character(text.charAt(0));
1215 }
1216
1217 /***
1218 * @return true if the given value is a valid character string (i.e. has length of 1)
1219 */
1220 protected boolean isValidCharacterString(Object value) {
1221 if (value instanceof String) {
1222 String s = (String) value;
1223 if (s.length() == 1) {
1224 return true;
1225 }
1226 }
1227 return false;
1228 }
1229
1230 public void removeMetaClass(Class clazz) {
1231 getMetaRegistry().removeMetaClass(clazz);
1232 }
1233 }