package org.apache.synapse.config.xml; import org.apache.axiom.om.*; import org.apache.axiom.om.util.DetachableInputStream; import org.apache.axiom.om.xpath.AXIOMXPath; import org.apache.commons.logging.Log; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseException; import org.apache.synapse.core.axis2.Axis2MessageContext; import org.apache.synapse.transport.passthru.PassThroughConstants; import org.apache.synapse.transport.passthru.Pipe; import org.apache.synapse.transport.passthru.config.PassThroughConfiguration; import org.apache.synapse.transport.passthru.util.RelayUtils; import org.apache.synapse.util.streaming_xpath.custom.components.ParserComponent; import org.apache.synapse.util.xpath.DOMSynapseXPathNamespaceMap; import org.apache.synapse.util.xpath.SynapseJsonPath; import org.apache.synapse.util.xpath.SynapseXPath; import org.jaxen.JaxenException; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.Iterator; public abstract class SynapsePath extends AXIOMXPath { public static final String X_PATH = "X_PATH"; public static final String JSON_PATH = "JSON_PATH"; private String pathType = null; public DOMSynapseXPathNamespaceMap domNamespaceMap = new DOMSynapseXPathNamespaceMap(); public String expression; public int bufferSizeSupport = 1024 * 8; public Log log; public boolean contentAware; public SynapsePath(OMElement element, String xpathExpr, Log log) throws JaxenException { super(element, xpathExpr); this.pathType = inferPathType(xpathExpr); this.log = log; } public SynapsePath(String xpathExpr, Log log) throws JaxenException { super(xpathExpr); this.pathType = inferPathType(xpathExpr); this.log = log; } public SynapsePath(String path, String pathType, Log log) throws JaxenException { super("/"); this.expression = path; this.pathType = inferPathType(path); this.log = log; } private String inferPathType(String expression) { if (expression.startsWith("json-eval(")) { return X_PATH; } else { return JSON_PATH; } } public SynapsePath(OMAttribute attribute, Log log) throws JaxenException { super(attribute); this.pathType = X_PATH; this.log = log; } public String getExpression() { return expression; } public void setExpression(String expression) { this.expression = expression; } public String getPathType() { return this.pathType; } public void setPathType(String pathType) { this.pathType = pathType; } public boolean isContentAware() { return this.contentAware; } @Override public String toString() { if(this.pathType.equals(JSON_PATH)) { return "json-eval(" + this.getExpression().toString() + ")"; } else { return this.getExpression().toString(); } } public abstract String stringValueOf(MessageContext synCtx); public void handleException(String msg, Throwable e) { log.error(msg, e); throw new SynapseException(msg, e); } public void addNamespacesForFallbackProcessing(OMElement element) { OMElement currentElem = element; while (currentElem != null) { Iterator it = currentElem.getAllDeclaredNamespaces(); while (it.hasNext()) { OMNamespace n = (OMNamespace) it.next(); // Exclude the default namespace as explained in the Javadoc // above if (n != null && !"".equals(n.getPrefix())) { ParserComponent.addToNameSpaceMap(n.getPrefix(), n.getNamespaceURI()); domNamespaceMap.addNamespace(n.getPrefix(), n.getNamespaceURI()); } } OMContainer parent = currentElem.getParent(); // if the parent is a document element or parent is null ,then // return if (parent == null || parent instanceof OMDocument) { return; } if (parent instanceof OMElement) { currentElem = (OMElement) parent; } } } public InputStream getMessageInputStreamPT(org.apache.axis2.context.MessageContext context) throws IOException { Pipe pipe= (Pipe) context.getProperty(PassThroughConstants.PASS_THROUGH_PIPE); if (pipe != null && context.getProperty(PassThroughConstants.BUFFERED_INPUT_STREAM) != null){ BufferedInputStream bufferedInputStream = (BufferedInputStream) context.getProperty(PassThroughConstants.BUFFERED_INPUT_STREAM); try{ bufferedInputStream.reset(); bufferedInputStream.mark(0); }catch (Exception e) { //just ignore the error } return bufferedInputStream; } if (pipe != null) { BufferedInputStream bufferedInputStream = new BufferedInputStream(pipe.getInputStream()); // Multiplied it by two because we always need a bigger read-limit than the buffer size. bufferedInputStream.mark(PassThroughConfiguration.getInstance().getIOBufferSize() * 2); OutputStream resetOutStream = pipe.resetOutputStream(); ReadableByteChannel inputChannel = Channels.newChannel(bufferedInputStream); WritableByteChannel outputChannel = Channels.newChannel(resetOutStream); if (!isMessageBiggerThanBuffer(inputChannel, outputChannel)) { //TODO:need to find a proper solution try { bufferedInputStream.reset(); context.setProperty(PassThroughConstants.BUFFERED_INPUT_STREAM, bufferedInputStream); RelayUtils.buildMessage(context); } catch (Exception e) { log.error("Error while building message", e); } return null; } try { bufferedInputStream.reset(); } catch (Exception e) { // just ignore the error } pipe.setRawSerializationComplete(true); return bufferedInputStream; } return null; } public boolean isMessageBiggerThanBuffer(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException { bufferSizeSupport = PassThroughConfiguration.getInstance().getIOBufferSize(); // Added one to make sure temp buffer is always bigger than the io_buffer final ByteBuffer buffer = ByteBuffer.allocate(bufferSizeSupport + 1); while (src.read(buffer) != -1) { if (bufferSizeSupport < buffer.position()) { return false; } } buffer.flip(); dest.write(buffer); return true; } }