/*
* Copyright 2013, The Sporting Exchange Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.betfair.testing.utils.cougar.helpers;
import com.betfair.testing.utils.cougar.beans.HttpCallBean;
import org.apache.xerces.dom.AttributeMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import java.util.Map;
public class SOAPRequestBuilder {
private String nameSpace = null;
private static final String SECURITY_NAME_SPACE = "http://www.betfair.com/security/";
/*
* Construct the SOAPMessage based on xml doc and CallBean
*
* @param document
* @param httpCallBean
* @return
*/
public SOAPMessage buildSOAPRequest(Document document,
HttpCallBean httpCallBean) {
nameSpace = httpCallBean.getNameSpace();
if (nameSpace == null || nameSpace.equals("")) {
throw new RuntimeException(
"Cannot create SOAP message using the following name space : "
+ nameSpace);
}
// Construct SOAPMessage
MessageFactory mf;
try {
mf = MessageFactory.newInstance();
SOAPMessage message = mf.createMessage();
//add headers here
MimeHeaders hd = message.getMimeHeaders();
hd.addHeader("X-Forwarded-For", httpCallBean.getIpAddress());
//SCR: 103 Trace Me testing
//hd.addHeader("X-Trace-Me", "true");
//
if(httpCallBean.getHeaderParams()!=null)
{
for (String key: httpCallBean.getHeaderParams().keySet())
{
hd.addHeader(key, httpCallBean.getHeaderParams().get(key));
}
}
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("bas", nameSpace);
// generate header
generateSoapHeader(envelope, httpCallBean);
// generate body
generateSOAPBody(envelope, document);
message.saveChanges();
// TODO write this to the logs
//Uncomment for debug
/*try
{
System.out.println("\n Soap Request:\n");
message.writeTo(System.out);
System.out.println();
}
catch (IOException e) {
throw new UtilityException(e);
}*/
return message;
} catch (SOAPException e) {
throw new RuntimeException(e);
}
}
private void generateSOAPBody(SOAPEnvelope envelope, Document document) throws SOAPException {
org.w3c.dom.NodeList childNodes = document.getChildNodes();
// Construct the body
SOAPBody body = envelope.getBody();
// for each child node in the message, get name and value
for (int i = 0; i < childNodes.getLength(); i++) {
Node aNode = (Node) childNodes.item(i);
iterate(envelope, aNode, body);
}
}
public void generateSoapHeader(SOAPEnvelope envelope,
HttpCallBean httpCallBean) throws SOAPException {
// Remove existing null header
envelope.getHeader().detachNode();
// add new soap header
SOAPHeader soapHeader = envelope.addHeader();
// header are not set then break
if (httpCallBean.getAuthority() == null
&& httpCallBean.getSubject() == null
&& httpCallBean.getAuthCredentials()== null) {
return;
}
// create element for headers
if (httpCallBean.getAuthority() != null) {
String authority = httpCallBean.getAuthority();
/*soapHeader.addChildElement(
envelope.createName("Authentication", "", secNameSpace))
.setTextContent(authority);*/
soapHeader.addChildElement(
envelope.createName("X-Authentication", "", SECURITY_NAME_SPACE))
.setValue(authority);
}
if (httpCallBean.getAuthCredentials() != null) {
Map<String, String> credentials = httpCallBean.getAuthCredentials();
SOAPElement credElement = soapHeader.addChildElement(
envelope.createName("Credentials", "", SECURITY_NAME_SPACE));
for(Map.Entry<String,String> entry: credentials.entrySet()){
credElement.addChildElement(entry.getKey(), "", SECURITY_NAME_SPACE).setValue(entry.getValue());
}
}
if (httpCallBean.getSubject() != null) {
String subject = httpCallBean.getSubject();
/*soapHeader.addChildElement(
envelope.createName("Subject", "", secNameSpace))
.setTextContent(subject);*/
soapHeader.addChildElement(
envelope.createName("Subject", "", SECURITY_NAME_SPACE))
.setValue(subject);
}
}
/*
* Recursive loop to find children and add to body, if attributes exist then adds those
*
* @param envelope
* @param node
* @param parentElement
* @throws SOAPException
*/
public void iterate(SOAPEnvelope envelope, Node node,
SOAPElement parentElement) throws SOAPException {
// if the node is an element then process it and it's children
if(node instanceof Element){
Element elemt = (Element) node;
String localName = elemt.getNodeName();
SOAPElement newParent = parentElement.addChildElement(localName,"bas", nameSpace);
// If the node has attributes then process them
if(node.hasAttributes()){
AttributeMap map = (AttributeMap) node.getAttributes();
for (int x = 0; x < map.getLength(); x++) {
String name = map.item(x).getNodeName();
newParent.setAttribute(name, map.item(x).getNodeValue());
}
}
org.w3c.dom.NodeList childNodes = node.getChildNodes();
// for each of this nodes children recursively call this method
for (int i = 0; i < childNodes.getLength(); i++) {
iterate(envelope, childNodes.item(i), newParent);
}
} else if (node.getNodeType() == Node.TEXT_NODE){ // Node is a text node so add it's value
String value = node.getNodeValue();
if (value==null) {
parentElement.addTextNode("");
} else {
parentElement.addTextNode(value);
}
}
// Else is some other kind of node which can be ignored
}
}