package com.ejie.aa21b.ws.handler;

import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Node;

import weblogic.utils.ArrayUtils;

import com.ejie.aa21b.ldap.SecurityHelpperXLNets;
import com.ejie.aa21b.util.Aa21bConstantes;

public class N38TokenServerHandler implements SOAPHandler<SOAPMessageContext> {

	private String tokenN38XQuery = "//n38";
	private XPathExpression expression;
	private TransformerFactory transformerFactory;

	/**
	 * Constructor por defecto.
	 * 
	 * @throws XPathExpressionException
	 */
	public N38TokenServerHandler() throws XPathExpressionException {
		// inicializacion de la expresi�n XPATH
		XPathFactory xpFactory = XPathFactory.newInstance();
		XPath xpath = xpFactory.newXPath();
		this.expression = xpath.compile(tokenN38XQuery);
		this.transformerFactory = TransformerFactory.newInstance();
	}

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

	public void close(MessageContext context) {
		// Nada que hacer
	}

	/**
	 * @see javax.xml.ws.handler.Handler#handleFault(javax.xml.ws.handler.MessageContext)
	 */
	public boolean handleFault(SOAPMessageContext context) {
		return true;
	}

	/**
	 * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext)
	 */
	public boolean handleMessage(SOAPMessageContext context) {
		boolean valid = false;

		Boolean outbound = (Boolean) context
				.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

		// solo para los mensajes entrantes
		if (outbound != null && !outbound.booleanValue()) {
			// TODO comento esta l�nea para probar en local, pero habr�a que
			// dejarla a false
			// valid = false;

			try {
				String tokenN38 = doExtractToken(context.getMessage()
						.getSOAPHeader());

				if (tokenN38 != null && !tokenN38.equals("")) { // TODO
																// verificar que
																// la sesion es
																// valida

					// TODO verificar los permisos del cliente
					SecurityHelpperXLNets seguridad = new SecurityHelpperXLNets(
							tokenN38);

					String[] perfiles = seguridad.getPerfiles();
					if (ArrayUtils.contains(perfiles,
							Aa21bConstantes.XLNET_PERFIL_INTEGRADOR)) {
						// En el ejemplo unicamente comprobamos que se ha
						// enviado //
						// unasesion de aplicacion

						valid = true;
					} else {
						valid = false;
					}
				}
			} catch (Exception e) {
				valid = false;
			}

		}
		return valid;
	}

	/**
	 * Extrae el xml correspondiente a la sesi�n de aplicaci�n.
	 * 
	 * @param node
	 * @return
	 * @throws XPathExpressionException
	 * @throws TransformerException
	 */
	private String doExtractToken(Node node) throws XPathExpressionException,
			TransformerException {
		String tokenN38 = "";

		// busqueda XPath del nodo n38
		Node tokenN38Node = (Node) expression.evaluate(node,
				XPathConstants.NODE);

		if (tokenN38Node != null) {
			// convertimos a String el nodo del token
			Source tokenN38NodeSource = new DOMSource(tokenN38Node);

			StringWriter writer = new StringWriter();
			Result result = new StreamResult(writer);

			transformerFactory.newTransformer().transform(tokenN38NodeSource,
					result);
			tokenN38 = writer.toString();
		}
		return tokenN38;
	}

}
