org.coos.messaging.plugin.PluginChannel 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.plugin;
import java.util.Hashtable;
import org.coos.messaging.Channel;
import org.coos.messaging.ConnectingException;
import org.coos.messaging.Endpoint;
import org.coos.messaging.Link;
import org.coos.messaging.Connectable;
import org.coos.messaging.Message;
import org.coos.messaging.Processor;
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;
/**
* A channel connecting plugins to coos instances (router nodes)
*
* @author Knut Eilif Husa, Tellu AS
*
*/
public class PluginChannel extends DefaultChannel {
private static final String PROPERTY_CONNECTION_TIMEOUT = "connectionTimeout";
private static final String PROPERTY_STARTUP_ORDERED = "startupOrdered";
private int connectionTimeout = 10000; // Default value
private boolean startupOrdered = true; // Default value
private String connectionErrorCause = null;
public PluginChannel() {
}
public long getConnectionTimeout() {
return connectionTimeout;
}
public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
public boolean isStartupOrdered() {
return startupOrdered;
}
public void setStartupOrdered(boolean startupOrdered) {
this.startupOrdered = startupOrdered;
}
public void addInFilter(Processor filter) {
inLink.addFilterProcessor(filter);
}
public void addOutFilter(Processor filter) {
outLink.addFilterProcessor(filter);
}
public void setProperties(Hashtable properties) {
super.setProperties(properties);
if (properties.get(PROPERTY_CONNECTION_TIMEOUT) != null) {
connectionTimeout = Integer.valueOf((String) properties.get(PROPERTY_CONNECTION_TIMEOUT)).intValue();
}
/*String startupOrderedStr = (String) properties.get(PROPERTY_STARTUP_ORDERED);
if (startupOrderedStr != null && startupOrderedStr.equals("false")) {
startupOrdered = false;
}*/
}
public void connect(Connectable connectable) throws ConnectingException {
synchronized (this) {
if (!(connectable instanceof Endpoint)) {
throw new ConnectingException("This channel can only be connected to Endpoints.");
}
if (connected) {
throw new ConnectingException("This channel is already connected.");
}
this.connectable = connectable;
final Endpoint endpoint = (Endpoint) connectable;
try {
if (transport == null) {
String className = "org.coos.messaging.transport.JvmTransport";
Class transportClass = Class.forName(className);
transport = (Transport) transportClass.newInstance();
transport.setChannel(this);
}
transport.setChainedProcessor(new DefaultProcessor() {
public void processMessage(Message msg) throws ProcessorException {
if (msg.getType().equals(Message.TYPE_ERROR)) {
endpoint.setEndpointState(Endpoint.STATE_STARTUP_FAILED);
connectionErrorCause = msg.getHeader(Message.ERROR_REASON);
} else if (msg.getName().equals(CONNECT_ACK)) {
String allocUuid = msg.getHeader(CONNECT_ALLOCATED_UUID);
String routerUuid = msg.getHeader(CONNECT_ROUTER_UUID);
transport.setChainedProcessor(inLink);
outLink.setDestinationUuid(routerUuid);
if (allocUuid != null) {
inLink.setDestinationUuid(allocUuid);
endpoint.setEndpointUuid(allocUuid);
if (endpoint.getEndpointUri() == null) {
endpoint.setName(allocUuid);
endpoint.setEndpointUri("coos://" + allocUuid);
}
}
connected = true;
}
new Thread(new Runnable(){
public void run() {
synchronized (PluginChannel.this) {
PluginChannel.this.notifyAll();
}
}
}).start();
if(!connected && !startupOrdered){
throwConnectingException();
}
}
});
DefaultMessage msg = new DefaultMessage(Channel.CONNECT);
if (endpoint.getEndpointUuid() == null) {
// must allocate a uuid
msg.setHeader(CONNECT_SEGMENT, segment);
} else {
// has predefined uuid
msg.setHeader(CONNECT_UUID, endpoint.getEndpointUuid());
}
// Set the aliases of the endpoint as a property in the body of
// the message
Hashtable props = new Hashtable();
props.put(Link.ALIASES, endpoint.getAliases());
msg.setBody(props);
inLink.setChainedProcessor(endpoint);
for (int i = 0; i < protocols.size(); i++) {
endpoint.addLink((String) protocols.elementAt(i), outLink);
}
outLink.setChainedProcessor(transport);
transport.start();
outLink.start();
inLink.start();
transport.processMessage(msg);
if (startupOrdered) {
this.wait(connectionTimeout);
if(!connected){
throwConnectingException();
}
}
} catch (Exception e) {
disconnect();
e.printStackTrace();
throw new ConnectingException("Connecting channel: " + name + " failed, cause: "
+ e.getMessage());
}
}
}
private void throwConnectingException() throws ConnectingException {
if(connectionErrorCause == null){
throw new ConnectingException("Timeout, no response from connecting coos router");
} else {
throw new ConnectingException(connectionErrorCause);
}
}
public void disconnect() {
try {
connected = false;
if (connectable != null) {
connectable.removeLinkById(outLink.getLinkId());
}
outLink.stop();
inLink.stop();
if (transport != null) {
transport.stop();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isConnected() {
return connected;
}
}