/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-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 1any 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.jaxws.test;

import java.io.ByteArrayOutputStream;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.messaging.URLEndpoint;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import org.ow2.jonas.ws.jaxws.test.util.JWebServicesTestCase;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;


public class EJBClientTestCases extends JWebServicesTestCase {
    private static final String PORT_URL_WITH_WEBMETHOD = "/jaxws-ejb-webmethod/JAXWSBeanWithWebMethod";
    private static final String PORT_URL_WITHOUT_WEBMETHOD = "/jaxws-ejb-webmethod/JAXWSBeanWithoutWebMethod";
    private static final String PORT_URL_DESCRIPTOR = "/jaxws-ejb-descriptor/JAXWSBean_descriptor";   
    private static final String PORT_URL_INJECTION = "/jaxws-ejb-injection/JAXWSBeanInjection";  
    private static final String PORT_URL_INTERCEPTOR = "/jaxws-ejb-interceptor/EJBWSwihtInterceptors";
    public EJBClientTestCases(String s) throws Exception {
        super(s);
    }

    @BeforeClass
    public void setUp() throws Exception {
    }

    @AfterClass
    public void tearDown() throws Exception {
    }

    @Test(groups = { "EJB_with_webmethod" })
    public void testWithWebmethodWSDL() throws Exception {
        useBeans("jaxws-ejb-webmethod");
        try {
            Assert.assertNotNull(getWSDLForService(PORT_URL_WITH_WEBMETHOD),"Can not get wsdl for EJB_with_webmethod!");
        } finally {
            unUseBeans("jaxws-ejb-webmethod");
        }
   }

    @Test(groups = { "EJB_with_webmethod" })
    public void testWithWebmethodInvoke() throws Exception {
        useBeans("jaxws-ejb-webmethod");
        String response = null;          
        try {
            response = invokeEJBWebService(PORT_URL_WITH_WEBMETHOD,"greetMe","arg0");
            Assert.assertTrue(response.contains("<return>Hello foo bar</return>"),"greetMe() should be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITH_WEBMETHOD,"greetMeFault","arg0");
            Assert.assertTrue(response.contains("<faultstring>my error</faultstring>"),"greetMeFault() should be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITH_WEBMETHOD,"greetYou","arg0");
            Assert.assertTrue(!response.contains("<return>Hi foo bar</return>"),"greetYou() should not be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITH_WEBMETHOD,"sayHello","arg0");
            Assert.assertTrue(!response.contains("<return>Hello World! foo bar</return>"),"sayHello() should not be exposed as web method!");

        } finally {
            unUseBeans("jaxws-ejb-webmethod");
        }
    }

    @Test(groups = { "EJB_without_webmethod" })
    public void testWithoutWebmethodWSDL() throws Exception {
        useBeans("jaxws-ejb-webmethod");
        try {
            Assert.assertNotNull(getWSDLForService(PORT_URL_WITHOUT_WEBMETHOD),"Can not get wsdl for EJB_without_webmethod!");
        } finally {
            unUseBeans("jaxws-ejb-webmethod");
        }
    }
    
    @Test(groups = { "EJB_without_webmethod" })
    public void testWithoutWebmethodInvoke() throws Exception {
        useBeans("jaxws-ejb-webmethod");
        String response = null;
        try {
            response = invokeEJBWebService(PORT_URL_WITHOUT_WEBMETHOD,"greetMe","arg0");
            Assert.assertTrue(response.contains("<return>Hello foo bar</return>"),"greetMe() should be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITHOUT_WEBMETHOD,"greetYou","arg0");
            //System.out.println("******************greetYou : " + response);
            Assert.assertTrue(response.contains("<return>Hi foo bar</return>"),"greetYou() should be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITHOUT_WEBMETHOD,"greetMeFault","arg0");
            Assert.assertTrue(response.contains("<faultstring>my error</faultstring>"),"greetMeFault() should be exposed as web method!");

            response = invokeEJBWebService(PORT_URL_WITHOUT_WEBMETHOD,"sayHello","arg0");
            Assert.assertTrue(!response.contains("<return>Hello World! foo bar</return>"),"sayHello() should not be exposed as web method!");

        } finally {
            unUseBeans("jaxws-ejb-webmethod");
        }
    }

    @Test(groups = { "EJB_descriptor" })
    public void testDescriptorWSDL() throws Exception {
        useBeans("jaxws-ejb-descriptor");
        try {
            Assert.assertNotNull(getWSDLForService(PORT_URL_DESCRIPTOR),"Can not get wsdl for EJB_descriptor!");
        } finally {
            unUseBeans("jaxws-ejb-descriptor");
        }
   }

    @Test(groups = { "EJB_descriptor" })
    public void testDescriptorInvoke() throws Exception {
        useBeans("jaxws-ejb-descriptor");
        String response = null;
        try {
            response = invokeEJBWebService(PORT_URL_DESCRIPTOR,"greetMe","arg0");
            Assert.assertTrue(response.contains("<return>Hello foo bar</return>"),"Reply of greetMe() is not right!");
        } finally {
            unUseBeans("jaxws-ejb-descriptor");
        }
    }

    @Test(groups = { "EJB_injection" })
    public void testWSContextInjectionInvoke() throws Exception {
        useBeans("jaxws-ejb-injection");
        String response = null;
        try {
            response = invokeEJBWebService(PORT_URL_INJECTION,"greetMe","arg0");
            Assert.assertTrue(response.contains("<return>foo barwsContext"),"wsContext is not injected correctly!");
        } finally {
            unUseBeans("jaxws-ejb-injection");
        }
    }

    @Test(groups = { "EJB_injection" })
    public void testEJBResourceInjectionInvoke() throws Exception {
        useBeans("jaxws-ejb-injection");
        useBeans("ejb3");
        String response = null;
        try {
            response = invokeEJBWebService(PORT_URL_INJECTION,"greetMe","arg0");
            Assert.assertTrue(response.contains("<return>foo barwsContexthello"),"EJB resource is not injected correctly!");
        } finally {
            unUseBeans("jaxws-ejb-injection");
            unUseBeans("ejb3");
        }
    }
    
    @Test(groups = { "EJB_interceptor" })
    public void testEJBInterceptorInvoke() throws Exception {
        useBeans("jaxws-ejb-interceptor");
        String response = null;
        try {
            response = invokeEJBWebService(PORT_URL_INTERCEPTOR,"greetMe","arg0");
            Assert.assertTrue(response.contains("intercepted"),"EJB resource is not injected correctly!");
        } finally {
            unUseBeans("jaxws-ejb-interceptor");
        }
    }

    private Definition getWSDLForService(String servicePort) throws WSDLException {
        String port = System.getProperty("http.port");
        if(port == null) 
            port = "9000";

        String url = "http://localhost:" + port + servicePort + "?WSDL";
        WSDLFactory factory = WSDLFactory.newInstance();
        WSDLReader reader = factory.newWSDLReader();
        reader.setFeature("javax.wsdl.importDocuments", true);
        return reader.readWSDL(url);
    }

    private String invokeEJBWebService(String servicePort, String opName, String paraName) throws UnsupportedOperationException, SOAPException {

        String port = System.getProperty("http.port");

        if(port == null) {
            port = "9000";
        }
        SOAPConnectionFactory soapConnFactory = 
            SOAPConnectionFactory.newInstance();
        SOAPConnection connection  = soapConnFactory.createConnection();

        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage message = messageFactory.createMessage();

        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = (SOAPEnvelope) soapPart.getEnvelope();
        SOAPBody body = envelope.getBody();

        SOAPElement bodyElement = body.addChildElement(envelope.createName(opName));
        SOAPElement strElement = bodyElement.addChildElement(paraName);
        strElement.setValue("foo bar");

        message.saveChanges();
        //message.writeTo(System.out);
        //System.out.println();

        URLEndpoint destination = new URLEndpoint("http://localhost:"+ port + servicePort);
        SOAPMessage reply = connection.call(message, destination);

        Assert.assertNotNull(reply,"Reply of " + servicePort + " is Null!");
        String response = null;  
        try{
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            reply.writeTo(os);
            response = new String(os.toByteArray());
        } catch(Exception e) {
            e.printStackTrace();
        }
        connection.close();
        return response;
    }

}
