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.
jadex.platform.service.message.MessageService Maven / Gradle / Ivy
Go to download
The Jadex platform package contains implementations of platform services as well as the platform component itself.
package jadex.platform.service.message;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Logger;
import jadex.bridge.ComponentIdentifier;
import jadex.bridge.ComponentTerminatedException;
import jadex.bridge.ContentException;
import jadex.bridge.DefaultMessageAdapter;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IComponentStep;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInputConnection;
import jadex.bridge.IInternalAccess;
import jadex.bridge.IMessageAdapter;
import jadex.bridge.IOutputConnection;
import jadex.bridge.IResourceIdentifier;
import jadex.bridge.ITransportComponentIdentifier;
import jadex.bridge.MessageFailureException;
import jadex.bridge.ResourceIdentifier;
import jadex.bridge.ServiceTerminatedException;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.component.IMessageFeature;
import jadex.bridge.component.impl.IInternalMessageFeature;
import jadex.bridge.fipa.SFipa;
import jadex.bridge.modelinfo.IModelInfo;
import jadex.bridge.service.BasicService;
import jadex.bridge.service.RequiredServiceInfo;
import jadex.bridge.service.annotation.Timeout;
import jadex.bridge.service.component.BasicServiceInvocationHandler;
import jadex.bridge.service.search.SServiceProvider;
import jadex.bridge.service.types.address.ITransportAddressService;
import jadex.bridge.service.types.address.TransportAddressBook;
import jadex.bridge.service.types.awareness.AwarenessInfo;
import jadex.bridge.service.types.awareness.DiscoveryInfo;
import jadex.bridge.service.types.awareness.IAwarenessManagementService;
import jadex.bridge.service.types.awareness.IDiscoveryService;
import jadex.bridge.service.types.clock.IClockService;
import jadex.bridge.service.types.cms.IComponentDescription;
import jadex.bridge.service.types.cms.IComponentManagementService;
import jadex.bridge.service.types.execution.IExecutionService;
import jadex.bridge.service.types.library.ILibraryService;
import jadex.bridge.service.types.message.EncodingContext;
import jadex.bridge.service.types.message.ICodec;
import jadex.bridge.service.types.message.IContentCodec;
import jadex.bridge.service.types.message.IEncodingContext;
import jadex.bridge.service.types.message.IMessageListener;
import jadex.bridge.service.types.message.IMessageService;
import jadex.bridge.service.types.message.MessageType;
import jadex.commons.ICommand;
import jadex.commons.IFilter;
import jadex.commons.IResultCommand;
import jadex.commons.SReflect;
import jadex.commons.SUtil;
import jadex.commons.collection.LRU;
import jadex.commons.collection.MultiCollection;
import jadex.commons.collection.SCollection;
import jadex.commons.concurrent.IExecutable;
import jadex.commons.future.CollectionResultListener;
import jadex.commons.future.CounterResultListener;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.ExceptionDelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;
import jadex.commons.transformation.STransformation;
import jadex.commons.transformation.annotations.Classname;
import jadex.commons.transformation.binaryserializer.IErrorReporter;
import jadex.commons.transformation.binaryserializer.SerializerDecodingException;
import jadex.commons.transformation.traverser.ITraverseProcessor;
import jadex.commons.transformation.traverser.Traverser;
import jadex.platform.service.address.TransportAddressService;
import jadex.platform.service.awareness.discovery.message.IMessageAwarenessService;
import jadex.platform.service.message.streams.AbstractConnectionHandler;
import jadex.platform.service.message.streams.AckInfo;
import jadex.platform.service.message.streams.InitInfo;
import jadex.platform.service.message.streams.InputConnection;
import jadex.platform.service.message.streams.InputConnectionHandler;
import jadex.platform.service.message.streams.OutputConnection;
import jadex.platform.service.message.streams.OutputConnectionHandler;
import jadex.platform.service.message.streams.StreamSendTask;
import jadex.platform.service.message.transport.ITransport;
import jadex.platform.service.message.transport.MessageEnvelope;
import jadex.platform.service.message.transport.codecs.CodecFactory;
import jadex.platform.service.remote.RemoteMethodInvocationHandler;
/**
* The Message service serves several message-oriented purposes: a) sending and
* delivering messages by using transports b) management of transports
* (add/remove)
*
* The message service performs sending and delivering messages by separate actions
* that are individually executed on the execution service, i.e. they are delivered
* synchronous or asynchronous depending on the execution service mode.
*/
public class MessageService extends BasicService implements IMessageService
{
//-------- constants --------
/** The default codecs. */
public static IContentCodec[] CODECS = !SReflect.isAndroid() ? new IContentCodec[]
{
new jadex.platform.service.message.contentcodecs.JavaXMLContentCodec(),
new jadex.platform.service.message.contentcodecs.JadexXMLContentCodec(),
new jadex.platform.service.message.contentcodecs.NuggetsXMLContentCodec(),
new jadex.platform.service.message.contentcodecs.JadexBinaryContentCodec()
}
: SUtil.androidUtils().hasXmlSupport()?
new IContentCodec[]
{
new jadex.platform.service.message.contentcodecs.JadexBinaryContentCodec()
}
:new IContentCodec[]
{
new jadex.platform.service.message.contentcodecs.JadexBinaryContentCodec(),
new jadex.platform.service.message.contentcodecs.JadexXMLContentCodec()
};
//-------- attributes --------
/** The component. */
protected IInternalAccess component;
/** The transports. */
protected List transports;
/** All addresses of this platform. */
private String[] addresses;
/** The message types. */
protected Map messagetypes;
/** The deliver message action executed by platform executor. */
protected DeliverMessage delivermsg;
/** The logger. */
protected Logger logger;
/** The listeners (listener->filter). */
protected Map listeners;
/** The cashed clock service. */
protected IClockService clockservice;
/** The library service. */
protected ILibraryService libservice;
/** The execution service. */
protected IExecutionService exeservice;
// /** The address service. */
protected ITransportAddressService addrservice;
protected TransportAddressBook taddresses;
/** The awareness service. */
// protected IAwarenessManagementService ams;
/** Release date cache */
protected LRU releasedatecache = new LRU(100);
/** The cms. */
protected IComponentManagementService cms;
/** The class loader of the message service (only for envelope en/decoding, content is handled by receiver class loader). */
protected ClassLoader classloader;
/** The target managers (platform id->manager). */
protected LRU managers;
/** The codec factory for messages. */
protected CodecFactory codecfactory;
/** The delivery handler map. */
protected Map deliveryhandlers;
/** The initiator connections. */
protected Map icons;
/** The participant connections. */
protected Map pcons;
/** The content codecs. */
protected List contentcodecs;
/** The default content language (if not specified). */
protected String deflanguage;
/** The map of content codec infos. */
protected Map, Object[]>> contentcodecinfos;
/** Enable strict communication (i.e. fail on recoverable decoding errors). */
protected boolean strictcom;
//-------- constructors --------
/**
* Constructor for Outbox.
* @param platform
*/
public MessageService(IInternalAccess component, Logger logger, ITransport[] transports,
MessageType[] messagetypes)
{
this(component, logger, transports, messagetypes, null, null, null, false);
}
/**
* Constructor for Outbox.
* @param platform
*/
public MessageService(IInternalAccess component, Logger logger, ITransport[] transports,
MessageType[] messagetypes, IContentCodec[] contentcodecs, String deflanguage, CodecFactory codecfactory, boolean strictcom)
{
super(component.getComponentIdentifier(), IMessageService.class, null);
// Register communication classes with aliases
STransformation.registerClass(MessageEnvelope.class);
STransformation.registerClass(AckInfo.class);
STransformation.registerClass(InitInfo.class);
this.strictcom = strictcom;
this.component = component;
this.transports = SCollection.createArrayList();
for(int i=0; i(800);
if(contentcodecs!=null)
{
for(int i=0; i();
deliveryhandlers.put(MapSendTask.MESSAGE_TYPE_MAP, new MapDeliveryHandler());
deliveryhandlers.put(StreamSendTask.MESSAGE_TYPE_STREAM, new StreamDeliveryHandler());
this.icons = Collections.synchronizedMap(new HashMap());
this.pcons = Collections.synchronizedMap(new HashMap());
}
//-------- interface methods --------
/**
*
*/
public IInputConnection getParticipantInputConnection(int conid, ITransportComponentIdentifier initiator, ITransportComponentIdentifier participant, Map nonfunc)
{
return initInputConnection(conid, initiator, participant, nonfunc);
}
/**
*
*/
public IOutputConnection getParticipantOutputConnection(int conid, ITransportComponentIdentifier initiator, ITransportComponentIdentifier participant, Map nonfunc)
{
return initOutputConnection(conid, initiator, participant, nonfunc);
}
/**
* Create a virtual output connection.
*/
public OutputConnection internalCreateOutputConnection(IComponentIdentifier sender, IComponentIdentifier receiver, Map nonfunc)
{
UUID uuconid = UUID.randomUUID();
int conid = uuconid.hashCode();
OutputConnectionHandler och = new OutputConnectionHandler(this, nonfunc);
icons.put(conid, och);
OutputConnection con = new OutputConnection(TransportAddressService.getTransportComponentIdentifier(sender, taddresses),
TransportAddressService.getTransportComponentIdentifier(receiver, taddresses), conid, true, och);
// System.out.println("created ocon: "+component+", "+System.currentTimeMillis()+", "+och.getConnectionId());
return con;
}
/**
* Create a virtual output connection.
*/
public IFuture createOutputConnection(IComponentIdentifier sender, IComponentIdentifier receiver, Map nonfunc)
{
return new Future(internalCreateOutputConnection(sender, receiver, nonfunc));
}
/**
* Create a virtual input connection.
*/
public InputConnection internalCreateInputConnection(IComponentIdentifier sender, IComponentIdentifier receiver, Map nonfunc)
{
UUID uuconid = UUID.randomUUID();
int conid = uuconid.hashCode();
InputConnectionHandler ich = new InputConnectionHandler(this, nonfunc);
icons.put(conid, ich);
InputConnection con = new InputConnection(TransportAddressService.getTransportComponentIdentifier(sender, taddresses),
TransportAddressService.getTransportComponentIdentifier(receiver, taddresses), conid, true, ich);
// System.out.println("created icon: "+component+", "+System.currentTimeMillis()+", "+ich.getConnectionId());
return con;
}
/**
* Create a virtual input connection.
*/
public IFuture createInputConnection(IComponentIdentifier sender, IComponentIdentifier receiver, Map nonfunc)
{
return new Future(internalCreateInputConnection(sender, receiver, nonfunc));
}
/**
* Send a message.
* @param message The message as key value pairs.
* @param msgtype The message type.
* @param sender The sender component identifier.
* @param rid The resource identifier used by the sending component (i.e. corresponding to classes of objects in the message map).
* @param realrec The real receiver if different from the message receiver (e.g. message to rms encapsulating service call to other component).
* @param codecids The codecs to use for encoding (if different from default).
* @return Future that indicates an exception when messages could not be delivered to components.
*/
public IFuture sendMessage(final Map origmsg, final MessageType type,
final IComponentIdentifier osender, final IResourceIdentifier rid,
final IComponentIdentifier realrec, final byte[] codecids)//, final Map nonfunc)
{
final Future ret = new Future();
// final RuntimeException e = new RuntimeException();
// ret.addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// }
// public void exceptionOccurred(Exception exception)
// {
// if(exception instanceof IOException)
// {
// System.out.println("io");
// e.printStackTrace();
// }
// }
// });
// IResultListener disclistener = new IResultListener()
// {
// public void resultAvailable(final DiscoveryInfo discoveryinfo)
// {
// }
//
// public void exceptionOccurred(Exception exception)
// {
// resultAvailable(null);
// }
// };
//
// if (ams != null)
// {
// ams.getPlatformInfo(realrec.getRoot()).addResultListener(disclistener);
// }
// else
// {
// disclistener.resultAvailable(null);
// }
final IComponentIdentifier loc = IComponentIdentifier.LOCAL.get();
// System.err.println("send msg2: "+osender+" "+origmsg.get(SFipa.CONTENT));
final Map msg = new HashMap(origmsg);
final ITransportComponentIdentifier sender = TransportAddressService.getTransportComponentIdentifier(osender, taddresses);
// final IComponentIdentifier sender = internalUpdateComponentIdentifier(osender);
// addrservice.getTransportComponentIdentifier(osender).addResultListener(new ExceptionDelegationResultListener(ret)
// {
// public void customResultAvailable(final ITransportComponentIdentifier sender)
// {
// System.out.println("on0: "+IComponentIdentifier.CALLER.get()+" "+IComponentIdentifier.LOCAL.get());
libservice.getClassLoader(rid)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final ClassLoader cl)
{
// System.err.println("send msg3: "+sender+" "+msg.get(SFipa.CONTENT));
// System.out.println("on1: "+IComponentIdentifier.CALLER.get()+" "+IComponentIdentifier.LOCAL.get());
if(loc!=null && IComponentIdentifier.LOCAL.get()!=null && !loc.equals(IComponentIdentifier.LOCAL.get()))
{
logger.severe("Component thread backswitch failed. Should be: "+loc+" but is "+IComponentIdentifier.LOCAL.get());
}
// IComponentIdentifier sender = adapter.getComponentIdentifier();
if(sender==null)
{
ret.setException(new RuntimeException("Sender must not be null: "+msg));
return;
}
// Replace own component identifiers.
// Now done just before send
// String[] params = type.getParameterNames();
// for(int i=0; i(ret)
// {
// public void customResultAvailable(IExternalAccess exta)
// {
//// System.out.println("msgservice calling doSendMessage()");
//// System.out.println("on2: "+IComponentIdentifier.CALLER.get()+" "+IComponentIdentifier.LOCAL.get());
//
//// System.err.println("send msg4: "+sender+" "+msg.get(SFipa.CONTENT));
// IEncodingContext enccont = new EncodingContext(new Date());
// doSendMessage(msg, type, exta, cl, ret, codecids, enccont);
// }
// public void exceptionOccurred(Exception exception)
// {
// super.exceptionOccurred(exception);
// }
// });
// System.out.println("Getting final release date: " + msg);
getReleaseDate(type, msg).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(Date result)
{
// System.out.println("Got final release date: " + String.valueOf(result));
final Date freleasedate = result;
// final Date freleasedate = null;
// External access of sender required for content encoding etc.
// SServiceProvider.getServiceUpwards(component.getServiceProvider(), IComponentManagementService.class)
// .addResultListener(new ExceptionDelegationResultListener(ret)
// {
// public void customResultAvailable(IComponentManagementService cms)
// {
// String smsg = "MessageService.sendMessage("+msg+")";
// ServiceCall next = ServiceCall.getOrCreateNextInvocation();
// next.setProperty("debugsource", smsg);
cms.getExternalAccess(sender).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IExternalAccess exta)
{
// System.out.println("msgservice calling doSendMessage()");
// System.out.println("on2: "+IComponentIdentifier.CALLER.get()+" "+IComponentIdentifier.LOCAL.get());
// System.err.println("send msg4: "+sender+" "+msg.get(SFipa.CONTENT));
IEncodingContext enccont = new EncodingContext(freleasedate);
doSendMessage(msg, type, exta, cl, ret, codecids, enccont);
}
public void exceptionOccurred(Exception exception)
{
super.exceptionOccurred(exception);
}
});
// }
// });
}
});
// }
// });
}
});
//
// ret.addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// }
// public void exceptionOccurred(Exception exception)
// {
// System.out.println("ex msg send: "+exception);
// }
// });
return ret;
}
/**
* Extracted method to be callable from listener.
*/
protected void doSendMessage(Map msg, final MessageType type, IExternalAccess comp,
final ClassLoader cl, Future ret, byte[] codecids, final IEncodingContext enccontext)
{
final Map msgcopy = new HashMap(msg);
// Conversion via platform specific codecs
// Hack?! Preprocess content to enhance component identifiers.
IContentCodec[] compcodecs = getContentCodecs(comp.getModel(), cl);
List procs = Traverser.getDefaultProcessors();
procs.add(1, new ITraverseProcessor()
{
public Object process(Object object, Type type,
List processors, Traverser traverser,
Map traversed, boolean clone, ClassLoader targetcl, Object context)
{
return TransportAddressService.getTransportComponentIdentifier((ITransportComponentIdentifier)object, taddresses);
// return internalUpdateComponentIdentifier((ITransportComponentIdentifier)object);
}
public boolean isApplicable(Object object, Type type, boolean clone, ClassLoader targetcl)
{
return object instanceof ITransportComponentIdentifier;
}
});
// Ignore service proxies.
procs.add(1, new ITraverseProcessor()
{
public Object process(Object object, Type type,
List processors, Traverser traverser,
Map traversed, boolean clone, ClassLoader targetcl, Object context)
{
return object;
}
public boolean isApplicable(Object object, Type type, boolean clone, ClassLoader targetcl)
{
Class> clazz = SReflect.getClass(type);
return Proxy.isProxyClass(clazz) &&
(Proxy.getInvocationHandler(object) instanceof BasicServiceInvocationHandler
|| Proxy.getInvocationHandler(object) instanceof RemoteMethodInvocationHandler);
}
});
String[] names = (String[])msgcopy.keySet().toArray(new String[0]);
for(int i=0; i managers = new MultiCollection();
String recid = type.getReceiverIdentifier();
Object tmp = msgcopy.get(recid);
if(SReflect.isIterable(tmp))
{
for(Iterator> it = SReflect.getIterator(tmp); it.hasNext(); )
{
IComponentIdentifier cid = (IComponentIdentifier)it.next();
ITransportComponentIdentifier tcid = TransportAddressService.getTransportComponentIdentifier(cid, taddresses);
SendManager sm = getSendManager(tcid);
managers.add(sm, tcid);
}
}
else
{
IComponentIdentifier cid = (IComponentIdentifier)tmp;
ITransportComponentIdentifier tcid = TransportAddressService.getTransportComponentIdentifier(cid, taddresses);
SendManager sm = getSendManager(tcid);
managers.add(sm, tcid);
}
byte[] cids = codecids;
if(cids==null || cids.length==0)
cids = codecfactory.getDefaultCodecIds();
final ICodec[] codecs = getMessageCodecs(cids);
// ICodec[] codecs = new ICodec[cids.length];
// for(int i=0; i crl = new CounterResultListener(managers.size(), false, new DelegationResultListener(ret));
for(Iterator> it=managers.keySet().iterator(); it.hasNext();)
{
final SendManager tm = (SendManager)it.next();
ITransportComponentIdentifier[] recs = managers.getCollection(tm).toArray(new ITransportComponentIdentifier[0]);
MapSendTask task = new MapSendTask(msgcopy, type, recs, getTransports(), codecs, cl, enccontext);
tm.addMessage(task).addResultListener(crl);
// addrservice.getTransportComponentIdentifiers(recs).addResultListener(new IResultListener()
// {
// public void resultAvailable(ITransportComponentIdentifier[] trecs)
// {
// MapSendTask task = new MapSendTask(msgcopy, type, trecs, getTransports(), codecs, cl, enccontext);
// tm.addMessage(task).addResultListener(crl);
//// task.getSendManager().addMessage(task).addResultListener(crl);
// }
//
// public void exceptionOccurred(Exception exception)
// {
// }
// });
}
// sendmsg.addMessage(msgcopy, type, receivers, ret);
}
/**
* Get array of message codecs for codec ids.
*/
public ICodec[] getMessageCodecs(byte[] codecids)
{
ICodec[] codecs = new ICodec[codecids.length];
for(int i=0; i, Object[]> getContentCodecInfo(IModelInfo model, ClassLoader cl)
// {
// Map, Object[]> ret = null;
// Map props = model.getProperties();
// if(props!=null)
// {
// for(Iterator it=props.keySet().iterator(); ret==null && it.hasNext();)
// {
// String name = (String)it.next();
// if(name.startsWith("contentcodecinfo"))
// {
// ret = (Map, Object[]>)model.getProperty(name, cl);
// }
// }
// }
//
// return ret;
// }
/**
* Get a matching content codec.
* @param props The properties.
*/
// todo: called from rms, hack :-(
public void setContentCodecInfo(IComponentIdentifier cid, Map, Object[]> info)
{
if(contentcodecinfos==null)
contentcodecinfos = Collections.synchronizedMap(new HashMap, Object[]>>());
contentcodecinfos.put(cid, info);
}
/**
* Get a matching content codec.
* @param props The properties.
* @return The content codec.
*/
public Map, Object[]> getContentCodecInfo(IComponentIdentifier cid)
{
Map, Object[]> ret = (Map, Object[]>)contentcodecinfos.get(cid);
// if(ret==null)
// System.out.println("sdffdsdf");
return ret;
// return (Map, Object[]>)contentcodecinfos.get(cid);
}
/**
* Get the codec factory.
* @return The codec factory.
*/
public CodecFactory getCodecFactory()
{
return codecfactory;
}
// /**
// * Get the clock service.
// * @return The clock service.
// */
// public IClockService getClockService()
// {
// return clockservice;
// }
// /**
// * Deliver a message to some components.
// */
// public void deliverMessage(Map msg, String type, IComponentIdentifier[] receivers)
// {
// delivermsg.addMessage(new MessageEnvelope(msg, Arrays.asList(receivers), type));
// }
/**
* Get the codecs with message codecs.
* @return The codec factory.
*/
public IFuture> getAllCodecs()
{
return new Future>(getCodecFactory().getAllCodecs());
}
/**
* Get the default codecs.
* @return The default codecs.
*/
public IFuture getDefaultCodecs()
{
return new Future(getCodecFactory().getDefaultCodecs());
}
/**
* Deliver a message to the intended components. Called from transports.
* @param message The native message.
* (Synchronized because can be called from concurrently executing transports)
*/
public void deliverMessage(Object msg)
{
delivermsg.addMessage(msg);
}
/**
* Adds a transport for this outbox.
* @param transport The transport.
*/
public void addTransport(ITransport transport)
{
transports.add(transport);
addresses = null;
}
/**
* Remove a transport for the outbox.
* @param transport The transport.
*/
public void removeTransport(ITransport transport)
{
transports.remove(transport);
transport.shutdown();
addresses = null;
}
/**
* Moves a transport up or down.
* @param up Move up?
* @param transport The transport to move.
*/
public synchronized void changeTransportPosition(boolean up, ITransport transport)
{
int index = transports.indexOf(transport);
if(up && index>0)
{
ITransport temptrans = (ITransport)transports.get(index - 1);
transports.set(index - 1, transport);
transports.set(index, temptrans);
}
else if(index!=-1 && index getAddresses()
{
return new Future(internalGetAddresses());
}
/**
* Get addresses of all transports.
* @return The address schemes of all transports.
*/
public String[] getAddressSchemes()
{
ITransport[] trans = (ITransport[])transports.toArray(new ITransport[transports.size()]);
ArrayList schemes = new ArrayList();
for(int i = 0; i < trans.length; i++)
{
String[] aschemes = trans[i].getServiceSchemas();
schemes.addAll(Arrays.asList(aschemes));
}
return (String[])schemes.toArray(new String[schemes.size()]);
}
/**
* Get the transports.
* @return The transports.
*/
public ITransport[] getTransports()
{
ITransport[] transportsArray = new ITransport[transports.size()];
return (ITransport[])transports.toArray(transportsArray);
}
/**
* Get a send target manager for addresses.
*/
public SendManager getSendManager(IComponentIdentifier cid)
{
SendManager ret = managers.get(cid.getRoot());
if(ret==null)
{
ret = new SendManager();
managers.put(cid.getRoot(), ret);
}
return ret;
}
//-------- IPlatformService interface --------
// /**
// * Start the service.
// */
// public IFuture startService()
// {
// final Future ret = new Future();
//
// ITransport[] tps = (ITransport[])transports.toArray(new ITransport[transports.size()]);
// if(transports.size()==0)
// {
// ret.setException(new RuntimeException("MessageService has no working transport for sending messages."));
// }
// else
// {
// CounterResultListener lis = new CounterResultListener(tps.length, new IResultListener()
// {
// public void resultAvailable(Object result)
// {
// SServiceProvider.getService(provider, IClockService.class, RequiredServiceInfo.SCOPE_PLATFORM).addResultListener(new IResultListener()
// {
// public void resultAvailable(Object result)
// {
// clockservice = (IClockService)result;
// SServiceProvider.getServiceUpwards(provider, IComponentManagementService.class).addResultListener(new IResultListener()
// {
// public void resultAvailable(Object result)
// {
// cms = (IComponentManagementService)result;
// MessageService.super.startService().addResultListener(new DelegationResultListener(ret));
// }
//
// public void exceptionOccurred(Exception exception)
// {
// ret.setException(exception);
// }
// });
// }
//
// public void exceptionOccurred(Exception exception)
// {
// ret.setException(exception);
// }
// });
// }
//
// public void exceptionOccurred(Exception exception)
// {
// }
// });
//
// for(int i=0; i startService()
{
final Future ret = new Future();
super.startService().addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
if(transports.size()==0)
{
ret.setException(new RuntimeException("MessageService has no working transport for sending messages."));
}
else
{
exeservice = SServiceProvider.getLocalService(component, IExecutionService.class, RequiredServiceInfo.SCOPE_PLATFORM, false);
cms = SServiceProvider.getLocalService(component, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM, false);
ITransport[] tps = (ITransport[])transports.toArray(new ITransport[transports.size()]);
CollectionResultListener lis = new CollectionResultListener(tps.length, true,
new ExceptionDelegationResultListener, Void>(ret)
{
public void customResultAvailable(Collection result)
{
if(result.isEmpty())
{
ret.setException(new RuntimeException("MessageService has no working transport for sending messages."));
}
else
{
addrservice = SServiceProvider.getLocalService(component, ITransportAddressService.class, RequiredServiceInfo.SCOPE_PLATFORM, false);
addrservice.getTransportAddresses().addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(TransportAddressBook result)
{
taddresses = result;
addrservice.addPlatformAddresses(new ComponentIdentifier(component.getComponentIdentifier().getRoot().getName(), internalGetAddresses()))
.addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
clockservice = SServiceProvider.getLocalService(component, IClockService.class, RequiredServiceInfo.SCOPE_PLATFORM, false);
libservice = SServiceProvider.getLocalService(component, ILibraryService.class, RequiredServiceInfo.SCOPE_PLATFORM, false);
libservice.getClassLoader(component.getModel().getResourceIdentifier())
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(ClassLoader result)
{
classloader = result;
startStreamSendAliveBehavior();
startStreamCheckAliveBehavior();
// ams = SServiceProvider.getLocalService(component, IAwarenessManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM);
ret.setResult(null);
}
});
}
});
}
});
}
}
});
for(int i=0; i fut = transport.start();
fut.addResultListener(lis);
fut.addResultListener(new IResultListener()
{
public void resultAvailable(Void result)
{
}
public void exceptionOccurred(final Exception exception)
{
transports.remove(transport);
getComponent().scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
ia.getLogger().warning("Could not initialize transport: "+transport+" reason: "+exception);
return IFuture.DONE;
}
});
}
});
}
}
}
});
return ret;
}
/**
* Called when the platform shuts down. Do necessary cleanup here (if any).
*/
public IFuture shutdownService()
{
Future ret = new Future();
// ret.addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// System.err.println("MessageService shutdown end");
// }
//
// public void exceptionOccurred(Exception exception)
// {
// System.err.println("MessageService shutdown error");
// exception.printStackTrace();
// }
// });
SendManager[] tmp = (SendManager[])managers.values().toArray(new SendManager[managers.size()]);
final SendManager[] sms = (SendManager[])SUtil.arrayToSet(tmp).toArray(new SendManager[0]);
// System.err.println("MessageService shutdown start: "+(transports.size()+sms.length+1));
final CounterResultListener crl = new CounterResultListener(transports.size()+sms.length+1, true, new DelegationResultListener(ret));
// {
// public void intermediateResultAvailable(Void result)
// {
// System.err.println("MessageService shutdown intermediate result: "+result+", "+cnt);
// super.intermediateResultAvailable(result);
// }
// public boolean intermediateExceptionOccurred(Exception exception)
// {
// System.err.println("MessageService shutdown intermediate error: "+exception+", "+cnt);
// return super.intermediateExceptionOccurred(exception);
// }
// };
super.shutdownService().addResultListener(crl);
for(int i=0; i addMessageListener(IMessageListener listener, IFilter filter)
{
if(listeners==null)
listeners = new LinkedHashMap();
listeners.put(listener, filter);
return IFuture.DONE;
}
/**
* Remove a message listener.
* @param listener The change listener.
*/
public synchronized IFuture removeMessageListener(IMessageListener listener)
{
listeners.remove(listener);
return IFuture.DONE;
}
/**
* Add content codec type.
* @param codec The codec type.
*/
public IFuture addContentCodec(IContentCodec codec)
{
if(contentcodecs==null)
contentcodecs = new ArrayList();
contentcodecs.add(codec);
return IFuture.DONE;
}
/**
* Remove content codec type.
* @param codec The codec type.
*/
public IFuture removeContentCodec(IContentCodec codec)
{
if(contentcodecs!=null)
contentcodecs.remove(codec);
return IFuture.DONE;
}
/**
* Add message codec type.
* @param codec The codec type.
*/
public IFuture addMessageCodec(Class codec)
{
codecfactory.addCodec(codec);
return IFuture.DONE;
}
/**
* Remove message codec type.
* @param codec The codec type.
*/
public IFuture removeMessageCodec(Class codec)
{
codecfactory.removeCodec(codec);
return IFuture.DONE;
}
// /**
// * Update component identifier.
// * @param cid The component identifier.
// * @return The component identifier.
// */
// public ITransportComponentIdentifier internalUpdateComponentIdentifier(ITransportComponentIdentifier cid)
// {
// TransportComponentIdentifier ret = null;
// if(cid.getPlatformName().equals(component.getComponentIdentifier().getRoot().getLocalName()))
// {
// ret = new TransportComponentIdentifier(cid.getName(), internalGetAddresses());
//// System.out.println("Rewritten cid: "+ret+" :"+SUtil.arrayToString(ret.getAddresses()));
// }
// return ret==null? cid: ret;
// }
/**
* Announce that addresses of transports might have changed.
*/
public IFuture refreshAddresses()
{
addresses = null;
for(IDiscoveryService ds: SServiceProvider.getLocalServices(component, IDiscoveryService.class, RequiredServiceInfo.SCOPE_PLATFORM))
{
ds.republish();
}
// this is suboptimal currently because internalGetAddresses has to rebuild addresses immediately so
// it could be done here
return addrservice.addPlatformAddresses(new ComponentIdentifier(component.getComponentIdentifier().getRoot().getName(), internalGetAddresses()));
}
// /**
// * Update component identifier.
// * @param cid The component identifier.
// * @return The component identifier.
// */
// public IFuture updateComponentIdentifier(ITransportComponentIdentifier cid)
// {
// return new Future(internalUpdateComponentIdentifier(cid));
// }
//-------- internal methods --------
/**
* Get the component.
* @return The component.
*/
public IExternalAccess getComponent()
{
return component.getExternalAccess();
}
/**
*
*/
public void startStreamSendAliveBehavior()
{
final long lt = StreamSendTask.getMinLeaseTime(getComponent().getComponentIdentifier());
if(lt!=Timeout.NONE)
{
getComponent().scheduleStep(new IComponentStep()
{
@Classname("sendAlive")
public IFuture execute(IInternalAccess ia)
{
// System.out.println("sendAlive: "+pcons+" "+icons);
AbstractConnectionHandler[] mypcons = (AbstractConnectionHandler[])pcons.values().toArray(new AbstractConnectionHandler[0]);
for(int i=0; i()
{
@Classname("checkAlive")
public IFuture execute(IInternalAccess ia)
{
// final IComponentStep step = this;
// final Future ret = new Future();
AbstractConnectionHandler[] mypcons = (AbstractConnectionHandler[])pcons.values().toArray(new AbstractConnectionHandler[0]);
for(int i=0; i getRIDClassLoader(final Map msg, final MessageType mt)
{
final Future ret = new Future();
// MessageType mt = getMessageType(type);
final IResourceIdentifier rid = (IResourceIdentifier)msg.get(mt.getResourceIdIdentifier());
final IComponentIdentifier realrec = (IComponentIdentifier)msg.get(mt.getRealReceiverIdentifier());
// System.out.println("getRIDCl: "+SUtil.arrayToString(msg.get(SFipa.RECEIVERS))+" "+rid+" "+realrec);
// Explanation for only using global rids:
// Local rids are mapped to a path, but different platforms may use different
// means for inlcuding them a) as new resource with custom rid b) in the startup path with platform rid
if(rid!=null && rid.getGlobalIdentifier()!=null)
{
SServiceProvider.getService(component, ILibraryService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final ILibraryService ls)
{
ls.getClassLoader(rid).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(ClassLoader result)
{
// System.out.println("got: "+result+" "+rid);
// Hack!!! Use current platform class loader for rms message, if no rid class loader available.
if(result==null)
{
Object recs = msg.get(mt.getReceiverIdentifier());
if((recs instanceof IComponentIdentifier[] && ((IComponentIdentifier[])recs).length==1
&& ((IComponentIdentifier[])recs)[0].getLocalName().equals("rms"))
|| (recs instanceof List && ((List>)recs).size()==1
&& ((IComponentIdentifier)((List>)recs).get(0)).getLocalName().equals("rms")))
{
// System.out.println("cl is global");
ls.getClassLoader(null).addResultListener(new DelegationResultListener(ret));
}
else
{
// System.out.println("cl is ridloader: "+result);
super.customResultAvailable(null);
}
}
else
{
super.customResultAvailable(result);
}
}
});
}
public void exceptionOccurred(Exception exception)
{
super.resultAvailable(null);
}
});
}
else if(realrec!=null)
{
SServiceProvider.getService(component, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IComponentManagementService cms)
{
cms.getComponentDescription(realrec).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final IComponentDescription desc)
{
SServiceProvider.getService(component, ILibraryService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(ILibraryService ls)
{
ls.getClassLoader(desc.getResourceIdentifier()).addResultListener(new DelegationResultListener(ret));
}
public void exceptionOccurred(Exception exception)
{
super.resultAvailable(null);
}
});
}
});
}
public void exceptionOccurred(Exception exception)
{
super.resultAvailable(null);
}
});
}
else
{
// Hack? Use global loader if no rid declared? Use x_receiver?
SServiceProvider.getService(component, ILibraryService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final ILibraryService ls)
{
ls.getClassLoader(null).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(ClassLoader result)
{
super.customResultAvailable(result);
}
});
}
});
// ret.setResult(null);
}
return ret;
}
/**
* Send message(s) executable.
*/
public class SendManager implements IExecutable
{
//-------- attributes --------
/** The list of messages to send. */
protected List tasks;
//-------- constructors --------
/**
* Send manager.
*/
public SendManager()
{
this.tasks = new ArrayList();
}
//-------- methods --------
/**
* Send a message.
*/
public boolean execute()
{
AbstractSendTask tmp = null;
boolean isempty;
synchronized(this)
{
if(!tasks.isEmpty())
tmp = tasks.remove(0);
isempty = tasks.isEmpty();
}
final AbstractSendTask task = tmp;
if(task!=null)
{
// Todo: move back to send manager thread after isValid()
// (hack!!! currently only works because message service is raw)
// hack!!! doesn't make much sense to check isValid as send manager executes on different thread.
isValid().addResultListener(new IResultListener()
{
public void resultAvailable(Boolean result)
{
if(result.booleanValue())
{
task.doSendMessage();
}
// Quit when service was terminated.
else
{
// System.out.println("send message not executed");
task.getFuture().setException(new MessageFailureException(task.getMessage(), task.getMessageType(), null, "Message service terminated."));
// isempty = true;
// messages.clear();
}
}
public void exceptionOccurred(Exception exception)
{
// System.out.println("send message not executed");
task.getFuture().setException(new MessageFailureException(task.getMessage(), task.getMessageType(), null, "Message service terminated."));
// isempty = true;
// messages.clear();
}
});
}
return !isempty;
}
/**
* Add a message to be sent.
* @param message The message.
*/
public IFuture addMessage(final AbstractSendTask task)
{
// if(new Random().nextInt(1000)==0)
// {
// task.getFuture().setException(new RuntimeException("Random message error for testing: "+task.getFuture()));
// }
// else
{
isValid().addResultListener(new ExceptionDelegationResultListener(task.getFuture())
{
public void customResultAvailable(Boolean result)
{
if(result.booleanValue())
{
synchronized(SendManager.this)
{
tasks.add(task);
}
exeservice.execute(SendManager.this);
}
// Fail when service was shut down.
else
{
// System.out.println("message not added");
task.getFuture().setException(new ServiceTerminatedException(getServiceIdentifier()));
}
}
});
}
return task.getFuture();
}
}
/**
* Deliver message(s) executable.
*/
protected class DeliverMessage implements IExecutable
{
//-------- attributes --------
/** The list of messages to send. */
protected List messages;
//-------- constructors --------
/**
* Create a new deliver message executable.
*/
public DeliverMessage()
{
this.messages = new ArrayList();
}
//-------- methods --------
/**
* Deliver the message.
*/
public boolean execute()
{
Object tmp = null;
boolean isempty;
synchronized(this)
{
if(!messages.isEmpty())
tmp = messages.remove(0);
isempty = messages.isEmpty();
}
if(tmp!=null)
{
internalDeliverMessage(tmp);
}
return !isempty;
}
/**
* Add a message to be delivered.
*/
public void addMessage(Object msg)
{
synchronized(this)
{
messages.add(msg);
}
exeservice.execute(DeliverMessage.this);
}
}
int cnt;
/**
* Handle stream messages.
*/
class StreamDeliveryHandler implements ICommand
{
/**
* Execute the command.
*/
public void execute(Object obj)
{
try
{
byte[] rawmsg = (byte[])obj;
int mycnt = cnt++;
// System.out.println("aaaa: "+mycnt+" "+getComponent().getComponentIdentifier());
// System.out.println("Received binary: "+SUtil.arrayToString(rawmsg));
int idx = 1;
byte type = rawmsg[idx++];
byte[] codec_ids = new byte[rawmsg[idx++]];
byte[] bconid = new byte[4];
for(int i=0; i-1; i--)
{
ICodec dec = codecfactory.getCodec(codec_ids[i]);
tmp = dec.decode(tmp, classloader, null);
}
data = tmp;
}
// Handle output connection participant side
if(type==StreamSendTask.INIT_OUTPUT_INITIATOR)
{
InitInfo ii = (InitInfo)data;
initInputConnection(conid, ii.getInitiator(), ii.getParticipant(), ii.getNonFunctionalProperties());
addrservice.addPlatformAddresses(ii.getInitiator());
addrservice.addPlatformAddresses(ii.getParticipant());
}
else if(type==StreamSendTask.ACKINIT_OUTPUT_PARTICIPANT)
{
// System.out.println("CCC: ack init");
OutputConnectionHandler och = (OutputConnectionHandler)icons.get(Integer.valueOf(conid));
if(och!=null)
{
och.ackReceived(StreamSendTask.INIT, data);
}
else
{
System.out.println("OutputStream not found (ackinit): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.DATA_OUTPUT_INITIATOR)
{
// System.out.println("received data");
InputConnectionHandler ich = (InputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.addData(seqnumber, (byte[])data);
}
else
{
System.out.println("InputStream not found (dai): "+conid+" "+pcons+" "+getComponent().getComponentIdentifier());
}
}
else if(type==StreamSendTask.CLOSE_OUTPUT_INITIATOR)
{
// System.out.println("CCC: close");
InputConnectionHandler ich = (InputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.closeReceived(SUtil.bytesToInt((byte[])data));
}
else
{
System.out.println("InputStream not found (coi): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.ACKCLOSE_OUTPUT_PARTICIPANT)
{
// System.out.println("CCC: ackclose");
OutputConnectionHandler och = (OutputConnectionHandler)icons.get(Integer.valueOf(conid));
if(och!=null)
{
och.ackReceived(StreamSendTask.CLOSE, data);
}
else
{
System.out.println("OutputStream not found (ackclose): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.CLOSEREQ_OUTPUT_PARTICIPANT)
{
// System.out.println("CCC: closereq");
OutputConnectionHandler och = (OutputConnectionHandler)icons.get(Integer.valueOf(conid));
if(och!=null)
{
och.closeRequestReceived();
}
else
{
System.out.println("OutputStream not found (closereq): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.ACKCLOSEREQ_OUTPUT_INITIATOR)
{
// System.out.println("CCC: ackclosereq");
InputConnectionHandler ich = (InputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.ackReceived(StreamSendTask.CLOSEREQ, data);
// ich.ackCloseRequestReceived();
}
else
{
System.out.println("OutputStream not found (ackclosereq): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.ACKDATA_OUTPUT_PARTICIPANT)
{
// Handle input connection initiator side
OutputConnectionHandler och = (OutputConnectionHandler)icons.get(Integer.valueOf(conid));
if(och!=null)
{
AckInfo ackinfo = (AckInfo)data;
och.ackDataReceived(ackinfo);
}
else
{
System.out.println("OutputStream not found (ackdata): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.INIT_INPUT_INITIATOR)
{
InitInfo ii = (InitInfo)data;
initOutputConnection(conid, ii.getInitiator(), ii.getParticipant(), ii.getNonFunctionalProperties());
addrservice.addPlatformAddresses(ii.getInitiator());
addrservice.addPlatformAddresses(ii.getParticipant());
}
else if(type==StreamSendTask.ACKINIT_INPUT_PARTICIPANT)
{
InputConnectionHandler ich = (InputConnectionHandler)icons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.ackReceived(StreamSendTask.INIT, data);
}
else
{
System.out.println("InputStream not found (ackinit): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.DATA_INPUT_PARTICIPANT)
{
InputConnectionHandler ich = (InputConnectionHandler)icons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.addData(seqnumber, (byte[])data);
}
else
{
System.out.println("InputStream not found (data input): "+conid);
}
}
else if(type==StreamSendTask.ACKDATA_INPUT_INITIATOR)
{
OutputConnectionHandler och = (OutputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(och!=null)
{
AckInfo ackinfo = (AckInfo)data;
och.ackDataReceived(ackinfo);
}
else
{
System.out.println("OutputStream not found (ackdata): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.CLOSEREQ_INPUT_INITIATOR)
{
OutputConnectionHandler och = (OutputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(och!=null)
{
och.closeRequestReceived();
}
else
{
System.out.println("InputStream not found (closereq): "+conid);
}
}
else if(type==StreamSendTask.ACKCLOSEREQ_INPUT_PARTICIPANT)
{
InputConnectionHandler ich = (InputConnectionHandler)icons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.ackReceived(StreamSendTask.CLOSEREQ, data);
}
else
{
System.out.println("InputStream not found (ackclosereq): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.CLOSE_INPUT_PARTICIPANT)
{
InputConnectionHandler ich = (InputConnectionHandler)icons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.closeReceived(SUtil.bytesToInt((byte[])data));
}
else
{
System.out.println("OutputStream not found (closeinput): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.ACKCLOSE_INPUT_INITIATOR)
{
OutputConnectionHandler ich = (OutputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(ich!=null)
{
ich.ackReceived(StreamSendTask.CLOSE, data);
}
else
{
System.out.println("InputStream not found (ackclose): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
// Handle lease time update
else if(type==StreamSendTask.ALIVE_INITIATOR)
{
// System.out.println("alive initiator");
AbstractConnectionHandler con = (AbstractConnectionHandler)pcons.get(Integer.valueOf(conid));
if(con!=null)
{
con.setAliveTime(System.currentTimeMillis());
}
else
{
System.out.println("Stream not found (alive ini): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
else if(type==StreamSendTask.ALIVE_PARTICIPANT)
{
// System.out.println("alive particpant");
AbstractConnectionHandler con = (AbstractConnectionHandler)icons.get(Integer.valueOf(conid));
if(con!=null)
{
con.setAliveTime(System.currentTimeMillis());
}
else
{
System.out.println("Stream not found (alive par): "+component+", "+System.currentTimeMillis()+", "+conid);
}
}
// System.out.println("bbbb: "+mycnt+" "+getComponent().getComponentIdentifier());
}
// catch(Throwable e)
catch(final Exception e)
{
// e.printStackTrace();
getComponent().scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
ia.getLogger().warning("Exception in stream: "+e.getMessage());
return IFuture.DONE;
}
});
}
}
}
/**
* Handle map messages, i.e. normal text messages.
*/
class MapDeliveryHandler implements ICommand
{
/**
* Execute the command.
*/
public void execute(Object obj)
{
MessageEnvelope me;
if(obj instanceof MessageEnvelope)
{
me = (MessageEnvelope)obj;
}
else
{
final List errors = new ArrayList();
IErrorReporter rep = strictcom ? null :new IErrorReporter()
{
public void exceptionOccurred(Exception e)
{
errors.add(e);
}
};
me = (MessageEnvelope)MapSendTask.decodeMessage((byte[])obj, codecfactory.getAllCodecs(), classloader, rep);
if(!errors.isEmpty())
{
logger.warning("Ignored errors during message decoding: "+errors);
// for(Exception e: errors)
// {
// e.printStackTrace();
// }
}
// byte[] rawmsg = (byte[])obj;
// int idx = 0;
// byte rmt = rawmsg[idx++];
// byte[] codec_ids = new byte[rawmsg[idx++]];
// for(int i=0; i-1; i--)
// {
// ICodec dec = codecfactory.getCodec(codec_ids[i]);
// tmp = dec.decode(tmp, classloader);
// }
// me = (MessageEnvelope)tmp;
}
final Map msg = me.getMessage();
final String type = me.getTypeName();
final IComponentIdentifier[] receivers = me.getReceivers();
// System.out.println("Received message: "+SUtil.arrayToString(receivers));
final MessageType messagetype = getMessageType(type);
// if(msg.get(SFipa.X_NONFUNCTIONAL)!=null
// && ((Map)msg.get(SFipa.X_NONFUNCTIONAL)).get("cause") instanceof String)
// {
// System.out.println("sdklvugi: "+msg.get(SFipa.SENDER));
// }
// Announce receiver to message awareness
ITransportComponentIdentifier sender = (ITransportComponentIdentifier)msg.get(messagetype.getSenderIdentifier());
announceComponentIdentifier(sender);
addrservice.addPlatformAddresses(sender);
// Content decoding works as follows:
// Find correct classloader for each receiver by
// a) if message contains rid ask library service for classloader (global rids are resolved with maven, locals possibly with peer to peer jar transfer)
// b) if library service could not resolve rid or message does not contain rid the receiver classloader can be used
final Future ret = new Future();
// todo: what to do with exception here?
// ret.addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// }
// public void exceptionOccurred(Exception exception)
// {
// exception.printStackTrace();
// }
// });
getRIDClassLoader(msg, getMessageType(type))
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(final ClassLoader classloader)
{
SServiceProvider.getService(component, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IComponentManagementService cms)
{
deliverToAllReceivers(receivers, cms, classloader, msg, logger, messagetype)
.addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
IFilter[] fils;
IMessageListener[] lis;
synchronized(this)
{
fils = listeners==null? null: (IFilter[])listeners.values().toArray(new IFilter[listeners.size()]);
lis = listeners==null? null: (IMessageListener[])listeners.keySet().toArray(new IMessageListener[listeners.size()]);
}
if(lis!=null)
{
// Decode message for listener. What if listener has different class loader?
decodeMessage(logger, messagetype, msg, classloader, null, component);
IMessageAdapter message = new DefaultMessageAdapter(msg, messagetype);
for(int i=0; i deliverToAllReceivers(final IComponentIdentifier[] receivers, final IComponentManagementService cms,
final ClassLoader classloader, final Map msg, final Logger logger, final MessageType messagetype)
{
final Future ret = new Future();
final int[] i = new int[1];
deliverToReceiver(receivers, i[0], cms, classloader, msg, logger, messagetype)
.addResultListener(new IResultListener()
{
public void resultAvailable(Void result)
{
if(++i[0] deliverToReceiver(final IComponentIdentifier[] receivers, final int i, final IComponentManagementService cms, final ClassLoader classloader,
final Map msg, final Logger logger, final MessageType messagetype)
{
// System.out.println("dtr: "+SUtil.arrayToString(receivers)+" "+i+" "+classloader);
final Future ret = new Future();
final IComponentIdentifier receiver = receivers[i];
// Copy message for state isolation.
final Map fmessage = new HashMap(msg);
// Perform decoding on component thread (necessary for rms)
cms.getExternalAccess(receiver).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IExternalAccess exta)
{
exta.scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
IInternalMessageFeature com = (IInternalMessageFeature)ia.getComponentFeature(IMessageFeature.class);
if(com!=null)
{
ClassLoader cl = classloader!=null? classloader: ia.getClassLoader();
decodeMessage(logger, messagetype, fmessage, cl, receiver, ia);
try
{
com.messageArrived(new DefaultMessageAdapter(fmessage, messagetype));
}
catch(Exception e)
{
logger.warning("Message could not be delivered to local receiver: " + receiver + ", "+ fmessage.get(messagetype.getIdIdentifier())+", "+e+", "+fmessage.get(messagetype.getSenderIdentifier()));
// todo: notify sender that message could not be delivered!
// Problem: there is no connection back to the sender, so that
// the only chance is sending a separate failure message.
}
}
else
{
logger.warning("Message could not be delivered to local receiver (no communication feature): " + receiver + ", "+ fmessage.get(messagetype.getIdIdentifier())+", "+fmessage.get(messagetype.getSenderIdentifier()));
}
return IFuture.DONE;
}
}).addResultListener(component.getComponentFeature(IExecutionFeature.class)
.createResultListener( new DelegationResultListener(ret)));
}
public void exceptionOccurred(Exception exception)
{
logger.warning("Message could not be delivered to local receiver: " + receiver + ", "+ msg.get(messagetype.getIdIdentifier())+", "+exception+", "+fmessage.get(messagetype.getSenderIdentifier()));
ret.setResult(null);
}
});
return ret;
}
/** The (real) system clock timer. */
protected volatile Timer timer;
/**
* Wait for a time delay on the (real) system clock.
*/
public TimerTask waitForRealDelay(long delay, final IComponentStep> step)
{
if(timer==null)
{
synchronized(this)
{
if(timer==null)
{
timer = new Timer(component.getComponentIdentifier().getName()+".message.timer", true);
}
}
}
TimerTask ret = new TimerTask()
{
public void run()
{
try
{
getComponent().scheduleStep(step);
}
catch(ComponentTerminatedException cte)
{
// ignore and stop timer.
timer.cancel();
}
}
};
timer.schedule(ret, delay);
return ret;
}
/**
* Create local input connection side after receiving a remote init output message.
* May be called multiple times and does nothing, if connection already exists.
*/
protected IInputConnection initInputConnection(final int conid, final ITransportComponentIdentifier initiator,
final ITransportComponentIdentifier participant, final Map nonfunc)
{
boolean created;
InputConnectionHandler ich = null;
InputConnection con = null;
synchronized(this)
{
ich = (InputConnectionHandler)pcons.get(Integer.valueOf(conid));
if(ich==null)
{
ich = new InputConnectionHandler(MessageService.this, nonfunc);
con = new InputConnection(initiator, participant, conid, false, ich);
pcons.put(Integer.valueOf(conid), ich);
// System.out.println("created for: "+conid+" "+pcons+" "+getComponent().getComponentIdentifier());
created = true;
}
else
{
con = ich.getInputConnection();
created = false;
}
}
if(created)
{
ich.initReceived();
final InputConnection fcon = con;
final Future ret = new Future();
SServiceProvider.getService(component, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IComponentManagementService cms)
{
cms.getExternalAccess(participant).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IExternalAccess ea)
{
ea.scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
IInternalMessageFeature com = (IInternalMessageFeature)ia.getComponentFeature(IMessageFeature.class);
if(com!=null)
{
com.streamArrived(fcon);
}
else
{
ia.getLogger().warning("Component received stream, but ha no communication feature: "+fcon);
}
return IFuture.DONE;
}
});
}
});
}
});
}
else
{
// If connection arrives late
if(nonfunc!=null)
ich.setNonFunctionalProperties(nonfunc);
}
return con;
}
/**
* Create local output connection side after receiving a remote init input message.
* May be called multiple times and does nothing, if connection already exists.
*/
protected IOutputConnection initOutputConnection(final int conid, final ITransportComponentIdentifier initiator,
final ITransportComponentIdentifier participant, final Map nonfunc)
{
boolean created;
OutputConnectionHandler och;
OutputConnection con = null;
synchronized(this)
{
och = (OutputConnectionHandler) pcons.get(Integer.valueOf(conid));
if(och==null)
{
och = new OutputConnectionHandler(MessageService.this, nonfunc);
con = new OutputConnection(initiator, participant, conid, false, och);
pcons.put(Integer.valueOf(conid), och);
// System.out.println("created: "+con.hashCode());
created = true;
}
else
{
con = och.getOutputConnection();
created = false;
}
}
if(created)
{
och.initReceived();
final OutputConnection fcon = con;
final Future ret = new Future();
SServiceProvider.getService(component, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IComponentManagementService cms)
{
cms.getExternalAccess(participant).addResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IExternalAccess ea)
{
ea.scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
IInternalMessageFeature com = (IInternalMessageFeature)ia.getComponentFeature(IMessageFeature.class);
if(com!=null)
{
com.streamArrived(fcon);
}
else
{
ia.getLogger().warning("Component received stream, but ha no communication feature: "+fcon);
}
return IFuture.DONE;
}
});
}
});
}
});
}
else
{
// If connection arrives late
if(nonfunc!=null)
och.setNonFunctionalProperties(nonfunc);
}
return con;
}
/**
*
*/
public static void main(String[] args)
{
boolean doread = false;
int max = 100000;
if(args.length>0)
doread = args[0].equals("read");
int len = 10000;
long start = System.currentTimeMillis();
if(doread)
{
ServerSocket ss = null;
try
{
ss = new ServerSocket(44444);
Socket s = ss.accept();
InputStream is = new BufferedInputStream(s.getInputStream());
byte[] read = new byte[len];
int packcnt = 0;
for(; packcnt5000)
{
mwstime = System.currentTimeMillis();
getComponent().scheduleStep(new IComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
SServiceProvider.getService(ia, IMessageAwarenessService.class, RequiredServiceInfo.SCOPE_PLATFORM)
.addResultListener(ia.getComponentFeature(IExecutionFeature.class).createResultListener(new IResultListener()
{
public void resultAvailable(IMessageAwarenessService result)
{
mws = result;
announceComponentIdentifier(cid);
}
public void exceptionOccurred(Exception exception)
{
// ignore if message awareness service not found
}
}));
return IFuture.DONE;
}
});
}
else if(mws!=null)
{
mws.announceComponentIdentifier(cid);
}
}
/**
* Get the release date from a message.
*/
protected IFuture getReleaseDate(MessageType type, final Map msg)
{
final Future ret = new Future();
Object tmp = msg.get(type.getReceiverIdentifier());
if(tmp instanceof IComponentIdentifier)
{
tmp = new IComponentIdentifier[] { (IComponentIdentifier) tmp };
}
if(SReflect.isIterable(tmp))
{
int size = 0;
for(Iterator> it=SReflect.getIterator(tmp); it.hasNext(); )
{
++size;
it.next();
}
final CollectionResultListener crl = new CollectionResultListener(size, false, new ExceptionDelegationResultListener, Date>(ret)
{
public void customResultAvailable(Collection result)
{
Date releasedate = null;
for(Date date : result)
{
if (date != null && (releasedate == null || releasedate.after(date)))
{
releasedate = date;
}
}
// Unknown platform date, assume oldest chain.
if(releasedate == null)
{
releasedate = new Date(1);
}
ret.setResult(releasedate);
}
});
for(Iterator> it=SReflect.getIterator(tmp); it.hasNext(); )
{
final IComponentIdentifier rec = (IComponentIdentifier)it.next();
if(rec==null)
{
crl.exceptionOccurred(new MessageFailureException(msg, type, null, "A receiver nulls: "+msg));
}
// Addresses may only null for local messages, i.e. intra platform communication
else if((
(rec instanceof ITransportComponentIdentifier && ((ITransportComponentIdentifier)rec).getAddresses()==null)
|| !(rec instanceof ITransportComponentIdentifier)) &&
!(rec.getPlatformName().equals(component.getComponentIdentifier().getPlatformName())))
{
crl.exceptionOccurred(new MessageFailureException(msg, type, null, "A receiver addresses nulls: "+msg));
}
else if(!releasedatecache.containsKey(rec.getRoot()))
{
SServiceProvider.getService(component, IAwarenessManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM, false).addResultListener(new IResultListener()
{
public void resultAvailable(IAwarenessManagementService ams)
{
ams.getPlatformInfo(rec.getRoot()).addResultListener(new IResultListener()
{
public void resultAvailable(DiscoveryInfo info)
{
if (info != null)
{
Map props = info.getProperties();
String stringdate = props != null? props.get(AwarenessInfo.PROPERTY_JADEXDATE): null;
Date date = stringdate != null? new Date(Long.parseLong(stringdate)) : null;
releasedatecache.put(rec.getRoot(), date);
crl.resultAvailable(date);
}
else
{
releasedatecache.put(rec.getRoot(), null);
crl.resultAvailable(null);
}
}
public void exceptionOccurred(
Exception exception)
{
releasedatecache.put(rec.getRoot(), null);
crl.resultAvailable(null);
}
});
}
public void exceptionOccurred(Exception exception)
{
releasedatecache.put(rec.getRoot(), null);
crl.resultAvailable(null);
}
});
}
else
{
Date date = releasedatecache.get(rec.getRoot());
crl.resultAvailable(date);
}
}
}
return ret;
}
/**
* Decode a message.
*/
protected void decodeMessage(final Logger logger, final MessageType messagetype, final Map fmessage, ClassLoader cl, IComponentIdentifier rec, IInternalAccess component)
{
// System.out.println("dec: "+cl+" "+component.getComponentIdentifier()+" "+MessageService.this.component.getComponentIdentifier());
// Conversion via platform specific codecs
if(rec==null)
{
Object recs = fmessage.get(messagetype.getReceiverIdentifier());
if(SReflect.isIterable(recs))
{
rec = (IComponentIdentifier)SReflect.getIterator(recs).next();
}
else
{
rec = (IComponentIdentifier)recs;
}
}
IContentCodec[] compcodecs = getContentCodecs(component.getModel(), cl);
for(Iterator it=fmessage.keySet().iterator(); it.hasNext(); )
{
String name = (String)it.next();
Object value = fmessage.get(name);
IContentCodec codec = messagetype.findContentCodec(compcodecs, fmessage, name);
if(codec==null)
codec = messagetype.findContentCodec(getContentCodecs(), fmessage, name);
if(codec!=null)
{
// System.out.println("dec2: "+codec+fmessage);
try
{
final List errors = new ArrayList();
IErrorReporter rep = strictcom ? null :new IErrorReporter()
{
public void exceptionOccurred(Exception e)
{
errors.add(e);
}
};
Object val = codec.decode((byte[])value, cl, getContentCodecInfo(rec), rep);
if(!errors.isEmpty())
{
logger.warning("Ignored errors during message decoding: "+errors);
// for(Exception e: errors)
// {
// e.printStackTrace();
// }
}
fmessage.put(name, val);
}
catch(Exception e)
{
// System.out.println("classloader: "+cl);
// e.printStackTrace();
String offsetstr="";
if (e instanceof SerializerDecodingException)
{
offsetstr=" at " + ((SerializerDecodingException) e).getContext().getCurrentOffset();
}
if(!(e instanceof ContentException))
{
// Todo: find out why 50MB sized messages are sent...
if(((byte[])value).length>3000)
{
byte[] tmp = new byte[3000];
System.arraycopy(value, 0, tmp, 0, tmp.length);
logger.info("ContentException"+offsetstr+": "+((byte[])value).length+", "+fmessage+", "+new String(tmp, Charset.forName("UTF-8")));
value = tmp;
}
e = new ContentException("ContentException"+offsetstr+", value:"+new String((byte[])value, Charset.forName("UTF-8")), e);
}
fmessage.put(name, e);
}
}
if(fmessage.get(name) instanceof byte[])
{
System.out.println("message problem\n"+new String((byte[])fmessage.get(name), Charset.forName("UTF-8")));
}
}
}
}