View Javadoc

1   /*
2    $Id: ScriptBytecodeAdapter.java 4294 2006-12-02 19:31:27Z blackdrag $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  package org.codehaus.groovy.runtime;
47  
48  import groovy.lang.*;
49  
50  import java.util.Iterator;
51  import java.util.List;
52  import java.util.ArrayList;
53  import java.util.Map;
54  import java.util.regex.Matcher;
55  import java.util.regex.Pattern;
56  
57  import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
58  import org.codehaus.groovy.runtime.wrappers.GroovyObjectWrapper;
59  import org.codehaus.groovy.runtime.wrappers.PojoWrapper;
60  import org.codehaus.groovy.runtime.wrappers.Wrapper;
61  
62  /***
63   * A static helper class to interface bytecode and runtime 
64   *
65   * @author Jochen Theodorou
66   * @version $Revision: 4294 $
67   */
68  public class ScriptBytecodeAdapter {
69      public static final Object[] EMPTY_ARGS = {};
70      private static final Integer ZERO = new Integer(0);
71      private static final Integer MINUS_ONE = new Integer(-1);
72      private static final Integer ONE = new Integer(1);
73  
74      //  --------------------------------------------------------
75      //                   exception handling
76      //  --------------------------------------------------------
77      private static Object unwrap(GroovyRuntimeException gre) throws Throwable{
78          Throwable th = gre;
79          if (th.getCause()!=null && th.getCause()!=gre) th=th.getCause();
80          if (th!=gre && (th instanceof GroovyRuntimeException)) unwrap((GroovyRuntimeException) th);
81          throw th;
82      }
83      
84      //  --------------------------------------------------------
85      //                       methods for this
86      //  --------------------------------------------------------
87      public static Object invokeMethodOnCurrentN(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
88          Object result=null;
89          try {
90              try {
91                  // if it's a pure interceptable object (even intercepting toString(), clone(), ...)
92                  if (receiver instanceof GroovyInterceptable) {
93                      result = receiver.invokeMethod(messageName, messageArguments);
94                  }
95                  //else if there's a statically typed method or a GDK method
96                  else {
97                      result = receiver.getMetaClass().invokeMethod(senderClass, receiver, messageName, messageArguments, false, true);
98                  }
99              } catch (MissingMethodException e) {
100                 if (receiver.getClass() == e.getType() && e.getMethod().equals(messageName)) {
101                     // in case there's nothing else, invoke the object's own invokeMethod()
102                     result = receiver.invokeMethod(messageName, messageArguments);
103                 } else {
104                     throw e;
105                 }
106             }
107         } catch (GroovyRuntimeException t) {
108             unwrap(t);
109         }
110         return result;
111     }
112     
113     public static Object invokeMethodOnCurrentNSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
114         return invokeMethodOnCurrentN(senderClass,receiver,messageName,messageArguments);
115     }
116     
117     public static Object invokeMethodOnCurrentNSpreadSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
118         if (! (receiver instanceof List)) return invokeMethodOnCurrentN(senderClass,receiver,messageName, messageArguments);
119         
120         List list = (List) receiver;
121         List answer = new ArrayList();
122         for (Iterator it = list.iterator(); it.hasNext();) {
123             answer.add(invokeMethodNSafe(senderClass, it.next(), messageName, messageArguments));
124         }
125         return answer;
126     }
127     
128     public static Object invokeMethodOnCurrent0(Class senderClass, GroovyObject receiver, String messageName)  throws Throwable{
129         return invokeMethodOnCurrentN(senderClass,receiver,messageName,EMPTY_ARGS);
130     }
131     
132     public static Object invokeMethodOnCurrent0Safe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
133         return invokeMethodOnCurrentNSafe(senderClass,receiver,messageName,EMPTY_ARGS);
134     }
135     
136     public static Object invokeMethodOnCurrent0SpreadSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
137         return invokeMethodOnCurrentNSpreadSafe(senderClass,receiver,messageName,EMPTY_ARGS);
138     }
139     
140     //  --------------------------------------------------------
141     //                       methods for super
142     //  --------------------------------------------------------
143     public static Object invokeMethodOnSuperN(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
144         MetaClass metaClass = receiver.getMetaClass();
145         // ignore interception and missing method fallback
146         Object result=null;
147         try {
148             result = metaClass.invokeMethod(senderClass, receiver, messageName, messageArguments, true, true);
149         } catch (GroovyRuntimeException t) {
150             unwrap(t);
151         }
152         return result;        
153     }
154     
155     public static Object invokeMethodOnSuperNSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
156         return invokeMethodOnSuperN(senderClass,receiver,messageName,messageArguments);
157     }
158     
159     public static Object invokeMethodOnSuperNSpreadSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
160         if (! (receiver instanceof List)) return invokeMethodOnSuperN(senderClass,receiver,messageName, messageArguments);
161         
162         List list = (List) receiver;
163         List answer = new ArrayList();
164         for (Iterator it = list.iterator(); it.hasNext();) {
165             answer.add(invokeMethodNSafe(senderClass,it.next(), messageName, messageArguments));
166         }
167         return answer;
168     }
169     
170     public static Object invokeMethodOnSuper0(Class senderClass, GroovyObject receiver, String messageName)  throws Throwable{
171         return invokeMethodOnSuperN(senderClass,receiver,messageName,EMPTY_ARGS);
172     }
173     
174     public static Object invokeMethodOnSuper0Safe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
175         return invokeMethodOnSuperNSafe(senderClass,receiver,messageName,EMPTY_ARGS);
176     }
177     
178     public static Object invokeMethodOnSuper0SpreadSafe(Class senderClass, GroovyObject receiver, String messageName, Object[] messageArguments) throws Throwable{
179         return invokeMethodOnSuperNSpreadSafe(senderClass,receiver,messageName,EMPTY_ARGS);
180     }
181 
182     //  --------------------------------------------------------
183     //              normal method invocation
184     //  --------------------------------------------------------       
185     public static Object invokeMethodN(Class senderClass, Object receiver, String messageName, Object[] messageArguments) throws Throwable{
186         try {
187             return InvokerHelper.invokeMethod(receiver, messageName, messageArguments);
188         } catch (GroovyRuntimeException gre) {
189             return unwrap(gre);
190         }
191     }
192     
193     public static Object invokeMethodNSafe(Class senderClass, Object receiver, String messageName, Object[] messageArguments) throws Throwable{
194         if (receiver==null) return null;
195         return invokeMethodN(senderClass,receiver,messageName,messageArguments);
196     }
197     
198     public static Object invokeMethodNSpreadSafe(Class senderClass, Object receiver, String messageName, Object[] messageArguments) throws Throwable{
199         if (receiver==null) return null;
200         if (! (receiver instanceof List)) return invokeMethodN(senderClass,receiver,messageName, messageArguments);
201         
202         List list = (List) receiver;
203         List answer = new ArrayList();
204         for (Iterator it = list.iterator(); it.hasNext();) {
205             answer.add(invokeMethodNSafe(senderClass, it.next(), messageName, messageArguments));
206         }
207         return answer;
208     }
209     
210     public static Object invokeMethod0(Class senderClass, Object receiver, String messageName)  throws Throwable{
211         return invokeMethodN(senderClass,receiver,messageName,EMPTY_ARGS);
212     }
213     
214     public static Object invokeMethod0Safe(Class senderClass, Object receiver, String messageName) throws Throwable{
215         if (receiver==null) return null;
216         return invokeMethodNSafe(senderClass,receiver,messageName,EMPTY_ARGS);
217     }
218     
219     public static Object invokeMethod0SpreadSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
220         return invokeMethodNSpreadSafe(senderClass,receiver,messageName,EMPTY_ARGS);
221     }
222     
223     //  --------------------------------------------------------
224     //                static normal method invocation
225     //  --------------------------------------------------------       
226     public static Object invokeStaticMethodN(Class senderClass, Class receiver, String messageName, Object[] messageArguments) throws Throwable{
227         try {
228             return InvokerHelper.invokeStaticMethod(receiver, messageName, messageArguments);
229         } catch (GroovyRuntimeException gre) {
230             return unwrap(gre);
231         }
232     }
233     
234     public static Object invokeStaticMethod0(Class senderClass, Class receiver, String messageName)  throws Throwable{
235         return invokeStaticMethodN(senderClass,receiver,messageName,EMPTY_ARGS);
236     }
237     
238     //  --------------------------------------------------------
239     //              normal constructor invocation (via new)
240     //  --------------------------------------------------------       
241     public static Object invokeNewN(Class senderClass, Class receiver, Object arguments) throws Throwable{
242         try {
243             return InvokerHelper.invokeConstructorOf(receiver, arguments);
244         } catch (GroovyRuntimeException gre) {
245             return unwrap(gre);
246         }  
247     }
248     
249     public static Object invokeNew0(Class senderClass, Class receiver) throws Throwable {
250         return invokeNewN(senderClass, receiver, EMPTY_ARGS);
251     }
252 
253     //  --------------------------------------------------------
254     //       special constructor invocation (via this/super)
255     //  --------------------------------------------------------       
256 
257     public static int selectConstructorAndTransformArguments(Object[] arguments, int numberOfCosntructors, Class which) {
258         MetaClassImpl metaClass = (MetaClassImpl) InvokerHelper.getInstance().getMetaRegistry().getMetaClass(which);
259         return metaClass.selectConstructorAndTransformArguments(numberOfCosntructors, arguments);
260     }
261 
262     //  --------------------------------------------------------
263     //              field handling super: get
264     //  --------------------------------------------------------       
265 
266     public static Object getFieldOnSuper(Class senderClass, Object receiver, String messageName) throws Throwable{
267         try {
268             if (receiver instanceof Class) {
269                 return InvokerHelper.getAttribute(receiver,messageName); 
270             } else {            
271                 MetaClass mc = ((GroovyObject) receiver).getMetaClass();
272                 return mc.getAttribute(senderClass, receiver, messageName, true);
273             }
274         } catch (GroovyRuntimeException gre) {
275             return unwrap(gre);
276         }
277     }
278     
279     public static Object getFieldOnSuperSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
280         return getFieldOnSuper(senderClass,receiver,messageName);
281     }
282     
283     public static Object getFieldOnSuperSpreadSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
284         if (! (receiver instanceof List)) return getFieldOnSuper(senderClass,receiver,messageName);
285         
286         List list = (List) receiver;
287         List answer = new ArrayList();
288         for (Iterator it = list.iterator(); it.hasNext();) {
289             answer.add(getFieldOnSuper(senderClass, it.next(), messageName));
290         }
291         return answer;
292     }
293 
294     //  --------------------------------------------------------
295     //              field handling super: set
296     //  --------------------------------------------------------       
297 
298     public static void setFieldOnSuper(Object messageArgument,Class senderClass, Object receiver, String messageName) throws Throwable{
299         try {
300             if (receiver instanceof Class) {
301                 InvokerHelper.setAttribute(receiver,messageName,messageArgument); 
302             } else {          
303                 MetaClass mc = ((GroovyObject) receiver).getMetaClass();
304                 mc.setAttribute(senderClass, receiver, messageName, messageArgument, true, true);
305             }
306         } catch (GroovyRuntimeException gre) {
307             unwrap(gre);
308         }
309     }
310     
311     public static void setFieldOnSuperSafe(Object messageArgument,Class senderClass, Object receiver, String messageName) throws Throwable{
312         setFieldOnSuper(messageArgument,senderClass,receiver,messageName);
313     }
314     
315     public static void setFieldOnSuperSpreadSafe(Object messageArgument,Class senderClass, Object receiver, String messageName) throws Throwable{
316         if (! (receiver instanceof List)) {
317             setFieldOnSuper(messageArgument,senderClass,receiver,messageName);
318             return;
319         }
320         
321         List list = (List) receiver;
322         List answer = new ArrayList();
323         for (Iterator it = list.iterator(); it.hasNext();) {
324             setFieldOnSuper(messageArgument,senderClass, it.next(), messageName);
325         }
326     }
327 
328     
329     //  --------------------------------------------------------
330     //              normal field handling : get
331     //  --------------------------------------------------------       
332 
333     public static Object getField(Class senderClass, Object receiver, String messageName) throws Throwable{
334         try {
335             return InvokerHelper.getAttribute(receiver, messageName);
336         } catch (GroovyRuntimeException gre) {
337             return unwrap(gre);
338         }
339     }
340     
341     public static Object getFieldSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
342         if (receiver==null) return null;
343         return getField(senderClass,receiver,messageName);
344     }
345     
346     public static Object getFieldSpreadSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
347         if (receiver==null) return null;
348         if (! (receiver instanceof List)) return getField(senderClass,receiver,messageName);
349         
350         List list = (List) receiver;
351         List answer = new ArrayList();
352         for (Iterator it = list.iterator(); it.hasNext();) {
353             answer.add(getFieldSafe(senderClass, it.next(), messageName));
354         }
355         return answer;
356     }
357 
358     //  --------------------------------------------------------
359     //              normal field handling : set
360     //  --------------------------------------------------------       
361 
362     public static void setField(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
363         try {
364             InvokerHelper.setAttribute(receiver, messageName,messageArgument);
365         } catch (GroovyRuntimeException gre) {
366             unwrap(gre);
367         }
368     }
369     
370     public static void setFieldSafe(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
371         if (receiver==null) return;
372         setField(messageArgument,senderClass,receiver,messageName);
373     }
374     
375     public static void setFieldSpreadSafe(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
376         if (receiver==null) return;
377         if (! (receiver instanceof List)) {
378             setField(messageArgument,senderClass,receiver,messageName);
379             return;
380         }
381         
382         List list = (List) receiver;
383         List answer = new ArrayList();
384         for (Iterator it = list.iterator(); it.hasNext();) {
385             setFieldSafe(messageArgument,senderClass, it.next(), messageName);
386         }
387     }
388     
389     //  --------------------------------------------------------
390     //              normal GroovyObject field handling : get
391     //  --------------------------------------------------------       
392 
393     public static Object getGroovyObjectField(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
394         return receiver.getMetaClass().getAttribute(receiver,messageName);
395     }
396     
397     public static Object getGroovyObjectFieldSafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
398         if (receiver==null) return null;
399         return receiver.getMetaClass().getAttribute(receiver,messageName);
400     }
401     
402     public static Object getGroovyObjectFieldSpreadSafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
403         if (receiver==null) return null;
404         if (! (receiver instanceof List)) return getGroovyObjectField(senderClass,receiver,messageName);
405         
406         List list = (List) receiver;
407         List answer = new ArrayList();
408         for (Iterator it = list.iterator(); it.hasNext();) {
409             answer.add(getFieldSafe(senderClass, it.next(), messageName));
410         }
411         return answer;
412     }
413 
414     //  --------------------------------------------------------
415     //              normal field handling : set
416     //  --------------------------------------------------------       
417 
418     public static void setGroovyObjectField(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
419         receiver.getMetaClass().setAttribute(receiver,messageName,messageArgument);
420     }
421     
422     public static void setGroovyObjectFieldSafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
423         if (receiver==null) return;
424         receiver.getMetaClass().setAttribute(receiver,messageName,messageArgument);
425     }
426     
427     public static void setGroovyObjectFieldSpreadSafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
428         if (receiver==null) return;
429         if (! (receiver instanceof List)) {
430             setGroovyObjectField(messageArgument,senderClass,receiver,messageName);
431             return;
432         }
433         
434         List list = (List) receiver;
435         List answer = new ArrayList();
436         for (Iterator it = list.iterator(); it.hasNext();) {
437             setFieldSafe(messageArgument,senderClass, it.next(), messageName);
438         }
439     }
440 
441     //  --------------------------------------------------------
442     //              Property handling super: get
443     //  --------------------------------------------------------       
444 
445     public static Object getPropertyOnSuper(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
446         return invokeMethodOnSuperN(senderClass, receiver, "getProperty", new Object[]{messageName});
447     }
448     
449     public static Object getPropertyOnSuperSafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
450         return getPropertyOnSuper(senderClass,receiver,messageName);
451     }
452     
453     public static Object getPropertyOnSuperSpreadSafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
454         if (! (receiver instanceof List)) return getPropertyOnSuper(senderClass,receiver,messageName);
455         
456         List list = (List) receiver;
457         List answer = new ArrayList();
458         for (Iterator it = list.iterator(); it.hasNext();) {
459             answer.add(getPropertySafe(senderClass, it.next(), messageName));
460         }
461         return answer;
462     }
463 
464     //  --------------------------------------------------------
465     //              Property handling super: set
466     //  --------------------------------------------------------       
467 
468     public static void setPropertyOnSuper(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
469         try {
470             InvokerHelper.setAttribute(receiver, messageName,messageArgument);
471         } catch (GroovyRuntimeException gre) {
472             unwrap(gre);
473         }
474     }
475     
476     public static void setPropertyOnSuperSafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
477         setPropertyOnSuper(messageArgument, senderClass,receiver,messageName);
478     }
479     
480     public static void setPropertyOnSuperSpreadSafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
481         if (! (receiver instanceof List)) {
482             setPropertyOnSuper(messageArgument, senderClass,receiver,messageName);
483             return;
484         }
485         
486         List list = (List) receiver;
487         List answer = new ArrayList();
488         for (Iterator it = list.iterator(); it.hasNext();) {
489             setPropertySafe(messageArgument, senderClass, it.next(), messageName);
490         }
491     }
492 
493     
494     //  --------------------------------------------------------
495     //              normal Property handling : get
496     //  --------------------------------------------------------       
497 
498     public static Object getProperty(Class senderClass, Object receiver, String messageName) throws Throwable{
499         try {
500             return InvokerHelper.getProperty(receiver, messageName);
501         } catch (GroovyRuntimeException gre) {
502             return unwrap(gre);
503         }
504     }
505     
506     public static Object getPropertySafe(Class senderClass, Object receiver, String messageName) throws Throwable{
507         if (receiver==null) return null;
508         return getProperty(senderClass,receiver,messageName);
509     }
510     
511     public static Object getPropertySpreadSafe(Class senderClass, Object receiver, String messageName) throws Throwable{
512         if (receiver==null) return null;
513         if (! (receiver instanceof List)) return getProperty(senderClass,receiver,messageName);
514         
515         List list = (List) receiver;
516         List answer = new ArrayList();
517         for (Iterator it = list.iterator(); it.hasNext();) {
518             answer.add(getPropertySafe(senderClass, it.next(), messageName));
519         }
520         return answer;
521     }
522     
523     //  --------------------------------------------------------
524     //              normal Property handling : set
525     //  --------------------------------------------------------       
526 
527     public static void setProperty(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
528         try {
529             InvokerHelper.setProperty(receiver, messageName,messageArgument);
530         } catch (GroovyRuntimeException gre) {
531             unwrap(gre);
532         }
533     }
534     
535     public static void setPropertySafe(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
536         if (receiver==null) return;
537         setProperty(messageArgument,senderClass,receiver,messageName);
538     }
539     
540     public static void setPropertySpreadSafe(Object messageArgument, Class senderClass, Object receiver, String messageName) throws Throwable{
541         if (receiver==null) return;
542         if (! (receiver instanceof List)) {
543             setProperty(messageArgument, senderClass, receiver, messageName);
544             return;
545         }
546         
547         List list = (List) receiver;
548         List answer = new ArrayList();
549         for (Iterator it = list.iterator(); it.hasNext();) {
550             setPropertySafe(messageArgument, senderClass, it.next(), messageName);
551         }
552     }
553     
554     
555     //  --------------------------------------------------------
556     //              normal GroovyObject Property handling : get
557     //  --------------------------------------------------------       
558 
559     public static Object getGroovyObjectProperty(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
560         return receiver.getProperty(messageName);
561     }
562     
563     public static Object getGroovyObjectPropertySafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
564         if (receiver==null) return null;
565         return receiver.getProperty(messageName);
566     }
567     
568     public static Object getGroovyObjectPropertySpreadSafe(Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
569         if (receiver==null) return null;
570         if (! (receiver instanceof List)) return getGroovyObjectProperty(senderClass,receiver,messageName);
571         
572         List list = (List) receiver;
573         List answer = new ArrayList();
574         for (Iterator it = list.iterator(); it.hasNext();) {
575             answer.add(getPropertySafe(senderClass, it.next(), messageName));
576         }
577         return answer;
578     }
579 
580     //  --------------------------------------------------------
581     //              normal GroovyObject Property handling : set
582     //  --------------------------------------------------------       
583 
584     public static void setGroovyObjectProperty(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
585         receiver.setProperty(messageName,messageArgument);
586     }
587     
588     public static void setGroovyObjectPropertySafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
589         if (receiver==null) return;
590         receiver.setProperty(messageName,messageArgument);
591     }
592     
593     public static void setGroovyObjectPropertySpreadSafe(Object messageArgument, Class senderClass, GroovyObject receiver, String messageName) throws Throwable{
594         if (receiver==null) return;
595         if (! (receiver instanceof List)) {
596             setProperty(messageArgument, senderClass, receiver, messageName);
597             return;
598         }
599         
600         List list = (List) receiver;
601         List answer = new ArrayList();
602         for (Iterator it = list.iterator(); it.hasNext();) {
603             setPropertySafe(messageArgument, senderClass, it.next(), messageName);
604         }
605     }
606     
607     //  **********************************************************************************
608     //  **********************************************************************************
609     //  **************          methods not covered by the new MOP          **************
610     //  **********************************************************************************
611     //  **********************************************************************************
612     
613     //  --------------------------------------------------------
614     //                     Closures
615     //  --------------------------------------------------------           
616     
617     /***
618      * Returns the method pointer for the given object name
619      */
620     public static Closure getMethodPointer(Object object, String methodName) {
621         return InvokerHelper.getMethodPointer(object, methodName);
622     }
623     
624     // TODO: set sender class
625     public static Object invokeClosure(Object closure, Object[] arguments) throws Throwable {
626         return invokeMethodN(closure.getClass(), closure, "doCall", arguments);
627     } 
628         
629 
630     //  --------------------------------------------------------
631     //                     type conversion
632     //  --------------------------------------------------------           
633           
634     /***
635      * Provides a hook for type coercion of the given object to the required type
636      *
637      * @param type   of object to convert the given object to
638      * @param object the object to be converted
639      * @return the original object or a new converted value
640      * @throws Throwable 
641      */
642     public static Object asType(Object object, Class type) throws Throwable {
643         return invokeMethodN(object.getClass(),object,"asType",new Object[]{type});
644     }
645     
646     /***
647      * Provides a hook for type casting of the given object to the required type
648      * 
649      * @param type   of object to convert the given object to
650      * @param object the object to be converted
651      * @return the original object or a new converted value
652      * @throws Throwable 
653      */
654     public static Object castToType(Object object, Class type) throws Throwable{
655         try {
656             return DefaultTypeTransformation.castToType(object,type);
657         } catch (GroovyRuntimeException gre) {
658             return (Matcher) unwrap(gre);
659         }
660     }    
661 
662     public static Tuple createTuple(Object[] array) {
663         return new Tuple(array);
664     }
665 
666     public static List createList(Object[] values) {
667         return InvokerHelper.createList(values);
668     }
669     
670     public static Wrapper createPojoWrapper(Object val, Class clazz) {
671         return new PojoWrapper(val,clazz);
672     }
673 
674     public static Wrapper createGroovyObjectWrapper(GroovyObject val, Class clazz) {
675         return new GroovyObjectWrapper(val,clazz);
676     }
677     
678     public static Map createMap(Object[] values) {
679         return InvokerHelper.createMap(values);
680     }
681     
682 
683     //TODO: refactor
684     public static List createRange(Object from, Object to, boolean inclusive) throws Throwable {
685         if (!inclusive) {
686             if (compareEqual(from,to)){
687                 return new EmptyRange((Comparable)from);
688             }
689             if (compareGreaterThan(from, to)) {
690                 to = invokeMethod0(ScriptBytecodeAdapter.class, to, "next");
691             }
692             else {
693                 to = invokeMethod0(ScriptBytecodeAdapter.class, to, "previous");
694             }
695         }
696         if (from instanceof Integer && to instanceof Integer) {
697             return new IntRange(DefaultTypeTransformation.intUnbox(from), DefaultTypeTransformation.intUnbox(to));
698         }
699         else {
700             return new ObjectRange((Comparable) from, (Comparable) to);
701         }
702     }
703     
704     //assert
705     public static void assertFailed(Object expression, Object message) {
706         InvokerHelper.assertFailed(expression,message);
707     }
708 
709     //isCase
710     //TODO: set sender class
711     public static boolean isCase(Object switchValue, Object caseExpression) throws Throwable{
712         if (caseExpression == null) {
713             return switchValue == null;
714         }
715         return DefaultTypeTransformation.castToBoolean(invokeMethodN(caseExpression.getClass(), caseExpression, "isCase", new Object[]{switchValue}));
716     }
717     
718     //compare
719     public static boolean compareIdentical(Object left, Object right) {
720         return left == right;
721     }
722     
723     public static boolean compareEqual(Object left, Object right) {
724         return DefaultTypeTransformation.compareEqual(left, right);
725     }
726     
727     public static boolean compareNotEqual(Object left, Object right) {
728         return !compareEqual(left, right);
729     }
730     
731     public static Integer compareTo(Object left, Object right) {
732         int answer = DefaultTypeTransformation.compareTo(left, right);
733         if (answer == 0) {
734             return ZERO;
735         }
736         else {
737             return answer > 0 ? ONE : MINUS_ONE;
738         }
739     }    
740 
741     public static boolean compareLessThan(Object left, Object right) {
742         return compareTo(left, right).intValue() < 0;
743     }
744     
745     public static boolean compareLessThanEqual(Object left, Object right){
746         return compareTo(left, right).intValue() <= 0;
747     }
748     
749     public static boolean compareGreaterThan(Object left, Object right){
750         return compareTo(left, right).intValue() > 0;
751     }
752 
753     public static boolean compareGreaterThanEqual(Object left, Object right){
754         return compareTo(left, right).intValue() >= 0;
755     }
756 
757     //regexpr
758     public static Pattern regexPattern(Object regex) {
759         return DefaultGroovyMethods.negate(regex.toString());
760     }
761     
762     public static Matcher findRegex(Object left, Object right) throws Throwable{
763         try {
764             return InvokerHelper.findRegex(left, right);
765         } catch (GroovyRuntimeException gre) {
766             return (Matcher) unwrap(gre);
767         }
768     }
769     
770     public static boolean matchRegex(Object left, Object right) {
771         return InvokerHelper.matchRegex(left, right);
772     }
773     
774     
775     //spread expressions
776     public static Object[] despreadList(Object[] args, Object[] spreads, int[] positions) {
777         ArrayList ret = new ArrayList();
778         int argsPos = 0;
779         int spreadPos = 0;
780         for (int pos = 0; pos<positions.length; pos++) {
781             for (;argsPos<positions[pos];argsPos++) {
782                 ret.add(args[argsPos]);
783             }
784             Object value = spreads[spreadPos];
785             if (value==null) {
786                 ret.add(null);
787             } else if (value instanceof List) {
788                 ret.addAll((List) value);
789             } else if (value.getClass().isArray()) {
790                 ret.addAll(DefaultTypeTransformation.primitiveArrayToList(value));
791             } else {
792                 throw new IllegalArgumentException("connot spread the type "+ value.getClass().getName()+" with value "+value);
793             }
794             spreadPos++;
795         }
796         for (;argsPos<args.length;argsPos++) {
797             ret.add(args[argsPos]);
798         }
799         return ret.toArray();
800     }
801     
802     public static Object spreadMap(Object value) {
803         return InvokerHelper.spreadMap(value);
804     }
805     
806     //negation
807     public static Object negate(Object value) throws Throwable {
808         try {
809             return InvokerHelper.negate(value);
810         } catch (GroovyRuntimeException gre) {
811             return unwrap(gre);
812         }
813     }
814     
815     public static Object bitNegate(Object value) {
816         return InvokerHelper.bitNegate(value);
817     }
818 
819     public static MetaClass initMetaClass(Object object) {
820         return InvokerHelper.getMetaClass(object);
821     }
822     
823     private static MetaClass getMetaClassObjectNotNull(Object object) {
824         if (!(object instanceof GroovyObject)) {
825             return initMetaClass(object);
826         } else {
827             return ((GroovyObject) object).getMetaClass();
828         }        
829     }
830     
831     
832 
833 }