All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.messaging.impl.DefaultEndpoint Maven / Gradle / Ivy

/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.messaging.impl;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.coos.messaging.AsyncCallback;
import org.coos.messaging.ConnectingException;
import org.coos.messaging.Consumer;
import org.coos.messaging.Endpoint;
import org.coos.messaging.EndpointException;
import org.coos.messaging.Exchange;
import org.coos.messaging.ExchangePattern;
import org.coos.messaging.InteractionHelper;
import org.coos.messaging.Link;
import org.coos.messaging.Message;
import org.coos.messaging.Notification;
import org.coos.messaging.Plugin;
import org.coos.messaging.Processor;
import org.coos.messaging.ProcessorException;
import org.coos.messaging.Producer;
import org.coos.messaging.Service;
import org.coos.messaging.SubscriptionFilter;
import org.coos.messaging.util.ExecutorService;
import org.coos.messaging.util.Executors;
import org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
import org.coos.messaging.util.URIHelper;
import org.coos.messaging.util.URIProtocolHelper;
import org.coos.messaging.util.UuidGenerator;
import org.coos.messaging.util.UuidHelper;
import org.coos.module.CommonConstants;
import org.coos.module.EdgeLCMMessageFactory;
import org.coos.module.EdgeMessageProperties;
import org.coos.module.LCMEdgeMessageFactory;

/**
 * @author Knut Eilif Husa, Tellu AS
 * @author anders
 */
public abstract class DefaultEndpoint extends DefaultProcessor implements Endpoint {

    private String uri;
    private String endpointUuid;
    private Plugin plugin;
    private Vector aliases = new Vector();
    private Hashtable outLinks = new Hashtable();
    private Vector services = new Vector();
    private Hashtable exchanges = new Hashtable();
    private Hashtable callbacks = new Hashtable();
    private UuidGenerator uuidGenerator = new UuidGenerator();
    private int maxPoolSize = DEFAULT_MAX_POOL_SIZE;
    protected ExecutorService threadPool;
    private long timeout;
    protected Vector deferQueue = new Vector();
    protected Log log = LogFactory.getLog(this.getClass().getName());


    private String endpointState = STATE_READY;
    private Hashtable childStates = new Hashtable();
    protected boolean heartbeat;
    protected Timer timer;

    protected DefaultEndpoint() {
    }

    public DefaultEndpoint(String uri, Processor processor) {
        // This is for test purposes since this constructor only is called in
        // tests
        this.uri = uri;
        outLinks.put("coos", processor);
        threadPool = Executors.newThreadPool(2);
        uuidGenerator = new UuidGenerator("xId-" + ((getName() == null) ? getEndpointUuid() : getName()));
        setEndpointState(Endpoint.STATE_RUNNING);

    }

    public void setName(String name) {
        if (name != null && !UuidHelper.isUuid(name)) {
            aliases.addElement(name);
        }
        super.setName(name);
    }

    public Consumer createConsumer() {
        // TODO Auto-generated method stub
        return null;
    }

    public Producer createProducer() {
        // TODO Auto-generated method stub
        return null;
    }

    public String getEndpointUuid() {
        return endpointUuid;
    }

    public void setEndpointUuid(String endpointUuid) {
        this.endpointUuid = endpointUuid;
        log.putMDC("UUID", endpointUuid);
    }

    public String getEndpointState() {
        return endpointState;
    }

    public void setEndpointState(String endpointState) {
        this.endpointState = endpointState;
        if (isStateRunning()) {
            for (int i = 0; i < deferQueue.size(); i++) {
                Message message = (Message) deferQueue.elementAt(i);
                processMessage(message);
            }
            deferQueue.removeAllElements();
        }
    }

    public void setChildEndpointState(String childName, String state) {
        childStates.put(childName, state);
    }

    public String getChildEndpointState(String childName) {
        return (String) childStates.get(childName);
    }

    public void setProperties(Hashtable properties) {
        this.properties = properties;
        String timoutStr = (String) properties.get(PROP_EXCHANGE_TIMEOUT);
        if (timoutStr != null) {
            timeout = Long.parseLong(timoutStr);
        } else {
            timeout = DEFAULT_TIMEOUT;
        }

        maxPoolSize=Integer.parseInt(getProperty(PROP_MAX_POOL_SIZE,String.valueOf(DEFAULT_MAX_POOL_SIZE)));
    }


    public Exchange createExchange() {
        Exchange exchange = new DefaultExchange(new ExchangePattern(ExchangePattern.OutIn));		
        return exchange;
    }

    public Exchange createExchange(ExchangePattern pattern) {
        Exchange exchange = new DefaultExchange(pattern);		
        return exchange;
    }

    public String getEndpointUri() {
        return uri;
    }

    public void setEndpointUri(String endpointUri) {
        this.uri = endpointUri;
        log.putMDC("URI", endpointUri);
    }

    public String createUuid() {
        return uuidGenerator.generateId();
    }

    /**
     * Method that registers endpoint into lifecycle manager.
     * 
     * @throws EndpointException
     *             if registration fails
     */
    private void registerLCM() throws EndpointException {
        // registration to LCM

        boolean failIfError = false;

        String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);

        if (lcmRegReq != null && lcmRegReq.equals("true")) {
            failIfError = true;
        }

        log.info("Registering endpoint: " + uri + " to LifeCycleManager.");
        String pollingInterval=getProperty(PROP_LCM_POLLING_INTERVAL);
        Exchange ex;
        if(pollingInterval==null)
            ex = LCMEdgeMessageFactory.createRegisterEndpointExchange(endpointState, getChildStates(),DEFAULT_LCM_POLLING_INTERVAL);
        else
            ex = LCMEdgeMessageFactory.createRegisterEndpointExchange(endpointState, getChildStates(),Long.parseLong(pollingInterval));
        InteractionHelper helper=new InteractionHelper(this);
        ex=helper.request(LIFE_CYCLE_MANGER_ADDRESS,ex);
        if (ex.getFaultMessage() != null) {
            if (failIfError)
                throw new EndpointException("Registration to LifeCycleManager failed due to :"
                        + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
        } else {
            Message reply = ex.getInBoundMessage();
            if (reply==null || reply.getHeader(Message.MESSAGE_NAME).equals(CommonConstants.REPLY_NACK)) {
                if (failIfError)
                    throw new EndpointException("Registration to lifecycle manager failed");
                // else
                // log.
            }
        }
    }

    private void unRegisterLCM() throws EndpointException {

        // unregistration to LCM
        log.info("UnRegistering endpoint: " + uri + " from LifeCycleManager.");
        InteractionHelper helper=new InteractionHelper(this);
        Exchange ex= LCMEdgeMessageFactory.createUnregisterEndpointExchange();
        ex = helper.request(LIFE_CYCLE_MANGER_ADDRESS, ex);
        if (ex.getFaultMessage() != null) {
            log.info("Endpoint: " + getEndpointUri()
                    + ", Unregistration to LifeCycleManager failed due to: "
                    + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
        }
        else {
            Message reply = ex.getInBoundMessage();
            if (reply==null || reply.getHeader(Message.MESSAGE_NAME).equals(CommonConstants.REPLY_NACK)) {
                log.info("Endpoint: " + getEndpointUri()
                        + ", Unregistration to lifecycle manager failed");
            }
        }

    }


    private void reportChildren() throws EndpointException {
        log.info("Reporting state: " + endpointState + " to LifeCycleManager.");
        Exchange ex=LCMEdgeMessageFactory.createSetChildrenStatesExchange(childStates);
        InteractionHelper helper=new InteractionHelper(this);
        ex=helper.request(LIFE_CYCLE_MANGER_ADDRESS,ex);
        if (ex.getFaultMessage() != null) {
            throw new EndpointException("Children reply to LifeCycleManager failed due to :"
                    + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
        }
        Message reply = ex.getInBoundMessage();
        String signalName = reply.getHeader(Message.MESSAGE_NAME);
        if (signalName.equals(CommonConstants.REPLY_NACK)) {
            throw new EndpointException("Children reply to lifecycle manager failed");
        }
    }

    public void reportState() throws EndpointException {
        boolean failIfError = false;

        String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);

        if (lcmRegReq != null && lcmRegReq.equals("true")) {
            failIfError = true;
        }

        log.info("Sending state: " + getEndpointState() + " to LifeCycleManager.");
        Exchange ex = LCMEdgeMessageFactory.createSetStateExchange(getEndpointState());
        InteractionHelper helper=new InteractionHelper(this);
        ex=helper.request(LIFE_CYCLE_MANGER_ADDRESS,ex);
        if (ex.getFaultMessage() != null) {
            if (failIfError)
                throw new EndpointException("Pushing state to Lifecycle Mangager failed :"
                        + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
        } else {
            Message reply = ex.getInBoundMessage();
            String signalName = reply.getHeader(Message.MESSAGE_NAME);
            if (signalName.equals(CommonConstants.REPLY_NACK)) {
                if (failIfError)
                    throw new EndpointException("Pushing state to Lifecycle Manager failed.");
                // else
                // log.
            }
        }
    }

    public void reportChildState(String childName) throws EndpointException {
        boolean failIfError = false;

        String lcmRegReq = (String) properties.get(PROP_LCM_REGISTRATION_REQUIRED);

        if (lcmRegReq != null && lcmRegReq.equals("true")) {
            failIfError = true;
        }

        String childState = (String) getChildStates().get(childName);

        log.info("Sending state: " + childState + " of child: " + childName + " to LifeCycleManager.");
        Exchange ex= LCMEdgeMessageFactory.createRegisterEndpointChildExchange(childName, childState);
        InteractionHelper helper=new InteractionHelper(this);
        ex=helper.request(LIFE_CYCLE_MANGER_ADDRESS,ex);
        if (ex.getFaultMessage() != null) {
            if (failIfError)
                throw new EndpointException("Pushing child-state to Lifecycle Mangager failed :"
                        + ex.getFaultMessage().getHeader(Message.ERROR_REASON));
        } else {
            Message reply = ex.getInBoundMessage();
            String signalName = reply.getHeader(Message.MESSAGE_NAME);
            if (signalName.equals(CommonConstants.REPLY_NACK)) {
                if (failIfError)
                    throw new EndpointException("Pushing child-state to Lifecycle Manager failed.");
                // else
                // log.
            }
        }
    }



    /**
     * Sync processing of inBound messages
     * 
     * @param exchange
     * @return
     */
    public Exchange processExchange(Exchange exchange) {
        Processor processor = prepareExchange(exchange);
        log.debug("Endpoint: " + uri + ", Processing outgoing exchange: " + exchange);
        if (exchange.getFaultMessage() != null) {
            return exchange;
        }
        synchronized (exchange) {
            try {
                processor.processMessage(exchange.getOutBoundMessage());
            } catch (ProcessorException e) {
                Message fault = new DefaultMessage();
                fault.setReceiverEndpointUri(getEndpointUri());
                fault.setHeader(Message.TYPE_MSG, Message.TYPE_ERROR);
                fault.setHeader(Message.ERROR_REASON, e.getMessage());
                fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
                exchange.setFaultMessage(fault);
                exchange.setException(e);
                log.warn("Endpoint: " + uri + ", Exception processing exchange: " + exchange);
                return exchange;
            }

            ExchangePattern xp = exchange.getPattern();
            if (xp.equals(ExchangePattern.OutIn)||xp.equals(ExchangePattern.RobustOutOnly)) {
                try {
                    exchange.wait(timeout);
                    if (!exchange.isProcessed()) {
                        log.warn("Endpoint: " + uri + ", exchange: "+exchange+" timed out ("+timeout+" ms).");
                        Message fault = new DefaultMessage();
                        fault.setReceiverEndpointUri(getEndpointUri());
                        fault.setHeader(Message.TYPE, Message.TYPE_ERROR);
                        fault.setHeader(Message.ERROR_REASON, "Exchange timeout");
                        fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
                        exchange.setFaultMessage(fault);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return exchange;
    }

    /**
     * Simple method to send a message to a receiver, using a set exchange pattern. Returns the inbound Message object from the used exchange.
     * @param msg
     * @param receiver - coos url of the receiver
     * @param exchangePattern
     * @return
     */
    public Message sendMessage(Message msg, String receiver, String exchangePattern) {
        Exchange e = createExchange(new ExchangePattern(exchangePattern));
        msg.setReceiverEndpointUri(receiver);
        e.setOutBoundMessage(msg);
        Exchange response = processExchange(e);
        return response.getInBoundMessage();
    }

    /**
     * Prepares the exchange before it is processed. This includes checking that
     * sender and receiver adresses are resolved
     * 
     * @param exchange
     *            the exchange
     */
    private Processor prepareExchange(Exchange exchange) {
        try {

            //            if (!isStateRunning()&&!endpointState.equals(STATE_STARTING)) {
            //                throw new EndpointException("Endpoint not able to handle exchanges. Endpoint State is: "
            //                        + endpointState);
            //            }

            String senderUri = exchange.getOutBoundMessage().getSenderEndpointUri();
            URIHelper helper;

            if (senderUri == null || senderUri.equals("")) {
                helper = new URIHelper(uri);
            } else {
                helper = new URIHelper(senderUri);
            }
            helper.setEndpoint(endpointUuid);
            exchange.getOutBoundMessage().setSenderEndpointUri(helper.getEndpointUri());

            String uri = exchange.getOutBoundMessage().getReceiverEndpointUri();

            if(exchange.getExchangeId() == null){
                exchange.setExchangeId(uuidGenerator.generateId());
            }

            ExchangePattern xPattern = exchange.getPattern();
            if (xPattern.equals(ExchangePattern.OutIn) || xPattern.equals(ExchangePattern.RobustOutOnly)) {
                exchanges.put(exchange.getExchangeId(), exchange);
            }

            if(exchange.getPattern().equals(ExchangePattern.InOut)){
                //If this is a reply we search through the message for header values that are to be passed
                //along with the reply
                exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_ID, exchange.getInBoundMessage().getHeader(Message.EXCHANGE_ID));
                Message outMsg = exchange.getOutBoundMessage();
                Message inMsg = exchange.getInBoundMessage();
                Enumeration keys = inMsg.getHeaders().keys();
                while (keys.hasMoreElements()) {
                    String key = (String) keys.nextElement();
                    if(key.startsWith(Message.EXCHANGE_PREFIX)){
                        outMsg.setHeader(key, exchange.getInBoundMessage().getHeader(key));
                    }
                }

            } else {
                exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
            }

            exchange.getOutBoundMessage().setHeader(Message.EXCHANGE_PATTERN, exchange.getPattern().toString());

            if (exchange.getOutBoundMessage().getType() == null) {
                exchange.getOutBoundMessage().setHeader(Message.TYPE, Message.TYPE_MSG);
            }

            if(xPattern.equals(ExchangePattern.RobustOutOnly)){
                long rdTimeout = timeout/2;
                exchange.getOutBoundMessage().setHeader(Message.ROBUST_DELIVERY_TIME, String.valueOf(rdTimeout));
                exchange.getOutBoundMessage().setHeader(Message.ROBUST_DELIVERY_ACK_URI, helper.getEndpointUri());
            }

            String protocol = URIProtocolHelper.getProtocol(uri);

            Processor processor = resolveOutgoingProcessor(protocol);

            if (protocol.startsWith("coos")) {

                helper = new URIHelper(uri);
                exchange.getOutBoundMessage().setReceiverEndpointName(helper.getEndpoint());
                exchange.getOutBoundMessage().setSenderEndpointName(
                        ((getName() == null) ? getEndpointUuid() : getName()));

            }

            return processor;

        } catch (Exception e) {
            e.printStackTrace();
            exchange.setFaultMessage(new DefaultMessage().setHeader(Message.ERROR_REASON, e.getMessage()));
        }

        return null;

    }

    private boolean isStateRunning() {
        if (endpointState.equals(STATE_RUNNING)) {
            return true;
        }
        if (endpointState.equals(STATE_STARTING) || endpointState.equals(STATE_INSTALLED) || endpointState.equals(STATE_PAUSED)
                || endpointState.equals(STATE_READY) || endpointState.equals(STATE_STARTUP_FAILED)
                || endpointState.equals(STATE_UNINNSTALLED) || endpointState.equals(STATE_UPDATING)
                || endpointState.equals(STATE_UPGRADING))
            return false;
        return true;
    }

    protected Processor resolveOutgoingProcessor(String protocol) throws EndpointException {
        Processor processor = (Processor) outLinks.get(protocol);

        if (processor == null) {
            throw new EndpointException("No channel defined for protocol: " + protocol);
        }
        return processor;
    }

    /**
     * Async processing of outbound messages
     * 
     * @param exchange
     * @param callback
     */
    public void processExchange(Exchange exchange, AsyncCallback callback) {
        log.debug("Endpoint: " + uri + ", Processing outgoing exchange: " + exchange);
        Processor processor = prepareExchange(exchange);
        if (exchange.getFaultMessage() != null) {
            callback.processExchange(exchange);
            return;
        }
        exchanges.put(exchange.getExchangeId(), exchange);
        callbacks.put(exchange.getExchangeId(), callback);
        synchronized (exchange) {
            try {
                processor.processMessage(exchange.getOutBoundMessage());
            } catch (ProcessorException e) {
                Message fault = new DefaultMessage();
                fault.setHeader(Message.TYPE_MSG, Message.TYPE_ERROR);
                fault.setHeader(Message.ERROR_REASON, e.getMessage());
                fault.setHeader(Message.EXCHANGE_ID, exchange.getExchangeId());
                fault.setHeader(Message.EXCHANGE_PATTERN, exchange.getPattern().toString());
                processMessage(fault);

            }
        }
    }

    /**
     * Processing of Inbound messages
     * 
     * @param msg
     */
    public void processMessage(Message msg) {

        //if(coContainer != null) 
        msg.setDeserializeClassLoader(coContainer);
        String msgType = msg.getHeader(Message.TYPE);
        if (msgType.equals(Message.TYPE_MSG) || msgType.equals(Message.TYPE_ERROR)) {
            if (msg.getName().equals(Notification.NOTIFY)) {
                msg = new DefaultNotification(msg);
            }
            String xpattern = msg.getHeader(Message.EXCHANGE_PATTERN);
            ExchangePattern xp = new ExchangePattern(xpattern);
            final String xId = msg.getHeader(Message.EXCHANGE_ID);
            final Message retMsg = msg;
            try {
                retMsg.getBody();
            } catch (Exception e) {
                retMsg.setHeader(Message.TYPE, Message.TYPE_ERROR);
                retMsg.setHeader(Message.ERROR_REASON, "Deserialization error: " + e.getMessage());
            }
            Consumer consumer = createConsumer();
            // Error handling
            if (msg.getHeader(Message.TYPE).equals(Message.TYPE_ERROR)) {
                if (exchanges.containsKey(xId)) {
                    final Exchange exchange = (Exchange) exchanges.remove(xId);
                    log.warn("Endpoint: " + uri
                            + ", Processing incoming exchange: " + exchange
                            + ": fault :" + retMsg);

                    exchange.setFaultMessage(retMsg);
                    exchange.setProcessed(true);
                    if (callbacks.containsKey(xId)) {
                        threadPool.execute(new Runnable() {
                            public void run() {
                                // this is an async return
                                AsyncCallback callback = (AsyncCallback) callbacks
                                .remove(xId);
                                callback.processExchange(exchange);
                            }
                        });
                    } else {
                        // this is a sync return
                        // todo when moved to java 1.6 can check if current thread holds lock
                        // New thread is only necessary in that case
                        new Thread(new Runnable() {
                            public void run() {
                                synchronized (exchange) {
                                    exchange.notifyAll();
                                }
                            }
                        }).start();
                    }
                } else {
                    log.warn("Endpoint: " + uri + ", Error message:" + retMsg);
                }

            } else {
                // Message handling
                Exchange exchange = null;
                if (exchanges.containsKey(xId) && !xp.isOutBoundInitiated()) {
                    // this is a return or a message to same endpoint.
                    final Exchange exchange2 = (Exchange) exchanges.remove(xId);
                    log.debug("Endpoint: " + uri
                            + ", Processing incoming exchange: " + exchange2);

                    if(xp.equals(ExchangePattern.InOut)){
                        exchange2.setInBoundMessage(retMsg);
                    }
                    exchange2.setProcessed(true);
                    if (callbacks.containsKey(xId)) {
                        threadPool.execute(new Runnable() {
                            public void run() {
                                // this is an async return
                                AsyncCallback callback = (AsyncCallback) callbacks
                                .remove(xId);
                                callback.processExchange(exchange2);
                            }
                        });
                    } else {
                        // this is a sync return
                        // todo when moved to java 1.6 can check if current thread holds lock
                        // New thread is only necessary in that case
                        new Thread(new Runnable() {
                            public void run() {
                                synchronized (exchange2) {
                                    exchange2.notifyAll();
                                }
                            }
                        }).start();
                    }
                } else if (consumer != null) {
                    if (msg.getHeader(Message.MESSAGE_NAME).equals(EdgeLCMMessageFactory.EDGE_REQUEST_STATE)) {
                        threadPool.execute(new Runnable() {
                            public void run() {
                                try {
                                    reportState();
                                } catch (EndpointException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                        return;
                    } else if (msg.getHeader(Message.MESSAGE_NAME).equals(
                            EdgeLCMMessageFactory.EDGE_REQUEST_CHILD_STATE)) {
                        final String childAddress = (String) msg.getBodyAsProperties().get(
                                EdgeMessageProperties.EDGE_PROP_CHILD_NAME);
                        threadPool.execute(new Runnable() {
                            public void run() {
                                try {
                                    reportChildState(childAddress);
                                } catch (EndpointException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                        return;
                    } else if (msg.getHeader(Message.MESSAGE_NAME).equals(EdgeLCMMessageFactory.EDGE_REQUEST_CHILDREN) && msg.getBodyAsProperties().get(EdgeMessageProperties.EDGE_PROP_CHILDREN)==null) {
                        threadPool.execute(new Runnable() {
                            public void run() {
                                try {
                                    reportChildren();
                                } catch (EndpointException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                        return;
                    }

                    // this is an initiating request, will only be handled in
                    // state running, else it will be deferred to
                    // the endpoint reaches state running
                    if (checkDefer(msg))
                        return;

                    if (xpattern.equals(ExchangePattern.OutIn)) {
                        exchange = createExchange(new ExchangePattern(ExchangePattern.InOut));
                    } else {
                        // default behaviour is inOnly
                        if(xpattern.equals(ExchangePattern.RobustOutOnly)){
                            DefaultMessage confMsg = new DefaultMessage();
                            confMsg.setHeader(Message.DELIVERY_STATUS, Message.DELIVERY_SUCCESS);
                            Exchange e = createExchange(new ExchangePattern(ExchangePattern.RobustInOnly));
                            e.setExchangeId(msg.getHeader(Message.EXCHANGE_ID));
                            confMsg.setReceiverEndpointUri(msg.getHeader(Message.ROBUST_DELIVERY_ACK_URI));
                            e.setOutBoundMessage(confMsg);
                            processExchange(e);
                            log.debug("Endpoint: " + uri + ", Sending robust ack: " + e);
                        }
                        exchange = createExchange(new ExchangePattern(ExchangePattern.InOnly));
                    }

                    if (exchange != null) {
                        exchange.setInBoundMessage(msg);
                        exchange.setExchangeId(xId);
                        final Exchange exchange1 = exchange;
                        final Consumer consumer1 = consumer;
                        threadPool.execute(new Runnable() {
                            public void run() {
                                // Todo might insert e semaphore here to control
                                // concurrent access to consumer
                                log.debug("Endpoint: " + uri + ", Processing incoming exchange: " + exchange1);
                                consumer1.process(exchange1);
                            }
                        });
                    }
                }
            }
        }
    }

    protected boolean checkDefer(Message msg) {
        if (ExchangePattern.InOut.equals(msg.getHeader(Message.EXCHANGE_PATTERN)) || isStateRunning()) {
            return false;
        }

        log.debug("State isn't Running ("+endpointState+"). Deferring message to queue.");
        deferQueue.addElement(msg);
        return true;
    }

    public Vector getServices() {
        return services;
    }

    public final void initializeEndpoint() {
        uuidGenerator = new UuidGenerator("xId-" + ((getName() == null) ? getEndpointUuid() : getName()));
        threadPool = Executors.newThreadPool(maxPoolSize);
        if (getEndpointState().equals(STATE_READY)) {
            try {
                preStart();
                start();
                postStart();
            } catch (Exception e) {
                e.printStackTrace();
                setEndpointState(STATE_STARTUP_FAILED);
            }
        }
    }

    protected void preStart() throws EndpointException {
        String s = !name.equals(endpointUuid)?"(name="+name+")":"";
        log.info("Starting endpoint: " + endpointUuid + s);
        setEndpointState(STATE_STARTING);

        // if (producer instanceof Service && !(producer instanceof Endpoint)) {
        // services.addElement(producer);
        // ((Service) producer).start();
        // }
    }

    public void start() throws Exception {
        // Override this method
    }

    protected void postStart() throws EndpointException {
        createProducer();

        setEndpointState(STATE_RUNNING);
        // register to the life cycle manager
        String lcmRegEnabled=getProperty(PROP_LCM_REGISTRATION_ENABLED);
        if(lcmRegEnabled==null || !lcmRegEnabled.equalsIgnoreCase("false")) {
            registerLCM();
            heartbeat=true;
            startLCMHeartbeat();
        }

        String s = !name.equals(endpointUuid)?"(name="+name+")":"";
        log.info("Successfully started endpoint: " + endpointUuid + s);
    }

    private void startLCMHeartbeat() {
        timer = new Timer();
        long delay=Long.parseLong(getProperty(PROP_LCM_HEARTBEAT_INTERVAL, "120000"));
        if(delay>0) {
            TimerTask task=new TimerTask() {

                public void run() {
                    threadPool.execute(new Runnable() {

                        public void run() {
                            try {
                                reportState();
                            } catch (EndpointException e) {}
                        }
                    });
                }
            };
            timer.schedule(task, delay, delay);
        }
    }

    public void stop() throws Exception {
        // Override this method
    }

    public final void shutDownEndpoint() {

        if (!isStateRunning()) {
            return;
        }
        log.info("Stopping endpoint: " + uri);
        setEndpointState(STATE_STOPPING);

        try {
            stop();
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (int i = 0; i < services.size(); i++) {
            Service service = (Service) services.elementAt(i);
            try {
                service.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // unregister to the life cycle manager
        if(timer!=null)
            timer.cancel();
        String lcmRegEnabled=getProperty(PROP_LCM_REGISTRATION_ENABLED);
        if(lcmRegEnabled==null || !lcmRegEnabled.equalsIgnoreCase("false")) {
            try {
                unRegisterLCM();
            } catch (EndpointException e) {
                e.printStackTrace();
            }
        }

        if (threadPool != null) // Null if endpoint was not started successfully
            // (ie couldn't connect)
            threadPool.stop();

        setEndpointState(STATE_READY);
    }


    public void addLink(String protocol, Link link) throws ConnectingException {
        outLinks.put(protocol, link);

    }

    public void addAlias(String alias) {
        if (alias != null 
                && !UuidHelper.isUuid(alias) 
                && UuidHelper.isValidAliasForUuid(alias, getEndpointUuid())) {
            aliases.addElement(alias);
            updateAliases();
        } else {
            log.warn("Cannot assign this endpoint alias:" + alias 
                    + ". Only alias with segment 'dico', 'localcoos' or '" 
                    + UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(getEndpointUuid()) + "' is allowed.");
        }
    }

    public void removeAlias(String alias) {
        aliases.removeElement(alias);
        updateAliases();
    }

    public Vector getAliases() {
        return aliases;
    }

    private void updateAliases() {
        Link link = (Link) outLinks.get("coos");
        if (link != null) {
            Message msg = new DefaultMessage("alias", Message.TYPE_ALIAS);
            msg.setReceiverEndpointUri("coos://" + link.getDestinationUuid());
            msg.setBody(aliases);
            Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
            ex.setOutBoundMessage(msg);
            processExchange(ex);
        }
    }

    public Processor getDefaultProcessor() {
        return this;
    }

    public Link getLink(String id) {
        return (Link) outLinks.get(id);
    }

    public void removeLink(String id) {
        outLinks.remove(id);

    }

    public void removeLinkById(String linkId) {
        // TODO Auto-generated method stub

    }

    public boolean subscribe(SubscriptionFilter filter) {
        log.debug("Endpoint: " + uri + " subscribing: " + filter);
        filter.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
        filter.setSenderEndpointUri(uri);
        filter.setHeader(Message.MESSAGE_NAME, SubscriptionFilter.SUBSCRIBE);
        Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutIn));
        ex.setOutBoundMessage(filter);
        processExchange(ex);
        if(ex.getFaultMessage() != null){
            return false;
        }
        return true;
    }

    public void unsubscribe() {
        log.debug("Endpoint: " + uri + " unSubscribing all");
        Message msg = new DefaultMessage(SubscriptionFilter.UNSUBSCRIBE_ALL);
        msg.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
        msg.setSenderEndpointUri(uri);
        Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
        ex.setOutBoundMessage(msg);
        processExchange(ex);
    }

    public void unsubscribe(SubscriptionFilter filter) {
        log.debug("Endpoint: " + uri + " unSubscribing: " + filter);
        filter.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
        filter.setSenderEndpointUri(uri);
        filter.setHeader(Message.MESSAGE_NAME, SubscriptionFilter.UNSUBSCRIBE);
        Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
        ex.setOutBoundMessage(filter);
        processExchange(ex);
    }

    public void publish(Notification notification) {
        log.debug("Endpoint: " + uri + " publishing: " + notification);
        notification.setReceiverEndpointUri(NOTIFICATION_BROKER_ADDRESS);
        notification.setSenderEndpointUri(uri);
        Exchange ex = createExchange(new ExchangePattern(ExchangePattern.OutOnly));
        ex.setOutBoundMessage(notification);
        processExchange(ex);
    }

    public void setChildStates(Hashtable childStates) {
        this.childStates = childStates;
    }

    public Hashtable getChildStates() {
        return childStates;
    }

    public Hashtable getProperties() {
        return properties;
    }

    public void setLinkAliases(Vector regAliases, Link outlink) {
        // Not implemented
    }

    public Plugin getPlugin() {
        return plugin;
    }

    public void setPlugin(Plugin plugin) {
        this.plugin = plugin;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy