mirror of https://github.com/sipwise/jitsi.git
parent
58166d140e
commit
273bdaac93
@ -1,8 +1,452 @@
|
||||
#include "net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery.h"
|
||||
|
||||
#include "MsOutlookMAPI.h"
|
||||
#include "MsOutlookMAPIHResultException.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define WIND32_MEAN_AND_LEAK
|
||||
#include <windows.h>
|
||||
|
||||
static void Exception_throwNew
|
||||
(JNIEnv *jniEnv, const char *className, const char *message);
|
||||
|
||||
static jboolean MsOutlookAddressBookContactQuery_foreachMailUser
|
||||
(ULONG objType, LPUNKNOWN iUnknown,
|
||||
JNIEnv *jniEnv,
|
||||
jstring query,
|
||||
jobject callback, jmethodID callbackMethodID);
|
||||
static jboolean MsOutlookAddressBookContactQuery_foreachMailUserInContainerTable
|
||||
(LPMAPICONTAINER mapiContainer, LPMAPITABLE mapiTable,
|
||||
JNIEnv *jniEnv,
|
||||
jstring query,
|
||||
jobject callback, jmethodID callbackMethodID);
|
||||
static void MsOutlookAddressBookContactQuery_freeSRowSet(LPSRowSet rows);
|
||||
static jboolean MsOutlookAddressBookContactQuery_mailUserMatches
|
||||
(LPMAPIPROP mailUser, JNIEnv *jniEnv, jstring query);
|
||||
|
||||
static void
|
||||
Exception_throwNew(JNIEnv *jniEnv, const char *className, const char *message)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
clazz = jniEnv->FindClass(className);
|
||||
if (clazz)
|
||||
jniEnv->ThrowNew(clazz, message);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery_foreachMailUser
|
||||
(JNIEnv *jniEnv, jclass clazz, jstring query, jobject callback)
|
||||
{
|
||||
jclass callbackClass;
|
||||
jmethodID callbackMethodID;
|
||||
|
||||
HRESULT hResult;
|
||||
LPMAPISESSION mapiSession;
|
||||
|
||||
/*
|
||||
* Make sure that the specified arguments are valid. For example, check
|
||||
* whether callback exists and has the necessary signature.
|
||||
*/
|
||||
if (!callback)
|
||||
{
|
||||
Exception_throwNew(
|
||||
jniEnv, "java/lang/NullPointerException", "callback");
|
||||
return;
|
||||
}
|
||||
callbackClass = jniEnv->GetObjectClass(callback);
|
||||
if (!callbackClass)
|
||||
return;
|
||||
callbackMethodID = jniEnv->GetMethodID(callbackClass, "callback", "(J)Z");
|
||||
if (!callbackMethodID)
|
||||
{
|
||||
Exception_throwNew(
|
||||
jniEnv, "java/lang/IllegalArgumentException", "callback");
|
||||
return;
|
||||
}
|
||||
|
||||
hResult
|
||||
= MAPILogonEx(
|
||||
0,
|
||||
NULL, NULL,
|
||||
MAPI_EXTENDED | MAPI_NO_MAIL | MAPI_USE_DEFAULT,
|
||||
&mapiSession);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
LPADRBOOK adrBook;
|
||||
|
||||
hResult = mapiSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &adrBook);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
ULONG objType;
|
||||
LPUNKNOWN iUnknown;
|
||||
|
||||
hResult = adrBook->OpenEntry(0, NULL, NULL, 0, &objType, &iUnknown);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
MsOutlookAddressBookContactQuery_foreachMailUser(
|
||||
objType, iUnknown,
|
||||
jniEnv, query, callback, callbackMethodID);
|
||||
|
||||
iUnknown->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
MsOutlookMAPIHResultException_throwNew(
|
||||
jniEnv,
|
||||
hResult,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
adrBook->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
MsOutlookMAPIHResultException_throwNew(
|
||||
jniEnv,
|
||||
hResult,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
mapiSession->Logoff(0, 0, 0);
|
||||
mapiSession->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
MsOutlookMAPIHResultException_throwNew(
|
||||
jniEnv,
|
||||
hResult,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery_IMAPIProp_1GetProps
|
||||
(JNIEnv *jniEnv, jclass clazz,
|
||||
jlong mapiProp, jlongArray propIds, jlong flags)
|
||||
{
|
||||
jsize propIdCount;
|
||||
LPSPropTagArray propTagArray;
|
||||
jobjectArray props = NULL;
|
||||
|
||||
propIdCount = jniEnv->GetArrayLength(propIds);
|
||||
if (S_OK
|
||||
== MAPIAllocateBuffer(
|
||||
CbNewSPropTagArray(propIdCount),
|
||||
(void **) &propTagArray))
|
||||
{
|
||||
jsize i;
|
||||
|
||||
propTagArray->cValues = propIdCount;
|
||||
for (i = 0; i < propIdCount; i++)
|
||||
{
|
||||
jlong propId;
|
||||
|
||||
jniEnv->GetLongArrayRegion(propIds, i, 1, &propId);
|
||||
if (JNI_TRUE == jniEnv->ExceptionCheck())
|
||||
{
|
||||
MAPIFreeBuffer(propTagArray);
|
||||
propTagArray = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(propTagArray->aulPropTag + i)
|
||||
= PROP_TAG(PT_UNSPECIFIED, propId);
|
||||
}
|
||||
}
|
||||
if (propTagArray)
|
||||
{
|
||||
HRESULT hResult;
|
||||
ULONG propCount;
|
||||
LPSPropValue propArray;
|
||||
|
||||
hResult
|
||||
= ((LPMAPIPROP) mapiProp)->GetProps(
|
||||
propTagArray,
|
||||
(ULONG) flags,
|
||||
&propCount, &propArray);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
jclass objectClass;
|
||||
ULONG j;
|
||||
|
||||
objectClass = jniEnv->FindClass("java/lang/Object");
|
||||
if (objectClass)
|
||||
{
|
||||
props
|
||||
= jniEnv->NewObjectArray(
|
||||
(jsize) propCount,
|
||||
objectClass,
|
||||
NULL);
|
||||
}
|
||||
for (j = 0; j < propCount; j++)
|
||||
{
|
||||
LPSPropValue prop = propArray;
|
||||
|
||||
if (props)
|
||||
{
|
||||
switch (PROP_TYPE(prop->ulPropTag))
|
||||
{
|
||||
case PT_STRING8:
|
||||
{
|
||||
jstring value;
|
||||
|
||||
value = jniEnv->NewStringUTF(prop->Value.lpszA);
|
||||
if (value)
|
||||
{
|
||||
jniEnv->SetObjectArrayElement(props, j, value);
|
||||
if (jniEnv->ExceptionCheck())
|
||||
props = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_UNICODE:
|
||||
{
|
||||
jstring value;
|
||||
|
||||
value
|
||||
= jniEnv->NewString(
|
||||
(const jchar *) (prop->Value.lpszW),
|
||||
wcslen(prop->Value.lpszW));
|
||||
if (value)
|
||||
{
|
||||
jniEnv->SetObjectArrayElement(props, j, value);
|
||||
if (jniEnv->ExceptionCheck())
|
||||
props = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MAPIFreeBuffer(prop);
|
||||
propArray++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MsOutlookMAPIHResultException_throwNew(
|
||||
jniEnv,
|
||||
hResult,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
MAPIFreeBuffer(propTagArray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MsOutlookMAPIHResultException_throwNew(
|
||||
jniEnv,
|
||||
MAPI_E_NOT_ENOUGH_MEMORY,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MsOutlookAddressBookContactQuery_foreachMailUser
|
||||
(ULONG objType, LPUNKNOWN iUnknown,
|
||||
JNIEnv *jniEnv,
|
||||
jstring query,
|
||||
jobject callback, jmethodID callbackMethodID)
|
||||
{
|
||||
jboolean proceed;
|
||||
|
||||
switch (objType)
|
||||
{
|
||||
case MAPI_ABCONT:
|
||||
{
|
||||
LPMAPICONTAINER mapiContainer = (LPMAPICONTAINER) iUnknown;
|
||||
|
||||
HRESULT hResult;
|
||||
LPMAPITABLE mapiTable;
|
||||
|
||||
proceed = JNI_TRUE;
|
||||
|
||||
/* Look for MAPI_MAILUSER through the contents. */
|
||||
mapiTable = NULL;
|
||||
hResult = mapiContainer->GetContentsTable(0, &mapiTable);
|
||||
if (HR_SUCCEEDED(hResult) && mapiTable)
|
||||
{
|
||||
proceed
|
||||
= MsOutlookAddressBookContactQuery_foreachMailUserInContainerTable(
|
||||
mapiContainer, mapiTable,
|
||||
jniEnv, query, callback, callbackMethodID);
|
||||
mapiTable->Release();
|
||||
}
|
||||
|
||||
/* Drill down the hierarchy. */
|
||||
if (JNI_TRUE == proceed)
|
||||
{
|
||||
mapiTable = NULL;
|
||||
hResult = mapiContainer->GetHierarchyTable(0, &mapiTable);
|
||||
if (HR_SUCCEEDED(hResult) && mapiTable)
|
||||
{
|
||||
proceed
|
||||
= MsOutlookAddressBookContactQuery_foreachMailUserInContainerTable(
|
||||
mapiContainer, mapiTable,
|
||||
jniEnv, query, callback, callbackMethodID);
|
||||
mapiTable->Release();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MAPI_MAILUSER:
|
||||
{
|
||||
if (JNI_TRUE
|
||||
== MsOutlookAddressBookContactQuery_mailUserMatches(
|
||||
(LPMAPIPROP) iUnknown,
|
||||
jniEnv, query))
|
||||
{
|
||||
/* Report the MAPI_MAILUSER to the callback. */
|
||||
proceed
|
||||
= jniEnv->CallBooleanMethod(
|
||||
callback, callbackMethodID,
|
||||
iUnknown);
|
||||
/*
|
||||
* XXX When an exception is thrown in the callback, does proceed get
|
||||
* assigned JNI_FALSE?
|
||||
*/
|
||||
if ((JNI_TRUE == proceed) && (JNI_TRUE == jniEnv->ExceptionCheck()))
|
||||
proceed = JNI_FALSE;
|
||||
}
|
||||
else
|
||||
proceed = JNI_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return proceed;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MsOutlookAddressBookContactQuery_foreachMailUserInContainerTable
|
||||
(LPMAPICONTAINER mapiContainer, LPMAPITABLE mapiTable,
|
||||
JNIEnv *jniEnv,
|
||||
jstring query,
|
||||
jobject callback, jmethodID callbackMethodID)
|
||||
{
|
||||
HRESULT hResult;
|
||||
jboolean proceed;
|
||||
|
||||
hResult = mapiTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
LPSRowSet rows;
|
||||
|
||||
proceed = JNI_TRUE;
|
||||
while ((JNI_TRUE == proceed)
|
||||
&& HR_SUCCEEDED(hResult = mapiTable->QueryRows(1, 0, &rows)))
|
||||
{
|
||||
if (rows->cRows == 1)
|
||||
{
|
||||
ULONG i;
|
||||
LPSRow row = rows->aRow;
|
||||
ULONG objType = 0;
|
||||
SBinary entryIDBinary = {0, NULL};
|
||||
|
||||
for (i = 0; i < row->cValues; i++)
|
||||
{
|
||||
LPSPropValue prop = (row->lpProps) + i;
|
||||
|
||||
switch (prop->ulPropTag)
|
||||
{
|
||||
case PR_OBJECT_TYPE:
|
||||
objType = prop->Value.ul;
|
||||
break;
|
||||
case PR_ENTRYID:
|
||||
entryIDBinary = prop->Value.bin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (objType && entryIDBinary.cb && entryIDBinary.lpb)
|
||||
{
|
||||
LPENTRYID entryID;
|
||||
|
||||
if (S_OK
|
||||
== MAPIAllocateBuffer(
|
||||
entryIDBinary.cb,
|
||||
(void **) &entryID))
|
||||
{
|
||||
LPUNKNOWN iUnknown;
|
||||
|
||||
CopyMemory(
|
||||
entryID,
|
||||
entryIDBinary.lpb,
|
||||
entryIDBinary.cb);
|
||||
|
||||
/*
|
||||
* We no longer need the rows at this point so free them
|
||||
* before we drill down the hierarchy and allocate even more rows.
|
||||
*/
|
||||
MsOutlookAddressBookContactQuery_freeSRowSet(rows);
|
||||
|
||||
hResult
|
||||
= mapiContainer->OpenEntry(
|
||||
entryIDBinary.cb, entryID,
|
||||
NULL,
|
||||
0,
|
||||
&objType, &iUnknown);
|
||||
if (HR_SUCCEEDED(hResult))
|
||||
{
|
||||
proceed
|
||||
= MsOutlookAddressBookContactQuery_foreachMailUser(
|
||||
objType, iUnknown,
|
||||
jniEnv, query, callback, callbackMethodID);
|
||||
iUnknown->Release();
|
||||
}
|
||||
|
||||
MAPIFreeBuffer(entryID);
|
||||
}
|
||||
else
|
||||
MsOutlookAddressBookContactQuery_freeSRowSet(rows);
|
||||
}
|
||||
else
|
||||
MsOutlookAddressBookContactQuery_freeSRowSet(rows);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPIFreeBuffer(rows);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We've failed but other parts of the hierarchy may still succeed. */
|
||||
proceed = JNI_TRUE;
|
||||
}
|
||||
return proceed;
|
||||
}
|
||||
|
||||
static void
|
||||
MsOutlookAddressBookContactQuery_freeSRowSet(LPSRowSet rows)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < rows->cRows; i++)
|
||||
{
|
||||
LPSRow row = (rows->aRow) + i;
|
||||
ULONG j;
|
||||
|
||||
for (j = 0; j < row->cValues; j++)
|
||||
{
|
||||
LPSPropValue prop = (row->lpProps) + j;
|
||||
|
||||
MAPIFreeBuffer(prop);
|
||||
}
|
||||
}
|
||||
MAPIFreeBuffer(rows);
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MsOutlookAddressBookContactQuery_mailUserMatches
|
||||
(LPMAPIPROP mailUser, JNIEnv *jniEnv, jstring query)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.msoutlook;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* Implements <tt>SourceContact</tt> for a <tt>MAPI_MAILUSER</tt>.
|
||||
*
|
||||
* @author Lyubomir Marinov
|
||||
*/
|
||||
public class MsOutlookMailUserSourceContact
|
||||
implements SourceContact
|
||||
{
|
||||
/**
|
||||
* The <tt>ContactDetail</tt>s of this <tt>SourceContact</tt>.
|
||||
*/
|
||||
private final List<ContactDetail> contactDetails;
|
||||
|
||||
/**
|
||||
* The <tt>ContactSourceService</tt> which has created this
|
||||
* <tt>SourceContact</tt>.
|
||||
*/
|
||||
private final MsOutlookAddressBookContactSourceService contactSource;
|
||||
|
||||
/**
|
||||
* The display name of this <tt>SourceContact</tt>.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Initializes a new <tt>MsOutlookMailUserSourceContact</tt> instance.
|
||||
*
|
||||
* @param contactSource the <tt>ContactSourceService</tt> which is creating
|
||||
* the new instance
|
||||
* @param displayName the display name of the new instance
|
||||
* @param contactDetails the <tt>ContactDetail</tt>s of the new instance
|
||||
*/
|
||||
public MsOutlookMailUserSourceContact(
|
||||
MsOutlookAddressBookContactSourceService contactSource,
|
||||
String displayName,
|
||||
List<ContactDetail> contactDetails)
|
||||
{
|
||||
this.contactSource = contactSource;
|
||||
this.displayName = displayName;
|
||||
this.contactDetails = contactDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>ContactDetail</tt>s of this <tt>SourceContact</tt>.
|
||||
*
|
||||
* @return the <tt>ContactDetail</tt>s of this <tt>SourceContact</tt>
|
||||
* @see SourceContact#getContactDetails()
|
||||
*/
|
||||
public List<ContactDetail> getContactDetails()
|
||||
{
|
||||
return Collections.unmodifiableList(contactDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>ContactDetail</tt>s of this <tt>SourceContact</tt> which
|
||||
* support a specific <tt>OperationSet</tt>.
|
||||
*
|
||||
* @param operationSet the <tt>OperationSet</tt> the supporting
|
||||
* <tt>ContactDetail</tt>s of which are to be returned
|
||||
* @return the <tt>ContactDetail</tt>s of this <tt>SourceContact</tt> which
|
||||
* support the specified <tt>operationSet</tt>
|
||||
* @see SourceContact#getContactDetails(Class)
|
||||
*/
|
||||
public List<ContactDetail> getContactDetails(
|
||||
Class<? extends OperationSet> operationSet)
|
||||
{
|
||||
List<ContactDetail> contactDetails = new LinkedList<ContactDetail>();
|
||||
|
||||
for (ContactDetail contactDetail : getContactDetails())
|
||||
{
|
||||
List<Class<? extends OperationSet>> supportedOperationSets
|
||||
= contactDetail.getSupportedOperationSets();
|
||||
|
||||
if ((supportedOperationSets != null)
|
||||
&& supportedOperationSets.contains(operationSet))
|
||||
contactDetails.add(contactDetail);
|
||||
}
|
||||
return contactDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>ContactSourceService</tt> which has created this
|
||||
* <tt>SourceContact</tt>.
|
||||
*
|
||||
* @return the <tt>ContactSourceService</tt> which has created this
|
||||
* <tt>SourceContact</tt>
|
||||
* @see SourceContact#getContactSource()
|
||||
*/
|
||||
public MsOutlookAddressBookContactSourceService getContactSource()
|
||||
{
|
||||
return contactSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display details of this <tt>SourceContact</tt>.
|
||||
*
|
||||
* @return the display details of this <tt>SourceContact</tt>
|
||||
* @see SourceContact#getDisplayDetails()
|
||||
*/
|
||||
public String getDisplayDetails()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name of this <tt>SourceContact</tt>.
|
||||
*
|
||||
* @return the display name of this <tt>SourceContact</tt>
|
||||
* @see SourceContact#getDisplayName()
|
||||
*/
|
||||
public String getDisplayName()
|
||||
{
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image/avatar of this <tt>SourceContact</tt>.
|
||||
*
|
||||
* @return the image/avatar of this <tt>SourceContact</tt>
|
||||
* @see SourceContact#getImage()
|
||||
*/
|
||||
public byte[] getImage()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the preferred <tt>ContactDetail</tt> for a specific
|
||||
* <tt>OperationSet</tt>.
|
||||
*
|
||||
* @param operationSet the <tt>OperationSet</tt> to get the preferred
|
||||
* <tt>ContactDetail</tt> for
|
||||
* @return the preferred <tt>ContactDetail</tt> for the specified
|
||||
* <tt>operationSet</tt>
|
||||
* @see SourceContact#getPreferredContactDetail(Class)
|
||||
*/
|
||||
public ContactDetail getPreferredContactDetail(
|
||||
Class<? extends OperationSet> operationSet)
|
||||
{
|
||||
List<ContactDetail> contactDetails = getContactDetails(operationSet);
|
||||
|
||||
return contactDetails.isEmpty() ? null : contactDetails.get(0);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue