org.wso2.carbon.inbound.endpoint.protocol.jms.JMSInjectHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.inbound.endpoint.protocol.jms.JMSInjectHandler.java

Source

/*
 *  Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 Inc. 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.wso2.carbon.inbound.endpoint.protocol.jms;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.TextMessage;

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.util.UUIDGenerator;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.builder.BuilderUtil;
import org.apache.axis2.builder.SOAPBuilder;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.format.DataSourceMessageBuilder;
import org.apache.axis2.transport.TransportUtils;
import org.apache.commons.io.input.AutoCloseInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.SynapseException;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.inbound.InboundEndpoint;
import org.apache.synapse.inbound.InboundEndpointConstants;
import org.apache.synapse.mediators.MediatorFaultHandler;
import org.apache.synapse.mediators.base.SequenceMediator;
import org.apache.synapse.transport.customlogsetter.CustomLogSetter;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.inbound.endpoint.protocol.generic.GenericConstants;
import org.wso2.carbon.inbound.endpoint.protocol.jms.factory.CachedJMSConnectionFactory;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;

/**
 * 
 * JMSInjectHandler use to mediate the received JMS message
 * 
 */
public class JMSInjectHandler {

    private static final Log log = LogFactory.getLog(JMSInjectHandler.class);

    private String injectingSeq;
    private String onErrorSeq;
    private boolean sequential;
    private SynapseEnvironment synapseEnvironment;
    private Properties jmsProperties;
    //Following is used when using reply destination
    private Connection connection;
    private Destination replyDestination;

    public JMSInjectHandler(String injectingSeq, String onErrorSeq, boolean sequential,
            SynapseEnvironment synapseEnvironment, Properties jmsProperties) {
        this.injectingSeq = injectingSeq;
        this.onErrorSeq = onErrorSeq;
        this.sequential = sequential;
        this.synapseEnvironment = synapseEnvironment;
        this.jmsProperties = jmsProperties;

    }

    /**
     * Invoke the mediation logic for the passed message
     * */
    public boolean invoke(Object object, String name) throws SynapseException {

        Message msg = (Message) object;
        try {
            org.apache.synapse.MessageContext msgCtx = createMessageContext();
            msgCtx.setProperty("inbound.endpoint.name", name);
            InboundEndpoint inboundEndpoint = msgCtx.getConfiguration().getInboundEndpoint(name);
            CustomLogSetter.getInstance().setLogAppender(inboundEndpoint.getArtifactContainerName());
            String contentType = msg.getJMSType();

            if (contentType == null || contentType.trim().equals("")) {
                String contentTypeProperty = jmsProperties.getProperty(JMSConstants.CONTENT_TYPE_PROPERTY);
                if (contentTypeProperty != null) {
                    contentType = msg.getStringProperty(contentTypeProperty);
                }
            } else {
                msgCtx.setProperty(JMSConstants.JMS_MESSAGE_TYPE, contentType);
            }

            if (contentType == null || contentType.trim().equals("")) {
                contentType = jmsProperties.getProperty(JMSConstants.CONTENT_TYPE);
            }
            if (log.isDebugEnabled()) {
                log.debug("Processed JMS Message of Content-type : " + contentType);
            }
            MessageContext axis2MsgCtx = ((org.apache.synapse.core.axis2.Axis2MessageContext) msgCtx)
                    .getAxis2MessageContext();
            //setting transport headers
            axis2MsgCtx.setProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS,
                    JMSUtils.getTransportHeaders(msg, axis2MsgCtx));
            // set the JMS Message ID as the Message ID of the MessageContext
            try {
                msgCtx.setMessageID(msg.getJMSMessageID());
                String jmsCorrelationID = msg.getJMSCorrelationID();
                if (jmsCorrelationID != null && !jmsCorrelationID.isEmpty()) {
                    msgCtx.setProperty(JMSConstants.JMS_COORELATION_ID, jmsCorrelationID);
                } else {
                    msgCtx.setProperty(JMSConstants.JMS_COORELATION_ID, msg.getJMSMessageID());
                }
            } catch (JMSException ignore) {
                log.warn("Error getting the COORELATION ID from the message.");
            }

            // Handle dual channel
            Destination replyTo = msg.getJMSReplyTo();
            if (replyTo != null) {
                msgCtx.setProperty(SynapseConstants.IS_INBOUND, true);
                // Create the cachedJMSConnectionFactory with the existing
                // connection
                CachedJMSConnectionFactory cachedJMSConnectionFactory = new CachedJMSConnectionFactory(
                        jmsProperties, connection);
                String strUserName = jmsProperties.getProperty(JMSConstants.PARAM_JMS_USERNAME);
                String strPassword = jmsProperties.getProperty(JMSConstants.PARAM_JMS_PASSWORD);
                JMSReplySender jmsReplySender = new JMSReplySender(replyTo, cachedJMSConnectionFactory, strUserName,
                        strPassword);
                msgCtx.setProperty(InboundEndpointConstants.INBOUND_ENDPOINT_RESPONSE_WORKER, jmsReplySender);
            } else if (replyDestination != null) {
                msgCtx.setProperty(SynapseConstants.IS_INBOUND, true);
                // Create the cachedJMSConnectionFactory with the existing
                // connection
                CachedJMSConnectionFactory cachedJMSConnectionFactory = new CachedJMSConnectionFactory(
                        jmsProperties, connection);
                String strUserName = jmsProperties.getProperty(JMSConstants.PARAM_JMS_USERNAME);
                String strPassword = jmsProperties.getProperty(JMSConstants.PARAM_JMS_PASSWORD);
                JMSReplySender jmsReplySender = new JMSReplySender(replyDestination, cachedJMSConnectionFactory,
                        strUserName, strPassword);
                msgCtx.setProperty(InboundEndpointConstants.INBOUND_ENDPOINT_RESPONSE_WORKER, jmsReplySender);
            }

            // Determine the message builder to use
            Builder builder;
            if (contentType == null) {
                log.debug("No content type specified. Using SOAP builder.");
                builder = new SOAPBuilder();
            } else {
                int index = contentType.indexOf(';');
                String type = index > 0 ? contentType.substring(0, index) : contentType;
                builder = BuilderUtil.getBuilderFromSelector(type, axis2MsgCtx);
                if (builder == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("No message builder found for type '" + type + "'. Falling back to SOAP.");
                    }
                    builder = new SOAPBuilder();
                }
            }
            OMElement documentElement = null;
            // set the message payload to the message context
            try {
                if (msg instanceof TextMessage) {
                    String message = ((TextMessage) msg).getText();
                    InputStream in = new AutoCloseInputStream(new ByteArrayInputStream(message.getBytes()));
                    documentElement = builder.processDocument(in, contentType, axis2MsgCtx);
                } else if (msg instanceof BytesMessage) {
                    if (builder instanceof DataSourceMessageBuilder) {
                        documentElement = ((DataSourceMessageBuilder) builder).processDocument(
                                new BytesMessageDataSource((BytesMessage) msg), contentType, axis2MsgCtx);
                    } else {
                        documentElement = builder.processDocument(new BytesMessageInputStream((BytesMessage) msg),
                                contentType, axis2MsgCtx);
                    }
                } else if (msg instanceof MapMessage) {
                    documentElement = convertJMSMapToXML((MapMessage) msg);
                }
            } catch (Exception ex) {
                // Handle message building error
                log.error("Error while building the message", ex);
                msgCtx.setProperty(SynapseConstants.ERROR_CODE, GenericConstants.INBOUND_BUILD_ERROR);
                msgCtx.setProperty(SynapseConstants.ERROR_MESSAGE, ex.getMessage());
                SequenceMediator faultSequence = getFaultSequence(msgCtx, inboundEndpoint);
                faultSequence.mediate(msgCtx);

                if (isRollback(msgCtx)) {
                    return false;
                }
                return true;
            }

            // Setting JMSXDeliveryCount header on the message context
            try {
                int deliveryCount = msg.getIntProperty("JMSXDeliveryCount");
                msgCtx.setProperty(JMSConstants.DELIVERY_COUNT, deliveryCount);
            } catch (NumberFormatException nfe) {
                if (log.isDebugEnabled()) {
                    log.debug("JMSXDeliveryCount is not set in the received message");
                }
            }

            // Inject the message to the sequence.
            msgCtx.setEnvelope(TransportUtils.createSOAPEnvelope(documentElement));
            if (injectingSeq == null || injectingSeq.equals("")) {
                log.error("Sequence name not specified. Sequence : " + injectingSeq);
                return false;
            }
            SequenceMediator seq = (SequenceMediator) synapseEnvironment.getSynapseConfiguration()
                    .getSequence(injectingSeq);
            if (seq != null) {
                if (log.isDebugEnabled()) {
                    log.debug("injecting message to sequence : " + injectingSeq);
                }
                if (!seq.isInitialized()) {
                    seq.init(synapseEnvironment);
                }
                SequenceMediator faultSequence = getFaultSequence(msgCtx, inboundEndpoint);
                MediatorFaultHandler mediatorFaultHandler = new MediatorFaultHandler(faultSequence);
                msgCtx.pushFaultHandler(mediatorFaultHandler);

                if (!synapseEnvironment.injectInbound(msgCtx, seq, sequential)) {
                    return false;
                }
            } else {
                log.error("Sequence: " + injectingSeq + " not found");
            }

            if (isRollback(msgCtx)) {
                return false;
            }
        } catch (SynapseException se) {
            throw se;
        } catch (Exception e) {
            log.error("Error while processing the JMS Message", e);
            throw new SynapseException("Error while processing the JMS Message", e);
        }
        return true;
    }

    private boolean isRollback(org.apache.synapse.MessageContext msgCtx) {
        // First check for rollback property from synapse context
        Object rollbackProp = msgCtx.getProperty(JMSConstants.SET_ROLLBACK_ONLY);
        if (rollbackProp != null) {
            if ((rollbackProp instanceof Boolean && ((Boolean) rollbackProp))
                    || (rollbackProp instanceof String && Boolean.valueOf((String) rollbackProp))) {
                return true;
            }
            return false;
        }
        // Then from axis2 context - This is for make it consistent with JMS Transport config parameters
        rollbackProp = (((Axis2MessageContext) msgCtx).getAxis2MessageContext())
                .getProperty(JMSConstants.SET_ROLLBACK_ONLY);
        if ((rollbackProp instanceof Boolean && ((Boolean) rollbackProp))
                || (rollbackProp instanceof String && Boolean.valueOf((String) rollbackProp))) {
            return true;
        }
        return false;
    }

    /**
     * 
     * @param message
     *            JMSMap message
     * @return XML representation of JMS Map message
     */
    public static OMElement convertJMSMapToXML(MapMessage message) {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace jmsMapNS = OMAbstractFactory.getOMFactory().createOMNamespace(JMSConstants.JMS_MAP_NS, "");
        OMElement jmsMap = fac.createOMElement(JMSConstants.JMS_MAP_ELEMENT_NAME, jmsMapNS);
        try {
            Enumeration names = message.getMapNames();
            while (names.hasMoreElements()) {
                String nextName = names.nextElement().toString();
                String nextVal = message.getString(nextName);
                OMElement next = fac.createOMElement(nextName.replace(" ", ""), jmsMapNS);
                next.setText(nextVal);
                jmsMap.addChild(next);
            }
        } catch (JMSException e) {
            log.error("Error while processing the JMS Map Message. " + e.getMessage());
        }
        return jmsMap;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public void setReplyDestination(Destination replyDestination) {
        this.replyDestination = replyDestination;
    }

    /**
     * Create the initial message context for the file
     * */
    private org.apache.synapse.MessageContext createMessageContext() {
        org.apache.synapse.MessageContext msgCtx = synapseEnvironment.createMessageContext();
        //Need to set this to build the message
        msgCtx.setProperty(SynapseConstants.INBOUND_JMS_PROTOCOL, true);
        MessageContext axis2MsgCtx = ((org.apache.synapse.core.axis2.Axis2MessageContext) msgCtx)
                .getAxis2MessageContext();
        axis2MsgCtx.setServerSide(true);
        axis2MsgCtx.setMessageID(UUIDGenerator.getUUID());
        PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
        axis2MsgCtx.setProperty(MultitenantConstants.TENANT_DOMAIN, carbonContext.getTenantDomain());
        // There is a discrepency in what I thought, Axis2 spawns a nes threads
        // to
        // send a message is this is TRUE - and I want it to be the other way
        msgCtx.setProperty(MessageContext.CLIENT_API_NON_BLOCKING, true);
        return msgCtx;
    }

    private SequenceMediator getFaultSequence(org.apache.synapse.MessageContext synCtx, InboundEndpoint endpoint) {
        SequenceMediator faultSequence = null;
        if (endpoint.getOnErrorSeq() != null) {
            faultSequence = (SequenceMediator) synCtx.getSequence(endpoint.getOnErrorSeq());
        }

        if (faultSequence == null) {
            faultSequence = (SequenceMediator) synCtx.getFaultSequence();
        }

        return faultSequence;
    }

}