diff options
author | Sebastien Vincent <seb@jitsi.org> | 2011-03-22 16:23:01 +0000 |
---|---|---|
committer | Sebastien Vincent <seb@jitsi.org> | 2011-03-22 16:23:01 +0000 |
commit | 76767db08a34b0bdff9217111d680acce62d40dd (patch) | |
tree | dd5e7acd9e437df2e506a5b85c957289712289cb /src/net | |
parent | 260fd209ae9a458309d4825740085e04ed75cf2c (diff) | |
download | jitsi-76767db08a34b0bdff9217111d680acce62d40dd.zip jitsi-76767db08a34b0bdff9217111d680acce62d40dd.tar.gz jitsi-76767db08a34b0bdff9217111d680acce62d40dd.tar.bz2 |
Initial support for Google Contacts as contact source.
Diffstat (limited to 'src/net')
27 files changed, 3699 insertions, 8 deletions
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 0000000..31475dd --- /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 <tt>Logger</tt> used by the <tt>GoogleContactsActivator</tt> class + * and its instances for logging output. + */ + private final Logger logger = Logger.getLogger( + GoogleContactsActivator.class); + + /** + * The OSGi <tt>ServiceRegistration</tt> of + * <tt>GoogleContactsServiceImpl</tt>. + */ + 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 <tt>PhoneNumberI18nService</tt> instance used + * by the functionality of the Google Contacts plug-in and fetched from its + * <tt>BundleContext</tt>. + */ + private static PhoneNumberI18nService phoneNumberI18nService; + + /** + * Google contacts service. + */ + private static GoogleContactsServiceImpl googleContactsService; + + /** + * List of contact source service registrations. + */ + private static Map<GoogleContactsSourceService, ServiceRegistration> cssList + = new HashMap<GoogleContactsSourceService, ServiceRegistration>(); + + /** + * Gets the <tt>PhoneNumberI18nService</tt> to be used by the functionality + * of the addrbook plug-in. + * + * @return the <tt>PhoneNumberI18nService</tt> 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<String, String> properties = + new Hashtable<String, String>(); + 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<GoogleContactsSourceService, ServiceRegistration> 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 + * <tt>GoogleContactsConnection</tt>. + * + * @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 + * <tt>GoogleContactsConnection</tt>. + * + * @param cnx <tt>GoogleContactsConnection</tt> + */ + 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 + * <tt>GoogleContactsConnection</tt>. + * + * @param login login + */ + public static void disableContactSource(String login) + { + GoogleContactsSourceService found = null; + + for(Map.Entry<GoogleContactsSourceService, ServiceRegistration> 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 + * <tt>GoogleContactsConnection</tt>. + * + * @param cnx <tt>GoogleContactsConnection</tt>. + */ + public static void disableContactSource(GoogleContactsConnection cnx) + { + GoogleContactsSourceService found = null; + + for(Map.Entry<GoogleContactsSourceService, ServiceRegistration> 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 0000000..592c6ba --- /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 0000000..1b4f739 --- /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<String> homeMails = new ArrayList<String>(); + + /** + * Work mails list. + */ + private final List<String> workMails = new ArrayList<String>(); + + /** + * Home phones list. + */ + private final List<String> homePhones = new ArrayList<String>(); + + /** + * Work phones list. + */ + private final List<String> workPhones = new ArrayList<String>(); + + /** + * Mobile phones list. + */ + private final List<String> mobilePhones = new ArrayList<String>(); + + /** + * IM addresses map. + */ + private final Map<String, IMProtocol> imAddresses = + new HashMap<String, IMProtocol>(); + + /** + * 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<String> getAllMails() + { + List<String> mails = new ArrayList<String>(); + + 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<String> 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<String> getWorkMails() + { + return workMails; + } + + /** + * Returns telephone numbers. + * + * @return telephone numbers + */ + public List<String> getAllPhones() + { + List<String> phones = new ArrayList<String>(); + + 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<String> 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<String> 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<String> 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<String, IMProtocol> 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 <tt>ContactEntry</tt> + */ + 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 <tt>GoogleContactsEntry</tt>. + */ + @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<String, IMProtocol> 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 0000000..decfe5e --- /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 <tt>ContactQuery</tt> for Google Contacts. + * + * @author Sebastien Vincent + */ +public class GoogleContactsQuery + extends AsyncContactQuery<GoogleContactsSourceService> +{ + /** + * 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 <tt>GoogleContactsQuery</tt> instance which is to + * perform a specific <tt>query</tt> on behalf of a specific + * <tt>contactSource</tt>. + * + * @param contactSource the <tt>ContactSourceService</tt> which is to + * perform the new <tt>ContactQuery</tt> instance + * @param query the <tt>Pattern</tt> for which <tt>contactSource</tt> 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 <tt>String</tt> phone number by converting alpha characters + * to their respective digits on a keypad and then stripping non-digit + * characters. + * + * @param phoneNumber a <tt>String</tt> which represents a phone number to + * normalize + * @return a <tt>String</tt> which is a normalized form of the specified + * <tt>phoneNumber</tt> + */ + protected String normalizePhoneNumber(String phoneNumber) + { + PhoneNumberI18nService phoneNumberI18nService + = GoogleContactsActivator.getPhoneNumberI18nService(); + + return + (phoneNumberI18nService == null) + ? phoneNumber + : phoneNumberI18nService.normalize(phoneNumber); + } + + /** + * Determines whether a specific <tt>String</tt> phone number matches the + * {@link #query} of this <tt>AsyncContactQuery</tt>. + * + * @param phoneNumber the <tt>String</tt> which represents the phone number + * to match to the <tt>query</tt> of this <tt>AsyncContactQuery</tt> + * @return <tt>true</tt> if the specified <tt>phoneNumber</tt> matches the + * <tt>query</tt> of this <tt>AsyncContactQuery</tt>; otherwise, + * <tt>false</tt> + */ + 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 <tt>SourceContact</tt> from a <tt>GoogleContactsEntry</tt>. + * + * @param entry <tt>GoogleContactsEntry</tt> + */ + 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<ContactDetail> 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 <tt>AsyncContactQuery</tt> in a background <tt>Thread</tt>. + * + * @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 <tt>contactDetails</tt> to be set on a <tt>SourceContact</tt>. + * + * @param entry <tt>GoogleContactsEntry</tt> + * @return the <tt>contactDetails</tt> to be set on a <tt>SourceContact</tt> + */ + private List<ContactDetail> getContactDetails(GoogleContactsEntry entry) + { + List<ContactDetail> ret = new LinkedList<ContactDetail>(); + List<String> homeMails = entry.getHomeMails(); + List<String> workMails = entry.getWorkMails(); + List<String> mobilePhones = entry.getMobilePhones(); + List<String> homePhones = entry.getHomePhones(); + List<String> workPhones = entry.getWorkPhones(); + Map<String, GoogleContactsEntry.IMProtocol> 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<Class<? extends OperationSet>> supportedOpSets + = new ArrayList<Class<? extends OperationSet>>(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<Class<? extends OperationSet>> supportedOpSets + = new ArrayList<Class<? extends OperationSet>>(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<Class<? extends OperationSet>> supportedOpSets + = new ArrayList<Class<? extends OperationSet>>(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<String, GoogleContactsEntry.IMProtocol> 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 <tt>ContactDetail</tt> (e.g. + * <tt>supportedOpSets</tt>). + * + * @param contactDetail the <tt>ContactDetail</tt> to set the capabilities + * of + * @param protocol protocol + * @return <tt>contactDetail</tt> + */ + private ContactDetail setIMCapabilities( + ContactDetail contactDetail, + GoogleContactsEntry.IMProtocol protocol) + { + List<Class<? extends OperationSet>> supportedOpSets + = new LinkedList<Class<? extends OperationSet>>(); + Map<Class<? extends OperationSet>, String> preferredProtocols + = new HashMap<Class<? extends OperationSet>, 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 <tt>GoogleContactsQuery</tt> that it has stopped performing + * in the associated background <tt>Thread</tt>. + * + * @param completed <tt>true</tt> if this <tt>ContactQuery</tt> has + * successfully completed, <tt>false</tt> 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 <tt>ContactQuery</tt>. + * + * @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 0000000..77efe3c --- /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<GoogleContactsConnectionImpl> accounts = + new ArrayList<GoogleContactsConnectionImpl>(); + + /** + * 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<GoogleContactsConnectionImpl> getAccounts() + { + return accounts; + } + + /** + * Loads configuration. + */ + private void loadConfig() + { + ConfigurationService configService = + GoogleContactsActivator.getConfigService(); + CredentialsStorageService credentialsService = + GoogleContactsActivator.getCredentialsService(); + + List<String> 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 <tt>GoogleContactsConnection</tt> 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 + * <tt>GoogleContactsEntry</tt> found + * @return list of <tt>GoogleContactsEntry</tt> + */ + public List<GoogleContactsEntry> searchContact( + GoogleContactsConnection cnx, GoogleQuery gQuery, int count, + GoogleEntryCallback callback) + { + URL url = null; + ContactFeed contactFeed = null; + ContactQuery query = null; + List<GoogleContactsEntry> ret = new ArrayList<GoogleContactsEntry>(); + 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 <tt>filter</tt>. + * + * @param entry <tt>ContactEntry</tt> + * @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 <tt>GoogleContactsEntry</tt> from a <tt>ContactEntry</tt> + * + * @param entry <tt>ContactEntry</tt> + * @return <tt>GoogleContactsEntry</tt> + */ + private GoogleContactsEntry getGoogleContactsEntry(ContactEntry entry) + { + GoogleContactsEntryImpl ret = new GoogleContactsEntryImpl(); + + ret.setField(entry); + return ret; + } + + /** + * Get the full contacts list. + * + * @return list of <tt>GoogleContactsEntry</tt> + */ + public List<GoogleContactsEntry> getContacts() + { + return null; + } + + /** + * Get a <tt>GoogleContactsConnection</tt>. + * + * @param login login to connect to the service + * @param password password to connect to the service + * @return <tt>GoogleContactsConnection</tt>. + */ + 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. + * + * <tt>GoogleContactsConnection</tt>. + * @param cnx <tt>GoogleContactsConnection</tt>. + */ + public void addContactSource(GoogleContactsConnection cnx) + { + GoogleContactsActivator.enableContactSource(cnx); + } + + /** + * Add a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @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. + * + * <tt>GoogleContactsConnection</tt>. + * @param cnx <tt>GoogleContactsConnection</tt>. + */ + public void removeContactSource(GoogleContactsConnection cnx) + { + GoogleContactsActivator.disableContactSource(cnx); + } + + /** + * Remove a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @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 0000000..d36c78f --- /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 <tt>ContactSourceService</tt> for Google Contacts. + * + * @author Sebastien Vincent + */ +public class GoogleContactsSourceService + implements ExtendedContactSourceService +{ + /** + * Logger. + */ + private static final Logger logger = + Logger.getLogger(GoogleContactsSourceService.class); + + /** + * The <tt>List</tt> of <tt>GoogleContactsQuery</tt> instances + * which have been started and haven't stopped yet. + */ + private final List<GoogleContactsQuery> queries + = new LinkedList<GoogleContactsQuery>(); + + /** + * 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 <tt>searchPattern</tt>. + * + * @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 <tt>searchPattern</tt>. + * + * @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 <tt>queryString</tt>. + * @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 <tt>queryString</tt>. + * + * @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 <tt>ContactSourceService</tt> implementation and prepares it + * for garbage collection. + * + * @see AsyncContactSourceService#stop() + */ + public void stop() + { + boolean interrupted = false; + + synchronized (queries) + { + while (!queries.isEmpty()) + { + queries.get(0).cancel(); + try + { + queries.wait(); + } + catch (InterruptedException iex) + { + interrupted = true; + } + } + } + if (interrupted) + Thread.currentThread().interrupt(); + } + + /** + * Notifies this <tt>GoogleContactsSourceService</tt> that a specific + * <tt>GoogleContactsQuery</tt> has stopped. + * + * @param query the <tt>GoogleContactsQuery</tt> 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 0000000..8cc961a --- /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 <tt>true</tt> if this dialog has been closed by pressing + * the Esc key; otherwise, <tt>false</tt> + */ + 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 0000000..60ad270 --- /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. + * <p> + * 0 is the first position + * -1 means that the form will be put at the end + * </p> + * @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 <tt>true</tt> if this is an advanced configuration form, + * otherwise it returns <tt>false</tt> + */ + 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 0000000..bc51bbc --- /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<GoogleContactsConnectionImpl> 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 0000000..2e01fc4 --- /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 <tt>Resources</tt> 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 0000000..04c9fba --- /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 12428a0..d3b4355 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 class LdapActivator * 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 class LdapActivator /** * 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 9cb4c1e..71bf547 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 class MediaServiceImpl return null; } - + /** * Get origin for desktop streaming device. * @@ -1130,7 +1130,7 @@ public class MediaServiceImpl 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 552c8be..c40c1ce 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.netaddr.*; 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 <tt>PacketLoggingService</tt> + * instance. + */ + private static PacketLoggingService packetLoggingService = null; + + /** + * A reference to the currently valid <tt>GoogleContactsService</tt> + * instance. + */ + private static GoogleContactsService googleService = null; /** * Called when this bundle is started so the Framework can perform the @@ -323,4 +335,24 @@ public class JabberActivator } 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 adf88e0..ab74f5e 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 class ProtocolProviderFactoryJabberImpl 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 7cd11b2..7521866 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.jingle.*; 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 @@ public class ProtocolProviderServiceJabberImpl } catch (Exception e) {} - connectionListener = null; connection = null; // make it null as it also holds a reference to the old connection @@ -1258,6 +1258,9 @@ public class ProtocolProviderServiceJabberImpl OperationSetGenericNotifications.class, new OperationSetGenericNotificationsJabberImpl(this)); + /* add Google Contacts as contact source if enabled */ + registerGoogleContactsSource(); + isInitialized = true; } } @@ -1274,6 +1277,8 @@ public class ProtocolProviderServiceJabberImpl if (logger.isTraceEnabled()) logger.trace("Killing the Jabber Protocol Provider."); + unregisterGoogleContactsSource(); + //kill all active calls OperationSetBasicTelephonyJabberImpl telephony = (OperationSetBasicTelephonyJabberImpl)getOperationSet( @@ -1898,6 +1903,56 @@ public class ProtocolProviderServiceJabberImpl } /** + * 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 <tt>Throwable</tt> cause as an * error using the current <tt>Logger</tt> and then throws a new * <tt>OperationFailedException</tt> with the message, a specific error code 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 47839ae..730b671 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 6ba3414..bbbd93a 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 javax.swing.event.*; 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 class ConnectionPanel = 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); @@ -257,6 +267,28 @@ public class ConnectionPanel } /** + * Returns <tt>true</tt> if the "Google contacts" check box is selected, + * otherwise returns <tt>false</tt>. + * @return <tt>true</tt> if the "Google contacts" check box is selected, + * otherwise returns <tt>false</tt> + */ + boolean isGoogleContactsEnabled() + { + return googleContactsBox.isSelected(); + } + + /** + * Selects/unselects the "Google contacts" check box according to the + * given <tt>isEnabled</tt> 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 */ private void setNextButtonAccordingToPortAndPriority() diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/FirstWizardPage.java index 69a96c4..7c71148 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 f3b5489..7606f69 100755 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistration.java @@ -89,6 +89,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. */ private boolean isUseIce = false; @@ -233,6 +238,18 @@ public class JabberAccountRegistration } /** + * Determines whether SIP Communicator should use Google Contacts as + * ContactSource + * + * @return <tt>true</tt> if we are to enable Google Contacts and + * <tt>false</tt> otherwise. + */ + public boolean isGoogleContactsEnabled() + { + return enableGoogleContacts; + } + + /** * Sets the User ID of the jabber registration account. * * @param userID the identifier of the jabber registration account. @@ -317,6 +334,18 @@ public class JabberAccountRegistration } /** + * Specifies whether SIP Communicator should use Google Contacts as + * ContactSource. + * + * @param enabled <tt>true</tt> if we are to enable Google Contacts and + * <tt>false</tt> 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 dfdb7ed..70acc2d 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 @@ import net.java.sip.communicator.util.swing.*; 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 @@ public class JabberAccountRegistrationForm } /** - * 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 @@ public class JabberAccountRegistrationForm /** * Indicates if this wizard is modifying an existing account or is creating * a new one. - * + * * @return <code>true</code> to indicate that this wizard is currently in * modification mode, <code>false</code> - otherwise. */ @@ -193,6 +198,8 @@ public class JabberAccountRegistrationForm 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 class JabberAccountRegistrationForm 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 5b3b10c..ee46655 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 @@ public class JabberAccountRegistrationWizard 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 0000000..9d0ee38 --- /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 0000000..fd1fba7 --- /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<String> 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<String> 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<String> getWorkMails(); + + /** + * Returns telephone numbers. + * + * @return telephone numbers + */ + public List<String> 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<String> 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<String> 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<String> 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<String, IMProtocol> 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 0000000..421710b --- /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 <tt>GoogleContactsConnection</tt> 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 + * <tt>GoogleContactsEntry</tt> found + * @return list of <tt>GoogleContactsEntry</tt> + */ + public List<GoogleContactsEntry> searchContact(GoogleContactsConnection cnx, + GoogleQuery query, int count, GoogleEntryCallback callback); + + /** + * Get a <tt>GoogleContactsConnection</tt>. + * + * @param login login to connect to the service + * @param password password to connect to the service + * @return <tt>GoogleContactsConnection</tt>. + */ + public GoogleContactsConnection getConnection(String login, + String password); + + /** + * Get the full contacts list. + * + * @return list of <tt>GoogleContactsEntry</tt> + */ + public List<GoogleContactsEntry> getContacts(); + + /** + * Add a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @param login login + * @param password password + */ + public void addContactSource(String login, String password); + + /** + * Add a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @param cnx <tt>GoogleContactsConnection</tt>. + */ + public void addContactSource(GoogleContactsConnection cnx); + + /** + * Remove a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @param cnx <tt>GoogleContactsConnection</tt>. + */ + public void removeContactSource(GoogleContactsConnection cnx); + + /** + * Remove a contact source service with the specified + * <tt>GoogleContactsConnection</tt>. + * + * @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 0000000..fde0a99 --- /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 + * <tt>GoogleContactsService</tt> when a new <tt>GoogleContactsEntry</tt> has + * been found during a search. + */ +public interface GoogleEntryCallback +{ + /** + * Notifies this <tt>GoogleEntryCallback</tt> when a new + * <tt>GoogleContactsEntry</tt> has been found. + * + * @param entry the <tt>GoogleContactsEntry</tt> 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 0000000..d8f6148 --- /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; + } +} |