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

org.coos.messaging.PluginFactory Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show 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;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import org.coos.messaging.impl.DefaultChannel;
import org.coos.messaging.util.URIHelper;
import org.coos.messaging.util.UuidHelper;
import org.coos.pluginXMLSchema.ChannelType;
import org.coos.pluginXMLSchema.FilterType;
import org.coos.pluginXMLSchema.InBoundType;
import org.coos.pluginXMLSchema.OutBoundType;
import org.coos.pluginXMLSchema.PluginType;
import org.coos.pluginXMLSchema.PluginsDocument;
import org.coos.pluginXMLSchema.PluginsType;
import org.coos.pluginXMLSchema.ProcessorType;
import org.coos.pluginXMLSchema.PropertyType;
import org.coos.pluginXMLSchema.TransportType;
import org.coos.util.macro.MacroSubstituteReader;

/**
 * Factory for Plugin instances
 * 
 * @author Knut Eilif Husa, Tellu AS
 */
public class PluginFactory extends COFactory {

    public static final String JVM_TRANSPORT_CLASS = "org.coos.messaging.transport.JvmTransport";
    public static final String PLUGIN_CHANNEL_CLASS = "org.coos.messaging.plugin.PluginChannel";

    private static Map sharedProcessors = new HashMap();
    private static Map processorTypes = new HashMap();

    

    private PluginFactory() {

    }

    // Used in tests only
    public static Plugin createPlugin(String name, String className, String segment, String coosInstanceName,
			String channelServerName) throws Exception {

		COContainer cl = new COContainer() {

			public Class loadClass(String className) throws ClassNotFoundException {
				return Class.forName(className);
			}

			public InputStream getResource(String resourceName) throws IOException {
				InputStream is = COContainer.class.getResourceAsStream(resourceName);
				return substitute(is);
			}

			public Object getObject(String name) {
				return null;
			}

			public void start() {
			}

			public void stop() {
			}
		};

		Plugin plugin = new Plugin();

		Class pluginClass = PluginFactory.tryClass(cl, className);
		Endpoint endpoint = (Endpoint) pluginClass.newInstance();
		endpoint.setCoContainer(cl);
		endpoint.setEndpointUri("coos://" + name);
		endpoint.setProperties(new Hashtable());
		plugin.setEndpoint(endpoint);

		URIHelper helper = new URIHelper(endpoint.getEndpointUri());
		if (helper.isEndpointUuid()) {
			endpoint.setEndpointUuid(name);
		}
		endpoint.setName(name);
		if (segment == null) {
			segment = ".";
		}
		Class channelClass = PluginFactory.tryClass(cl, PLUGIN_CHANNEL_CLASS);
		DefaultChannel channel = (DefaultChannel) channelClass.newInstance();
		channel.addProtocol("coos");
		channel.setCoContainer(cl);
		channel.setSegment(segment);
		plugin.addChannel(channel);
		Hashtable properties = new Hashtable();
		if (coosInstanceName != null)
			properties.put("COOSInstanceName", coosInstanceName);
		properties.put("ChannelServerName", channelServerName);
		Class transportClass = PluginFactory.tryClass(cl, JVM_TRANSPORT_CLASS);
		Transport transport = (Transport) transportClass.newInstance();
		transport.setProperties(properties);
		channel.setTransport(transport);

		return plugin;
	}
    

    // Used in tests only
    public static Plugin[] createPlugins(InputStream config) throws Exception {


        PluginsDocument doc = PluginsDocument.Factory.parse(config);
        COContainer cl = new COContainer() {

            public Class loadClass(String className) throws ClassNotFoundException {
                return Class.forName(className);
            }

            public InputStream getResource(String resourceName) throws IOException {
                InputStream is = COContainer.class.getResourceAsStream(resourceName);
                return substitute(is);
            }

            public Object getObject(String name) {
                return null;
            }

            @Override
            public void start() {
            }

            @Override
            public void stop() {
            }
        };
        Plugin[] plugins = instantiate(doc.getPlugins(), cl);
        return plugins;
    }

    private static InputStream substitute(InputStream is) throws IOException {
        InputStreamReader isr = new InputStreamReader(is);
        MacroSubstituteReader msr = new MacroSubstituteReader(isr);
        String substituted = msr.substituteMacros();
        is = new ByteArrayInputStream(substituted.getBytes());
        return is;
    }

    public static Plugin[] createPlugins(InputStream config, COContainer cl) throws Exception {

        // XmlOptions options = new XmlOptions();
        PluginsDocument doc = PluginsDocument.Factory.parse(config);
        Plugin[] plugins = instantiate(doc.getPlugins(), cl);
        return plugins;
    }

    private static Plugin[] instantiate(PluginsType model, COContainer cl) throws Exception {
        Plugin[] res = new Plugin[model.getPluginArray().length];

        // processors
        for (int i = 0; i < model.getProcessorArray().length; i++) {
            ProcessorType processorType = model.getProcessorArray()[i];
            if (processorType.getName() == null || processorType.getClass1() == null) {
                throw new Exception("Plugin processors must have a name and a implementing class. Must be defined!");
            }
            String name = processorType.getName();
            processorTypes.put(name, processorType);
            Processor processor = instantiateProcessor(processorType, cl);
            if (processor.isShared()) {
                sharedProcessors.put(name, processor);
            }
        }

        HashMap transportMap = new HashMap();

        // transports
        for (int i = 0; i < model.getTransportArray().length; i++) {
            TransportType transportType = model.getTransportArray()[i];
            if (transportType.getName() == null || transportType.getClass1() == null) {
                throw new Exception("Plugin transports must have a name and an implementing class. Must be defined!");
            }
            String name = transportType.getName();
            String className = transportType.getClass1();
            Map props = new HashMap();
            for (int j = 0; j < transportType.getPropertyArray().length; j++) {
                PropertyType propertyType = transportType.getPropertyArray()[j];
                if (propertyType.getName() == null || propertyType.getValue() == null) {
                    throw new Exception("Plugin properties must have a name and a value. Must be defined!");
                }
                props.put(propertyType.getName(), propertyType.getValue());
            }
            Class transportClass = PluginFactory.tryClass(cl, className);
            Transport transport = (Transport) transportClass.newInstance();
            transport.setName(name);
            transport.setCoContainer(cl);
            transport.setProperties(new Hashtable(props));
            transportMap.put(name, transport);
        }

        // channels
        HashMap channelMap = new HashMap();

        for (int i = 0; i < model.getChannelArray().length; i++) {
            ChannelType channelType = model.getChannelArray()[i];
            if (channelType.getName() == null || channelType.getClass1() == null) {
                throw new Exception("Plugin channels must have a name and an implementing class. Must be defined!");
            }
            String name = channelType.getName();
            String className = channelType.getClass1();
            String protocol = channelType.getProtocol2();
            String segment = channelType.getSegment();
            Class channelClass = PluginFactory.tryClass(cl, className);
            Channel channel = (Channel) channelClass.newInstance();
            channel.setCoContainer(cl);
            if (protocol != null) {
                channel.addProtocol(protocol);
            } else {
            	channel.addProtocol("coos"); //The default protocol
            }
            channel.setName(name);
            if(segment != null){
                channel.setSegment(segment);
            }

            Map props = new HashMap();

            for (int j = 0; j < channelType.getPropertyArray().length; j++) {
                PropertyType propertyType = channelType.getPropertyArray()[j];
                if (propertyType.getName() == null || propertyType.getValue() == null) {
                    throw new Exception("Plugin properties must have a name and a value. Must be defined!");
                }
                props.put(propertyType.getName(), propertyType.getValue());
            }
            channel.setProperties(new Hashtable(props));

            for (int j = 0; j < channelType.getProtocolArray().length; j++) {
                String prot = channelType.getProtocolArray()[j];
                channel.addProtocol(prot);
            }

            String transportType = channelType.getTransport();
            if (transportType != null) {
                if (!transportMap.keySet().contains(transportType)) {
                    throw new Exception("Transport " + transportType + " is not declared.");
                }
                channel.setTransport((Transport) transportMap.get(transportType).copy());
            } else {
                Class transportClass = PluginFactory.tryClass(cl, JVM_TRANSPORT_CLASS);
                Transport transport = (Transport) transportClass.newInstance();
                transport.setCoContainer(cl);
                channel.setTransport(transport);
            }

            OutBoundType outBoundType = channelType.getOutBound();
            if (outBoundType != null) {
                for (int j = 0; j < outBoundType.getFilterArray().length; j++) {
                    FilterType filterType = outBoundType.getFilterArray()[j];
                    String processor = filterType.getProcessor();
                    ProcessorType procType = processorTypes.get(processor);
                    if (procType == null) {
                        throw new Exception("Processor " + processor + " is not declared.");
                    }
                    if (procType.getShared()) {
                        channel.getOutLink().addFilterProcessor(sharedProcessors.get(processor));
                    } else {
                        channel.getOutLink().addFilterProcessor(instantiateProcessor(procType, cl));
                    }
                }
            }

            InBoundType inBoundType = channelType.getInBound();
            if (inBoundType != null) {
                for (int j = 0; j < inBoundType.getFilterArray().length; j++) {
                    FilterType filterType = inBoundType.getFilterArray()[j];
                    String processor = filterType.getProcessor();
                    ProcessorType procType = processorTypes.get(processor);
                    if (procType == null) {
                        throw new Exception("Processor " + processor + " is not declared.");
                    }
                    if (procType.getShared()) {
                        channel.getInLink().addFilterProcessor(sharedProcessors.get(processor));
                    } else {
                        channel.getInLink().addFilterProcessor(instantiateProcessor(procType, cl));
                    }
                }
            }

            channelMap.put(name, channel);
        }

        // Plugins
        for (int i = 0; i < model.getPluginArray().length; i++) {

            Plugin plugin = new Plugin();

            PluginType pluginType = model.getPluginArray()[i];

            if (pluginType.getClass1() == null) {
                throw new Exception("Plugin properties must have a name and a value. Must be defined!");
            }

            String className = pluginType.getClass1();
            Class pluginClass = PluginFactory.tryClass(cl, className);
            Endpoint endpoint = (Endpoint) pluginClass.newInstance();

            endpoint.setCoContainer(cl);

            String name = pluginType.getName();
            String nameSegment = null;
            if (name != null) {
                if (UuidHelper.isUuid(name)) {
                    endpoint.setEndpointUuid(name);
                    endpoint.setEndpointUri("coos://" + name);
                    nameSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(name);
                } else {
                    endpoint.setEndpointUri("coos://" + name);
                    URIHelper uHelper = new URIHelper(endpoint.getEndpointUri());
                    nameSegment = uHelper.getSegment();
                }
                endpoint.setName(name); // the alias
            }
            String channelName = pluginType.getChannel2();
            String startLevelStr = pluginType.getStartLevel();
            if (startLevelStr != null) {
                plugin.setStartLevel(Integer.valueOf(startLevelStr));
            }
            String[] aliases = pluginType.getAliasArray();
            for (int j = 0; j < aliases.length; j++) {
                endpoint.addAlias(aliases[j]);
            }

            if (channelName == null && pluginType.getChannelArray().length == 0) {
                // Always add the PluginChannel
                Class channelClass1 = PluginFactory.tryClass(cl, PLUGIN_CHANNEL_CLASS);
                Channel channel1 = (Channel) channelClass1.newInstance();
                channel1.addProtocol("coos");
                channel1.setCoContainer(cl);
                channel1.setName("default");
                channelMap.put("default", channel1);
                String transportType = pluginType.getTransport();
                if (transportType != null) {
                    if (!transportMap.keySet().contains(transportType)) {
                        throw new Exception("Transport " + transportType + " is not declared.");
                    }
                    channel1.setTransport(transportMap.get(transportType));
                } else {
                    Class transportClass1 = PluginFactory.tryClass(cl, JVM_TRANSPORT_CLASS);
                    Transport transport1 = (Transport) transportClass1.newInstance();
                    transport1.setCoContainer(cl);
                    channel1.setTransport(transport1);
                }

                plugin.addChannel((Channel) channelMap.get("default").copy());
            }
            if (channelName != null) {
                if (!channelMap.keySet().contains(channelName)) {
                    throw new Exception("Plugin channel " + channelName + " is not declared for plugin: " + name);
                }
                plugin.addChannel((Channel) channelMap.get(channelName).copy());
            }
            for (int j = 0; j < pluginType.getChannelArray().length; j++) {
                channelName = pluginType.getChannelArray(j);
                if (!channelMap.keySet().contains(channelName)) {
                    throw new Exception("Channel " + channelName + " is not declared for plugin: " + name);
                }
                Channel channel = (Channel) channelMap.get(channelName);
                if (nameSegment != null && channel.getSegment() != null && !channel.getSegment().equals(nameSegment)) {
                    throw new Exception("Channel " + channelName + " with segment " + channel.getSegment()
                            + " does not match segment declared for plugin: " + name);
                }
                plugin.addChannel((Channel) channelMap.get(channelName).copy());
            }

            Map props = new HashMap();
            for (int k = 0; k < pluginType.getPropertyArray().length; k++) {
                PropertyType propertyType = pluginType.getPropertyArray()[k];
                if (propertyType.getName() == null || propertyType.getValue() == null) {
                    throw new Exception("Plugin properties must have a name and a value. Must be defined!");
                }
                props.put(propertyType.getName(), propertyType.getValue());
            }
            endpoint.setProperties(new Hashtable(props));
            plugin.setEndpoint(endpoint);

            res[i] = plugin;
        }
        return res;
    }

    private static Processor instantiateProcessor(ProcessorType processorType, COContainer cl) throws Exception {
        String className = processorType.getClass1();
        boolean isShared = processorType.getShared();
        String name = processorType.getName();
        Map props = new HashMap();
        for (int j = 0; j < processorType.getPropertyArray().length; j++) {
            PropertyType propertyType = processorType.getPropertyArray()[j];
            if (propertyType.getName() == null || propertyType.getValue() == null) {
                throw new Exception("COOS properties must have a name and a value. Must be defined!");
            }
            props.put(propertyType.getName(), propertyType.getValue());
        }
        Class procClass = PluginFactory.tryClass(cl, className);
        Processor processor = (Processor) procClass.newInstance();
        processor.setCoContainer(cl);
        processor.setName(name);
        processor.setProperties(new Hashtable(props));
        processor.setShared(isShared);
        return processor;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy