/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2010, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.test.ws.jaxws.jbws2991;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPFault;
import javax.xml.ws.Holder;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.soap.SOAPFaultException;

import junit.framework.Test;

import org.jboss.test.ws.jaxws.common.W3CAddressingConstants;
import org.jboss.test.ws.jaxws.common.WsaSOAPUtils;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest1;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest1Service;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest2;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest2Service;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest3;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest3Service;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest4;
import org.jboss.test.ws.jaxws.jbws2991.generated.AddressingFeatureTest4Service;
import org.jboss.wsf.test.JBossWSTest;
import org.jboss.wsf.test.JBossWSTestSetup;

public class JBWS2991TestCase extends JBossWSTest
{

   private static final String NAMESPACEURI = "http://addressingfeatureservice.org/wsdl";

   private QName SERVICE1_QNAME = new QName(NAMESPACEURI, "AddressingFeatureTest1Service");

   private QName SERVICE2_QNAME = new QName(NAMESPACEURI, "AddressingFeatureTest2Service");

   private QName SERVICE3_QNAME = new QName(NAMESPACEURI, "AddressingFeatureTest3Service");

   private QName SERVICE4_QNAME = new QName(NAMESPACEURI, "AddressingFeatureTest4Service");

   private QName PORT_QNAME1 = new QName(NAMESPACEURI, "AddressingFeatureTest1Port");

   private QName PORT_QNAME2 = new QName(NAMESPACEURI, "AddressingFeatureTest2Port");

   private QName PORT_QNAME3 = new QName(NAMESPACEURI, "AddressingFeatureTest3Port");

   private QName PORT_QNAME4 = new QName(NAMESPACEURI, "AddressingFeatureTest4Port");

   private AddressingFeatureTest1 port1 = null;

   private AddressingFeatureTest2 port2 = null;

   private AddressingFeatureTest3 port3 = null;

   private AddressingFeatureTest4 port4 = null;

   private AddressingFeatureTest1 port5 = null;

   private AddressingFeatureTest2 port6 = null;

   private AddressingFeatureTest4 port7 = null;

   private boolean initialized;

   private WebServiceFeature[] enabledNotRequiredwsf =
   {new AddressingFeature(true, false)};

   private WebServiceFeature[] nonEnabledwsf =
   {new AddressingFeature(false)};

   private WebServiceFeature[] enabledRequiredwsf =
   {new AddressingFeature(true, true)};

   public static Test suite()
   {
      return new JBossWSTestSetup(JBWS2991TestCase.class, "jaxws-jbws2991.war");
   }

   protected void setUp() throws Exception
   {
      if (!this.initialized)
      {
         this.initialized = true;

         Service service = null;
         URL wsdlURL = null;
         // client side Addressing enabled/NotRequired; server side Addressing/NotRequired
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint1?wsdl");
         service = new AddressingFeatureTest1Service(wsdlURL, SERVICE1_QNAME);
         port1 = service.getPort(PORT_QNAME1, AddressingFeatureTest1.class, enabledNotRequiredwsf);

         // client side Addressing enabled/NotRequired; server side Addressing/Required 
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint2?wsdl");
         service = new AddressingFeatureTest2Service(wsdlURL, SERVICE2_QNAME);
         port2 = service.getPort(PORT_QNAME2, AddressingFeatureTest2.class, enabledNotRequiredwsf);

         // client side Addressing enabled/NotRequired; server side Addressing (using default) 
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint3?wsdl");
         service = new AddressingFeatureTest3Service(wsdlURL, SERVICE3_QNAME);
         port3 = service.getPort(PORT_QNAME3, AddressingFeatureTest3.class, enabledNotRequiredwsf);

         // client side Addressing enabled/NotRequired; server side Addressing off
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint4?wsdl");
         service = new AddressingFeatureTest4Service(wsdlURL, SERVICE4_QNAME);
         port4 = service.getPort(PORT_QNAME4, AddressingFeatureTest4.class, enabledNotRequiredwsf);

         // client side Addressing off; server side Addressing/NotRequired 
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint1?wsdl");
         service = new AddressingFeatureTest1Service(wsdlURL, SERVICE1_QNAME);
         port5 = service.getPort(PORT_QNAME1, AddressingFeatureTest1.class, nonEnabledwsf);

         // client side Addressing off; server side Addressing/Required 
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint2?wsdl");
         service = new AddressingFeatureTest2Service(wsdlURL, SERVICE2_QNAME);
         port6 = service.getPort(PORT_QNAME2, AddressingFeatureTest2.class, nonEnabledwsf);

         // client side Addressing enabled/Required; server side off
         wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws2991/Endpoint4?wsdl");
         service = new AddressingFeatureTest4Service(wsdlURL, SERVICE4_QNAME);
         port7 = service.getPort(PORT_QNAME4, AddressingFeatureTest4.class, enabledRequiredwsf);
      }
   }

   public void testClientEnabledNotREQServerEnabledNotREQTest() throws Exception
   {
      // client side Addressing enabled/NotRequired; server side Addressing/NotRequired 
      port1.addNumbers(new Holder("ClientEnabledNotREQServerEnabledNotREQ"), 10, 10);
   }

   public void testClientEnabledNotREQServerEnabledREQTest() throws Exception
   {
      // client side Addressing enabled/NotRequired; server side Addressing/Required 
      port2.addNumbers(new Holder("ClientEnabledNotREQServerEnabledREQ"), 10, 10);
   }

   public void testClientEnabledNotREQServerUsingDefaultsTest() throws Exception
   {
      // client side Addressing enabled/NotRequired; Server side using defaults
      port3.addNumbers(new Holder("ClientEnabledNotREQServerUsingDefaults"), 10, 10);
   }

   public void testClientEnabledNotREQServerNotEnabledTest() throws Exception
   {
      // client side Addressing enabled/NotRequired; Server NotEnabled
      port4.addNumbers(new Holder("ClientEnabledNotREQServerNotEnabled"), 10, 10);
   }

   public void testClientNotEnabledServerEnabledNotREQTest() throws Exception
   {
      // Verify Addressing headers are NOT present on SOAPRequest and SOAPResponse
      port5.addNumbers(new Holder("ClientNotEnabledServerEnabledNotREQ"), 10, 10);
   }

   public void testClientNotEnabledServerEnabledREQTest() throws Exception
   {
      // Verify MessageAddressingHeaderRequired soap fault is thrown by endpoint
      try
      {
         port6.addNumbers(new Holder("ClientNotEnabledServerEnabledREQ"), 10, 10);
      }
      catch (SOAPFaultException sfe)
      {
         log.debug("Caught expected SOAPFaultException: " + sfe.getMessage());
         log.debug("FaultCode=" + WsaSOAPUtils.getFaultCode(sfe));
         String faultString = WsaSOAPUtils.getFaultString(sfe);
         if (W3CAddressingConstants.MAP_REQUIRED_TEXT.equals(faultString))
         {
            log.debug("Found expected FaultString: " + faultString);
         }
         else
         {
            throw new Exception("Found unexpected FaultString [" + faultString + "] Expected ["
                  + W3CAddressingConstants.MAP_REQUIRED_TEXT + "]");
         }
         if (WsaSOAPUtils.isMessageAddressingHeaderRequiredFaultCode(sfe))
            log.debug("SOAPFault contains expected faultcode MessageAddressingHeaderRequired");
         else
         {
            String faultcode = WsaSOAPUtils.getFaultCode(sfe);
            throw new Exception("SOAPFault contains unexpected faultcode got: " + faultcode
                  + ", expected: MessageAddressingHeaderRequired");
         }
         String faultdetail[] = WsaSOAPUtils.getFaultDetail(sfe);
         if (faultdetail != null)
         {
            log
                  .error("The SOAP 1.1 fault detail is only for use with faults related to the body of a message and is therefore not used for SOAP 1.1 faults related to processing of addressing headers.");
            String output = "FaultDetail:";
            for (int i = 0; faultdetail[i] != null; i++)
            {
               output += " " + faultdetail[i];
            }
            log.error("" + output);
         }
         else
         {
            log
                  .debug("The SOAP 1.1 fault detail is correctly not used, since fault detail is only for use with faults related to the body of a message and is therefore not used for SOAP 1.1 faults related to processing of addressing headers.");
         }
      }
   }

   public void testClientEnabledREQServerNotEnabledTest() throws Exception
   {
      // Verify MessageAddressingHeaderRequired soap fault is thrown by endpoint
      try
      {
         port7.addNumbers(new Holder("ClientEnabledREQServerNotEnabled"), 10, 10);
      }
      catch (SOAPFaultException sfe)
      {
         log.debug("Caught Expected SOAPFaultException: " + sfe.getMessage());
         SOAPFault sf = sfe.getFault();
         String faultString = sf.getFaultString();
         String faultCode = sf.getFaultCode();
         System.out.println("faultString [" + faultString + "]");
         System.out.println("faultCode [" + faultCode + "]");
         QName faultCodeQName = sf.getFaultCodeAsQName();
         String faultCodeQNameLocalPart = faultCodeQName.getLocalPart();
         if (!W3CAddressingConstants.MAP_REQUIRED_QNAME.getLocalPart().equals(faultCodeQNameLocalPart))
         {
            log.error("Caught expected SOAPFaultException, but with incorrect FaultCode, expected ["
                  + W3CAddressingConstants.MAP_REQUIRED_QNAME.getLocalPart() + "], Actual [" + faultCodeQNameLocalPart
                  + "]");
            throw new Exception("afClientEnabledREQServerNotEnabledTest failed", sfe);
         }
         else
         {
            log.debug("Caught expected SOAPFaultException with correct FaultCode, expected ["
                  + W3CAddressingConstants.MAP_REQUIRED_QNAME.getLocalPart() + "], Actual [" + faultCodeQNameLocalPart
                  + "]");
         }
         if (!W3CAddressingConstants.MAP_REQUIRED_TEXT.equals(faultString))
         {
            log.error("Caught expected SOAPFaultException, but with incorrect FaultString set in FaultCode, expected ["
                  + W3CAddressingConstants.MAP_REQUIRED_TEXT + "], Actual [" + faultString + "]");
            throw new Exception("afClientEnabledREQServerNotEnabledTest failed", sfe);
         }
         else
         {
            log.debug("Caught expected SOAPFaultException with correct FaultString set in FaultCode, expected ["
                  + W3CAddressingConstants.MAP_REQUIRED_TEXT + "], Actual [" + faultString + "]");
         }
      }
   }
}
