Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.coos.messaging.PluginFactory 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;
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.serializer.ObjectJavaSerializer;
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() {
SerializerFactory.registerSerializer(Message.SERIALIZATION_METHOD_JAVA, new ObjectJavaSerializer());
}
// 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);
if(name.matches(".*\\.")){
throw new Exception("Name :"+ name + " not allowed. '.' is reserved for separating segments");
}
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 = "";
if (name != null && !name.equals("")) {
if(name.matches(".*\\.")){
throw new Exception("Name :"+ name + " not allowed. '.' is reserved for separating segments");
}
if (UuidHelper.isUuid(name)) {
name = UuidHelper.getQualifiedUuid(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) {
addChannel(channelMap, plugin, name, nameSegment, channelName);
}
for (int j = 0; j < pluginType.getChannelArray().length; j++) {
channelName = pluginType.getChannelArray(j);
addChannel(channelMap, plugin, name, nameSegment, channelName);
}
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 void addChannel(HashMap channelMap, Plugin plugin, String name, String nameSegment, String channelName)
throws Exception {
if (!channelMap.keySet().contains(channelName)) {
throw new Exception("Channel " + channelName + " is not declared for plugin: " + name);
}
Channel channel = (Channel) channelMap.get(channelName).copy();
if (!nameSegment.equals("")) {
if (channel.getSegment().equals("")) {
//use namesegment as channelsegment
channel.setSegment(nameSegment);
} else if (!channel.getSegment().equals(nameSegment)) {
//if different they must match
throw new Exception("Channel " + channelName + " with segment '" + channel.getSegment() +
"' does not match segment declared for plugin: " + name);
}
}
plugin.addChannel(channel);
}
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;
}
}