Xmpp协议有XEP-0055 :Jabber Search协议。不过这个只能单个用户搜索。然而我们的需求是要进行批量搜索,然后返回有效的Jid。为了实现这个功能,需要开发自己的一套iq包。
import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import tigase.db.DBInitException; import tigase.db.NonAuthUserRepository; import tigase.db.RepositoryFactory; import tigase.db.UserRepository; import tigase.server.Iq; import tigase.server.Packet; import tigase.util.TigaseStringprepException; import tigase.xml.Element; import tigase.xmpp.Authorization; import tigase.xmpp.BareJID; import tigase.xmpp.NotAuthorizedException; import tigase.xmpp.PacketErrorTypeException; import tigase.xmpp.StanzaType; import tigase.xmpp.XMPPException; import tigase.xmpp.XMPPPreprocessorIfc; import tigase.xmpp.XMPPProcessor; import tigase.xmpp.XMPPProcessorIfc; import tigase.xmpp.XMPPResourceConnection; import tigase.xmpp.impl.roster.RosterAbstract; public class TalkKingRoster extends XMPPProcessor implements XMPPProcessorIfc, XMPPPreprocessorIfc{ private static Logger log = Logger.getLogger(TalkKingRoster.class.getName()); public static final String ID = "talkKing:" + RosterAbstract.XMLNS; public static final String XMLNS = "talkKing:roster"; private static final String[] XMLNSS = {XMLNS}; private static final String[][] ELEMENTS = {Iq.IQ_QUERY_PATH}; private static final Element[] FEATURES = { new Element("roster", new String[] { "xmlns" }, new String[] { XMLNS }) }; @Override public String id() { // TODO Auto-generated method stub return ID; } @Override public boolean preProcess(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) { // TODO Auto-generated method stub return false; } @Override public void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws XMPPException { // TODO Auto-generated method stub if (log.isLoggable(Level.FINEST)) { log.finest("Processing packet: " + packet.toString()); } if(session==null){ if(log.isLoggable(Level.FINE)){ log.log(Level.FINE,"Session is null, ignoring packet: {0}",packet); return; } } if (packet.getStanzaFrom()!= null && session.isUserId(packet.getStanzaFrom().getBareJID())&& !session.isAuthorized()) { if ( log.isLoggable( Level.FINE ) ){ log.log( Level.FINE, "Session is not authorized, ignoring packet: {0}", packet ); } return; } try { if (!session.isServerSession() && (packet.getStanzaFrom() != null ) && !session.isUserId(packet.getStanzaFrom().getBareJID())) { // RFC says: ignore such request log.log( Level.WARNING, "Roster request ''from'' attribute doesn't match " + "session: {0}, request: {1}", new Object[] { session, packet } ); return; } StanzaType type = packet.getType(); String xmlns = packet.getElement().getXMLNSStaticStr( Iq.IQ_QUERY_PATH ); if (xmlns == XMLNS && type == StanzaType.get){ List<Element> items = packet.getElemChildrenStaticStr(Iq.IQ_QUERY_PATH); if (items!=null) { String uri = System.getProperty( "user-db-uri" ); UserRepository userRepository = RepositoryFactory.getUserRepository( null, uri, null ); String serverDomain = session.getDomainAsJID().getDomain(); Set<BareJID> found = new HashSet<BareJID>(); for (Element item : items) { if (!item.getName().equals("item")) { continue; } BareJID jid = BareJID.bareJIDInstance(item.getAttributeStaticStr("jid")); String domain = jid.getDomain(); BareJID localJid = BareJID.bareJIDInstance(jid.getLocalpart(),serverDomain); boolean isLocalJid = domain.equals(serverDomain); if (isLocalJid) { if (userRepository.userExists(localJid)) { found.add(jid); } } } Element query = new Element(Iq.QUERY_NAME); query.setXMLNS(XMLNS); for (BareJID bareJID : found) { Element item = new Element("item"); item.setAttribute("jid", bareJID.toString()); query.addChild(item); } results.offer(packet.okResult(query, 0)); packet.processedBy(ID); } } } catch (NotAuthorizedException e){ log.log( Level.WARNING, "Received roster request but user session is not authorized yet: {0}", packet ); try { results.offer( Authorization.NOT_AUTHORIZED.getResponseMessage( packet, "You must authorize session first.", true ) ); } catch (PacketErrorTypeException pe) { // ignored } } catch (TigaseStringprepException e) { // TODO Auto-generated catch block } catch (DBInitException e) { // TODO Auto-generated catch block log.log( Level.WARNING, "Database problem, please contact admin:", e ); try { results.offer( Authorization.INTERNAL_SERVER_ERROR.getResponseMessage( packet, "Database access problem, please contact administrator.", true ) ); } catch (PacketErrorTypeException pe) { // ignored } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public Set<StanzaType> supTypes() { return new HashSet<StanzaType>(Arrays.asList(StanzaType.get)); } @Override public String[][] supElementNamePaths() { // TODO Auto-generated method stub return ELEMENTS; } @Override public String[] supNamespaces() { // TODO Auto-generated method stub return XMLNSS; } @Override public Element[] supStreamFeatures(XMPPResourceConnection session) { if (log.isLoggable(Level.FINEST) && (session != null)) { log.finest("VHostItem: " + session.getDomain()); } if (session != null) { return FEATURES; } else { return null; } } }