View Javadoc

1   /*
2    $Id: InvokerHelper.java,v 1.73 2005/10/03 18:07:36 tug 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.beans.Introspector;
51  import java.io.IOException;
52  import java.io.InputStream;
53  import java.io.InputStreamReader;
54  import java.io.Reader;
55  import java.io.Writer;
56  import java.lang.reflect.Array;
57  import java.math.BigDecimal;
58  import java.math.BigInteger;
59  import java.util.ArrayList;
60  import java.util.Collection;
61  import java.util.HashMap;
62  import java.util.Iterator;
63  import java.util.List;
64  import java.util.Map;
65  import java.util.regex.Matcher;
66  import java.util.regex.Pattern;
67  
68  /***
69   * A static helper class to make bytecode generation easier and act as a facade over the Invoker
70   *
71   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
72   * @version $Revision: 1.73 $
73   */
74  public class InvokerHelper {
75      public static final Object[] EMPTY_ARGS = {
76      };
77  
78      private static final Object[] EMPTY_MAIN_ARGS = new Object[]{new String[0]};
79  
80      private static final Invoker singleton = new Invoker();
81  
82      private static final Integer ZERO = new Integer(0);
83      private static final Integer MINUS_ONE = new Integer(-1);
84      private static final Integer ONE = new Integer(1);
85  
86      public static MetaClass getMetaClass(Object object) {
87          return getInstance().getMetaClass(object);
88      }
89  
90      public static void removeClass(Class clazz) {
91          getInstance().removeMetaClass(clazz);
92          Introspector.flushFromCaches(clazz);
93      }
94  
95      public static Invoker getInstance() {
96          return singleton;
97      }
98  
99      public static Object invokeNoArgumentsMethod(Object object, String methodName) {
100         return getInstance().invokeMethod(object, methodName, EMPTY_ARGS);
101     }
102 
103     public static Object invokeMethod(Object object, String methodName, Object arguments) {
104         return getInstance().invokeMethod(object, methodName, arguments);
105     }
106 
107     public static Object invokeSuperMethod(Object object, String methodName, Object arguments) {
108         return getInstance().invokeSuperMethod(object, methodName, arguments);
109     }
110 
111     public static Object invokeMethodSafe(Object object, String methodName, Object arguments) {
112         if (object != null) {
113             return getInstance().invokeMethod(object, methodName, arguments);
114         }
115         return null;
116     }
117 
118     public static Object invokeStaticMethod(String type, String methodName, Object arguments) {
119         return getInstance().invokeStaticMethod(type, methodName, arguments);
120     }
121 
122     public static Object invokeStaticNoArgumentsMethod(String type, String methodName) {
123         return getInstance().invokeStaticMethod(type, methodName, EMPTY_ARGS);
124     }
125 
126     public static Object invokeConstructorAt(Class at, Class type, Object arguments) {
127         return getInstance().invokeConstructorAt(at, type, arguments);
128     }
129 
130     public static Object invokeConstructorAt(Class at, String type, Object arguments) {
131         return getInstance().invokeConstructorAt(at, type, arguments);
132     }
133 
134     public static Object invokeNoArgumentsConstructorAt(Class at, Class type) {
135         return getInstance().invokeConstructorAt(at, type, EMPTY_ARGS);
136     }
137 
138     public static Object invokeConstructorOf(String type, Object arguments) {
139         return getInstance().invokeConstructorOf(type, arguments);
140     }
141 
142     public static Object invokeConstructorOf(Class type, Object arguments) {
143         return getInstance().invokeConstructorOf(type, arguments);
144     }
145 
146     public static Object invokeNoArgumentsConstructorOf(Class type) {
147         return getInstance().invokeConstructorOf(type, EMPTY_ARGS);
148     }
149 
150     public static Object invokeClosure(Object closure, Object arguments) {
151         return getInstance().invokeMethod(closure, "doCall", arguments);
152     }
153 
154     public static Iterator asIterator(Object collection) {
155         return getInstance().asIterator(collection);
156     }
157 
158     public static Collection asCollection(Object collection) {
159         return getInstance().asCollection(collection);
160     }
161 
162     public static List asList(Object args) {
163         return getInstance().asList(args);
164     }
165 
166     public static String toString(Object arguments) {
167         if (arguments instanceof Object[])
168             return getInstance().toArrayString((Object[])arguments);
169         else if (arguments instanceof Collection)
170             return getInstance().toListString((Collection)arguments);
171         else if (arguments instanceof Map)
172             return getInstance().toMapString((Map)arguments);
173         else
174             return getInstance().toString(arguments);
175     }
176 
177     public static String toTypeString(Object[] arguments) {
178         return getInstance().toTypeString(arguments);
179     }
180 
181     public static String toMapString(Map arg) {
182         return getInstance().toMapString(arg);
183     }
184 
185     public static String toListString(Collection arg) {
186         return getInstance().toListString(arg);
187     }
188 
189     public static String toArrayString(Object[] arguments) {
190         return getInstance().toArrayString(arguments);
191     }
192 
193     public static String inspect(Object self) {
194         return getInstance().inspect(self);
195     }
196 
197     public static Object getAttribute(Object object, String attribute) {
198         return getInstance().getAttribute(object, attribute);
199     }
200 
201     public static void setAttribute(Object object, String attribute, Object newValue) {
202         getInstance().setAttribute(object, attribute, newValue);
203     }
204 
205     public static Object getProperty(Object object, String property) {
206         return getInstance().getProperty(object, property);
207     }
208 
209     public static Object getPropertySafe(Object object, String property) {
210         if (object != null) {
211             return getInstance().getProperty(object, property);
212         }
213         return null;
214     }
215 
216     public static void setProperty(Object object, String property, Object newValue) {
217         getInstance().setProperty(object, property, newValue);
218     }
219 
220     /***
221      * This is so we don't have to reorder the stack when we call this method.
222      * At some point a better name might be in order.
223      */
224     public static void setProperty2(Object newValue, Object object, String property) {
225         getInstance().setProperty(object, property, newValue);
226     }
227 
228 
229     /***
230      * This is so we don't have to reorder the stack when we call this method.
231      * At some point a better name might be in order.
232      */
233     public static void setGroovyObjectProperty(Object newValue, GroovyObject object, String property) {
234         object.setProperty(property, newValue);
235     }
236 
237     public static Object getGroovyObjectProperty(GroovyObject object, String property) {
238         return object.getProperty(property);
239     }
240 
241 
242     /***
243      * This is so we don't have to reorder the stack when we call this method.
244      * At some point a better name might be in order.
245      */
246     public static void setPropertySafe2(Object newValue, Object object, String property) {
247         if (object != null) {
248             setProperty2(newValue, object, property);
249         }
250     }
251 
252     /***
253      * Returns the method pointer for the given object name
254      */
255     public static Closure getMethodPointer(Object object, String methodName) {
256         return getInstance().getMethodPointer(object, methodName);
257     }
258 
259     /***
260      * Provides a hook for type coercion of the given object to the required type
261      *
262      * @param type   of object to convert the given object to
263      * @param object the object to be converted
264      * @return the original object or a new converted value
265      */
266     public static Object asType(Object object, Class type) {
267         return getInstance().asType(object, type);
268     }
269 
270     public static boolean asBool(Object object) {
271         return getInstance().asBool(object);
272     }
273 
274     public static boolean notObject(Object object) {
275         return !asBool(object);
276     }
277 
278     public static boolean notBoolean(boolean bool) {
279         return !bool;
280     }
281 
282     public static Object negate(Object value) {
283         if (value instanceof Integer) {
284             Integer number = (Integer) value;
285             return integerValue(-number.intValue());
286         }
287         else if (value instanceof Long) {
288             Long number = (Long) value;
289             return new Long(-number.longValue());
290         }
291         else if (value instanceof BigInteger) {
292             return ((BigInteger) value).negate();
293         }
294         else if (value instanceof BigDecimal) {
295             return ((BigDecimal) value).negate();
296         }
297         else if (value instanceof Double) {
298             Double number = (Double) value;
299             return new Double(-number.doubleValue());
300         }
301         else if (value instanceof Float) {
302             Float number = (Float) value;
303             return new Float(-number.floatValue());
304         }
305         else if (value instanceof ArrayList) {
306             // value is an list.
307             ArrayList newlist = new ArrayList();
308             Iterator it = ((ArrayList) value).iterator();
309             for (; it.hasNext();) {
310                 newlist.add(negate(it.next()));
311             }
312             return newlist;
313         }
314         else {
315             throw new GroovyRuntimeException("Cannot negate type " + value.getClass().getName() + ", value " + value);
316         }
317     }
318 
319     public static Object bitNegate(Object value) {
320         if (value instanceof Integer) {
321             Integer number = (Integer) value;
322             return integerValue(~number.intValue());
323         }
324         else if (value instanceof Long) {
325             Long number = (Long) value;
326             return new Long(~number.longValue());
327         }
328         else if (value instanceof BigInteger) {
329             return ((BigInteger) value).not();
330         }
331         else if (value instanceof String) {
332             // value is a regular expression.
333             return getInstance().regexPattern(value);
334         }
335         else if (value instanceof GString) {
336             // value is a regular expression.
337             return getInstance().regexPattern(value.toString());
338         }
339         else if (value instanceof ArrayList) {
340             // value is an list.
341             ArrayList newlist = new ArrayList();
342             Iterator it = ((ArrayList) value).iterator();
343             for (; it.hasNext();) {
344                 newlist.add(bitNegate(it.next()));
345             }
346             return newlist;
347         }
348         else {
349             throw new BitwiseNegateEvaluatingException("Cannot bitwise negate type " + value.getClass().getName() + ", value " + value);
350         }
351     }
352 
353     public static boolean isCase(Object switchValue, Object caseExpression) {
354         return asBool(invokeMethod(caseExpression, "isCase", new Object[]{switchValue}));
355     }
356 
357     public static boolean compareIdentical(Object left, Object right) {
358         return left == right;
359     }
360 
361     public static boolean compareEqual(Object left, Object right) {
362         return getInstance().objectsEqual(left, right);
363     }
364 
365     public static Matcher findRegex(Object left, Object right) {
366         return getInstance().objectFindRegex(left, right);
367     }
368 
369     public static boolean matchRegex(Object left, Object right) {
370         return getInstance().objectMatchRegex(left, right);
371     }
372 
373     public static Pattern regexPattern(Object regex) {
374         return getInstance().regexPattern(regex);
375     }
376 
377     public static boolean compareNotEqual(Object left, Object right) {
378         return !getInstance().objectsEqual(left, right);
379     }
380 
381     public static boolean compareLessThan(Object left, Object right) {
382         return getInstance().compareTo(left, right) < 0;
383     }
384 
385     public static boolean compareLessThanEqual(Object left, Object right) {
386         return getInstance().compareTo(left, right) <= 0;
387     }
388 
389     public static boolean compareGreaterThan(Object left, Object right) {
390         return getInstance().compareTo(left, right) > 0;
391     }
392 
393     public static boolean compareGreaterThanEqual(Object left, Object right) {
394         return getInstance().compareTo(left, right) >= 0;
395     }
396 
397     public static Integer compareTo(Object left, Object right) {
398         int answer = getInstance().compareTo(left, right);
399         if (answer == 0) {
400             return ZERO;
401         }
402         else {
403             return answer > 0 ? ONE : MINUS_ONE;
404         }
405     }
406 
407     public static Tuple createTuple(Object[] array) {
408         return new Tuple(array);
409     }
410 
411     public static SpreadList spreadList(Object value) {
412         if (value instanceof List) {
413             // value is a list.
414             Object[] values = new Object[((List) value).size()];
415             int index = 0;
416             Iterator it = ((List) value).iterator();
417             for (; it.hasNext();) {
418                 values[index++] = it.next();
419             }
420             return new SpreadList(values);
421         }
422         else {
423             throw new SpreadListEvaluatingException("Cannot spread the type " + value.getClass().getName() + ", value " + value);
424         }
425     }
426 
427     public static SpreadMap spreadMap(Object value) {
428         if (value instanceof Map) {
429             Object[] values = new Object[((Map) value).keySet().size() * 2];
430             int index = 0;
431             Iterator it = ((Map) value).keySet().iterator();
432             for (; it.hasNext();) {
433                 Object key = it.next();
434                 values[index++] = key;
435                 values[index++] = ((Map) value).get(key);
436             }
437             return new SpreadMap(values);
438         }
439         else {
440             throw new SpreadMapEvaluatingException("Cannot spread the map " + value.getClass().getName() + ", value " + value);
441         }
442     }
443 
444     public static List createList(Object[] values) {
445         ArrayList answer = new ArrayList(values.length);
446         for (int i = 0; i < values.length; i++) {
447             if (values[i] instanceof SpreadList) {
448                 SpreadList slist = (SpreadList) values[i];
449                 for (int j = 0; j < slist.size(); j++) {
450                     answer.add(slist.get(j));
451                 }
452             }
453             else {
454                 answer.add(values[i]);
455             }
456         }
457         return answer;
458     }
459 
460     public static Map createMap(Object[] values) {
461         Map answer = new HashMap(values.length / 2);
462         int i = 0;
463         while (i < values.length - 1) {
464             if ((values[i] instanceof SpreadMap) && (values[i+1] instanceof Map)) {
465                 Map smap = (Map) values[i+1];
466                 Iterator iter = smap.keySet().iterator();
467                 for (; iter.hasNext(); ) {
468                     Object key = (Object) iter.next();
469                     answer.put(key, smap.get(key));
470                 }
471                 i+=2;
472             }
473             else {
474                 answer.put(values[i++], values[i++]);
475             }
476         }
477         return answer;
478     }
479 
480     public static List createRange(Object from, Object to, boolean inclusive) {
481         if (!inclusive) {
482             if (compareEqual(from,to)){
483                 return new EmptyRange((Comparable)from);
484             }
485             if (compareGreaterThan(from, to)) {
486                 to = invokeMethod(to, "next", EMPTY_ARGS);
487             }
488             else {
489                 to = invokeMethod(to, "previous", EMPTY_ARGS);
490             }
491         }
492         if (from instanceof Integer && to instanceof Integer) {
493             return new IntRange(asInt(from), asInt(to));
494         }
495         else {
496             return new ObjectRange((Comparable) from, (Comparable) to);
497         }
498     }
499 
500     public static int asInt(Object value) {
501         return getInstance().asInt(value);
502     }
503 
504     public static void assertFailed(Object expression, Object message) {
505         if (message == null || "".equals(message)) {
506             throw new AssertionError("Expression: " + expression);
507         }
508         else {
509             throw new AssertionError("" + message + ". Expression: " + expression);
510         }
511     }
512 
513     public static Object runScript(Class scriptClass, String[] args) {
514         Binding context = new Binding(args);
515         Script script = createScript(scriptClass, context);
516         return invokeMethod(script, "run", EMPTY_ARGS);
517     }
518 
519     public static Script createScript(Class scriptClass, Binding context) {
520         // for empty scripts
521         if (scriptClass == null) {
522             return new Script() {
523                 public Object run() {
524                     return null;
525                 }
526             };
527         }
528         try {
529             final GroovyObject object = (GroovyObject) scriptClass.newInstance();
530             Script script = null;
531             if (object instanceof Script) {
532                 script = (Script) object;
533             }
534             else {
535                 // it could just be a class, so lets wrap it in a Script wrapper
536                 // though the bindings will be ignored
537                 script = new Script() {
538                     public Object run() {
539                         object.invokeMethod("main", EMPTY_MAIN_ARGS);
540                         return null;
541                     }
542                 };
543                 setProperties(object, context.getVariables());
544             }
545             script.setBinding(context);
546             return script;
547         }
548         catch (Exception e) {
549             throw new GroovyRuntimeException("Failed to create Script instance for class: " + scriptClass + ". Reason: " + e,
550                     e);
551         }
552     }
553 
554     /***
555      * Sets the properties on the given object
556      *
557      * @param object
558      * @param map
559      */
560     public static void setProperties(Object object, Map map) {
561         getMetaClass(object).setProperties(object, map);
562     }
563 
564     public static String getVersion() {
565         String version = null;
566         Package p = Package.getPackage("groovy.lang");
567         if (p != null) {
568             version = p.getImplementationVersion();
569         }
570         if (version == null) {
571             version = "";
572         }
573         return version;
574     }
575 
576     /***
577      * Allows conversion of arrays into a mutable List
578      *
579      * @return the array as a List
580      */
581     protected static List primitiveArrayToList(Object array) {
582         int size = Array.getLength(array);
583         List list = new ArrayList(size);
584         for (int i = 0; i < size; i++) {
585             list.add(Array.get(array, i));
586         }
587         return list;
588     }
589 
590     /***
591      * Writes the given object to the given stream
592      */
593     public static void write(Writer out, Object object) throws IOException {
594         if (object instanceof String) {
595             out.write((String) object);
596         }
597         else if (object instanceof Object[]) {
598             out.write(toArrayString((Object[]) object));
599         }
600         else if (object instanceof Map) {
601             out.write(toMapString((Map) object));
602         }
603         else if (object instanceof Collection) {
604             out.write(toListString((Collection) object));
605         }
606         else if (object instanceof Writable) {
607             Writable writable = (Writable) object;
608             writable.writeTo(out);
609         }
610         else if (object instanceof InputStream || object instanceof Reader) {
611             // Copy stream to stream
612             Reader reader;
613             if (object instanceof InputStream) {
614                 reader = new InputStreamReader((InputStream) object);
615             }
616             else {
617                 reader = (Reader) object;
618             }
619             char[] chars = new char[8192];
620             int i;
621             while ((i = reader.read(chars)) != -1) {
622                 out.write(chars, 0, i);
623             }
624             reader.close();
625         }
626         else {
627             out.write(toString(object));
628         }
629     }
630 
631     public static Object box(boolean value) {
632         return value ? Boolean.TRUE : Boolean.FALSE;
633     }
634 
635     public static Object box(byte value) {
636         return new Byte(value);
637     }
638 
639     public static Object box(char value) {
640         return new Character(value);
641     }
642 
643     public static Object box(short value) {
644         return new Short(value);
645     }
646 
647     public static Object box(int value) {
648         return integerValue(value);
649     }
650 
651     public static Object box(long value) {
652         return new Long(value);
653     }
654 
655     public static Object box(float value) {
656         return new Float(value);
657     }
658 
659     public static Object box(double value) {
660         return new Double(value);
661     }
662 
663     public static byte byteUnbox(Object value) {
664         Number n = (Number) asType(value, Byte.class);
665         return n.byteValue();
666     }
667 
668     public static char charUnbox(Object value) {
669         Character n = (Character) asType(value, Character.class);
670         return n.charValue();
671     }
672 
673     public static short shortUnbox(Object value) {
674         Number n = (Number) asType(value, Short.class);
675         return n.shortValue();
676     }
677 
678     public static int intUnbox(Object value) {
679         Number n = (Number) asType(value, Integer.class);
680         return n.intValue();
681     }
682 
683     public static boolean booleanUnbox(Object value) {
684         Boolean n = (Boolean) asType(value, Boolean.class);
685         return n.booleanValue();
686     }
687 
688     public static long longUnbox(Object value) {
689         Number n = (Number) asType(value, Long.class);
690         return n.longValue();
691     }
692 
693     public static float floatUnbox(Object value) {
694         Number n = (Number) asType(value, Float.class);
695         return n.floatValue();
696     }
697 
698     public static double doubleUnbox(Object value) {
699         Number n = (Number) asType(value, Double.class);
700         return n.doubleValue();
701     }
702 
703     /***
704      * @param a    array of primitives
705      * @param type component type of the array
706      * @return
707      */
708     public static Object[] convertPrimitiveArray(Object a, Class type) {
709 //        System.out.println("a.getClass() = " + a.getClass());
710         Object[] ans = null;
711         String elemType = type.getName();
712         if (elemType.equals("int")) {
713             // conservative coding
714             if (a.getClass().getName().equals("[Ljava.lang.Integer;")) {
715                 ans = (Integer[]) a;
716             }
717             else {
718                 int[] ia = (int[]) a;
719                 ans = new Integer[ia.length];
720                 for (int i = 0; i < ia.length; i++) {
721                     int e = ia[i];
722                     ans[i] = integerValue(e);
723                 }
724             }
725         }
726         else if (elemType.equals("char")) {
727             if (a.getClass().getName().equals("[Ljava.lang.Character;")) {
728                 ans = (Character[]) a;
729             }
730             else {
731                 char[] ia = (char[]) a;
732                 ans = new Character[ia.length];
733                 for (int i = 0; i < ia.length; i++) {
734                     char e = ia[i];
735                     ans[i] = new Character(e);
736                 }
737             }
738         }
739         else if (elemType.equals("boolean")) {
740             if (a.getClass().getName().equals("[Ljava.lang.Boolean;")) {
741                 ans = (Boolean[]) a;
742             }
743             else {
744                 boolean[] ia = (boolean[]) a;
745                 ans = new Boolean[ia.length];
746                 for (int i = 0; i < ia.length; i++) {
747                     boolean e = ia[i];
748                     ans[i] = new Boolean(e);
749                 }
750             }
751         }
752         else if (elemType.equals("byte")) {
753             if (a.getClass().getName().equals("[Ljava.lang.Byte;")) {
754                 ans = (Byte[]) a;
755             }
756             else {
757                 byte[] ia = (byte[]) a;
758                 ans = new Byte[ia.length];
759                 for (int i = 0; i < ia.length; i++) {
760                     byte e = ia[i];
761                     ans[i] = new Byte(e);
762                 }
763             }
764         }
765         else if (elemType.equals("short")) {
766             if (a.getClass().getName().equals("[Ljava.lang.Short;")) {
767                 ans = (Short[]) a;
768             }
769             else {
770                 short[] ia = (short[]) a;
771                 ans = new Short[ia.length];
772                 for (int i = 0; i < ia.length; i++) {
773                     short e = ia[i];
774                     ans[i] = new Short(e);
775                 }
776             }
777         }
778         else if (elemType.equals("float")) {
779             if (a.getClass().getName().equals("[Ljava.lang.Float;")) {
780                 ans = (Float[]) a;
781             }
782             else {
783                 float[] ia = (float[]) a;
784                 ans = new Float[ia.length];
785                 for (int i = 0; i < ia.length; i++) {
786                     float e = ia[i];
787                     ans[i] = new Float(e);
788                 }
789             }
790         }
791         else if (elemType.equals("long")) {
792             if (a.getClass().getName().equals("[Ljava.lang.Long;")) {
793                 ans = (Long[]) a;
794             }
795             else {
796                 long[] ia = (long[]) a;
797                 ans = new Long[ia.length];
798                 for (int i = 0; i < ia.length; i++) {
799                     long e = ia[i];
800                     ans[i] = new Long(e);
801                 }
802             }
803         }
804         else if (elemType.equals("double")) {
805             if (a.getClass().getName().equals("[Ljava.lang.Double;")) {
806                 ans = (Double[]) a;
807             }
808             else {
809                 double[] ia = (double[]) a;
810                 ans = new Double[ia.length];
811                 for (int i = 0; i < ia.length; i++) {
812                     double e = ia[i];
813                     ans[i] = new Double(e);
814                 }
815             }
816         }
817         return ans;
818     }
819 
820     public static int[] convertToIntArray(Object a) {
821         int[] ans = null;
822 
823         // conservative coding
824         if (a.getClass().getName().equals("[I")) {
825             ans = (int[]) a;
826         }
827         else {
828             Object[] ia = (Object[]) a;
829             ans = new int[ia.length];
830             for (int i = 0; i < ia.length; i++) {
831                 if (ia[i] == null) {
832                     continue;
833                 }
834                 ans[i] = ((Number) ia[i]).intValue();
835             }
836         }
837         return ans;
838     }
839 
840     public static boolean[] convertToBooleanArray(Object a) {
841         boolean[] ans = null;
842 
843         // conservative coding
844         if (a.getClass().getName().equals("[Z")) {
845             ans = (boolean[]) a;
846         }
847         else {
848             Object[] ia = (Object[]) a;
849             ans = new boolean[ia.length];
850             for (int i = 0; i < ia.length; i++) {
851                 if (ia[i] == null) {
852                     continue;
853                 }
854                 ans[i] = ((Boolean) ia[i]).booleanValue();
855             }
856         }
857         return ans;
858     }
859 
860     public static byte[] convertToByteArray(Object a) {
861         byte[] ans = null;
862 
863         // conservative coding
864         if (a.getClass().getName().equals("[B")) {
865             ans = (byte[]) a;
866         }
867         else {
868             Object[] ia = (Object[]) a;
869             ans = new byte[ia.length];
870             for (int i = 0; i < ia.length; i++) {
871                 if (ia[i] != null) {
872                     ans[i] = ((Number) ia[i]).byteValue();
873                 }
874             }
875         }
876         return ans;
877     }
878 
879     public static short[] convertToShortArray(Object a) {
880         short[] ans = null;
881 
882         // conservative coding
883         if (a.getClass().getName().equals("[S")) {
884             ans = (short[]) a;
885         }
886         else {
887             Object[] ia = (Object[]) a;
888             ans = new short[ia.length];
889             for (int i = 0; i < ia.length; i++) {
890                 ans[i] = ((Number) ia[i]).shortValue();
891             }
892         }
893         return ans;
894     }
895 
896     public static char[] convertToCharArray(Object a) {
897         char[] ans = null;
898 
899         // conservative coding
900         if (a.getClass().getName().equals("[C")) {
901             ans = (char[]) a;
902         }
903         else {
904             Object[] ia = (Object[]) a;
905             ans = new char[ia.length];
906             for (int i = 0; i < ia.length; i++) {
907                 if (ia[i] == null) {
908                     continue;
909                 }
910                 ans[i] = ((Character) ia[i]).charValue();
911             }
912         }
913         return ans;
914     }
915 
916     public static long[] convertToLongArray(Object a) {
917         long[] ans = null;
918 
919         // conservative coding
920         if (a.getClass().getName().equals("[J")) {
921             ans = (long[]) a;
922         }
923         else {
924             Object[] ia = (Object[]) a;
925             ans = new long[ia.length];
926             for (int i = 0; i < ia.length; i++) {
927                 if (ia[i] == null) {
928                     continue;
929                 }
930                 ans[i] = ((Number) ia[i]).longValue();
931             }
932         }
933         return ans;
934     }
935 
936     public static float[] convertToFloatArray(Object a) {
937         float[] ans = null;
938 
939         // conservative coding
940         if (a.getClass().getName().equals("[F")) {
941             ans = (float[]) a;
942         }
943         else {
944             Object[] ia = (Object[]) a;
945             ans = new float[ia.length];
946             for (int i = 0; i < ia.length; i++) {
947                 if (ia[i] == null) {
948                     continue;
949                 }
950                 ans[i] = ((Number) ia[i]).floatValue();
951             }
952         }
953         return ans;
954     }
955 
956     public static double[] convertToDoubleArray(Object a) {
957         double[] ans = null;
958 
959         // conservative coding
960         if (a.getClass().getName().equals("[D")) {
961             ans = (double[]) a;
962         }
963         else {
964             Object[] ia = (Object[]) a;
965             ans = new double[ia.length];
966             for (int i = 0; i < ia.length; i++) {
967                 if (ia[i] == null) {
968                     continue;
969                 }
970                 ans[i] = ((Number) ia[i]).doubleValue();
971             }
972         }
973         return ans;
974     }
975 
976     public static Object convertToPrimitiveArray(Object a, Class type) {
977         if (type == Byte.TYPE) {
978             return convertToByteArray(a);
979         }
980         if (type == Boolean.TYPE) {
981             return convertToBooleanArray(a);
982         }
983         if (type == Short.TYPE) {
984             return convertToShortArray(a);
985         }
986         if (type == Character.TYPE) {
987             return convertToCharArray(a);
988         }
989         if (type == Integer.TYPE) {
990             return convertToIntArray(a);
991         }
992         if (type == Long.TYPE) {
993             return convertToLongArray(a);
994         }
995         if (type == Float.TYPE) {
996             return convertToFloatArray(a);
997         }
998         if (type == Double.TYPE) {
999             return convertToDoubleArray(a);
1000         }
1001         else {
1002             return a;
1003         }
1004     }
1005 
1006     /***
1007      * get the Integer object from an int. Cached version is used for small ints.
1008      *
1009      * @param v
1010      * @return
1011      */
1012     public static Integer integerValue(int v) {
1013         int index = v + INT_CACHE_OFFSET;
1014         if (index >= 0 && index < INT_CACHE_LEN) {
1015             return SMALL_INTEGERS[index];
1016         }
1017         else {
1018             return new Integer(v);
1019         }
1020     }
1021 
1022     private static Integer[] SMALL_INTEGERS;
1023     private static int INT_CACHE_OFFSET = 128, INT_CACHE_LEN = 256;
1024 
1025     static {
1026         SMALL_INTEGERS = new Integer[INT_CACHE_LEN];
1027         for (int i = 0; i < SMALL_INTEGERS.length; i++) {
1028             SMALL_INTEGERS[i] = new Integer(i - INT_CACHE_OFFSET);
1029         }
1030     }
1031 }