• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2003-2007 Jive Software.
3  *
4  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.jivesoftware.smackx.search;
18 
19 import org.jivesoftware.smack.PacketCollector;
20 import org.jivesoftware.smack.SmackConfiguration;
21 import org.jivesoftware.smack.Connection;
22 import org.jivesoftware.smack.XMPPException;
23 import org.jivesoftware.smack.filter.PacketIDFilter;
24 import org.jivesoftware.smack.packet.IQ;
25 import org.jivesoftware.smack.provider.IQProvider;
26 import org.jivesoftware.smack.util.PacketParserUtils;
27 import org.jivesoftware.smackx.Form;
28 import org.jivesoftware.smackx.FormField;
29 import org.jivesoftware.smackx.ReportedData;
30 import org.jivesoftware.smackx.packet.DataForm;
31 import org.xmlpull.v1.XmlPullParser;
32 
33 /**
34  * Implements the protocol currently used to search information repositories on the Jabber network. To date, the jabber:iq:search protocol
35  * has been used mainly to search for people who have registered with user directories (e.g., the "Jabber User Directory" hosted at users.jabber.org).
36  * However, the jabber:iq:search protocol is not limited to user directories, and could be used to search other Jabber information repositories
37  * (such as chatroom directories) or even to provide a Jabber interface to conventional search engines.
38  * <p/>
39  * The basic functionality is to query an information repository regarding the possible search fields, to send a search query, and to receive search results.
40  *
41  * @author Derek DeMoro
42  */
43 public class UserSearch extends IQ {
44 
45     /**
46      * Creates a new instance of UserSearch.
47      */
UserSearch()48     public UserSearch() {
49     }
50 
getChildElementXML()51     public String getChildElementXML() {
52         StringBuilder buf = new StringBuilder();
53         buf.append("<query xmlns=\"jabber:iq:search\">");
54         buf.append(getExtensionsXML());
55         buf.append("</query>");
56         return buf.toString();
57     }
58 
59     /**
60      * Returns the form for all search fields supported by the search service.
61      *
62      * @param con           the current Connection.
63      * @param searchService the search service to use. (ex. search.jivesoftware.com)
64      * @return the search form received by the server.
65      * @throws org.jivesoftware.smack.XMPPException
66      *          thrown if a server error has occurred.
67      */
getSearchForm(Connection con, String searchService)68     public Form getSearchForm(Connection con, String searchService) throws XMPPException {
69         UserSearch search = new UserSearch();
70         search.setType(IQ.Type.GET);
71         search.setTo(searchService);
72 
73         PacketCollector collector = con.createPacketCollector(new PacketIDFilter(search.getPacketID()));
74         con.sendPacket(search);
75 
76         IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
77 
78         // Cancel the collector.
79         collector.cancel();
80         if (response == null) {
81             throw new XMPPException("No response from server on status set.");
82         }
83         if (response.getError() != null) {
84             throw new XMPPException(response.getError());
85         }
86         return Form.getFormFrom(response);
87     }
88 
89     /**
90      * Sends the filled out answer form to be sent and queried by the search service.
91      *
92      * @param con           the current Connection.
93      * @param searchForm    the <code>Form</code> to send for querying.
94      * @param searchService the search service to use. (ex. search.jivesoftware.com)
95      * @return ReportedData the data found from the query.
96      * @throws org.jivesoftware.smack.XMPPException
97      *          thrown if a server error has occurred.
98      */
sendSearchForm(Connection con, Form searchForm, String searchService)99     public ReportedData sendSearchForm(Connection con, Form searchForm, String searchService) throws XMPPException {
100         UserSearch search = new UserSearch();
101         search.setType(IQ.Type.SET);
102         search.setTo(searchService);
103         search.addExtension(searchForm.getDataFormToSend());
104 
105         PacketCollector collector = con.createPacketCollector(new PacketIDFilter(search.getPacketID()));
106 
107         con.sendPacket(search);
108 
109         IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
110 
111         // Cancel the collector.
112         collector.cancel();
113         if (response == null) {
114             throw new XMPPException("No response from server on status set.");
115         }
116         if (response.getError() != null) {
117             return sendSimpleSearchForm(con, searchForm, searchService);
118         }
119 
120 
121         return ReportedData.getReportedDataFrom(response);
122     }
123 
124     /**
125      * Sends the filled out answer form to be sent and queried by the search service.
126      *
127      * @param con           the current Connection.
128      * @param searchForm    the <code>Form</code> to send for querying.
129      * @param searchService the search service to use. (ex. search.jivesoftware.com)
130      * @return ReportedData the data found from the query.
131      * @throws org.jivesoftware.smack.XMPPException
132      *          thrown if a server error has occurred.
133      */
sendSimpleSearchForm(Connection con, Form searchForm, String searchService)134     public ReportedData sendSimpleSearchForm(Connection con, Form searchForm, String searchService) throws XMPPException {
135         SimpleUserSearch search = new SimpleUserSearch();
136         search.setForm(searchForm);
137         search.setType(IQ.Type.SET);
138         search.setTo(searchService);
139 
140         PacketCollector collector = con.createPacketCollector(new PacketIDFilter(search.getPacketID()));
141 
142         con.sendPacket(search);
143 
144         IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
145 
146         // Cancel the collector.
147         collector.cancel();
148         if (response == null) {
149             throw new XMPPException("No response from server on status set.");
150         }
151         if (response.getError() != null) {
152             throw new XMPPException(response.getError());
153         }
154 
155         if (response instanceof SimpleUserSearch) {
156             return ((SimpleUserSearch) response).getReportedData();
157         }
158         return null;
159     }
160 
161     /**
162      * Internal Search service Provider.
163      */
164     public static class Provider implements IQProvider {
165 
166         /**
167          * Provider Constructor.
168          */
Provider()169         public Provider() {
170             super();
171         }
172 
parseIQ(XmlPullParser parser)173         public IQ parseIQ(XmlPullParser parser) throws Exception {
174             UserSearch search = null;
175             SimpleUserSearch simpleUserSearch = new SimpleUserSearch();
176 
177             boolean done = false;
178             while (!done) {
179                 int eventType = parser.next();
180                 if (eventType == XmlPullParser.START_TAG && parser.getName().equals("instructions")) {
181                     buildDataForm(simpleUserSearch, parser.nextText(), parser);
182                     return simpleUserSearch;
183                 }
184                 else if (eventType == XmlPullParser.START_TAG && parser.getName().equals("item")) {
185                     simpleUserSearch.parseItems(parser);
186                     return simpleUserSearch;
187                 }
188                 else if (eventType == XmlPullParser.START_TAG && parser.getNamespace().equals("jabber:x:data")) {
189                     // Otherwise, it must be a packet extension.
190                     search = new UserSearch();
191                     search.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(),
192                             parser.getNamespace(), parser));
193 
194                 }
195                 else if (eventType == XmlPullParser.END_TAG) {
196                     if (parser.getName().equals("query")) {
197                         done = true;
198                     }
199                 }
200             }
201 
202             if (search != null) {
203                 return search;
204             }
205             return simpleUserSearch;
206         }
207     }
208 
buildDataForm(SimpleUserSearch search, String instructions, XmlPullParser parser)209     private static void buildDataForm(SimpleUserSearch search, String instructions, XmlPullParser parser) throws Exception {
210         DataForm dataForm = new DataForm(Form.TYPE_FORM);
211         boolean done = false;
212         dataForm.setTitle("User Search");
213         dataForm.addInstruction(instructions);
214         while (!done) {
215             int eventType = parser.next();
216 
217             if (eventType == XmlPullParser.START_TAG && !parser.getNamespace().equals("jabber:x:data")) {
218                 String name = parser.getName();
219                 FormField field = new FormField(name);
220 
221                 // Handle hard coded values.
222                 if(name.equals("first")){
223                     field.setLabel("First Name");
224                 }
225                 else if(name.equals("last")){
226                     field.setLabel("Last Name");
227                 }
228                 else if(name.equals("email")){
229                     field.setLabel("Email Address");
230                 }
231                 else if(name.equals("nick")){
232                     field.setLabel("Nickname");
233                 }
234 
235                 field.setType(FormField.TYPE_TEXT_SINGLE);
236                 dataForm.addField(field);
237             }
238             else if (eventType == XmlPullParser.END_TAG) {
239                 if (parser.getName().equals("query")) {
240                     done = true;
241                 }
242             }
243             else if (eventType == XmlPullParser.START_TAG && parser.getNamespace().equals("jabber:x:data")) {
244                 search.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(),
245                         parser.getNamespace(), parser));
246                 done = true;
247             }
248         }
249         if (search.getExtension("x", "jabber:x:data") == null) {
250             search.addExtension(dataForm);
251         }
252     }
253 
254 
255 }
256