package example.common.handler;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class SoapClientSideHandler implements SOAPHandler<SOAPMessageContext> {

    static Logger logger = LoggerFactory.getLogger(SoapClientSideHandler.class);

    public Set<QName> getHeaders() {
        return null;
    }

    public boolean handleMessage(SOAPMessageContext context) {
        return true;
    }

    public boolean handleFault(SOAPMessageContext context) {
        SOAPMessage message = context.getMessage();
        SOAPPart part = message.getSOAPPart();
        NodeList exceptions = part.getElementsByTagNameNS(
                "http://jax-ws.dev.java.net/", "exception");
        if (exceptions.getLength() == 1) {
            handleException((Element) exceptions.item(0));
        }
        return true;
    }

    void handleException(Element exception) {
        String className = exception.getAttribute("class");
        Element messageNode = (Element)
                exception.getElementsByTagName("message").item(0);
        String message = messageNode.getTextContent();
        try {
            Class<?> clazz = Class.forName(className);
            Constructor<?> c = clazz.getConstructor(String.class);
            Object o = c.newInstance(message);
            if (o instanceof RuntimeException) {
                throw (RuntimeException) o;
            }
        } catch (ClassNotFoundException e) {
            logger.warn(e.toString());
        } catch (NoSuchMethodException e) {
            logger.warn(e.toString());
        } catch (InstantiationException e) {
            logger.warn(e.toString());
        } catch (IllegalAccessException e) {
            logger.warn(e.toString());
        } catch (InvocationTargetException e) {
            logger.warn(e.toString());
        }
    }

    public void close(MessageContext context) {
    }

}
