package org.neo4j.graphalgo.competition; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * A converter that converts the result of a method invocation when a particular * exception is intercepted. * * @param <EX> the type to convert from. */ public abstract class ExceptionConverter<EX extends Exception> { private final Class<EX> exceptionType; /** * Create a converter from one exception type to another. * * @param exception the exception type to catch and convert. */ protected ExceptionConverter( Class<EX> exception ) { if ( exception == null ) throw new NullPointerException(); this.exceptionType = exception; } /** * Convert the exception. * * @param cause the method that caused the exception. * @param exception the exception. * @return the converted result. * @throws Throwable if the result of the conversion is to throw an * exception. */ protected abstract Object convert( Method cause, EX exception ) throws Throwable; /** * Crate a proxy instance of a class that delegates to the specified object * and converts the specified exception. * * @param <T> the type to proxy. * @param type the type to proxy. * @param object the object to delegate to. * @return the proxy instance. */ public final <T> T proxy( Class<T> type, final T object ) { if ( object == null ) throw new NullPointerException(); return type.cast( Proxy.newProxyInstance( type.getClassLoader(), new Class[] { type }, new InvocationHandler() { public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable { try { return method.invoke( object, args ); } catch ( IllegalArgumentException e ) { throw new InvocationError( e ); } catch ( IllegalAccessException e ) { throw new InvocationError( e ); } catch ( InvocationTargetException e ) { Throwable ex = e.getTargetException(); if ( exceptionType.isInstance( ex ) ) { return convert( method, exceptionType.cast( ex ) ); } else { throw ex; } } } } ) ); } @SuppressWarnings( "serial" ) private static class InvocationError extends Error { InvocationError( Exception cause ) { super( cause ); } } }