001package co.codewizards.cloudstore.core.dto;
002
003import java.lang.reflect.Constructor;
004import java.lang.reflect.InvocationTargetException;
005
006public final class RemoteExceptionUtil {
007
008        private RemoteExceptionUtil() { }
009
010        public static void throwOriginalExceptionIfPossible(final Error error) {
011                Class<?> clazz;
012                try {
013                        clazz = Class.forName(error.getClassName());
014                } catch (final ClassNotFoundException e) {
015                        return;
016                }
017                if (!Throwable.class.isAssignableFrom(clazz))
018                        return;
019
020                @SuppressWarnings("unchecked")
021                final Class<? extends Throwable> clasz = (Class<? extends Throwable>) clazz;
022
023                final RemoteException cause = new RemoteException(error);
024
025                Throwable throwable = null;
026
027                // trying XyzException(String message, Throwable cause)
028                if (throwable == null)
029                        throwable = getObjectOrNull(clasz, new Class<?>[] { String.class, Throwable.class }, error.getMessage(), cause);
030
031                // trying XyzException(String message)
032                if (throwable == null)
033                        throwable = getObjectOrNull(clasz, new Class<?>[] { String.class }, error.getMessage());
034
035                // trying XyzException(Throwable cause)
036                if (throwable == null)
037                        throwable = getObjectOrNull(clasz, new Class<?>[] { Throwable.class }, cause);
038
039                // trying XyzException()
040                if (throwable == null)
041                        throwable = getObjectOrNull(clasz, null);
042
043                if (throwable != null) {
044                        try {
045                                throwable.initCause(cause);
046                        } catch (final Exception x) {
047                                // This happens, if either the cause was already set in an appropriate constructor (see above)
048                                // or the concrete Throwable does not support it. If we were unable to set the cause we want,
049                                // we better use a RemoteException and not the original one.
050                                if (throwable.getCause() != cause)
051                                        return;
052                        }
053                        if (throwable instanceof RuntimeException)
054                                throw (RuntimeException) throwable;
055
056                        if (throwable instanceof java.lang.Error)
057                                throw (java.lang.Error) throwable;
058
059                        throw new RuntimeException(throwable);
060                }
061        }
062
063        private static <T> T getObjectOrNull(final Class<T> clazz, Class<?>[] argumentTypes, final Object ... arguments) {
064                T result = null;
065                if (argumentTypes == null)
066                        argumentTypes = new Class<?> [0];
067
068                if (argumentTypes.length == 0) {
069                        try {
070                                result = clazz.newInstance();
071                        } catch (final InstantiationException e) {
072                                return null;
073                        } catch (final IllegalAccessException e) {
074                                return null;
075                        }
076                }
077
078                if (result == null) {
079                        Constructor<T> constructor;
080                        try {
081                                constructor = clazz.getConstructor(argumentTypes);
082                        } catch (final NoSuchMethodException e) {
083                                return null;
084                        } catch (final SecurityException e) {
085                                return null;
086                        }
087
088                        try {
089                                result = constructor.newInstance(arguments);
090                        } catch (final InstantiationException e) {
091                                return null;
092                        } catch (final IllegalAccessException e) {
093                                return null;
094                        } catch (final IllegalArgumentException e) {
095                                return null;
096                        } catch (final InvocationTargetException e) {
097                                return null;
098                        }
099                }
100
101                return result;
102        }
103}