Package extensions.wsrm

Source Code of extensions.wsrm.AckService$MessageRecord

/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Axis" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package extensions.wsrm;

import org.apache.axis.MessageContext;
import org.apache.axis.AxisFault;
import org.apache.axis.client.Call;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.message.PrefixedQName;
import org.apache.axis.message.MessageElement;
import org.apache.axis.handlers.BasicHandler;

import javax.xml.namespace.QName;
import java.util.*;

public class AckService extends BasicHandler implements RMConstants {
    static RetryGuy myRetryGuy = null;

    /**
     * Wake up every three seconds, and scan all active sequences to see
     * if any messages need to be resent (no ack in 20 seconds).
     */
    class RetryGuy implements Runnable {
        public void run() {
            while (true) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                Iterator i = sequences.values().iterator();
                while (i.hasNext()) {
                    MySequence seq = (MySequence)i.next();
                    synchronized (seq.activeMessages) {
                        Iterator msgs = seq.activeMessages.iterator();
                        while (msgs.hasNext()) {
                            MessageRecord msg = (MessageRecord)msgs.next();
                            if (msg.timestamp < (new Date().getTime() - 20000)) {
                                try {
                                    resendMsg(msg, seq.destination);
                                } catch (Exception e) {
                                    e.printStackTrace()//To change body of catch statement use Options | File Templates.
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    class MySequence {
        String id;
        String destination;

        int currentMsgNum = 1;

        // My queue of active messages, indexed by sequence number
        LinkedList activeMessages = new LinkedList();
    }

    class MessageRecord {
        int sequenceNumber;
        long timestamp = new Date().getTime();
        SOAPEnvelope env;
    }

    void resendMsg(MessageRecord msg, String destination) throws Exception {
        System.out.println("Resending : dest = " + destination + ", msg " + msg.sequenceNumber);
       
        Call call = new Call(destination);
        call.setProperty("OneWay", Boolean.TRUE);
        call.invoke(msg.env);
        msg.timestamp = new Date().getTime();
    }

    Map sequences = new HashMap();

    public void invoke(MessageContext msgContext) throws AxisFault {
        processAck(msgContext.getRequestMessage().getSOAPEnvelope());
    }

    public void processAck(SOAPEnvelope req) throws AxisFault
    {
        SOAPHeaderElement header = req.getHeaderByName(NS_URI_WSRM, "SequenceAcknowledgement");
        if (header == null)
            return// Fault?

        Iterator i = header.getChildElements(new PrefixedQName(NS_URI_WSU, "Identifier", null));
        if (!i.hasNext()) {
            // return fault
            throw new AxisFault("WSRM.Fault", "Missing identifier in Sequence", null, null);
        }

        MessageElement el = (MessageElement)i.next();
        String id = el.getValue();
        MySequence seq = (MySequence)sequences.get(id);
        if (seq == null) {
            // Acknowledging a sequence I don't know about...
            throw new AxisFault("WSRM.UnknownSequence", "Don't recognize ack of sequence '" + id + "'", null, null);
        }

        i = header.getChildElements(new PrefixedQName(NS_URI_WSRM, "AcknowledgementRange", null));
        while (i.hasNext()) {
            el = (MessageElement)i.next();
            String val = el.getAttributeValue("Upper");
            int upper = Integer.parseInt(val);
            val = el.getAttributeValue("Lower");
            int lower = Integer.parseInt(val);
            acknowledgeRange(seq, lower, upper);
        }

        header.setProcessed(true);

        header = req.getHeaderByName(NS_URI_WSA, "From");
        if (header != null) {
            header.setProcessed(true);
        }

        header = req.getHeaderByName(NS_URI_WSA, "To");
        if (header != null) {
            header.setProcessed(true);
        }

        header = req.getHeaderByName(NS_URI_WSA, "MessageID");
        if (header != null) {
            header.setProcessed(true);
        }

        header = req.getHeaderByName(NS_URI_WSA, "Action");
        if (header != null) {
            header.setProcessed(true);
        }
    }

    /**
     * Process an acknowledgement range.  Remove every matching message from
     * our resend queue.
     *
     * @param seq the sequence we're dealing with
     * @param min the lowest messageID that has been ack'ed
     * @param max the highest messageID that has been ack'ed
     */
    public void acknowledgeRange(MySequence seq, int min, int max) {
        LinkedList activeMessages = seq.activeMessages;
        synchronized (activeMessages) {
            for (int i = 0; i < activeMessages.size(); i++) {
                MessageRecord curMsg = (MessageRecord)activeMessages.get(i);
                if (min <= curMsg.sequenceNumber && max >= curMsg.sequenceNumber) {
                    System.out.println("Removed msg #" + curMsg.sequenceNumber);
                    activeMessages.remove(i);
                    i--;
                }
            }
        }
    }

    /**
     * Take a SOAP envelope that we want to send in a particular sequence,
     * and decorate it appropriately with all the WS-RM headers.
     *
     * @param env the envelope
     * @param toAddr the destination address
     * @param fromAddr the origination address (can be anonymous - see spec)
     * @param identifier the sequence identifier
     * @param isLast true if this is the last message in the sequence
     * @param skip cheesy extra parameter to tell the engine to skip a sequence
     *             number for testing purposes
     * @throws Exception
     */
    public void doit(SOAPEnvelope env,
                     String toAddr,
                     String fromAddr,
                     String identifier,
                     boolean isLast,
                     boolean skip) throws Exception {
        MySequence myseq = (MySequence)sequences.get(identifier);
        if (myseq == null) {
            // New one
            myseq = new MySequence();
            myseq.id = identifier;
            myseq.destination = toAddr;
            sequences.put(identifier, myseq);
        }

        int curMsgNum = myseq.currentMsgNum++;
        if (skip) {
            curMsgNum = myseq.currentMsgNum++;
        }
        Integer seq = new Integer(curMsgNum);
        String myAddr = fromAddr;

        SOAPHeaderElement header =
                new SOAPHeaderElement(SEQUENCE_QNAME.getNamespaceURI(),
                                      SEQUENCE_QNAME.getLocalPart());
        MessageElement el;

        el = new MessageElement(IDENTIFIER_QNAME, identifier);
        header.addChild(el);

        el = new MessageElement(MSGNUM_QNAME, seq);
        header.addChild(el);
        if (isLast) {
            el = new MessageElement(NS_URI_WSRM, "LastMessage");
            header.addChild(el);
        }

        env.addHeader(header);

        header = new SOAPHeaderElement(NS_URI_WSA, "Action", PING_URI);
        header.setMustUnderstand(true);
        env.addHeader(header);

        header = new SOAPHeaderElement(NS_URI_WSA, "From");
        header.setMustUnderstand(true);
        el = new MessageElement(new QName(NS_URI_WSA, "Address"), myAddr);
        header.addChild(el);
        env.addHeader(header);

        header = new SOAPHeaderElement(NS_URI_WSA, "To", toAddr);
        header.setMustUnderstand(true);
        env.addHeader(header);

        header = new SOAPHeaderElement(NS_URI_WSA, "MessageID", ReliableMessagingHandler.generateNewMsgID());
        header.setMustUnderstand(true);
        env.addHeader(header);

        MessageRecord msgRec = new MessageRecord();
        msgRec.env = env;
        msgRec.sequenceNumber = curMsgNum;
        myseq.activeMessages.add(msgRec);

        // Tack on any piggybacked acks I have for this guy...
        Iterator seqs = ReliableMessagingHandler.sequences.values().iterator();
        while (seqs.hasNext()) {
            Sequence s = (Sequence)seqs.next();
            if (s.endpoint.equals(toAddr)) {
                ReliableMessagingHandler.generateAck(env, s);
            }
        }

        synchronized (this) {
            if (myRetryGuy == null) {
                myRetryGuy = new RetryGuy();
                new Thread(myRetryGuy).start();
            }
        }
    }
}
TOP

Related Classes of extensions.wsrm.AckService$MessageRecord

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.