diff options
Diffstat (limited to 'src/net/java/sip/communicator/plugin/addrbook')
11 files changed, 1134 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/plugin/addrbook/AddrBookActivator.java b/src/net/java/sip/communicator/plugin/addrbook/AddrBookActivator.java new file mode 100644 index 0000000..854972d --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/AddrBookActivator.java @@ -0,0 +1,115 @@ +/*
+ * 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.addrbook;
+
+import net.java.sip.communicator.service.contactsource.*;
+import net.java.sip.communicator.util.*;
+
+import org.osgi.framework.*;
+
+/**
+ * Implements <tt>BundleActivator</tt> for the addrbook plug-in which provides
+ * support for OS-specific Address Book.
+ *
+ * @author Lyubomir Marinov
+ */
+public class AddrBookActivator
+ implements BundleActivator
+{
+ /**
+ * The <tt>ContactSourceService</tt> implementation for the OS-specific
+ * Address Book.
+ */
+ private ContactSourceService css;
+
+ /**
+ * The <tt>ServiceRegistration</tt> of {@link #css} in the
+ * <tt>BundleContext</tt> in which this <tt>AddrBookActivator</tt> has been
+ * started.
+ */
+ private ServiceRegistration cssServiceRegistration;
+
+ /**
+ * Starts the addrbook plug-in.
+ *
+ * @param bundleContext the <tt>BundleContext</tt> in which the addrbook
+ * plug-in is to be started
+ * @throws Exception if anything goes wrong while starting the addrbook
+ * plug-in
+ * @see BundleActivator#start(BundleContext)
+ */
+ public void start(BundleContext bundleContext)
+ throws Exception
+ {
+ String cssClassName;
+
+ if (OSUtils.IS_WINDOWS)
+ {
+ cssClassName
+ = "net.java.sip.communicator.plugin.addrbook"
+ + ".msoutlook.MsOutlookAddrBookContactSourceService";
+ }
+ else if (OSUtils.IS_MAC)
+ {
+ cssClassName
+ = "net.java.sip.communicator.plugin.addrbook"
+ + ".macosx.MacOSXAddrBookContactSourceService";
+ }
+ else
+ return;
+
+ css = (ContactSourceService) Class.forName(cssClassName).newInstance();
+ try
+ {
+ cssServiceRegistration
+ = bundleContext.registerService(
+ ContactSourceService.class.getName(),
+ css,
+ null);
+ }
+ finally
+ {
+ if (cssServiceRegistration == null)
+ {
+ if (css instanceof AsyncContactSourceService)
+ ((AsyncContactSourceService) css).stop();
+ css = null;
+ }
+ }
+ }
+
+ /**
+ * Stops the addrbook plug-in.
+ *
+ * @param bundleContext the <tt>BundleContext</tt> in which the addrbook
+ * plug-in is to be stopped
+ * @throws Exception if anything goes wrong while stopping the addrbook
+ * plug-in
+ * @see BundleActivator#stop(BundleContext)
+ */
+ public void stop(BundleContext bundleContext)
+ throws Exception
+ {
+ try
+ {
+ if (cssServiceRegistration != null)
+ {
+ cssServiceRegistration.unregister();
+ cssServiceRegistration = null;
+ }
+ }
+ finally
+ {
+ if (css != null)
+ {
+ if (css instanceof AsyncContactSourceService)
+ ((AsyncContactSourceService) css).stop();
+ css = null;
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/AsyncContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/AsyncContactQuery.java new file mode 100644 index 0000000..d03742c --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/AsyncContactQuery.java @@ -0,0 +1,148 @@ +/*
+ * 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.addrbook;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.contactsource.*;
+
+/**
+ * Provides an abstract implementation of a <tt>ContactQuery</tt> which runs in
+ * a separate <tt>Thread</tt>.
+ *
+ * @author Lyubomir Marinov
+ * @param <T> the very type of <tt>ContactSourceService</tt> which performs the
+ * <tt>ContactQuery</tt>
+ */
+public abstract class AsyncContactQuery<T extends ContactSourceService>
+ extends AbstractContactQuery<T>
+{
+
+ /**
+ * The <tt>String</tt> for which the associated
+ * <tt>ContactSourceService</tt> is being queried.
+ */
+ protected final String query;
+
+ /**
+ * The <tt>SourceContact</tt>s which match {@link #query}.
+ */
+ private final List<SourceContact> queryResults
+ = new LinkedList<SourceContact>();
+
+ /**
+ * The <tt>Thread</tt> in which this <tt>AsyncContactQuery</tt> is
+ * performing {@link #query}.
+ */
+ private Thread thread;
+
+ /**
+ * Initializes a new <tt>AsyncContactQuery</tt> instance which is to perform
+ * a specific <tt>query</tt> on behalf of a specific <tt>contactSource</tt>.
+ *
+ * @param contactSource the <tt>ContactSourceService</tt> which is to
+ * perform the new <tt>ContactQuery</tt> instance
+ * @param query the <tt>String</tt> for which <tt>contactSource</tt> is
+ * being queried
+ */
+ protected AsyncContactQuery(T contactSource, String query)
+ {
+ super(contactSource);
+
+ this.query = (query == null) ? null : query.toLowerCase();
+ }
+
+ /**
+ * Adds a specific <tt>SourceContact</tt> to the list of
+ * <tt>SourceContact</tt>s to be returned by this <tt>ContactQuery</tt> in
+ * response to {@link #getQueryResults()}.
+ *
+ * @param sourceContact the <tt>SourceContact</tt> to be added to the
+ * <tt>queryResults</tt> of this <tt>ContactQuery</tt>
+ * @return <tt>true</tt> if the <tt>queryResults</tt> of this
+ * <tt>ContactQuery</tt> has changed in response to the call
+ */
+ protected boolean addQueryResult(SourceContact sourceContact)
+ {
+ boolean changed;
+
+ synchronized (queryResults)
+ {
+ changed = queryResults.add(sourceContact);
+ }
+ if (changed)
+ fireContactReceived(sourceContact);
+ return changed;
+ }
+
+ /**
+ * Gets the <tt>List</tt> of <tt>SourceContact</tt>s which match this
+ * <tt>ContactQuery</tt>.
+ *
+ * @return the <tt>List</tt> of <tt>SourceContact</tt>s which match this
+ * <tt>ContactQuery</tt>
+ * @see ContactQuery#getQueryResults()
+ */
+ public List<SourceContact> getQueryResults()
+ {
+ List<SourceContact> qr;
+
+ synchronized (queryResults)
+ {
+ qr = new ArrayList<SourceContact>(queryResults.size());
+ qr.addAll(queryResults);
+ }
+ return qr;
+ }
+
+ /**
+ * Performs this <tt>ContactQuery</tt> in a background <tt>Thread</tt>.
+ */
+ protected abstract void run();
+
+ /**
+ * Starts this <tt>AsyncContactQuery</tt>.
+ */
+ public synchronized void start()
+ {
+ if (thread == null)
+ {
+ thread
+ = new Thread()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ AsyncContactQuery.this.run();
+ }
+ finally
+ {
+ synchronized (AsyncContactQuery.this)
+ {
+ if (thread == Thread.currentThread())
+ stopped();
+ }
+ }
+ }
+ };
+ thread.setDaemon(true);
+ thread.start();
+ }
+ else
+ throw new IllegalStateException("thread");
+ }
+
+ /**
+ * Notifies this <tt>AsyncContactQuery</tt> that it has stopped performing
+ * in the associated background <tt>Thread</tt>.
+ */
+ protected void stopped()
+ {
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/AsyncContactSourceService.java b/src/net/java/sip/communicator/plugin/addrbook/AsyncContactSourceService.java new file mode 100644 index 0000000..ab12921 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/AsyncContactSourceService.java @@ -0,0 +1,24 @@ +/*
+ * 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.addrbook;
+
+import net.java.sip.communicator.service.contactsource.*;
+
+/**
+ * Declares the interface of a <tt>ContactSourceService</tt> which performs
+ * <tt>ContactQuery</tt>s in a separate <tt>Thread</tt>.
+ *
+ * @author Lyubomir Marinov
+ */
+public interface AsyncContactSourceService
+ extends ContactSourceService
+{
+ /**
+ * Stops this <tt>ContactSourceService</tt>.
+ */
+ public void stop();
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf b/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf new file mode 100644 index 0000000..f8b1032 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/addrbook.manifest.mf @@ -0,0 +1,10 @@ +Bundle-Activator: net.java.sip.communicator.plugin.addrbook.AddrBookActivator
+Bundle-Description: OS-specific Address Book support
+Bundle-Name: OS-specific Address Book 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,
+ net.java.sip.communicator.util,
+ org.osgi.framework
+System-Bundle: yes
diff --git a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java new file mode 100644 index 0000000..68be1f4 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java @@ -0,0 +1,46 @@ +/*
+ * 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.addrbook.macosx;
+
+import net.java.sip.communicator.plugin.addrbook.*;
+
+/**
+ * Implements <tt>ContactQuery</tt> for the Address Book of Mac OS X.
+ *
+ * @author Lyubomir Marinov
+ */
+public class MacOSXAddrBookContactQuery
+ extends AsyncContactQuery<MacOSXAddrBookContactSourceService>
+{
+
+ /**
+ * Initializes a new <tt>MacOSXAddrBookContactQuery</tt> which is to perform
+ * a specific <tt>query</tt> in the Address Book of Mac OS X on behalf of a
+ * specific <tt>MacOSXAddrBookContactSourceService</tt>.
+ *
+ * @param contactSource the <tt>MacOSXAddrBookContactSourceService</tt>
+ * which is to perform the new <tt>ContactQuery</tt> instance
+ * @param query the <tt>String</tt> for which <tt>contactSource</tt> i.e.
+ * the Address Book of Mac OS X is being queried
+ */
+ public MacOSXAddrBookContactQuery(
+ MacOSXAddrBookContactSourceService contactSource,
+ String query)
+ {
+ super(contactSource, query);
+ }
+
+ /**
+ * Performs this <tt>AsyncContactQuery</tt> in a background <tt>Thread</tt>.
+ *
+ * @see AsyncContactQuery#run()
+ */
+ protected void run()
+ {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactSourceService.java b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactSourceService.java new file mode 100644 index 0000000..eb27bd1 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactSourceService.java @@ -0,0 +1,72 @@ +/*
+ * 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.addrbook.macosx;
+
+import net.java.sip.communicator.service.contactsource.*;
+
+/**
+ * Implements <tt>ContactSourceService</tt> for the Address Book of Mac OS X.
+ *
+ * @author Lyubomir Marinov
+ */
+public class MacOSXAddrBookContactSourceService
+ implements ContactSourceService
+{
+ /**
+ * Initializes a new <tt>MacOSXAddrBookContactSourceService</tt> instance.
+ */
+ public MacOSXAddrBookContactSourceService()
+ {
+ }
+
+ /**
+ * Gets a human-readable <tt>String</tt> which names this
+ * <tt>ContactSourceService</tt> implementation.
+ *
+ * @return a human-readable <tt>String</tt> which names this
+ * <tt>ContactSourceService</tt> implementation
+ * @see ContactSourceService#getDisplayName()
+ */
+ public String getDisplayName()
+ {
+ return "Mac OS X Address Book";
+ }
+
+ /**
+ * Gets a <tt>String</tt> which uniquely identifies the instances of the
+ * <tt>MacOSXAddrBookContactSourceService</tt> implementation.
+ *
+ * @return a <tt>String</tt> which uniquely identifies the instances of the
+ * <tt>MacOSXAddrBookContactSourceService</tt> implementation
+ * @see ContactSourceService#getIdentifier()
+ */
+ public String getIdentifier()
+ {
+ return "MacOSXAddressBook";
+ }
+
+ /**
+ * Queries this <tt>ContactSourceService</tt> for <tt>SourceContact</tt>s
+ * which match a specific <tt>query</tt> <tt>String</tt>.
+ *
+ * @param query the <tt>String</tt> which this <tt>ContactSourceService</tt>
+ * is being queried for
+ * @return a <tt>ContactQuery</tt> which represents the query of this
+ * <tt>ContactSourceService</tt> implementation for the specified
+ * <tt>String</tt> and via which the matching <tt>SourceContact</tt>s (if
+ * any) will be returned
+ * @see ContactSourceService#queryContactSource(String)
+ */
+ public ContactQuery queryContactSource(String query)
+ {
+ MacOSXAddrBookContactQuery mosxabcq
+ = new MacOSXAddrBookContactQuery(this, query);
+
+ mosxabcq.start();
+ return mosxabcq;
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookCallback.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookCallback.java new file mode 100644 index 0000000..1b80348 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookCallback.java @@ -0,0 +1,28 @@ +/*
+ * 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.addrbook.msoutlook;
+
+/**
+ * Defines the interface for a callback function which is called by the Address
+ * Book of Microsoft Outlook with a pointer to an <tt>IUnknown</tt> instance as
+ * its argument.
+ *
+ * @author Lyubomir Marinov
+ */
+public interface MsOutlookAddrBookCallback
+{
+ /**
+ * Notifies this <tt>MsOutlookAddrBookCallback</tt> about a specific
+ * <tt>IUnknown</tt>.
+ *
+ * @param iUnknown the pointer to the <tt>IUnknown</tt> instance to notify
+ * this <tt>MsOutlookAddrBookCallback</tt> about
+ * @return <tt>true</tt> if this <tt>MsOutlookAddrBookCallback</tt> is to
+ * continue being called; otherwise, <tt>false</tt>
+ */
+ boolean callback(long iUnknown);
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java new file mode 100644 index 0000000..8757fd9 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactQuery.java @@ -0,0 +1,262 @@ +/*
+ * 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.addrbook.msoutlook;
+
+import java.util.*;
+
+import net.java.sip.communicator.plugin.addrbook.*;
+import net.java.sip.communicator.service.contactsource.*;
+
+/**
+ * Implements <tt>ContactQuery</tt> for the Address Book of Microsoft Outlook.
+ *
+ * @author Lyubomir Marinov
+ */
+public class MsOutlookAddrBookContactQuery
+ extends AsyncContactQuery<MsOutlookAddrBookContactSourceService>
+{
+
+ /**
+ * The IDs of the properties of <tt>MAPI_MAILUSER</tt> which are to be
+ * queried by the <tt>MsOutlookAddrBookContactQuery</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 flag which signals that MAPI strings should be returned in the
+ * Unicode character set.
+ */
+ private static final long MAPI_UNICODE = 0x80000000;
+
+ /**
+ * 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("jmsoutlookaddrbook");
+ }
+
+ /**
+ * Initializes a new <tt>MsOutlookAddrBookContactQuery</tt> instance to
+ * be performed by a specific
+ * <tt>MsOutlookAddrBookContactSourceService</tt>.
+ *
+ * @param msoabcss the <tt>MsOutlookAddrBookContactSourceService</tt>
+ * which is to perform the new <tt>ContactQuery</tt>
+ * @param query the <tt>String</tt> for which <tt>msoabcss</tt> is being
+ * queried
+ */
+ public MsOutlookAddrBookContactQuery(
+ MsOutlookAddrBookContactSourceService msoabcss,
+ String query)
+ {
+ super(msoabcss, query);
+ }
+
+ /**
+ * Calls back to a specific <tt>MsOutlookAddrBookCallback</tt> for each
+ * <tt>MAPI_MAILUSER</tt> found in the Address Book of Microsoft Outlook
+ * 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. <bb>Warning</bb>: Ignored at the time of this
+ * writing.
+ * @param callback the <tt>MsOutlookAddrBookCallback</tt> to be notified
+ * about the matching <tt>MAPI_MAILUSER</tt>s
+ */
+ private static native void foreachMailUser(
+ String query,
+ MsOutlookAddrBookCallback callback);
+
+ private static native Object[] IMAPIProp_GetProps(
+ long mapiProp,
+ long[] propIds, long flags)
+ throws MsOutlookMAPIHResultException;
+
+ /**
+ * Notifies this <tt>MsOutlookAddrBookContactQuery</tt> about a specific
+ * <tt>MAPI_MAILUSER</tt>.
+ *
+ * @param iUnknown a pointer to an <tt>IUnknown</tt> instance for the
+ * <tt>MAPI_MAILUSER</tt> to notify about
+ * @return <tt>true</tt> if this <tt>MsOutlookAddrBookContactQuery</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
+ {
+ Object[] props
+ = IMAPIProp_GetProps(
+ iUnknown,
+ MAPI_MAILUSER_PROP_IDS,
+ MAPI_UNICODE);
+ 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);
+
+ addQueryResult(sourceContact);
+ }
+ return (getStatus() == QUERY_IN_PROGRESS);
+ }
+
+ /**
+ * Performs this <tt>AsyncContactQuery</tt> in a background <tt>Thread</tt>.
+ *
+ * @see AsyncContactQuery#run()
+ */
+ protected void run()
+ {
+ foreachMailUser(
+ query,
+ new MsOutlookAddrBookCallback()
+ {
+ public boolean callback(long iUnknown)
+ {
+ try
+ {
+ return onMailUser(iUnknown);
+ }
+ catch (MsOutlookMAPIHResultException ex)
+ {
+ ex.printStackTrace(System.err);
+ return false;
+ }
+ }
+ });
+ }
+
+ /**
+ * Notifies this <tt>AsyncContactQuery</tt> that it has stopped performing
+ * in the associated background <tt>Thread</tt>.
+ *
+ * @see AsyncContactQuery#stopped()
+ */
+ @Override
+ protected void stopped()
+ {
+ getContactSource().stopped(this);
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactSourceService.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactSourceService.java new file mode 100644 index 0000000..fca8320 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookAddrBookContactSourceService.java @@ -0,0 +1,173 @@ +/*
+ * 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.addrbook.msoutlook;
+
+import java.util.*;
+
+import net.java.sip.communicator.plugin.addrbook.*;
+import net.java.sip.communicator.service.contactsource.*;
+
+/**
+ * Implements <tt>ContactSourceService</tt> for the Address Book of Microsoft
+ * Outlook.
+ *
+ * @author Lyubomir Marinov
+ */
+public class MsOutlookAddrBookContactSourceService
+ implements AsyncContactSourceService
+{
+ private static final long MAPI_INIT_VERSION = 0;
+
+ private static final long MAPI_MULTITHREAD_NOTIFICATIONS = 0x00000001;
+
+ static
+ {
+ System.loadLibrary("jmsoutlookaddrbook");
+ }
+
+ /**
+ * The <tt>List</tt> of <tt>MsOutlookAddrBookContactQuery</tt> instances
+ * which have been started and haven't stopped yet.
+ */
+ private final List<MsOutlookAddrBookContactQuery> queries
+ = new LinkedList<MsOutlookAddrBookContactQuery>();
+
+ /**
+ * Initializes a new <tt>MsOutlookAddrBookContactSourceService</tt>
+ * instance.
+ *
+ * @throws MsOutlookMAPIHResultException if anything goes wrong while
+ * initializing the new <tt>MsOutlookAddrBookContactSourceService</tt>
+ * instance
+ */
+ public MsOutlookAddrBookContactSourceService()
+ throws MsOutlookMAPIHResultException
+ {
+ MAPIInitialize(MAPI_INIT_VERSION, MAPI_MULTITHREAD_NOTIFICATIONS);
+ }
+
+ /**
+ * Gets a human-readable <tt>String</tt> which names this
+ * <tt>ContactSourceService</tt> implementation.
+ *
+ * @return a human-readable <tt>String</tt> which names this
+ * <tt>ContactSourceService</tt> implementation
+ * @see ContactSourceService#getDisplayName()
+ */
+ public String getDisplayName()
+ {
+ return "Microsoft Outlook Address Book";
+ }
+
+ /**
+ * Gets a <tt>String</tt> which uniquely identifies the instances of the
+ * <tt>MsOutlookAddrBookContactSourceService</tt> implementation.
+ *
+ * @return a <tt>String</tt> which uniquely identifies the instances of the
+ * <tt>MsOutlookAddrBookContactSourceService</tt> implementation
+ * @see ContactSourceService#getIdentifier()
+ */
+ public String getIdentifier()
+ {
+ return "MsOutlookAddressBook";
+ }
+
+ private static native void MAPIInitialize(long version, long flags)
+ throws MsOutlookMAPIHResultException;
+
+ private static native void MAPIUninitialize();
+
+ /**
+ * Queries this <tt>ContactSourceService</tt> for <tt>SourceContact</tt>s
+ * which match a specific <tt>query</tt> <tt>String</tt>.
+ *
+ * @param query the <tt>String</tt> which this <tt>ContactSourceService</tt>
+ * is being queried for
+ * @return a <tt>ContactQuery</tt> which represents the query of this
+ * <tt>ContactSourceService</tt> implementation for the specified
+ * <tt>String</tt> and via which the matching <tt>SourceContact</tt>s (if
+ * any) will be returned
+ * @see ContactSourceService#queryContactSource(String)
+ */
+ public ContactQuery queryContactSource(String query)
+ {
+ MsOutlookAddrBookContactQuery msoabcq
+ = new MsOutlookAddrBookContactQuery(this, query);
+
+ synchronized (queries)
+ {
+ queries.add(msoabcq);
+ }
+
+ boolean msoabcqHasStarted = false;
+
+ try
+ {
+ msoabcq.start();
+ msoabcqHasStarted = true;
+ }
+ finally
+ {
+ if (!msoabcqHasStarted)
+ {
+ synchronized (queries)
+ {
+ if (queries.remove(msoabcq))
+ queries.notify();
+ }
+ }
+ }
+ return msoabcq;
+ }
+
+ /**
+ * Stops this <tt>ContactSourceService</tt> implementation and prepares it
+ * for garbage collection.
+ *
+ * @see AsyncContactSourceService#stop()
+ */
+ public void stop()
+ {
+ boolean interrupted = false;
+
+ synchronized (queries)
+ {
+ while (!queries.isEmpty())
+ {
+ queries.get(0).cancel();
+ try
+ {
+ queries.wait();
+ }
+ catch (InterruptedException iex)
+ {
+ interrupted = true;
+ }
+ }
+ }
+ if (interrupted)
+ Thread.currentThread().interrupt();
+
+ MAPIUninitialize();
+ }
+
+ /**
+ * Notifies this <tt>MsOutlookAddrBookContactSourceService</tt> that a
+ * specific <tt>MsOutlookAddrBookContactQuery</tt> has stopped.
+ *
+ * @param msoabcq the <tt>MsOutlookAddrBookContactQuery</tt> which has
+ * stopped
+ */
+ void stopped(MsOutlookAddrBookContactQuery msoabcq)
+ {
+ synchronized (queries)
+ {
+ if (queries.remove(msoabcq))
+ queries.notify();
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java new file mode 100644 index 0000000..18e0fa1 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java @@ -0,0 +1,97 @@ +/*
+ * 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.addrbook.msoutlook;
+
+/**
+ * Represents a specific Microsoft Outlook MAPI <tt>HRESULT</tt> as an
+ * <tt>Exception</tt>.
+ *
+ * @author Lyubomir Marinov
+ */
+public class MsOutlookMAPIHResultException
+ extends Exception
+{
+ /**
+ * The <tt>HRESULT</tt> which is represented by this <tt>Exception</tt>.
+ */
+ private final long hResult;
+
+ /**
+ * Initializes a new <tt>MsOutlookMAPIHResultException</tt> instance which
+ * is to represent a specific <tt>HRESULT</tt>.
+ *
+ * @param hResult the <tt>HRESULT</tt> to be represented by the new instance
+ */
+ public MsOutlookMAPIHResultException(long hResult)
+ {
+ this(hResult, toString(hResult));
+ }
+
+ /**
+ * Initializes a new <tt>MsOutlookMAPIHResultException</tt> instance which
+ * is to represent a specific <tt>HRESULT</tt> and to provide a specific
+ * <tt>String</tt> message.
+ *
+ * @param hResult the <tt>HRESULT</tt> to be represented by the new instance
+ * @param message the <tt>String</tt> message to be provided by the new
+ * instance
+ */
+ public MsOutlookMAPIHResultException(long hResult, String message)
+ {
+ super(message);
+
+ this.hResult = hResult;
+ }
+
+ /**
+ * Initializes a new <tt>MsOutlookMAPIHResultException</tt> instance with a
+ * specific <tt>String</tt> message.
+ *
+ * @param message the <tt>String</tt> message to be provided by the new
+ * instance
+ */
+ public MsOutlookMAPIHResultException(String message)
+ {
+ this(0, message);
+ }
+
+ /**
+ * Gets the <tt>HRESULT</tt> which is represented by this
+ * <tt>Exception</tt>.
+ *
+ * @return the <tt>HRESULT</tt> which is represented by this
+ * <tt>Exception</tt>
+ */
+ 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();
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMailUserSourceContact.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMailUserSourceContact.java new file mode 100644 index 0000000..c60c4e7 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMailUserSourceContact.java @@ -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.addrbook.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 MsOutlookAddrBookContactSourceService 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(
+ MsOutlookAddrBookContactSourceService 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 MsOutlookAddrBookContactSourceService 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);
+ }
+}
|