KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > smack > util > PacketParserUtils


1 /**
2  * $RCSfile$
3  * $Revision: 2518 $
4  * $Date: 2005-08-02 23:42:53 -0300 (Tue, 02 Aug 2005) $
5  *
6  * Copyright 2003-2004 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */

20
21 package org.jivesoftware.smack.util;
22
23 import java.beans.PropertyDescriptor JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.io.ObjectInputStream JavaDoc;
28 import java.io.ByteArrayInputStream JavaDoc;
29
30 import org.jivesoftware.smack.packet.*;
31 import org.jivesoftware.smack.provider.PacketExtensionProvider;
32 import org.jivesoftware.smack.provider.ProviderManager;
33 import org.xmlpull.v1.XmlPullParser;
34 import org.xmlpull.v1.XmlPullParserException;
35
36 /**
37  * Utility class that helps to parse packets. Any parsing packets method that must be shared
38  * between many clients must be placed in this utility class.
39  *
40  * @author Gaston Dombiak
41  */

42 public class PacketParserUtils {
43
44     /**
45      * Namespace used to store packet properties.
46      */

47     private static final String JavaDoc PROPERTIES_NAMESPACE =
48             "http://www.jivesoftware.com/xmlns/xmpp/properties";
49
50     /**
51      * Parses a message packet.
52      *
53      * @param parser the XML parser, positioned at the start of a message packet.
54      * @return a Message packet.
55      * @throws Exception if an exception occurs while parsing the packet.
56      */

57     public static Packet parseMessage(XmlPullParser parser) throws Exception JavaDoc {
58         Message message = new Message();
59         String JavaDoc id = parser.getAttributeValue("", "id");
60         message.setPacketID(id == null ? Packet.ID_NOT_AVAILABLE : id);
61         message.setTo(parser.getAttributeValue("", "to"));
62         message.setFrom(parser.getAttributeValue("", "from"));
63         message.setType(Message.Type.fromString(parser.getAttributeValue("", "type")));
64
65         // Parse sub-elements. We include extra logic to make sure the values
66
// are only read once. This is because it's possible for the names to appear
67
// in arbitrary sub-elements.
68
boolean done = false;
69         String JavaDoc subject = null;
70         String JavaDoc body = null;
71         String JavaDoc thread = null;
72         Map JavaDoc properties = null;
73         while (!done) {
74             int eventType = parser.next();
75             if (eventType == XmlPullParser.START_TAG) {
76                 String JavaDoc elementName = parser.getName();
77                 String JavaDoc namespace = parser.getNamespace();
78                 if (elementName.equals("subject")) {
79                     if (subject == null) {
80                         subject = parser.nextText();
81                     }
82                 }
83                 else if (elementName.equals("body")) {
84                     if (body == null) {
85                         body = parser.nextText();
86                     }
87                 }
88                 else if (elementName.equals("thread")) {
89                     if (thread == null) {
90                         thread = parser.nextText();
91                     }
92                 }
93                 else if (elementName.equals("error")) {
94                     message.setError(parseError(parser));
95                 }
96                 else if (elementName.equals("properties") &&
97                         namespace.equals(PROPERTIES_NAMESPACE))
98                 {
99                     properties = parseProperties(parser);
100                 }
101                 // Otherwise, it must be a packet extension.
102
else {
103                     message.addExtension(
104                     PacketParserUtils.parsePacketExtension(elementName, namespace, parser));
105                 }
106             }
107             else if (eventType == XmlPullParser.END_TAG) {
108                 if (parser.getName().equals("message")) {
109                     done = true;
110                 }
111             }
112         }
113         message.setSubject(subject);
114         message.setBody(body);
115         message.setThread(thread);
116         // Set packet properties.
117
if (properties != null) {
118             for (Iterator JavaDoc i=properties.keySet().iterator(); i.hasNext(); ) {
119                 String JavaDoc name = (String JavaDoc)i.next();
120                 message.setProperty(name, properties.get(name));
121             }
122         }
123         return message;
124     }
125
126     /**
127      * Parses a presence packet.
128      *
129      * @param parser the XML parser, positioned at the start of a presence packet.
130      * @return a Presence packet.
131      * @throws Exception if an exception occurs while parsing the packet.
132      */

133     public static Presence parsePresence(XmlPullParser parser) throws Exception JavaDoc {
134         Presence.Type type = Presence.Type.fromString(parser.getAttributeValue("", "type"));
135
136         Presence presence = new Presence(type);
137         presence.setTo(parser.getAttributeValue("", "to"));
138         presence.setFrom(parser.getAttributeValue("", "from"));
139         String JavaDoc id = parser.getAttributeValue("", "id");
140         presence.setPacketID(id == null ? Packet.ID_NOT_AVAILABLE : id);
141
142         // Parse sub-elements
143
boolean done = false;
144         while (!done) {
145             int eventType = parser.next();
146             if (eventType == XmlPullParser.START_TAG) {
147                 String JavaDoc elementName = parser.getName();
148                 String JavaDoc namespace = parser.getNamespace();
149                 if (elementName.equals("status")) {
150                     presence.setStatus(parser.nextText());
151                 }
152                 else if (elementName.equals("priority")) {
153                     try {
154                         int priority = Integer.parseInt(parser.nextText());
155                         presence.setPriority(priority);
156                     }
157                     catch (NumberFormatException JavaDoc nfe) { }
158                     catch (IllegalArgumentException JavaDoc iae) {
159                         // Presence priority is out of range so assume priority to be zero
160
presence.setPriority(0);
161                     }
162                 }
163                 else if (elementName.equals("show")) {
164                     presence.setMode(Presence.Mode.fromString(parser.nextText()));
165                 }
166                 else if (elementName.equals("error")) {
167                     presence.setError(parseError(parser));
168                 }
169                 else if (elementName.equals("properties") &&
170                         namespace.equals(PROPERTIES_NAMESPACE))
171                 {
172                     Map JavaDoc properties = parseProperties(parser);
173                     // Set packet properties.
174
for (Iterator JavaDoc i=properties.keySet().iterator(); i.hasNext(); ) {
175                         String JavaDoc name = (String JavaDoc)i.next();
176                         presence.setProperty(name, properties.get(name));
177                     }
178                 }
179                 // Otherwise, it must be a packet extension.
180
else {
181                     presence.addExtension(
182                         PacketParserUtils.parsePacketExtension(elementName, namespace, parser));
183                 }
184             }
185             else if (eventType == XmlPullParser.END_TAG) {
186                 if (parser.getName().equals("presence")) {
187                     done = true;
188                 }
189             }
190         }
191         return presence;
192     }
193
194     /**
195      * Parse a properties sub-packet. If any errors occur while de-serializing Java object
196      * properties, an exception will be printed and not thrown since a thrown
197      * exception will shut down the entire connection. ClassCastExceptions will occur
198      * when both the sender and receiver of the packet don't have identical versions
199      * of the same class.
200      *
201      * @param parser the XML parser, positioned at the start of a properties sub-packet.
202      * @return a map of the properties.
203      * @throws Exception if an error occurs while parsing the properties.
204      */

205     public static Map JavaDoc parseProperties(XmlPullParser parser) throws Exception JavaDoc {
206         Map JavaDoc properties = new HashMap JavaDoc();
207         while (true) {
208             int eventType = parser.next();
209             if (eventType == XmlPullParser.START_TAG && parser.getName().equals("property")) {
210                 // Parse a property
211
boolean done = false;
212                 String JavaDoc name = null;
213                 String JavaDoc type = null;
214                 String JavaDoc valueText = null;
215                 Object JavaDoc value = null;
216                 while (!done) {
217                     eventType = parser.next();
218                     if (eventType == XmlPullParser.START_TAG) {
219                         String JavaDoc elementName = parser.getName();
220                         if (elementName.equals("name")) {
221                             name = parser.nextText();
222                         }
223                         else if (elementName.equals("value")) {
224                             type = parser.getAttributeValue("", "type");
225                             valueText = parser.nextText();
226                         }
227                     }
228                     else if (eventType == XmlPullParser.END_TAG) {
229                         if (parser.getName().equals("property")) {
230                             if ("integer".equals(type)) {
231                                 value = new Integer JavaDoc(valueText);
232                             }
233                             else if ("long".equals(type)) {
234                                 value = new Long JavaDoc(valueText);
235                             }
236                             else if ("float".equals(type)) {
237                                 value = new Float JavaDoc(valueText);
238                             }
239                             else if ("double".equals(type)) {
240                                 value = new Double JavaDoc(valueText);
241                             }
242                             else if ("boolean".equals(type)) {
243                                 value = new Boolean JavaDoc(valueText);
244                             }
245                             else if ("string".equals(type)) {
246                                 value = valueText;
247                             }
248                             else if ("java-object".equals(type)) {
249                                 try {
250                                     byte [] bytes = StringUtils.decodeBase64(valueText);
251                                     ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(bytes));
252                                     value = in.readObject();
253                                 }
254                                 catch (Exception JavaDoc e) {
255                                     e.printStackTrace();
256                                 }
257                             }
258                             if (name != null && value != null) {
259                                 properties.put(name, value);
260                             }
261                             done = true;
262                         }
263                     }
264                 }
265             }
266             else if (eventType == XmlPullParser.END_TAG) {
267                 if (parser.getName().equals("properties")) {
268                     break;
269                 }
270             }
271         }
272         return properties;
273     }
274
275     /**
276      * Parses error sub-packets.
277      *
278      * @param parser the XML parser.
279      * @return an error sub-packet.
280      * @throws Exception if an exception occurs while parsing the packet.
281      */

282     public static XMPPError parseError(XmlPullParser parser) throws Exception JavaDoc {
283         String JavaDoc errorCode = "-1";
284         String JavaDoc message = null;
285         for (int i=0; i<parser.getAttributeCount(); i++) {
286             if (parser.getAttributeName(i).equals("code")) {
287                 errorCode = parser.getAttributeValue("", "code");
288             }
289         }
290         // Get the error text in a safe way since we are not sure about the error message format
291
try {
292             message = parser.nextText();
293         }
294         catch (XmlPullParserException ex) {}
295         while (true) {
296             if (parser.getEventType() == XmlPullParser.END_TAG && parser.getName().equals("error")) {
297                 break;
298             }
299             parser.next();
300         }
301         return new XMPPError(Integer.parseInt(errorCode), message);
302     }
303
304     /**
305      * Parses a packet extension sub-packet.
306      *
307      * @param elementName the XML element name of the packet extension.
308      * @param namespace the XML namespace of the packet extension.
309      * @param parser the XML parser, positioned at the starting element of the extension.
310      * @return a PacketExtension.
311      * @throws Exception if a parsing error occurs.
312      */

313     public static PacketExtension parsePacketExtension(String JavaDoc elementName, String JavaDoc namespace, XmlPullParser parser)
314             throws Exception JavaDoc
315     {
316         // See if a provider is registered to handle the extension.
317
Object JavaDoc provider = ProviderManager.getExtensionProvider(elementName, namespace);
318         if (provider != null) {
319             if (provider instanceof PacketExtensionProvider) {
320                 return ((PacketExtensionProvider)provider).parseExtension(parser);
321             }
322             else if (provider instanceof Class JavaDoc) {
323                 return (PacketExtension)parseWithIntrospection(
324                         elementName, (Class JavaDoc)provider, parser);
325             }
326         }
327         // No providers registered, so use a default extension.
328
DefaultPacketExtension extension = new DefaultPacketExtension(elementName, namespace);
329         boolean done = false;
330         while (!done) {
331             int eventType = parser.next();
332             if (eventType == XmlPullParser.START_TAG) {
333                 String JavaDoc name = parser.getName();
334                 // If an empty element, set the value with the empty string.
335
if (parser.isEmptyElementTag()) {
336                     extension.setValue(name,"");
337                 }
338                 // Otherwise, get the the element text.
339
else {
340                     eventType = parser.next();
341                     if (eventType == XmlPullParser.TEXT) {
342                         String JavaDoc value = parser.getText();
343                         extension.setValue(name, value);
344                     }
345                 }
346             }
347             else if (eventType == XmlPullParser.END_TAG) {
348                 if (parser.getName().equals(elementName)) {
349                     done = true;
350                 }
351             }
352         }
353         return extension;
354     }
355
356     public static Object JavaDoc parseWithIntrospection(String JavaDoc elementName,
357             Class JavaDoc objectClass, XmlPullParser parser) throws Exception JavaDoc
358     {
359         boolean done = false;
360         Object JavaDoc object = objectClass.newInstance();
361         while (!done) {
362             int eventType = parser.next();
363             if (eventType == XmlPullParser.START_TAG) {
364                 String JavaDoc name = parser.getName();
365                 String JavaDoc stringValue = parser.nextText();
366                 PropertyDescriptor JavaDoc descriptor = new PropertyDescriptor JavaDoc(name, objectClass);
367                 // Load the class type of the property.
368
Class JavaDoc propertyType = descriptor.getPropertyType();
369                 // Get the value of the property by converting it from a
370
// String to the correct object type.
371
Object JavaDoc value = decode(propertyType, stringValue);
372                 // Set the value of the bean.
373
descriptor.getWriteMethod().invoke(object, new Object JavaDoc[] { value });
374             }
375             else if (eventType == XmlPullParser.END_TAG) {
376                 if (parser.getName().equals(elementName)) {
377                     done = true;
378                 }
379             }
380         }
381         return object;
382     }
383
384     /**
385      * Decodes a String into an object of the specified type. If the object
386      * type is not supported, null will be returned.
387      *
388      * @param type the type of the property.
389      * @param value the encode String value to decode.
390      * @return the String value decoded into the specified type.
391      */

392     private static Object JavaDoc decode(Class JavaDoc type, String JavaDoc value) throws Exception JavaDoc {
393         if (type.getName().equals("java.lang.String")) {
394             return value;
395         }
396         if (type.getName().equals("boolean")) {
397             return Boolean.valueOf(value);
398         }
399         if (type.getName().equals("int")) {
400             return Integer.valueOf(value);
401         }
402         if (type.getName().equals("long")) {
403             return Long.valueOf(value);
404         }
405         if (type.getName().equals("float")) {
406             return Float.valueOf(value);
407         }
408         if (type.getName().equals("double")) {
409             return Double.valueOf(value);
410         }
411         if (type.getName().equals("java.lang.Class")) {
412             return Class.forName(value);
413         }
414         return null;
415     }
416
417 }
418
Popular Tags