2e31fa5e984a0369e82abd2dd3cd42aa5073d38f
[scilab.git] / scilab / modules / external_objects_java / src / java / org / scilab / modules / external_objects_java / ScilabJavaObject.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - 2011 - Calixte DENIZET <calixte@contrib.scilab.org>
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.external_objects_java;
14
15 import java.beans.BeanInfo;
16 import java.beans.IntrospectionException;
17 import java.beans.Introspector;
18 import java.beans.MethodDescriptor;
19 import java.beans.PropertyDescriptor;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.PrintStream;
23 import java.lang.reflect.Array;
24 import java.lang.reflect.Field;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.lang.reflect.Modifier;
28 import java.nio.Buffer;
29 import java.nio.ByteBuffer;
30 import java.nio.ByteOrder;
31 import java.nio.CharBuffer;
32 import java.nio.DoubleBuffer;
33 import java.nio.FloatBuffer;
34 import java.nio.IntBuffer;
35 import java.nio.LongBuffer;
36 import java.nio.ShortBuffer;
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 import java.util.TreeSet;
43 import java.util.logging.FileHandler;
44 import java.util.logging.Level;
45 import java.util.logging.Logger;
46 import java.util.logging.SimpleFormatter;
47
48 /**
49  * Main class to communicate with Scilab via jni interface generated with Giws.
50  * @autor Calixte DENIZET
51  */
52 @SuppressWarnings(value = {"unchecked", "serial"})
53 public class ScilabJavaObject {
54
55     private static final int INITIALCAPACITY = 1024;
56     private static final Map<Class, Integer> unwrappableType = new HashMap<Class, Integer>(51);
57     private static final Map<Class, Integer> listBaseType = new HashMap<Class, Integer>(9);
58     private static final Class[] returnType = new Class[1];
59
60     static final Map<Class, Class> primTypes = new HashMap<Class, Class>(8);
61
62     private static int currentPos = 1;
63     private static FreePlace freePlace = new FreePlace();
64
65     static boolean debug;
66     static Logger logger;
67     static FileHandler handler;
68
69     protected static int currentCapacity = INITIALCAPACITY;
70     protected static ScilabJavaObject[] arraySJO = new ScilabJavaObject[currentCapacity];
71
72     static {
73         primTypes.put(double.class, Double.class);
74         primTypes.put(float.class, Float.class);
75         primTypes.put(int.class, Integer.class);
76         primTypes.put(short.class, Short.class);
77         primTypes.put(byte.class, Byte.class);
78         primTypes.put(char.class, Character.class);
79         primTypes.put(long.class, Long.class);
80         primTypes.put(boolean.class, Boolean.class);
81
82         unwrappableType.put(double.class, 2);
83         unwrappableType.put(double[].class, 3);
84         unwrappableType.put(double[][].class, 4);
85         unwrappableType.put(String.class, 5);
86         unwrappableType.put(String[].class, 6);
87         unwrappableType.put(String[][].class, 7);
88         unwrappableType.put(boolean.class, 8);
89         unwrappableType.put(boolean[].class, 9);
90         unwrappableType.put(boolean[][].class, 10);
91         unwrappableType.put(byte.class, 11);
92         unwrappableType.put(byte[].class, 12);
93         unwrappableType.put(byte[][].class, 13);
94         unwrappableType.put(short.class, 17);
95         unwrappableType.put(short[].class, 18);
96         unwrappableType.put(short[][].class, 19);
97         unwrappableType.put(char.class, 20);
98         unwrappableType.put(char[].class, 21);
99         unwrappableType.put(char[][].class, 22);
100         unwrappableType.put(int.class, 23);
101         unwrappableType.put(int[].class, 24);
102         unwrappableType.put(int[][].class, 25);
103         unwrappableType.put(long.class, 29);
104         unwrappableType.put(long[].class, 30);
105         unwrappableType.put(long[][].class, 31);
106         unwrappableType.put(float.class, 35);
107         unwrappableType.put(float[].class, 36);
108         unwrappableType.put(float[][].class, 37);
109         unwrappableType.put(Double.class, 2);
110         unwrappableType.put(Double[].class, 3);
111         unwrappableType.put(Double[][].class, 4);
112         unwrappableType.put(Integer.class, 23);
113         unwrappableType.put(Integer[].class, 24);
114         unwrappableType.put(Integer[][].class, 25);
115         unwrappableType.put(Long.class, 29);
116         unwrappableType.put(Long[].class, 30);
117         unwrappableType.put(Long[][].class, 31);
118         unwrappableType.put(Byte.class, 11);
119         unwrappableType.put(Byte[].class, 12);
120         unwrappableType.put(Byte[][].class, 13);
121         unwrappableType.put(Character.class, 20);
122         unwrappableType.put(Character[].class, 21);
123         unwrappableType.put(Character[][].class, 22);
124         unwrappableType.put(Boolean.class, 8);
125         unwrappableType.put(Boolean[].class, 9);
126         unwrappableType.put(Boolean[][].class, 10);
127         unwrappableType.put(Float.class, 35);
128         unwrappableType.put(Float[].class, 36);
129         unwrappableType.put(Float[][].class, 37);
130         unwrappableType.put(Short.class, 17);
131         unwrappableType.put(Short[].class, 18);
132         unwrappableType.put(Short[][].class, 19);
133
134         listBaseType.put(Double.class, 3);
135         listBaseType.put(Integer.class, 24);
136         listBaseType.put(Long.class, 30);
137         listBaseType.put(Byte.class, 12);
138         listBaseType.put(Character.class, 21);
139         listBaseType.put(Boolean.class, 9);
140         listBaseType.put(Float.class, 36);
141         listBaseType.put(Short.class, 18);
142         listBaseType.put(String.class, 6);
143
144         arraySJO[0] = new ScilabJavaObject(null, null);
145     }
146
147     protected Object object;
148     protected Class clazz;
149     protected int id;
150
151     /**
152      * Constructor
153      * @param obj the Java Object to wrap
154      */
155     public ScilabJavaObject(Object obj) {
156         this(obj, obj == null ? null : obj.getClass());
157     }
158
159     /**
160      * Constructor
161      * @param obj the Java Object to wrap
162      * @param clazz the Java Object class
163      */
164     public ScilabJavaObject(Object obj, Class clazz) {
165         this.object = obj;
166         this.clazz = clazz;
167
168         if (obj != null) {
169             int fp = freePlace.getFreePlace();
170             if (fp == -1) {
171                 this.id = currentPos;
172                 ++currentPos;
173             } else {
174                 this.id = fp;
175             }
176
177             arraySJO[this.id] = this;
178
179             if (debug) {
180                 logger.log(Level.INFO, "Object creation with id=" + this.id + " and class=" + clazz.toString());
181             }
182
183             if (currentPos >= currentCapacity) {
184                 currentCapacity = currentCapacity * 2;
185                 ScilabJavaObject[] arr = new ScilabJavaObject[currentCapacity];
186                 System.arraycopy(arraySJO, 0, arr, 0, currentPos);
187                 arraySJO = arr;
188                 if (debug) {
189                     logger.log(Level.INFO, "Scope copy");
190                 }
191             }
192         } else {
193             if (debug) {
194                 logger.log(Level.INFO, "Object creation with id=0");
195             }
196             this.id = 0;
197         }
198     }
199
200     /**
201      * Do nothing !
202      */
203     public static final void initScilabJavaObject() { }
204
205     /**
206      * @param filename the log file
207      */
208     public static final void enableTrace(String filename) throws ScilabJavaException {
209         if (debug) {
210             disableTrace();
211         }
212
213         debug = true;
214         logger = Logger.getLogger("JIMS");
215
216         try {
217             handler = new FileHandler(filename, true);
218             logger.addHandler(handler);
219             logger.setLevel(Level.ALL);
220             SimpleFormatter formatter = new SimpleFormatter();
221             handler.setFormatter(formatter);
222         } catch (SecurityException e) {
223             debug = false;
224             throw new ScilabJavaException("A security exception has been thrown:\n" + e);
225         } catch (IOException e) {
226             debug = false;
227             throw new ScilabJavaException("I/O problem:\n" + e);
228         }
229     }
230
231     public static final void writeLog(String s) {
232         if (debug) {
233             logger.log(Level.INFO, s);
234         }
235     }
236
237     /**
238      * Disable trace
239      */
240     public static final void disableTrace() {
241         if (debug && logger != null && handler != null) {
242             logger.removeHandler(handler);
243             handler.flush();
244             handler.close();
245             handler = null;
246             debug = false;
247         }
248     }
249
250     /**
251      * {@inheritedDoc}
252      */
253     public String toString() {
254         if (object == null) {
255             return "null";
256         }
257
258         String str = object.toString();
259         if (str != null) {
260             return str;
261         }
262
263         return "Instance of " + object.getClass() + " with hashcode " + System.identityHashCode(object);
264     }
265
266     /**
267      * Create a new identical reference to a java object
268      * @return A deep copy of this {@link ScilabJavaObject}
269      */
270     @Override
271     protected ScilabJavaObject clone() {
272         return new ScilabJavaObject(object, clazz);
273     }
274
275     /**
276      * Get info as returned by java -version
277      * @return version
278      */
279     public static final String[] getInfos() {
280         try {
281             Class c = Class.forName("sun.misc.Version");
282             Method m = c.getMethod("print", new Class[] { PrintStream.class });
283             ByteArrayOutputStream baos = new ByteArrayOutputStream();
284             PrintStream out = new PrintStream(baos);
285             m.invoke(null, out);
286             out.flush();
287             String[] ret = baos.toString().split("\n");
288             out.close();
289             baos.close();
290
291             return ret;
292         } catch (Exception e) {
293             return null;
294         }
295     }
296
297     /**
298      * @param id the Java Object id
299      * @return the string to represent this object
300      */
301     public static final String getRepresentation(final int id) {
302         if (arraySJO[id] != null) {
303             return arraySJO[id].toString();
304         }
305
306         return "Invalid Java object";
307     }
308
309     /**
310      * @param id the Java Object id
311      * @return true if the object is valid
312      */
313     public static final boolean isValidJavaObject(final int id) {
314         return id == 0 || (id > 0 && arraySJO[id] != null);
315     }
316
317     /**
318      * @param id the Java Object id
319      * @param index an array of index
320      * @return the id of the element at position given by index in id
321      */
322     public static final int getArrayElement(final int id, final int[] index) throws ScilabJavaException {
323         if (id > 0) {
324             if (debug) {
325                 StringBuffer buf = new StringBuffer();
326                 buf.append("(");
327                 if (index.length > 0) {
328                     int i = 0;
329                     for (; i < index.length - 1; i++) {
330                         buf.append(Integer.toString(index[i]));
331                         buf.append(",");
332                     }
333                     buf.append(Integer.toString(index[i]));
334                 }
335                 buf.append(")");
336                 logger.log(Level.INFO, "Get array element: array id=" + id + " at position " + buf.toString());
337             }
338
339             if (arraySJO[id] == null) {
340                 throw new ScilabJavaException("Invalid Java object");
341             }
342
343             return new ScilabJavaObject(ScilabJavaArray.get(arraySJO[id].object, index)).id;
344         }
345         throw new ScilabJavaException("null is not an array");
346     }
347
348     /**
349      * @param id the Java Object id
350      * @param index an array of index
351      * @param idArg the id of an element to put at the position given by index
352      */
353     public static final void setArrayElement(final int id, final int[] index, final int idArg) throws ScilabJavaException {
354         if (id > 0) {
355             if (debug) {
356                 StringBuffer buf = new StringBuffer();
357                 buf.append("(");
358                 if (index.length > 0) {
359                     int i = 0;
360                     for (; i < index.length - 1; i++) {
361                         buf.append(Integer.toString(index[i]));
362                         buf.append(",");
363                     }
364                     buf.append(Integer.toString(index[i]));
365                 }
366                 buf.append(")");
367                 logger.log(Level.INFO, "Set array element: array id=" + id + " at position " + buf.toString() + " and element id=" + idArg);
368             }
369
370             if (arraySJO[id] == null) {
371                 throw new ScilabJavaException("Invalid Java object");
372             }
373
374             ScilabJavaArray.set(arraySJO[id].object, index, arraySJO[idArg].object);
375         } else {
376             throw new ScilabJavaException("null is not an array");
377         }
378     }
379
380     /**
381      * @param id the Java Object id
382      * @return the accessibles methods and fields corresponding to the given path
383      */
384     public static final String[] getCompletion(final int id, final String[] fieldPath) throws ScilabJavaException {
385         if (id > 0) {
386             if (debug) {
387                 logger.log(Level.INFO, "Get accessible methods and fields in object id=" + id + " with path " + Arrays.deepToString(fieldPath));
388             }
389
390             if (arraySJO[id] == null) {
391                 throw new ScilabJavaException("Invalid Java object");
392             }
393
394             Class clazz = arraySJO[id].clazz;
395             final boolean isClass = arraySJO[id].object == clazz;
396
397             if (fieldPath.length == 0) {
398                 return getFieldsAndMethods(clazz, isClass);
399             }
400
401             if (isClass) {
402                 // We have a class object
403                 try {
404                     Field f = clazz.getField(fieldPath[0]);
405                     int modifiers = f.getModifiers();
406                     if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
407                         clazz = f.getType();
408                     } else {
409                         return new String[0];
410                     }
411                 } catch (Exception e) {
412                     return new String[0];
413                 }
414             }
415
416             for (int i = (isClass ? 1 : 0); i < fieldPath.length; i++) {
417                 try {
418                     Field f = clazz.getField(fieldPath[i]);
419                     if (Modifier.isPublic(f.getModifiers())) {
420                         clazz = f.getType();
421                     } else {
422                         return new String[0];
423                     }
424                 } catch (Exception e) {
425                     return new String[0];
426                 }
427             }
428
429             return getFieldsAndMethods(clazz, false);
430         } else {
431             return new String[0];
432         }
433     }
434
435     /**
436      * Get fields and methods in a Class
437      * @param clazz the base class
438      * @return names
439      */
440     private static final String[] getFieldsAndMethods(final Class clazz, final boolean staticOnly) {
441         if (clazz.isArray()) {
442             return new String[] {"length"};
443         }
444
445         try {
446             final Field[] fs = clazz.getFields();
447             final Method[] ms = clazz.getMethods();
448
449             Set<String> set = new TreeSet<String>();
450             for (Field f : fs) {
451                 final int modifiers = f.getModifiers();
452                 if (Modifier.isPublic(modifiers) && (!staticOnly || Modifier.isStatic(modifiers))) {
453                     set.add(f.getName());
454                 }
455             }
456
457             for (Method m : ms) {
458                 final int modifiers = m.getModifiers();
459                 if (Modifier.isPublic(modifiers) && (!staticOnly || Modifier.isStatic(modifiers))) {
460                     set.add(m.getName());
461                 }
462             }
463
464             // Append beans properties (and remove accessor methods)
465             try {
466                 final BeanInfo info = Introspector.getBeanInfo(clazz);
467
468                 final PropertyDescriptor[] properties = info.getPropertyDescriptors();
469                 if (properties != null) {
470                     for (PropertyDescriptor p : properties) {
471                         set.add(p.getName());
472
473                         final Method getter = p.getReadMethod();
474                         final Method setter = p.getWriteMethod();
475                         if (getter != null) {
476                             set.remove(getter.getName());
477                         }
478                         if (setter != null) {
479                             set.remove(setter.getName());
480                         }
481                     }
482                 }
483             } catch (IntrospectionException e) {
484             }
485
486             return set.toArray(new String[set.size()]);
487         } catch (Exception e) {
488             return new String[0];
489         }
490     }
491
492     /**
493      * @param id the Java Object id
494      * @return the accessibles methods in the object represented by id
495      */
496     public static final String[] getAccessibleMethods(final int id) throws ScilabJavaException {
497         if (id > 0) {
498             if (debug) {
499                 logger.log(Level.INFO, "Get accessible methods in object id=" + id);
500             }
501
502             if (arraySJO[id] == null) {
503                 throw new ScilabJavaException("Invalid Java object");
504             }
505
506             final Method[] ms = arraySJO[id].clazz.getMethods();
507             Set<String> set = new TreeSet<String>();
508             for (Method m : ms) {
509                 if (Modifier.isPublic(m.getModifiers())) {
510                     set.add(m.getName());
511                 }
512             }
513
514             return set.toArray(new String[set.size()]);
515         } else {
516             return new String[0];
517         }
518     }
519
520     /**
521      * @param id the Java Object id
522      * @return the accessibles fields in the object represented by id
523      */
524     public static final String[] getAccessibleFields(final int id) throws ScilabJavaException {
525         if (id > 0) {
526             if (debug) {
527                 logger.log(Level.INFO, "Get accessible fields in object id=" + id);
528             }
529
530             if (arraySJO[id] == null) {
531                 throw new ScilabJavaException("Invalid Java object");
532             }
533
534             if (arraySJO[id].clazz.isArray()) {
535                 return new String[] {"length"};
536             }
537
538             final Field[] f = arraySJO[id].clazz.getFields();
539             final String[] sf = new String[f.length];
540             for (int i = 0; i < f.length; i++) {
541                 if (Modifier.isPublic(f[i].getModifiers())) {
542                     sf[i] = f[i].getName();
543                 }
544             }
545             return sf;
546         } else {
547             return new String[0];
548         }
549     }
550
551     /**
552      * @param id the Java Object id
553      * @return the class name of the object represented by id
554      */
555     public static final String getClassName(final int id) throws ScilabJavaException {
556         if (id > 0) {
557             if (debug) {
558                 logger.log(Level.INFO, "Get class name of object id=" + id);
559             }
560
561             if (arraySJO[id] == null) {
562                 throw new ScilabJavaException("Invalid Java object");
563             }
564
565             return arraySJO[id].clazz.getName();
566         } else {
567             return "null";
568         }
569     }
570
571     /**
572      * @param id the Java Object id
573      * @param fieldName the field name to set
574      * @param idArg the id of the element to set
575      */
576     public static final void setField(final int id, final String fieldName, final int idarg) throws ScilabJavaException {
577         if (id > 0) {
578             Field f = null;
579             try {
580                 if (debug) {
581                     logger.log(Level.INFO, "Set field \'" + fieldName + "\' in object id=" + id + " with value id=" + idarg);
582                 }
583
584                 if (arraySJO[id] == null) {
585                     throw new ScilabJavaException("Invalid Java object");
586                 }
587
588                 try  {
589                     f = arraySJO[id].clazz.getField(fieldName);
590
591                     // standard field access
592                     try {
593                         f.set(arraySJO[id].object, arraySJO[idarg].object);
594                     } catch (IllegalArgumentException e) {
595                         if (f != null && f.getType() == int.class && (arraySJO[idarg].clazz == double.class || arraySJO[idarg].clazz == Double.class) && ((Double) arraySJO[idarg].object).intValue() == ((Double) arraySJO[idarg].object).doubleValue()) {
596                             f.set(arraySJO[id].object, ((Double) arraySJO[idarg].object).intValue());
597                             return;
598                         } else {
599                             throw e;
600                         }
601                     }
602                 } catch (NoSuchFieldException e) {
603                 }
604
605                 // lookup for a bean property
606                 final PropertyDescriptor p = lookupBeanProperty(id, fieldName);
607                 final Method method  = p.getWriteMethod();
608                 if (method == null) {
609                     throw new ScilabJavaException("Cannot read the property " + fieldName + " in object " + getClassName(id));
610                 }
611                 method.invoke(arraySJO[id].object, arraySJO[idarg].object);
612             } catch (IllegalArgumentException e) {
613                 throw new ScilabJavaException("Bad argument value for field " + fieldName + " in object " + getClassName(id));
614             } catch (IllegalAccessException e) {
615                 throw new ScilabJavaException("Cannot access to the field " + fieldName + " in object " + getClassName(id));
616             } catch (InvocationTargetException e) {
617                 throw new ScilabJavaException("Exception occurs on write access to the property " + fieldName + " in object " + getClassName(id));
618             }
619         } else {
620             throw new ScilabJavaException("null is not an object");
621         }
622     }
623
624     /**
625      * @param id the Java Object id
626      * @param fieldName the field name to set
627      * @return the id of the got object
628      */
629     public static final int getField(final int id, final String fieldName) throws ScilabJavaException {
630         if (id > 0) {
631             try {
632                 if (debug) {
633                     logger.log(Level.INFO, "Get field \'" + fieldName + "\' in object id=" + id);
634                 }
635
636                 if (arraySJO[id] == null) {
637                     throw new ScilabJavaException("Invalid Java object");
638                 }
639
640                 if (arraySJO[id].clazz.isArray() && fieldName.equals("length")) {
641                     return new ScilabJavaObject(Array.getLength(arraySJO[id].object), int.class).id;
642                 }
643
644                 if (arraySJO[id].object == arraySJO[id].clazz && fieldName.equals("class")) {
645                     return new ScilabJavaObject(arraySJO[id].object, arraySJO[id].object.getClass()).id;
646                 }
647
648                 try {
649                     final Field f = arraySJO[id].clazz.getField(fieldName);
650                     final Class cl = f.getType();
651                     if (cl == int.class) {
652                         return new ScilabJavaObject(f.getInt(arraySJO[id].object), int.class).id;
653                     } else if (cl == double.class) {
654                         return new ScilabJavaObject(f.getDouble(arraySJO[id].object), double.class).id;
655                     } else if (cl == boolean.class) {
656                         return new ScilabJavaObject(f.getBoolean(arraySJO[id].object), boolean.class).id;
657                     } else if (cl == short.class) {
658                         return new ScilabJavaObject(f.getShort(arraySJO[id].object), short.class).id;
659                     } else if (cl == char.class) {
660                         return new ScilabJavaObject(f.getChar(arraySJO[id].object), char.class).id;
661                     } else if (cl == float.class) {
662                         return new ScilabJavaObject(f.getFloat(arraySJO[id].object), float.class).id;
663                     } else if (cl == byte.class) {
664                         return new ScilabJavaObject(f.getByte(arraySJO[id].object), byte.class).id;
665                     } else if (cl == long.class) {
666                         return new ScilabJavaObject(f.getLong(arraySJO[id].object), long.class).id;
667                     }
668
669                     return new ScilabJavaObject(f.get(arraySJO[id].object)).id;
670                 } catch (NoSuchFieldException e) {
671                 }
672
673                 // lookup for a bean property
674                 final PropertyDescriptor p = lookupBeanProperty(id, fieldName);
675                 final Method method  = p.getReadMethod();
676                 if (method == null) {
677                     throw new ScilabJavaException("Cannot read the field or property " + fieldName + " in object " + getClassName(id));
678                 }
679                 final Object retValue = method.invoke(arraySJO[id].object);
680                 final Class cl = retValue.getClass();
681                 if (cl == int.class) {
682                     return new ScilabJavaObject(retValue, int.class).id;
683                 } else if (cl == double.class) {
684                     return new ScilabJavaObject(retValue, double.class).id;
685                 } else if (cl == boolean.class) {
686                     return new ScilabJavaObject(retValue, boolean.class).id;
687                 } else if (cl == short.class) {
688                     return new ScilabJavaObject(retValue, short.class).id;
689                 } else if (cl == char.class) {
690                     return new ScilabJavaObject(retValue, char.class).id;
691                 } else if (cl == float.class) {
692                     return new ScilabJavaObject(retValue, float.class).id;
693                 } else if (cl == byte.class) {
694                     return new ScilabJavaObject(retValue, byte.class).id;
695                 } else if (cl == long.class) {
696                     return new ScilabJavaObject(retValue, long.class).id;
697                 }
698                 return new ScilabJavaObject(retValue).id;
699             } catch (IllegalArgumentException e) {
700                 throw new ScilabJavaException("Bad argument value for field " + fieldName + " in object " + getClassName(id));
701             } catch (IllegalAccessException e) {
702                 throw new ScilabJavaException("Cannot access to the field " + fieldName + " in object " + getClassName(id));
703             } catch (InvocationTargetException e) {
704                 throw new ScilabJavaException("Exception occurs on read access to the property " + fieldName + " in object " + getClassName(id));
705             }
706         } else {
707             throw new ScilabJavaException("null is not an object");
708         }
709     }
710
711     /**
712      * @param id the Java Object id
713      * @param fieldName the field name to set
714      * @return the type of the field in object represented by id:
715      *         * -1 for unknown
716      *         * 0 for a method
717      *         * 1 for a field
718      */
719     public static final int getFieldType(final int id, final String fieldName) {
720         if (id > 0 && arraySJO[id] != null) {
721             if (debug) {
722                 logger.log(Level.INFO, "Get field type of \'" + fieldName + "\' in object id=" + id);
723             }
724
725             if (isValidMethod(id, fieldName)) {
726                 return 0;
727             }
728             try {
729                 if (arraySJO[id].clazz.isArray()) {
730                     if (fieldName.equals("length")) {
731                         return 1;
732                     } else {
733                         return -1;
734                     }
735                 }
736
737                 if (arraySJO[id].object == arraySJO[id].clazz && fieldName.equals("class")) {
738                     return 1;
739                 }
740
741                 try {
742                     Field f = arraySJO[id].clazz.getField(fieldName);
743                     return 1;
744                 } catch (NoSuchFieldException e) {
745                 }
746
747                 // lookup for a bean property
748                 lookupBeanProperty(id, fieldName);
749                 return 1;
750             } catch (IllegalArgumentException e) {
751                 return -1;
752             } catch (ScilabJavaException e) {
753                 return -1;
754             }
755         }
756
757         return -1;
758     }
759
760     private static final boolean isValidMethod(int id, String methName) {
761         final BeanInfo info;
762         try {
763             info = Introspector.getBeanInfo(arraySJO[id].clazz);
764         } catch (IntrospectionException e) {
765             return false;
766         }
767
768         final MethodDescriptor[] methods = info.getMethodDescriptors();
769         if (methods == null) {
770             return false;
771         }
772
773         for (MethodDescriptor m : methods) {
774             if (methName.equals(m.getName())) {
775                 return true;
776             }
777         }
778
779         return false;
780     }
781
782     private static final PropertyDescriptor lookupBeanProperty(int id, String fieldName) throws ScilabJavaException {
783         final BeanInfo info;
784         try {
785             info = Introspector.getBeanInfo(arraySJO[id].clazz);
786         } catch (IntrospectionException e) {
787             throw new ScilabJavaException("Unable to get properties of object " + getClassName(id));
788         }
789
790         final PropertyDescriptor[] properties = info.getPropertyDescriptors();
791         if (properties == null) {
792             throw new ScilabJavaException("No property " + fieldName + " in object " + getClassName(id));
793         }
794
795         for (PropertyDescriptor p : properties) {
796             if (fieldName.equals(p.getName())) {
797                 return p;
798             }
799         }
800
801         throw new ScilabJavaException("No property " + fieldName + " in object " + getClassName(id));
802     }
803
804     /**
805      * @param id the Java Object id
806      * @param methName the method name to invoke
807      * @param args an array containing the id of the arguments
808      * @return the id of the invocation result
809      */
810     public static final int invoke(final int id, final String methName, final int[] args) throws ScilabJavaException {
811         if (id > 0) {
812             if (debug) {
813                 StringBuffer buf = new StringBuffer();
814                 buf.append("(");
815                 if (args.length > 0) {
816                     int i = 0;
817                     for (; i < args.length - 1; i++) {
818                         buf.append(Integer.toString(args[i]));
819                         buf.append(",");
820                     }
821                     buf.append(Integer.toString(args[i]));
822                 }
823                 buf.append(")");
824                 logger.log(Level.INFO, "Invoke method \'" + methName + "\' in object id=" + id + " with arguments id=" + buf.toString());
825             }
826
827             if (arraySJO[id] != null) {
828                 Object ret = ScilabJavaMethod.invoke(methName, arraySJO[id].clazz, arraySJO[id].object, returnType, args);
829                 if (ret == null && returnType[0] == Void.TYPE) {
830                     return -1;
831                 } else {
832                     return new ScilabJavaObject(ret, returnType[0]).id;
833                 }
834             } else {
835                 throw new ScilabJavaException("Invalid Java object");
836             }
837         } else {
838             throw new ScilabJavaException("null is not an object");
839         }
840     }
841
842     /**
843      * @param id the Java Object id
844      * @param args an array containing the id of the arguments
845      * @return the id of the invocation result
846      */
847     public static final int extract(final int id, final int[] args) throws ScilabJavaException {
848         if (id > 0) {
849             if (debug) {
850                 StringBuffer buf = new StringBuffer();
851                 buf.append("(");
852                 if (args.length > 0) {
853                     int i = 0;
854                     for (; i < args.length - 1; i++) {
855                         buf.append(Integer.toString(args[i]));
856                         buf.append(",");
857                     }
858                     buf.append(Integer.toString(args[i]));
859                 }
860                 buf.append(")");
861                 logger.log(Level.INFO, "Extract in object id=" + id + " with arguments id=" + buf.toString());
862             }
863
864             for (int i = 0; i < args.length; i++) {
865                 if (args[i] < 0 || arraySJO[args[i]] == null) {
866                     throw new ScilabJavaException("Invalid Java object at position " + i);
867                 }
868             }
869
870             if (arraySJO[id] != null) {
871                 Object o = arraySJO[id].object;
872                 for (int i = 0; i < args.length; i++) {
873                     Object a = args[i] == 0 ? null : arraySJO[args[i]].object;
874                     if (o instanceof Map) {
875                         o = ((Map) o).get(a);
876                     } else if (o instanceof List) {
877                         List l = (List) o;
878                         int pos = -1;
879                         if (a instanceof Double) {
880                             // Scilab index begins at 1
881                             pos = ((Double) a).intValue() - 1;
882                         } else if (a instanceof Integer) {
883                             pos = ((Integer) a).intValue() - 1;
884                         } else {
885                             pos = l.indexOf(a);
886                         }
887                         if (pos >= 0 || pos < l.size()) {
888                             o = l.get(pos);
889                         } else {
890                             throw new ScilabJavaException("Cannot get object at position " + (i + 1));
891                         }
892                     } else if (o.getClass().isArray()) {
893                         int pos = -1;
894                         if (a instanceof Double) {
895                             pos = ((Double) a).intValue();
896                         } else if (a instanceof Integer) {
897                             pos = ((Integer) a).intValue();
898                         }
899
900                         o = ScilabJavaArray.get(o, new int[] {pos - 1});
901                     } else {
902                         throw new ScilabJavaException("Invalid field " + (a == null ? "null" : a.toString()));
903                     }
904                 }
905
906                 if (o == null) {
907                     return 0;
908                 }
909
910                 return new ScilabJavaObject(o).id;
911             }
912             throw new ScilabJavaException("Invalid Java object");
913         } else {
914             throw new ScilabJavaException("null is not an object");
915         }
916     }
917
918     /**
919      * @param id the Java Object id
920      * @param keys an array containing the id of the arguments
921      * @param value the id of the value
922      */
923     public static final void insert(final int id, final int[] keys, final int value) throws ScilabJavaException {
924         if (id > 0) {
925             if (debug) {
926                 StringBuffer buf = new StringBuffer();
927                 buf.append("(");
928                 if (keys.length > 0) {
929                     int i = 0;
930                     for (; i < keys.length - 1; i++) {
931                         buf.append(Integer.toString(keys[i]));
932                         buf.append(",");
933                     }
934                     buf.append(Integer.toString(keys[i]));
935                 }
936                 buf.append(")");
937                 logger.log(Level.INFO, "Insert in object id=" + id + " with arguments id=" + buf.toString() + " and the value id=" + value);
938             }
939
940             if (arraySJO[id] != null) {
941                 Object o = arraySJO[id].object;
942                 for (int i = 0; i < keys.length - 1; i++) {
943                     Object a = keys[i] == 0 ? null : arraySJO[keys[i]].object;
944                     if (o instanceof Map) {
945                         o = ((Map) o).get(a);
946                     } else if (o instanceof List) {
947                         List l = (List) o;
948                         int pos = -1;
949                         if (a instanceof Double) {
950                             // Scilab index begins at 1
951                             pos = ((Double) a).intValue() - 1;
952                         } else if (a instanceof Integer) {
953                             pos = ((Integer) a).intValue() - 1;
954                         } else {
955                             pos = l.indexOf(a);
956                         }
957                         if (pos >= 0 || pos < l.size()) {
958                             o = l.get(pos);
959                         } else {
960                             throw new ScilabJavaException("Cannot get object at position " + (i + 1));
961                         }
962                     } else if (o.getClass().isArray()) {
963                         int pos = -1;
964                         if (a instanceof Double) {
965                             pos = ((Double) a).intValue();
966                         } else if (a instanceof Integer) {
967                             pos = ((Integer) a).intValue();
968                         }
969
970                         o = ScilabJavaArray.get(o, new int[] {pos - 1});
971                     } else {
972                         throw new ScilabJavaException("Invalid field " + (a == null ? "null" : a.toString()));
973                     }
974                 }
975
976                 if (o == null) {
977                     return;
978                 }
979
980                 int last = keys[keys.length - 1];
981                 Object a = last == 0 ? null : arraySJO[last].object;
982                 if (o instanceof Map) {
983                     ((Map) o).put(a, arraySJO[value].object);
984                 } else if (o instanceof List) {
985                     List l = (List) o;
986                     int pos = -1;
987                     if (a instanceof Double) {
988                         // Scilab index begins at 1
989                         pos = ((Double) a).intValue() - 1;
990                     } else if (a instanceof Integer) {
991                         pos = ((Integer) a).intValue() - 1;
992                     } else {
993                         pos = l.indexOf(a);
994                     }
995                     if (pos >= 0 || pos < l.size()) {
996                         l.set(pos, arraySJO[value].object);
997                     } else if (pos < 0) {
998                         l.add(0, arraySJO[value].object);
999                     } else {
1000                         l.add(arraySJO[value].object);
1001                     }
1002                 } else if (o.getClass().isArray()) {
1003                     int pos = -1;
1004                     if (a instanceof Double) {
1005                         pos = ((Double) a).intValue();
1006                     } else if (a instanceof Integer) {
1007                         pos = ((Integer) a).intValue();
1008                     }
1009
1010                     ScilabJavaArray.set(o, new int[] {pos - 1}, arraySJO[value].object);
1011                 } else {
1012                     throw new ScilabJavaException("Invalid field " + (a == null ? "null" : a.toString()));
1013                 }
1014
1015                 return;
1016             }
1017             throw new ScilabJavaException("Invalid Java object");
1018         } else {
1019             throw new ScilabJavaException("null is not an object");
1020         }
1021     }
1022
1023     /**
1024      * @param id the Java Object id
1025      * @param className the target class name
1026      * @return the id of the cast result
1027      */
1028     public static final int javaCast(final int id, final String className) throws ScilabJavaException {
1029         if (id > 0) {
1030             if (debug) {
1031                 logger.log(Level.INFO, "Cast object id=" + id + " to class " + className);
1032             }
1033
1034             final int idC = ScilabClassLoader.loadJavaClass(className, false);
1035             final Class clazz = (Class) arraySJO[idC].object;
1036             try {
1037                 int idR = new ScilabJavaObject(clazz.cast(arraySJO[id].object), clazz).id;
1038                 removeScilabJavaObject(idC);
1039                 return idR;
1040             } catch (ClassCastException e) {
1041                 throw new ScilabJavaException("Cannot cast object " + getClassName(id) + " into " + getClassName(idC));
1042             }
1043         } else {
1044             throw new ScilabJavaException("null is not an object");
1045         }
1046     }
1047
1048     /**
1049      * @param id the Java Object id
1050      * @param classId the target class id
1051      * @return the id of the cast result
1052      */
1053     public static final int javaCast(final int id, final int classId) throws ScilabJavaException {
1054         if (id > 0) {
1055             if (debug) {
1056                 logger.log(Level.INFO, "Cast object id=" + id + " to class with id=" + classId);
1057             }
1058
1059             final Class clazz = (Class) arraySJO[classId].object;
1060             try {
1061                 return new ScilabJavaObject(clazz.cast(arraySJO[id].object), clazz).id;
1062             } catch (ClassCastException e) {
1063                 throw new ScilabJavaException("Cannot cast object " + getClassName(id) + " into " + getClassName(classId));
1064             }
1065         } else {
1066             throw new ScilabJavaException("null is not an object");
1067         }
1068     }
1069
1070     /**
1071      * Remove an object.
1072      * @param id the Java Object id
1073      */
1074     public static final void removeScilabJavaObject(final int id) {
1075         if (id > 0 && arraySJO[id] != null) {
1076             if (debug) {
1077                 logger.log(Level.INFO, "Remove object id=" + id);
1078             }
1079             freePlace.addFreePlace(id);
1080             if (arraySJO[id] instanceof ScilabJavaClass) {
1081                 ScilabClassLoader.removeID(id);
1082             }
1083             arraySJO[id] = null;
1084         }
1085     }
1086
1087     /**
1088      * Remove objects.
1089      * @param ids the Java Object ids
1090      */
1091     public static final void removeScilabJavaObject(final int[] ids) {
1092         for (int id : ids) {
1093             removeScilabJavaObject(id);
1094         }
1095     }
1096
1097     /**
1098      * Set the limit of a direct buffer to 0 to make it unusable.
1099      * @param id the Java Object id
1100      */
1101     public static final void limitDirectBuffer(final int id) {
1102         if (id > 0 && arraySJO[id] != null && (arraySJO[id].object instanceof Buffer)) {
1103             if (debug) {
1104                 logger.log(Level.INFO, "Limit direct buffer with id=" + id);
1105             }
1106
1107             ((Buffer) arraySJO[id].object).limit(0);
1108         }
1109     }
1110
1111     /**
1112      * Remove all the objects and start a garbage collection
1113      */
1114     public static final void garbageCollect() {
1115         if (debug) {
1116             logger.log(Level.INFO, "Garbage collection");
1117         }
1118         currentPos = 1;
1119         currentCapacity = INITIALCAPACITY;
1120         arraySJO = new ScilabJavaObject[currentCapacity];
1121         arraySJO[0] = new ScilabJavaObject(null, null);
1122         freePlace = new FreePlace();
1123         ScilabClassLoader.clazz.clear();
1124         System.gc();
1125     }
1126
1127     /**
1128      * @param x the variable to wrap into a Java Object
1129      * @return the corresponding id
1130      */
1131     public static final int wrapAsDirectByteBuffer(final ByteBuffer x) {
1132         x.order(ByteOrder.nativeOrder());
1133         return new ScilabJavaObject(x, ByteBuffer.class).id;
1134     }
1135
1136     /**
1137      * @param x the variable to wrap into a Java Object
1138      * @return the corresponding id
1139      */
1140     public static final int wrapAsDirectDoubleBuffer(final ByteBuffer x) {
1141         x.order(ByteOrder.nativeOrder());
1142         return new ScilabJavaObject(x.asDoubleBuffer(), DoubleBuffer.class).id;
1143     }
1144
1145     /**
1146      * @param x the variable to wrap into a Java Object
1147      * @return the corresponding id
1148      */
1149     public static final int wrapAsDirectIntBuffer(final ByteBuffer x) {
1150         x.order(ByteOrder.nativeOrder());
1151         return new ScilabJavaObject(x.asIntBuffer(), IntBuffer.class).id;
1152     }
1153
1154     /**
1155      * @param x the variable to wrap into a Java Object
1156      * @return the corresponding id
1157      */
1158     public static final int wrapAsDirectCharBuffer(final ByteBuffer x) {
1159         x.order(ByteOrder.nativeOrder());
1160         return new ScilabJavaObject(x.asCharBuffer(), CharBuffer.class).id;
1161     }
1162
1163     /**
1164      * @param x the variable to wrap into a Java Object
1165      * @return the corresponding id
1166      */
1167     public static final int wrapAsDirectFloatBuffer(final ByteBuffer x) {
1168         x.order(ByteOrder.nativeOrder());
1169         return new ScilabJavaObject(x.asFloatBuffer(), FloatBuffer.class).id;
1170     }
1171
1172     /**
1173      * @param x the variable to wrap into a Java Object
1174      * @return the corresponding id
1175      */
1176     public static final int wrapAsDirectLongBuffer(final ByteBuffer x) {
1177         x.order(ByteOrder.nativeOrder());
1178         return new ScilabJavaObject(x.asLongBuffer(), LongBuffer.class).id;
1179     }
1180
1181     /**
1182      * @param x the variable to wrap into a Java Object
1183      * @return the corresponding id
1184      */
1185     public static final int wrapAsDirectShortBuffer(final ByteBuffer x) {
1186         x.order(ByteOrder.nativeOrder());
1187         return new ScilabJavaObject(x.asShortBuffer(), ShortBuffer.class).id;
1188     }
1189
1190     /**
1191      * @param x the variable to wrap into a Java Object
1192      * @return the corresponding id
1193      */
1194     public static final int wrap(final double x) {
1195         return new ScilabJavaObject(x, double.class).id;
1196     }
1197
1198     /**
1199      * @param x the variable to wrap into a Java Object
1200      * @return the corresponding id
1201      */
1202     public static final int wrap(final double[] x) {
1203         return new ScilabJavaObject(x, double[].class).id;
1204     }
1205
1206     /**
1207      * @param x the variable to wrap into a Java Object
1208      * @return the corresponding id
1209      */
1210     public static final int wrap(final double[][] x) {
1211         return new ScilabJavaObject(x, double[][].class).id;
1212     }
1213
1214     /**
1215      * @param x the variable to wrap into a Java Object
1216      * @return the corresponding id
1217      */
1218     public static final int wrap(final int x) {
1219         return new ScilabJavaObject(x, int.class).id;
1220     }
1221
1222     /**
1223      * @param x the variable to wrap into a Java Object
1224      * @return the corresponding id
1225      */
1226     public static final int wrap(final int[] x) {
1227         return new ScilabJavaObject(x, int[].class).id;
1228     }
1229
1230     /**
1231      * @param x the variable to wrap into a Java Object
1232      * @return the corresponding id
1233      */
1234     public static final int wrap(final int[][] x) {
1235         return new ScilabJavaObject(x, int[][].class).id;
1236     }
1237
1238     /**
1239      * @param x the variable to wrap into a Java Object
1240      * @return the corresponding id
1241      */
1242     public static final int wrap(final long x) {
1243         return new ScilabJavaObject(x, long.class).id;
1244     }
1245
1246     /**
1247      * @param x the variable to wrap into a Java Object
1248      * @return the corresponding id
1249      */
1250     public static final int wrap(final long[] x) {
1251         return new ScilabJavaObject(x, long[].class).id;
1252     }
1253
1254     /**
1255      * @param x the variable to wrap into a Java Object
1256      * @return the corresponding id
1257      */
1258     public static final int wrap(final long[][] x) {
1259         return new ScilabJavaObject(x, long[][].class).id;
1260     }
1261
1262     /**
1263      * @param x the variable to wrap into a Java Object
1264      * @return the corresponding id
1265      */
1266     public static final int wrap(final byte x) {
1267         return new ScilabJavaObject(x, byte.class).id;
1268     }
1269
1270     /**
1271      * @param x the variable to wrap into a Java Object
1272      * @return the corresponding id
1273      */
1274     public static final int wrap(final byte[] x) {
1275         return new ScilabJavaObject(x, byte[].class).id;
1276     }
1277
1278     /**
1279      * @param x the variable to wrap into a Java Object
1280      * @return the corresponding id
1281      */
1282     public static final int wrap(final byte[][] x) {
1283         return new ScilabJavaObject(x, byte[][].class).id;
1284     }
1285
1286     /**
1287      * @param x the variable to wrap into a Java Object
1288      * @return the corresponding id
1289      */
1290     public static final int wrap(final short x) {
1291         return new ScilabJavaObject(x, short.class).id;
1292     }
1293
1294     /**
1295      * @param x the variable to wrap into a Java Object
1296      * @return the corresponding id
1297      */
1298     public static final int wrap(final short[] x) {
1299         return new ScilabJavaObject(x, short[].class).id;
1300     }
1301
1302     /**
1303      * @param x the variable to wrap into a Java Object
1304      * @return the corresponding id
1305      */
1306     public static final int wrap(final short[][] x) {
1307         return new ScilabJavaObject(x, short[][].class).id;
1308     }
1309
1310     /**
1311      * @param x the variable to wrap into a Java Object
1312      * @return the corresponding id
1313      */
1314     public static final int wrap(final String x) {
1315         return new ScilabJavaObject(x, String.class).id;
1316     }
1317
1318     /**
1319      * @param x the variable to wrap into a Java Object
1320      * @return the corresponding id
1321      */
1322     public static final int wrap(final String[] x) {
1323         return new ScilabJavaObject(x, String[].class).id;
1324     }
1325
1326     /**
1327      * @param x the variable to wrap into a Java Object
1328      * @return the corresponding id
1329      */
1330     public static final int wrap(final String[][] x) {
1331         return new ScilabJavaObject(x, String[][].class).id;
1332     }
1333
1334     /**
1335      * @param x the variable to wrap into a Java Object
1336      * @return the corresponding id
1337      */
1338     public static final int wrap(final boolean x) {
1339         return new ScilabJavaObject(x, boolean.class).id;
1340     }
1341
1342     /**
1343      * @param x the variable to wrap into a Java Object
1344      * @return the corresponding id
1345      */
1346     public static final int wrap(final boolean[] x) {
1347         return new ScilabJavaObject(x, boolean[].class).id;
1348     }
1349
1350     /**
1351      * @param x the variable to wrap into a Java Object
1352      * @return the corresponding id
1353      */
1354     public static final int wrap(final boolean[][] x) {
1355         return new ScilabJavaObject(x, boolean[][].class).id;
1356     }
1357
1358     /**
1359      * @param x the variable to wrap into a Java Object
1360      * @return the corresponding id
1361      */
1362     public static final int wrap(final char x) {
1363         return new ScilabJavaObject(x, char.class).id;
1364     }
1365
1366     /**
1367      * @param x the variable to wrap into a Java Object
1368      * @return the corresponding id
1369      */
1370     public static final int wrap(final char[] x) {
1371         return new ScilabJavaObject(x, char[].class).id;
1372     }
1373
1374     /**
1375      * @param x the variable to wrap into a Java Object
1376      * @return the corresponding id
1377      */
1378     public static final int wrap(final char[][] x) {
1379         return new ScilabJavaObject(x, char[][].class).id;
1380     }
1381
1382     /**
1383      * @param x the variable to wrap into a Java Object
1384      * @return the corresponding id
1385      */
1386     public static final int wrap(final float x) {
1387         return new ScilabJavaObject(x, float.class).id;
1388     }
1389
1390     /**
1391      * @param x the variable to wrap into a Java Object
1392      * @return the corresponding id
1393      */
1394     public static final int wrap(final float[] x) {
1395         return new ScilabJavaObject(x, float[].class).id;
1396     }
1397
1398     /**
1399      * @param x the variable to wrap into a Java Object
1400      * @return the corresponding id
1401      */
1402     public static final int wrap(final float[][] x) {
1403         return new ScilabJavaObject(x, float[][].class).id;
1404     }
1405
1406     /**
1407      * @param id the Java Object id
1408      * @return the resulting unwrapping
1409      */
1410     public static final double unwrapDouble(final int id) {
1411         return ((Double) (arraySJO[id].object)).doubleValue();
1412     }
1413
1414     /**
1415      * @param id the Java Object id
1416      * @return the resulting unwrapping
1417      */
1418     public static final Object unwrapRowDouble(final int id) {
1419         if (arraySJO[id].object instanceof List) {
1420             return ScilabJavaArray.toDoubleArray((List<Double>) arraySJO[id].object);
1421         } else if (arraySJO[id].object instanceof Double[]) {
1422             return ScilabJavaArray.toPrimitive((Double[]) arraySJO[id].object);
1423         } else if (arraySJO[id].object instanceof DoubleBuffer && !((DoubleBuffer) arraySJO[id].object).isDirect()) {
1424             return ((DoubleBuffer) arraySJO[id].object).array();
1425         }
1426
1427         return arraySJO[id].object;
1428     }
1429
1430     /**
1431      * @param id the Java Object id
1432      * @return the resulting unwrapping
1433      */
1434     public static final double[][] unwrapMatDouble(final int id) {
1435         if (arraySJO[id].object instanceof Double[][]) {
1436             Object o = ScilabJavaArray.toPrimitive(arraySJO[id].object);
1437             return (double[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1438         }
1439
1440         return (double[][]) arraySJO[id].object;
1441     }
1442
1443     /**
1444      * @param id the Java Object id
1445      * @return the resulting unwrapping
1446      */
1447     public static final int unwrapInt(final int id) {
1448         return ((Integer) (arraySJO[id].object)).intValue();
1449     }
1450
1451     /**
1452      * @param id the Java Object id
1453      * @return the resulting unwrapping
1454      */
1455     public static final Object unwrapRowInt(final int id) {
1456         if (arraySJO[id].object instanceof List) {
1457             return ScilabJavaArray.toIntArray((List<Integer>) arraySJO[id].object);
1458         } else if (arraySJO[id].object instanceof Integer[]) {
1459             return ScilabJavaArray.toPrimitive((Integer[]) arraySJO[id].object);
1460         } else if (arraySJO[id].object instanceof IntBuffer && !((IntBuffer) arraySJO[id].object).isDirect()) {
1461             return ((IntBuffer) arraySJO[id].object).array();
1462         }
1463
1464         return arraySJO[id].object;
1465     }
1466
1467     /**
1468      * @param id the Java Object id
1469      * @return the resulting unwrapping
1470      */
1471     public static final int[][] unwrapMatInt(final int id) {
1472         if (arraySJO[id].object instanceof Integer[][]) {
1473             return (int[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1474         }
1475
1476         return (int[][]) (arraySJO[id].object);
1477     }
1478
1479     /**
1480      * @param id the Java Object id
1481      * @return the resulting unwrapping
1482      */
1483     public static final short unwrapShort(final int id) {
1484         return ((Short) (arraySJO[id].object)).shortValue();
1485     }
1486
1487     /**
1488      * @param id the Java Object id
1489      * @return the resulting unwrapping
1490      */
1491     public static final Object unwrapRowShort(final int id) {
1492         if (arraySJO[id].object instanceof List) {
1493             return ScilabJavaArray.toShortArray((List<Short>) arraySJO[id].object);
1494         } else if (arraySJO[id].object instanceof Short[]) {
1495             return ScilabJavaArray.toPrimitive((Short[]) arraySJO[id].object);
1496         } else if (arraySJO[id].object instanceof ShortBuffer && !((ShortBuffer) arraySJO[id].object).isDirect()) {
1497             return ((ShortBuffer) arraySJO[id].object).array();
1498         }
1499
1500         return arraySJO[id].object;
1501     }
1502
1503     /**
1504      * @param id the Java Object id
1505      * @return the resulting unwrapping
1506      */
1507     public static final short[][] unwrapMatShort(final int id) {
1508         if (arraySJO[id].object instanceof Short[][]) {
1509             return (short[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1510         }
1511
1512         return (short[][]) (arraySJO[id].object);
1513     }
1514
1515     /**
1516      * @param id the Java Object id
1517      * @return the resulting unwrapping
1518      */
1519     public static final byte unwrapByte(final int id) {
1520         return ((Byte) (arraySJO[id].object)).byteValue();
1521     }
1522
1523     /**
1524      * @param id the Java Object id
1525      * @return the resulting unwrapping
1526      */
1527     public static final Object unwrapRowByte(final int id) {
1528         if (arraySJO[id].object instanceof List) {
1529             return ScilabJavaArray.toByteArray((List<Byte>) arraySJO[id].object);
1530         } else if (arraySJO[id].object instanceof Byte[]) {
1531             return ScilabJavaArray.toPrimitive((Byte[]) arraySJO[id].object);
1532         } else if (arraySJO[id].object instanceof ByteBuffer && !((ByteBuffer) arraySJO[id].object).isDirect()) {
1533             return ((ByteBuffer) arraySJO[id].object).array();
1534         }
1535
1536         return arraySJO[id].object;
1537     }
1538
1539     /**
1540      * @param id the Java Object id
1541      * @return the resulting unwrapping
1542      */
1543     public static final byte[][] unwrapMatByte(final int id) {
1544         if (arraySJO[id].object instanceof Byte[][]) {
1545             return (byte[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1546         }
1547
1548         return (byte[][]) (arraySJO[id].object);
1549     }
1550
1551     /**
1552      * @param id the Java Object id
1553      * @return the resulting unwrapping
1554      */
1555     public static final String unwrapString(final int id) {
1556         return (String) (arraySJO[id].object);
1557     }
1558
1559     /**
1560      * @param id the Java Object id
1561      * @return the resulting unwrapping
1562      */
1563     public static final String[] unwrapRowString(final int id) {
1564         if (arraySJO[id].object instanceof List) {
1565             return ScilabJavaArray.toStringArray((List<String>) arraySJO[id].object);
1566         }
1567
1568         return (String[]) (arraySJO[id].object);
1569     }
1570
1571     /**
1572      * @param id the Java Object id
1573      * @return the resulting unwrapping
1574      */
1575     public static final String[][] unwrapMatString(final int id) {
1576         return (String[][]) (arraySJO[id].object);
1577     }
1578
1579     /**
1580      * @param id the Java Object id
1581      * @return the resulting unwrapping
1582      */
1583     public static final boolean unwrapBoolean(final int id) {
1584         return (Boolean) (arraySJO[id].object);
1585     }
1586
1587     /**
1588      * @param id the Java Object id
1589      * @return the resulting unwrapping
1590      */
1591     public static final boolean[] unwrapRowBoolean(final int id) {
1592         if (arraySJO[id].object instanceof List) {
1593             return ScilabJavaArray.toBooleanArray((List<Boolean>) arraySJO[id].object);
1594         } else if (arraySJO[id].object instanceof Boolean[]) {
1595             return ScilabJavaArray.toPrimitive((Boolean[]) arraySJO[id].object);
1596         }
1597
1598         return (boolean[]) (arraySJO[id].object);
1599     }
1600
1601     /**
1602      * @param id the Java Object id
1603      * @return the resulting unwrapping
1604      */
1605     public static final boolean[][] unwrapMatBoolean(final int id) {
1606         if (arraySJO[id].object instanceof Boolean[][]) {
1607             return (boolean[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1608         }
1609
1610         return (boolean[][]) (arraySJO[id].object);
1611     }
1612
1613     /**
1614      * @param id the Java Object id
1615      * @return the resulting unwrapping
1616      */
1617     public static final char unwrapChar(final int id) {
1618         return (Character) (arraySJO[id].object);
1619     }
1620
1621     /**
1622      * @param id the Java Object id
1623      * @return the resulting unwrapping
1624      */
1625     public static final Object unwrapRowChar(final int id) {
1626         if (arraySJO[id].object instanceof List) {
1627             return ScilabJavaArray.toCharArray((List<Character>) arraySJO[id].object);
1628         } else if (arraySJO[id].object instanceof Character[]) {
1629             return ScilabJavaArray.toPrimitive((Character[]) arraySJO[id].object);
1630         } else if (arraySJO[id].object instanceof CharBuffer && !((CharBuffer) arraySJO[id].object).isDirect()) {
1631             return ((CharBuffer) arraySJO[id].object).array();
1632         }
1633
1634         return arraySJO[id].object;
1635     }
1636
1637     /**
1638      * @param id the Java Object id
1639      * @return the resulting unwrapping
1640      */
1641     public static final char[][] unwrapMatChar(final int id) {
1642         if (arraySJO[id].object instanceof Character[][]) {
1643             return (char[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1644         }
1645
1646         return (char[][]) (arraySJO[id].object);
1647     }
1648
1649     /**
1650      * @param id the Java Object id
1651      * @return the resulting unwrapping
1652      */
1653     public static final float unwrapFloat(final int id) {
1654         return (Float) (arraySJO[id].object);
1655     }
1656
1657     /**
1658      * @param id the Java Object id
1659      * @return the resulting unwrapping
1660      */
1661     public static final Object unwrapRowFloat(final int id) {
1662         if (arraySJO[id].object instanceof List) {
1663             return ScilabJavaArray.toFloatArray((List<Float>) arraySJO[id].object);
1664         } else if (arraySJO[id].object instanceof Double[]) {
1665             return ScilabJavaArray.toPrimitive((Float[]) arraySJO[id].object);
1666         } else if (arraySJO[id].object instanceof FloatBuffer && !((FloatBuffer) arraySJO[id].object).isDirect()) {
1667             return ((FloatBuffer) arraySJO[id].object).array();
1668         }
1669
1670         return arraySJO[id].object;
1671     }
1672
1673     /**
1674      * @param id the Java Object id
1675      * @return the resulting unwrapping
1676      */
1677     public static final float[][] unwrapMatFloat(final int id) {
1678         if (arraySJO[id].object instanceof Float[][]) {
1679             return (float[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1680         }
1681
1682         return (float[][]) (arraySJO[id].object);
1683     }
1684
1685     /**
1686      * @param id the Java Object id
1687      * @return the resulting unwrapping
1688      */
1689     public static final long unwrapLong(final int id) {
1690         return (Long) (arraySJO[id].object);
1691     }
1692
1693     /**
1694      * @param id the Java Object id
1695      * @return the resulting unwrapping
1696      */
1697     public static final Object unwrapRowLong(final int id) {
1698         if (arraySJO[id].object instanceof List) {
1699             return ScilabJavaArray.toLongArray((List<Long>) arraySJO[id].object);
1700         } else if (arraySJO[id].object instanceof Long[]) {
1701             return ScilabJavaArray.toPrimitive((Long[]) arraySJO[id].object);
1702         } else if (arraySJO[id].object instanceof LongBuffer && !((LongBuffer) arraySJO[id].object).isDirect()) {
1703             return ((LongBuffer) arraySJO[id].object).array();
1704         }
1705
1706         return arraySJO[id].object;
1707     }
1708
1709     /**
1710      * @param id the Java Object id
1711      * @return the resulting unwrapping
1712      */
1713     public static final long[][] unwrapMatLong(final int id) {
1714         if (arraySJO[id].object instanceof Long[][]) {
1715             return (long[][]) ScilabJavaArray.toPrimitive(arraySJO[id].object);
1716         }
1717
1718         return (long[][]) (arraySJO[id].object);
1719     }
1720
1721     /**
1722      * @param id the Java Object id
1723      * @return the identifier of the unwrappable type or -1 if nothing
1724      */
1725     public static final int isUnwrappable(final int id) {
1726         if (id == 0) {
1727             System.out.println("unwrappable=0");
1728             // Null object
1729             return 1;
1730         }
1731
1732         Integer t = unwrappableType.get(arraySJO[id].clazz);
1733         if (t != null) {
1734             return t;
1735         } else if (arraySJO[id].object instanceof List) {
1736             List l = (List) arraySJO[id].object;
1737             if (l.size() == 0 || l.get(0) == null) {
1738                 return -1;
1739             } else {
1740                 Class cl = l.get(0).getClass();
1741                 Integer i = listBaseType.get(cl);
1742                 if (i != null) {
1743                     for (Object o : l) {
1744                         if (o.getClass() != cl) {
1745                             return -1;
1746                         }
1747                     }
1748                 }
1749
1750                 if (i == null) {
1751                     return -1;
1752                 }
1753
1754                 return i;
1755             }
1756         } else if (arraySJO[id].object instanceof Buffer) {
1757             if (arraySJO[id].object instanceof DoubleBuffer) {
1758                 unwrappableType.put(arraySJO[id].clazz, 3);
1759                 return 3;
1760             } else if (arraySJO[id].object instanceof ByteBuffer) {
1761                 unwrappableType.put(arraySJO[id].clazz, 12);
1762                 return 12;
1763             } else if (arraySJO[id].object instanceof IntBuffer) {
1764                 unwrappableType.put(arraySJO[id].clazz, 24);
1765                 return 24;
1766             } else if (arraySJO[id].object instanceof CharBuffer) {
1767                 unwrappableType.put(arraySJO[id].clazz, 21);
1768                 return 21;
1769             } else if (arraySJO[id].object instanceof FloatBuffer) {
1770                 unwrappableType.put(arraySJO[id].clazz, 36);
1771                 return 36;
1772             } else if (arraySJO[id].object instanceof LongBuffer) {
1773                 unwrappableType.put(arraySJO[id].clazz, 30);
1774                 return 30;
1775             } else if (arraySJO[id].object instanceof ShortBuffer) {
1776                 unwrappableType.put(arraySJO[id].clazz, 18);
1777                 return 18;
1778             }
1779
1780             return -1;
1781         } else {
1782             return -1;
1783         }
1784     }
1785
1786     /**
1787      * Inner class to manage the free places
1788      */
1789     private static final class FreePlace {
1790
1791         int[] fp;
1792         int currentPos;
1793
1794         FreePlace() {
1795             this.fp = new int[INITIALCAPACITY];
1796             currentPos = -1;
1797         }
1798
1799         final void addFreePlace(final int n) {
1800             if (currentPos == fp.length - 1) {
1801                 int[] newFp = new int[(int) (1.5 * fp.length)];
1802                 System.arraycopy(fp, 0, newFp, 0, fp.length);
1803                 fp = newFp;
1804             }
1805             fp[++currentPos] = n;
1806         }
1807
1808         final int getFreePlace() {
1809             if (currentPos == -1) {
1810                 return -1;
1811             }
1812             return fp[currentPos--];
1813         }
1814
1815         final int[] getCurrentFreePlace() {
1816             if (currentPos == -1) {
1817                 return null;
1818             }
1819
1820             int[] ret = new int[currentPos + 1];
1821             System.arraycopy(fp, 0, ret, 0, ret.length);
1822
1823             return ret;
1824         }
1825     }
1826 }