View Javadoc

1   /*
2    $Id: ScriptBytecodeAdapter.java,v 1.3 2005/02/21 17:11:53 phk Exp $
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.Map;
53  import java.util.regex.Matcher;
54  import java.util.regex.Pattern;
55  
56  /***
57   * A static helper class to make bytecode generation easier and act as a facade over the Invoker. 
58   *
59   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
60   * @version $Revision: 1.3 $
61   */
62  public class ScriptBytecodeAdapter {
63      public static final Object[] EMPTY_ARGS = {
64      };
65  /*
66      private static final Object[] EMPTY_MAIN_ARGS = new Object[]{new String[0]};
67  
68      private static final Invoker singleton = new Invoker();
69  
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      private static Object unwrap(GroovyRuntimeException gre) throws Throwable{
76          Throwable th = gre;
77          if (th.getCause()!=null && th.getCause()!=gre) th=th.getCause();
78          if (th!=gre && (th instanceof GroovyRuntimeException)) unwrap((GroovyRuntimeException) th);
79          throw th;
80      }
81  
82      public static Object invokeMethod(Object object, String methodName, Object arguments)  throws Throwable{
83          try {
84              return InvokerHelper.invokeMethod(object, methodName, arguments);
85          } catch (GroovyRuntimeException gre) {
86              return unwrap(gre);
87          }
88      }
89      
90      public static Object invokeMethodSafe(Object object, String methodName, Object arguments) throws Throwable{
91          if (object != null) return invokeMethod(object, methodName, arguments);
92          return null;
93      }    
94  
95      public static Object invokeStaticMethod(String type, String methodName, Object arguments) throws Throwable{
96          try {
97              return InvokerHelper.invokeStaticMethod(type, methodName, arguments);
98          } catch (GroovyRuntimeException gre) {
99              return unwrap(gre);
100         }
101     }
102 
103     public static Object invokeConstructor(String type, Object arguments) throws Throwable{
104         try {
105             return InvokerHelper.invokeConstructor(type, arguments);
106         } catch (GroovyRuntimeException gre) {
107             return unwrap(gre);
108         }
109     }
110 
111     public static Object invokeConstructorOf(Class type, Object arguments) throws Throwable{
112         try {
113             return InvokerHelper.invokeConstructorOf(type, arguments);
114         } catch (GroovyRuntimeException gre) {
115             return unwrap(gre);
116         }  
117     }
118     
119     public static Object invokeNoArgumentsConstructorOf(Class type) throws Throwable{
120         return invokeConstructorOf(type, EMPTY_ARGS);
121     }
122     
123     public static Object invokeClosure(Object closure, Object arguments) throws Throwable {
124         return invokeMethod(closure, "doCall", arguments);
125     }    
126     
127     public static Object invokeSuperMethod(Object object, String methodName, Object arguments) throws Throwable{
128         try {
129             return InvokerHelper.invokeSuperMethod(object, methodName, arguments);
130         } catch (GroovyRuntimeException gre) {
131             return unwrap(gre);
132         } 
133     }
134     
135     public static Object invokeNoArgumentsMethod(Object object, String methodName) throws Throwable {
136         return invokeMethod(object, methodName, EMPTY_ARGS);
137     }
138     
139     public static Object invokeStaticNoArgumentsMethod(String type, String methodName) throws Throwable {
140         return invokeStaticMethod(type, methodName, EMPTY_ARGS);
141     }
142     
143     public static int asInt(Object value) throws Throwable {
144         try {
145             return InvokerHelper.asInt(value);
146         } catch (GroovyRuntimeException gre) {
147            unwrap(gre);
148            // return never reached
149            return -1;
150         }
151     }
152     
153     /***
154      * Provides a hook for type coercion of the given object to the required type
155      *
156      * @param type   of object to convert the given object to
157      * @param object the object to be converted
158      * @return the original object or a new converted value
159      * @throws Throwable 
160      */
161     public static Object asType(Object object, Class type) throws Throwable {
162         try {
163             return InvokerHelper.asType(object, type);
164         } catch (GroovyRuntimeException gre) {
165             return unwrap(gre);
166         }
167     }
168 
169 
170 
171     // Attributes
172     //-------------------------------------------------------------------------
173     public static Object getAttribute(Object object, String attribute) throws Throwable {
174         try {
175             return InvokerHelper.getAttribute(object, attribute);
176         } catch (GroovyRuntimeException gre) {
177             return unwrap(gre);
178         }
179     }
180 
181     public static Object getAttributeSafe(Object object, String attribute) throws Throwable {
182         if (object != null) return getAttribute(object, attribute);
183         return null;
184     }
185 
186     public static void setAttribute(Object object, String attribute, Object newValue) throws Throwable {
187         try {
188             InvokerHelper.setAttribute(object, attribute, newValue);
189         } catch (GroovyRuntimeException gre) {
190             unwrap(gre);
191         }
192     }
193     /***
194      * This is so we don't have to reorder the stack when we call this method.
195      * At some point a better name might be in order.
196      * @throws Throwable
197      */
198     public static void setAttribute2(Object newValue, Object object, String property) throws Throwable {
199         setAttribute(object, property, newValue);
200     }
201 
202     /***
203      * This is so we don't have to reorder the stack when we call this method.
204      * At some point a better name might be in order.
205      * @throws Throwable
206      */
207     public static void setAttributeSafe2(Object newValue, Object object, String property) throws Throwable {
208         setAttribute2(newValue, object, property);
209     }
210 
211 
212 
213     // Properties
214     //-------------------------------------------------------------------------
215     public static Object getProperty(Object object, String property) throws Throwable {
216         try {
217             return InvokerHelper.getProperty(object, property);
218         } catch (GroovyRuntimeException gre) {
219             return unwrap(gre);
220         }
221     }
222 
223     public static Object getPropertySafe(Object object, String property) throws Throwable {
224         if (object != null) return getProperty(object, property);
225         return null;
226     }
227 
228     public static void setProperty(Object object, String property, Object newValue) throws Throwable {
229         try {
230             InvokerHelper.setProperty(object, property, newValue);
231         } catch (GroovyRuntimeException gre) {
232             unwrap(gre);
233         }
234     }
235     
236     /***
237      * This is so we don't have to reorder the stack when we call this method.
238      * At some point a better name might be in order.
239      * @throws Throwable 
240      */
241     public static void setProperty2(Object newValue, Object object, String property) throws Throwable {
242         setProperty(object, property, newValue);
243     }
244 
245     /***
246      * This is so we don't have to reorder the stack when we call this method.
247      * At some point a better name might be in order.
248      * @throws Throwable 
249      */
250     public static void setPropertySafe2(Object newValue, Object object, String property) throws Throwable {
251         setProperty2(newValue, object, property);
252     }
253 
254 
255     /***
256      * This is so we don't have to reorder the stack when we call this method.
257      * At some point a better name might be in order.
258      * @throws Throwable 
259      */
260     public static void setGroovyObjectProperty(Object newValue, GroovyObject object, String property) throws Throwable {
261         try {
262             object.setProperty(property, newValue);
263         } catch (GroovyRuntimeException gre) {
264             unwrap(gre);
265         }
266     }
267 
268     public static Object getGroovyObjectProperty(GroovyObject object, String property) throws Throwable {
269         try {
270             return object.getProperty(property);
271         } catch (GroovyRuntimeException gre) {
272             return unwrap(gre);
273         }
274     }
275 
276 
277     // Coercions
278     //-------------------------------------------------------------------------
279     public static Iterator asIterator(Object collection) throws Throwable {
280         try {
281             return InvokerHelper.asIterator(collection);
282         } catch (GroovyRuntimeException gre) {
283             return (Iterator) unwrap(gre);
284         }
285     }    
286     
287     public static boolean asBool(Object object) throws Throwable {
288         try {
289             return InvokerHelper.asBool(object);
290         } catch (GroovyRuntimeException gre) {
291             unwrap(gre);
292             //return never reached
293             return false;
294         }
295     }
296     
297     public static boolean notBoolean(boolean bool) {
298         return !bool;
299     }    
300     
301     public static boolean notObject(Object object) throws Throwable {
302         return !asBool(object);
303     }
304     
305     public static Pattern regexPattern(Object regex) throws Throwable {
306         try {
307             return InvokerHelper.regexPattern(regex);
308         } catch (GroovyRuntimeException gre) {
309             return (Pattern) unwrap(gre);
310         }
311     }
312     
313     public static Object negate(Object value) throws Throwable {
314         try {
315             return InvokerHelper.negate(value);
316         } catch (GroovyRuntimeException gre) {
317             return unwrap(gre);
318         }
319     }
320     
321     public static Object bitNegate(Object value) throws Throwable {
322         try {
323             return InvokerHelper.bitNegate(value);
324         } catch (GroovyRuntimeException gre) {
325             return unwrap(gre);
326         }
327     }
328     
329     /***
330      * @param a    array of primitives
331      * @param type component type of the array
332      * @return
333      * @throws Throwable 
334      */
335     public static Object[] convertPrimitiveArray(Object a, Class type) throws Throwable {
336         try {
337             return InvokerHelper.convertPrimitiveArray(a,type);
338         } catch (GroovyRuntimeException gre) {
339             return (Object[])unwrap(gre);
340         }
341     }
342     
343     public static Object convertToPrimitiveArray(Object a, Class type) throws Throwable {
344         try {
345             return InvokerHelper.convertToPrimitiveArray(a,type);
346         } catch (GroovyRuntimeException gre) {
347             return unwrap(gre);
348         }
349     }
350 
351     public static boolean compareIdentical(Object left, Object right) {
352         return left == right;
353     }
354     
355     public static boolean compareEqual(Object left, Object right) throws Throwable{
356         try {
357             return InvokerHelper.compareEqual(left, right);
358         } catch (GroovyRuntimeException gre) {
359             unwrap(gre);
360             // return never reached
361             return false;
362         }
363     }
364     
365     public static boolean compareNotEqual(Object left, Object right) throws Throwable{
366         return !compareEqual(left, right);
367     }
368     
369     public static Integer compareTo(Object left, Object right) throws Throwable{
370         try {
371             return InvokerHelper.compareTo(left, right);
372         } catch (GroovyRuntimeException gre) {
373             return (Integer) unwrap(gre);
374         }
375     }    
376 
377     public static Matcher findRegex(Object left, Object right) throws Throwable{
378         try {
379             return InvokerHelper.findRegex(left, right);
380         } catch (GroovyRuntimeException gre) {
381             return (Matcher) unwrap(gre);
382         }
383     }
384     
385     public static boolean matchRegex(Object left, Object right) throws Throwable{
386         try {
387             return InvokerHelper.matchRegex(left, right);
388         } catch (GroovyRuntimeException gre) {
389             unwrap(gre);
390             // return never reached
391             return false;
392         }
393     }
394 
395     public static boolean compareLessThan(Object left, Object right) throws Throwable{
396         return compareTo(left, right).intValue() < 0;
397     }
398     
399     public static boolean compareLessThanEqual(Object left, Object right) throws Throwable{
400         return compareTo(left, right).intValue() <= 0;
401     }
402     
403     public static boolean compareGreaterThan(Object left, Object right) throws Throwable{
404         return compareTo(left, right).intValue() > 0;
405     }
406 
407     public static boolean compareGreaterThanEqual(Object left, Object right) throws Throwable{
408         return compareTo(left, right).intValue() >= 0;
409     }
410     
411     public static boolean isCase(Object switchValue, Object caseExpression) throws Throwable{
412         return asBool(invokeMethod(caseExpression, "isCase", new Object[]{switchValue}));
413     }
414     
415     public static Tuple createTuple(Object[] array) throws Throwable{
416         return new Tuple(array);
417     }
418 
419     public static List createList(Object[] values) throws Throwable{
420         return InvokerHelper.createList(values);
421     }
422 
423     public static Map createMap(Object[] values) throws Throwable{
424         return InvokerHelper.createMap(values);
425     }
426     
427     public static List createRange(Object from, Object to, boolean inclusive) throws Throwable{
428         try {
429             return InvokerHelper.createRange(from,to,inclusive);
430         } catch (GroovyRuntimeException gre) {
431             return (List) unwrap(gre);
432         }
433     }
434     
435     public static void assertFailed(Object expression, Object message) {
436         InvokerHelper.assertFailed(expression,message);
437     }
438     
439     public static Object box(boolean value) {
440         return value ? Boolean.TRUE : Boolean.FALSE;
441     }
442 
443     public static Object box(byte value) {
444         return new Byte(value);
445     }
446 
447     public static Object box(char value) {
448         return new Character(value);
449     }
450 
451     public static Object box(short value) {
452         return new Short(value);
453     }
454 
455     public static Object box(int value) {
456         return integerValue(value);
457     }
458 
459     public static Object box(long value) {
460         return new Long(value);
461     }
462 
463     public static Object box(float value) {
464         return new Float(value);
465     }
466 
467     public static Object box(double value) {
468         return new Double(value);
469     }
470     
471     /***
472      * get the Integer object from an int. Cached version is used for small ints.
473      *
474      * @param v
475      * @return
476      */
477     public static Integer integerValue(int v) {
478         return InvokerHelper.integerValue(v);
479     }    
480 
481     public static byte byteUnbox(Object value) throws Throwable {
482         Number n = (Number) asType(value, Byte.class);
483         return n.byteValue();
484     }
485 
486     public static char charUnbox(Object value) throws Throwable {
487         Character n = (Character) asType(value, Character.class);
488         return n.charValue();
489     }
490 
491     public static short shortUnbox(Object value) throws Throwable {
492         Number n = (Number) asType(value, Short.class);
493         return n.shortValue();
494     }
495 
496     public static int intUnbox(Object value) throws Throwable {
497         Number n = (Number) asType(value, Integer.class);
498         return n.intValue();
499     }
500 
501     public static boolean booleanUnbox(Object value) throws Throwable {
502         Boolean n = (Boolean) asType(value, Boolean.class);
503         return n.booleanValue();
504     }
505 
506     public static long longUnbox(Object value) throws Throwable {
507         Number n = (Number) asType(value, Long.class);
508         return n.longValue();
509     }
510 
511     public static float floatUnbox(Object value) throws Throwable {
512         Number n = (Number) asType(value, Float.class);
513         return n.floatValue();
514     }
515 
516     public static double doubleUnbox(Object value) throws Throwable {
517         Number n = (Number) asType(value, Double.class);
518         return n.doubleValue();
519     }    
520     
521     public static MetaClass getMetaClass(Object object) {
522         return InvokerHelper.getMetaClass(object);
523     }
524 
525     /*
526     public static void removeClass(Class clazz) {
527         getInstance().removeMetaClass(clazz);
528         Introspector.flushFromCaches(clazz);
529     }
530 
531     public static Invoker getInstance() {
532         return singleton;
533     }
534 
535     public static Collection asCollection(Object collection) {
536         return getInstance().asCollection(collection);
537     }
538 
539     public static List asList(Object args) {
540         return getInstance().asList(args);
541     }
542 
543     public static String toString(Object arguments) {
544         return getInstance().toString(arguments);
545     }
546 
547     public static String toTypeString(Object[] arguments) {
548         return getInstance().toTypeString(arguments);
549     }
550 
551     public static String inspect(Object self) {
552         return getInstance().inspect(self);
553     }
554 
555 
556 
557     public static Object runScript(Class scriptClass, String[] args) {
558         Binding context = new Binding(args);
559         Script script = createScript(scriptClass, context);
560         return invokeMethod(script, "run", EMPTY_ARGS);
561     }
562 
563     public static Script createScript(Class scriptClass, Binding context) {
564         try {
565             final GroovyObject object = (GroovyObject) scriptClass.newInstance();
566             Script script = null;
567             if (object instanceof Script) {
568                 script = (Script) object;
569             } else {
570                 // it could just be a class, so lets wrap it in a Script wrapper
571                 // though the bindings will be ignored
572                 script = new Script() {
573                     public Object run() {
574                         object.invokeMethod("main", EMPTY_MAIN_ARGS);
575                         return null;
576                     }
577                 };
578                 setProperties(object, context.getVariables());
579             }
580             script.setBinding(context);
581             return script;
582         } catch (Exception e) {
583             throw new GroovyRuntimeException("Failed to create Script instance for class: " + scriptClass + ". Reason: " + e,
584                     e);
585         }
586     }
587 */
588     
589     /***
590      * Sets the properties on the given object
591      *
592      * @param object
593      * @param map
594      */
595 /*    public static void setProperties(Object object, Map map) {
596         getMetaClass(object).setProperties(object, map);
597     }
598 
599     public static String getVersion() {
600         String version = null;
601         Package p = Package.getPackage("groovy.lang");
602         if (p != null) {
603             version = p.getImplementationVersion();
604         }
605         if (version == null) {
606             version = "";
607         }
608         return version;
609     }*/
610 
611     /***
612      * Allows conversion of arrays into a mutable List
613      *
614      * @return the array as a List
615      */
616     /*protected static List primitiveArrayToList(Object array) {
617         int size = Array.getLength(array);
618         List list = new ArrayList(size);
619         for (int i = 0; i < size; i++) {
620             list.add(Array.get(array, i));
621         }
622         return list;
623     }*/
624 
625     /***
626      * Writes the given object to the given stream
627      */
628 /*    public static void write(Writer out, Object object) throws IOException {
629         if (object instanceof String) {
630             out.write((String) object);
631         } else if (object instanceof Writable) {
632             Writable writable = (Writable) object;
633             writable.writeTo(out);
634         } else if (object instanceof InputStream || object instanceof Reader) {
635             // Copy stream to stream
636             Reader reader;
637             if (object instanceof InputStream) {
638                 reader = new InputStreamReader((InputStream) object);
639             } else {
640                 reader = (Reader) object;
641             }
642             char[] chars = new char[8192];
643             int i;
644             while ((i = reader.read(chars)) != -1) {
645                 out.write(chars, 0, i);
646             }
647             reader.close();
648         } else {
649             out.write(toString(object));
650         }
651     }
652 
653     public static int[] convertToIntArray(Object a) {
654         int[] ans = null;
655 
656         // conservative coding
657         if (a.getClass().getName().equals("[I")) {
658             ans = (int[]) a;
659         } else {
660             Object[] ia = (Object[]) a;
661             ans = new int[ia.length];
662             for (int i = 0; i < ia.length; i++) {
663                 ans[i] = ((Number) ia[i]).intValue();
664             }
665         }
666         return ans;
667     }
668 
669     public static boolean[] convertToBooleanArray(Object a) {
670         boolean[] ans = null;
671 
672         // conservative coding
673         if (a.getClass().getName().equals("[Z")) {
674             ans = (boolean[]) a;
675         } else {
676             Object[] ia = (Object[]) a;
677             ans = new boolean[ia.length];
678             for (int i = 0; i < ia.length; i++) {
679                 ans[i] = ((Boolean) ia[i]).booleanValue();
680             }
681         }
682         return ans;
683     }
684 
685     public static byte[] convertToByteArray(Object a) {
686         byte[] ans = null;
687 
688         // conservative coding
689         if (a.getClass().getName().equals("[B")) {
690             ans = (byte[]) a;
691         } else {
692             Object[] ia = (Object[]) a;
693             ans = new byte[ia.length];
694             for (int i = 0; i < ia.length; i++) {
695                 if (ia[i] != null)
696                     ans[i] = ((Number) ia[i]).byteValue();
697             }
698         }
699         return ans;
700     }
701 
702     public static short[] convertToShortArray(Object a) {
703         short[] ans = null;
704 
705         // conservative coding
706         if (a.getClass().getName().equals("[S")) {
707             ans = (short[]) a;
708         } else {
709             Object[] ia = (Object[]) a;
710             ans = new short[ia.length];
711             for (int i = 0; i < ia.length; i++) {
712                 ans[i] = ((Number) ia[i]).shortValue();
713             }
714         }
715         return ans;
716     }
717 
718     public static char[] convertToCharArray(Object a) {
719         char[] ans = null;
720 
721         // conservative coding
722         if (a.getClass().getName().equals("[C")) {
723             ans = (char[]) a;
724         } else {
725             Object[] ia = (Object[]) a;
726             ans = new char[ia.length];
727             for (int i = 0; i < ia.length; i++) {
728                 ans[i] = ((Character) ia[i]).charValue();
729             }
730         }
731         return ans;
732     }
733 
734     public static long[] convertToLongArray(Object a) {
735         long[] ans = null;
736 
737         // conservative coding
738         if (a.getClass().getName().equals("[J")) {
739             ans = (long[]) a;
740         } else {
741             Object[] ia = (Object[]) a;
742             ans = new long[ia.length];
743             for (int i = 0; i < ia.length; i++) {
744                 ans[i] = ((Number) ia[i]).longValue();
745             }
746         }
747         return ans;
748     }
749 
750     public static float[] convertToFloatArray(Object a) {
751         float[] ans = null;
752 
753         // conservative coding
754         if (a.getClass().getName().equals("[F")) {
755             ans = (float[]) a;
756         } else {
757             Object[] ia = (Object[]) a;
758             ans = new float[ia.length];
759             for (int i = 0; i < ia.length; i++) {
760                 ans[i] = ((Number) ia[i]).floatValue();
761             }
762         }
763         return ans;
764     }
765 
766     public static double[] convertToDoubleArray(Object a) {
767         double[] ans = null;
768 
769         // conservative coding
770         if (a.getClass().getName().equals("[D")) {
771             ans = (double[]) a;
772         } else {
773             Object[] ia = (Object[]) a;
774             ans = new double[ia.length];
775             for (int i = 0; i < ia.length; i++) {
776                 ans[i] = ((Number) ia[i]).doubleValue();
777             }
778         }
779         return ans;
780     }
781 */
782     
783     /*
784 
785     private static Integer[] SMALL_INTEGERS;
786     private static int INT_CACHE_OFFSET = 128, INT_CACHE_LEN = 256;
787 
788     static {
789         SMALL_INTEGERS = new Integer[INT_CACHE_LEN];
790         for (int i = 0; i < SMALL_INTEGERS.length; i++) {
791             SMALL_INTEGERS[i] = new Integer(i - INT_CACHE_OFFSET);
792         }
793     }*/
794 }