diff --git a/build.xml b/build.xml index a1b2d6f90..b30f9f2db 100644 --- a/build.xml +++ b/build.xml @@ -890,7 +890,7 @@ bundle-callhistory, bundle-callhistory-slick, bundle-popupmessagehandler-slick, bundle-netaddr,bundle-netaddr-slick,bundle-slickless, bundle-slick-runner,bundle-sip,bundle-sip-slick,bundle-fileaccess, - bundle-fileaccess-slick,bundle-neomedia,bundle-hid,bundle-ldap, + bundle-fileaccess-slick,bundle-neomedia,bundle-hid,bundle-ldap,bundle-googlecontacts, bundle-resource-manager,bundle-resources-defaultpack, bundle-protocol,bundle-protocol-media,bundle-icq, bundle-icq-slick,bundle-mock,bundle-smacklib,bundle-jmdnslib, @@ -1201,6 +1201,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 90017db20..286f50098 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -64,6 +64,7 @@ felix.auto.start.45= \ felix.auto.start.49= \ reference:file:sc-bundles/provisioning.jar \ + reference:file:sc-bundles/googlecontacts.jar \ reference:file:sc-bundles/bouncycastle.jar \ reference:file:sc-bundles/zrtp4j.jar \ reference:file:sc-bundles/protocol.jar \ diff --git a/lib/installer-exclude/gdata-client-1.0.jar b/lib/installer-exclude/gdata-client-1.0.jar new file mode 100644 index 000000000..633fa0710 Binary files /dev/null and b/lib/installer-exclude/gdata-client-1.0.jar differ diff --git a/lib/installer-exclude/gdata-client-meta-1.0.jar b/lib/installer-exclude/gdata-client-meta-1.0.jar new file mode 100644 index 000000000..b6dacf6f5 Binary files /dev/null and b/lib/installer-exclude/gdata-client-meta-1.0.jar differ diff --git a/lib/installer-exclude/gdata-contacts-3.0.jar b/lib/installer-exclude/gdata-contacts-3.0.jar new file mode 100644 index 000000000..bec6d77e9 Binary files /dev/null and b/lib/installer-exclude/gdata-contacts-3.0.jar differ diff --git a/lib/installer-exclude/gdata-contacts-meta-3.0.jar b/lib/installer-exclude/gdata-contacts-meta-3.0.jar new file mode 100644 index 000000000..9b6d0e159 Binary files /dev/null and b/lib/installer-exclude/gdata-contacts-meta-3.0.jar differ diff --git a/lib/installer-exclude/gdata-core-1.0.jar b/lib/installer-exclude/gdata-core-1.0.jar new file mode 100644 index 000000000..4ca367aec Binary files /dev/null and b/lib/installer-exclude/gdata-core-1.0.jar differ diff --git a/lib/installer-exclude/google-collect-1.0-rc1.jar b/lib/installer-exclude/google-collect-1.0-rc1.jar new file mode 100644 index 000000000..bc499eea6 Binary files /dev/null and b/lib/installer-exclude/google-collect-1.0-rc1.jar differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index b63e06fa1..437ab60b4 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -578,6 +578,7 @@ impl.gui.main.account.DEFAULT_PAGE_BODY=You can use the list above to select the impl.gui.main.account.DUMMY_PROTOCOL_NAME=select network impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=select network +# LDAP impl.ldap.CONFIG_FORM_TITLE=LDAP configuration impl.ldap.NEW=New impl.ldap.EDIT=edit @@ -601,6 +602,19 @@ impl.ldap.SEARCH_BASE=Search base impl.ldap.SCOPE=Scope impl.ldap.WRONG_CREDENTIALS=Wrong credentials for LDAP directory {0} +# Google Contacts +impl.googlecontacts.CONFIG_FORM_TITLE=Google Contacts +impl.googlecontacts.NEW=New +impl.googlecontacts.EDIT=edit +impl.googlecontacts.REMOVE=Remove +impl.googlecontacts.ENABLED=Enabled +impl.googlecontacts.ACCOUNT_NAME=Account name +impl.googlecontacts.SAVE=Save +impl.googlecontacts.CANCEL=Cancel +impl.googlecontacts.USERNAME=Account name +impl.googlecontacts.PASSWORD=Password +impl.googlecontacts.WRONG_CREDENTIALS=Wrong credentials for Google account {0} + # account info plugin.accountinfo.TITLE=Account Info plugin.accountinfo.EXTENDED=Extended @@ -738,6 +752,7 @@ plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Connect Server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Enable keep alive plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS=Enable Gmail notifications for new messages +plugin.jabberaccregwizz.ENABLE_GOOGLE_CONTACTS_SOURCE=Enable Google Contacts search plugin.jabberaccregwizz.NEW_ACCOUNT_TITLE=Jabber new account registration plugin.jabberaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=In case you don't have a Jabber account, click on this button to create a new one. plugin.jabberaccregwizz.CHOOSE_SERVER_TITLE=Jabber new account server chooser diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsActivator.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsActivator.java new file mode 100644 index 000000000..31475dd82 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsActivator.java @@ -0,0 +1,393 @@ +/* + * 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.impl.googlecontacts; + +import java.util.*; + +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.service.googlecontacts.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * Activates the Google Contacts Service + * + * @author Sebastien Vincent + */ +public class GoogleContactsActivator implements BundleActivator +{ + /** + * The Logger used by the GoogleContactsActivator class + * and its instances for logging output. + */ + private final Logger logger = Logger.getLogger( + GoogleContactsActivator.class); + + /** + * The OSGi ServiceRegistration of + * GoogleContactsServiceImpl. + */ + private ServiceRegistration serviceRegistration = null; + + /** + * BundleContext from the OSGI bus. + */ + private static BundleContext bundleContext; + + /** + * Reference to the configuration service + */ + private static ConfigurationService configService; + + /** + * Reference to the credentials service + */ + private static CredentialsStorageService credentialsService; + + /** + * Reference to the resource management service + */ + private static ResourceManagementService resourceService; + + /** + * The cached reference to the PhoneNumberI18nService instance used + * by the functionality of the Google Contacts plug-in and fetched from its + * BundleContext. + */ + private static PhoneNumberI18nService phoneNumberI18nService; + + /** + * Google contacts service. + */ + private static GoogleContactsServiceImpl googleContactsService; + + /** + * List of contact source service registrations. + */ + private static Map cssList + = new HashMap(); + + /** + * Gets the PhoneNumberI18nService to be used by the functionality + * of the addrbook plug-in. + * + * @return the PhoneNumberI18nService to be used by the + * functionality of the addrbook plug-in + */ + public static PhoneNumberI18nService getPhoneNumberI18nService() + { + if (phoneNumberI18nService == null) + { + phoneNumberI18nService + = ServiceUtils.getService( + bundleContext, + PhoneNumberI18nService.class); + } + return phoneNumberI18nService; + } + + /** + * Returns a reference to a ConfigurationService implementation currently + * registered in the bundle context or null if no such implementation was + * found. + * + * @return a currently valid implementation of the ConfigurationService. + */ + public static ConfigurationService getConfigService() + { + if(configService == null) + { + ServiceReference confReference + = bundleContext.getServiceReference( + ConfigurationService.class.getName()); + configService + = (ConfigurationService) bundleContext.getService( + confReference); + } + return configService; + } + + /** + * Returns a reference to a GoogleContactsService implementation currently + * registered in the bundle context or null if no such implementation was + * found. + * + * @return a currently valid implementation of the GoogleContactsService + */ + public static GoogleContactsServiceImpl getGoogleContactsService() + { + return googleContactsService; + } + + /** + * Returns a reference to a CredentialsStorageConfigurationService + * implementation currently registered in the bundle context or null if no + * such implementation was found. + * + * @return a currently valid implementation of the + * CredentialsStorageService. + */ + public static CredentialsStorageService getCredentialsService() + { + if(credentialsService == null) + { + ServiceReference confReference + = bundleContext.getServiceReference( + CredentialsStorageService.class.getName()); + credentialsService + = (CredentialsStorageService) bundleContext.getService( + confReference); + } + return credentialsService; + } + + /** + * Returns a reference to a ResourceManagementService implementation + * currently registered in the bundle context or null if no such + * implementation was found. + * + * @return a currently valid implementation of the + * ResourceManagementService. + */ + public static ResourceManagementService getResourceManagementService() + { + if(resourceService == null) + { + ServiceReference confReference + = bundleContext.getServiceReference( + ResourceManagementService.class.getName()); + resourceService + = (ResourceManagementService) bundleContext.getService( + confReference); + } + return resourceService; + } + + /** + * Starts the Google Contacts service + * + * @param bundleContext BundleContext + * @throws Exception if something goes wrong when starting service + */ + public void start(BundleContext bundleContext) + throws Exception + { + if (logger.isDebugEnabled()) + logger.debug("Started."); + + GoogleContactsActivator.bundleContext = bundleContext; + googleContactsService = + new GoogleContactsServiceImpl(); + serviceRegistration = + bundleContext.registerService(GoogleContactsService.class.getName(), + googleContactsService, null); + + /* registers the configuration form */ + Dictionary properties = + new Hashtable(); + properties.put( ConfigurationForm.FORM_TYPE, + ConfigurationForm.ADVANCED_TYPE); + + bundleContext.registerService( + ConfigurationForm.class.getName(), + new LazyConfigurationForm( + "net.java.sip.communicator.impl.googlecontacts.configform.GoogleContactsConfigForm", + getClass().getClassLoader(), + "impl.googlecontacts.PLUGIN_ICON", + "impl.googlecontacts.CONFIG_FORM_TITLE", + 2000, true), + properties); + + if (logger.isDebugEnabled()) + logger.debug("Google Contacts Service ... [REGISTERED]"); + } + + /** + * Stops the Google Contacts service. + * + * @param bundleContext BundleContext + * @throws Exception if something goes wrong when stopping service + */ + public void stop(BundleContext bundleContext) + throws Exception + { + if (serviceRegistration != null) + { + serviceRegistration.unregister(); + serviceRegistration = null; + } + + /* remove contact source services */ + for(Map.Entry entry : + cssList.entrySet()) + { + if (entry.getValue() != null) + { + try + { + entry.getValue().unregister(); + } + finally + { + entry.getKey().stop(); + } + } + } + cssList.clear(); + + GoogleContactsActivator.bundleContext = null; + } + + /** + * Enable contact source service with specified + * GoogleContactsConnection. + * + * @param login login + * @param password password + */ + public static void enableContactSource(String login, String password) + { + GoogleContactsSourceService css = new GoogleContactsSourceService( + login, password); + ServiceRegistration cssServiceRegistration = null; + + try + { + cssServiceRegistration + = bundleContext.registerService( + ContactSourceService.class.getName(), + css, + null); + } + finally + { + if (cssServiceRegistration == null) + { + css.stop(); + css = null; + } + else + { + cssList.put(css, cssServiceRegistration); + } + } + } + + /** + * Enable contact source service with specified + * GoogleContactsConnection. + * + * @param cnx GoogleContactsConnection + */ + public static void enableContactSource(GoogleContactsConnection cnx) + { + GoogleContactsSourceService css = new GoogleContactsSourceService( + cnx); + ServiceRegistration cssServiceRegistration = null; + + try + { + cssServiceRegistration + = bundleContext.registerService( + ContactSourceService.class.getName(), + css, + null); + } + finally + { + if (cssServiceRegistration == null) + { + css.stop(); + css = null; + } + else + { + cssList.put(css, cssServiceRegistration); + } + } + } + + /** + * Disable contact source service with specified + * GoogleContactsConnection. + * + * @param login login + */ + public static void disableContactSource(String login) + { + GoogleContactsSourceService found = null; + + for(Map.Entry entry : + cssList.entrySet()) + { + String cssName = + entry.getKey().getConnection().getLogin(); + + if(cssName.equals(login)) + { + try + { + entry.getValue().unregister(); + } + finally + { + entry.getKey().stop(); + } + found = entry.getKey(); + break; + } + } + + if(found != null) + { + cssList.remove(found); + } + } + + /** + * Disable contact source service with specified + * GoogleContactsConnection. + * + * @param cnx GoogleContactsConnection. + */ + public static void disableContactSource(GoogleContactsConnection cnx) + { + GoogleContactsSourceService found = null; + + for(Map.Entry entry : + cssList.entrySet()) + { + String cssName = + entry.getKey().getConnection().getLogin(); + String name = cnx.getLogin(); + if(cssName.equals(name)) + { + try + { + entry.getValue().unregister(); + } + finally + { + entry.getKey().stop(); + } + found = entry.getKey(); + break; + } + } + + if(found != null) + { + cssList.remove(found); + } + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsConnectionImpl.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsConnectionImpl.java new file mode 100644 index 000000000..592c6bad3 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsConnectionImpl.java @@ -0,0 +1,108 @@ +/* + * 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.impl.googlecontacts; + +import com.google.gdata.client.contacts.*; + +import net.java.sip.communicator.service.googlecontacts.*; + +/** + * Google Contacts credentials to connect to the service. + * + * @author Sebastien Vincent + */ +public class GoogleContactsConnectionImpl + implements GoogleContactsConnection +{ + /** + * Login. + */ + private final String login; + + /** + * Password. + */ + private final String password; + + /** + * If the connection is enabled. + */ + private boolean enabled = false; + + /** + * Google Contacts service. + */ + private final ContactsService googleService = + new ContactsService("GoogleContacts service for Jitsi"); + + /** + * Constructor. + * + * @param login the login to connect to the service + * @param password the password to connect to the service + * @throws Exception if something goes wrong during connection + */ + public GoogleContactsConnectionImpl(String login, String password) + throws Exception + { + this.login = login; + this.password = password; + + googleService.setUserCredentials(login, password); + googleService.useSsl(); + } + + /** + * Returns the Google service. + * + * @return the Google service + */ + public ContactsService getGoogleService() + { + return googleService; + } + + /** + * Get login. + * + * @return login to connect to the service + */ + public String getLogin() + { + return login; + } + + /** + * get password. + * + * @return password to connect to the service + */ + public String getPassword() + { + return password; + } + + /** + * Returns if the connection is enabled. + * + * @return true if connection is enabled, false otherwise + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * Set the connection to be enabled or not. + * + * @param enabled value to set + */ + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java new file mode 100644 index 000000000..1b4f73944 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java @@ -0,0 +1,527 @@ +/* + * 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.impl.googlecontacts; + +import java.util.*; + +import net.java.sip.communicator.service.googlecontacts.*; + +import com.google.gdata.data.*; +import com.google.gdata.data.extensions.*; +import com.google.gdata.data.contacts.ContactEntry; //disambiguation + +/** + * Google Contacts entry implementation. + * + * @author Sebastien Vincent + */ +public class GoogleContactsEntryImpl + implements GoogleContactsEntry +{ + /** + * Google Talk protocol type. + */ + private static final String GOOGLETALK_PROTOCOL = + "http://schemas.google.com/g/2005#GOOGLE_TALK"; + + /** + * Google Talk protocol type. + */ + private static final String YAHOO_PROTOCOL = + "http://schemas.google.com/g/2005#YAHOO"; + + /** + * Google Talk protocol type. + */ + private static final String AIM_PROTOCOL = + "http://schemas.google.com/g/2005#AIM"; + + /** + * Google Talk protocol type. + */ + private static final String MSN_PROTOCOL = + "http://schemas.google.com/g/2005#MSN"; + + /** + * Google Talk protocol type. + */ + private static final String ICQ_PROTOCOL = + "http://schemas.google.com/g/2005#ICQ"; + + /** + * Google Talk protocol type. + */ + private static final String JABBER_PROTOCOL = + "http://schemas.google.com/g/2005#JABBER"; + + /** + * Full name. + */ + private String fullName = null; + + /** + * Family name. + */ + private String familyName = null; + + /** + * Given name. + */ + private String givenName = null; + + /** + * Home mails list. + */ + private final List homeMails = new ArrayList(); + + /** + * Work mails list. + */ + private final List workMails = new ArrayList(); + + /** + * Home phones list. + */ + private final List homePhones = new ArrayList(); + + /** + * Work phones list. + */ + private final List workPhones = new ArrayList(); + + /** + * Mobile phones list. + */ + private final List mobilePhones = new ArrayList(); + + /** + * IM addresses map. + */ + private final Map imAddresses = + new HashMap(); + + /** + * Photo link. + */ + private String photoLink = null; + + /** + * Google photo link. + */ + private Link googlePhotoLink = null; + + /** + * Get the full name. + * + * @return full name + */ + public String getFullName() + { + return fullName; + } + + /** + * Get the family name. + * + * @return family name + */ + public String getFamilyName() + { + return familyName; + } + + /** + * Get the given name. + * + * @return given name + */ + public String getGivenName() + { + return givenName; + } + + /** + * Returns mails. + * + * @return mails + */ + public List getAllMails() + { + List mails = new ArrayList(); + + for(String mail : homeMails) + { + mails.add(mail); + } + + for(String mail : workMails) + { + mails.add(mail); + } + + return mails; + } + + /** + * Adds a home mail address. + * + * @param mail the mail address + */ + public void addHomeMail(String mail) + { + homeMails.add(mail); + } + + /** + * Returns home mail addresses. + * + * @return home mail addresses + */ + public List getHomeMails() + { + return homeMails; + } + + /** + * Adds a work mail address. + * + * @param mail the mail address + */ + public void addWorkMails(String mail) + { + workMails.add(mail); + } + + /** + * Returns work mail addresses. + * + * @return work mail addresses + */ + public List getWorkMails() + { + return workMails; + } + + /** + * Returns telephone numbers. + * + * @return telephone numbers + */ + public List getAllPhones() + { + List phones = new ArrayList(); + + for(String phone : mobilePhones) + { + phones.add(phone); + } + + for(String phone : homePhones) + { + phones.add(phone); + } + + for(String phone : workPhones) + { + phones.add(phone); + } + + return phones; + } + + /** + * Adds a work telephone number. + * + * @param telephoneNumber the work telephone number + */ + public void addWorkPhone(String telephoneNumber) + { + workPhones.add(telephoneNumber); + } + + /** + * Returns work telephone numbers. + * + * @return work telephone numbers + */ + public List getWorkPhones() + { + return workPhones; + } + + /** + * Adds a mobile telephone numbers. + * + * @param telephoneNumber the mobile telephone number + */ + public void addMobilePhone(String telephoneNumber) + { + mobilePhones.add(telephoneNumber); + } + + /** + * Returns mobile telephone numbers. + * + * @return mobile telephone numbers + */ + public List getMobilePhones() + { + return mobilePhones; + } + + /** + * Adds a home telephone numbers. + * + * @param telephoneNumber the home telephone number + */ + public void addHomePhone(String telephoneNumber) + { + homePhones.add(telephoneNumber); + } + + /** + * Returns home telephone numbers. + * + * @return home telephone numbers + */ + public List getHomePhones() + { + return homePhones; + } + + /** + * Get the photo full URI. + * + * @return the photo URI or null if there isn't + */ + public String getPhoto() + { + return photoLink; + } + + /** + * Get the Google photo full URI. + * + * @return the Google photo URI or null if there isn't + */ + public Link getPhotoLink() + { + return googlePhotoLink; + } + + /** + * Returns IM addresses. + * + * @return IM addresses + */ + public Map getIMAddresses() + { + return imAddresses; + } + + /** + * Adds an IM address. + * + * @param imAddress IM address + */ + public void addIMAddress(String imAddress, IMProtocol protocol) + { + imAddresses.put(imAddress, protocol); + } + + /** + * Set information. + * + * @param contact Google Contacts's ContactEntry + */ + public void setField(ContactEntry contact) + { + Name name = contact.getName(); + + if(name != null) + { + if(name.hasFullName()) + { + fullName = name.getFullName().getValue(); + } + + if(name.hasFamilyName()) + { + familyName = name.getFamilyName().getValue(); + } + + if(name.hasGivenName()) + { + givenName = name.getGivenName().getValue(); + } + + } + + photoLink = contact.getContactPhotoLink().getHref(); + googlePhotoLink = contact.getContactPhotoLink(); + + for(Email mail : contact.getEmailAddresses()) + { + if(mail.getRel().contains("#home")) + { + homeMails.add(mail.getAddress()); + } + else if(mail.getRel().contains("#work")) + { + workMails.add(mail.getAddress()); + } + else + { + homeMails.add(mail.getAddress()); + } + } + + for(PhoneNumber phone : contact.getPhoneNumbers()) + { + if(phone.getRel().contains("#work")) + { + workPhones.add(phone.getPhoneNumber()); + } + else if(phone.getRel().contains("#mobile")) + { + mobilePhones.add(phone.getPhoneNumber()); + } + else if(phone.getRel().contains("#home")) + { + homePhones.add(phone.getPhoneNumber()); + } + else + { + homePhones.add(phone.getPhoneNumber()); + } + } + + for(Im imAddress : contact.getImAddresses()) + { + String protocol = imAddress.getProtocol(); + IMProtocol proto; + + if(protocol.equals(GOOGLETALK_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.GOOGLETALK; + } + else if(protocol.equals(YAHOO_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.YAHOO; + } + else if(protocol.equals(AIM_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.AIM; + } + else if(protocol.equals(MSN_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.MSN; + } + else if(protocol.equals(ICQ_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.ICQ; + } + else if(protocol.equals(JABBER_PROTOCOL)) + { + proto = GoogleContactsEntry.IMProtocol.JABBER; + } + else + { + proto = GoogleContactsEntry.IMProtocol.OTHER; + } + + imAddresses.put(imAddress.getAddress(), proto); + } + } + + /** + * String representation of the GoogleContactsEntry. + */ + @Override + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + if(fullName != null) + { + buffer.append("Full name: "); + buffer.append(fullName); + buffer.append("\n"); + } + + if(givenName != null || familyName != null) + { + buffer.append("Display name: "); + buffer.append(givenName != null ? givenName : ""); + buffer.append(" "); + buffer.append(familyName != null ? familyName : ""); + buffer.append("\n"); + } + + if(getAllMails().size() > 0) + { + buffer.append("Mail:\n"); + + for(String mail : getAllMails()) + { + buffer.append("\t"); + buffer.append(mail); + buffer.append("\n"); + } + } + + if(workPhones.size() > 0) + { + buffer.append("Work phones:\n"); + for(String phone : workPhones) + { + buffer.append("\t"); + buffer.append(phone); + buffer.append("\n"); + } + } + + if(homePhones.size() > 0) + { + buffer.append("Home phones:\n"); + for(String phone : homePhones) + { + buffer.append("\t"); + buffer.append(phone); + buffer.append("\n"); + } + } + + if(mobilePhones.size() > 0) + { + buffer.append("Mobile phones:\n"); + for(String phone : mobilePhones) + { + buffer.append("\t"); + buffer.append(phone); + buffer.append("\n"); + } + } + + if(imAddresses.size() > 0) + { + buffer.append("IM addresses:\n"); + + for(Map.Entry entry : imAddresses.entrySet()) + { + buffer.append("\t"); + buffer.append(entry.getKey()); + buffer.append(" ("); + buffer.append(entry.getValue()); + buffer.append(")\n"); + } + } + + buffer.append("\n"); + return buffer.toString(); + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java new file mode 100644 index 000000000..decfe5ea3 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java @@ -0,0 +1,421 @@ +/* + * 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.impl.googlecontacts; + +import java.util.*; +import java.util.regex.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.googlecontacts.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * Implements ContactQuery for Google Contacts. + * + * @author Sebastien Vincent + */ +public class GoogleContactsQuery + extends AsyncContactQuery +{ + /** + * Maximum results for Google Contacts query. + */ + public static final int GOOGLECONTACTS_MAX_RESULTS = 20; + + /** + * Maximum number of results for this instance. + */ + private final int count; + + /** + * The Google query. + */ + private GoogleQuery gQuery = null; + + /** + * Initializes a new GoogleContactsQuery instance which is to + * perform a specific query on behalf of a specific + * contactSource. + * + * @param contactSource the ContactSourceService which is to + * perform the new ContactQuery instance + * @param query the Pattern for which contactSource is + * being queried + * @param count maximum number of results + */ + protected GoogleContactsQuery(GoogleContactsSourceService + contactSource, Pattern query, int count) + { + super(contactSource, query); + this.count = count; + } + + /** + * Normalizes a String phone number by converting alpha characters + * to their respective digits on a keypad and then stripping non-digit + * characters. + * + * @param phoneNumber a String which represents a phone number to + * normalize + * @return a String which is a normalized form of the specified + * phoneNumber + */ + protected String normalizePhoneNumber(String phoneNumber) + { + PhoneNumberI18nService phoneNumberI18nService + = GoogleContactsActivator.getPhoneNumberI18nService(); + + return + (phoneNumberI18nService == null) + ? phoneNumber + : phoneNumberI18nService.normalize(phoneNumber); + } + + /** + * Determines whether a specific String phone number matches the + * {@link #query} of this AsyncContactQuery. + * + * @param phoneNumber the String which represents the phone number + * to match to the query of this AsyncContactQuery + * @return true if the specified phoneNumber matches the + * query of this AsyncContactQuery; otherwise, + * false + */ + protected boolean phoneNumberMatches(String phoneNumber) + { + /* + * PhoneNumberI18nService implements functionality to aid the parsing, + * formatting and validation of international phone numbers so attempt to + * use it to determine whether the specified phoneNumber matches the + * query. For example, check whether the normalized phoneNumber matches + * the query. + */ + + PhoneNumberI18nService phoneNumberI18nService + = GoogleContactsActivator.getPhoneNumberI18nService(); + boolean phoneNumberMatches = false; + + if (phoneNumberI18nService != null) + { + if (query + .matcher(phoneNumberI18nService.normalize(phoneNumber)) + .find()) + { + phoneNumberMatches = true; + } + else + { + /* + * The fact that the normalized form of the phoneNumber doesn't + * match the query doesn't mean that, for example, it doesn't + * match the normalized form of the query. The latter, though, + * requires the query to look like a phone number as well. In + * order to not accidentally start matching all queries to phone + * numbers, it seems justified to normalize the query only when + * it is a phone number, not whenever it looks like a piece of a + * phone number. + */ + + String phoneNumberQuery = getPhoneNumberQuery(); + + if ((phoneNumberQuery != null) + && (phoneNumberQuery.length() != 0)) + { + try + { + phoneNumberMatches + = phoneNumberI18nService.phoneNumbersMatch( + phoneNumberQuery, + phoneNumber); + } + catch (IllegalArgumentException iaex) + { + /* + * Ignore it, phoneNumberMatches will remain equal to + * false. + */ + } + } + } + } + return phoneNumberMatches; + } + + + /** + * Create a SourceContact from a GoogleContactsEntry. + * + * @param entry GoogleContactsEntry + */ + private void onGoogleContactsEntry(GoogleContactsEntry entry) + { + String displayName = entry.getFullName(); + if(displayName == null || displayName.length() == 0) + { + if((entry.getGivenName() == null || + entry.getGivenName().length() == 0) && + (entry.getFamilyName() == null || + entry.getFamilyName().length() == 0)) + { + return; + } + + displayName = entry.getGivenName() + " " + + entry.getFamilyName(); + } + + List contactDetails = getContactDetails(entry); + + if (!contactDetails.isEmpty()) + { + GenericSourceContact sourceContact + = new GenericSourceContact( + getContactSource(), + displayName, + contactDetails); + + try + { + byte img[] = GoogleContactsServiceImpl.downloadPhoto( + ((GoogleContactsEntryImpl)entry).getPhotoLink(), + getContactSource().getConnection(). + getGoogleService()); + sourceContact.setImage(img); + } + catch (OutOfMemoryError oome) + { + // Ignore it, the image is not vital. + } + + addQueryResult(sourceContact); + } + } + + /** + * Performs this AsyncContactQuery in a background Thread. + * + * @see AsyncContactQuery#run() + */ + @Override + protected void run() + { + GoogleContactsServiceImpl service = (GoogleContactsServiceImpl) + GoogleContactsActivator.getGoogleContactsService(); + gQuery = new GoogleQuery(query); + + GoogleContactsConnection cnx = getContactSource().getConnection(); + + if(cnx == null) + { + return; + } + + service.searchContact( + cnx, + gQuery, + count, + new GoogleEntryCallback() + { + public void callback(GoogleContactsEntry entry) + { + onGoogleContactsEntry(entry); + } + }); + } + + /** + * Gets the contactDetails to be set on a SourceContact. + * + * @param entry GoogleContactsEntry + * @return the contactDetails to be set on a SourceContact + */ + private List getContactDetails(GoogleContactsEntry entry) + { + List ret = new LinkedList(); + List homeMails = entry.getHomeMails(); + List workMails = entry.getWorkMails(); + List mobilePhones = entry.getMobilePhones(); + List homePhones = entry.getHomePhones(); + List workPhones = entry.getWorkPhones(); + Map ims = + entry.getIMAddresses(); + ContactDetail detail = null; + + for(String mail : homeMails) + { + detail = new ContactDetail(mail, ContactDetail.CATEGORY_EMAIL, + new String[]{ContactDetail.LABEL_HOME}); + ret.add(detail); + } + for(String mail : workMails) + { + detail = new ContactDetail(mail, ContactDetail.CATEGORY_EMAIL, + new String[]{ContactDetail.LABEL_WORK}); + ret.add(detail); + } + + for(String homePhone : homePhones) + { + List> supportedOpSets + = new ArrayList>(1); + + supportedOpSets.add(OperationSetBasicTelephony.class); + homePhone = normalizePhoneNumber(homePhone); + detail = new ContactDetail(homePhone, + ContactDetail.CATEGORY_PHONE, + new String[]{ContactDetail.LABEL_HOME}); + detail.setSupportedOpSets(supportedOpSets); + ret.add(detail); + } + + for(String workPhone : workPhones) + { + List> supportedOpSets + = new ArrayList>(1); + + supportedOpSets.add(OperationSetBasicTelephony.class); + workPhone = normalizePhoneNumber(workPhone); + detail = new ContactDetail(workPhone, + ContactDetail.CATEGORY_PHONE, + new String[]{ContactDetail.LABEL_WORK}); + detail.setSupportedOpSets(supportedOpSets); + ret.add(detail); + } + + for(String mobilePhone : mobilePhones) + { + List> supportedOpSets + = new ArrayList>(1); + + supportedOpSets.add(OperationSetBasicTelephony.class); + mobilePhone = normalizePhoneNumber(mobilePhone); + detail = new ContactDetail(mobilePhone, + ContactDetail.CATEGORY_PHONE, + new String[]{ContactDetail.LABEL_MOBILE}); + detail.setSupportedOpSets(supportedOpSets); + ret.add(detail); + } + + for(Map.Entry im : + ims.entrySet()) + { + if(im.getValue() != GoogleContactsEntry.IMProtocol.OTHER) + { + detail = new ContactDetail(im.getKey(), + ContactDetail.CATEGORY_INSTANT_MESSAGING, + new String[]{im.getValue().toString()}); + + setIMCapabilities(detail, im.getValue()); + ret.add(detail); + } + } + + return ret; + } + + /** + * Sets the IM capabilities of a specific ContactDetail (e.g. + * supportedOpSets). + * + * @param contactDetail the ContactDetail to set the capabilities + * of + * @param protocol protocol + * @return contactDetail + */ + private ContactDetail setIMCapabilities( + ContactDetail contactDetail, + GoogleContactsEntry.IMProtocol protocol) + { + List> supportedOpSets + = new LinkedList>(); + Map, String> preferredProtocols + = new HashMap, String>(); + + switch (protocol) + { + case GOOGLETALK: + supportedOpSets.add(OperationSetBasicInstantMessaging.class); + preferredProtocols.put( + OperationSetBasicInstantMessaging.class, + ProtocolNames.AIM); + break; + case ICQ: + supportedOpSets.add(OperationSetBasicInstantMessaging.class); + preferredProtocols.put( + OperationSetBasicInstantMessaging.class, + ProtocolNames.ICQ); + break; + case JABBER: + supportedOpSets.add(OperationSetBasicInstantMessaging.class); + preferredProtocols.put( + OperationSetBasicInstantMessaging.class, + ProtocolNames.JABBER); + supportedOpSets.add(OperationSetBasicTelephony.class); + preferredProtocols.put( + OperationSetBasicTelephony.class, + ProtocolNames.JABBER); + break; + case MSN: + supportedOpSets.add(OperationSetBasicInstantMessaging.class); + preferredProtocols.put( + OperationSetBasicInstantMessaging.class, + ProtocolNames.MSN); + break; + case YAHOO: + supportedOpSets.add(OperationSetBasicInstantMessaging.class); + preferredProtocols.put( + OperationSetBasicInstantMessaging.class, + ProtocolNames.YAHOO); + break; + default: + break; + } + contactDetail.setSupportedOpSets(supportedOpSets); + + if (!preferredProtocols.isEmpty()) + contactDetail.setPreferredProtocols(preferredProtocols); + + return contactDetail; + } + + /** + * Notifies this GoogleContactsQuery that it has stopped performing + * in the associated background Thread. + * + * @param completed true if this ContactQuery has + * successfully completed, false if an error has been encountered + * during its execution + * @see AsyncContactQuery#stopped(boolean) + */ + @Override + protected void stopped(boolean completed) + { + try + { + super.stopped(completed); + } + finally + { + getContactSource().stopped(this); + } + } + + /** + * Cancels this ContactQuery. + * + * @see ContactQuery#cancel() + */ + @Override + public void cancel() + { + if(gQuery != null) + { + gQuery.cancel(); + } + super.cancel(); + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsServiceImpl.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsServiceImpl.java new file mode 100644 index 000000000..77efe3c83 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsServiceImpl.java @@ -0,0 +1,427 @@ +/* + * 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.impl.googlecontacts; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.regex.*; + +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.service.googlecontacts.*; +import net.java.sip.communicator.util.*; + +import com.google.gdata.client.Service.*; +import com.google.gdata.client.contacts.*; +import com.google.gdata.data.*; +import com.google.gdata.data.contacts.ContactFeed; +import com.google.gdata.data.contacts.ContactEntry; +import com.google.gdata.data.extensions.*; + +/** + * Implementation of Google Contacts service. + * We first get {@link #MAX_RESULT} contacts from Google Contacts then + * we filter it to get {@link #MAX_RESULT} that matched our query. + * If {@link #MAX_RESULT} is not reach, we try with additional + * contacts (if there are more than {@link #MAX_RESULT} contacts). + * + * @author Sebastien Vincent + */ +public class GoogleContactsServiceImpl + implements GoogleContactsService +{ + /** + * Logger. + */ + private static final Logger logger = + Logger.getLogger(GoogleContactsServiceImpl.class); + + /** + * Google Contacts feed URL string. + */ + private static final String feedURL = + "https://www.google.com/m8/feeds/contacts/default/full"; + + /** + * Maximum number of results for a query. + */ + public static final int MAX_RESULT = 20; + + /** + * Maximum number of contacts retrieved for a query. + */ + public static final int MAX_NUMBER = 1000; + + /** + * List of Google Contacts account. + */ + private final List accounts = + new ArrayList(); + + /** + * Path where to store the account settings + */ + private final static String CONFIGURATION_PATH = + "net.java.sip.communicator.impl.googlecontacts"; + + /** + * Constructor. + */ + public GoogleContactsServiceImpl() + { + loadConfig(); + } + + /** + * Get list of stored connections. + * + * @return list of connections + */ + public List getAccounts() + { + return accounts; + } + + /** + * Loads configuration. + */ + private void loadConfig() + { + ConfigurationService configService = + GoogleContactsActivator.getConfigService(); + CredentialsStorageService credentialsService = + GoogleContactsActivator.getCredentialsService(); + + List list = configService.getPropertyNamesByPrefix( + CONFIGURATION_PATH, true); + + for(Object configEntry : list) + { + String path = configEntry.toString(); + Object oen = configService.getProperty(path + ".enabled"); + boolean enabled = Boolean.parseBoolean((String)oen); + String login = + (String)configService.getProperty(path + ".account"); + String password = credentialsService.loadPassword(path); + + GoogleContactsConnectionImpl cnx = (GoogleContactsConnectionImpl) + getConnection(login, password); + cnx.setEnabled(enabled); + + if(cnx != null) + { + accounts.add(cnx); + /* register contact source */ + if(cnx.isEnabled()) + { + addContactSource(cnx); + } + } + } + } + + /** + * Perform a search for a contact using regular expression. + * + * @param cnx GoogleContactsConnection to perform the query + * @param gQuery Google query + * @param count maximum number of matched contacts + * @param callback object that will be notified for each new + * GoogleContactsEntry found + * @return list of GoogleContactsEntry + */ + public List searchContact( + GoogleContactsConnection cnx, GoogleQuery gQuery, int count, + GoogleEntryCallback callback) + { + URL url = null; + ContactFeed contactFeed = null; + ContactQuery query = null; + List ret = new ArrayList(); + boolean endOfContacts = false; + int matchedContacts = 0; + int index = 1; + GoogleContactsConnectionImpl cnxImpl = + (GoogleContactsConnectionImpl)cnx; + + if(count <= 0) + { + count = MAX_RESULT; + } + + try + { + url = new URL(feedURL); + } + catch(MalformedURLException e) + { + logger.info("Malformed URL", e); + return ret; + } + + if(gQuery.isCancelled()) + { + return ret; + } + + while(matchedContacts < count || endOfContacts) + { + query = new ContactQuery(url); + query.setStartIndex(index); + query.setMaxResults(MAX_NUMBER); + query.setSortOrder(ContactQuery.SortOrder.DESCENDING); + + if(gQuery.isCancelled()) + { + return ret; + } + + try + { + contactFeed = cnxImpl.getGoogleService().query( + query, ContactFeed.class); + } + catch(Exception e) + { + logger.info( + "Problem occurred during Google Contacts retrievment", + e); + return ret; + } + + if(contactFeed.getEntries().size() == 0) + { + endOfContacts = true; + break; + } + + for (int i = 0; i < contactFeed.getEntries().size(); i++) + { + if(gQuery.isCancelled()) + { + return ret; + } + + ContactEntry entry = contactFeed.getEntries().get(i); + + if(filter(entry, gQuery.getQueryPattern())) + { + GoogleContactsEntry gcEntry = null; + + gcEntry = getGoogleContactsEntry(entry); + matchedContacts++; + ret.add(gcEntry); + + if(callback != null) + { + callback.callback(gcEntry); + } + + if(matchedContacts >= count) + { + break; + } + } + } + + index += contactFeed.getEntries().size(); + } + return ret; + } + + /** + * Filter according to filter. + * + * @param entry ContactEntry + * @param filter regular expression + * @return true if entry match the filter, false otherwise + */ + private boolean filter(ContactEntry entry, Pattern filter) + { + Name name = entry.getName(); + + /* try to see if name, mail or phone match */ + + if(name != null) + { + if(name.hasFamilyName()) + { + Matcher m = filter.matcher(name.getFamilyName().getValue()); + if(m.matches()) + { + return true; + } + } + + if(name.hasGivenName()) + { + Matcher m = filter.matcher(name.getGivenName().getValue()); + if(m.find()) + { + return true; + } + } + + if(name.hasFullName()) + { + Matcher m = filter.matcher(name.getFullName().getValue()); + if(m.find()) + { + return true; + } + } + } + + for(Email mail : entry.getEmailAddresses()) + { + Matcher m = filter.matcher(mail.getAddress()); + + if(m.find()) + { + return true; + } + } + + for(PhoneNumber phone : entry.getPhoneNumbers()) + { + Matcher m = filter.matcher(phone.getPhoneNumber()); + + if(m.find()) + { + return true; + } + } + + return false; + } + + /** + * Get a GoogleContactsEntry from a ContactEntry + * + * @param entry ContactEntry + * @return GoogleContactsEntry + */ + private GoogleContactsEntry getGoogleContactsEntry(ContactEntry entry) + { + GoogleContactsEntryImpl ret = new GoogleContactsEntryImpl(); + + ret.setField(entry); + return ret; + } + + /** + * Get the full contacts list. + * + * @return list of GoogleContactsEntry + */ + public List getContacts() + { + return null; + } + + /** + * Get a GoogleContactsConnection. + * + * @param login login to connect to the service + * @param password password to connect to the service + * @return GoogleContactsConnection. + */ + public GoogleContactsConnection getConnection(String login, + String password) + { + try + { + return new GoogleContactsConnectionImpl(login, password); + } + catch(Exception e) + { + logger.info("Failed to authenticate Google Contacts", e); + return null; + } + } + + /** + * Add a contact source service with the specified. + * + * GoogleContactsConnection. + * @param cnx GoogleContactsConnection. + */ + public void addContactSource(GoogleContactsConnection cnx) + { + GoogleContactsActivator.enableContactSource(cnx); + } + + /** + * Add a contact source service with the specified + * GoogleContactsConnection. + * + * @param login login + * @param password password + */ + public void addContactSource(String login, String password) + { + GoogleContactsActivator.enableContactSource(login, password); + } + + /** + * Add a contact source service with the specified. + * + * GoogleContactsConnection. + * @param cnx GoogleContactsConnection. + */ + public void removeContactSource(GoogleContactsConnection cnx) + { + GoogleContactsActivator.disableContactSource(cnx); + } + + /** + * Remove a contact source service with the specified + * GoogleContactsConnection. + * + * @param login login + */ + public void removeContactSource(String login) + { + GoogleContactsActivator.disableContactSource(login); + } + + /** + * Retrieve photo of a contact. Adapted from Google sample. + * + * @param photoLink photo link + * @param service + * @return byte array containing image photo or null if problem happened + */ + public static byte[] downloadPhoto(ILink photoLink, + ContactsService service) + { + try + { + if (photoLink != null) + { + GDataRequest request = + service.createLinkQueryRequest(photoLink); + request.execute(); + InputStream in = request.getResponseStream(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + + for (int read = 0 ; (read = in.read(buffer)) != -1; + out.write(buffer, 0, read)); + + return out.toByteArray(); + } + } + catch(Exception e) + { + logger.info("Failed to retrieve photo of the contact", e); + } + return null; + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsSourceService.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsSourceService.java new file mode 100644 index 000000000..d36c78f25 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsSourceService.java @@ -0,0 +1,273 @@ +/* + * 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.impl.googlecontacts; + +import java.util.*; +import java.util.regex.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.googlecontacts.*; +import net.java.sip.communicator.util.*; + +/** + * Implements ContactSourceService for Google Contacts. + * + * @author Sebastien Vincent + */ +public class GoogleContactsSourceService + implements ExtendedContactSourceService +{ + /** + * Logger. + */ + private static final Logger logger = + Logger.getLogger(GoogleContactsSourceService.class); + + /** + * The List of GoogleContactsQuery instances + * which have been started and haven't stopped yet. + */ + private final List queries + = new LinkedList(); + + /** + * Login. + */ + private final String login; + + /** + * Password. + */ + private final String password; + + /** + * Google Contacts connection. + */ + private GoogleContactsConnection cnx = null; + + /** + * Constructor. + * + * @param login login + * @param password password + */ + public GoogleContactsSourceService(String login, String password) + { + super(); + this.login = login; + this.password = password; + } + + /** + * Constructor. + * + * @param cnx connection + */ + public GoogleContactsSourceService(GoogleContactsConnection cnx) + { + super(); + this.cnx = cnx; + this.login = cnx.getLogin(); + this.password = cnx.getPassword(); + } + + /** + * Queries this search source for the given searchPattern. + * + * @param queryPattern the pattern to search for + * @return the created query + */ + public ContactQuery queryContactSource(Pattern queryPattern) + { + return queryContactSource(queryPattern, + GoogleContactsQuery.GOOGLECONTACTS_MAX_RESULTS); + } + + /** + * Queries this search source for the given searchPattern. + * + * @param queryPattern the pattern to search for + * @param count maximum number of contact returned + * @return the created query + */ + public ContactQuery queryContactSource(Pattern queryPattern, int count) + { + GoogleContactsQuery query = new GoogleContactsQuery(this, queryPattern, + count); + + synchronized (queries) + { + queries.add(query); + } + + boolean hasStarted = false; + + try + { + query.start(); + hasStarted = true; + } + finally + { + if (!hasStarted) + { + synchronized (queries) + { + if (queries.remove(query)) + queries.notify(); + } + } + } + + return query; + } + + /** + * Returns the Google Contacts connection. + * + * @return Google Contacts connection + */ + public GoogleContactsConnectionImpl getConnection() + { + int s = login.indexOf('@'); + boolean isGoogleAppsOrGmail = false; + + if(s == -1) + { + return null; + } + + String domain = login.substring((s + 1)); + + try + { + SRVRecord srvRecords[] = + NetworkUtils.getSRVRecords("xmpp-client", "tcp", domain); + + if(srvRecords == null) + { + return null; + } + + for(SRVRecord srv : srvRecords) + { + if(srv.getTarget().endsWith("google.com") || + srv.getTarget().endsWith("google.com.")) + { + isGoogleAppsOrGmail = true; + break; + } + } + + if(isGoogleAppsOrGmail) + { + if(cnx == null) + { + cnx = new GoogleContactsConnectionImpl(login, password); + } + } + else + { + cnx = null; + } + } + catch(Exception e) + { + logger.info("GoogleContacts connection error", e); + return null; + } + + return (GoogleContactsConnectionImpl)cnx; + } + + /** + * Returns a user-friendly string that identifies this contact source. + * @return the display name of this contact source + */ + public String getDisplayName() + { + return login; + } + + /** + * Returns the identifier of this contact source. Some of the common + * identifiers are defined here (For example the CALL_HISTORY identifier + * should be returned by all call history implementations of this interface) + * @return the identifier of this contact source + */ + public String getIdentifier() + { + return "GoogleContacts"; + } + + /** + * Queries this search source for the given queryString. + * @param query the string to search for + * @return the created query + */ + public ContactQuery queryContactSource(String query) + { + return queryContactSource( + Pattern.compile(query), + GoogleContactsQuery.GOOGLECONTACTS_MAX_RESULTS); + } + + /** + * Queries this search source for the given queryString. + * + * @param query the string to search for + * @param contactCount the maximum count of result contacts + * @return the created query + */ + public ContactQuery queryContactSource(String query, int contactCount) + { + return queryContactSource(Pattern.compile(query), contactCount); + } + + /** + * Stops this ContactSourceService 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(); + } + + /** + * Notifies this GoogleContactsSourceService that a specific + * GoogleContactsQuery has stopped. + * + * @param query the GoogleContactsQuery which has stopped + */ + void stopped(GoogleContactsQuery query) + { + synchronized (queries) + { + if (queries.remove(query)) + queries.notify(); + } + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/configform/AccountSettingsForm.java b/src/net/java/sip/communicator/impl/googlecontacts/configform/AccountSettingsForm.java new file mode 100644 index 000000000..8cc961ab4 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/configform/AccountSettingsForm.java @@ -0,0 +1,282 @@ +/* + * 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.impl.googlecontacts.configform; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import net.java.sip.communicator.util.swing.*; +import net.java.sip.communicator.impl.googlecontacts.*; +import net.java.sip.communicator.service.googlecontacts.*; + +/** + * The page with hostname/port/encryption fields + * + * @author Sebastien Mazy + * @author Sebastien Vincent + */ +public class AccountSettingsForm + extends SIPCommDialog + implements ActionListener +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * component holding the name + */ + private JTextField nameField; + + /** + * the component holding the password + */ + private JPasswordField passwordField; + + /** + * Save button. + */ + private JButton saveBtn = new JButton( + Resources.getString("impl.googlecontacts.SAVE")); + + /** + * Cancel button. + */ + private JButton cancelBtn = new JButton( + Resources.getString("impl.googlecontacts.CANCEL")); + + /** + * Return code. + */ + private int retCode = 0; + + /** + * The Google Contacts connection. + */ + private GoogleContactsConnection cnx = null; + + /** + * Constructor. + */ + public AccountSettingsForm() + { + this.setTitle(Resources.getString( + "impl.googlecontacts.CONFIG_FORM_TITLE")); + getContentPane().add(getContentPanel()); + setMinimumSize(new Dimension(400, 200)); + setSize(new Dimension(400, 400)); + setPreferredSize(new Dimension(400, 200)); + pack(); + } + + /** + * the panel to display in the card layout of the wizard + * + * @return this page's panel + */ + public JPanel getContentPanel() + { + JPanel contentPanel = new TransparentPanel(new BorderLayout()); + JPanel mainPanel = new TransparentPanel(); + JPanel basePanel = new TransparentPanel(new GridBagLayout()); + JPanel btnPanel = new TransparentPanel(new FlowLayout( + FlowLayout.RIGHT)); + BoxLayout boxLayout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS); + + GridBagConstraints c = new GridBagConstraints(); + + /* name text field */ + JLabel nameLabel = new JLabel( + Resources.getString("impl.googlecontacts.ACCOUNT_NAME")); + this.nameField = new JTextField(); + nameLabel.setLabelFor(nameField); + c.gridx = 0; + c.gridy = 0; + c.weightx = 0; + c.weighty = 0; + c.gridwidth = 1; + c.insets = new Insets(2, 50, 0, 5); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_START; + basePanel.add(nameLabel, c); + c.gridx = 1; + c.gridy = 0; + c.weightx = 1; + c.weighty = 0; + c.gridwidth = GridBagConstraints.REMAINDER; + c.insets = new Insets(2, 5, 0, 50); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_END; + basePanel.add(nameField, c); + JLabel nameExampleLabel = new JLabel("myaccount@gmail.com"); + nameExampleLabel.setForeground(Color.GRAY); + nameExampleLabel.setFont(nameExampleLabel.getFont().deriveFont(8)); + c.gridx = 1; + c.gridy = 1; + c.weightx = 1; + c.weighty = 0; + c.gridwidth = GridBagConstraints.REMAINDER; + c.insets = new Insets(0, 13, 2, 0); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_START; + basePanel.add(nameExampleLabel, c); + + JLabel passwordLabel = new JLabel( + Resources.getString("impl.googlecontacts.PASSWORD")); + this.passwordField = new JPasswordField(); + nameLabel.setLabelFor(passwordField); + c.gridx = 0; + c.gridy = 2; + c.weightx = 0; + c.weighty = 0; + c.gridwidth = 1; + c.insets = new Insets(2, 50, 0, 5); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_START; + basePanel.add(passwordLabel, c); + c.gridx = 1; + c.gridy = 2; + c.weightx = 1; + c.weighty = 0; + c.gridwidth = GridBagConstraints.REMAINDER; + c.insets = new Insets(2, 5, 0, 50); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_END; + basePanel.add(passwordField, c); + + mainPanel.setLayout(boxLayout); + mainPanel.add(basePanel); + + /* listeners */ + this.nameField.addActionListener(this); + this.passwordField.addActionListener(this); + this.saveBtn.addActionListener(this); + this.cancelBtn.addActionListener(this); + + btnPanel.add(saveBtn); + btnPanel.add(cancelBtn); + + contentPanel.add(mainPanel, BorderLayout.CENTER); + contentPanel.add(btnPanel, BorderLayout.SOUTH); + + return contentPanel; + } + + /** + * Loads the information. + * + * @param cnx connection + */ + public void loadData(GoogleContactsConnection cnx) + { + if(cnx != null) + { + this.nameField.setText(cnx.getLogin()); + this.passwordField.setText(cnx.getPassword()); + } + else + { + this.nameField.setText(""); + this.passwordField.setText(""); + } + } + + /** + * Implementation of actionPerformed. + * + * @param e the ActionEvent triggered + */ + public void actionPerformed(ActionEvent e) + { + Object src = e.getSource(); + + if(src == saveBtn) + { + String login = nameField.getText(); + String password = new String(passwordField.getPassword()); + + cnx = GoogleContactsActivator.getGoogleContactsService(). + getConnection(login, password); + + if(cnx == null) + { + JOptionPane.showMessageDialog( + this, + Resources.getString( + "impl.googlecontacts.WRONG_CREDENTIALS", + new String[]{login}), + Resources.getString( + "impl.googlecontacts.WRONG_CREDENTIALS", + new String[]{login}), + JOptionPane.WARNING_MESSAGE); + return; + } + + retCode = 1; + dispose(); + } + else if(src == cancelBtn) + { + retCode = 0; + dispose(); + } + } + + /** + * Get the connection. + * + * @return GoogleContactsConnection + */ + public GoogleContactsConnection getConnection() + { + return cnx; + } + + /** + * All functions implemented in this method will be invoked when user + * presses the Escape key. + * + * @param escaped true if this dialog has been closed by pressing + * the Esc key; otherwise, false + */ + protected void close(boolean escaped) + { + cancelBtn.doClick(); + } + + /** + * Show the dialog and returns if the user has modified something (create + * or modify entry). + * + * @return true if the user has modified something (create + * or modify entry), false otherwise. + */ + public int showDialog() + { + retCode = 0; + + cnx = null; + setVisible(true); + + // this will block until user click on save/cancel/press escape/close + // the window + setVisible(false); + return retCode; + } + + /** + * Set the name field enable or not + * + * @param enable parameter to set + */ + public void setNameFieldEnabled(boolean enable) + { + this.nameField.setEnabled(enable); + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsConfigForm.java b/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsConfigForm.java new file mode 100644 index 000000000..60ad2701c --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsConfigForm.java @@ -0,0 +1,394 @@ +/* + * 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.impl.googlecontacts.configform; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; +import net.java.sip.communicator.impl.googlecontacts.*; +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.googlecontacts.*; + +/** + * This ConfigurationForm shows the list of Google Contacts account and allow + * users to manage them. + * + * @author Sebastien Mazy + * @author Sebastien Vincent + */ +public class GoogleContactsConfigForm + extends TransparentPanel + implements ConfigurationForm, + ActionListener, + ListSelectionListener + +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The logger for this class. + */ + private static Logger logger = Logger.getLogger( + GoogleContactsConfigForm.class); + + /** + * Opens the new directory registration wizard + */ + private JButton newButton = new JButton("+"); + + /** + * Opens a directory modification dialog + */ + private JButton modifyButton = new JButton( + Resources.getString("impl.googlecontacts.EDIT")); + + /** + * Pops a directory deletion confirmation dialog + */ + private JButton removeButton = new JButton("-"); + + /** + * Displays the registered Google Contacts account. + */ + private JTable accountTable = new JTable(); + + /** + * Contains the new/modify/remove buttons + */ + private TransparentPanel buttonsPanel + = new TransparentPanel(new FlowLayout(FlowLayout.LEFT)); + + /** + * Contains the directoryTable + */ + private JScrollPane scrollPane = new JScrollPane(); + + /** + * Contains the buttonsPanel, + */ + private JPanel rightPanel = new TransparentPanel(new BorderLayout()); + + /** + * Contains listPanel and rightPanel + */ + private JPanel mainPanel = this; + + /** + * Model for the directoryTable + */ + private GoogleContactsTableModel tableModel = + new GoogleContactsTableModel(); + + /** + * Settings form. + */ + private final AccountSettingsForm settingsForm = + new AccountSettingsForm(); + + /** + * Path where to store the account settings + */ + private final static String CONFIGURATION_PATH = + "net.java.sip.communicator.impl.googlecontacts"; + + /** + * Constructor + */ + public GoogleContactsConfigForm() + { + super(new BorderLayout()); + logger.trace("GoogleContacts configuration form."); + initComponents(); + } + + /** + * Remove a connection. + * + * @param cnx connection to save + */ + private void removeConfig(GoogleContactsConnection cnx) + { + ConfigurationService configService = + GoogleContactsActivator.getConfigService(); + configService.removeProperty(CONFIGURATION_PATH + ".acc" + + Math.abs(cnx.getLogin().hashCode())); + } + + /** + * Save configuration. + * + * @param cnx connection to save + */ + private void saveConfig(GoogleContactsConnection cnx) + { + ConfigurationService configService = + GoogleContactsActivator.getConfigService(); + CredentialsStorageService credentialsService = + GoogleContactsActivator.getCredentialsService(); + String login = cnx.getLogin(); + String path = CONFIGURATION_PATH + ".acc" + Math.abs(login.hashCode()); + + configService.setProperty( + path, + login); + configService.setProperty( + path + ".account", + login); + configService.setProperty( + path + ".enabled", + ((GoogleContactsConnectionImpl)cnx).isEnabled()); + credentialsService.storePassword(path, cnx.getPassword()); + } + + /** + * Inits the swing components + */ + private void initComponents() + { + modifyButton.setEnabled(false); + removeButton.setEnabled(false); + + newButton.setSize(newButton.getMinimumSize()); + modifyButton.setSize(modifyButton.getMinimumSize()); + removeButton.setSize(removeButton.getMinimumSize()); + + accountTable.setRowHeight(22); + accountTable.setSelectionMode( + ListSelectionModel.SINGLE_SELECTION); + + accountTable.setShowHorizontalLines(false); + accountTable.setShowVerticalLines(false); + accountTable.setModel(tableModel); + accountTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + accountTable.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + if(e.getClickCount() > 1) + { + } + } + }); + + settingsForm.setModal(true); + + /* consistency with the accounts config form */ + rightPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + rightPanel.add(buttonsPanel, BorderLayout.NORTH); + + scrollPane.getViewport().add(accountTable); + mainPanel.add(scrollPane, BorderLayout.CENTER); + mainPanel.add(rightPanel, BorderLayout.SOUTH); + + mainPanel.setPreferredSize(new Dimension(500, 400)); + + buttonsPanel.add(newButton); + buttonsPanel.add(removeButton); + buttonsPanel.add(modifyButton); + + accountTable.getSelectionModel().addListSelectionListener(this); + + newButton.setActionCommand("new"); + newButton.addActionListener(this); + modifyButton.addActionListener(this); + modifyButton.setActionCommand("modify"); + removeButton.addActionListener(this); + removeButton.setActionCommand("remove"); + } + + /** + * @see net.java.sip.communicator.service.gui.ConfigurationForm#getTitle + */ + public String getTitle() + { + return Resources.getString("impl.googlecontacts.CONFIG_FORM_TITLE"); + } + + /** + * @see net.java.sip.communicator.service.gui.ConfigurationForm#getIcon + */ + public byte[] getIcon() + { + return Resources.getImageInBytes( + "GOOGLECONTACTS_CONFIG_FORM_ICON"); + } + + /** + * @see net.java.sip.communicator.service.gui.ConfigurationForm#getForm + */ + public Object getForm() + { + return this; + } + + /** + * Required by ConfirgurationForm interface + * + * Returns the index of this configuration form in the configuration window. + * This index is used to put configuration forms in the desired order. + *

+ * 0 is the first position + * -1 means that the form will be put at the end + *

+ * @return the index of this configuration form in the configuration window. + * + * @see net.java.sip.communicator.service.gui.ConfigurationForm#getIndex + */ + public int getIndex() + { + return -1; + } + + /** + * Processes buttons events (new, modify, remove) + * + * @see java.awt.event.ActionListener#actionPerformed + */ + public void actionPerformed(ActionEvent e) + { + int row = accountTable.getSelectedRow(); + + if (e.getActionCommand().equals("new")) + { + settingsForm.setNameFieldEnabled(true); + settingsForm.loadData(null); + int ret = settingsForm.showDialog(); + + if(ret == 1) + { + GoogleContactsConnection cnx = settingsForm.getConnection(); + tableModel.addAccount(cnx, true); + new RefreshContactSourceThread(null, cnx).start(); + saveConfig(cnx); + refresh(); + } + } + + if (e.getActionCommand().equals("modify") && row != -1) + { + settingsForm.setNameFieldEnabled(false); + GoogleContactsConnection cnx = tableModel.getAccountAt(row); + settingsForm.loadData(cnx); + + int ret = settingsForm.showDialog(); + + if(ret == 1) + { + refresh(); + } + } + + if (e.getActionCommand().equals("remove") && row != -1) + { + GoogleContactsConnection cnx = tableModel.getAccountAt(row); + tableModel.removeAccount(cnx.getLogin()); + removeConfig(cnx); + new RefreshContactSourceThread(cnx, null).start(); + refresh(); + } + } + + /** + * Required by ListSelectionListener. Enables the "modify" + * button when a server is selected in the table + * + * @param e event triggered + */ + public void valueChanged(ListSelectionEvent e) + { + if(accountTable.getSelectedRow() == -1) + { + modifyButton.setEnabled(false); + removeButton.setEnabled(false); + return; + } + else if(!e.getValueIsAdjusting()) + { + modifyButton.setEnabled(true); + removeButton.setEnabled(true); + saveConfig(tableModel.getAccountAt(accountTable.getSelectedRow())); + } + } + + /** + * refreshes the table display + */ + private void refresh() + { + tableModel.fireTableStructureChanged(); + } + + /** + * Indicates if this is an advanced configuration form. + * @return true if this is an advanced configuration form, + * otherwise it returns false + */ + public boolean isAdvanced() + { + return true; + } + + /** + * Thread that will perform refresh of contact sources. + */ + public static class RefreshContactSourceThread + extends Thread + { + /** + * Old connection. + */ + private GoogleContactsConnection oldCnx = null; + + /** + * New connection. + */ + private GoogleContactsConnection newCnx = null; + + /** + * Constructor. + * + * @param oldCnx old connection. + * @param newCnx new connection. + */ + RefreshContactSourceThread(GoogleContactsConnection oldCnx, + GoogleContactsConnection newCnx) + { + this.oldCnx = oldCnx; + this.newCnx = newCnx; + } + + /** + * Thread entry point. + */ + public void run() + { + if(oldCnx != null) + { + GoogleContactsActivator.getGoogleContactsService(). + removeContactSource(oldCnx); + } + + if(newCnx != null) + { + GoogleContactsActivator.getGoogleContactsService(). + addContactSource(newCnx); + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsTableModel.java b/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsTableModel.java new file mode 100644 index 000000000..bc51bbc0f --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/configform/GoogleContactsTableModel.java @@ -0,0 +1,217 @@ +/* + * 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.impl.googlecontacts.configform; + +import java.util.*; + +import javax.swing.table.*; + +import net.java.sip.communicator.service.googlecontacts.*; +import net.java.sip.communicator.impl.googlecontacts.*; + + +/** + * A table model suitable for the directories list in + * the configuration form. Takes its data in an LdapDirectorySet. + * + * @author Sebastien Mazy + * @author Sebastien Vincent + */ +public class GoogleContactsTableModel + extends AbstractTableModel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Google Contacts service reference. + */ + private final GoogleContactsServiceImpl googleService = + GoogleContactsActivator.getGoogleContactsService(); + + /** + * Add account from table. + * + * @param cnx account + * @param enabled if the account should be enabled + */ + public void addAccount(GoogleContactsConnection cnx, boolean enabled) + { + if(cnx != null) + { + ((GoogleContactsConnectionImpl)cnx).setEnabled(enabled); + googleService.getAccounts().add((GoogleContactsConnectionImpl)cnx); + } + } + + /** + * Remove account from table. + * + * @param login account login to remove + */ + public void removeAccount(String login) + { + Iterator it = + googleService.getAccounts().iterator(); + + while(it.hasNext()) + { + GoogleContactsConnection cnx = it.next(); + if(cnx.getLogin().equals(login)) + { + it.remove(); + return; + } + } + } + + /** + * Returns the title for this column + * + * @param column the column + * + * @return the title for this column + * + * @see javax.swing.table.AbstractTableModel#getColumnName + */ + public String getColumnName(int column) + { + switch(column) + { + case 0: + return Resources.getString("impl.googlecontacts.ENABLED"); + case 1: + return Resources.getString("impl.googlecontacts.ACCOUNT_NAME"); + default: + throw new IllegalArgumentException("column not found"); + } + } + + /** + * Returns the number of rows in the table + * + * @return the number of rows in the table + * @see javax.swing.table.AbstractTableModel#getRowCount + */ + public int getRowCount() + { + return googleService.getAccounts().size(); + } + + /** + * Returns the number of column in the table + * + * @return the number of columns in the table + * + * @see javax.swing.table.AbstractTableModel#getColumnCount + */ + public int getColumnCount() + { + // 2 columns: "enable" and "account name" + return 2; + } + + /** + * Returns the text for the given cell of the table + * + * @param row cell row + * @param column cell column + * + * @see javax.swing.table.AbstractTableModel#getValueAt + */ + public Object getValueAt(int row, int column) + { + switch(column) + { + case 0: + return new Boolean(getAccountAt(row).isEnabled()); + case 1: + return getAccountAt(row).getLogin(); + default: + throw new IllegalArgumentException("column not found"); + } + } + + /** + * Returns the account credentials at the row 'row' + * + * @param row the row + * + * @return the login/password for the account + */ + public GoogleContactsConnectionImpl getAccountAt(int row) + { + if(row < 0 || row >= googleService.getAccounts().size()) + { + throw new IllegalArgumentException("row not found"); + } + else + { + return googleService.getAccounts().get(row); + } + } + + /** + * Returns whether a cell is editable. Only "enable" column (checkboxes) + * is editable + * + * @param row row of the cell + * @param col column of the cell + * + * @return whether the cell is editable + */ + public boolean isCellEditable(int row, int col) + { + if(col == 0) + return true; + else + return false; + } + + /** + * Overrides a method that always returned Object.class + * Now it will return Boolean.class for the first method, + * letting the DefaultTableCellRenderer create checkboxes. + * + * @param columnIndex index of the column + * @return Column class + */ + public Class getColumnClass(int columnIndex) + { + return getValueAt(0, columnIndex).getClass(); + } + + /** + * Sets a value in an editable cell, that is to say + * an enable/disable chekbox in colum 0 + */ + public void setValueAt(Object aValue, int rowIndex, int columnIndex) + { + if(columnIndex != 0) + throw new IllegalArgumentException("non editable column!"); + + GoogleContactsConfigForm.RefreshContactSourceThread th = null; + GoogleContactsConnectionImpl cnx = getAccountAt(rowIndex); + + if(cnx.isEnabled()) + { + th = new GoogleContactsConfigForm.RefreshContactSourceThread(cnx, + null); + } + else + { + th = new GoogleContactsConfigForm.RefreshContactSourceThread(null, + cnx); + } + + cnx.setEnabled(!cnx.isEnabled()); + + th.start(); + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/configform/Resources.java b/src/net/java/sip/communicator/impl/googlecontacts/configform/Resources.java new file mode 100644 index 000000000..2e01fc4cb --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/configform/Resources.java @@ -0,0 +1,68 @@ +/* + * 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.impl.googlecontacts.configform; + +import javax.swing.*; + +import net.java.sip.communicator.impl.googlecontacts.*; + +/** + * The Resources class manages the access to the internationalization + * properties files and the image resources used in this plugin. + * + * @author Yana Stamcheva + */ +public class Resources +{ + /** + * Returns an internationalized string corresponding to the given key. + * + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + return GoogleContactsActivator.getResourceManagementService() + .getI18NString(key); + } + + /** + * Returns an internationalized string corresponding to the given key. + * + * @param key The key of the string. + * @param params additionnal parameters + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key, String[] params) + { + return GoogleContactsActivator.getResourceManagementService() + .getI18NString(key, params); + } + + /** + * Loads an image from a given image identifier. + * + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static ImageIcon getImage(String imageID) + { + return GoogleContactsActivator.getResourceManagementService().getImage(imageID); + } + + /** + * Loads an image from a given image identifier. + * + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static byte[] getImageInBytes(String imageID) + { + return GoogleContactsActivator.getResourceManagementService(). + getImageInBytes(imageID); + } +} diff --git a/src/net/java/sip/communicator/impl/googlecontacts/googlecontacts.manifest.mf b/src/net/java/sip/communicator/impl/googlecontacts/googlecontacts.manifest.mf new file mode 100644 index 000000000..04c9fbaf2 --- /dev/null +++ b/src/net/java/sip/communicator/impl/googlecontacts/googlecontacts.manifest.mf @@ -0,0 +1,26 @@ +Bundle-Activator: net.java.sip.communicator.impl.googlecontacts.GoogleContactsActivator +Bundle-Name: Google Contacts Service Implementation +Bundle-Description: A bundle that offers access to Google Contacts +Bundle-Vendor: sip-communicator.org +Bundle-Version: 0.0.1 +System-Bundle: yes +Import-Package: org.osgi.framework, + net.java.sip.communicator.service.configuration, + net.java.sip.communicator.service.credentialsstorage, + net.java.sip.communicator.service.contactsource, + net.java.sip.communicator.service.gui, + net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.protocol, + net.java.sip.communicator.util, + net.java.sip.communicator.util.swing, + org.xml.sax, + org.xml.sax.helpers, + javax.xml.parsers, + javax.xml, + javax.swing, + javax.swing.border, + javax.swing.event, + javax.swing.table, + javax.swing.tree, + javax.swing.text, +Export-Package: net.java.sip.communicator.service.googlecontacts \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/ldap/LdapActivator.java b/src/net/java/sip/communicator/impl/ldap/LdapActivator.java index 12428a01a..d3b435519 100644 --- a/src/net/java/sip/communicator/impl/ldap/LdapActivator.java +++ b/src/net/java/sip/communicator/impl/ldap/LdapActivator.java @@ -44,7 +44,7 @@ public static LdapService getLdapService() * Starts the LDAP service * * @param bundleContext BundleContext - * @throws Exception + * @throws Exception if something goes wrong when starting service */ public void start(BundleContext bundleContext) throws Exception @@ -72,6 +72,9 @@ public void start(BundleContext bundleContext) /** * Stops the LDAP service + * + * @param bundleContext BundleContext + * @throws Exception if something goes wrong when stopping service */ public void stop(BundleContext bundleContext) throws Exception diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java index 9cb4c1ede..71bf547c9 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java @@ -1119,7 +1119,7 @@ public ScreenDevice getScreenForPoint(Point p) return null; } - + /** * Get origin for desktop streaming device. * @@ -1130,7 +1130,7 @@ public Point getOriginForDesktopStreamingDevice(MediaDevice mediaDevice) MediaDeviceImpl dev = (MediaDeviceImpl)mediaDevice; CaptureDeviceInfo devInfo = dev.getCaptureDeviceInfo(); MediaLocator locator = devInfo.getLocator(); - + if(!locator.getProtocol(). equals(ImageStreamingAuto.LOCATOR_PROTOCOL)) { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JabberActivator.java b/src/net/java/sip/communicator/impl/protocol/jabber/JabberActivator.java index 552c8be32..c40c1ce0c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JabberActivator.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JabberActivator.java @@ -16,8 +16,10 @@ import net.java.sip.communicator.service.packetlogging.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.service.googlecontacts.*; import net.java.sip.communicator.util.*; +import org.jivesoftware.smack.util.StringUtils; import org.osgi.framework.*; /** @@ -84,7 +86,17 @@ public class JabberActivator */ private static HIDService hidService = null; - private static PacketLoggingService packetLoggingService = null; + /** + * A reference to the currently valid PacketLoggingService + * instance. + */ + private static PacketLoggingService packetLoggingService = null; + + /** + * A reference to the currently valid GoogleContactsService + * instance. + */ + private static GoogleContactsService googleService = null; /** * Called when this bundle is started so the Framework can perform the @@ -323,4 +335,24 @@ public static PacketLoggingService getPacketLogging() } return packetLoggingService; } + + /** + * Returns a reference to the GoogleContactsService implementation + * currently registered in the bundle context or null if no such + * implementation was found. + * + * @return a reference to a GoogleContactsService implementation + * currently registered in the bundle context or null if no such + * implementation was found. + */ + public static GoogleContactsService getGoogleService() + { + if (googleService == null) + { + googleService + = ServiceUtils.getService( + bundleContext, GoogleContactsService.class); + } + return googleService; + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java index adf88e042..ab74f5e4f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java @@ -158,7 +158,10 @@ public void modifyAccount( ProtocolProviderService protocolProvider, try { if(protocolProvider.isRegistered()) + { protocolProvider.unregister(); + protocolProvider.shutdown(); + } } catch (Throwable e) { // we don't care for this, cause we are modifying and diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 7cd11b24a..7521866f9 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -22,6 +22,7 @@ import net.java.sip.communicator.impl.protocol.jabber.extensions.inputevt.*; import net.java.sip.communicator.impl.protocol.jabber.sasl.*; import net.java.sip.communicator.service.certificate.*; +import net.java.sip.communicator.service.googlecontacts.*; import org.jivesoftware.smack.*; import org.jivesoftware.smack.packet.*; @@ -927,7 +928,6 @@ private void disconnectAndCleanConnection() } catch (Exception e) {} - connectionListener = null; connection = null; // make it null as it also holds a reference to the old connection @@ -1258,6 +1258,9 @@ protected void initialize(String screenname, OperationSetGenericNotifications.class, new OperationSetGenericNotificationsJabberImpl(this)); + /* add Google Contacts as contact source if enabled */ + registerGoogleContactsSource(); + isInitialized = true; } } @@ -1274,6 +1277,8 @@ public void shutdown() if (logger.isTraceEnabled()) logger.trace("Killing the Jabber Protocol Provider."); + unregisterGoogleContactsSource(); + //kill all active calls OperationSetBasicTelephonyJabberImpl telephony = (OperationSetBasicTelephonyJabberImpl)getOperationSet( @@ -1897,6 +1902,56 @@ public SmackServiceNode getJingleNodesServiceNode() return jingleNodesServiceNode; } + /** + * Register Google Contacts as contact source if user has enable it. + */ + private void registerGoogleContactsSource() + { + if(accountID.getAccountPropertyBoolean( + "GOOGLE_CONTACTS_ENABLED", + false)) + { + logger.info("Register Google Contacts service as contact source"); + GoogleContactsService googleService = + JabberActivator.getGoogleService(); + + if(googleService != null) + { + googleService.addContactSource( + org.jivesoftware.smack.util.StringUtils.parseName( + getOurJID()) + "@" + + StringUtils.parseServer(getAccountID().getUserID()), + JabberActivator. + getProtocolProviderFactory().loadPassword( + getAccountID())); + } + } + } + + /** + * Unregister Google Contacts as contact source. + */ + private void unregisterGoogleContactsSource() + { + if(accountID.getAccountPropertyBoolean( + "GOOGLE_CONTACTS_ENABLED", + false)) + { + logger.info("Unregister Google Contacts service as contact source"); + + GoogleContactsService googleService = + JabberActivator.getGoogleService(); + + if(googleService != null) + { + googleService.removeContactSource( + org.jivesoftware.smack.util.StringUtils.parseName( + getOurJID()) + "@" + + StringUtils.parseServer(getAccountID().getUserID())); + } + } + } + /** * Logs a specific message and associated Throwable cause as an * error using the current Logger and then throws a new diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/jabber.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/jabber/jabber.provider.manifest.mf index 47839ae29..730b6711f 100755 --- a/src/net/java/sip/communicator/impl/protocol/jabber/jabber.provider.manifest.mf +++ b/src/net/java/sip/communicator/impl/protocol/jabber/jabber.provider.manifest.mf @@ -48,6 +48,7 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.argdelegation, net.java.sip.communicator.service.certificate, net.java.sip.communicator.service.gui, + net.java.sip.communicator.service.googlecontacts, org.xmlpull.v1, org.xmlpull.mxp1, javax.xml.parsers, diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/ConnectionPanel.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/ConnectionPanel.java index 6ba34140d..bbbd93a0b 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/ConnectionPanel.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/ConnectionPanel.java @@ -14,13 +14,18 @@ import net.java.sip.communicator.util.swing.*; /** - * + * * @author Yana Stamcheva */ public class ConnectionPanel extends TransparentPanel implements ValidatingPanel { + /** + * Serial version UID. + */ + private final static long serialVersionUID = 0L; + private final TransparentPanel mainPanel = new TransparentPanel(); private final JPanel advancedOpPanel @@ -39,6 +44,10 @@ public class ConnectionPanel Resources.getString( "plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS")); + private final JCheckBox googleContactsBox = new SIPCommCheckBox( + Resources.getString( + "plugin.jabberaccregwizz.ENABLE_GOOGLE_CONTACTS_SOURCE")); + private final JLabel resourceLabel = new JLabel(Resources.getString("plugin.jabberaccregwizz.RESOURCE")); @@ -126,6 +135,7 @@ public void removeUpdate(DocumentEvent evt) = new TransparentPanel(new GridLayout(0, 1, 10, 10)); checkBoxesPanel.add(sendKeepAliveBox); checkBoxesPanel.add(gmailNotificationsBox); + checkBoxesPanel.add(googleContactsBox); advancedOpPanel.add(checkBoxesPanel, BorderLayout.NORTH); advancedOpPanel.add(labelsAdvOpPanel, BorderLayout.WEST); @@ -256,6 +266,28 @@ void setGmailNotificationsEnabled(boolean isEnabled) gmailNotificationsBox.setSelected(isEnabled); } + /** + * Returns true if the "Google contacts" check box is selected, + * otherwise returns false. + * @return true if the "Google contacts" check box is selected, + * otherwise returns false + */ + boolean isGoogleContactsEnabled() + { + return googleContactsBox.isSelected(); + } + + /** + * Selects/unselects the "Google contacts" check box according to the + * given isEnabled property. + * @param isEnabled indicates if the "Google contacts" + * check box should be selected or not + */ + void setGoogleContactsEnabled(boolean isEnabled) + { + googleContactsBox.setSelected(isEnabled); + } + /** * Disables Next Button if Port field value is incorrect */ diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java index 69a96c4dd..7c71148d9 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java @@ -28,6 +28,9 @@ public class FirstWizardPage */ private static final long serialVersionUID = 0L; + /** + * Identifier of the first page. + */ public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier"; private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER; diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java index f3b54892e..7606f691f 100755 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java @@ -88,6 +88,11 @@ public class JabberAccountRegistration */ private boolean enableGmailNotification = false; + /** + * Indicates if Google Contacts should be enabled. + */ + private boolean enableGoogleContacts = false; + /** * Indicates if ICE should be used. */ @@ -232,6 +237,18 @@ public boolean isGmailNotificationEnabled() return enableGmailNotification; } + /** + * Determines whether SIP Communicator should use Google Contacts as + * ContactSource + * + * @return true if we are to enable Google Contacts and + * false otherwise. + */ + public boolean isGoogleContactsEnabled() + { + return enableGoogleContacts; + } + /** * Sets the User ID of the jabber registration account. * @@ -316,6 +333,18 @@ public void setGmailNotificationEnabled(boolean enabled) this.enableGmailNotification = enabled; } + /** + * Specifies whether SIP Communicator should use Google Contacts as + * ContactSource. + * + * @param enabled true if we are to enable Google Contacts and + * false otherwise. + */ + public void setGoogleContactsEnabled(boolean enabled) + { + this.enableGoogleContacts = enabled; + } + /** * Returns the resource. * @return the resource diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java index dfdb7edae..70acc2df0 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java @@ -17,6 +17,11 @@ public class JabberAccountRegistrationForm extends TransparentPanel { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + private final AccountPanel accountPanel; private final ConnectionPanel connectionPanel; @@ -125,7 +130,7 @@ void reValidateInput() } /** - * Adds panel to the list of panels with values which need validation. + * Adds panel to the list of panels with values which need validation. * @param panel ValidatingPanel. */ public void addValidatingPanel(ValidatingPanel panel) @@ -163,7 +168,7 @@ String getServerAddress() /** * Indicates if this wizard is modifying an existing account or is creating * a new one. - * + * * @return true to indicate that this wizard is currently in * modification mode, false - otherwise. */ @@ -193,6 +198,8 @@ public boolean commitPage(JabberAccountRegistration registration) registration.setSendKeepAlive(connectionPanel.isSendKeepAlive()); registration.setGmailNotificationEnabled( connectionPanel.isGmailNotificationsEnabled()); + registration.setGoogleContactsEnabled( + connectionPanel.isGoogleContactsEnabled()); registration.setResource(connectionPanel.getResource()); String serverPort = connectionPanel.getServerPort(); @@ -280,6 +287,12 @@ public void loadAccount(AccountID accountID) connectionPanel.setGmailNotificationsEnabled(gmailNotificationEnabled); + boolean googleContactsEnabled + = Boolean.parseBoolean( + accountProperties.get("GOOGLE_CONTACTS_ENABLED")); + + connectionPanel.setGoogleContactsEnabled(googleContactsEnabled); + String resource = accountProperties.get(ProtocolProviderFactory.RESOURCE); diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java index 5b3b10cd6..ee46655de 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java @@ -295,6 +295,8 @@ protected ProtocolProviderService installAccount( accountProperties.put("GMAIL_NOTIFICATIONS_ENABLED", String.valueOf(registration.isGmailNotificationEnabled())); + accountProperties.put("GOOGLE_CONTACTS_ENABLED", + String.valueOf(registration.isGoogleContactsEnabled())); String serverName = null; if (registration.getServerAddress() != null) diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsConnection.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsConnection.java new file mode 100644 index 000000000..9d0ee3808 --- /dev/null +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsConnection.java @@ -0,0 +1,29 @@ +/* + * 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.service.googlecontacts; + +/** + * Interface that define a Google Contacts connection. + * + * @author Sebastien Vincent + */ +public interface GoogleContactsConnection +{ + /** + * Get login. + * + * @return login to connect to the service + */ + public String getLogin(); + + /** + * get password. + * + * @return password to connect to the service + */ + public String getPassword(); +} diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java new file mode 100644 index 000000000..fd1fba7df --- /dev/null +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java @@ -0,0 +1,185 @@ +/* + * 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.service.googlecontacts; + +import java.util.*; + +/** + * Entry of Google Contacts directory. + * + * @author Sebastien Vincent + */ +public interface GoogleContactsEntry +{ + /** + * The supported IM protocol + */ + public enum IMProtocol + { + /** + * Google Talk protocol. + */ + GOOGLETALK, + + /** + * Yahoo protocol. + */ + YAHOO, + + /** + * AIM protocol. + */ + AIM, + + /** + * MSN protocol. + */ + MSN, + + /** + * ICQ protocol. + */ + ICQ, + + /** + * Jabber protocol. + */ + JABBER, + + /** + * Other protocol (i.e. not supported). + */ + OTHER, + } + + /** + * Get the full name. + * + * @return full name + */ + public String getFullName(); + + /** + * Get the family name. + * + * @return family name + */ + public String getFamilyName(); + + /** + * Get the given name. + * + * @return given name + */ + public String getGivenName(); + + /** + * Returns mails. + * + * @return mails + */ + public List getAllMails(); + + /** + * Adds a home mail address. + * + * @param mail the mail address + */ + public void addHomeMail(String mail); + + /** + * Returns home mail addresses. + * + * @return home mail addresses + */ + public List getHomeMails(); + + /** + * Adds a work mail address. + * + * @param mail the mail address + */ + public void addWorkMails(String mail); + + /** + * Returns work mail addresses. + * + * @return work mail addresses + */ + public List getWorkMails(); + + /** + * Returns telephone numbers. + * + * @return telephone numbers + */ + public List getAllPhones(); + + /** + * Adds a work telephone number. + * + * @param telephoneNumber the work telephone number + */ + public void addWorkPhone(String telephoneNumber); + + /** + * Returns work telephone numbers. + * + * @return work telephone numbers + */ + public List getWorkPhones(); + + /** + * Adds a mobile telephone numbers. + * + * @param telephoneNumber the mobile telephone number + */ + public void addMobilePhone(String telephoneNumber); + + /** + * Returns mobile telephone numbers. + * + * @return mobile telephone numbers + */ + public List getMobilePhones(); + + /** + * Adds a home telephone numbers. + * + * @param telephoneNumber the home telephone number + */ + public void addHomePhone(String telephoneNumber); + + /** + * Returns home telephone numbers. + * + * @return home telephone numbers + */ + public List getHomePhones(); + + /** + * Get the photo full URI. + * + * @return the photo URI or null if there isn't + */ + public String getPhoto(); + + /** + * Returns IM addresses. + * + * @return Map where key is IM address and value is IM protocol (MSN, ...) + */ + public Map getIMAddresses(); + + /** + * Adds an IM address. + * + * @param imAddress IM address + * @param protocol IM protocol + */ + public void addIMAddress(String imAddress, IMProtocol protocol); +} diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsService.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsService.java new file mode 100644 index 000000000..421710bba --- /dev/null +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsService.java @@ -0,0 +1,80 @@ +/* + * 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.service.googlecontacts; + +import java.util.*; + +/** + * Google Contacts service. + * + * @author Sebastien Vincent + */ +public interface GoogleContactsService +{ + /** + * Perform a search for a contact using regular expression. + * + * @param cnx GoogleContactsConnection to perform the query + * @param query Google query + * @param count maximum number of matched contacts + * @param callback object that will be notified for each new + * GoogleContactsEntry found + * @return list of GoogleContactsEntry + */ + public List searchContact(GoogleContactsConnection cnx, + GoogleQuery query, int count, GoogleEntryCallback callback); + + /** + * Get a GoogleContactsConnection. + * + * @param login login to connect to the service + * @param password password to connect to the service + * @return GoogleContactsConnection. + */ + public GoogleContactsConnection getConnection(String login, + String password); + + /** + * Get the full contacts list. + * + * @return list of GoogleContactsEntry + */ + public List getContacts(); + + /** + * Add a contact source service with the specified + * GoogleContactsConnection. + * + * @param login login + * @param password password + */ + public void addContactSource(String login, String password); + + /** + * Add a contact source service with the specified + * GoogleContactsConnection. + * + * @param cnx GoogleContactsConnection. + */ + public void addContactSource(GoogleContactsConnection cnx); + + /** + * Remove a contact source service with the specified + * GoogleContactsConnection. + * + * @param cnx GoogleContactsConnection. + */ + public void removeContactSource(GoogleContactsConnection cnx); + + /** + * Remove a contact source service with the specified + * GoogleContactsConnection. + * + * @param login login + */ + public void removeContactSource(String login); +} diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleEntryCallback.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleEntryCallback.java new file mode 100644 index 000000000..fde0a991d --- /dev/null +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleEntryCallback.java @@ -0,0 +1,23 @@ +/* + * 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.service.googlecontacts; + +/** + * Defines the interface for a callback function which is called by the + * GoogleContactsService when a new GoogleContactsEntry has + * been found during a search. + */ +public interface GoogleEntryCallback +{ + /** + * Notifies this GoogleEntryCallback when a new + * GoogleContactsEntry has been found. + * + * @param entry the GoogleContactsEntry found + */ + void callback(GoogleContactsEntry entry); +} diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleQuery.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleQuery.java new file mode 100644 index 000000000..d8f614893 --- /dev/null +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleQuery.java @@ -0,0 +1,65 @@ +/* + * 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.service.googlecontacts; + +import java.util.regex.*; + +/** + * Describes a Google query. + * + * @author Sebastien Vincent + */ +public class GoogleQuery +{ + /** + * If the query is cancelled. + */ + private boolean cancelled = false; + + /** + * The query pattern. + */ + private Pattern query = null; + + /** + * Constructor. + * + * @param query query string + */ + public GoogleQuery(Pattern query) + { + this.query = query; + } + + /** + * Get the query pattern. + * + * @return query pattern + */ + public Pattern getQueryPattern() + { + return query; + } + + /** + * Cancel the query. + */ + public void cancel() + { + cancelled = true; + } + + /** + * If the query has been cancelled. + * + * @return true If the query has been cancelled, false otherwise + */ + public boolean isCancelled() + { + return cancelled; + } +}