package com.nortal.jroad.endpoint;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import org.apache.axis.Message;
import org.springframework.xml.transform.StringResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.nortal.jroad.endpoint.helper.AxisContextHelper;
import com.nortal.jroad.enums.XRoadProtocolVersion;
import com.nortal.jroad.model.BeanXTeeMessage;
import com.nortal.jroad.model.XTeeAttachment;
import com.nortal.jroad.model.XTeeMessage;
import com.nortal.jroad.util.AxisUtil;
import com.nortal.jroad.util.SOAPUtil;
/**
* Axis marshalling implementation
*
* @author Dmitri Danilkin
* @param
* <P>
* Request class
* @param <V> Response class
*/
// TODO Lauri: see tuleks veel üle vaadata. Kas on üldse kusagil kastusel? Axis 1.4 on üsna vana vb saab ära kaotada?
public abstract class AbstractXTeeAxisEndpoint<P, V> extends AbstractXTeeBaseEndpoint {
private Class<P> paringKehaClass;
@Resource(name = "axisContextHelper")
private AxisContextHelper contextHelper;
@Override
@SuppressWarnings("unchecked")
protected void invokeInternalEx(XTeeMessage<Document> request,
XTeeMessage<Element> response,
SOAPMessage requestMessage,
SOAPMessage responseMessage) throws Exception {
requestMessage.getSOAPHeader().detachNode();
Node bodyNode;
if (XRoadProtocolVersion.V2_0 == version) {
bodyNode = SOAPUtil.getNodeByXPath(requestMessage.getSOAPBody(), "//keha");
} else {
bodyNode = requestMessage.getSOAPBody();
}
Node reqNode = bodyNode.getParentNode();
NodeList nl = bodyNode.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node curNode = nl.item(i);
reqNode.appendChild(curNode.cloneNode(true));
}
reqNode.removeChild(bodyNode);
// Since Axis needs the XML as a String a transformation is required.
StringResult result = new StringResult();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(requestMessage.getSOAPPart().getEnvelope()), result);
Message axisMessage = new Message(result.toString());
// The context is very important, as the binding stub creates all the type bindings for proper unmarshalling.
axisMessage.setMessageContext(getContextHelper().getMessageContext());
// Adding the attachments is needed to handle "href" attributes where the data is in an attachment.
for (Iterator<AttachmentPart> i = requestMessage.getAttachments(); i.hasNext();) {
axisMessage.addAttachmentPart(i.next());
}
XTeeMessage<P> axisRequestMessage = new BeanXTeeMessage<P>(request.getHeader(),
(P) axisMessage.getSOAPEnvelope().getFirstBody().getObjectValue(getParingKehaClass()),
request.getAttachments());
XTeeMessage<V> axisResponseMessage =
new BeanXTeeMessage<V>(response.getHeader(), null, new ArrayList<XTeeAttachment>());
invoke(axisRequestMessage, axisResponseMessage);
V responseBean = axisResponseMessage.getContent();
// If response is null we return <keha/>, otherwise some marshalling needs to be done.
if (responseBean != null) {
String responseXml = AxisUtil.serialize(responseBean);
Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(responseXml.getBytes("UTF-8")));
Node parent = response.getContent().getParentNode();
parent.removeChild(response.getContent());
parent.appendChild(parent.getOwnerDocument().importNode(doc.getFirstChild(), true));
}
}
public Class<P> getParingKehaClass() {
return paringKehaClass;
}
public void setParingKehaClass(Class<P> paringKehaClass) {
this.paringKehaClass = paringKehaClass;
}
/**
* Overridde this method if you require access to the header or attachments
*
* @param request
* @param response
* @throws Exception
*/
protected void invoke(XTeeMessage<P> request, XTeeMessage<V> response) throws Exception {
response.setContent(invokeBean(request.getContent()));
}
/**
* Override this method if you only require access to the message contents
*
* @param requestBean
* @return an object, which can be serialized by Axis
* @throws IOException
*/
protected V invokeBean(P requestBean) throws IOException {
throw new IllegalStateException("You must override either the 'invokeBean' or the 'invoke' method!");
}
public AxisContextHelper getContextHelper() {
return contextHelper;
}
public void setContextHelper(AxisContextHelper contextHelper) {
this.contextHelper = contextHelper;
}
}