1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-29 07:22:07 +01:00

Add (IQ|PacketExtension)IntrospectionProvider

This simplifies code as there is no longer a distinction between
"normal" providers and introspection providers in ProviderManager
necessary.

It's also easier to get an idea where introspection is used for parsing.
This commit is contained in:
Florian Schmaus 2014-12-10 11:06:04 +01:00
parent 00f5008794
commit 77f0fdc156
11 changed files with 284 additions and 212 deletions

View file

@ -17,13 +17,16 @@ There are two types of providers:
* jabber:iq:roster * jabber:iq:roster
* jabber:iq:register There are many more IQ types and extensions that are part of XMPP standards, and of course an endless number that can be added as custom extensions. To support this, an extensible parsing mechanism is provided via Smack and user build providers. * jabber:iq:register There are many more IQ types and extensions that are part of XMPP standards, and of course an endless number that can be added as custom extensions. To support this, an extensible parsing mechanism is provided via Smack and user build providers.
Whenever a packet extension is found in a packet, parsing will be passed to Whenever a packet extension is found in a packet, parsing will be
the correct provider. Each provider can either implement the passed to the correct provider. Each provider must implement the
PacketExtensionProvider interface or be a standard Java Bean. In the former PacketExtensionProvider interface. Each extension provider is
case, each extension provider is responsible for parsing the raw XML stream, responsible for parsing the raw XML stream, via the
via the [XML Pull Parser](http://www.xmlpull.org/), to contruct an object. In [XML Pull Parser](http://www.xmlpull.org/), to contruct an object.
the latter case, bean introspection is used to try to automatically set the
properties of the class using the values in the packet extension sub-element. You can also create an introspection provider
(`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here,
bean introspection is used to try to automatically set the properties
of the class using the values in the packet extension sub-element.
When no extension provider is registered for an element name and namespace When no extension provider is registered for an element name and namespace
combination, Smack will store all top-level elements of the sub-packet in the combination, Smack will store all top-level elements of the sub-packet in the
@ -58,17 +61,17 @@ or
IQ Providers IQ Providers
------------ ------------
The IQ provider class can either implement the IQProvider interface, or extend The IQ provider class must implement the IQProvider interface. Each
the IQ class. In the former case, each IQProvider is responsible for parsing IQProvider is responsible for parsing the raw XML stream to create an
the raw XML stream to create an IQ instance. In the latter case, bean IQ instance.
introspection is used to try to automatically set properties of the IQ
instance using the values found in the IQ packet XML. For example, an XMPP
time packet resembles the following:
### Introspection (DEPRECATED) You can also create an introspection provider
(`provider.IntrospectionProvider.IQIntrospectionProvider`). Which
uses, bean introspection to try to automatically set properties of the
IQ instance using the values found in the IQ packet XML. For example,
an XMPP time packet resembles the following:
*Note*: This feature is deprecated, using introspection for parsing is not recommended. ### Introspection
Instead implement your own provider like shown in the next section.
_Time Packet_ _Time Packet_
@ -111,6 +114,18 @@ _Time IQ Class_
} }
} }
_Time Provider_
```java
public class TimeProvider extends IQIntrospectionProvider<Time> {
public TimeProvider() {
super(Time.class);
}
}
```
The introspection service will automatically try to convert the String value The introspection service will automatically try to convert the String value
from the XML into a boolean, int, long, float, double, or Class depending on from the XML into a boolean, int, long, float, double, or Class depending on
the type the IQ instance expects. the type the IQ instance expects.

View file

@ -38,14 +38,4 @@ public final class ExtensionProviderInfo extends AbstractProviderInfo {
super(elementName, namespace, extProvider); super(elementName, namespace, extProvider);
} }
/**
* Defines an extension provider which is adheres to the JavaBean spec for parsing the extension.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param beanClass The provider bean class.
*/
public ExtensionProviderInfo(String elementName, String namespace, Class<?> beanClass) {
super(elementName, namespace, beanClass);
}
} }

View file

@ -37,15 +37,4 @@ public final class IQProviderInfo extends AbstractProviderInfo {
public IQProviderInfo(String elementName, String namespace, IQProvider<IQ> iqProvider) { public IQProviderInfo(String elementName, String namespace, IQProvider<IQ> iqProvider) {
super(elementName, namespace, iqProvider); super(elementName, namespace, iqProvider);
} }
/**
* Defines an IQ class which can be used as a provider via introspection.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param iqProviderClass The IQ class being parsed.
*/
public IQProviderInfo(String elementName, String namespace, Class<? extends IQ> iqProviderClass) {
super(elementName, namespace, iqProviderClass);
}
} }

View file

@ -0,0 +1,143 @@
/**
*
* Copyright © 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.provider;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.ParserUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class IntrospectionProvider{
// Unfortunately, we have to create two introspection providers, with the exactly the same code here
public static abstract class IQIntrospectionProvider<I extends IQ> extends IQProvider<I> {
private final Class<I> elementClass;
protected IQIntrospectionProvider(Class<I> elementClass) {
this.elementClass = elementClass;
}
@SuppressWarnings("unchecked")
@Override
public I parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException,
SmackException {
try {
return (I) parseWithIntrospection(elementClass, parser, initialDepth);
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException | ClassNotFoundException e) {
throw new SmackException(e);
}
}
}
public static abstract class PacketExtensionIntrospectionProvider<PE extends PacketExtension> extends PacketExtensionProvider<PE> {
private final Class<PE> elementClass;
protected PacketExtensionIntrospectionProvider(Class<PE> elementClass) {
this.elementClass = elementClass;
}
@SuppressWarnings("unchecked")
@Override
public PE parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException,
SmackException {
try {
return (PE) parseWithIntrospection(elementClass, parser, initialDepth);
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException | ClassNotFoundException e) {
throw new SmackException(e);
}
}
}
public static Object parseWithIntrospection(Class<?> objectClass,
XmlPullParser parser, final int initialDepth) throws NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, XmlPullParserException,
IOException, IllegalArgumentException, InvocationTargetException,
ClassNotFoundException {
ParserUtils.assertAtStartTag(parser);
Object object = objectClass.newInstance();
outerloop: while (true) {
int eventType = parser.next();
switch (eventType) {
case XmlPullParser.START_TAG:
String name = parser.getName();
String stringValue = parser.nextText();
Class<?> propertyType = object.getClass().getMethod(
"get" + Character.toUpperCase(name.charAt(0)) + name.substring(1)).getReturnType();
// 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.
object.getClass().getMethod(
"set" + Character.toUpperCase(name.charAt(0)) + name.substring(1),
propertyType).invoke(object, value);
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
}
}
ParserUtils.assertAtEndTag(parser);
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.
* @throws ClassNotFoundException
*/
private static Object decode(Class<?> type, String value) throws ClassNotFoundException {
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;
}
}

View file

@ -85,13 +85,8 @@ public class ProviderFileLoader implements ProviderLoader {
if (IQProvider.class.isAssignableFrom(provider)) { if (IQProvider.class.isAssignableFrom(provider)) {
iqProviders.add(new IQProviderInfo(elementName, namespace, (IQProvider<IQ>) provider.newInstance())); iqProviders.add(new IQProviderInfo(elementName, namespace, (IQProvider<IQ>) provider.newInstance()));
} }
else if (IQ.class.isAssignableFrom(provider)) {
iqProviders.add(new IQProviderInfo(elementName, namespace, (Class<? extends IQ>)provider));
}
else { else {
exceptions.add(new IllegalArgumentException( exceptions.add(new IllegalArgumentException(className + " is not a IQProvider"));
className
+ " is neither IQProvider or IQ class"));
} }
break; break;
case "extensionProvider": case "extensionProvider":
@ -103,13 +98,9 @@ public class ProviderFileLoader implements ProviderLoader {
if (PacketExtensionProvider.class.isAssignableFrom(provider)) { if (PacketExtensionProvider.class.isAssignableFrom(provider)) {
extProviders.add(new ExtensionProviderInfo(elementName, namespace, (PacketExtensionProvider<PacketExtension>) provider.newInstance())); extProviders.add(new ExtensionProviderInfo(elementName, namespace, (PacketExtensionProvider<PacketExtension>) provider.newInstance()));
} }
else if (PacketExtension.class.isAssignableFrom(provider)) {
extProviders.add(new ExtensionProviderInfo(elementName, namespace, provider));
}
else { else {
exceptions.add(new IllegalArgumentException( exceptions.add(new IllegalArgumentException(className
className + " is not a PacketExtensionProvider"));
+ " is neither PacketExtensionProvider or PacketExtension class"));
} }
break; break;
case "streamFeatureProvider": case "streamFeatureProvider":

View file

@ -18,7 +18,6 @@
package org.jivesoftware.smack.provider; package org.jivesoftware.smack.provider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -112,8 +111,6 @@ public final class ProviderManager {
private static final Map<String, PacketExtensionProvider<PacketExtension>> extensionProviders = new ConcurrentHashMap<String, PacketExtensionProvider<PacketExtension>>(); private static final Map<String, PacketExtensionProvider<PacketExtension>> extensionProviders = new ConcurrentHashMap<String, PacketExtensionProvider<PacketExtension>>();
private static final Map<String, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<String, IQProvider<IQ>>(); private static final Map<String, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<String, IQProvider<IQ>>();
private static final Map<String, Class<?>> extensionIntrospectionProviders = new ConcurrentHashMap<String, Class<?>>();
private static final Map<String, Class<?>> iqIntrospectionProviders = new ConcurrentHashMap<String, Class<?>>();
private static final Map<String, PacketExtensionProvider<PacketExtension>> streamFeatureProviders = new ConcurrentHashMap<String, PacketExtensionProvider<PacketExtension>>(); private static final Map<String, PacketExtensionProvider<PacketExtension>> streamFeatureProviders = new ConcurrentHashMap<String, PacketExtensionProvider<PacketExtension>>();
static { static {
@ -171,11 +168,6 @@ public final class ProviderManager {
return iqProviders.get(key); return iqProviders.get(key);
} }
public static Class<?> getIQIntrospectionProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace);
return iqIntrospectionProviders.get(key);
}
/** /**
* Returns an unmodifiable collection of all IQProvider instances. Each object * Returns an unmodifiable collection of all IQProvider instances. Each object
* in the collection will either be an IQProvider instance, or a Class object * in the collection will either be an IQProvider instance, or a Class object
@ -183,11 +175,10 @@ public final class ProviderManager {
* *
* @return all IQProvider instances. * @return all IQProvider instances.
*/ */
public static List<Object> getIQProviders() { public static List<IQProvider<IQ>> getIQProviders() {
List<Object> providers = new ArrayList<Object>(iqProviders.size() + iqIntrospectionProviders.size()); List<IQProvider<IQ>> providers = new ArrayList<>(iqProviders.size());
providers.addAll(iqProviders.values()); providers.addAll(iqProviders.values());
providers.addAll(iqIntrospectionProviders.values()); return providers;
return Collections.unmodifiableList(providers);
} }
/** /**
@ -208,11 +199,8 @@ public final class ProviderManager {
String key = removeIQProvider(elementName, namespace); String key = removeIQProvider(elementName, namespace);
if (provider instanceof IQProvider) { if (provider instanceof IQProvider) {
iqProviders.put(key, (IQProvider<IQ>) provider); iqProviders.put(key, (IQProvider<IQ>) provider);
} else if (provider instanceof Class && IQ.class.isAssignableFrom((Class<?>) provider)) {
iqIntrospectionProviders.put(key, (Class<?>) provider);
} else { } else {
throw new IllegalArgumentException("Provider must be an IQProvider " + throw new IllegalArgumentException("Provider must be an IQProvider");
"or a Class instance sublcassing IQ.");
} }
} }
@ -228,7 +216,6 @@ public final class ProviderManager {
public static String removeIQProvider(String elementName, String namespace) { public static String removeIQProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace); String key = getKey(elementName, namespace);
iqProviders.remove(key); iqProviders.remove(key);
iqIntrospectionProviders.remove(key);
return key; return key;
} }
@ -256,11 +243,6 @@ public final class ProviderManager {
return extensionProviders.get(key); return extensionProviders.get(key);
} }
public static Class<?> getExtensionIntrospectionProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace);
return extensionIntrospectionProviders.get(key);
}
/** /**
* Adds an extension provider with the specified element name and name space. The provider * Adds an extension provider with the specified element name and name space. The provider
* will override any providers loaded through the classpath. The provider must be either * will override any providers loaded through the classpath. The provider must be either
@ -279,11 +261,8 @@ public final class ProviderManager {
String key = removeExtensionProvider(elementName, namespace); String key = removeExtensionProvider(elementName, namespace);
if (provider instanceof PacketExtensionProvider) { if (provider instanceof PacketExtensionProvider) {
extensionProviders.put(key, (PacketExtensionProvider<PacketExtension>) provider); extensionProviders.put(key, (PacketExtensionProvider<PacketExtension>) provider);
} else if (provider instanceof Class && PacketExtension.class.isAssignableFrom((Class<?>) provider)) {
extensionIntrospectionProviders.put(key, (Class<?>) provider);
} else { } else {
throw new IllegalArgumentException("Provider must be a PacketExtensionProvider " + throw new IllegalArgumentException("Provider must be a PacketExtensionProvider");
"or a Class instance.");
} }
} }
@ -299,7 +278,6 @@ public final class ProviderManager {
public static String removeExtensionProvider(String elementName, String namespace) { public static String removeExtensionProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace); String key = getKey(elementName, namespace);
extensionProviders.remove(key); extensionProviders.remove(key);
extensionIntrospectionProviders.remove(key);
return key; return key;
} }
@ -310,11 +288,10 @@ public final class ProviderManager {
* *
* @return all PacketExtensionProvider instances. * @return all PacketExtensionProvider instances.
*/ */
public static List<Object> getExtensionProviders() { public static List<PacketExtensionProvider<PacketExtension>> getExtensionProviders() {
List<Object> providers = new ArrayList<Object>(extensionProviders.size() + extensionIntrospectionProviders.size()); List<PacketExtensionProvider<PacketExtension>> providers = new ArrayList<>(extensionProviders.size());
providers.addAll(extensionProviders.values()); providers.addAll(extensionProviders.values());
providers.addAll(extensionIntrospectionProviders.values()); return providers;
return Collections.unmodifiableList(providers);
} }
public static PacketExtensionProvider<PacketExtension> getStreamFeatureProvider(String elementName, String namespace) { public static PacketExtensionProvider<PacketExtension> getStreamFeatureProvider(String elementName, String namespace) {

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smack.util;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -627,13 +626,6 @@ public class PacketParserUtils {
IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace); IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
if (provider != null) { if (provider != null) {
iqPacket = provider.parse(parser); iqPacket = provider.parse(parser);
} else {
Class<?> introspectionProvider = ProviderManager.getIQIntrospectionProvider(
elementName, namespace);
if (introspectionProvider != null) {
iqPacket = (IQ) PacketParserUtils.parseWithIntrospection(
elementName, introspectionProvider,
parser);
} }
// Only handle unknown IQs of type result. Types of 'get' and 'set' which are not understood // Only handle unknown IQs of type result. Types of 'get' and 'set' which are not understood
// have to be answered with an IQ error response. See the code a few lines below // have to be answered with an IQ error response. See the code a few lines below
@ -644,7 +636,6 @@ public class PacketParserUtils {
// so that the content of the IQ can be examined later on // so that the content of the IQ can be examined later on
iqPacket = new UnparsedResultIQ(elementName, namespace, parseElement(parser)); iqPacket = new UnparsedResultIQ(elementName, namespace, parseElement(parser));
} }
}
break; break;
} }
break; break;
@ -931,18 +922,6 @@ public class PacketParserUtils {
if (provider != null) { if (provider != null) {
return provider.parse(parser); return provider.parse(parser);
} }
Class<?> introspectionProvider = ProviderManager.getExtensionIntrospectionProvider(elementName, namespace);
if (introspectionProvider != null) {
try {
return (PacketExtension)parseWithIntrospection(elementName, introspectionProvider, parser);
} catch (NoSuchMethodException | SecurityException
| InstantiationException | IllegalAccessException
| IllegalArgumentException
| InvocationTargetException
| ClassNotFoundException e) {
throw new SmackException(e);
}
}
final int initialDepth = parser.getDepth(); final int initialDepth = parser.getDepth();
// No providers registered, so use a default extension. // No providers registered, so use a default extension.
@ -1013,37 +992,6 @@ public class PacketParserUtils {
return null; return null;
} }
public static Object parseWithIntrospection(String elementName, Class<?> objectClass,
XmlPullParser parser) throws NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, XmlPullParserException,
IOException, IllegalArgumentException, InvocationTargetException,
ClassNotFoundException {
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();
Class<?> propertyType = object.getClass().getMethod(
"get" + Character.toUpperCase(name.charAt(0)) + name.substring(1)).getReturnType();
// 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.
object.getClass().getMethod(
"set" + Character.toUpperCase(name.charAt(0)) + name.substring(1),
propertyType).invoke(object, value);
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(elementName)) {
done = true;
}
}
}
return object;
}
public static void addPacketExtension(Packet packet, XmlPullParser parser) throws XmlPullParserException, public static void addPacketExtension(Packet packet, XmlPullParser parser) throws XmlPullParserException,
IOException, SmackException { IOException, SmackException {
ParserUtils.assertAtStartTag(parser); ParserUtils.assertAtStartTag(parser);
@ -1067,40 +1015,6 @@ public class PacketParserUtils {
collection.add(packetExtension); collection.add(packetExtension);
} }
/**
* 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.
* @throws ClassNotFoundException
*/
private static Object decode(Class<?> type, String value) throws ClassNotFoundException {
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;
}
/** /**
* This class represents and unparsed IQ of the type 'result'. Usually it's created when no IQProvider * This class represents and unparsed IQ of the type 'result'. Usually it's created when no IQProvider
* was found for the IQ element. * was found for the IQ element.

View file

@ -0,0 +1,28 @@
/**
*
* Copyright © 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.time.provider;
import org.jivesoftware.smack.provider.IntrospectionProvider.IQIntrospectionProvider;
import org.jivesoftware.smackx.time.packet.Time;
public class TimeProvider extends IQIntrospectionProvider<Time> {
public TimeProvider() {
super(Time.class);
}
}

View file

@ -13,7 +13,7 @@
<iqProvider> <iqProvider>
<elementName>time</elementName> <elementName>time</elementName>
<namespace>urn:xmpp:time</namespace> <namespace>urn:xmpp:time</namespace>
<className>org.jivesoftware.smackx.time.packet.Time</className> <className>org.jivesoftware.smackx.time.provider.TimeProvider</className>
</iqProvider> </iqProvider>
<!-- Chat State --> <!-- Chat State -->

View file

@ -17,14 +17,11 @@
package org.jivesoftware.smackx.time.packet; package org.jivesoftware.smackx.time.packet;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.InitExtensions; import org.jivesoftware.smackx.InitExtensions;
import org.junit.Test; import org.junit.Test;
@ -58,37 +55,4 @@ public class TimeTest extends InitExtensions {
assertEquals("+8:30", time.getTzo()); assertEquals("+8:30", time.getTzo());
} }
@Test
public void parseTimeWithIntrospectionTest() throws Exception {
// @formatter:off
final String request =
"<iq type='get'"
+ "from='romeo@montague.net/orchard'"
+ "to='juliet@capulet.com/balcony'"
+ "id='time_1'>"
+ "<time xmlns='urn:xmpp:time'/>"
+ "</iq>";
// @formatter:on
IQ iqRequest = (IQ) PacketParserUtils.parseStanza(request);
assertTrue(iqRequest instanceof Time);
// @formatter:off
final String response =
"<iq type='result'"
+ "from='juliet@capulet.com/balcony'"
+ "to='romeo@montague.net/orchard'"
+ "id='time_1'>"
+ "<time xmlns='urn:xmpp:time'>"
+ "<tzo>-06:00</tzo>"
+ "<utc>2006-12-19T17:58:35Z</utc>"
+ "</time>"
+ "</iq>";
// @formatter:on
IQ iqResponse = (IQ) PacketParserUtils.parseStanza(response);
assertTrue(iqResponse instanceof Time);
Time time = (Time) iqResponse;
assertEquals("-06:00", time.getTzo());
assertEquals("2006-12-19T17:58:35Z", time.getUtc());
}
} }

View file

@ -0,0 +1,61 @@
/**
*
* Copyright 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.time.provider;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.time.packet.Time;
import org.junit.Test;
public class TimeProviderTest {
@Test
public void parseTimeWithIntrospectionTest() throws Exception {
// @formatter:off
final String request =
"<iq type='get'"
+ "from='romeo@montague.net/orchard'"
+ "to='juliet@capulet.com/balcony'"
+ "id='time_1'>"
+ "<time xmlns='urn:xmpp:time'/>"
+ "</iq>";
// @formatter:on
IQ iqRequest = (IQ) PacketParserUtils.parseStanza(request);
assertTrue(iqRequest instanceof Time);
// @formatter:off
final String response =
"<iq type='result'"
+ "from='juliet@capulet.com/balcony'"
+ "to='romeo@montague.net/orchard'"
+ "id='time_1'>"
+ "<time xmlns='urn:xmpp:time'>"
+ "<tzo>-06:00</tzo>"
+ "<utc>2006-12-19T17:58:35Z</utc>"
+ "</time>"
+ "</iq>";
// @formatter:on
IQ iqResponse = (IQ) PacketParserUtils.parseStanza(response);
assertTrue(iqResponse instanceof Time);
Time time = (Time) iqResponse;
assertEquals("-06:00", time.getTzo());
assertEquals("2006-12-19T17:58:35Z", time.getUtc());
}
}