/** * $RCSfile$ * $Revision$ * $Date$ * * Copyright (C) 2002-2003 Jive Software. All rights reserved. * ==================================================================== * The Jive Software License (based on Apache Software License, Version 1.1) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by * Jive Software (http://www.jivesoftware.com)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Smack" and "Jive Software" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact webmaster@jivesoftware.com. * * 5. Products derived from this software may not be called "Smack", * nor may "Smack" appear in their name, without prior written * permission of Jive Software. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== */ package org.jivesoftware.smack.util; import java.beans.PropertyDescriptor; import org.jivesoftware.smack.packet.DefaultPacketExtension; import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.provider.PacketExtensionProvider; import org.jivesoftware.smack.provider.ProviderManager; import org.xmlpull.v1.XmlPullParser; /** * Utility class that helps to parse packets. Any parsing packets method that must be shared * between many clients must be placed in this utility class. * * @author Gaston Dombiak */ public class PacketParserUtils { /** * Parses a packet extension sub-packet. * * @param elementName the XML element name of the packet extension. * @param namespace the XML namespace of the packet extension. * @param parser the XML parser, positioned at the starting element of the extension. * @return a PacketExtension. * @throws Exception if a parsing error occurs. */ public static PacketExtension parsePacketExtension(String elementName, String namespace, XmlPullParser parser) throws Exception { // See if a provider is registered to handle the extension. Object provider = ProviderManager.getExtensionProvider(elementName, namespace); if (provider != null) { if (provider instanceof PacketExtensionProvider) { return ((PacketExtensionProvider)provider).parseExtension(parser); } else if (provider instanceof Class) { return (PacketExtension)parseWithIntrospection( elementName, (Class)provider, parser); } } // No providers registered, so use a default extension. DefaultPacketExtension extension = new DefaultPacketExtension(elementName, namespace); boolean done = false; while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { String name = parser.getName(); // If an empty element, set the value with the empty string. if (parser.isEmptyElementTag()) { extension.setValue(name,""); } // Otherwise, get the the element text. else { eventType = parser.next(); if (eventType == XmlPullParser.TEXT) { String value = parser.getText(); extension.setValue(name, value); } } } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals(elementName)) { done = true; } } } return extension; } public static Object parseWithIntrospection(String elementName, Class objectClass, XmlPullParser parser) throws Exception { boolean done = false; Object object = objectClass.newInstance(); while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { String name = parser.getName(); String stringValue = parser.nextText(); PropertyDescriptor descriptor = new PropertyDescriptor(name, objectClass); // Load the class type of the property. Class propertyType = descriptor.getPropertyType(); // Get the value of the property by converting it from a // String to the correct object type. Object value = decode(propertyType, stringValue); // Set the value of the bean. descriptor.getWriteMethod().invoke(object, new Object[] { value }); } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals(elementName)) { done = true; } } } return object; } /** * Decodes a String into an object of the specified type. If the object * type is not supported, null will be returned. * * @param type the type of the property. * @param value the encode String value to decode. * @return the String value decoded into the specified type. */ private static Object decode(Class type, String value) throws Exception { if (type.getName().equals("java.lang.String")) { return value; } if (type.getName().equals("boolean")) { return Boolean.valueOf(value); } if (type.getName().equals("int")) { return Integer.valueOf(value); } if (type.getName().equals("long")) { return Long.valueOf(value); } if (type.getName().equals("float")) { return Float.valueOf(value); } if (type.getName().equals("double")) { return Double.valueOf(value); } if (type.getName().equals("java.lang.Class")) { return Class.forName(value); } return null; } }