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.bridge.service.component.ProvidedServicesComponentFeature Maven / Gradle / Ivy
Go to download
Jadex bridge is a base package for kernels and platforms, i.e., it is used by both and provides commonly used interfaces and classes for active components and their management.
package jadex.bridge.service.component;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import jadex.base.IPlatformConfiguration;
import jadex.base.Starter;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.ProxyFactory;
import jadex.bridge.component.ComponentCreationInfo;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.component.impl.AbstractComponentFeature;
import jadex.bridge.modelinfo.ConfigurationInfo;
import jadex.bridge.modelinfo.UnparsedExpression;
import jadex.bridge.sensor.service.IMethodInvocationListener;
import jadex.bridge.service.BasicService;
import jadex.bridge.service.IInternalService;
import jadex.bridge.service.IService;
import jadex.bridge.service.IServiceIdentifier;
import jadex.bridge.service.ProvidedServiceImplementation;
import jadex.bridge.service.ProvidedServiceInfo;
import jadex.bridge.service.PublishInfo;
import jadex.bridge.service.RequiredServiceInfo;
import jadex.bridge.service.ServiceIdentifier;
import jadex.bridge.service.ServiceScope;
import jadex.bridge.service.annotation.Service;
import jadex.bridge.service.search.IServiceRegistry;
import jadex.bridge.service.search.ServiceNotFoundException;
import jadex.bridge.service.search.ServiceQuery;
import jadex.bridge.service.search.ServiceRegistry;
import jadex.bridge.service.types.library.ILibraryService;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishEventLevel;
import jadex.bridge.service.types.publish.IPublishService;
import jadex.commons.IValueFetcher;
import jadex.commons.MethodInfo;
import jadex.commons.SReflect;
import jadex.commons.SUtil;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.ExceptionDelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.FutureBarrier;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;
import jadex.commons.future.IntermediateEmptyResultListener;
import jadex.javaparser.SJavaParser;
/**
* Feature for provided services.
*/
public class ProvidedServicesComponentFeature extends AbstractComponentFeature implements IProvidedServicesFeature
{
//-------- attributes --------
/** The map of platform services. */
protected Map, Collection> services;
/** The map of provided service infos. (sid -> method listener) */
protected Map servicelisteners;
/** The map of provided service infos. (sid -> provided service info) */
protected Map serviceinfos;
//-------- constructors --------
/**
* Factory method constructor for instance level.
*/
public ProvidedServicesComponentFeature(IInternalAccess component, ComponentCreationInfo cinfo)
{
super(component, cinfo);
}
//-------- IComponentFeature interface / instance level --------
/**
* Initialize the feature.
*/
public IFuture init()
{
final Future ret = new Future();
// Collect provided services from model (name or type -> provided service info)
ProvidedServiceInfo[] ps = component.getModel().getProvidedServices();
Map sermap = new LinkedHashMap();
for(int i=0; i args = getComponent().getInternalAccess().getArguments();
Boolean extaarg = (Boolean)args.get("externalaccess");
Boolean extaplatarg = (Boolean)((Map)Starter.getPlatformValue(getComponent().getId(), IPlatformConfiguration.PLATFORMARGS)).get("externalaccess");
boolean on = extaarg!=null? extaarg.booleanValue(): extaplatarg!=null? extaplatarg.booleanValue(): true;
// System.out.println("on: "+on+" "+extaarg+" "+extaplatarg);
if(on)
{
ProvidedServiceImplementation impl = new ProvidedServiceImplementation();
impl.setValue("$component.getExternalAccess()");
// platform external access service will be published network wide, all others only on platform
ProvidedServiceInfo psi= new ProvidedServiceInfo("externalaccessservice", IExternalAccess.class, impl,
getComponent().getId().equals(getComponent().getId().getRoot())? ServiceScope.NETWORK: ServiceScope.PLATFORM, null, null, null, null);
sermap.put("externalaccessservice", psi);
}
FutureBarrier bar = new FutureBarrier<>();
// Instantiate service objects
for(ProvidedServiceInfo info: sermap.values())
{
// Evaluate and replace scope expression, if any.
ServiceScope scope = info.getScope();
if(ServiceScope.EXPRESSION.equals(scope))
{
scope = (ServiceScope)SJavaParser.getParsedValue(info.getScopeExpression(), component.getModel().getAllImports(), component.getFetcher(), component.getClassLoader());
info = new ProvidedServiceInfo(info.getName(), info.getType(), info.getImplementation(), scope, info.getScopeExpression(), info.getSecurity(), info.getPublish(), info.getProperties(), info.isSystemService());
// System.out.println("expression scope '"
// + (info.getScopeExpression()!=null ? info.getScopeExpression().getValue() : "")
// + "': "+scope);
}
final Future fut = new Future<>();
bar.addFuture(fut);
final ProvidedServiceImplementation impl = info.getImplementation();
// Virtual service (e.g. promoted)
if(impl!=null && impl.getBinding()!=null)
{
RequiredServiceInfo rsi = new RequiredServiceInfo(BasicService.generateServiceName(info.getType().getType(
component.getClassLoader(), component.getModel().getAllImports()))+":virtual", info.getType().getType(component.getClassLoader(), component.getModel().getAllImports()));
IServiceIdentifier sid = BasicService.createServiceIdentifier(component,
rsi.getName(), rsi.getType().getType(component.getClassLoader(), component.getModel().getAllImports()),
BasicServiceInvocationHandler.class, component.getModel().getResourceIdentifier(), info);
final IInternalService service = BasicServiceInvocationHandler.createDelegationProvidedServiceProxy(
component, sid, rsi, impl.getBinding(), component.getClassLoader(), Starter.isRealtimeTimeout(component.getId(), true));
addService(service, info);
fut.setResult(null);
}
else
{
final ProvidedServiceInfo finfo = info;
createServiceImplementation(info, getComponent().getFetcher())
.then(ser ->
{
// Implementation may null to disable service in some configurations.
if(ser!=null)
{
UnparsedExpression[] ins = finfo.getImplementation().getInterceptors();
IServiceInvocationInterceptor[] ics = null;
if(ins!=null)
{
ics = new IServiceInvocationInterceptor[ins.length];
for(int i=0; i0)
{
ics[i] = (IServiceInvocationInterceptor)SJavaParser.evaluateExpression(ins[i].getValue(), component.getModel().getAllImports(), component.getFetcher(), component.getClassLoader());
}
else
{
try
{
ics[i] = (IServiceInvocationInterceptor)ins[i].getClazz().getType(component.getClassLoader(), component.getModel().getAllImports()).newInstance();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
final Class> type = finfo.getType().getType(component.getClassLoader(), component.getModel().getAllImports());
PublishEventLevel elm = component.getDescription().getMonitoring()!=null? component.getDescription().getMonitoring(): null;
// todo: remove this? currently the level cannot be turned on due to missing interceptor
boolean moni = elm!=null? !PublishEventLevel.OFF.equals(elm.getLevel()): false;
final IInternalService proxy = BasicServiceInvocationHandler.createProvidedServiceProxy(
component, ser, finfo.getName(), type, ics,
moni, finfo);
addService(proxy, finfo);
}
fut.setResult(null);
}).catchEx(e -> {e.printStackTrace(); fut.setResult(null);});
}
}
bar.waitFor().then(v ->
{
// Start the services.
Collection allservices = getAllServices();
if(!allservices.isEmpty())
{
initServices(allservices.iterator()).addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
}).catchEx(ret);
return ret;
}
/**
* Check if the feature potentially executed user code in body.
* Allows blocking operations in user bodies by using separate steps for each feature.
* Non-user-body-features are directly executed for speed.
* If unsure just return true. ;-)
*/
public boolean hasUserBody()
{
return false;
}
/**
* Called when the feature is shutdowned.
*/
public IFuture shutdown()
{
Future ret = new Future();
// Shutdown the services.
Collection allservices = getAllServices();
if(!allservices.isEmpty())
{
LinkedList list = new LinkedList(allservices);
shutdownServices(list.descendingIterator()).addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
return ret;
}
/**
* Add a service.
* @param service The service object.
* @param info The service info.
*/
protected void addService(IInternalService service, ProvidedServiceInfo info)
{
if(serviceinfos==null)
serviceinfos = new HashMap();
serviceinfos.put(service.getServiceId(), info);
// Find service types
// Class> type = info.getType().getType(component.getClassLoader(), component.getModel().getAllImports());
Class> type = service.getServiceId().getServiceType().getType(component.getClassLoader(), component.getModel().getAllImports());
Set> types = new LinkedHashSet>();
types.add(type);
for(Class> sin: SReflect.getSuperInterfaces(new Class[]{type}))
{
if(sin.isAnnotationPresent(Service.class))
{
types.add(sin);
}
}
if(services==null)
services = Collections.synchronizedMap(new LinkedHashMap, Collection>());
// return ServiceRegistry.getRegistry(component.getComponentIdentifier()).addService(service);
// FutureBarrier bar = new FutureBarrier();
for(Class> servicetype: types)
{
Collection tmp = services.get(servicetype);
if(tmp==null)
{
tmp = Collections.synchronizedList(new ArrayList());
services.put(servicetype, tmp);
}
tmp.add(service);
// Make service available immediately, even before start (hack???).
// bar.addFuture(SynchronizedServiceRegistry.getRegistry(component.getComponentIdentifier()).addService(new ClassInfo(servicetype), service));
}
ServiceRegistry.getRegistry(component.getId()).addLocalService(service);
//System.out.println("added service: "+component.getId()+" "+service.getServiceId());
// return bar.waitFor();
}
/**
* Get the provided service info for a service.
* @param sid The service identifier.
* @return The provided service info.
*/
protected ProvidedServiceInfo getProvidedServiceInfo(IServiceIdentifier sid)
{
return serviceinfos.get(sid);
}
/**
* Remove a service.
* @param service The service object.
* @param info The service info.
*/
protected void removeService(IInternalService service)
{
IServiceRegistry registry = ServiceRegistry.getRegistry(component.getId());
if(registry!=null) // Maybe null on rescue thread (todo: why remove() on rescue thread?)
{
registry.removeService(service.getServiceId());
}
}
/**
* Create a service implementation from description.
*/
public IFuture createServiceImplementation(ProvidedServiceInfo info, IValueFetcher fetcher)
{
final Future ret = new Future<>();
Object ser = null;
ProvidedServiceImplementation impl = info.getImplementation();
if(impl!=null && impl.getValue()!=null)
{
// todo: other Class imports, how can be found out?
try
{
// SimpleValueFetcher fetcher = new SimpleValueFetcher(component.getFetcher());
// fetcher.setValue("$servicename", info.getName());
// fetcher.setValue("$servicetype", info.getType().getType(component.getClassLoader(), component.getModel().getAllImports()));
// System.out.println("sertype: "+fetcher.fetchValue("$servicetype")+" "+info.getName());
ser = SJavaParser.getParsedValue(impl, component.getModel().getAllImports(), fetcher, component.getClassLoader());
// System.out.println("added: "+ser+" "+model.getName());
ret.setResult(ser);
}
catch(RuntimeException e)
{
// e.printStackTrace();
ret.setException(new RuntimeException("Service creation error: "+info, e));
}
}
else if(impl!=null && impl.getClazz()!=null)
{
if(impl.getClazz().getType(component.getClassLoader(), component.getModel().getAllImports())!=null)
{
try
{
ser = impl.getClazz().getType(component.getClassLoader(), component.getModel().getAllImports()).newInstance();
ret.setResult(ser);
}
catch(Exception e)
{
ret.setException(e);
}
}
else
{
try
{
Class> c = Class.forName("jadex.extension.rs.publish.JettyRestPublishService", false, component.getClassLoader());
System.out.println("foundd: "+c);
}
catch(Exception e)
{
e.printStackTrace();
}
ret.setException(new RuntimeException("Could not load service implementation class: "+impl.getClazz()+" "+component.getClassLoader()));
}
}
else
{
ret.setResult(null);
}
// else if(IExternalAccess.class.equals(info.getType().getType(getComponent().getClassLoader())))
// {
// ser = getComponent().getExternalAccess();
// }
return ret;
}
/**
* Get all services in a single collection.
*/
protected Collection getAllServices()
{
Collection allservices;
if(services!=null && services.size()>0)
{
allservices = new LinkedHashSet();
for(Iterator> it=services.values().iterator(); it.hasNext(); )
{
// Service may occur at different positions if added with more than one interface
Collection col = it.next();
for(IInternalService ser: col)
{
if(!allservices.contains(ser))
{
allservices.add(ser);
}
}
}
}
else
{
allservices = Collections.emptySet();
}
return allservices;
}
/**
* Init the services one by one.
*/
protected IFuture initServices(final Iterator services)
{
final Future ret = new Future();
if(services.hasNext())
{
final IInternalService is = services.next();
initService(is).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
initServices(services).addResultListener(new DelegationResultListener(ret));
}
});
// component.getLogger().info("Starting service: "+is.getId());
// is.setComponentAccess(component).addResultListener(new DelegationResultListener(ret)
// {
// public void customResultAvailable(Void result)
// {
// is.startService().addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// component.getLogger().info("Started service: "+is.getId());
//
//
// }
//
// public void exceptionOccurred(Exception exception)
// {
// ret.setException(exception);
// }
// });
// }
// });
}
else
{
ret.setResult(null);
}
return ret;
}
/**
* Init a service, i.e. set the component (internal access) and call startService.
*/
protected IFuture initService(final IInternalService is)
{
final Future ret = new Future();
component.getLogger().info("Starting service: "+is.getServiceId()+" "+component.getFeature(IExecutionFeature.class).isComponentThread());
is.setComponentAccess(component).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
// System.out.println("Starting service: "+is.getServiceId()+" "+component.getFeature(IExecutionFeature.class).isComponentThread());
is.startService().addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
component.getLogger().info("Started service: "+is.getServiceId());
serviceStarted(is).addResultListener(new DelegationResultListener(ret));
}
});
}
});
return ret;
}
/**
* Called after a service has been started.
*/
public IFuture serviceStarted(final IInternalService service)
{
final Future ret = new Future();
ProvidedServiceInfo info = getProvidedServiceInfo(service.getServiceId());
PublishInfo pit = info==null? null: info.getPublish();
if(pit!=null)
{
// Hack?! evaluate the publish id string
// Must clone info to not change the model
final PublishInfo pi = new PublishInfo(pit);
try
{
String pid = (String)SJavaParser.evaluateExpression(pi.getPublishId(), getComponent().getModel().getAllImports(), getComponent().getFetcher(), getComponent().getClassLoader());
pi.setPublishId(pid);
// System.out.println("pid is now: "+pid);
}
catch(Exception e)
{
// e.printStackTrace();
}
if (pi.isMulti())
{
getComponent().getFeature(IRequiredServicesFeature.class)
.searchServices(new ServiceQuery<>(IPublishService.class, pi.getPublishScope()))
.addResultListener(new IntermediateEmptyResultListener()
{
/** Flag if published at least once. */
protected boolean published = false;
/** Flag if finished. */
protected boolean finished = false;
public void exceptionOccurred(Exception exception)
{
exception.printStackTrace();
}
public void intermediateResultAvailable(final IPublishService result)
{
result.publishService(service.getServiceId(), pi).addResultListener(new IResultListener()
{
public void resultAvailable(Void vresult)
{
if (!published)
{
ret.setResult(null);
published = true;
}
}
public void exceptionOccurred(Exception exception)
{
if (finished && !published)
{
getComponent().getLogger().severe("Could not publish: "+service.getServiceId());
ret.setException(exception);
}
}
});
}
public void finished()
{
finished = true;
}
});
// SServiceProvider.getServices(getComponent(), IPublishService.class, pi.getPublishScope()).addResultListener(new IResultListener>()
// {
// public void exceptionOccurred(Exception exception)
// {
// getComponent().getLogger().severe("Could not publish: "+service.getId()+" "+exception.getMessage());
// ret.setResult(null);
// }
//
// public void resultAvailable(Collection result)
// {
// for (final IPublishService pubserv : result)
// {
// pubserv.publishService(service.getId(), pi).addResultListener(new IResultListener()
// {
// public void resultAvailable(Void result)
// {
// }
//
// public void exceptionOccurred(Exception exception)
// {
// getComponent().getLogger().severe("Could not publish to " + pubserv + ": "+service.getId()+" "+exception.getMessage());
// }
// });
// }
// }
// });
}
else
{
getPublishService(getInternalAccess(), pi.getPublishType(), pi.getPublishScope(), (Iterator)null)
.addResultListener(getComponent().getFeature(IExecutionFeature.class)
.createResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(IPublishService ps)
{
//System.out.println("Got publish service " + ps);
ps.publishService(service.getServiceId(), pi)
.addResultListener(getComponent().getFeature(IExecutionFeature.class).createResultListener(new DelegationResultListener(ret)));
}
public void exceptionOccurred(Exception exception)
{
// exception.printStackTrace();
getComponent().getLogger().severe("Could not publish: "+service.getServiceId()+" "+exception.getMessage());
ret.setResult(null);
}
}));
}
}
else
{
ret.setResult(null);
}
return ret;
}
/**
* Called after a service has been shutdowned.
*/
public IFuture serviceShutdowned(final IInternalService service)
{
final Future ret = new Future();
// adapter.invokeLater(new Runnable()
// {
// public void run()
// {
ProvidedServiceInfo info = getProvidedServiceInfo(service.getServiceId());
final PublishInfo pi = info==null? null: info.getPublish();
// System.out.println("shutdown ser: "+service.getId());
if(pi!=null)
{
final IServiceIdentifier sid = service.getServiceId();
// getPublishService(instance, pi.getPublishType(), null).addResultListener(instance.createResultListener(new IResultListener()
getPublishService(getInternalAccess(), pi.getPublishType(), pi.getPublishScope(), null).addResultListener(new IResultListener()
{
public void resultAvailable(IPublishService ps)
{
ps.unpublishService(sid).addResultListener(new DelegationResultListener(ret));
}
public void exceptionOccurred(Exception exception)
{
// instance.getLogger().severe("Could not unpublish: "+sid+" "+exception.getMessage());
// ignore, if no publish info
ret.setResult(null);
// todo: what if publish info but no publish service?
}
});
}
else
{
ret.setResult(null);
}
// }
// });
return ret;
}
/**
* Get the publish service for a publish type (e.g. web service).
* @param type The type.
* @param services The iterator of publish services (can be null).
* @return The publish service.
*/
public static IFuture getPublishService(final IInternalAccess instance, final String type, final ServiceScope scope, final Iterator services)
{
final Future ret = new Future();
if(services==null)
{
IFuture> fut = instance.getFeature(IRequiredServicesFeature.class).searchServices(new ServiceQuery<>(IPublishService.class, scope));
fut.addResultListener(instance.getFeature(IExecutionFeature.class).createResultListener(new ExceptionDelegationResultListener, IPublishService>(ret)
{
@Override
public void exceptionOccurred(Exception exception) {
// TODO Auto-generated method stub
super.exceptionOccurred(exception);
exception.printStackTrace();
}
public void customResultAvailable(Collection result)
{
getPublishService(instance, type, scope, result.iterator()).addResultListener(new DelegationResultListener(ret));
}
}));
}
else
{
if(services.hasNext())
{
final IPublishService ps = (IPublishService)services.next();
ps.isSupported(type).addResultListener(instance.getFeature(IExecutionFeature.class).createResultListener(new ExceptionDelegationResultListener(ret)
{
public void customResultAvailable(Boolean supported)
{
if(supported.booleanValue())
{
ret.setResult(ps);
}
else
{
getPublishService(instance, type, scope, services).addResultListener(new DelegationResultListener(ret));
}
}
}));
}
else
{
// ret.setResult(null);
ret.setException(new ServiceNotFoundException("IPublishService not found."));
}
}
return ret;
}
/**
* Shutdown the services one by one.
*/
protected IFuture shutdownServices(final Iterator services)
{
final Future ret = new Future();
if(services.hasNext())
{
final IInternalService is = services.next();
// Remove service from registry before shutdown.
removeService(is);
// component.getLogger().info("Stopping service: "+is.getServiceId());
// if(is instanceof IExternalAccess)
// System.out.println("Stopping service: "+is.getServiceId());
is.shutdownService().addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
// component.getLogger().info("Stopped service: "+is.getServiceId());
// System.out.println("Stopped service: "+is.getServiceId());
serviceShutdowned(is).addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
shutdownServices(services).addResultListener(new DelegationResultListener(ret));
}
});
}
@Override
public void exceptionOccurred(Exception exception)
{
// On error -> print and continue shutdown process.
component.getLogger().severe("Exception in service shutdown: "+is+"\n"+SUtil.getExceptionStacktrace(exception));
customResultAvailable(null);
}
});
}
else
{
ret.setResult(null);
}
return ret;
}
//-------- IProvidedServicesFeature interface --------
/**
* Get provided (declared) service.
* @return The service.
*/
public IService getProvidedService(String name)
{
IService ret = null;
if(services!=null)
{
for(Iterator> it=services.keySet().iterator(); it.hasNext() && ret==null; )
{
Collection sers = services.get(it.next());
for(Iterator it2=sers.iterator(); it2.hasNext() && ret==null; )
{
IService ser = it2.next();
if(ser.getServiceId().getServiceName().equals(name))
{
ret = ser;
}
}
}
}
return ret;
}
/**
* Get the raw implementation of the provided service.
* @param clazz The class.
* @return The raw object.
*/
public T getProvidedServiceRawImpl(Class clazz)
{
T ret = null;
T service = getProvidedService(clazz);
if(service!=null)
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
ret = clazz.cast(handler.getDomainService());
}
return ret;
}
/**
* Get the provided service implementation object by name.
*
* @param name The service name.
* @return The service.
*/
public Object getProvidedServiceRawImpl(String name)
{
Object ret = null;
Object service = getProvidedService(name);
if(service!=null)
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
ret = handler.getDomainService();
}
return ret;
}
/**
* Get the provided service implementation object by id.
*
* @param name The service identifier.
* @return The service.
*/
public Object getProvidedService(IServiceIdentifier sid)
{
Object ret = null;
Object[] services = getProvidedServices(sid.getServiceType().getType(getComponent().getClassLoader()));
if(services!=null)
{
for(Object ser: services)
{
// Special case for fake proxies, i.e. creating a service proxy for a known component (without knowing cid)
if(sid.getServiceName().equals("NULL"))
{
((IService)ser).getServiceId().getServiceType().equals(sid.getServiceType());
ret = (IService)ser;
break;
}
else if(((IService)ser).getServiceId().equals(sid))
{
ret = (IService)ser;
break;
}
}
}
return ret;
}
/**
* Get the provided service implementation object by id.
*
* @param name The service identifier.
* @return The service.
*/
public Object getProvidedServiceRawImpl(IServiceIdentifier sid)
{
Object ret = null;
Object[] services = getProvidedServices(sid.getServiceType().getType(getComponent().getClassLoader()));
if(services!=null)
{
IService service = null;
for(Object ser: services)
{
if(((IService)ser).getServiceId().equals(sid))
{
service = (IService)ser;
break;
}
}
if(service!=null)
{
if(ProxyFactory.isProxyClass(service.getClass()))
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
ret = handler.getDomainService();
}
else
{
ret = service;
}
}
}
return ret;
}
/**
* Get provided (declared) service.
* @param clazz The interface.
* @return The service.
*/
public T[] getProvidedServices(Class clazz)
{
Collection coll = null;
if(services!=null)
{
if(clazz!=null)
{
coll = services.get(clazz);
}
else
{
coll = new HashSet();
for(Class> cl: services.keySet())
{
Collection sers = services.get(cl);
coll.addAll(sers);
}
}
}
T[] ret = (T[])Array.newInstance(clazz==null? Object.class: clazz, coll!=null ? coll.size(): 0);
return coll==null ? ret : coll.toArray(ret);
}
/**
* Get provided (declared) service.
* @param clazz The interface.
* @return The service.
*/
public T getProvidedService(Class clazz)
{
T[] ret = getProvidedServices(clazz);
return ret.length>0? ret[0]: null;
}
/**
* Get the services.
* @return The services.
*/
public Map, Collection> getServices()
{
return services;
}
/**
* Add a service to the platform.
* If under the same name and type a service was contained,
* the old one is removed and shutdowned.
* @param type The public service interface.
* @param service The service.
*/
public IFuture addService(String name, Class> type, Object service)
{
return addService(name, type, null, service, null);
}
/**
* Add a service to the platform.
* If under the same name and type a service was contained,
* the old one is removed and shutdowned.
* @param type The public service interface.
* @param service The service.
* @param type The proxy type (@see{BasicServiceInvocationHandler}).
*/
public IFuture addService(String name, Class> type, Object service, String proxytype)
{
ProvidedServiceImplementation impl = proxytype!=null ? new ProvidedServiceImplementation(null, null, proxytype, null, null) : null;
ProvidedServiceInfo info = proxytype!=null ? new ProvidedServiceInfo(name, type, impl): null;
return addService(name, type, null, service, info);
}
// todo:
// /**
// * Add a service to the platform.
// * If under the same name and type a service was contained,
// * the old one is removed and shutdowned.
// * @param type The public service interface.
// * @param service The service.
// */
// public void addService(String name, Class> type, Object service, PublishInfo pi)
// {
// addService(name, type, BasicServiceInvocationHandler.PROXYTYPE_DECOUPLED, null, service, pi);
// }
/**
* Add a service to the platform.
* If under the same name and type a service was contained,
* the old one is removed and shutdowned.
* @param type The public service interface.
* @param service The service.
* @param scope The service scope.
*/
public IFuture addService(String name, Class> type, Object service, PublishInfo pi, ServiceScope scope)
{
ProvidedServiceInfo psi = pi!=null || scope!=null ? new ProvidedServiceInfo(null, type, null, scope, null, null, pi, null): null;
return addService(name, type, service, psi);
}
/**
* Add a service to the platform.
* If under the same name and type a service was contained,
* the old one is removed and shutdowned.
* @param type The public service interface.
* @param info The config settings.
*/
public IFuture addService(String name, Class> type, Object service, ProvidedServiceInfo info)
{
return addService(name, type, null, service, info);
}
/**
* Sets the tags of a service.
*
* @param sid The Service identifier.
* @param tags The tags.
* @return New service identifier.
*/
public IFuture setTags(IServiceIdentifier sid, String... tags)
{
Future ret = new Future<>();
if(sid instanceof ServiceIdentifier)
{
ServiceIdentifier ssid = (ServiceIdentifier) sid;
ssid.setTags(new HashSet(Arrays.asList(tags)));
Collection coll = services.get(ssid.getServiceType().getType(component.getClassLoader()));
if(coll != null)
{
// synchronized(coll)
// {
for(Iterator it = coll.iterator(); it.hasNext(); )
{
IInternalService ser = it.next();
if(ser.getServiceId().equals(ssid))
{
ser.setServiceIdentifier(ssid);
break;
}
}
// }
}
// synchronized(servicelisteners)
// {
if (servicelisteners != null)
{
if (servicelisteners.containsKey(sid))
{
MethodListenerHandler hndlr = servicelisteners.get(sid);
servicelisteners.put(ssid, hndlr);
}
}
// }
// synchronized(serviceinfos)
// {
if (serviceinfos != null)
{
if (serviceinfos.containsKey(sid))
{
ProvidedServiceInfo info = serviceinfos.get(sid);
serviceinfos.put(ssid, info);
}
}
// }
ServiceRegistry.getRegistry(component.getId().getRoot()).updateService(ssid);
ret.setResult(null);
}
else
{
ret.setException(new IllegalArgumentException("Unsupported service identifier type: " + sid));
}
return ret;
}
/**
* Removes a service from the platform (shutdowns also the service).
* @param service The service.
*/
public IFuture removeService(final IServiceIdentifier sid)
{
final Future ret = new Future();
if(sid==null)
{
ret.setException(new IllegalArgumentException("Service identifier nulls."));
return ret;
}
getServiceTypes(sid).addResultListener(new ExceptionDelegationResultListener>, Void>(ret)
{
public void customResultAvailable(final Collection> servicetypes)
{
// System.out.println("Removing service: " + servicetype);
synchronized(this)
{
IInternalService service = null;
for(Class> servicetype: servicetypes)
{
Collection tmp = services!=null? services.get(servicetype): null;
service = null;
if(tmp!=null)
{
for(Iterator it=tmp.iterator(); it.hasNext() && service==null; )
{
final IInternalService tst = it.next();
if(tst.getServiceId().equals(sid))
{
service = tst;
tmp.remove(service);
}
}
// Remove collection if last service
if(tmp.isEmpty())
{
services.remove(servicetype);
}
}
if(service==null)
{
ret.setException(new IllegalArgumentException("Service not found: "+sid));
break;
}
}
if(service!=null)
{
final IInternalService fservice = service;
// Todo: fix started/terminated!? (i.e. addService() is ignored, when not started!?)
// if(!terminated)
// {
// if(sid.toString().indexOf("Context")!=-1)
// System.out.println("Terminating service: "+sid);
getComponent().getLogger().info("Terminating service: "+sid);
// Dispose nonfunc properties
// todo: how to shutdown?
ret.setResult(null);
// service.shutdownNFPropertyProvider().addResultListener(new DelegationResultListener(ret)
// {
// public void customResultAvailable(Void result)
// {
//// if(fservice.getId().toString().indexOf("ContextSer")!=-1)
//// System.out.println("hierda");
//
// fservice.shutdownService().addResultListener(new DelegationResultListener(ret)
// {
// public void customResultAvailable(Void result)
// {
//// if(id.getParent()==null)// && sid.toString().indexOf("Async")!=-1)
//// System.out.println("Terminated service: "+sid);
// getLogger().info("Terminated service: "+sid);
//
// for(Class> key: servicetypes)
// {
// getServiceRegistry().removeService(new ClassInfo(key), fservice);
// }
//
// serviceShutdowned(fservice).addResultListener(new DelegationResultListener(ret));
// }
//
// public void exceptionOccurred(Exception exception)
// {
// exception.printStackTrace();
// super.exceptionOccurred(exception);
// }
// });
// }
//
// public void exceptionOccurred(Exception exception)
// {
// exception.printStackTrace();
// super.exceptionOccurred(exception);
// }
// });
// }
// else
// {
// ret.setResult(null);
// }
}
}
}
});
return ret;
}
/**
*
*/
public IFuture>> getServiceTypes(final IServiceIdentifier sid)
{
final Future>> ret = new Future>>();
getServiceType(sid).addResultListener(new ExceptionDelegationResultListener, Collection>>(ret)
{
public void customResultAvailable(Class> result)
{
// todo: cache results
Set> res = new LinkedHashSet>();
res.add(result);
Class>[] sins = SReflect.getSuperInterfaces(new Class[]{result});
for(Class> sin: sins)
{
if(sin.isAnnotationPresent(Service.class))
{
res.add(sin);
}
}
ret.setResult(res);
}
});
return ret;
}
/**
*
*/
public IFuture> getServiceType(final IServiceIdentifier sid)
{
final Future> ret = new Future>();
if(sid.getServiceType().getType(getComponent().getClassLoader(), getComponent().getModel().getAllImports())!=null)
{
ret.setResult(sid.getServiceType().getType(getComponent().getClassLoader(), getComponent().getModel().getAllImports())); // todo: only local? remote would cause nullpointer
}
else
{
ILibraryService ls = getComponent().getFeature(IRequiredServicesFeature.class).getLocalService(new ServiceQuery<>(ILibraryService.class));
ls.getClassLoader(sid.getResourceIdentifier())
.addResultListener(new ExceptionDelegationResultListener>(ret)
{
public void customResultAvailable(ClassLoader cl)
{
ret.setResult(sid.getServiceType().getType(cl));
}
});
}
return ret;
}
/**
* Add a service to the component.
* @param type The service interface.
* @param service The service.
* @param proxytype The proxy type (@see{BasicServiceInvocationHandler}).
*/
public IFuture addService(final String name, final Class> type, final IServiceInvocationInterceptor[] ics, final Object service, final ProvidedServiceInfo info)
{
final Future ret = new Future();
// System.out.println("addS:"+service);
PublishEventLevel elm = getComponent().getDescription().getMonitoring()!=null? getComponent().getDescription().getMonitoring(): null;
// todo: remove this? currently the level cannot be turned on due to missing interceptor
// boolean moni = elm!=null? !PublishEventLevel.OFF.equals(elm.getLevel()): false;
boolean moni = elm!=null && !PublishEventLevel.OFF.equals(elm);
final IInternalService proxy = BasicServiceInvocationHandler.createProvidedServiceProxy(
getInternalAccess(), service, name, type, ics, moni, info);
// TODO: was this DEFAULT handling (commented out below) used somewhere?
// info, ServiceScope.DEFAULT.equals(scope) && info!=null? info.getScope() : scope);
addService(proxy, info);
initService(proxy).addResultListener(new DelegationResultListener(ret));
return ret;
}
/**
* Add a method invocation handler.
*/
public void addMethodInvocationListener(IServiceIdentifier sid, MethodInfo mi, IMethodInvocationListener listener)
{
// System.out.println("added lis: "+sid+" "+mi+" "+hashCode());
if(servicelisteners==null)
servicelisteners = new HashMap();
MethodListenerHandler handler = servicelisteners.get(sid);
if(handler==null)
{
handler = new MethodListenerHandler();
servicelisteners.put(sid, handler);
}
handler.addMethodListener(mi, listener);
}
/**
* Remove a method invocation handler.
*/
public void removeMethodInvocationListener(IServiceIdentifier sid, MethodInfo mi, IMethodInvocationListener listener)
{
if(servicelisteners!=null)
{
MethodListenerHandler handler = servicelisteners.get(sid);
if(handler!=null)
{
handler.removeMethodListener(mi, listener);
}
}
}
/**
* Notify listeners that a service method has been called.
*/
public void notifyMethodListeners(IServiceIdentifier sid, boolean start, Object proxy, final Method method, final Object[] args, Object callid, ServiceInvocationContext context)
{
if(servicelisteners!=null)
{
MethodListenerHandler handler = servicelisteners.get(sid);
if(handler!=null)
{
// MethodInfo mi = new MethodInfo(method);
handler.notifyMethodListeners(start, proxy, method, args, callid, context);
}
}
}
/**
* Test if service and method has listeners.
*/
public boolean hasMethodListeners(IServiceIdentifier sid, MethodInfo mi)
{
boolean ret = false;
if(servicelisteners!=null)
{
MethodListenerHandler handler = servicelisteners.get(sid);
if(handler!=null)
{
ret = handler.hasMethodListeners(sid, mi);
}
}
return ret;
}
/**
* Add a service interceptor.
* @param interceptor The interceptor.
* @param service The service.
* @param pos The position (0=first, -1=last-1, i.e. one before method invocation).
*/
public void addInterceptor(IServiceInvocationInterceptor interceptor, Object service, int pos)
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
handler.addServiceInterceptor(interceptor, pos);
}
/**
* Remove a service interceptor.
* @param interceptor The interceptor.
* @param service The service.
*/
public void removeInterceptor(IServiceInvocationInterceptor interceptor, Object service)
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
handler.removeServiceInterceptor(interceptor);
}
/**
* Get the interceptors of a service.
* @param service The service.
* @return The interceptors.
*/
public IServiceInvocationInterceptor[] getInterceptors(Object service)
{
BasicServiceInvocationHandler handler = (BasicServiceInvocationHandler)ProxyFactory.getInvocationHandler(service);
return handler.getInterceptors();
}
}