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

org.coos.messaging.transport.DefaultChannelServer Maven / Gradle / Ivy

The newest version!
/**
 * 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.transport;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.coos.messaging.COOS;
import org.coos.messaging.Channel;
import org.coos.messaging.ChannelServer;
import org.coos.messaging.ConnectingException;
import org.coos.messaging.Link;
import org.coos.messaging.LinkManager;
import org.coos.messaging.Message;
import org.coos.messaging.ProcessorException;
import org.coos.messaging.Transport;
import org.coos.messaging.impl.DefaultChannel;
import org.coos.messaging.impl.DefaultMessage;
import org.coos.messaging.impl.DefaultProcessor;
import org.coos.messaging.routing.Router;
import org.coos.messaging.routing.RouterChannel;
import org.coos.messaging.routing.RouterSegment;
import org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
import org.coos.messaging.util.UuidGenerator;
import org.coos.messaging.util.UuidHelper;


/**
 * @author Knut Eilif Husa, Tellu AS A default channel server
 */
public class DefaultChannelServer implements ChannelServer {
    private static final Log logger = LogFactory.getLog(DefaultChannelServer.class.getName());

    private Map channelMappings = new HashMap();
    protected Hashtable properties = new Hashtable();
    private LinkManager linkManager;
    private UuidGenerator uuidGenerator = new UuidGenerator();
    private COOS coosInstance;

    public void setChannelMappings(Hashtable channelMappings) {
        this.channelMappings = channelMappings;
    }

    public void addChannelMapping(String uuid, RouterChannel channel) {
        this.channelMappings.put(uuid, channel);
    }


    public void setCOOSInstance(COOS coosInstance) {
        this.coosInstance = coosInstance;
    }


    public void setLinkManager(LinkManager linkManager) {
        this.linkManager = linkManager;
    }

    public void initializeChannel(Transport transport) {
        transport.setChainedProcessor(new InitProcessor(transport));
    }

    /**
     * Starts the service
     *
     * @throws Exception
     *             Exception thrown if starting of service fails
     */
    public void start() throws Exception {
        // To change body of implemented methods use File | Settings | File
        // Templates.
    }

    /**
     * Stops the service
     *
     * @throws Exception
     *             Exception thrown if stopping of service fails
     */
    public void stop() throws Exception {
        // To change body of implemented methods use File | Settings | File
        // Templates.
    }

    @SuppressWarnings("unchecked")
	public void setProperties(Hashtable properties) {
        this.properties = properties;
    }

    public Hashtable getProperties() {
        return properties;
    }

    public String getProperty(String key) {
        return properties.get(key);
    }

    public void setProperty(String key, String value) {
        properties.put(key, value);

    }

    private class InitProcessor extends DefaultProcessor {
        Transport transport;

        public InitProcessor(Transport transport) {
            this.transport = transport;
        }

        @SuppressWarnings("unchecked")
		public void processMessage(Message msg) throws ProcessorException {

            if (msg.getHeader(Message.MESSAGE_NAME).equals(DefaultChannel.CONNECT)) {
                String conUuid = msg.getHeader(DefaultChannel.CONNECT_UUID);
                String conSeg = msg.getHeader(DefaultChannel.CONNECT_SEGMENT);
                String routingAlgName = msg.getHeader(DefaultChannel.ROUTING_ALGORITHM);
                Message reply = new DefaultMessage(Channel.CONNECT_ACK);
                RouterSegment seg;
                RouterChannel channel;
                try {

                    if ((conUuid != null) && (routingAlgName == null)) {

                        // this happens when endpoints with already allocated uuid connect
                        conSeg = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(conUuid);

                        // the routerUuids for the various segments
                        seg = linkManager.getSegment(conSeg);

                        if (seg == null) {
                            throwUUIDConnectingException(conUuid);
                        }

                        reply.setHeader(DefaultChannel.CONNECT_UUID, seg.getRouterUUID());
                        reply.setHeader(DefaultChannel.CONNECT_ROUTER_UUID, seg.getRouterUUID());
                    } else if ((conUuid != null) && (routingAlgName != null)) {
                        conSeg = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(conUuid);

                        // this happens when routers connect
                        // the routerUuids for the various segments
                        seg = linkManager.getSegment(conSeg);

                        if (seg == null) {

                            // parentsegment must be present and static
                            String parentSeg = UuidHelper.getParentSegment(conSeg);
                            seg = linkManager.getSegment(parentSeg);

                            if (seg == null) {
                                throwSegmentConnectingException(conUuid, routingAlgName);
                            }

                            linkManager.addDynamicSegment(conSeg, routingAlgName);
                            seg = linkManager.getSegment(conSeg);
                        } else {

                            if (!seg.getRoutingAlgorithmName().equals(routingAlgName)) {
                                throwSegmentConnectingException(conUuid, routingAlgName);
                            }
                        }

                        reply.setHeader(DefaultChannel.CONNECT_UUID, seg.getRouterUUID());
                        reply.setHeader(DefaultChannel.CONNECT_ROUTER_UUID, seg.getRouterUUID());
                    } else {

                        // This happens when endpoint attach to the bus and gets
                        // uuid allocated
                        if ((conSeg == null) || conSeg.equals("") || conSeg.equals(Router.LOCAL_SEGMENT) || conSeg.equals(Router.DICO_SEGMENT)) {

                            // If no segment id specified we pick the default from the
                            // segment mapping
                            for (RouterSegment rs : linkManager.getSegmentMap().values()) {

                                if (rs.isDefaultSegment()) {
                                    conSeg = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(rs.getRouterUUID());

                                    break;
                                }
                            }
                        }

                        seg = linkManager.getSegment(conSeg);

                        if (seg == null) {
                            throwSegmentConnectingException(conSeg, "n/a");
                        }

                        if (!conSeg.equals(".")) {
                            conSeg = new StringBuilder(conSeg).append(".").toString();
                        }

                        conUuid = new StringBuilder().append(conSeg).append(uuidGenerator.generateId()).toString();

                        reply.setHeader(DefaultChannel.CONNECT_ALLOCATED_UUID, conUuid);
                        reply.setHeader(DefaultChannel.CONNECT_ROUTER_UUID, seg.getRouterUUID());
                    }

                    Channel prototypeChannel = null;

                    for (String key : channelMappings.keySet()) {

                        if (conUuid.matches(key)) {
                            prototypeChannel = channelMappings.get(key);
                            logger.debug("Matched channel with key: " + key + " to channel: " + prototypeChannel.getName());
                        }
                    }

                    if (prototypeChannel == null) {
                        logger.debug("Allocating new channel!");
                        prototypeChannel = new RouterChannel();
                    }

                    channel = (RouterChannel) prototypeChannel.copy();

                    if (coosInstance != null) {
                        coosInstance.addChannel(conUuid, channel);
                    }

                    channel.getOutLink().setChainedProcessor(transport);

                    transport.setChannel(channel);

                    transport.setChainedProcessor(channel.getInLink());
                    channel.getInLink().setChainedProcessor(linkManager.getDefaultProcessor()); // The
                                                                                                // router
                    channel.getInLink().setDestinationUuid(seg.getRouterUUID());
                    channel.setLinkManager(linkManager);
                    channel.setTransport(transport);

                    linkManager.addLink(conUuid, channel.getOutLink());

                    // Retrieve the aliases
                    // They are not set on the link directly since we want to handle aliases
                    // a common way whether they arrive at registration or at later stages
                    Hashtable props = msg.getBodyAsProperties();

                    if (props != null) {
                        Vector aliases = (Vector) props.get(Link.ALIASES);
                        linkManager.setLinkAliases(aliases, channel.getOutLink());
                    }

                } catch (Exception e) {
                    logger.warn("Exception caught. Removing link " + conUuid, e);
                    linkManager.removeLink(conUuid);
                    transport.setChainedProcessor(null);
                    coosInstance.removeChannel(conUuid);
                    reply.setHeader(Message.MESSAGE_NAME, Channel.CONNECT_NACK);
                    reply.setHeader(Message.TYPE, Message.TYPE_ERROR);
                    reply.setHeader(Message.ERROR_REASON, e.getMessage());
                    transport.processMessage(reply);

                    return;
                }

                transport.processMessage(reply);
                channel.setConnected(true);
                
                
            } else {
                throw new ProcessorException("ChannelServer: Cannot process message: " + msg.toString());
            }
        }

        private void throwUUIDConnectingException(String conUuid) throws ConnectingException {
            Iterator iter = linkManager.getSegmentMap().keySet().iterator();
            String segmentListStr = "";

            while (iter.hasNext()) {
                segmentListStr += iter.next();
                segmentListStr += ", ";
            }

            String s = "Connection to endpoint/coos instance with uuid: " + conUuid + " failed. " +
                "This coos instance is declared to only connect to endpoints/coos instances in segment(s):" + segmentListStr;
            logger.error(s);

            throw new ConnectingException(s);
        }

        private void throwSegmentConnectingException(String conSeg, String routingAlg) throws ConnectingException {
            Iterator iter = linkManager.getSegmentMap().keySet().iterator();
            String segmentListStr = "";

            while (iter.hasNext()) {
                RouterSegment seg = linkManager.getSegmentMap().get(iter.next());
                segmentListStr += seg.getName() + ":" + seg.getRoutingAlgorithmName();
                segmentListStr += ", ";
            }

            String s = "Connection to endpoint/coos instance with segment: '" + conSeg + ", routingAlgorithm: " + routingAlg + "' failed. " +
                "This coos instance is declared to only connect to endpoints/coos instances in segment(s):" + segmentListStr;
            logger.error(s);


            throw new ConnectingException(s);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy