📄 searchplugin.java
字号:
*/ private static IQ replyDisabled(IQ packet) { IQ replyPacket = IQ.createResultIQ(packet); Element reply = replyPacket.setChildElement("query", NAMESPACE_JABBER_IQ_SEARCH); XDataFormImpl unavailableForm = new XDataFormImpl(DataForm.TYPE_CANCEL); unavailableForm.setTitle(LocaleUtils.getLocalizedString( "advance.user.search.title", "search")); unavailableForm.addInstruction(LocaleUtils.getLocalizedString( "search.service_unavailable", "search")); reply.add(unavailableForm.asXMLElement()); return replyPacket; } /** * Processes an IQ stanza of type 'get', which in the context of 'Jabber * Search' is a request for available search fields. * * @param packet An IQ stanza of type 'get' * @return A result IQ stanza that contains the possbile search fields. */ private IQ processGetPacket(IQ packet) { if (!packet.getType().equals(IQ.Type.get)) { throw new IllegalArgumentException( "This method only accepts 'get' typed IQ stanzas as an argument."); } IQ replyPacket = IQ.createResultIQ(packet); Element queryResult = DocumentHelper.createElement(QName.get("query", NAMESPACE_JABBER_IQ_SEARCH)); String instructions = LocaleUtils.getLocalizedString( "advance.user.search.details", "search"); // non-data form queryResult.addElement("instructions").addText(instructions); queryResult.addElement("first"); queryResult.addElement("last"); queryResult.addElement("nick"); queryResult.addElement("email"); XDataFormImpl searchForm = new XDataFormImpl(DataForm.TYPE_FORM); searchForm.setTitle(LocaleUtils.getLocalizedString( "advance.user.search.title", "search")); searchForm.addInstruction(instructions); XFormFieldImpl field = new XFormFieldImpl("FORM_TYPE"); field.setType(FormField.TYPE_HIDDEN); field.addValue(NAMESPACE_JABBER_IQ_SEARCH); searchForm.addField(field); field = new XFormFieldImpl("search"); field.setType(FormField.TYPE_TEXT_SINGLE); field.setLabel(LocaleUtils.getLocalizedString( "advance.user.search.search", "search")); field.setRequired(true); searchForm.addField(field); for (String searchField : getFilteredSearchFields()) { field = new XFormFieldImpl(searchField); field.setType(FormField.TYPE_BOOLEAN); field.addValue("1"); field.setLabel(LocaleUtils.getLocalizedString( "advance.user.search." + searchField.toLowerCase(), "search")); field.setRequired(false); searchForm.addField(field); } queryResult.add(searchForm.asXMLElement()); replyPacket.setChildElement(queryResult); return replyPacket; } /** * Processes an IQ stanza of type 'set', which in the context of 'Jabber * Search' is a search request. * * @param packet An IQ stanza of type 'get' * @return A result IQ stanza that contains the possbile search fields. */ private IQ processSetPacket(IQ packet) { if (!packet.getType().equals(IQ.Type.set)) { throw new IllegalArgumentException( "This method only accepts 'set' typed IQ stanzas as an argument."); } final IQ resultIQ; // check if the request complies to the XEP-0055 standards if (!isValidSearchRequest(packet)) { resultIQ = IQ.createResultIQ(packet); resultIQ.setError(Condition.bad_request); return resultIQ; } final Element incomingForm = packet.getChildElement(); final boolean isDataFormQuery = (incomingForm.element(QName.get("x", "jabber:x:data")) != null); final Set<User> searchResults = performSearch(incomingForm); final Element rsmElement = incomingForm.element(QName.get("set", ResultSet.NAMESPACE_RESULT_SET_MANAGEMENT)); final boolean applyRSM = rsmElement != null && !searchResults.isEmpty(); if (applyRSM) { // apply RSM final List<User> rsmResults; final ResultSet<User> rs = new ResultSetImpl<User>(searchResults); try { rsmResults = rs.applyRSMDirectives(rsmElement); } catch (NullPointerException e) { final IQ itemNotFound = IQ.createResultIQ(packet); itemNotFound.setError(Condition.item_not_found); return itemNotFound; } if (isDataFormQuery) { resultIQ = replyDataFormResult(rsmResults, packet); } else { resultIQ = replyNonDataFormResult(rsmResults, packet); } // add the additional 'set' element. final Element set = rs.generateSetElementFromResults(rsmResults); resultIQ.getChildElement().add(set); } else { // don't apply RSM if (isDataFormQuery) { resultIQ = replyDataFormResult(searchResults, packet); } else { resultIQ = replyNonDataFormResult(searchResults, packet); } } return resultIQ; } /** * This method checks if the search request that was received is a valid * JABBER:IQ:SEARCH request. In other words, it checks if the search request * is spec compliant (XEP-0055). It does this by checking: * <ul> * <li>if the IQ stanza is of type 'set';</li> * <li>if a child element identified by the jabber:iq:search namespace is * supplied;</li> * <li>if the stanza child element is has valid children itself.</li> * </ul> * * @param iq The IQ object that should include a jabber:iq:search request. * @return ''true'' if the supplied IQ stanza is a spec compliant search * request, ''false'' otherwise. */ public static boolean isValidSearchRequest(IQ iq) { if (iq == null) { throw new IllegalArgumentException("Argument 'iq' cannot be null."); } if (iq.getType() != IQ.Type.set) { return false; } final Element childElement = iq.getChildElement(); if (childElement == null) { return false; } if (!childElement.getNamespaceURI().equals(NAMESPACE_JABBER_IQ_SEARCH)) { return false; } if (!childElement.getName().equals("query")) { return false; } final List<Element> fields = childElement.elements(); if (fields.size() == 0) { return false; } for (Element element : fields) { final String name = element.getName(); if (!validSearchRequestFields.contains(name)) { return false; } // TODO: check dataform validity. // if (name.equals("x") && !isValidDataForm(element)) // { // return false; // } if (name.equals("set") && !ResultSet.isValidRSMRequest(element)) { return false; } } return true; } /** * Performs a search based on form data, and returns the search results. * * @param incomingForm The form containing the search data * @return A set of users that matches the search criteria. */ private Set<User> performSearch(Element incomingForm) { Set<User> users = new HashSet<User>(); Hashtable<String, String> searchList = extractSearchQuery(incomingForm); for (Entry<String, String> entry : searchList.entrySet()) { String field = entry.getKey(); String query = entry.getValue(); Collection<User> foundUsers = new ArrayList<User>(); if (userManager != null) { if (query.length() > 0 && !query.equals(NAMESPACE_JABBER_IQ_SEARCH)) { foundUsers .addAll(userManager.findUsers(new HashSet<String>( Arrays.asList((field))), query)); } } else { foundUsers.addAll(findUsers(field, query)); } // occasionally a null User is returned so filter them out for (User user : foundUsers) { if (user != null) { users.add(user); } } } return users; } /** * This utilty method extracts the search query from the request. A query is * defined as a set of key->value pairs, where the key denotes a search * field, and the value contains the value that was filled out by the user * for that field. * <p/> * The query can be specified in one of two ways. The first way is a query * is formed is by filling out any of the the standard search fields. The * other search method makes use of extended data forms. Search queries that * are supplied to this {@link #extractSearchQuery(Element)} that make use * of this last method get forwarded to * {@link #extractExtendedSearchQuery(Element)}. * * @param incomingForm The form from which to extract the query * @return The search query for a particular user search request. */ private Hashtable<String, String> extractSearchQuery(Element incomingForm) { if (incomingForm.element(QName.get("x", "jabber:x:data")) != null) { // forward the request. return extractExtendedSearchQuery(incomingForm); } final Hashtable<String, String> searchList = new Hashtable<String, String>(); // since not all clients request which fields are available for // searching attempt to match submitted fields with available search // fields Iterator<Element> iter = incomingForm.elementIterator(); while (iter.hasNext()) { Element element = iter.next(); String name = element.getName(); if (fieldLookup.containsKey(name)) { // make best effort to map the fields submitted by // the client to those that Openfire can search reverseFieldLookup.put(fieldLookup.get(name), name); searchList.put(fieldLookup.get(name), element.getText()); } } return searchList; } /** * Extracts a search query from a data form that makes use of data forms to * specify the search request. This 'extended' way of constructing a search * request is documented in XEP-0055, chapter 3. * * @param incomingForm The form from which to extract the query * @return The search query for a particular user search request. * @see #extractSearchQuery(Element) */ private Hashtable<String, String> extractExtendedSearchQuery( Element incomingForm) { final Element dataform = incomingForm.element(QName.get("x", "jabber:x:data")); Hashtable<String, String> searchList = new Hashtable<String, String>(); List<String> searchFields = new ArrayList<String>(); String search = ""; Iterator<Element> fields = dataform.elementIterator("field"); while (fields.hasNext()) { Element searchField = fields.next(); String field = searchField.attributeValue("var"); String value = ""; if (searchField.element("value") != null) { value = searchField.element("value").getTextTrim(); } if (field.equals("search")) { search = value; } else if (value.equals("1")) { searchFields.add(field); } } for (String field : searchFields) { searchList.put(field, search); } return searchList; } /** * Constructs a query that is returned as an IQ packet that contains the search results. * * @param users set of users that will be used to construct the search results * @param packet the IQ packet sent by the client * @return the iq packet that contains the search results */ private IQ replyDataFormResult(Collection<User> users, IQ packet) { XDataFormImpl searchResults = new XDataFormImpl(DataForm.TYPE_RESULT); XFormFieldImpl field = new XFormFieldImpl("FORM_TYPE"); field.setType(FormField.TYPE_HIDDEN); searchResults.addField(field); field = new XFormFieldImpl("jid"); field.setLabel("JID"); searchResults.addReportedField(field); for (String fieldName : getFilteredSearchFields()) { field = new XFormFieldImpl(fieldName); field.setLabel(LocaleUtils.getLocalizedString(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -