⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 searchplugin.java

📁 openfire 服务器源码下载
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/** * Copyright (C) 2008 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution, or a commercial license * agreement with Jive. */package org.jivesoftware.openfire.plugin;import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.dom4j.QName;import org.jivesoftware.openfire.XMPPServer;import org.jivesoftware.openfire.container.Plugin;import org.jivesoftware.openfire.container.PluginManager;import org.jivesoftware.openfire.disco.IQDiscoInfoHandler;import org.jivesoftware.openfire.disco.IQDiscoItemsHandler;import org.jivesoftware.openfire.forms.DataForm;import org.jivesoftware.openfire.forms.FormField;import org.jivesoftware.openfire.forms.spi.XDataFormImpl;import org.jivesoftware.openfire.forms.spi.XFormFieldImpl;import org.jivesoftware.openfire.resultsetmanager.ResultSet;import org.jivesoftware.openfire.resultsetmanager.ResultSetImpl;import org.jivesoftware.openfire.user.User;import org.jivesoftware.openfire.user.UserManager;import org.jivesoftware.openfire.user.UserNotFoundException;import org.jivesoftware.util.*;import org.xmpp.component.Component;import org.xmpp.component.ComponentException;import org.xmpp.component.ComponentManager;import org.xmpp.component.ComponentManagerFactory;import org.xmpp.packet.IQ;import org.xmpp.packet.IQ.Type;import org.xmpp.packet.JID;import org.xmpp.packet.Packet;import org.xmpp.packet.PacketError;import org.xmpp.packet.PacketError.Condition;import java.io.File;import java.util.*;import java.util.Map.Entry;/** * Provides support for Jabber Search * (<a href="http://www.xmpp.org/extensions/xep-0055.html">XEP-0055</a>).<p> * <p/> * The basic functionality is to query an information repository * regarding the possible search fields, to send a search query, * and to receive search results. This implementation was primarily designed to use * <a href="http://www.xmpp.org/extensions/xep-0004.html">Data Forms</a>, but * also supports non-dataform searches. * <p/> * * @author <a href="mailto:ryan@version2software.com">Ryan Graham</a> */public class SearchPlugin implements Component, Plugin, PropertyEventListener {    public static final String NAMESPACE_JABBER_IQ_SEARCH = "jabber:iq:search";    public static final String SERVICENAME = "plugin.search.serviceName";    public static final String SERVICEENABLED = "plugin.search.serviceEnabled";    public static final String EXCLUDEDFIELDS = "plugin.search.excludedFields";    private UserManager userManager;    private ComponentManager componentManager;    private PluginManager pluginManager;    private String serviceName;    private boolean serviceEnabled;    private Collection<String> exculudedFields;    private static String serverName;    private TreeMap<String, String> fieldLookup = new TreeMap<String, String>(new CaseInsensitiveComparator());    private Map<String, String> reverseFieldLookup = new HashMap<String, String>();    /**     * A list of field names that are valid in jabber:iq:search     */    public final static Collection<String> validSearchRequestFields = new ArrayList<String>();    static {        validSearchRequestFields.add("first");        validSearchRequestFields.add("last");        validSearchRequestFields.add("nick");        validSearchRequestFields.add("email");        validSearchRequestFields.add("x"); // extended info        // result set management (XEP-0059)        validSearchRequestFields.add("set");    }    public SearchPlugin() {        serviceName = JiveGlobals.getProperty(SERVICENAME, "search");        serviceEnabled = JiveGlobals.getBooleanProperty(SERVICEENABLED, true);        exculudedFields = StringUtils.stringToCollection(JiveGlobals.getProperty(EXCLUDEDFIELDS, ""));        serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();        userManager = UserManager.getInstance();        // Some clients, such as Miranda, are hard-coded to search specific fields,        // so we map those fields to the fields that Openfire actually supports.        fieldLookup.put("jid", "Username");        fieldLookup.put("username", "Username");        fieldLookup.put("first", "Name");        fieldLookup.put("last", "Name");        fieldLookup.put("nick", "Name");        fieldLookup.put("name", "Name");        fieldLookup.put("email", "Email");    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#getName()      */    public String getName() {        return pluginManager.getName(this);    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#getDescription()      */    public String getDescription() {        return pluginManager.getDescription(this);    }    /*      * (non-Javadoc)      *      * @see org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfire.container.PluginManager,      *      java.io.File)      */    public void initializePlugin(PluginManager manager, File pluginDirectory) {        pluginManager = manager;        componentManager = ComponentManagerFactory.getComponentManager();        try {            componentManager.addComponent(serviceName, this);        }        catch (ComponentException e) {            componentManager.getLog().error(e);        }        PropertyEventDispatcher.addListener(this);    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#initialize(org.xmpp.packet.JID,      *      org.xmpp.component.ComponentManager)      */    public void initialize(JID jid, ComponentManager componentManager) {    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#start()      */    public void start() {    }    /*      * (non-Javadoc)      *      * @see org.jivesoftware.openfire.container.Plugin#destroyPlugin()      */    public void destroyPlugin() {        PropertyEventDispatcher.removeListener(this);        pluginManager = null;        try {            componentManager.removeComponent(serviceName);            componentManager = null;        }        catch (Exception e) {            if (componentManager != null) {                componentManager.getLog().error(e);            }        }        serviceName = null;        userManager = null;        exculudedFields = null;        serverName = null;        fieldLookup = null;        reverseFieldLookup = null;    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#shutdown()      */    public void shutdown() {    }    /*      * (non-Javadoc)      *      * @see org.xmpp.component.Component#processPacket(org.xmpp.packet.Packet)      */    public void processPacket(Packet p) {        if (!(p instanceof IQ)) {            return;        }        final IQ packet = (IQ) p;        if (packet.getType().equals(IQ.Type.error)                || packet.getType().equals(IQ.Type.result)) {            return;        }        // Packet p is an IQ stanza of type GET or SET. Therefor, it _must_ be        // replied to.        final IQ replyPacket = handleIQRequest(packet);        try {            componentManager.sendPacket(this, replyPacket);        } catch (ComponentException e) {            componentManager.getLog().error(e);        }    }    /**     * Handles IQ requests. This method throws an IllegalArgumentException if an     * IQ stanza is supplied that is not a request (if the stanza is not of type     * 'get' or 'set'). This method will either throw an Exception, or return a     * non-null IQ stanza of type 'error' or 'result', as XMPP Core specifies     * that <strong>all</strong> IQ request stanza's (type 'get' or 'set') MUST     * be replied to.     *     * @param iq The IQ stanza that forms the request.     * @return The response to the request.     */    private IQ handleIQRequest(IQ iq) {        final IQ replyPacket; // 'final' to ensure that it is set.        if (iq == null) {            throw new IllegalArgumentException("Argument 'iq' cannot be null.");        }        final IQ.Type type = iq.getType();        if (type != IQ.Type.get && type != IQ.Type.set) {            throw new IllegalArgumentException(                    "Argument 'iq' must be of type 'get' or 'set'");        }        final Element childElement = iq.getChildElement();        if (childElement == null) {            replyPacket = IQ.createResultIQ(iq);            replyPacket                    .setError(new PacketError(                            Condition.bad_request,                            org.xmpp.packet.PacketError.Type.modify,                            "IQ stanzas of type 'get' and 'set' MUST contain one and only one child element (RFC 3920 section 9.2.3)."));            return replyPacket;        }        final String namespace = childElement.getNamespaceURI();        if (namespace == null) {            replyPacket = IQ.createResultIQ(iq);            replyPacket.setError(Condition.feature_not_implemented);            return replyPacket;        }        if (namespace.equals(NAMESPACE_JABBER_IQ_SEARCH)) {            replyPacket = handleSearchRequest(iq);        } else if (namespace.equals(IQDiscoInfoHandler.NAMESPACE_DISCO_INFO)) {            replyPacket = handleDiscoInfo(iq);        } else if (namespace.equals(IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS)) {            replyPacket = IQ.createResultIQ(iq);            replyPacket.setChildElement("query",                    IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS);        } else {            // don't known what to do with this.            replyPacket = IQ.createResultIQ(iq);            replyPacket.setError(Condition.feature_not_implemented);        }        return replyPacket;    }    /**     * Creates a response specific to the search plugin to Disco#Info requests.     *     * @param iq The IQ stanza that contains the request.     * @return An IQ stanza, formulated as an answer to the received request.     */    private static IQ handleDiscoInfo(IQ iq) {        if (iq == null) {            throw new IllegalArgumentException("Argument 'iq' cannot be null.");        }        if (!iq.getChildElement().getNamespaceURI().equals(                IQDiscoInfoHandler.NAMESPACE_DISCO_INFO)                || iq.getType() != Type.get) {            throw new IllegalArgumentException(                    "This is not a valid disco#info request.");        }        final IQ replyPacket = IQ.createResultIQ(iq);        final Element responseElement = replyPacket.setChildElement("query",                IQDiscoInfoHandler.NAMESPACE_DISCO_INFO);        responseElement.addElement("identity").addAttribute("category",                "directory").addAttribute("type", "user").addAttribute("name",                "User Search");        responseElement.addElement("feature").addAttribute("var",                NAMESPACE_JABBER_IQ_SEARCH);        responseElement.addElement("feature").addAttribute("var",                IQDiscoInfoHandler.NAMESPACE_DISCO_INFO);        responseElement.addElement("feature").addAttribute("var",                ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT);        return replyPacket;    }    private IQ handleSearchRequest(IQ packet) {        if (!serviceEnabled) {            return replyDisabled(packet);        }        switch (packet.getType()) {            case get:                return processGetPacket(packet);            case set:                return processSetPacket(packet);            default:                // we can safely ignore 'error' and 'result' typed iq stanzas.                return null;        }    }    /**     * Constructs a IQ result stanza, based on the request stanza that is     * provided as an argument. The stanza tells the recipient that this service     * is currently unavailable.     *     * @param packet The request IQ stanza to which a result will be returned.     * @return A result stanza, telling the user that this service is     *         unavailable.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -