/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2009 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.ws.axis2.test;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;

import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.ow2.jonas.ws.axis2.jaxws.Axis2WSEndpoint;
import org.ow2.jonas.ws.axis2.pojo.HelloService;
import org.ow2.jonas.ws.jaxws.IWSRequest;
import org.ow2.jonas.ws.jaxws.IWSResponse;
import org.ow2.jonas.ws.jaxws.IWebServiceEndpoint;
import org.ow2.jonas.ws.jaxws.PortMetaData;
import org.ow2.jonas.ws.jaxws.WSException;
import org.ow2.jonas.ws.jaxws.http.servlet.ServletRequestAdapter;
import org.ow2.jonas.ws.jaxws.http.servlet.ServletResponseAdapter;
import org.ow2.jonas.ws.jaxws.http.servlet.test.ServletInputStreamForTest;
import org.ow2.jonas.ws.jaxws.http.servlet.test.ServletOutputStreamForTest;
import org.ow2.jonas.ws.jaxws.http.servlet.test.ServletRequestAdapterForTest;
import org.ow2.jonas.ws.jaxws.http.servlet.test.ServletResponseAdapterForTest;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Axis2WSEndpointTest {

    @BeforeClass
    public void setUp() {
    }

    @AfterClass
    public void tearDown() {
    }
    //@Test(groups = { "POJO" })
    public void testAxis2WSEndpointGetWSDL() throws URISyntaxException, IOException {
        ServletRequestAdapterForTest request = new ServletRequestAdapterForTest(504,
                "text/xml; charset=utf-8",
                null,
                "GET",
                new HashMap<Object, Object>(),
                new URI("/HelloService"),
                new URL("http://localhost:9000/HelloService?wsdl"),
                "?wsdl",
                new HashMap<Object, Object>(),
                "127.0.0.1");

        ServletOutputStreamForTest out = new ServletOutputStreamForTest();

        ServletResponseAdapterForTest response = new ServletResponseAdapterForTest("text/xml; charset=utf-8",
                "127.0.0.1",
                null,
                null,
                8080,
                out);

        IWSRequest req = new ServletRequestAdapter(request);

        req.setAttribute(HttpServletRequest.class, request);

        req.setAttribute(HttpServletResponse.class, response);

        PortMetaData pmd = new PortMetaData();

        pmd.setContextRoot("/");
        pmd.setUrlPattern("HelloService");
        WebService ws = HelloService.class.getAnnotation(WebService.class);
        pmd.setWSDLLocation(ws.wsdlLocation());

        Axis2WSEndpoint endpoint = new Axis2WSEndpoint(HelloService.class, IWebServiceEndpoint.EndpointType.POJO, pmd, null,null);

        IWSResponse res = new ServletResponseAdapter(response);

        try {
            // init axis2
            endpoint.init();
        } catch (Exception e) {
            System.err.println("Exception occurs when creating POJO endpoint for HelloService !");
            e.printStackTrace();
        }

        try {
            endpoint.invoke(req, res);
        } catch (WSException e) {
            System.err.println("Exception occurs when invoking POJO endpoint HelloService !");
            e.printStackTrace();
        }
        Assert.assertTrue(out.getStringBuffer().toString().contains("wsdl:definitions"));
    }

    //@Test(groups = { "POJO" })
    public void testAxis2WSEndpointInvoke() {
        try {
            invokeWithRequestFile("HelloService", HelloService.class.getCanonicalName(), "WEB-INF/test_service_pojo.xml");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void invokeWithRequestFile(final String serviceName, final String endPointClassName, final String requestFile ) throws ParserConfigurationException, SAXException, IOException {

        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        InputStream in = cl.getResourceAsStream(requestFile);

        //This will reduce number of requests files
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = dbf.newDocumentBuilder();

        Document doc = null;
        try {
            System.out.println(in == null);
            doc = documentBuilder.parse(in);
        } catch(Exception e) {
            e.printStackTrace();
        }

        Element root = doc.getDocumentElement();
        NodeList nodeList = root.getElementsByTagName("soap:Envelope");




        ServletInputStreamForTest input;


        for(int i = 0; i < nodeList.getLength(); i++){

            StringBuffer envelope = new StringBuffer("<soap:Envelope");
            try {
            Element element = (Element)nodeList.item(i);
            NamedNodeMap attributes = element.getAttributes();
            if(attributes != null){
                for(int k=0; k < attributes.getLength(); k++){
                    envelope.append(" "+attributes.item(k).getNodeName().trim());
                    envelope.append("=\""+attributes.item(k).getNodeValue().trim()+"\"");
                }
                String content = element.getTextContent();

                if(content != null && !content.equals("")){
                    envelope.append(">");

                    NodeList children = element.getChildNodes();
                    if(children != null){
                        for(int j=0; j < children.getLength(); j++){
                            if(children.item(j).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){
                                Element child = (Element)children.item(j);
                                envelope.append(getElementContent(child).trim());
                            }else if(children.item(j).getNodeType() == org.w3c.dom.Node.TEXT_NODE){
                                envelope.append(children.item(j).getNodeValue().trim());
                            }
                        }
                    }
                    envelope.append("</soap:Envelope>");
                }else {
                    envelope.append("/>");
                }
            }
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println(envelope);

            PortMetaData pmd = new PortMetaData();

            pmd.setContextRoot("/");
            pmd.setUrlPattern("HelloService");
            WebService ws = HelloService.class.getAnnotation(WebService.class);
            pmd.setWSDLLocation(ws.wsdlLocation());

            input = new ServletInputStreamForTest(envelope.toString().getBytes("UTF-8"));


            ServletRequestAdapterForTest request = null;

            try {
                request = new ServletRequestAdapterForTest(504,
                        "text/xml; charset=utf-8",
                        input,
                        "POST",
                        new HashMap<Object, Object>(),
                        new URI("/HelloService"),
                        new URL("http://localhost:9000/HelloService"),
                        null,
                        new HashMap<Object, Object>(),
                        "127.0.0.1");
            } catch (URISyntaxException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            ServletOutputStreamForTest out = new ServletOutputStreamForTest();

            ServletResponseAdapterForTest response = new ServletResponseAdapterForTest("text/xml; charset=utf-8",
                    "127.0.0.1",
                    null,
                    null,
                    8080,
                    out);


            IWSRequest req = new ServletRequestAdapter(request);

            req.setAttribute(HttpServletRequest.class, request);

            req.setAttribute(HttpServletResponse.class, response);

            Axis2WSEndpoint endpoint = new Axis2WSEndpoint(HelloService.class, IWebServiceEndpoint.EndpointType.POJO, pmd, null,null);

            IWSResponse res = new ServletResponseAdapter(response);

            try {
                // init axis2
                endpoint.init();
            } catch (Exception e) {
                System.err.println("Exception occurs when creating POJO endpoint for HelloService !");
                e.printStackTrace();
            }

            try {
                endpoint.invoke(req, res);
            } catch (Exception e) {
                System.err.println("Exception occurs when invoking POJO endpoint HelloService !");
                e.printStackTrace();
            }

            System.out.println(out.getStringBuffer());
            Assert.assertTrue(out.getStringBuffer().toString().contains("helloJOnAS"));
        }
    }

    private String getElementContent(final Element e){
        StringBuffer content = new StringBuffer("<"+e.getNodeName());
        NamedNodeMap attributes = e.getAttributes();

        if(attributes != null){
            for(int k=0; k < attributes.getLength(); k++){
                content.append(" "+attributes.item(k).getNodeName()) ;
                content.append("=\""+attributes.item(k).getNodeValue()+"\"") ;
            }
        }

        String value = e.getTextContent();

        if(value != null && !value.equals("")){
            content.append(">");

            NodeList children = e.getChildNodes();
            if(children != null){
                for(int j=0; j < children.getLength(); j++){
                    if(children.item(j).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){
                        Element child = (Element)children.item(j);
                        content.append(getElementContent(child).trim());
                    }else if(children.item(j).getNodeType() == org.w3c.dom.Node.TEXT_NODE){
                        content.append(children.item(j).getNodeValue().trim());
                    }
                }
            }
            content.append("</"+e.getNodeName()+">");
        }else {
            content.append("/>");
        }

        return content.toString();
    }
}
