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