View Javadoc

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