The SafeArray Class of the com.ms.com Package wraps a Microsoft® ActiveX® Automation data structure. It bridges Java with the Automation object by wrapping a pointer to the native SAFEARRAY data structure. It does not duplicate the array data in Java form. This approach minimizes translation overhead but imposes extra rules on SafeArray usage.
public final class SafeArray { // Constructors public SafeArray(int vt); public SafeArray(int vt, int celems); public SafeArray(int vt, int celems1, int celems2); public SafeArray(int vt, int lbounds[], int celems[]); public SafeArray(String s); public native int getPhysicalSafeArray(); // Methods public native String asString(); public Object clone(); public void destroy(); protected void finalize(); public void fromBooleanArray(boolean ja[]); public void fromByteArray(byte ja[]); public void fromCharArray(char ja[]); public void fromDoubleArray(double ja[]); public void fromFloatArray(float ja[]); public void fromIntArray(int ja[]); public void fromShortArray(short ja[]); public void fromStringArray(String ja[]); public void fromVariantArray(Variant ja[]); public native boolean getBoolean(int sa_idx); public boolean getBoolean(int sa_idx1, int sa_idx2); public void getBooleans(int sa_idx, int nelems, boolean ja[], int ja_start); public byte getByte(int sa_idx); public byte getByte(int sa_idx1, int sa_idx2); public void getBytes(int sa_idx, int nelems, byte ja[], int ja_start); public char getChar(int sa_idx); public char getChar(int sa_idx1, int sa_idx2); public void getChars(int sa_idx, int nelems, char ja[], int ja_start); public native double getDouble(int sa_idx); public double getDouble(int sa_idx1, int sa_idx2); public void getDoubles(int sa_idx, int nelems, double ja[], int ja_start); public int getElemSize(); public int getFeatures(); public native float getFloat(int sa_idx); public float getFloat(int sa_idx1, int sa_idx2); public void getFloats(int sa_idx, int nelems, float ja[], int ja_start); public native int getInt(int sa_idx); public int getInt(int sa_idx1, int sa_idx2); public void getInts(int sa_idx, int nelems, int ja[], int ja_start); public int getLBound(); public int getLBound(int dim); public int getNumDim(); public int getNumLocks(); public short getShort(int sa_idx); public short getShort(int sa_idx1, int sa_idx2); public void getShorts(int sa_idx, int nelems, short ja[], int ja_start); public String getString(int sa_idx); public String getString(int sa_idx1, int sa_idx2); public void getStrings(int sa_idx, int nelems, String ja[], int ja_start); public int getUBound(); public int getUBound(int dim); public Variant getVariant(int sa_idx); public Variant getVariant(int sa_idx1, int sa_idx2); public void getVariants(int sa_idx, int nelems, Variant ja[], int ja_start); public int getvt(); public void reinit(SafeArray sa); public void reinterpretType(int vt); public native void setBoolean(int idx, boolean val); public void setBoolean(int idx1, int idx2, boolean val); public void setBooleans(int sa_idx, int nelems, boolean ja[], int ja_start); public void setByte(int idx, byte val); public void setByte(int idx1, int idx2, byte val); public void setBytes(int sa_idx, int nelems, byte ja[], int ja_start); public void setChar(int idx, char val); public void setChar(int idx1, int idx2, char val); public void setChars(int sa_idx, int nelems, char ja[], int ja_start); public native void setDouble(int idx, double val); public void setDouble(int idx1, int idx2, double val); public void setDoubles(int sa_idx, int nelems, double ja[], int ja_start); public native void setFloat(int idx, float val); public void setFloat(int idx1, int idx2, float val); public void setFloats(int sa_idx, int nelems, float ja[], int ja_start); public native void setInt(int idx, int val); public void setInt(int idx1, int idx2, int val); public void setInts(int sa_idx, int nelems, int ja[], int ja_start); public void setShort(int idx, short val); public void setShort(int idx1, int idx2, short val); public void setShorts(int sa_idx, int nelems, short ja[], int ja_start); public void setString(int idx, String val); public void setString(int idx1, int idx2, String val); public void setStrings(int sa_idx, int nelems, String ja[], int ja_start); public void setVariant(int idx, Variant val); public void setVariant(int idx1, int idx2, Variant val); public void setVariants(int sa_idx, int nelems, Variant ja[], int ja_start); public boolean[] toBooleanArray(); public byte[] toByteArray(); public char[] toCharArray(); public double[] toDoubleArray(); public float[] toFloatArray(); public int[] toIntArray(); public short[] toShortArray(); public String toString(); public String[] toStringArray(); public Variant[] toVariantArray(); }
The rules for using this class are simple, but they must be followed:
In addition to maintaining a pointer to a native SAFEARRAY data structure, a SafeArray instance separately maintains the exact variant type of SAFEARRAY data structure elements. The variant type is determined by an argument to the SafeArray class constructor or is bound into the .java file by the jactivex tool. The system class com.ms.com.Variant defines public constants (Variant.VariantXXX) for all the valid variant types. It is important to note that neither the VariantByref nor the VariantArray modifier should be set in the element variant type; setting either of these modifiers will cause a run-time error to occur.
The SAFEARRAY data structure does not have reference counts, so the process of creating and destroying SAFEARRAY data structures cannot be made completely transparent to the Java programmer. Therefore, the SafeArray class can only be loaded by a trusted applet.
SafeArrays of type VT_UNKNOWN or VT_DISPATCH can be manipulated by using variant-typed manipulators and then extracting the COM object from the variant, as in the following example:
SafeArray sa; Object elem = sa.getVariant(index).toObject();
However, support for this technique is limited to cases where the variant was obtained from an object whose threading model is either free or both. In most other cases, a WrongThreadException is thrown. The conflicting requirements of COM's apartment threading model and Java's non-message-based model preclude an efficient representation of SafeArrays of Objects.
Note for JavaTLB users: The JavaTLB tool (which has been superceded by the jactivex tool) emits an older class file format that does not provide the exact variant type. This means in some cases, the SAFEARRAY data structure will not provide enough information to determine an exact variant type. In this case, the virtual machine will choose a default variant type based on the following heuristics: