mirror of https://github.com/sipwise/jitsi.git
parent
e4627ba7d2
commit
fa49941803
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.jabber;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jivesoftware.smack.*;
|
||||
import org.jivesoftware.smackx.*;
|
||||
import org.jivesoftware.smackx.ReportedData.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* This operation set provides utility methods for user search implementation.
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class OperationSetUserSearchJabberImpl
|
||||
implements OperationSetUserSearch, RegistrationStateChangeListener
|
||||
{
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(OperationSetUserSearchJabberImpl.class);
|
||||
|
||||
/**
|
||||
* The <tt>UserSearchManager</tt> instance which actually implements the
|
||||
* user search.
|
||||
*/
|
||||
private UserSearchManager searchManager = null;
|
||||
|
||||
/**
|
||||
* The <tt>ProtocolProviderService</tt> instance.
|
||||
*/
|
||||
private ProtocolProviderServiceJabberImpl provider;
|
||||
|
||||
/**
|
||||
* The user search service name.
|
||||
*/
|
||||
private String serviceName = null;
|
||||
|
||||
/**
|
||||
* Whether the user search service is enabled or not.
|
||||
*/
|
||||
private Boolean userSearchEnabled = false;
|
||||
|
||||
/**
|
||||
* A list of <tt>UserSearchProviderListener</tt> listeners which will be
|
||||
* notified when the provider user search feature is enabled or disabled.
|
||||
*/
|
||||
private List<UserSearchProviderListener> listeners
|
||||
= new ArrayList<UserSearchProviderListener>();
|
||||
|
||||
/**
|
||||
* The property name of the user search service name.
|
||||
*/
|
||||
private static final String USER_SEARCH_SERVICE_NAME
|
||||
= "USER_SEARCH_SERVICE_NAME";
|
||||
|
||||
/**
|
||||
* Constructs new <tt>OperationSetUserSearchJabberImpl</tt> instance.
|
||||
* @param provider the provider associated with the operation set.
|
||||
*/
|
||||
protected OperationSetUserSearchJabberImpl(
|
||||
ProtocolProviderServiceJabberImpl provider)
|
||||
{
|
||||
this.provider = provider;
|
||||
serviceName = provider.getAccountID().getAccountPropertyString(
|
||||
USER_SEARCH_SERVICE_NAME, "");
|
||||
if(serviceName.equals(""))
|
||||
{
|
||||
provider.addRegistrationStateChangeListener(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
setUserSearchEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <tt>userSearchEnabled</tt> property and fires
|
||||
* <tt>UserSearchProviderEvent</tt> event.
|
||||
*
|
||||
* @param isEnabled the value to be set.
|
||||
*/
|
||||
private void setUserSearchEnabled(boolean isEnabled)
|
||||
{
|
||||
userSearchEnabled = isEnabled;
|
||||
int type = (isEnabled? UserSearchProviderEvent.PROVIDER_ADDED
|
||||
: UserSearchProviderEvent.PROVIDER_REMOVED);
|
||||
fireUserSearchProviderEvent(new UserSearchProviderEvent(provider, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires <tt>UserSearchProviderEvent</tt> event.
|
||||
* @param event the event to be fired.
|
||||
*/
|
||||
private void fireUserSearchProviderEvent(UserSearchProviderEvent event)
|
||||
{
|
||||
List<UserSearchProviderListener> tmpListeners;
|
||||
synchronized (listeners)
|
||||
{
|
||||
tmpListeners = new ArrayList<UserSearchProviderListener>(listeners);
|
||||
}
|
||||
for(UserSearchProviderListener l : tmpListeners)
|
||||
l.onUserSearchProviderEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registrationStateChanged(RegistrationStateChangeEvent evt)
|
||||
{
|
||||
if(evt.getNewState().equals(RegistrationState.REGISTERED))
|
||||
{
|
||||
discoverSearchService();
|
||||
}
|
||||
else if(evt.getNewState() == RegistrationState.UNREGISTERED
|
||||
|| evt.getNewState() == RegistrationState.AUTHENTICATION_FAILED
|
||||
|| evt.getNewState() == RegistrationState.CONNECTION_FAILED)
|
||||
{
|
||||
synchronized (userSearchEnabled)
|
||||
{
|
||||
setUserSearchEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to discover the user search service name.
|
||||
*/
|
||||
private void discoverSearchService()
|
||||
{
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
synchronized (userSearchEnabled)
|
||||
{
|
||||
List<String> serviceNames
|
||||
= UserSearchManager.getAvailableServiceNames(
|
||||
provider);
|
||||
if(!serviceNames.isEmpty())
|
||||
{
|
||||
serviceName = serviceNames.get(0);
|
||||
setUserSearchEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setUserSearchEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the <tt>UserSearchManager</tt> instance.
|
||||
*/
|
||||
public void createSearchManager()
|
||||
{
|
||||
if(searchManager == null)
|
||||
{
|
||||
searchManager
|
||||
= new UserSearchManager(provider.getConnection(), serviceName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the <tt>UserSearchManager</tt> instance.
|
||||
*/
|
||||
public void removeSearchManager()
|
||||
{
|
||||
searchManager = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs user search for the searched string and returns the JIDs of the
|
||||
* found contacts.
|
||||
*
|
||||
* @param searchedString the text we want to query the server.
|
||||
* @return the list of found JIDs
|
||||
*/
|
||||
public List<String> search(String searchedString)
|
||||
{
|
||||
ReportedData data = null;
|
||||
try
|
||||
{
|
||||
data = searchManager.searchForString(searchedString);
|
||||
}
|
||||
catch (XMPPException e)
|
||||
{
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if(data == null)
|
||||
{
|
||||
logger.error("No data have been received from server.");
|
||||
return null;
|
||||
}
|
||||
Iterator<Column> columns = data.getColumns();
|
||||
Iterator<Row> rows = data.getRows();
|
||||
if(columns == null || rows == null)
|
||||
{
|
||||
logger.error("The received data is corrupted.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Column jidColumn = null;
|
||||
while(columns.hasNext())
|
||||
{
|
||||
Column tmpCollumn = columns.next();
|
||||
if(tmpCollumn.getType().equals(FormField.TYPE_JID_SINGLE))
|
||||
{
|
||||
jidColumn = tmpCollumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(jidColumn == null)
|
||||
{
|
||||
logger.error("No jid collumn provided by the server.");
|
||||
return null;
|
||||
}
|
||||
List<String> result = new ArrayList<String>();
|
||||
while(rows.hasNext())
|
||||
{
|
||||
Row row = rows.next();
|
||||
result.add((String)row.getValues(jidColumn.getVariable()).next());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds <tt>UserSearchProviderListener</tt> instance to the list of
|
||||
* listeners.
|
||||
*
|
||||
* @param l the listener to be added
|
||||
*/
|
||||
public void addUserSearchProviderListener(UserSearchProviderListener l)
|
||||
{
|
||||
synchronized (listeners)
|
||||
{
|
||||
if(!listeners.contains(l))
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes <tt>UserSearchProviderListener</tt> instance from the list of
|
||||
* listeners.
|
||||
*
|
||||
* @param l the listener to be removed
|
||||
*/
|
||||
public void removeUserSearchProviderListener(UserSearchProviderListener l)
|
||||
{
|
||||
synchronized (listeners)
|
||||
{
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the user search service is enabled.
|
||||
*
|
||||
* @return <tt>true</tt> if the user search service is enabled.
|
||||
*/
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return userSearchEnabled;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.jabber;
|
||||
|
||||
import net.java.sip.communicator.impl.protocol.jabber.extensions.usersearch.*;
|
||||
|
||||
import org.jivesoftware.smack.*;
|
||||
import org.jivesoftware.smack.filter.*;
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smackx.*;
|
||||
import org.jivesoftware.smackx.packet.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The <tt>UserSearchManager</tt> implements the user search (XEP-0055). It
|
||||
* implements searching a contacts by string.
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class UserSearchManager {
|
||||
/**
|
||||
* The object that represents the connection to the server.
|
||||
*/
|
||||
private Connection con;
|
||||
|
||||
/**
|
||||
* Last received search form from the server.
|
||||
*/
|
||||
private UserSearchIQ userSearchForm = null;
|
||||
|
||||
/**
|
||||
* The user search service name.
|
||||
*/
|
||||
private String searchService;
|
||||
|
||||
/**
|
||||
* Creates a new UserSearchManager.
|
||||
*
|
||||
* @param con the Connection to use.
|
||||
* @param searchService the user search service name.
|
||||
*/
|
||||
public UserSearchManager(Connection con, String searchService) {
|
||||
this.con = con;
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with the available user search service names for a given
|
||||
* provider.
|
||||
* @param provider the provider.
|
||||
* @return a list with the available user search service names for a given
|
||||
* provider.
|
||||
*/
|
||||
public static List<String> getAvailableServiceNames(
|
||||
ProtocolProviderServiceJabberImpl provider)
|
||||
{
|
||||
final List<String> searchServices = new ArrayList<String>();
|
||||
ScServiceDiscoveryManager discoManager = provider.getDiscoveryManager();
|
||||
DiscoverItems items;
|
||||
try
|
||||
{
|
||||
items = discoManager.discoverItems(
|
||||
provider.getConnection().getServiceName());
|
||||
}
|
||||
catch (XMPPException e)
|
||||
{
|
||||
return searchServices;
|
||||
}
|
||||
Iterator<DiscoverItems.Item> iter = items.getItems();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
DiscoverItems.Item item = iter.next();
|
||||
try
|
||||
{
|
||||
DiscoverInfo info;
|
||||
info = discoManager.discoverInfo(item.getEntityID());
|
||||
|
||||
if (info.containsFeature("jabber:iq:search")
|
||||
&& !info.containsFeature("http://jabber.org/protocol/muc"))
|
||||
{
|
||||
searchServices.add(item.getEntityID());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return searchServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the form to fill out to perform a search.
|
||||
*
|
||||
* @return the form to fill out to perform a search.
|
||||
* @throws XMPPException thrown if a server error has occurred.
|
||||
*/
|
||||
private void getSearchForm() throws XMPPException {
|
||||
UserSearchIQ search = new UserSearchIQ();
|
||||
search.setType(IQ.Type.GET);
|
||||
search.setTo(searchService);
|
||||
|
||||
PacketCollector collector = con.createPacketCollector(
|
||||
new PacketIDFilter(search.getPacketID()));
|
||||
con.sendPacket(search);
|
||||
|
||||
IQ response = (IQ) collector.nextResult(
|
||||
SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
userSearchForm = (UserSearchIQ)response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs user search for the searched string.
|
||||
*
|
||||
* @param searchedString
|
||||
* @return the <tt>ReportedData</tt> instance which represents the search
|
||||
* results.
|
||||
* @throws XMPPException thrown if a server error has occurred.
|
||||
*/
|
||||
public ReportedData searchForString(String searchedString) throws XMPPException
|
||||
{
|
||||
if(userSearchForm == null)
|
||||
getSearchForm();
|
||||
UserSearchIQ search = new UserSearchIQ();
|
||||
search.setType(IQ.Type.SET);
|
||||
search.setTo(searchService);
|
||||
|
||||
Form form = userSearchForm.getAnswerForm();
|
||||
if(form != null)
|
||||
{
|
||||
Iterator<FormField> fields = form.getFields();
|
||||
while (fields.hasNext())
|
||||
{
|
||||
FormField formField = fields.next();
|
||||
if(formField.getType().equals(FormField.TYPE_BOOLEAN))
|
||||
{
|
||||
form.setAnswer(formField.getVariable(), true);
|
||||
}
|
||||
else if(formField.getType().equals(FormField.TYPE_TEXT_SINGLE))
|
||||
{
|
||||
form.setAnswer(formField.getVariable(), searchedString);
|
||||
}
|
||||
}
|
||||
search.setForm(form.getDataFormToSend());
|
||||
}
|
||||
else
|
||||
{
|
||||
for(String field : userSearchForm.getFields())
|
||||
search.addField(field, searchedString);
|
||||
}
|
||||
|
||||
PacketCollector collector = con.createPacketCollector(
|
||||
new PacketIDFilter(search.getPacketID()));
|
||||
|
||||
con.sendPacket(search);
|
||||
|
||||
UserSearchIQ response = (UserSearchIQ) collector.nextResult(
|
||||
SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
|
||||
return response.getData();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.jabber.extensions.usersearch;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smack.util.*;
|
||||
import org.jivesoftware.smackx.*;
|
||||
import org.jivesoftware.smackx.packet.*;
|
||||
|
||||
/**
|
||||
* Implements the <tt>IQ</tt> packets for user search (XEP-0055)
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class UserSearchIQ extends IQ {
|
||||
/**
|
||||
* This field represents the result of the search.
|
||||
*/
|
||||
private ReportedData data;
|
||||
|
||||
/**
|
||||
* This map stores the supported fields that are not defined in the data
|
||||
* form and their values.
|
||||
*/
|
||||
private Map<String, String> simpleFieldsNames
|
||||
= new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public String getChildElementXML() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<query xmlns=\"jabber:iq:search\">");
|
||||
if(getExtension("x", "jabber:x:data") != null)
|
||||
{
|
||||
buf.append(getExtensionsXML());
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append(getItemsToSearch());
|
||||
}
|
||||
buf.append("</query>");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <tt>data</tt> property of the class.
|
||||
* @param data the data to be set.
|
||||
*/
|
||||
public void setData(ReportedData data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <tt>data</tt> property of the class.
|
||||
* @return
|
||||
*/
|
||||
public ReportedData getData()
|
||||
{
|
||||
ReportedData data = ReportedData.getReportedDataFrom(this);
|
||||
if(data == null)
|
||||
return this.data;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds filter field to the <tt>IQ</tt> packet and value for the field.
|
||||
* @param field the field name.
|
||||
* @param value the value of the field.
|
||||
*/
|
||||
public void addField(String field, String value)
|
||||
{
|
||||
simpleFieldsNames.put(field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns XML string with the fields that are not included in the data form
|
||||
* @return XML string with the fields that are not included in the data form
|
||||
*/
|
||||
private String getItemsToSearch() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
if (simpleFieldsNames.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
for (String name : simpleFieldsNames.keySet())
|
||||
{
|
||||
String value = simpleFieldsNames.get(name);
|
||||
if (value != null && value.trim().length() > 0) {
|
||||
buf.append("<").append(name).append(">")
|
||||
.append(StringUtils.escapeForXML(value)).append("</")
|
||||
.append(name).append(">");
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the fields that are not included in the data form.
|
||||
* @return the field names.
|
||||
*/
|
||||
public Set<String> getFields()
|
||||
{
|
||||
return simpleFieldsNames.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns answer form.
|
||||
* @return the answer form.
|
||||
*/
|
||||
public Form getAnswerForm()
|
||||
{
|
||||
Form form = Form.getFormFrom(this);
|
||||
if(form == null)
|
||||
return null;
|
||||
return form.createAnswerForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets data form in the <tt>IQ</tt> packet.
|
||||
* @param form the form to be set.
|
||||
*/
|
||||
public void setForm(DataForm form)
|
||||
{
|
||||
addExtension(form);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.jabber.extensions.usersearch;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smack.provider.*;
|
||||
import org.jivesoftware.smack.util.*;
|
||||
import org.jivesoftware.smackx.*;
|
||||
import org.jivesoftware.smackx.ReportedData.*;
|
||||
import org.xmlpull.v1.*;
|
||||
|
||||
/**
|
||||
* Internal Search service Provider. It parses the <tt>UserSeachIQ</tt> packets.
|
||||
*/
|
||||
public class UserSearchProvider implements IQProvider
|
||||
{
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception
|
||||
{
|
||||
UserSearchIQ search = new UserSearchIQ();
|
||||
boolean done = false;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
int eventType = parser.next();
|
||||
if (eventType == XmlPullParser.START_TAG
|
||||
&& parser.getName().equals("item"))
|
||||
{
|
||||
search.setData(parseItems(parser));
|
||||
return search;
|
||||
}
|
||||
else if (eventType == XmlPullParser.START_TAG
|
||||
&& parser.getName().equals("instructions"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (eventType == XmlPullParser.START_TAG
|
||||
&& !parser.getNamespace().equals("jabber:x:data"))
|
||||
{
|
||||
search.addField(parser.getName(), null);
|
||||
|
||||
}
|
||||
else if (eventType == XmlPullParser.START_TAG
|
||||
&& parser.getNamespace().equals("jabber:x:data"))
|
||||
{
|
||||
// Otherwise, it must be a packet extension.
|
||||
search.addExtension(PacketParserUtils.parsePacketExtension(
|
||||
parser.getName(), parser.getNamespace(), parser));
|
||||
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
if (parser.getName().equals("query"))
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the items from the result packet.
|
||||
* @param parser the parser.
|
||||
* @return <tt>ReportedData</tt> instance with the search results.
|
||||
* @throws Exception if parser error occurred.
|
||||
*/
|
||||
protected ReportedData parseItems(XmlPullParser parser) throws Exception
|
||||
{
|
||||
ReportedData data = new ReportedData();
|
||||
data.addColumn(
|
||||
new ReportedData.Column("JID", "jid", FormField.TYPE_JID_SINGLE));
|
||||
|
||||
boolean done = false;
|
||||
|
||||
List<ReportedData.Field> fields
|
||||
= new ArrayList<ReportedData.Field>();
|
||||
|
||||
while (!done)
|
||||
{
|
||||
if (parser.getAttributeCount() > 0)
|
||||
{
|
||||
String jid = parser.getAttributeValue("", "jid");
|
||||
List<String> valueList = new ArrayList<String>();
|
||||
valueList.add(jid);
|
||||
ReportedData.Field field = new ReportedData.Field("jid", valueList);
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
int eventType = parser.next();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG
|
||||
&& parser.getName().equals("item"))
|
||||
{
|
||||
fields = new ArrayList<ReportedData.Field>();
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG
|
||||
&& parser.getName().equals("item"))
|
||||
{
|
||||
ReportedData.Row row = new ReportedData.Row(fields);
|
||||
data.addRow(row);
|
||||
}
|
||||
else if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String name = parser.getName();
|
||||
String value = parser.nextText();
|
||||
|
||||
List<String> valueList = new ArrayList<String>();
|
||||
valueList.add(value);
|
||||
ReportedData.Field field
|
||||
= new ReportedData.Field(name, valueList);
|
||||
fields.add(field);
|
||||
|
||||
boolean exists = false;
|
||||
Iterator<Column> cols = data.getColumns();
|
||||
while (cols.hasNext())
|
||||
{
|
||||
ReportedData.Column column = cols.next();
|
||||
if (column.getVariable().equals(name))
|
||||
exists = true;
|
||||
}
|
||||
|
||||
// Column name should be the same
|
||||
if (!exists)
|
||||
{
|
||||
ReportedData.Column column = new ReportedData.Column(
|
||||
name, name, "text-single");
|
||||
data.addColumn(column);
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
if (parser.getName().equals("query"))
|
||||
done = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license. See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.usersearch;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.jitsi.service.resources.ResourceManagementService;
|
||||
import org.osgi.framework.*;
|
||||
|
||||
/**
|
||||
* Activates the user search plugin which includes the user search contact
|
||||
* source.
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class UserSearchActivator
|
||||
implements BundleActivator
|
||||
{
|
||||
/**
|
||||
* List with the available protocol providers that may support user search.
|
||||
*/
|
||||
private static LinkedList<ProtocolProviderService> userSearchProviders;
|
||||
|
||||
/**
|
||||
* The bundle context.
|
||||
*/
|
||||
public static BundleContext bundleContext;
|
||||
|
||||
/**
|
||||
* A listener for
|
||||
*/
|
||||
private static UserSearchProviderStateListener userSeachListener = null;
|
||||
|
||||
/**
|
||||
* A list with providers that support user search.
|
||||
*/
|
||||
private static LinkedList<ProtocolProviderService> supportedProviders
|
||||
= new LinkedList<ProtocolProviderService>();
|
||||
|
||||
/**
|
||||
* A list of listeners that will be notified about adding and removing
|
||||
* providers that support user search.
|
||||
*/
|
||||
private static LinkedList<UserSearchSupportedProviderListener> listeners
|
||||
= new LinkedList<UserSearchSupportedProviderListener>();
|
||||
|
||||
/**
|
||||
* The <tt>ServiceRegistration</tt> instance for the contact source.
|
||||
*/
|
||||
private static ServiceRegistration contactSourceRegistration = null;
|
||||
|
||||
/**
|
||||
* The <tt>Logger</tt> used by the
|
||||
* <tt>UserSearchActivator</tt> class for logging output.
|
||||
*/
|
||||
private static Logger logger = Logger.getLogger(UserSearchActivator.class);
|
||||
|
||||
/**
|
||||
* Contact source instance.
|
||||
*/
|
||||
private static UserSearchContactSource userSearchContactSource = null;
|
||||
|
||||
/**
|
||||
* The resource service.
|
||||
*/
|
||||
private static ResourceManagementService resources = null;
|
||||
|
||||
/**
|
||||
* Initializes a list of all currently providers and a list with the
|
||||
* providers that support user search.
|
||||
*/
|
||||
public static void initUserSearchProviders()
|
||||
{
|
||||
if (userSearchProviders != null)
|
||||
return;
|
||||
|
||||
userSearchProviders = new LinkedList<ProtocolProviderService>();
|
||||
|
||||
bundleContext.addServiceListener(new ProtocolProviderRegListener());
|
||||
|
||||
ServiceReference[] serRefs = null;
|
||||
try
|
||||
{
|
||||
// get all registered provider factories
|
||||
serRefs
|
||||
= bundleContext.getServiceReferences(
|
||||
ProtocolProviderFactory.class.getName(),
|
||||
null);
|
||||
}
|
||||
catch (InvalidSyntaxException e)
|
||||
{
|
||||
logger.error("LoginManager : " + e);
|
||||
}
|
||||
|
||||
if (serRefs != null)
|
||||
{
|
||||
for (ServiceReference serRef : serRefs)
|
||||
{
|
||||
ProtocolProviderFactory providerFactory
|
||||
= (ProtocolProviderFactory)
|
||||
bundleContext.getService(serRef);
|
||||
|
||||
ProtocolProviderService protocolProvider;
|
||||
|
||||
for (AccountID accountID
|
||||
: providerFactory.getRegisteredAccounts())
|
||||
{
|
||||
serRef = providerFactory.getProviderForAccount(accountID);
|
||||
|
||||
protocolProvider
|
||||
= (ProtocolProviderService) bundleContext
|
||||
.getService(serRef);
|
||||
|
||||
handleProviderAdded(protocolProvider);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of providers that support user search.
|
||||
* @return the list of providers that support user search.
|
||||
*/
|
||||
public static LinkedList<ProtocolProviderService> getSupportedProviders()
|
||||
{
|
||||
return supportedProviders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new <tt>UserSearchSupportedProviderListener</tt> to the list of
|
||||
* listeners.
|
||||
* @param listener the listener to be added.
|
||||
*/
|
||||
public static void addUserSearchSupportedProviderListener(
|
||||
UserSearchSupportedProviderListener listener)
|
||||
{
|
||||
synchronized (listeners)
|
||||
{
|
||||
if(!listeners.contains(listener))
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes <tt>UserSearchSupportedProviderListener</tt> from the list of
|
||||
* listeners.
|
||||
* @param listener the listener to be removed.
|
||||
*/
|
||||
public static void removeUserSearchSupportedProviderListener(
|
||||
UserSearchSupportedProviderListener listener)
|
||||
{
|
||||
synchronized (listeners)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for <tt>ProtocolProviderService</tt> registrations.
|
||||
*/
|
||||
private static class ProtocolProviderRegListener
|
||||
implements ServiceListener
|
||||
{
|
||||
public void serviceChanged(ServiceEvent event)
|
||||
{
|
||||
ServiceReference serviceRef = event.getServiceReference();
|
||||
|
||||
// if the event is caused by a bundle being stopped, we don't want to
|
||||
// know
|
||||
if (serviceRef.getBundle().getState() == Bundle.STOPPING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Object service = bundleContext.getService(serviceRef);
|
||||
|
||||
// we don't care if the source service is not a protocol provider
|
||||
if (!(service instanceof ProtocolProviderService))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getType())
|
||||
{
|
||||
case ServiceEvent.REGISTERED:
|
||||
handleProviderAdded((ProtocolProviderService) service);
|
||||
break;
|
||||
case ServiceEvent.UNREGISTERING:
|
||||
handleProviderRemoved((ProtocolProviderService) service);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the registration of a new <tt>ProtocolProviderService</tt>. Adds
|
||||
* the given <tt>protocolProvider</tt> to the list of queried providers.
|
||||
*
|
||||
* @param protocolProvider the <tt>ProtocolProviderService</tt> to add
|
||||
*/
|
||||
private static void handleProviderAdded(
|
||||
ProtocolProviderService protocolProvider)
|
||||
{
|
||||
if (protocolProvider.getOperationSet(
|
||||
OperationSetServerStoredContactInfo.class) != null
|
||||
&& !userSearchProviders.contains(protocolProvider))
|
||||
{
|
||||
OperationSetUserSearch opSet
|
||||
= protocolProvider.getOperationSet(OperationSetUserSearch.class);
|
||||
if(opSet == null)
|
||||
return;
|
||||
if(userSeachListener == null)
|
||||
userSeachListener = new UserSearchProviderStateListener();
|
||||
opSet.addUserSearchProviderListener(userSeachListener);
|
||||
if(opSet.isEnabled())
|
||||
addSupportedProvider(protocolProvider);
|
||||
userSearchProviders.add(protocolProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the un-registration of a <tt>ProtocolProviderService</tt>.
|
||||
* Removes the given <tt>protocolProvider</tt> from the list of queried
|
||||
* providers.
|
||||
*
|
||||
* @param protocolProvider the <tt>ProtocolProviderService</tt> to remove
|
||||
*/
|
||||
private static void handleProviderRemoved(
|
||||
ProtocolProviderService protocolProvider)
|
||||
{
|
||||
if (userSearchProviders.contains(protocolProvider))
|
||||
{
|
||||
userSearchProviders.remove(protocolProvider);
|
||||
removeSupportedProvider(protocolProvider);
|
||||
if(userSeachListener == null)
|
||||
return;
|
||||
OperationSetUserSearch opSet
|
||||
= protocolProvider.getOperationSet(OperationSetUserSearch.class);
|
||||
if(opSet == null)
|
||||
return;
|
||||
opSet.removeUserSearchProviderListener(userSeachListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds provider to the list of providers that support user search.
|
||||
* @param provider the provider to be added
|
||||
*/
|
||||
private static void addSupportedProvider(ProtocolProviderService provider)
|
||||
{
|
||||
if(!supportedProviders.contains(provider))
|
||||
{
|
||||
supportedProviders.add(provider);
|
||||
LinkedList<UserSearchSupportedProviderListener> tmpListeners;
|
||||
synchronized (listeners)
|
||||
{
|
||||
tmpListeners
|
||||
= new LinkedList<UserSearchSupportedProviderListener>(
|
||||
listeners);
|
||||
}
|
||||
|
||||
for(UserSearchSupportedProviderListener l : tmpListeners)
|
||||
{
|
||||
l.providerAdded(provider);
|
||||
}
|
||||
if(supportedProviders.size() == 1)
|
||||
{
|
||||
if(userSearchContactSource == null)
|
||||
userSearchContactSource = new UserSearchContactSource();
|
||||
//register contact source
|
||||
contactSourceRegistration = bundleContext.registerService(
|
||||
ContactSourceService.class.getName(),
|
||||
userSearchContactSource ,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes provider from the list of providers that support user search.
|
||||
* @param provider the procider to be removed.
|
||||
*/
|
||||
private static void removeSupportedProvider(
|
||||
ProtocolProviderService provider)
|
||||
{
|
||||
if(supportedProviders.contains(provider))
|
||||
{
|
||||
supportedProviders.remove(provider);
|
||||
for(UserSearchSupportedProviderListener l : listeners)
|
||||
{
|
||||
l.providerRemoved(provider);
|
||||
}
|
||||
|
||||
if(supportedProviders.isEmpty()
|
||||
&& contactSourceRegistration != null)
|
||||
{
|
||||
contactSourceRegistration.unregister();
|
||||
contactSourceRegistration = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception
|
||||
{
|
||||
bundleContext = context;
|
||||
|
||||
initUserSearchProviders();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception
|
||||
{
|
||||
userSeachListener = null;
|
||||
userSearchProviders.clear();
|
||||
supportedProviders.clear();
|
||||
listeners.clear();
|
||||
contactSourceRegistration = null;
|
||||
userSearchContactSource = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the ResourceManagementService implementation
|
||||
* currently registered in the bundle context or null if no such
|
||||
* implementation was found.
|
||||
*
|
||||
* @return a reference to a ResourceManagementService implementation
|
||||
* currently registered in the bundle context or null if no such
|
||||
* implementation was found.
|
||||
*/
|
||||
public static ResourceManagementService getResources()
|
||||
{
|
||||
if (resources == null)
|
||||
{
|
||||
resources
|
||||
= ServiceUtils.getService(
|
||||
bundleContext, ResourceManagementService.class);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for added or removed providers that support user search.
|
||||
*/
|
||||
private static class UserSearchProviderStateListener
|
||||
implements UserSearchProviderListener
|
||||
{
|
||||
@Override
|
||||
public void onUserSearchProviderEvent(UserSearchProviderEvent event)
|
||||
{
|
||||
if(event.getType() == UserSearchProviderEvent.PROVIDER_ADDED)
|
||||
{
|
||||
addSupportedProvider(event.getProvider());
|
||||
}
|
||||
else if(event.getType() == UserSearchProviderEvent.PROVIDER_REMOVED)
|
||||
{
|
||||
removeSupportedProvider(event.getProvider());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license. See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.usersearch;
|
||||
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
|
||||
/**
|
||||
* The user search contact source.
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class UserSearchContactSource
|
||||
implements ContactSourceService
|
||||
{
|
||||
|
||||
/**
|
||||
* The time to wait before actually start the searching. If the query is
|
||||
* canceled before the timeout the query won't be started.
|
||||
*/
|
||||
public static final long QUERY_DELAY = 500;
|
||||
|
||||
/**
|
||||
* Returns the type of this contact source.
|
||||
*
|
||||
* @return the type of this contact source
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return SEARCH_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName()
|
||||
{
|
||||
return UserSearchActivator.getResources().getI18NString(
|
||||
"plugin.usersearch.USER_SEARCH");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactQuery createContactQuery(String queryString)
|
||||
{
|
||||
return createContactQuery(queryString, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactQuery createContactQuery(String queryString, int contactCount)
|
||||
{
|
||||
if(queryString == null)
|
||||
queryString = "";
|
||||
|
||||
UserSearchQuery query = new UserSearchQuery(queryString, this);
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.usersearch;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* The <tt>UserSearchQuery</tt> is a query over
|
||||
* <tt>UserSearchContactSource</tt>.
|
||||
*/
|
||||
public class UserSearchQuery
|
||||
extends AsyncContactQuery<ContactSourceService>
|
||||
implements UserSearchSupportedProviderListener
|
||||
{
|
||||
/**
|
||||
* The query string.
|
||||
*/
|
||||
private String queryString;
|
||||
|
||||
/**
|
||||
* A list with the found contacts.
|
||||
*/
|
||||
private List<UserSearchContact> contacts
|
||||
= new LinkedList<UserSearchContact>();
|
||||
|
||||
/**
|
||||
* A list of providers that are already displayed.
|
||||
*/
|
||||
private List<ProtocolProviderService> displayedProviders
|
||||
= new LinkedList<ProtocolProviderService>();
|
||||
|
||||
/**
|
||||
* The number of the listeners added to the query.
|
||||
*/
|
||||
private int contactQueryListenersCount = 0;
|
||||
|
||||
/**
|
||||
* Creates an instance of <tt>ChatRoomQuery</tt> by specifying
|
||||
* the parent contact source, the query string to match and the maximum
|
||||
* result contacts to return.
|
||||
*
|
||||
* @param queryString the query string to match
|
||||
* @param contactSource the parent contact source
|
||||
*/
|
||||
public UserSearchQuery(String queryString,
|
||||
UserSearchContactSource contactSource)
|
||||
{
|
||||
super(contactSource,
|
||||
Pattern.compile(queryString, Pattern.CASE_INSENSITIVE
|
||||
| Pattern.LITERAL), true);
|
||||
this.queryString = queryString;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(UserSearchContactSource.QUERY_DELAY);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{ }
|
||||
if(getStatus() == QUERY_CANCELED)
|
||||
return;
|
||||
|
||||
for(ProtocolProviderService provider :
|
||||
UserSearchActivator.getSupportedProviders())
|
||||
{
|
||||
providerAdded(provider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles provider addition.
|
||||
*
|
||||
* @param provider the provider that was added.
|
||||
*/
|
||||
public void providerAdded(ProtocolProviderService provider)
|
||||
{
|
||||
synchronized (displayedProviders)
|
||||
{
|
||||
if(displayedProviders.contains(provider))
|
||||
return;
|
||||
displayedProviders.add(provider);
|
||||
}
|
||||
|
||||
OperationSetUserSearch opSetUserSearch
|
||||
= provider.getOperationSet(
|
||||
OperationSetUserSearch.class);
|
||||
if(opSetUserSearch == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
opSetUserSearch.createSearchManager();
|
||||
List<String> jidList = opSetUserSearch.search(queryString);
|
||||
if(jidList == null || jidList.isEmpty())
|
||||
return;
|
||||
|
||||
List<Class<? extends OperationSet>> supportedOpSets
|
||||
= new ArrayList<Class<? extends OperationSet>>(1);
|
||||
supportedOpSets.add(OperationSetPersistentPresence.class);
|
||||
|
||||
ContactDetail detail = new ContactDetail(queryString);
|
||||
|
||||
for(String jid : jidList)
|
||||
{
|
||||
List<ContactDetail> contactDetails
|
||||
= new LinkedList<ContactDetail>();
|
||||
|
||||
ContactDetail jidDetail = new ContactDetail(jid);
|
||||
jidDetail.setSupportedOpSets(supportedOpSets);
|
||||
|
||||
contactDetails.add(jidDetail);
|
||||
|
||||
contactDetails.add(detail);
|
||||
|
||||
UserSearchContact contact
|
||||
= new UserSearchContact(
|
||||
this,
|
||||
getContactSource(),
|
||||
jid,
|
||||
contactDetails,
|
||||
provider);
|
||||
contact.setContactAddress(jid);
|
||||
synchronized (contacts)
|
||||
{
|
||||
contacts.add(contact);
|
||||
}
|
||||
|
||||
fireContactReceived(contact);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles provider removal.
|
||||
*
|
||||
* @param provider the provider that was removed.
|
||||
*/
|
||||
public void providerRemoved(ProtocolProviderService provider)
|
||||
{
|
||||
synchronized (displayedProviders)
|
||||
{
|
||||
displayedProviders.remove(provider);
|
||||
}
|
||||
|
||||
OperationSetUserSearch opSetUserSearch
|
||||
= provider.getOperationSet(
|
||||
OperationSetUserSearch.class);
|
||||
if(opSetUserSearch == null)
|
||||
return;
|
||||
opSetUserSearch.removeSearchManager();
|
||||
List<UserSearchContact> tmpContacts;
|
||||
synchronized (contacts)
|
||||
{
|
||||
tmpContacts = new LinkedList<UserSearchContact>(contacts);
|
||||
}
|
||||
for(UserSearchContact contact : tmpContacts)
|
||||
{
|
||||
if(contact.getProvider().equals(provider))
|
||||
{
|
||||
synchronized (contacts)
|
||||
{
|
||||
contacts.remove(contact);
|
||||
}
|
||||
fireContactRemoved(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the resources of the query.
|
||||
*/
|
||||
private void dispose()
|
||||
{
|
||||
UserSearchActivator.removeUserSearchSupportedProviderListener(this);
|
||||
|
||||
synchronized (contacts)
|
||||
{
|
||||
contacts.clear();
|
||||
}
|
||||
|
||||
synchronized (displayedProviders)
|
||||
{
|
||||
displayedProviders.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this <tt>ContactQuery</tt>.
|
||||
*
|
||||
* @see ContactQuery#cancel()
|
||||
*/
|
||||
public void cancel()
|
||||
{
|
||||
dispose();
|
||||
|
||||
super.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* If query has status changed to cancel, let's clear listeners.
|
||||
* @param status {@link ContactQuery#QUERY_CANCELED},
|
||||
* {@link ContactQuery#QUERY_COMPLETED}
|
||||
*/
|
||||
public void setStatus(int status)
|
||||
{
|
||||
if(status == QUERY_CANCELED)
|
||||
dispose();
|
||||
|
||||
super.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContactQueryListener(ContactQueryListener l)
|
||||
{
|
||||
super.addContactQueryListener(l);
|
||||
contactQueryListenersCount++;
|
||||
if(contactQueryListenersCount == 1)
|
||||
{
|
||||
UserSearchActivator.addUserSearchSupportedProviderListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeContactQueryListener(ContactQueryListener l)
|
||||
{
|
||||
super.removeContactQueryListener(l);
|
||||
contactQueryListenersCount--;
|
||||
if(contactQueryListenersCount == 0)
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A specific user search source contact.
|
||||
*/
|
||||
private class UserSearchContact
|
||||
extends SortedGenericSourceContact
|
||||
{
|
||||
/**
|
||||
* The provider associated with the contact.
|
||||
*/
|
||||
private ProtocolProviderService provider;
|
||||
|
||||
public UserSearchContact(ContactQuery parentQuery,
|
||||
ContactSourceService cSourceService, String displayName,
|
||||
List<ContactDetail> contactDetails,
|
||||
ProtocolProviderService provider)
|
||||
{
|
||||
super(parentQuery, cSourceService, displayName, contactDetails);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider associated with the contact.
|
||||
* @return the provider associated with the contact.
|
||||
*/
|
||||
public ProtocolProviderService getProvider()
|
||||
{
|
||||
return provider;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<SourceContact> getQueryResults()
|
||||
{
|
||||
List<SourceContact> queryResults;
|
||||
synchronized (contacts)
|
||||
{
|
||||
queryResults = new LinkedList<SourceContact>(contacts);
|
||||
}
|
||||
return queryResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getQueryResultCount()
|
||||
{
|
||||
synchronized (contacts)
|
||||
{
|
||||
return contacts.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.usersearch;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* A interface for a listener that will be notified when providers that support
|
||||
* user search are added or removed.
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public interface UserSearchSupportedProviderListener
|
||||
{
|
||||
/**
|
||||
* Handles provider addition.
|
||||
*
|
||||
* @param provider the provider that was added.
|
||||
*/
|
||||
public void providerAdded(ProtocolProviderService provider);
|
||||
|
||||
/**
|
||||
* Handles provider removal.
|
||||
*
|
||||
* @param provider the provider that was removed.
|
||||
*/
|
||||
public void providerRemoved(ProtocolProviderService provider);
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
Bundle-Activator: net.java.sip.communicator.plugin.usersearch.UserSearchActivator
|
||||
Bundle-Name: User search contact source
|
||||
Bundle-Description: User search contact source
|
||||
Bundle-Vendor: jitsi.org
|
||||
Bundle-Version: 0.0.1
|
||||
Bundle-SymbolicName: net.java.sip.communicator.plugin.usersearch
|
||||
Import-Package: org.osgi.framework,
|
||||
net.java.sip.communicator.service.contactsource,
|
||||
net.java.sip.communicator.service.protocol,
|
||||
net.java.sip.communicator.service.protocol.event,
|
||||
net.java.sip.communicator.util,
|
||||
org.jitsi.service.resources
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
|
||||
/**
|
||||
* This operation set provides interface for user search service.
|
||||
*
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public interface OperationSetUserSearch
|
||||
extends OperationSet
|
||||
{
|
||||
/**
|
||||
* Creates the search manager.
|
||||
*/
|
||||
public void createSearchManager();
|
||||
|
||||
/**
|
||||
* Removes search manager.
|
||||
*/
|
||||
public void removeSearchManager();
|
||||
|
||||
/**
|
||||
* Performs user search for the searched string and returns the contact
|
||||
* addresses of the found contacts.
|
||||
*
|
||||
* @param searchedString the text we want to query the server.
|
||||
* @return the list of found contact addresses.
|
||||
*/
|
||||
public List<String> search(String searchedString);
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the user search service is enabled.
|
||||
*
|
||||
* @return <tt>true</tt> if the user search service is enabled.
|
||||
*/
|
||||
public boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Adds <tt>UserSearchProviderListener</tt> instance to the list of
|
||||
* listeners.
|
||||
*
|
||||
* @param l the listener to be added
|
||||
*/
|
||||
public void addUserSearchProviderListener(UserSearchProviderListener l);
|
||||
|
||||
/**
|
||||
* Removes <tt>UserSearchProviderListener</tt> instance from the list of
|
||||
* listeners.
|
||||
*
|
||||
* @param l the listener to be removed
|
||||
*/
|
||||
public void removeUserSearchProviderListener(UserSearchProviderListener l);
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.event;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* Notifies <tt>UserSearchProviderListener</tt> that a provider that supports
|
||||
* user search is added or removed.
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public class UserSearchProviderEvent
|
||||
extends EventObject
|
||||
{
|
||||
/**
|
||||
* The serial ID.
|
||||
*/
|
||||
private static final long serialVersionUID = -1285649707213476360L;
|
||||
|
||||
/**
|
||||
* A type that indicates that the provider is added.
|
||||
*/
|
||||
public static int PROVIDER_ADDED = 0;
|
||||
|
||||
/**
|
||||
* A type that indicates that the provider is removed.
|
||||
*/
|
||||
public static int PROVIDER_REMOVED = 1;
|
||||
|
||||
/**
|
||||
* The type of the event.
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
/**
|
||||
* Constructs new <tt>UserSearchProviderEvent</tt> event.
|
||||
* @param provider the provider.
|
||||
* @param type the type of the event.
|
||||
*/
|
||||
public UserSearchProviderEvent(ProtocolProviderService provider, int type)
|
||||
{
|
||||
super(provider);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider associated with the event.
|
||||
* @return the provider associated with the event.
|
||||
*/
|
||||
public ProtocolProviderService getProvider()
|
||||
{
|
||||
return (ProtocolProviderService) getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the event.
|
||||
* @return the type of the event.
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Jitsi, 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.protocol.event;
|
||||
|
||||
/**
|
||||
* An interface for listener that will be notified when provider that supports
|
||||
* user search is added or removed.
|
||||
* @author Hristo Terezov
|
||||
*/
|
||||
public interface UserSearchProviderListener
|
||||
{
|
||||
/**
|
||||
* Notifies the listener with <tt>UserSearchProviderEvent</tt> event.
|
||||
* @param event the event
|
||||
*/
|
||||
public void onUserSearchProviderEvent(UserSearchProviderEvent event);
|
||||
}
|
||||
Loading…
Reference in new issue