/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.googlecontacts; import java.util.*; import java.util.regex.*; import net.java.sip.communicator.impl.googlecontacts.configform.*; 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, PrefixedContactSourceService { /** * 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; /** * The prefix for all google contact phone numbers. */ private String phoneNumberprefix; /** * Google Contacts connection. */ private GoogleContactsConnection cnx = null; /** * The account settings form. */ private AccountSettingsForm settings = null; /** * If the account has been created using GoogleTalk wizard or via * external Google Contacts. */ private boolean googleTalk = false; /** * Constructor. * * @param login login * @param password password */ public GoogleContactsSourceService(String login) { super(); this.login = login; } /** * Constructor. * * @param cnx connection */ public GoogleContactsSourceService(GoogleContactsConnection cnx) { super(); this.cnx = cnx; this.login = cnx.getLogin(); this.phoneNumberprefix = cnx.getPrefix(); } /** * Returns login. * * @return login */ public String getLogin() { return login; } /** * Set whether or not the account has been created via GoogleTalk wizard or * external Google contacts. * * @param googleTalk value to set */ public void setGoogleTalk(boolean googleTalk) { this.googleTalk = googleTalk; } /** * Returns whether or not the account has been created via GoogleTalk * wizard or via external Google Contacts. * * @return true if account has been created via GoogleTalk wizard or via * external Google Contacts. */ public boolean isGoogleTalk() { return googleTalk; } /** * Creates query for the given <tt>searchPattern</tt>. * * @param queryPattern the pattern to search for * @return the created query */ public ContactQuery createContactQuery(Pattern queryPattern) { return createContactQuery(queryPattern, GoogleContactsQuery.GOOGLECONTACTS_MAX_RESULTS); } /** * Creates query 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 createContactQuery(Pattern queryPattern, int count) { GoogleContactsQuery query = new GoogleContactsQuery(this, queryPattern, count); synchronized (queries) { queries.add(query); } return query; } /** * Removes query from the list of queries. * * @param query the query that will be removed. */ public synchronized void removeQuery(ContactQuery query) { if (queries.remove(query)) queries.notify(); } /** * 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) { // To detect that account is a google ones, we try following: // - lookup in SRV and see if it is google.com; // - if the account has been created with GoogleTalk form; // - if it is an "external" google contact. // SRV checks for(SRVRecord srv : srvRecords) { if(srv.getTarget().endsWith("google.com") || srv.getTarget().endsWith("google.com.")) { isGoogleAppsOrGmail = true; break; } } } // GoogleTalk based account or external Google Contacts ? if(!isGoogleAppsOrGmail) { isGoogleAppsOrGmail = googleTalk; } if(isGoogleAppsOrGmail) { if(cnx == null) { cnx = new GoogleContactsConnectionImpl(login); if(cnx.connect() == GoogleContactsConnection.ConnectionStatus. ERROR_INVALID_CREDENTIALS) { synchronized(this) { if(settings != null) { cnx = null; return null; } else { settings = new AccountSettingsForm(); } } settings.setModal(true); settings.loadData(cnx); int ret = settings.showDialog(); if(ret == 1) { cnx = settings.getConnection(); GoogleContactsActivator.getGoogleContactsService(). saveConfig(cnx); } else { cnx = null; } } } else if(cnx.connect() == GoogleContactsConnection.ConnectionStatus. ERROR_INVALID_CREDENTIALS) { synchronized(this) { if(settings != null) { cnx = null; return null; } else { settings = new AccountSettingsForm(); } } settings.setModal(true); settings.loadData(cnx); int ret = settings.showDialog(); if(ret == 1) { cnx = settings.getConnection(); GoogleContactsActivator.getGoogleContactsService(). saveConfig(cnx); } else { cnx = null; } } } 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 SEARCH_TYPE to indicate that this contact source * * @return the identifier of this contact source */ public int getType() { return SEARCH_TYPE; } /** * Queries this search source for the given <tt>queryString</tt>. * @param query the string to search for * @return the created query */ public ContactQuery createContactQuery(String query) { return createContactQuery( query, GoogleContactsQuery.GOOGLECONTACTS_MAX_RESULTS); } /** *Creates query 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 createContactQuery(String query, int contactCount) { Pattern pattern = null; try { pattern = Pattern.compile(query); } catch (PatternSyntaxException pse) { pattern = Pattern.compile( Pattern.quote(query)); } if(pattern != null) { return createContactQuery(pattern, contactCount); } return null; } /** * 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(); } } /** * Returns the phoneNumber prefix for all phone numbers. * * @return the phoneNumber prefix for all phone numbers */ @Override public String getPhoneNumberPrefix() { return phoneNumberprefix; } /** * Sets the phone number prefix. * * @param phoneNumberprefix the phone number prefix to set */ public void setPhoneNumberPrefix(String phoneNumberprefix) { this.phoneNumberprefix = phoneNumberprefix; } /** * Returns the index of the contact source in the result list. * * @return the index of the contact source in the result list */ public int getIndex() { return -1; } }