org.apache.synapse.format.hessian.HessianMessageBuilder Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.synapse.format.hessian;
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.OMText;
import org.apache.axis2.AxisFault;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.transport.base.BaseConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.transport.nhttp.NhttpConstants;
import org.apache.synapse.util.SynapseBinaryDataSource;
import javax.activation.DataHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
/**
* Enables a message encoded using the Hessian binary protocol to be received by axis2/synapse
* and this builds the HessianDataSource to represent the hessian message inside the SOAP info-set
*
* @see org.apache.axis2.builder.Builder
* @see org.apache.synapse.util.SynapseBinaryDataSource
*/
public class HessianMessageBuilder implements Builder {
private static final Log log = LogFactory.getLog(HessianMessageBuilder.class);
/**
* Returns an OMElement from a Hessian encoded message
*
* @param inputStream stream containing the Hessian message to be built
* @param contentType content type of the message
* @param messageContext message to which the hessian message has to be attached
* @return OMElement containing Hessian data handler keeping the message
* @throws AxisFault in case of a failure in building the hessian message
*
* @see org.apache.axis2.builder.Builder#processDocument(java.io.InputStream,
* String, org.apache.axis2.context.MessageContext)
*/
public OMElement processDocument(final InputStream inputStream, final String contentType,
final MessageContext messageContext) throws AxisFault {
if (log.isDebugEnabled()) {
log.debug("Start building the hessian message in to a HessianDataSource");
}
OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace ns = factory.createOMNamespace(HessianConstants.HESSIAN_NAMESPACE_URI,
HessianConstants.HESSIAN_NS_PREFIX);
OMElement element = factory.createOMElement(
HessianConstants.HESSIAN_ELEMENT_LOCAL_NAME, ns);
try {
Parameter synEnv = messageContext.getConfigurationContext().getAxisConfiguration()
.getParameter(SynapseConstants.SYNAPSE_ENV);
PushbackInputStream pis = detectAndMarkMessageFault(messageContext, inputStream);
DataHandler dataHandler;
if (synEnv != null && synEnv.getValue() != null) {
dataHandler = new DataHandler(new SynapseBinaryDataSource(pis, contentType,
(SynapseEnvironment) synEnv.getValue()));
} else {
// add Hessian data inside a data handler
dataHandler = new DataHandler(new SynapseBinaryDataSource(pis, contentType));
}
OMText textData = factory.createOMText(dataHandler, true);
element.addChild(textData);
// indicate that message faults shall be handled as http 200
messageContext.setProperty(NhttpConstants.FAULTS_AS_HTTP_200, NhttpConstants.TRUE);
} catch (IOException e) {
String msg = "Unable to create the HessianDataSource";
log.error(msg, e);
throw new AxisFault(msg, e);
}
if (log.isDebugEnabled()) {
log.debug("Building the hessian message using HessianDataSource is successful");
}
return element;
}
/**
* Reads the first four bytes of the inputstream to detect whether the message represents a
* fault message. Once a fault message has been detected, a property used to mark fault messages
* is stored in the Axis2 message context. The implementaton uses a PushbackInputStream to be
* able to put those four bytes back at the end of processing.
*
* @param messageContext the Axis2 message context
* @param inputStream the inputstream to read the Hessian message
*
* @return the wrapped (pushback) input stream
*
* @throws IOException if an I/O error occurs
*/
private PushbackInputStream detectAndMarkMessageFault(final MessageContext messageContext,
final InputStream inputStream) throws IOException {
int bytesToRead = 4;
PushbackInputStream pis = new PushbackInputStream(inputStream, bytesToRead);
byte[] headerBytes = new byte[bytesToRead];
int n = pis.read(headerBytes);
// checking fourth byte for fault marker
if (n == bytesToRead) {
if (headerBytes[bytesToRead - 1] == HessianConstants.HESSIAN_V1_FAULT_IDENTIFIER
|| headerBytes[bytesToRead - 1] == HessianConstants.HESSIAN_V2_FAULT_IDENTIFIER) {
messageContext.setProperty(BaseConstants.FAULT_MESSAGE, SynapseConstants.TRUE);
if (log.isDebugEnabled()) {
log.debug("Hessian fault detected, marking in Axis2 message context");
}
}
pis.unread(headerBytes);
} else if (n > 0) {
byte[] bytesRead = new byte[n];
System.arraycopy(headerBytes, 0, bytesRead, 0, n);
pis.unread(bytesRead);
}
return pis;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy