001/**
002 *
003 * Copyright 2019-2024 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.net.MalformedURLException;
024import java.net.URI;
025import java.net.URISyntaxException;
026import java.net.URL;
027import java.text.ParseException;
028
029import org.jivesoftware.smack.packet.Element;
030import org.jivesoftware.smack.parsing.SmackParsingException;
031import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException;
032import org.jivesoftware.smack.xml.XmlPullParserException;
033
034public class AbstractProvider<E extends Element> {
035
036    private final Class<E> elementClass;
037
038    @SuppressWarnings("unchecked")
039    protected AbstractProvider() {
040        Type currentType = getClass().getGenericSuperclass();
041        while (!(currentType instanceof ParameterizedType)) {
042            Class<?> currentClass = (Class<?>) currentType;
043            currentType = currentClass.getGenericSuperclass();
044        }
045        ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType;
046        Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments();
047        Type elementType = actualTypeArguments[0];
048
049
050        if (elementType instanceof Class) {
051            elementClass = (Class<E>) elementType;
052        } else if (elementType instanceof ParameterizedType) {
053            ParameterizedType parameteriezedElementType = (ParameterizedType) elementType;
054            elementClass = (Class<E>) parameteriezedElementType.getRawType();
055        } else if (elementType instanceof TypeVariable) {
056            TypeVariable<?> typeVariableElementType = (TypeVariable<?>) elementType;
057            elementClass = (Class<E>) typeVariableElementType.getClass();
058        } else {
059            throw new AssertionError("Element type '" + elementType + "' (" + elementType.getClass()
060                            + ") is neither of type Class, ParameterizedType or TypeVariable");
061        }
062    }
063
064    public final Class<E> getElementClass() {
065        return elementClass;
066    }
067
068    public static final class TextParseException extends SmackParsingException {
069        /**
070         *
071         */
072        private static final long serialVersionUID = 1L;
073
074        private final ParseException parseException;
075
076        private TextParseException(ParseException parseException) {
077            super(parseException);
078            this.parseException = parseException;
079        }
080
081        public ParseException getParseException() {
082            return parseException;
083        }
084    }
085
086    public static final class NumberFormatParseException extends SmackParsingException {
087        /**
088         *
089         */
090        private static final long serialVersionUID = 1L;
091
092        private NumberFormatParseException(NumberFormatException numberFormatException) {
093            super(numberFormatException);
094        }
095    }
096
097    protected interface WrappableParser<E> {
098        E parse() throws XmlPullParserException, IOException, SmackParsingException, ParseException;
099    }
100
101    protected static <E> E wrapExceptions(WrappableParser<E> parser)
102                    throws XmlPullParserException, IOException, SmackParsingException {
103        E e;
104        try {
105            e = parser.parse();
106        } catch (ParseException parseException) {
107            throw new TextParseException(parseException);
108        } catch (NumberFormatException numberFormatException) {
109            throw new NumberFormatParseException(numberFormatException);
110        }
111
112        return e;
113    }
114
115    public static URL toUrl(String string) throws SmackUriSyntaxParsingException, MalformedURLException {
116        URI uri;
117        try {
118            uri = new URI(string);
119        } catch (URISyntaxException e) {
120            throw new SmackUriSyntaxParsingException(e);
121        }
122        return uri.toURL();
123    }
124}