001/** 002 * 003 * Copyright 2019-2021 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.provider; 018 019import java.io.IOException; 020import java.lang.reflect.ParameterizedType; 021import java.lang.reflect.Type; 022import java.lang.reflect.TypeVariable; 023import java.text.ParseException; 024 025import org.jivesoftware.smack.packet.Element; 026import org.jivesoftware.smack.parsing.SmackParsingException; 027import org.jivesoftware.smack.xml.XmlPullParserException; 028 029public class AbstractProvider<E extends Element> { 030 031 private final Class<E> elementClass; 032 033 @SuppressWarnings("unchecked") 034 protected AbstractProvider() { 035 Type currentType = getClass().getGenericSuperclass(); 036 while (!(currentType instanceof ParameterizedType)) { 037 Class<?> currentClass = (Class<?>) currentType; 038 currentType = currentClass.getGenericSuperclass(); 039 } 040 ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType; 041 Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments(); 042 Type elementType = actualTypeArguments[0]; 043 044 045 if (elementType instanceof Class) { 046 elementClass = (Class<E>) elementType; 047 } else if (elementType instanceof ParameterizedType) { 048 ParameterizedType parameteriezedElementType = (ParameterizedType) elementType; 049 elementClass = (Class<E>) parameteriezedElementType.getRawType(); 050 } else if (elementType instanceof TypeVariable) { 051 TypeVariable<?> typeVariableElementType = (TypeVariable<?>) elementType; 052 elementClass = (Class<E>) typeVariableElementType.getClass(); 053 } else { 054 throw new AssertionError("Element type '" + elementType + "' (" + elementType.getClass() 055 + ") is neither of type Class, ParameterizedType or TypeVariable"); 056 } 057 } 058 059 public final Class<E> getElementClass() { 060 return elementClass; 061 } 062 063 public static final class TextParseException extends SmackParsingException { 064 /** 065 * 066 */ 067 private static final long serialVersionUID = 1L; 068 069 private final ParseException parseException; 070 071 private TextParseException(ParseException parseException) { 072 super(parseException); 073 this.parseException = parseException; 074 } 075 076 public ParseException getParseException() { 077 return parseException; 078 } 079 } 080 081 public static final class NumberFormatParseException extends SmackParsingException { 082 /** 083 * 084 */ 085 private static final long serialVersionUID = 1L; 086 087 private NumberFormatParseException(NumberFormatException numberFormatException) { 088 super(numberFormatException); 089 } 090 } 091 092 protected interface WrappableParser<E> { 093 E parse() throws XmlPullParserException, IOException, SmackParsingException, ParseException; 094 } 095 096 protected static <E> E wrapExceptions(WrappableParser<E> parser) 097 throws XmlPullParserException, IOException, SmackParsingException { 098 E e; 099 try { 100 e = parser.parse(); 101 } catch (ParseException parseException) { 102 throw new TextParseException(parseException); 103 } catch (NumberFormatException numberFormatException) { 104 throw new NumberFormatParseException(numberFormatException); 105 } 106 107 return e; 108 } 109}