package example.common.interceptor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.HandlerResolver;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class JaxwsProxyInterceptor implements MethodInterceptor {

    URL wsdlLocation;

    QName serviceName;

    HandlerResolver handlerResolver;

    public void setWsdlLocation(URL wsdlLocation) {
        this.wsdlLocation = wsdlLocation;
    }

    public void setServiceName(QName serviceName) {
        this.serviceName = serviceName;
    }

    public void setHandlerResolver(HandlerResolver handlerResolver) {
        this.handlerResolver = handlerResolver;
    }

    public Object invoke(MethodInvocation invocation) throws Throwable {
        Service service = new Service(wsdlLocation, serviceName) {};
        if (handlerResolver != null) {
            service.setHandlerResolver(handlerResolver);
        }
        Method method = invocation.getMethod();
        Class<?> endpointInterface = method.getDeclaringClass();
        Object port = service.getPort(endpointInterface);
        try {
            return method.invoke(port, invocation.getArguments());
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof WebServiceException) {
                handleWebServiceException((WebServiceException) cause);
            }
            throw (cause == null ? e : cause);
        }
    }

    void handleWebServiceException(WebServiceException e) throws Throwable {
        Throwable cause = e.getCause();
        throw (cause == null ? e : cause);
    }

}
