blob: 8feca9e86ca62234448e91b1be048477ce1c0467 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Hisashi MIYASHITA - initial API and implementation
* Daisuke SATO
*******************************************************************************/
/*
Java <-> COM Type Bridge
*/
#include "Com.h"
/*
VT_NULL
VT_BOOL
VT_BSTR
VT_CY
VT_DATE
VT_DISPATCH
VT_EMPTY
VT_ERROR
VT_I1
VT_I2
VT_I4
VT_INT
VT_I8
VT_R4
VT_R8
VT_UI1
VT_UI2
VT_UI4
VT_UINT
VT_UNKNOWN
VT_BOOL | VT_BYREF
VT_BSTR | VT_BYREF
VT_CY | VT_BYREF
VT_DATE | VT_BYREF
VT_DECIMAL | VT_BYREF
VT_DISPATCH | VT_BYREF
VT_ERROR | VT_BYREF
VT_I1 | VT_BYREF
VT_I2 | VT_BYREF
VT_I4 | VT_BYREF
VT_INT | VT_BYREF
VT_I8 | VT_BYREF
VT_R4 | VT_BYREF
VT_R8 | VT_BYREF
VT_UI1 | VT_BYREF
VT_UI2 | VT_BYREF
VT_UI4 | VT_BYREF
VT_UINT | VT_BYREF
VT_UNKNOWN | VT_BYREF
VT_VARIANT | VT_BYREF
VT_GUID | VT_BYREF
VT_ARRAY | *
*/
int j2v(JNIEnv* env, jobject o, VARIANT* v)
{
if (!o) {
v->vt = VT_NULL;
return 1;
}
if (env->IsInstanceOf(o, class_java_lang_string)) {
jstring js = (jstring) o;
v->vt = VT_BSTR;
int len = env->GetStringLength(js);
const jchar* jc = env->GetStringChars(js, NULL);
v->bstrVal = SysAllocStringLen((OLECHAR*) jc, len);
env->ReleaseStringChars(js, jc);
} else if (env->IsInstanceOf(o, class_IDispatch)) {
v->vt = VT_DISPATCH;
v->pdispVal = (IDispatch*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_IUnknown)) {
v->vt = VT_UNKNOWN;
v->punkVal = (IUnknown*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_java_lang_boolean)) {
v->vt = VT_BOOL;
v->boolVal = env->CallBooleanMethod(o, booleanValue);
} else if (env->IsInstanceOf(o, class_java_lang_integer)) {
v->vt = VT_I4;
v->lVal = env->CallIntMethod(o, intValue);
} else if (env->IsInstanceOf(o, class_java_lang_byte)) {
v->vt = VT_UI1;
v->bVal = (BYTE) env->CallByteMethod(o, byteValue);
} else if (env->IsInstanceOf(o, class_java_lang_short)) {
v->vt = VT_I2;
v->iVal = env->CallShortMethod(o, shortValue);
} else if (env->IsInstanceOf(o, class_java_lang_long)) {
v->vt = VT_I8;
v->llVal = env->CallLongMethod(o, longValue);
} else if (env->IsInstanceOf(o, class_java_lang_double)) {
v->vt = VT_R8;
v->dblVal = env->CallDoubleMethod(o, doubleValue);
} else if (env->IsInstanceOf(o, class_java_lang_float)) {
v->vt = VT_R4;
v->fltVal = env->CallFloatMethod(o, floatValue);
} else if (env->IsInstanceOf(o, class_RefString)) {
v->vt = VT_BSTR | VT_BYREF;
v->pbstrVal = (BSTR*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefInt)) {
v->vt = VT_I4 | VT_BYREF;
v->pintVal = (INT*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefByte)) {
v->vt = VT_UI1 | VT_BYREF;
v->pbVal = (BYTE*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefShort)) {
v->vt = VT_I2 | VT_BYREF;
v->piVal = (SHORT*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefLong)) {
v->vt = VT_I8 | VT_BYREF;
v->pllVal = (LONGLONG*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefDouble)) {
v->vt = VT_R8 | VT_BYREF;
v->pdblVal = (DOUBLE*) getPtr(env, o);
} else if (env->IsInstanceOf(o, class_RefFloat)) {
v->vt = VT_R4 | VT_BYREF;
v->pfltVal = (FLOAT*) getPtr(env, o);
} else {
//
// currently do not support safearray, CY, DATE, ERROR.
//
wchar_t *pobjstr = jobject_to_string(env, o);
throw_DispatchException(env, L"%s is not yet supported.", pobjstr);
free(pobjstr);
return 0;
}
return 1;
}
jobject v2j(JNIEnv* env, jobject jidisp, VARIANT* v)
{
if (v->vt & VT_ARRAY) {
return jc_make_array(env, jidisp, v);
}
if (v->vt & VT_BYREF) {
// TODO
return NULL;
}
switch (v->vt) {
case VT_NULL:
return NULL;
case VT_BOOL:
return env->NewObject(class_java_lang_boolean,
booleanConstructor,
v->boolVal ? JNI_TRUE : JNI_FALSE);
case VT_BSTR:
{
int len = SysStringLen(v->bstrVal);
return env->NewString((const jchar*) v->bstrVal, len);
}
case VT_I1:
return env->NewObject(class_java_lang_byte,
byteConstructor, (jbyte) v->cVal);
case VT_I2:
return env->NewObject(class_java_lang_short,
shortConstructor, (jshort) v->iVal);
case VT_INT:
return env->NewObject(class_java_lang_integer,
intConstructor, (jint) v->intVal);
case VT_I4:
return env->NewObject(class_java_lang_integer,
intConstructor, (jint) v->lVal);
case VT_I8:
return env->NewObject(class_java_lang_long,
longConstructor, (jlong) v->llVal);
case VT_R4:
return env->NewObject(class_java_lang_float,
floatConstructor, (jfloat) v->fltVal);
case VT_R8:
return env->NewObject(class_java_lang_double,
doubleConstructor, (jdouble) v->dblVal);
case VT_DISPATCH:
return create_IDispatch(env, jidisp, v->pdispVal);
case VT_UNKNOWN:
return create_IUnknown(env, jidisp, v->punkVal);
case VT_UI1:
return env->NewObject(class_java_lang_byte,
byteConstructor, (jbyte) v->bVal);
/* All unsigned integers other than byte are treated as long in Java. */
case VT_UI2:
return env->NewObject(class_java_lang_long,
longConstructor, (jlong) v->uiVal);
case VT_UI4:
return env->NewObject(class_java_lang_long,
longConstructor, (jlong) v->ulVal);
case VT_UINT:
return env->NewObject(class_java_lang_long,
longConstructor, (jlong) v->uintVal);
case VT_EMPTY:
// This should be illegal but it is used for representing void.
// throw_DispatchException(env, L"Unexpectedly VT_EMPTY is returned!");
return NULL;
case VT_CY:
throw_DispatchException(env, L"VT_CY is not yet supported.");
break;
case VT_DATE:
throw_DispatchException(env, L"VT_DATE is not yet supported.");
break;
case VT_ERROR:
throw_DispatchException(env, L"VT_ERROR is not yet supported.");
break;
default:
throw_DispatchException(env, L"Unexpected variant type:%x.", v->vt);
break;
}
return NULL;
}
int
jc_variant_clear(VARIANT* pv, int releaseIUnknown)
{
switch (pv->vt) {
case VT_BSTR:
SysFreeString(pv->bstrVal);
return 1;
case VT_DISPATCH:
if (releaseIUnknown) {
IDispatch* pdispVal = pv->pdispVal;
if (pdispVal) {
pdispVal->Release();
}
}
return 1;
case VT_UNKNOWN:
if (releaseIUnknown) {
IUnknown* punkVal = pv->punkVal;
if (punkVal) {
punkVal->Release();
}
}
return 1;
case VT_ARRAY:
SafeArrayDestroy(pv->parray);
return 0;
}
return 1;
}