XmppElementUtil.java
- /**
- *
- * Copyright 2018-2021 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.util;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.logging.Logger;
- import javax.xml.namespace.QName;
- import org.jivesoftware.smack.packet.ExtensionElement;
- import org.jivesoftware.smack.packet.StandardExtensionElement;
- import org.jivesoftware.smack.packet.XmlElement;
- import org.jivesoftware.smack.provider.ProviderManager;
- import org.jxmpp.util.cache.LruCache;
- public class XmppElementUtil {
- private static final LruCache<Class<? extends XmlElement>, QName> CLASS_TO_QNAME_CACHE = new LruCache<>(512);
- public static final Logger LOGGER = Logger.getLogger(XmppElementUtil.class.getName());
- public static QName getQNameFor(Class<? extends XmlElement> fullyQualifiedElement) {
- QName qname = CLASS_TO_QNAME_CACHE.get(fullyQualifiedElement);
- if (qname != null) {
- return qname;
- }
- try {
- Object qnameObject = fullyQualifiedElement.getField("QNAME").get(null);
- if (QName.class.isAssignableFrom(qnameObject.getClass())) {
- qname = (QName) qnameObject;
- CLASS_TO_QNAME_CACHE.put(fullyQualifiedElement, qname);
- return qname;
- }
- LOGGER.warning("The QNAME field of " + fullyQualifiedElement + " is not of type QNAME.");
- } catch (NoSuchFieldException e) {
- LOGGER.finer("The " + fullyQualifiedElement + " has no static QNAME field. Consider adding one.");
- // Proceed to fallback strategy.
- } catch (IllegalArgumentException | IllegalAccessException | SecurityException e) {
- throw new IllegalArgumentException(e);
- }
- String element, namespace;
- try {
- element = (String) fullyQualifiedElement.getField("ELEMENT").get(null);
- namespace = (String) fullyQualifiedElement.getField("NAMESPACE").get(null);
- }
- catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
- throw new IllegalArgumentException("The " + fullyQualifiedElement + " has no ELEMENT, NAMESPACE or QNAME member. Consider adding QNAME", e);
- }
- qname = new QName(namespace, element);
- CLASS_TO_QNAME_CACHE.put(fullyQualifiedElement, qname);
- return qname;
- }
- public static <E extends ExtensionElement> List<E> getElementsFrom(
- MultiMap<QName, XmlElement> elementMap, Class<E> extensionElementClass) {
- QName qname = XmppElementUtil.getQNameFor(extensionElementClass);
- List<XmlElement> extensionElements = elementMap.getAll(qname);
- if (extensionElements.isEmpty()) {
- return Collections.emptyList();
- }
- List<E> res = new ArrayList<>(extensionElements.size());
- for (XmlElement extensionElement : extensionElements) {
- E e = castOrThrow(extensionElement, extensionElementClass);
- res.add(e);
- }
- return res;
- }
- public static <E extends ExtensionElement> E castOrThrow(XmlElement extensionElement, Class<E> extensionElementClass) {
- if (!extensionElementClass.isInstance(extensionElement)) {
- final QName qname = getQNameFor(extensionElementClass);
- final String detailMessage;
- if (extensionElement instanceof StandardExtensionElement) {
- detailMessage = "because there is no according extension element provider registered with ProviderManager for "
- + qname
- + ". WARNING: This indicates a serious problem with your Smack setup, probably causing Smack not being able to properly initialize itself.";
- } else {
- Object provider = ProviderManager.getExtensionProvider(qname);
- detailMessage = "because there is an inconsistency with the provider registered with ProviderManager: the active provider for "
- + qname + " '" + provider.getClass()
- + "' does not return instances of type " + extensionElementClass
- + ", but instead returns instances of type " + extensionElement.getClass() + ".";
- }
- String message = "Extension element is not of expected class '" + extensionElementClass.getName() + "', "
- + detailMessage;
- throw new IllegalStateException(message);
- }
- return extensionElementClass.cast(extensionElement);
- }
- }