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