View Javadoc

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