package org.myrobotlab.net; import java.io.Serializable; import java.net.URI; import java.util.HashMap; import org.myrobotlab.codec.CodecUtils; import org.myrobotlab.framework.Message; import org.myrobotlab.logging.Level; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.logging.LoggingFactory; import org.myrobotlab.service.Runtime; import org.myrobotlab.service.interfaces.CommunicationInterface; import org.myrobotlab.service.interfaces.Gateway; import org.myrobotlab.service.interfaces.NameProvider; import org.myrobotlab.service.interfaces.ServiceInterface; import org.slf4j.Logger; /** * goal of this class is to provide the interface for non-blocking communication * (local & remote) a good test of this goal is for this class to be used * outside of MRL process. * * e.g. - the goal is the design of a very small library - using only native * dependencies can do all of the necessary messaging MRL supports with very * little work * * @author GroG * */ public class CommunicationManager implements Serializable, CommunicationInterface, NameProvider { private static final long serialVersionUID = 1L; public final static Logger log = LoggerFactory.getLogger(CommunicationManager.class); String name; /** * mrlToProtocolKey - */ static HashMap<URI, URI> mrlToProtocolKey = new HashMap<URI, URI>(); public CommunicationManager(String name) { this.name = name; } // FIXME - put in Runtime @Override public void addRemote(URI mrlHost, URI protocolKey) { mrlToProtocolKey.put(mrlHost, protocolKey); } /** * mrl:/ get a gateway for remote communication */ public Gateway getComm(URI uri) { if (uri.getScheme().equals(CodecUtils.SCHEME_MRL)) { Gateway gateway = (Gateway) Runtime.getService(uri.getHost()); return gateway; } else { log.error(String.format("%s not SCHEME_MRL", uri)); return null; } } @Override final public void send(final Message msg) { ServiceInterface sw = Runtime.getService(msg.getName()); if (sw == null) { log.error(String.format("could not find service %s to process %s from sender %s - tearing down route", msg.name, msg.method, msg.sender)); ServiceInterface sender = Runtime.getService(msg.sender); if (sender != null) { sender.removeListener(msg.sendingMethod, msg.getName(), msg.method); } return; } URI host = sw.getInstanceId(); if (host == null) { // local message // log.info(String.format("local %s.%s->%s/%s.%s(%s)", msg.sender, // msg.sendingMethod, sw.getHost(), msg.name, msg.method, // Encoder.getParameterSignature(msg.data))); sw.in(msg); } else { // remote message // log.info(String.format("remote %s.%s->%s/%s.%s(%s)", msg.sender, // msg.sendingMethod, sw.getHost(), msg.name, msg.method, // Encoder.getParameterSignature(msg.data))); URI protocolKey = mrlToProtocolKey.get(host); getComm(host).sendRemote(protocolKey, msg); } } /** * get a gateway, send the message through the gateway with a protocol key */ @Override final public void send(final URI uri, final Message msg) { getComm(uri).sendRemote(uri, msg); } // FIXME - remove all others !!! public Message createMessage(String name, String method, Object... data) { Message msg = new Message(); msg.name = name; // destination instance name msg.sender = getName(); msg.data = data; msg.method = method; return msg; } @Override public String getName() { return name; } static public int count(String data, char toCount) { int charCount = 0; for (int i = 0; i < data.length(); i++) { char tmp = data.charAt(i); if (toCount == tmp) ++charCount; } return charCount; } public static void main(String[] args) { LoggingFactory.init(Level.WARN); // TODO - send a verify for service & another verify for method ? /* * FIXME PUT IN JUNIT TestThrower thrower = * (TestThrower)Runtime.start("thrower", "TestThrower"); TestCatcher catcher * = (TestCatcher)Runtime.start("catcher", "TestCatcher"); * * CommunicationManager cm = new CommunicationManager("catcher"); */ } }