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; } }