/*
 * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * $Id: SOAPBodyTestServlet.java 63095 2011-06-16 15:39:26Z adf $
 */

package com.sun.ts.tests.saaj.api.javax_xml_soap.SOAPBody;

import com.sun.ts.lib.util.*;
import com.sun.ts.lib.porting.*;
import com.sun.ts.tests.saaj.common.*;

import javax.servlet.http.*;
import javax.servlet.*;
import javax.xml.soap.*;
import javax.xml.namespace.QName;
import javax.activation.DataHandler;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;

public class SOAPBodyTestServlet extends HttpServlet {
    private MessageFactory mf = null;
    private SOAPMessage msg = null;
    private SOAPPart sp = null;
    private SOAPEnvelope envelope = null;
    private SOAPHeader hdr = null;
    private SOAPHeaderElement she = null;
    private SOAPBody body = null;
    private SOAPBodyElement bodye = null;
    private SOAPFault fault = null;
    private SOAPFault fault1 = null;
    private SOAPFault fault2 = null;
    private String prefix = null;
    private String uri = null;

    private void setup() throws Exception 
    {
	TestUtil.logTrace("setup");

	SOAP_Util.setup();

	// Create a message from the message factory.
	TestUtil.logMsg("Create message from message factory");
	msg = SOAP_Util.getMessageFactory().createMessage();

	// Message creation takes care of creating the SOAPPart - a
	// required part of the message as per the SOAP 1.1 spec.
	TestUtil.logMsg("Get SOAP Part");
	sp = msg.getSOAPPart();

	// Retrieve the envelope from the soap part to start building
	// the soap message.
	TestUtil.logMsg("Get SOAP Envelope");
	envelope = sp.getEnvelope();
	prefix = envelope.getElementName().getPrefix();
	uri = envelope.getElementName().getURI();

	// Retrieve the soap header from the envelope.
	TestUtil.logMsg("Get SOAP Header");
        hdr = envelope.getHeader();

	// Retrieve the soap header from the envelope.
	TestUtil.logMsg("Get SOAP Body");
        body = envelope.getBody();
    }

    private void dispatch(HttpServletRequest req, HttpServletResponse res)
                               throws ServletException, IOException 
    {
	TestUtil.logTrace("dispatch");
	   String testname = SOAP_Util.getHarnessProps().getProperty("TESTNAME");
	   if(testname.equals("addBodyElementTest1")) {
            TestUtil.logMsg("Starting addBodyElementTest1");
            addBodyElementTest1(req, res);
        } else if(testname.equals("addBodyElementTest2")) {
            TestUtil.logMsg("Starting addBodyElementTest2");
            addBodyElementTest2(req, res);
        } else if(testname.equals("addFaultTest1")) {
            TestUtil.logMsg("Starting addFaultTest1");
            addFaultTest1(req, res);
        } else if(testname.equals("addFaultTest2")) {
            TestUtil.logMsg("Starting addFaultTest2");
            addFaultTest2(req, res);
        } else if(testname.equals("addFaultTest3")) {
            TestUtil.logMsg("Starting addFaultTest3");
            addFaultTest3(req, res);
        } else if(testname.equals("addFaultTest4")) {
            TestUtil.logMsg("Starting addFaultTest4");
            addFaultTest4(req, res);
        } else if(testname.equals("addFaultTest5")) {
            TestUtil.logMsg("Starting addFaultTest5");
            addFaultTest5(req, res);
        } else if(testname.equals("addDocumentTest")) {
            TestUtil.logMsg("Starting addDocumentTest");
            addDocumentTest(req, res);
        } else if(testname.equals("getFaultTest")) {
            TestUtil.logMsg("Starting getFaultTest");
            getFaultTest(req, res);
	   } else if(testname.equals("hasFaultTest")) {
            TestUtil.logMsg("Starting hasFaultTest");
            hasFaultTest(req, res);
	   } else if(testname.equals("extractContentAsDocumentTest1")) {
            TestUtil.logMsg("Starting extractContentAsDocumentTest1");
            extractContentAsDocumentTest1(req, res);
        } else if(testname.equals("extractContentAsDocumentTest2")) {
            TestUtil.logMsg("Starting extractContentAsDocumentTest2");
            extractContentAsDocumentTest2(req, res);
        } else {
        throw new ServletException("The testname '"+testname+"' was not found in the test servlet");

        }

    }

    public void init(ServletConfig servletConfig) throws ServletException 
    {
	super.init(servletConfig);
	System.out.println("SOAPBodyTestServlet:init (Entering)");
	SOAP_Util.doServletInit(servletConfig);
	System.out.println("SOAPBodyTestServlet:init (Leaving)");
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res)
                               throws ServletException, IOException 
    {
	TestUtil.logTrace("doGet");
	dispatch(req, res);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
                               throws ServletException, IOException 
    {
	TestUtil.logTrace("doPost");
	SOAP_Util.doServletPost(req, res);
	doGet(req, res);
    }

    private void addBodyElementTest1(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addBodyElementTest1");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap body element to the soap body
            TestUtil.logMsg("Add Name SOAPBodyElement to SOAPBody object");
	    Name name = envelope.createName("GetLastTradePrice",
                        	"ztrade", "http://wombat.ztrade.com");
            bodye = body.addBodyElement(name);

	    TestUtil.logMsg("Validating SOAPBodyElement object creation ...");
	    if (bodye == null) {
		TestUtil.logErr("SOAPBodyElement is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPBodyElement was created");
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addBodyElementTest2(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addBodyElementTest2");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap body element to the soap body
            TestUtil.logMsg("Add QName SOAPBodyElement to SOAPBody object");
	    QName name = new QName("http://wombat.ztrade.com", 
			"GetLastTradePrice", "ztrade");
            bodye = body.addBodyElement(name);

	    TestUtil.logMsg("Validating SOAPBodyElement object creation ...");
	    if (bodye == null) {
		TestUtil.logErr("SOAPBodyElement is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPBodyElement was created");
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addFaultTest1(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addFaultTest1");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
            TestUtil.logMsg("Add SOAPFault to SOAPBody object");
            fault = body.addFault();

	    TestUtil.logMsg("Validating SOAPFault object creation ...");
	    if (fault == null) {
		TestUtil.logErr("SOAPFault is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault was created");
		TestUtil.logMsg("SOAPFault = " + fault);
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addFaultTest2(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addFaultTest2");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
	    Name name = envelope.createName("Server", prefix, uri);
            TestUtil.logMsg("Add Name object SOAPFault to SOAPBody object");
            fault = body.addFault(name, "This is a Server fault");

	    TestUtil.logMsg("Validating SOAPFault object creation ...");
	    if (fault == null) {
		TestUtil.logErr("SOAPFault is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault was created");
		TestUtil.logMsg("SOAPFault = " + fault);
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addFaultTest3(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addFaultTest3");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
	    Name name = envelope.createName("Server", prefix, uri);
            TestUtil.logMsg("Add Name object SOAPFault to SOAPBody object with Locale");
	    Locale l = new Locale("en", "US");
            fault = body.addFault(name, "This is a Server fault", l);

	    TestUtil.logMsg("Validating SOAPFault object creation ...");
	    if (fault == null) {
		TestUtil.logErr("SOAPFault is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault was created");
		TestUtil.logMsg("SOAPFault = " + fault);
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addFaultTest4(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addFaultTest4");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
            TestUtil.logMsg("Add QName object SOAPFault to SOAPBody object");
	    QName name = new QName(uri, "Server", prefix);
            fault = body.addFault(name, "This is a Server fault");

	    TestUtil.logMsg("Validating SOAPFault object creation ...");
	    if (fault == null) {
		TestUtil.logErr("SOAPFault is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault was created");
		TestUtil.logMsg("SOAPFault = " + fault);
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addFaultTest5(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addFaultTest5");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
            TestUtil.logMsg("Add QName object SOAPFault to SOAPBody object with Locale");
	    QName name = new QName(uri, "Server", prefix);
	    Locale l = new Locale("en", "US");
            fault = body.addFault(name, "This is a Server fault", l);

	    TestUtil.logMsg("Validating SOAPFault object creation ...");
	    if (fault == null) {
		TestUtil.logErr("SOAPFault is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault was created");
		TestUtil.logMsg("SOAPFault = " + fault);
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void getFaultTest(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("getFaultTest");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a soap fault to the soap body
            TestUtil.logMsg("Add SOAPFault fault1 to SOAPBody object");
            fault1 = body.addFault();

	    // Get soap fault from the soap body
            TestUtil.logMsg("Get SOAPFault fault2 from SOAPBody object");
            fault2 = body.getFault();

	    TestUtil.logMsg(
		"Validating SOAPFault fault1 and fault2 equality ...");
	    if (fault1 == null || fault2 == null) {
		TestUtil.logErr("SOAPFault fault1 or fault2 is null");
		pass = false;
	    } else if (!(fault1 instanceof SOAPFault) || 
			!(fault2 instanceof SOAPFault)) {
		TestUtil.logErr(
		    "SOAPFault fault1 or fault2 not instance of SOAPFault");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPFault fault1 was created");
		TestUtil.logMsg("SOAPFault fault2 was created");
		TestUtil.logMsg("SOAPFault fault1 = " + fault1);
		TestUtil.logMsg("SOAPFault fault2 = " + fault2);
		if(!fault1.equals(fault2)) {
		    TestUtil.logErr(
			"SOAPFault fault1 and fault2 are not equal");
		    pass = false;
		}
	    }

	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void hasFaultTest(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("hasFaultTest");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Test if soap body has a soap fault
            TestUtil.logMsg("Test that SOAPBody does not have a SOAPFault");
            if(body.hasFault()) {
		TestUtil.logErr("SOAPBody has a fault (unexpected)");
		pass = false;
	    } else {
		TestUtil.logMsg(
		    "SOAPBody does not have a SOAPFault (expected)");
	    }

	    // Now add a soap fault to the soap body
            TestUtil.logMsg("Add SOAPFault to SOAPBody object");
            fault = body.addFault();

	    // Test if soap body has a soap fault
            TestUtil.logMsg("Test that SOAPBody does have a SOAPFault");
            if(body.hasFault()) {
		TestUtil.logMsg("SOAPBody has a fault (expected)");
	    } else {
		TestUtil.logErr(
		    "SOAPBody does not have a SOAPFault (unexpected)");
		pass = false;
	    }

	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void addDocumentTest(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("addDocumentTest");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a document to the soap body
            TestUtil.logMsg("Add Document to SOAPBody object");
            Document document = null;
            org.w3c.dom.Document myDomDocument = makeDocument();
            SOAPBodyElement sbe = null;
            if (myDomDocument == null) { 
               pass = false;
            } else {
               sbe = body.addDocument(myDomDocument);
	       SOAP_Util.dumpSOAPMessage(msg);
            }
	    TestUtil.logMsg("Validating addDocument object creation ...");
	    if (sbe == null) {
		TestUtil.logErr("SOAPBodyElement is null");
		pass = false;
	    } else {
		TestUtil.logMsg("SOAPBodyElement was created");
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private Document makeDocument() {
        
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        } catch (Exception e) {
            TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
            return null;
        }
        DOMImplementation domImpl = docBuilder.getDOMImplementation();
        DocumentType docType = domImpl.createDocumentType("root", "//Test/addDocument", null);
        Document document = domImpl.createDocument(null, "root", docType);
        return document;
   }

    private void extractContentAsDocumentTest1(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("extractContentAsDocumentTest1");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();

	try {
	    setup();

	    // Add a child soap element to the soap body
	    QName qname1 = new QName("http://wombat.ztrade.com", 
				"GetLastTradePrice", "ztrade");
	    TestUtil.logMsg("Qname1=" + qname1);
            TestUtil.logMsg("Add child soap element QName1 to the SOAPBody");
	    body.addChildElement(qname1);
	    SOAP_Util.dumpSOAPMessage(msg);

	    // Extract soap body content as a DOM document
	    TestUtil.logMsg("Extract SOAPBody content as a DOM Document");
	    Document document = body.extractContentAsDocument();

	    TestUtil.logMsg("Validate that a DOM Document was returned");
	    if (document == null) {
		TestUtil.logErr("Document is null");
		pass = false;
	    } else {
		TestUtil.logMsg("DOM Document was created");
		TestUtil.logMsg("Get the Element from the DOM Document");
		Element element = document.getDocumentElement();
		TestUtil.logMsg("Now get the Element Name");
		String elementName = element.getTagName();
		TestUtil.logMsg("Element Name=" + elementName);
	    }

	    TestUtil.logMsg("Retreive the children of the SOAPBody (should be none)");
	    Iterator i = body.getChildElements();
	    int count = SOAP_Util.getIteratorCount(i);
	    if(count != 0) {
                TestUtil.logErr("Wrong iterator count returned of " +
                    count + ", expected 0");
                TestUtil.logErr("The child soap element was not removed");
                pass = false;
            } 
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}
	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }

    private void extractContentAsDocumentTest2(HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException 
    {
	TestUtil.logTrace("extractContentAsDocumentTest2");
	Properties resultProps = new Properties();
	boolean pass = true;

	res.setContentType("text/plain");
	PrintWriter out = res.getWriter();
	try {
	    setup();

	    // Add a 2 child elements to the soap body
	    QName qname1 = new QName("http://wombat.ztrade.com", 
				"GetLastTradePrice", "ztrade");
	    QName qname2 = new QName("foo");
	    TestUtil.logMsg("Qname1=" + qname1);
	    TestUtil.logMsg("Qname2=" + qname2);
            TestUtil.logMsg("Add child soap element QName1 to the SOAPBody");
	    body.addChildElement(qname1);
            TestUtil.logMsg("Add another child soap element QName2 to the SOAPBody");
	    body.addChildElement(qname2);
	    SOAP_Util.dumpSOAPMessage(msg);
	    TestUtil.logMsg("The SOAPBody content cannot be extraced " +
			"if more than 1 child element");
	    try {
	        // Extract soap body content as a DOM document
	        TestUtil.logMsg("Extract SOAPBody content as a DOM Document");
	        TestUtil.logMsg("Expect a SOAPException to be thrown");
	        body.extractContentAsDocument();
	        TestUtil.logErr("Did not throw expected SOAPException");
		pass = false;
	    } catch(SOAPException e) {
	        TestUtil.logMsg("Caught expected SOAPException");
	    }
	} catch(Exception e) {
	    TestUtil.logErr("Exception: " + e);
            TestUtil.printStackTrace(e);
	    pass = false;
	}

	// Send response object and test result back to client
	if(pass)
            resultProps.setProperty("TESTRESULT", "pass");
	else
            resultProps.setProperty("TESTRESULT", "fail");
        resultProps.list(out);
    }
}
