Provides an initial implementation of searching in the Address Book of Microsoft Outlook.

cusax-fix
Lyubomir Marinov 15 years ago
parent 58166d140e
commit 273bdaac93

@ -2579,6 +2579,16 @@ org.apache.http.util"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN-MSOUTLOOK -->
<target name="bundle-msoutlook">
<!-- Creates a bundle which provides support for Microsoft Outlook. -->
<jar compress="false" destfile="${bundles.dest}/msoutlook.jar"
manifest="${src}/net/java/sip/communicator/plugin/msoutlook/msoutlook.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/msoutlook"
prefix="net/java/sip/communicator/plugin/msoutlook" />
</jar>
</target>
<target name="bundle-certificate">
<jar compress="false" destfile="${bundles.dest}/certificate.jar"
manifest="${src}/net/java/sip/communicator/impl/certificate/certificate.manifest.mf">

@ -4,6 +4,7 @@
#ifndef __in_opt
#define __in_opt
#endif /* #ifndef __in_opt */
#include <mapitags.h>
#include <mapix.h>
#endif /* #ifndef _NET_JAVA_SIP_COMMUNICATOR_PLUGIN_MSOUTLOOK_MSOUTLOOKMAPI_H_ */

@ -1,9 +1,8 @@
#include "MsOutlookMAPIHResultException.h"
#include <tchar.h>
void
MsOutlookMAPIHResultException_throwNew(JNIEnv *jniEnv, HRESULT hResult)
MsOutlookMAPIHResultException_throwNew
(JNIEnv *jniEnv, HRESULT hResult, LPCTSTR file, ULONG line)
{
jclass clazz;
@ -16,9 +15,33 @@ MsOutlookMAPIHResultException_throwNew(JNIEnv *jniEnv, HRESULT hResult)
switch (hResult)
{
case MAPI_E_LOGON_FAILED:
message = _T("MAPI_E_LOGON_FAILED");
break;
case MAPI_E_NO_ACCESS:
message = _T("MAPI_E_NO_ACCESS");
break;
case MAPI_E_NOT_ENOUGH_MEMORY:
message = _T("MAPI_E_NOT_ENOUGH_MEMORY");
break;
case MAPI_E_NOT_FOUND:
message = _T("MAPI_E_NOT_FOUND");
break;
case MAPI_E_NOT_INITIALIZED:
message = _T("MAPI_E_NOT_INITIALIZED");
break;
case MAPI_E_TIMEOUT:
message = _T("MAPI_E_TIMEOUT");
break;
case MAPI_E_UNKNOWN_ENTRYID:
message = _T("MAPI_E_UNKNOWN_ENTRYID");
break;
case MAPI_E_USER_CANCEL:
message = _T("MAPI_E_USER_CANCEL");
break;
case MAPI_W_ERRORS_RETURNED:
message = _T("MAPI_W_ERRORS_RETURNED");
break;
case S_OK:
message = _T("S_OK");
break;
@ -27,10 +50,41 @@ MsOutlookMAPIHResultException_throwNew(JNIEnv *jniEnv, HRESULT hResult)
break;
}
/*
* TODO Use MsOutlookMAPIHResultException(long, String) in order to
* communicate hResult as a HRESULT value.
*/
if (message)
{
jmethodID methodID;
methodID
= jniEnv->GetMethodID(
clazz,
"<init>",
"(JLjava/lang/String;)V");
if (methodID)
{
jobject t;
t = jniEnv->NewObject(clazz, methodID, hResult, message);
if (t)
jniEnv->Throw((jthrowable) t);
return;
}
}
{
jmethodID methodID;
methodID = jniEnv->GetMethodID(clazz, "<init>", "(J)V");
if (methodID)
{
jobject t;
t = jniEnv->NewObject(clazz, methodID, hResult);
if (t)
jniEnv->Throw((jthrowable) t);
return;
}
}
jniEnv->ThrowNew(clazz, message);
}
}

@ -3,12 +3,14 @@
#include <jni.h>
#include "MsOutlookMAPI.h"
#include <tchar.h>
#ifdef __cplusplus
extern "C" {
#endif /* #ifdef __cplusplus */
void MsOutlookMAPIHResultException_throwNew(JNIEnv *jniEnv, HRESULT hResult);
void MsOutlookMAPIHResultException_throwNew
(JNIEnv *jniEnv, HRESULT hResult, LPCTSTR file, ULONG line);
#ifdef __cplusplus
}

@ -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;
}

@ -15,6 +15,14 @@ extern "C" {
JNIEXPORT void JNICALL Java_net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery_foreachMailUser
(JNIEnv *, jclass, jstring, jobject);
/*
* Class: net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery
* Method: IMAPIProp_GetProps
* Signature: (J[JJ)[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactQuery_IMAPIProp_1GetProps
(JNIEnv *, jclass, jlong, jlongArray, jlong);
#ifdef __cplusplus
}
#endif

@ -13,7 +13,12 @@ Java_net_java_sip_communicator_plugin_msoutlook_MsOutlookAddressBookContactSourc
hResult = MAPIInitialize(&mapiInit);
if (HR_FAILED(hResult))
MsOutlookMAPIHResultException_throwNew(jniEnv, hResult);
{
MsOutlookMAPIHResultException_throwNew(
jniEnv,
hResult,
__FILE__, __LINE__);
}
}
JNIEXPORT void JNICALL

@ -174,15 +174,17 @@ public boolean isMatching(UIGroup uiGroup)
public void setFilterString(String filter)
{
// First escape all special characters from the given filter string.
this.filterString = Pattern.quote(filter);
this.filterString = filter;
// Then create the pattern.
// By default, case-insensitive matching assumes that only characters
// in the US-ASCII charset are being matched, that's why we use
// the UNICODE_CASE flag to enable unicode case-insensitive matching.
// Sun Bug ID: 6486934 "RegEx case_insensitive match is broken"
this.filterPattern = Pattern.compile(
filterString, Pattern.MULTILINE
this.filterPattern
= Pattern.compile(
Pattern.quote(filterString),
Pattern.MULTILINE
| Pattern.CASE_INSENSITIVE
| Pattern.UNICODE_CASE);
}
@ -304,9 +306,6 @@ public Collection<ExternalContactSource> getContactSources()
*/
public boolean hasDefaultSource()
{
if (searchSourceType == DEFAULT_SOURCE)
return true;
else
return false;
return (searchSourceType == DEFAULT_SOURCE);
}
}

@ -119,16 +119,23 @@ public ImageIcon getStatusIcon()
*/
public ImageIcon getAvatar(boolean isSelected, int width, int height)
{
ImageIcon icon = new ImageIcon(sourceContact.getImage());
byte[] image = sourceContact.getImage();
if (icon.getIconWidth() > width
|| icon.getIconHeight() > height)
if (image != null)
{
icon = ImageUtils
.getScaledRoundedIcon(icon.getImage(), width, height);
ImageIcon icon = new ImageIcon();
if (icon.getIconWidth() > width || icon.getIconHeight() > height)
{
icon
= ImageUtils.getScaledRoundedIcon(
icon.getImage(),
width, height);
}
return icon;
}
return icon;
else
return null;
}
/**
@ -186,8 +193,11 @@ public List<UIContactDetail> getContactDetailsForOperationSet(
while (details.hasNext())
{
ContactDetail detail = details.next();
List<Class<? extends OperationSet>> supportedOperationSets
= detail.getSupportedOperationSets();
if (detail.getSupportedOperationSets().contains(opSetClass))
if ((supportedOperationSets != null)
&& supportedOperationSets.contains(opSetClass))
resultList.add(new SourceContactDetail(detail, opSetClass));
}
return resultList;

@ -18,6 +18,102 @@
public class MsOutlookAddressBookContactQuery
extends AbstractContactQuery<MsOutlookAddressBookContactSourceService>
{
/**
* The IDs of the properties of <tt>MAPI_MAILUSER</tt> which are to be
* queried by the <tt>MsOutlookAddressBookContactQuery</tt> instances.
*/
private static final long[] MAPI_MAILUSER_PROP_IDS
= new long[]
{
0x3001 /* PR_DISPLAY_NAME */,
0x3003 /* PR_EMAIL_ADDRESS */,
0x3A06 /* PR_GIVEN_NAME */,
0x3A44 /* PR_MIDDLE_NAME */,
0x3A11 /* PR_SURNAME */,
0x3A08 /* PR_BUSINESS_TELEPHONE_NUMBER */,
0x3A1B /* PR_BUSINESS2_TELEPHONE_NUMBER */,
0x3A09 /* PR_HOME_TELEPHONE_NUMBER */,
0x3A2F /* PR_HOME2_TELEPHONE_NUMBER */,
0x3A1C /* PR_MOBILE_TELEPHONE_NUMBER */
};
/**
* The index of the id of the <tt>PR_BUSINESS_TELEPHONE_NUMBER</tt> property
* in {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_BUSINESS_TELEPHONE_NUMBER_INDEX = 5;
/**
* The index of the id of the <tt>PR_BUSINESS2_TELEPHONE_NUMBER</tt>
* property in {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_BUSINESS2_TELEPHONE_NUMBER_INDEX = 6;
/**
* The index of the id of the <tt>PR_DISPLAY_NAME</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_DISPLAY_NAME_INDEX = 0;
/**
* The index of the id of the <tt>PR_EMAIL_ADDRESS</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_EMAIL_ADDRESS_INDEX = 1;
/**
* The index of the id of the <tt>PR_GIVEN_NAME</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_GIVEN_NAME_INDEX = 2;
/**
* The index of the id of the <tt>PR_HOME_TELEPHONE_NUMBER</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_HOME_TELEPHONE_NUMBER_INDEX = 7;
/**
* The index of the id of the <tt>PR_HOME2_TELEPHONE_NUMBER</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_HOME2_TELEPHONE_NUMBER_INDEX = 8;
/**
* The index of the id of the <tt>PR_MIDDLE_NAME</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_MIDDLE_NAME_INDEX = 3;
/**
* The index of the id of the <tt>PR_MOBILE_TELEPHONE_NUMBER</tt> property
* in {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_MOBILE_TELEPHONE_NUMBER_INDEX = 9;
/**
* The index of the id of the <tt>PR_SURNAME</tt> property in
* {@link #MAPI_MAILUSER_PROP_IDS}.
*/
private static final int PR_SURNAME_INDEX = 4;
/**
* The indexes in {@link #MAPI_MAILUSER_PROP_IDS} of the property IDs which
* are to be represented in <tt>SourceContact</tt> as
* <tt>ContactDetail</tt>s.
*/
private static final int[] CONTACT_DETAIL_PROP_INDEXES
= new int[]
{
PR_EMAIL_ADDRESS_INDEX,
PR_BUSINESS_TELEPHONE_NUMBER_INDEX,
PR_BUSINESS2_TELEPHONE_NUMBER_INDEX,
PR_HOME_TELEPHONE_NUMBER_INDEX,
PR_HOME2_TELEPHONE_NUMBER_INDEX,
PR_MOBILE_TELEPHONE_NUMBER_INDEX
};
static
{
System.loadLibrary("jmsoutlook");
@ -57,7 +153,7 @@ public MsOutlookAddressBookContactQuery(
{
super(msoabcss);
this.query = query;
this.query = (query == null) ? null : query.toLowerCase();
}
/**
@ -66,7 +162,8 @@ public MsOutlookAddressBookContactQuery(
* which matches a specific <tt>String</tt>.
*
* @param query the <tt>String</tt> for which the Address Book of Microsoft
* Outlook is to be queried
* Outlook is to be queried. <bb>Warning</bb>: Ignored at the time of this
* writing.
* @param callback the <tt>MsOutlookAddressBookCallback</tt> to be notified
* about the matching <tt>MAPI_MAILUSER</tt>s
*/
@ -94,6 +191,11 @@ public List<SourceContact> getQueryResults()
return qr;
}
private static native Object[] IMAPIProp_GetProps(
long mapiProp,
long[] propIds, long flags)
throws MsOutlookMAPIHResultException;
/**
* Notifies this <tt>MsOutlookAddressBookContactQuery</tt> about a specific
* <tt>MAPI_MAILUSER</tt>.
@ -102,10 +204,52 @@ public List<SourceContact> getQueryResults()
* <tt>MAPI_MAILUSER</tt> to notify about
* @return <tt>true</tt> if this <tt>MsOutlookAddressBookContactQuery</tt>
* is to continue being called; otherwise, <tt>false</tt>
* @throws MsOutlookMAPIHResultException if anything goes wrong while
* getting the properties of the specified <tt>MAPI_MAILUSER</tt>
*/
private boolean onMailUser(long iUnknown)
throws MsOutlookMAPIHResultException
{
// TODO Auto-generated method stub
Object[] props
= IMAPIProp_GetProps(iUnknown, MAPI_MAILUSER_PROP_IDS, 0);
boolean matches = false;
for (Object prop : props)
{
if ((prop instanceof String)
&& ((String) prop).toLowerCase().contains(query))
{
matches = true;
break;
}
}
if (matches)
{
List<ContactDetail> contactDetails
= new LinkedList<ContactDetail>();
for (int i = 0; i < CONTACT_DETAIL_PROP_INDEXES.length; i++)
{
Object prop = props[CONTACT_DETAIL_PROP_INDEXES[i]];
if (prop instanceof String)
{
String stringProp = (String) prop;
if (stringProp.length() != 0)
contactDetails.add(new ContactDetail(stringProp));
}
}
SourceContact sourceContact
= new MsOutlookMailUserSourceContact(
getContactSource(),
(String) props[PR_DISPLAY_NAME_INDEX],
contactDetails);
queryResults.add(sourceContact);
fireContactReceived(sourceContact);
}
return (getStatus() == QUERY_IN_PROGRESS);
}
@ -130,7 +274,15 @@ public void run()
{
public boolean callback(long iUnknown)
{
return onMailUser(iUnknown);
try
{
return onMailUser(iUnknown);
}
catch (MsOutlookMAPIHResultException ex)
{
ex.printStackTrace(System.err);
return false;
}
}
});
}

@ -28,7 +28,7 @@ public class MsOutlookMAPIHResultException
*/
public MsOutlookMAPIHResultException(long hResult)
{
this.hResult = hResult;
this(hResult, toString(hResult));
}
/**
@ -70,4 +70,28 @@ public long getHResult()
{
return hResult;
}
/**
* Converts a specific <tt>HRESULT</tt> to a touch more readable
* <tt>String</tt> in accord with the rule of constructing MAPI
* <tt>HRESULT</tt> values.
*
* @param hResult the <tt>HRESULT</tt> to convert
* @return a <tt>String</tt> which represents the specified <tt>hResult</tt>
* in a touch more readable form
*/
private static String toString(long hResult)
{
if (hResult == 0)
return "S_OK";
else
{
StringBuilder s = new StringBuilder("MAPI_");
s.append(((hResult & 0x80000000L) == 0) ? 'W' : 'E');
s.append("_0x");
s.append(Long.toHexString(hResult & 0xFFFL));
return s.toString();
}
}
}

@ -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);
}
}

@ -4,5 +4,6 @@ Bundle-Name: Microsoft Outlook support
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
Import-Package: net.java.sip.communicator.service.contactsource,
net.java.sip.communicator.service.protocol,
org.osgi.framework
System-Bundle: yes

Loading…
Cancel
Save