mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-06-23 20:04:51 +02:00
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.
144 lines
5.7 KiB
Java
144 lines
5.7 KiB
Java
/**
|
|
*
|
|
* 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;
|
|
}
|
|
}
|