/*
* Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.carbon.mediator.transform;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.AxisFault;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.util.xpath.SynapseXPath;
import org.jaxen.JaxenException;
import org.milyn.payload.JavaResult;
public class Output {
public static final String ACTION_REPLACE = "replace";
public static final String ACTION_ADD_CHILD = "child";
public static final String ACTION_ADD_SIBLING = "sibling";
public final static String AXIOMPAYLOADNS = "http://ws.apache.org/commons/ns/payload";
public final static QName TEXTELT = new QName(AXIOMPAYLOADNS, "text", "ax");
private SmooksMediator.TYPES type = SmooksMediator.TYPES.XML;
private SynapseXPath expression = null;
private String property = null;
private String action = null;
public void process(ByteArrayOutputStream outputStream,
MessageContext synCtx, SynapseLog synLog, JavaResult result) throws AxisFault {
ByteArrayInputStream inputStream = null;
if (outputStream != null && outputStream.size() > 0) {
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
}
if (inputStream != null && type == SmooksMediator.TYPES.XML) {
try {
StAXOMBuilder builder = new StAXOMBuilder(inputStream);
// create the transformed element
OMElement transformedElement = builder.getDocumentElement();
if (property != null) {
synCtx.setProperty(property, transformedElement);
} else if (expression != null) {
Object targetObj = expression.selectSingleNode(synCtx);
if (targetObj instanceof OMElement) {
OMElement targetElem = (OMElement) targetObj;
insertElement(transformedElement, targetElem, synLog);
} else if (targetObj instanceof OMText) {
OMText targetText = (OMText) targetObj;
Object targetParent = targetText.getParent();
if (targetParent instanceof OMElement) {
targetText.detach();
((OMElement) targetParent).addChild(transformedElement);
}
} else {
handleException("Invalid Target object to be enrich.", synLog);
}
} else {
setXMLPayload(synCtx, transformedElement);
}
} catch (XMLStreamException e) {
handleException("Error creating the parser form the result of smooks", synLog, e);
} catch (JaxenException e) {
handleException("Error evaluating the Xpath expression: " + expression, synLog, e);
}
} else if (inputStream != null && type == SmooksMediator.TYPES.TEXT) {
if (expression != null) {
Object targetObj = null;
try {
targetObj = expression.selectSingleNode(synCtx);
} catch (JaxenException e) {
handleException("Error evaluating the XPath: " + expression, synLog, e);
}
if (targetObj instanceof OMElement) {
((OMElement) targetObj).setText(byteArrayIStoString(inputStream));
} else if (targetObj instanceof OMText) {
OMText targetText = (OMText) targetObj;
if (targetText.getParent() != null) {
Object parent = targetText.getParent();
if (parent instanceof OMElement) {
((OMElement) parent).setText(byteArrayIStoString(inputStream));
}
}
} else {
handleException("Invalid Target object to be enrich.", synLog);
}
} else if (property != null) {
synCtx.setProperty(property, byteArrayIStoString(inputStream));
} else {
setTextPayload(synCtx, byteArrayIStoString(inputStream));
}
} else if (type == SmooksMediator.TYPES.JAVA) {
if (property != null) {
synCtx.setProperty(property, result);
}
}
}
public String byteArrayIStoString(ByteArrayInputStream is) {
int size = is.available();
char[] theChars = new char[size];
byte[] bytes = new byte[size];
is.read(bytes, 0, size);
for (int i = 0; i < size;) {
theChars[i] = (char) (bytes[i++] & 0xff);
}
return new String(theChars);
}
private void insertElement(OMNode source, OMElement e, SynapseLog synLog) {
if (action.equals(ACTION_REPLACE)) {
boolean isInserted = false;
if (source instanceof OMElement) {
e.insertSiblingAfter(source);
isInserted = true;
} else if (source instanceof OMText) {
e.setText(((OMText) source).getText());
} else {
handleException("Invalid Source object to be inserted.", synLog);
}
if (isInserted) {
e.detach();
}
} else if (action.equals(ACTION_ADD_CHILD)) {
if (source instanceof OMElement) {
e.addChild(source);
}
} else if (action.equals(ACTION_ADD_SIBLING)) {
if (source instanceof OMElement) {
e.insertSiblingAfter(source);
}
}
}
public SmooksMediator.TYPES getType() {
return type;
}
public SynapseXPath getExpression() {
return expression;
}
public String getProperty() {
return property;
}
public String getAction() {
return action;
}
public void setType(SmooksMediator.TYPES type) {
this.type = type;
}
public void setExpression(SynapseXPath expression) {
this.expression = expression;
}
public void setProperty(String property) {
this.property = property;
}
public void setAction(String action) {
this.action = action;
}
private void handleException(String message, SynapseLog log) {
log.error(message);
throw new SynapseException(message);
}
private void handleException(String message, SynapseLog log, Exception e) {
log.error(message);
throw new SynapseException(message, e);
}
public static void setXMLPayload(MessageContext synCtx, OMElement element) throws AxisFault {
SOAPEnvelope envelope = synCtx.getEnvelope();
SOAPEnvelope newElement = getNewSOAPEnvelope(envelope);
newElement.getBody().addChild(element);
synCtx.setEnvelope(newElement);
}
public static void setTextPayload(MessageContext synCtx, String text) throws AxisFault {
SOAPEnvelope envelope = synCtx.getEnvelope();
OMFactory fac = envelope.getOMFactory();
OMElement textElt = envelope.getOMFactory().createOMElement(TEXTELT);
OMText textNode = fac.createOMText(text);
textElt.addChild(textNode);
setXMLPayload(synCtx, textElt);
}
/**
* New SOAPEnvelope is created with namespace & header elements of envelope
* @param envelope Envelope from MessageContext
* @return New SOAPEnvelope
*/
public static SOAPEnvelope getNewSOAPEnvelope(SOAPEnvelope envelope) {
OMNamespace namespace = envelope.getNamespace();
String nsURI = namespace.getNamespaceURI();
SOAPFactory soapFactory = null;
if (nsURI.equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
soapFactory = OMAbstractFactory.getSOAP11Factory();
} else if (nsURI.equals(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
soapFactory = OMAbstractFactory.getSOAP12Factory();
}
if (soapFactory != null) {
SOAPEnvelope new_envelope = soapFactory.createSOAPEnvelope();
SOAPHeader header = envelope.getHeader();
if (header!=null) {
soapFactory.createSOAPHeader(new_envelope);
SOAPHeader new_header = new_envelope.getHeader();
for (Iterator<?> itr =header.getChildElements(); itr.hasNext();) {
OMElement element = (OMElement) itr.next();
new_header.addChild(element);
}
}
soapFactory.createSOAPBody(new_envelope);
return new_envelope;
}
return null;
}
}