Package org.apache.sandesha.client

Source Code of org.apache.sandesha.client.RMSender

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.apache.sandesha.client;

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.client.Call;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.components.uuid.UUIDGen;
import org.apache.axis.components.uuid.UUIDGenFactory;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.commons.logging.Log;
import org.apache.sandesha.Constants;
import org.apache.sandesha.IStorageManager;
import org.apache.sandesha.RMMessageContext;
import org.apache.sandesha.RMReport;
import org.apache.sandesha.util.PolicyLoader;
import org.apache.sandesha.util.RMMessageCreator;
import org.apache.sandesha.ws.rm.RMHeaders;

/**
* In the client side of axis there is a flexibility of using custom sender to send SOAP messages.
* However axis's use of senders are mainly to handle transport related funtionalites.
* <code>RMSender</code>has to be used by the users who wish to use WS-ReliableMessaging capability
* in their clients.<P>
* The main funtionality of <code>RMSender</code> is to insert the messages coming from client and
* also the generated messages to the <code>SandeshaQueue</code>.
* If the message coming in from the client is request/response in nature then <code>RMSender</code>
* will wait polling <code>SandeshaQueue</code> till it gets an appropriate response.
* Due to the above reason, if the client is sending several messages
* (of request/response in nature) to be sent reliably, they will be sent reliably by
* <b>Sandesha</b> however the client will wait at each message till it gets the response, to send
* the next. To avoid this client can use callbacks provided by axis
* in <code>org.apache.axis.client.async</code> package.
*/
public class RMSender extends BasicHandler {

    private IStorageManager storageManager;
    private static final Log log = LogFactory.getLog(RMSender.class.getName());
    private final UUIDGen uuidGen = UUIDGenFactory.getUUIDGen();
    private static Boolean lock = new Boolean(false);

    /**
     * This is the main method that is invoked by the axis engine. This method will add the reqest
     * messages from the client to <code>SandeshaQueue</code> with the generated messages such as
     * Create Sequence message and Terminate Sequence message.
     *
     * @param msgContext
     * @throws AxisFault
     */

    public void invoke(MessageContext msgContext) throws AxisFault {

        storageManager = new ClientStorageManager();

        try {
            RMMessageContext reqMsgCtx = null;
            String tempSeqID = null;

            reqMsgCtx = getRMMessageContext(msgContext);

            tempSeqID = reqMsgCtx.getSequenceID();

            reqMsgCtx = processRequestMessage(reqMsgCtx, reqMsgCtx.getSync());

            if (reqMsgCtx.isHasResponse()) {
                RMMessageContext responseMessageContext = null;
                long startingTime = System.currentTimeMillis();
                long inactivityTimeOut = PolicyLoader.getInstance().getInactivityTimeout();

                while (responseMessageContext == null) {
                    synchronized (lock) {
                        responseMessageContext =
                                checkTheQueueForResponse(tempSeqID, reqMsgCtx.getMessageID());
                        if ((System.currentTimeMillis() - startingTime) >= inactivityTimeOut) {
                            reqMsgCtx.getCtx().stopClientByForce();
                        }
                        Thread.sleep(Constants.CLIENT_RESPONSE_CHECKING_INTERVAL);
                    }
                }

                //setting RMReport;
                if (responseMessageContext != null) {
                    String oldSeqId = reqMsgCtx.getOldSequenceID();
                    if (oldSeqId != null) {
                        Call call = (Call) reqMsgCtx.getCtx().getCallMap().get(reqMsgCtx.getOldSequenceID());

                        if (call != null) {
                            RMReport report = (RMReport) call.getProperty(Constants.ClientProperties.REPORT);
                            report.incrementReturnedMsgCount();
                        }
                    }
                }

                //We need these steps to filter all addressing and rm related headers.
                Message resMsg = responseMessageContext.getMsgContext().getRequestMessage();
                RMHeaders.removeHeaders(resMsg.getSOAPEnvelope());
                AddressingHeaders addHeaders = new AddressingHeaders(resMsg.getSOAPEnvelope(), null, true, true, false, null);
                msgContext.setResponseMessage(new Message(resMsg.getSOAPPartAsString()));

            } else {
                msgContext.setResponseMessage(null);
            }

        } catch (Exception ex) {
            log.error(ex);

            throw new AxisFault(ex.getMessage());

        }
    }

    /**
     * This method will process the first request message.
     *
     * @param reqRMMsgContext
     * @param sync
     * @return
     * @throws Exception
     */
    private RMMessageContext processRequestMessage(RMMessageContext reqRMMsgContext,
                                                   boolean sync) throws Exception {
        synchronized (lock) {

            if (!storageManager.isSequenceExist(reqRMMsgContext.getSequenceID())) {
                String msgID = Constants.UUID + uuidGen.nextUUID();
                String offerID = null;
                if (reqRMMsgContext.isHasResponse() && reqRMMsgContext.isSendOffer()) {
                    offerID = Constants.UUID + uuidGen.nextUUID();
                    storageManager.addRequestedSequence(offerID);
                    storageManager.addOffer(msgID, offerID);
                }

                RMMessageContext createSeqRMMsgContext = RMMessageCreator.createCreateSeqMsg(reqRMMsgContext, Constants.CLIENT, msgID, offerID);
                storageManager.addOutgoingSequence(reqRMMsgContext.getSequenceID());
                storageManager.setTemporaryOutSequence(reqRMMsgContext.getSequenceID(),
                        createSeqRMMsgContext.getMessageID());

                createSeqRMMsgContext.setSync(sync);
                storageManager.addCreateSequenceRequest(createSeqRMMsgContext);
                processMessage(reqRMMsgContext);

            } else {
                processMessage(reqRMMsgContext);
            }

        }


        return reqRMMsgContext;
    }

    private RMMessageContext processMessage(RMMessageContext reqRMMsgContext)
            throws Exception {
        if (reqRMMsgContext.isLastMessage()) {
            storageManager.insertTerminateSeqMessage(RMMessageCreator.createTerminateSeqMsg(reqRMMsgContext, Constants.CLIENT));
        }
        RMMessageContext serviceRequestMsg = RMMessageCreator.createServiceRequestMessage(reqRMMsgContext);
        storageManager.insertOutgoingMessage(serviceRequestMsg);
        return reqRMMsgContext;
    }

    private RMMessageContext checkTheQueueForResponse(String sequenceId, String reqMessageID) {
        return storageManager.checkForResponseMessage(sequenceId, reqMessageID);
    }

    private RMMessageContext getRMMessageContext(MessageContext msgCtx) throws Exception {
        //Get a copy of the MessageContext. This is required when sending multiple messages from
        //one call object
        MessageContext newMsgContext = RMMessageCreator.cloneMsgContext(msgCtx);
        RMMessageContext requestMesssageContext = new RMMessageContext();
        Call call = (Call) newMsgContext.getProperty(MessageContext.CALL);

        requestMesssageContext = ClientPropertyValidator.validate(call);
        requestMesssageContext.setOutGoingAddress((String) msgCtx.getProperty(MessageContext.TRANS_URL));
        requestMesssageContext.setMsgContext(newMsgContext);
        return requestMesssageContext;
    }


}


TOP

Related Classes of org.apache.sandesha.client.RMSender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.