diff --git a/jacob/docs/ReleaseNotes.html b/jacob/docs/ReleaseNotes.html index 7c817fa..6b38c08 100644 --- a/jacob/docs/ReleaseNotes.html +++ b/jacob/docs/ReleaseNotes.html @@ -65,7 +65,13 @@

Tracked Changes

1690420 - (pre-release 4)Incorrect memcpy lengths for Currency Variants + (pre-release 4) Incorrect memcpy lengths for Currency Variants + + + 1650134 + (pre-release 6) Beta support for VT_VARIANT (VariantVariant). + Includes support for putVariant, getVariant, toJavaObject, Variant(Object,flag). + Enclosed variants are retreived as Java objects. diff --git a/jacob/jni/Variant.cpp b/jacob/jni/Variant.cpp index 4daae27..30b59e9 100644 --- a/jacob/jni/Variant.cpp +++ b/jacob/jni/Variant.cpp @@ -1013,4 +1013,67 @@ JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isVariantConsideredNull return JNI_FALSE; } +/** + * Puts a variant into a the Variant as its data and sets the type + * to VT_VARIANT|VT_BYREF. + * Added 1.12 pre 6 + * + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantVariant + (JNIEnv *env, jobject _this, jobject var) +{ + + VARIANT *vVar = extractVariant(env, var); + VARIANT *v = extractVariant(env, _this); + + if (v) { + VariantClear(v); // whatever was there before + + V_VT(v) = VT_VARIANT|VT_BYREF; + V_VARIANTREF(v) = vVar; + } + +} + +/** + * retrieves the enclosed variant when they are of type VT_VARIANT + * Added 1.12 pre 6 + * + * */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantVariant +(JNIEnv *env, jobject _this) +{ + + VARIANT *v = extractVariant(env, _this); + if (v) { + + if (V_VT(v) != (VT_VARIANT|VT_BYREF)) { + return NULL; + } + + //Construct a new Variant + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID defaultCon = env->GetMethodID(variantClass, "", "()V"); + jobject newVariant = env->NewObject(variantClass, defaultCon); + + VARIANT *refVar = V_VARIANTREF(v); + VARIANT *newV = extractVariant(env, newVariant); + + // we could have made a copy of refV here but we aren't every going to free + // it outside of the scope of the enclosing context so we will just used the + // enclosed. This relies on the java layer to zero out its ref to this + // enclosed variant before the gc can come along and free the memory out from + // under this enclosing variant. + + jfieldID jf = env->GetFieldID( variantClass, VARIANT_FLD, "I"); + env->SetIntField(newVariant, jf, (unsigned int)refVar); + + return newVariant; + } + + return NULL; + +} + + } \ No newline at end of file diff --git a/jacob/jni/Variant.h b/jacob/jni/Variant.h index d7d1149..b240c17 100644 --- a/jacob/jni/Variant.h +++ b/jacob/jni/Variant.h @@ -496,6 +496,23 @@ JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_Variant_SerializationWriteToByte JNIEXPORT void JNICALL Java_com_jacob_com_Variant_SerializationReadFromBytes (JNIEnv *, jobject, jbyteArray); +/* + * Class: com_jacob_com_Variant + * Method: putVariantVariant + * Signature: (Lcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantVariant + (JNIEnv *, jobject, jobject); + + +/* + * Class: com_jacob_com_Variant + * Method: getVariantVariant + * Signature: ()Lcom/jacob/com/Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantVariant + (JNIEnv *, jobject); + /* * Class: com_jacob_com_Variant * Method: isVariantConsideredNull diff --git a/jacob/src/com/jacob/com/Variant.java b/jacob/src/com/jacob/com/Variant.java index d35d64e..fbe2aa0 100644 --- a/jacob/src/com/jacob/com/Variant.java +++ b/jacob/src/com/jacob/com/Variant.java @@ -26,6 +26,10 @@ * between Java and COM. It provides a single class that can handle all data * types. *

+ * PROPVARIANT introduces new types so eventually Variant will need to be + * upgraded to support PropVariant types. + * http://blogs.msdn.com/benkaras/archive/2006/09/13/749962.aspx + *

* This object no longer implements Serializable because serialization is broken * (and has been since 2000/xp). The underlying * marshalling/unmarshalling code is broken in the JNI layer. @@ -78,7 +82,7 @@ public class Variant extends JacobObject { /** variant's type is short VT_I2*/ public static final short VariantShort = 2; - /** variant's type is int VT_I4*/ + /** variant's type is int VT_I4, a Long in VC*/ public static final short VariantInt = 3; /** variant's type is float VT_R4*/ @@ -350,6 +354,72 @@ public void putStringRef(String in){ getvt(); putVariantStringRef(in); } + + /** + * Puts a variant into this variant making it type VT_VARIANT. + * Added 1.12 pre 6 + * + * @throws IllegalArgumentException + * if inVariant = null + * @param in + * a variant that is to be referenced by this variant + */ + public void putVariant(Variant inVariant) { + if (inVariant == null) { + throw new IllegalArgumentException("Cannot put null in as a variant"); + } else { + putVariantVariant(inVariant); + } + } + + /** + * All VariantVariant type variants are BYREF. + * + * Set the content of this variant to a string (VT_VARIANT|VT_BYREF). + * + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * @param in variant to be wrapped + * + */ + private native void putVariantVariant(Variant in); + + /** + * Used to get the value from a windows type of VT_VARIANT + * or a jacob Variant type of VariantVariant. + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * @returns Object a java Object that represents the content of the enclosed Variant + */ + public Object getVariant() { + if ((this.getvt() & VariantVariant) == VariantVariant + && (this.getvt() & VariantByref) == VariantByref) { + if (JacobObject.isDebugEnabled()){ + JacobObject.debug("About to call getVariantVariant()"); + } + Variant enclosedVariant = getVariantVariant(); + Object enclosedVariantAsJava = enclosedVariant.toJavaObject(); + // zero out the reference to the underlying windows memory so that + // it is still only owned in one place by one java object + // (this object of type VariantVariant) + //enclosedVariant.putEmpty(); // don't know if this would have had side effects + if (JacobObject.isDebugEnabled()){ + JacobObject.debug("Zeroing out enclosed Variant's ref to windows memory"); + } + enclosedVariant.m_pVariant = 0; + return enclosedVariantAsJava; + } else { + throw new IllegalStateException( + "getVariant() only legal on Variants of type VariantVariant, not " + + this.getvt()); + } + } + + /** + * Returns the variant type via a native method call. + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * @return Variant one of the VT_Variant types + */ + private native Variant getVariantVariant(); + /** * get the content of this variant as a short * @return short @@ -1451,6 +1521,9 @@ public Variant(Object pValueObject, boolean fByRef) { putDispatchRef((Dispatch)pValueObject); else putDispatch((Dispatch)pValueObject); + } else if (pValueObject instanceof Variant){ + // newly added 1.12-pre6 + putVariant((Variant)pValueObject); } else { // should really throw an illegal argument exception if its an invalid type if (fByRef) @@ -1629,12 +1702,13 @@ public boolean isNull(){ *

* Unlike other toXXX() methods, it does not do a type conversion * except for special data types (it shouldn't do any!) - * + *

+ * Converts Variant.VariantArray types to SafeArrays * @return Corresponding Java object of the type matching the Variant type. * @throws IllegalStateException if no underlying windows data structure * @throws NotImplementedException if unsupported conversion is requested */ - protected Object toJavaObject() throws JacobException { + public Object toJavaObject() throws JacobException { Object result = null; short type = this.getvt(); //variant type @@ -1707,8 +1781,11 @@ protected Object toJavaObject() throws JacobException { case Variant.VariantBoolean | Variant.VariantByref: //11 result = new Boolean(this.getBooleanRef()); break; - case Variant.VariantVariant : //12 - result = new NotImplementedException("toJavaObject() Not implemented for VariantVariant"); + case Variant.VariantVariant : //12 they are always by ref + result = new NotImplementedException("toJavaObject() Not implemented for VariantVariant without ByRef"); + break; + case Variant.VariantVariant | Variant.VariantByref: //12 + result = getVariant(); break; case Variant.VariantObject : //13 result = new NotImplementedException("toJavaObject() Not implemented for VariantObject");