org.codehaus.wadi.group.impl.AbstractDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.wadi.group.impl.AbstractDispatcher.java

Source

/**
 *
 * Copyright 2003-2005 Core Developers Network Ltd.
 *
 *  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.codehaus.wadi.group.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.wadi.group.Address;
import org.codehaus.wadi.group.Dispatcher;
import org.codehaus.wadi.group.DispatcherContext;
import org.codehaus.wadi.group.Envelope;
import org.codehaus.wadi.group.EnvelopeInterceptor;
import org.codehaus.wadi.group.MessageExchangeException;
import org.codehaus.wadi.group.Quipu;
import org.codehaus.wadi.group.QuipuException;
import org.codehaus.wadi.group.ServiceEndpoint;

/**
 * The portable aspects of a Dispatcher implementation
 *
 * @version $Revision: 1595 $
 */
public abstract class AbstractDispatcher implements Dispatcher {
    protected final Log log = LogFactory.getLog(getClass());
    protected final ThreadPool _executor;
    protected final Map<String, Quipu> rvMap = new ConcurrentHashMap<String, Quipu>();
    protected final List<EnvelopeInterceptor> interceptors;
    private final DispatcherContext context;
    private final EnvelopeDispatcherManager inboundEnvelopeDispatcher;

    public AbstractDispatcher(ThreadPool executor) {
        _executor = executor;

        interceptors = new CopyOnWriteArrayList<EnvelopeInterceptor>();
        inboundEnvelopeDispatcher = new BasicEnvelopeDispatcherManager(this, _executor);
        context = new BasicDispatcherContext();
    }

    public AbstractDispatcher() {
        this(new PooledExecutorAdapter(10));
    }

    public DispatcherContext getContext() {
        return context;
    }

    public void addInterceptor(EnvelopeInterceptor interceptor) {
        interceptor.registerLoopbackEnvelopeListener(this);
        interceptors.add(interceptor);
    }

    public void removeInterceptor(EnvelopeInterceptor interceptor) {
        interceptors.remove(interceptor);
        interceptor.unregisterLoopbackEnvelopeListener(this);
    }

    public List<EnvelopeInterceptor> getInterceptors() {
        return new ArrayList<EnvelopeInterceptor>(interceptors);
    }

    public void register(ServiceEndpoint msgDispatcher) {
        inboundEnvelopeDispatcher.register(msgDispatcher);
    }

    public void unregister(ServiceEndpoint msgDispatcher, int nbAttemp, long delayMillis) {
        inboundEnvelopeDispatcher.unregister(msgDispatcher, nbAttemp, delayMillis);
    }

    public final void onEnvelope(Envelope envelope) {
        try {
            envelope = onInboundEnvelope(envelope);
        } catch (MessageExchangeException e) {
            log.error("See nested", e);
        }
        if (null == envelope) {
            return;
        }

        doOnEnvelope(envelope);
    }

    protected void doOnEnvelope(Envelope envelope) {
        inboundEnvelopeDispatcher.onEnvelope(envelope);
    }

    class SimpleCorrelationIDFactory {

        protected int count;

        public synchronized String create() {
            return Integer.toString(count++);
        }

    }

    protected final SimpleCorrelationIDFactory _factory = new SimpleCorrelationIDFactory();

    public void addRendezVousEnvelope(Envelope envelope) {
        String targetCorrelationId = envelope.getTargetCorrelationId();
        if (null == targetCorrelationId) {
            throw new IllegalStateException("No targetCorrelationId");
        }
        Quipu rv = rvMap.get(targetCorrelationId);
        if (null == rv) {
            if (log.isTraceEnabled()) {
                log.trace("no one waiting for [" + targetCorrelationId + "]");
            }
        } else {
            if (log.isTraceEnabled()) {
                log.trace("successful correlation [" + targetCorrelationId + "]");
            }
            rv.putResult(envelope);
        }
    }

    public Quipu newRendezVous(int numLlamas) {
        return setRendezVous(_factory.create(), numLlamas);
    }

    public Envelope attemptRendezVous(Quipu rv, long timeout) throws MessageExchangeException {
        Collection messages = attemptMultiRendezVous(rv, timeout);
        if (messages.size() > 1) {
            throw new MessageExchangeException("[" + messages.size() + "] result messages. Expected only one.");
        }
        return (Envelope) messages.iterator().next();
    }

    public Collection attemptMultiRendezVous(Quipu rv, long timeout) throws MessageExchangeException {
        Collection response = null;
        try {
            do {
                try {
                    long startTime = System.currentTimeMillis();
                    if (rv.waitFor(timeout)) {
                        response = rv.getResults();
                        long elapsedTime = System.currentTimeMillis() - startTime;
                        if (log.isTraceEnabled()) {
                            log.trace("successful message exchange within timeframe (" + elapsedTime + "<" + timeout
                                    + " millis) {" + rv + "}");
                        }
                    } else {
                        log.debug("unsuccessful message exchange within timeframe (" + timeout + " millis) {" + rv
                                + "}", new Exception());
                    }
                } catch (InterruptedException e) {
                    log.debug("waiting for response - interruption ignored");
                } catch (QuipuException e) {
                    throw new MessageExchangeException(e);
                }
            } while (Thread.interrupted());
        } finally {
            rvMap.remove(rv.getCorrelationId());
        }
        if (null == response) {
            throw new MessageExchangeException("No correlated messages received within [" + timeout + "]ms");
        }
        return response;
    }

    public Envelope exchangeSend(Address to, Serializable body, long timeout) throws MessageExchangeException {
        return exchangeSend(to, body, timeout, null);
    }

    public void reply(Envelope envelope, Serializable body) throws MessageExchangeException {
        Envelope reply = createEnvelope();
        reply.setPayload(body);
        reply(envelope, reply);
    }

    public void reply(Envelope request, Envelope reply) throws MessageExchangeException {
        Address from = getCluster().getLocalPeer().getAddress();
        reply.setReplyTo(from);
        Address to = request.getReplyTo();
        reply.setAddress(to);
        String incomingCorrelationId = request.getSourceCorrelationId();
        reply.setTargetCorrelationId(incomingCorrelationId);
        EnvelopeHelper.setAsReply(reply);
        send(to, reply);
    }

    public void send(Address to, Serializable body) throws MessageExchangeException {
        try {
            Envelope envelope = createEnvelope();
            envelope.setReplyTo(getCluster().getLocalPeer().getAddress());
            envelope.setAddress(to);
            envelope.setPayload(body);
            send(to, envelope);
        } catch (Exception e) {
            log.error("problem sending " + body, e);
        }
    }

    public void send(Address target, Quipu quipu, Serializable pojo) throws MessageExchangeException {
        try {
            Envelope envelope = createEnvelope();
            envelope.setReplyTo(getCluster().getLocalPeer().getAddress());
            envelope.setAddress(target);
            envelope.setPayload(pojo);
            envelope.setQuipu(quipu);
            send(target, envelope);
        } catch (Exception e) {
            log.error("problem sending " + pojo, e);
        }
    }

    public void send(Address source, Address target, Quipu quipu, Serializable pojo)
            throws MessageExchangeException {
        Envelope envelope = createEnvelope();
        envelope.setReplyTo(source);
        envelope.setAddress(target);
        envelope.setQuipu(quipu);
        envelope.setPayload(pojo);
        send(target, envelope);
    }

    public final void send(Address target, Envelope envelope) throws MessageExchangeException {
        envelope = onOutboundEnvelope(envelope);
        if (null == envelope) {
            return;
        }

        doSend(target, envelope);
    }

    public Envelope exchangeSend(Address target, Serializable pojo, long timeout, String targetCorrelationId)
            throws MessageExchangeException {
        Envelope envelope = createEnvelope();
        envelope.setPayload(pojo);
        return exchangeSend(target, envelope, timeout, targetCorrelationId);
    }

    public Envelope exchangeSend(Address target, Envelope envelope, long timeout) throws MessageExchangeException {
        return exchangeSend(target, envelope, timeout, null);
    }

    public Envelope exchangeSend(Address target, Envelope envelope, long timeout, String targetCorrelationId)
            throws MessageExchangeException {
        Address from = getCluster().getLocalPeer().getAddress();
        envelope.setReplyTo(from);
        envelope.setAddress(target);

        Quipu rv = newRendezVous(1);
        envelope.setQuipu(rv);

        if (targetCorrelationId != null) {
            envelope.setTargetCorrelationId(targetCorrelationId);
        }

        send(target, envelope);
        return attemptRendezVous(rv, timeout);
    }

    public void reply(Address from, Address to, String incomingCorrelationId, Serializable body)
            throws MessageExchangeException {
        Envelope envelope = createEnvelope();
        envelope.setReplyTo(from);
        envelope.setAddress(to);
        envelope.setTargetCorrelationId(incomingCorrelationId);
        envelope.setPayload(body);
        EnvelopeHelper.setAsReply(envelope);
        send(to, envelope);
    }

    protected Quipu setRendezVous(String correlationId, int numLlamas) {
        Quipu rv = new Quipu(numLlamas, correlationId);
        rvMap.put(correlationId, rv);
        return rv;
    }

    protected void hook() {
        AbstractCluster.clusterThreadLocal.set(getCluster());
    }

    public ThreadPool getExecutor() {
        return _executor;
    }

    protected abstract void doSend(Address target, Envelope envelope) throws MessageExchangeException;

    protected Envelope onOutboundEnvelope(Envelope envelope) throws MessageExchangeException {
        for (EnvelopeInterceptor interceptor : interceptors) {
            envelope = interceptor.onOutboundEnvelope(envelope);
            if (null == envelope) {
                return null;
            }
        }
        return envelope;
    }

    protected Envelope onInboundEnvelope(Envelope envelope) throws MessageExchangeException {
        for (EnvelopeInterceptor interceptor : interceptors) {
            envelope = interceptor.onInboundEnvelope(envelope);
            if (null == envelope) {
                return null;
            }
        }
        return envelope;
    }

}