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.component.impl.SubcomponentsComponentFeature 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.component.impl;
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.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jadex.bridge.ComponentTerminatedException;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.ISearchConstraints;
import jadex.bridge.ImmediateComponentStep;
import jadex.bridge.component.ComponentCreationInfo;
import jadex.bridge.component.DependencyResolver;
import jadex.bridge.component.IComponentFeatureFactory;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.component.IMonitoringComponentFeature;
import jadex.bridge.component.ISubcomponentsFeature;
import jadex.bridge.modelinfo.ComponentInstanceInfo;
import jadex.bridge.modelinfo.ConfigurationInfo;
import jadex.bridge.modelinfo.IModelInfo;
import jadex.bridge.modelinfo.SubcomponentTypeInfo;
import jadex.bridge.modelinfo.UnparsedExpression;
import jadex.bridge.service.RequiredServiceBinding;
import jadex.bridge.service.component.IRequiredServicesFeature;
import jadex.bridge.service.search.ServiceQuery;
import jadex.bridge.service.types.clock.IClockService;
import jadex.bridge.service.types.cms.CMSComponentDescription;
import jadex.bridge.service.types.cms.CMSStatusEvent;
import jadex.bridge.service.types.cms.CreationInfo;
import jadex.bridge.service.types.cms.IComponentDescription;
import jadex.bridge.service.types.cms.PlatformComponent;
import jadex.bridge.service.types.cms.SComponentManagementService;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishEventLevel;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishTarget;
import jadex.bridge.service.types.monitoring.MonitoringEvent;
import jadex.commons.MultiException;
import jadex.commons.SUtil;
import jadex.commons.Tuple2;
import jadex.commons.Tuple3;
import jadex.commons.collection.MultiCollection;
import jadex.commons.future.CollectionResultListener;
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.IIntermediateFuture;
import jadex.commons.future.IResultListener;
import jadex.commons.future.ISubscriptionIntermediateFuture;
import jadex.commons.future.IntermediateDefaultResultListener;
import jadex.commons.future.IntermediateDelegationResultListener;
import jadex.commons.future.IntermediateFuture;
import jadex.commons.future.SubscriptionIntermediateFuture;
import jadex.javaparser.SJavaParser;
import jadex.javaparser.SimpleValueFetcher;
/**
* This feature provides subcomponents.
*/
public class SubcomponentsComponentFeature extends AbstractComponentFeature implements ISubcomponentsFeature, IInternalSubcomponentsFeature
{
// /** The number of children. */
// protected int childcount;
/** Debug flag. */
protected boolean debug = false;
/**
* Create the feature.
*/
public SubcomponentsComponentFeature(IInternalAccess component, ComponentCreationInfo cinfo)
{
super(component, cinfo);
// debug = Boolean.TRUE.equals(component.getArgument("debug"));
}
/**
* Initialize the feature.
*/
public IFuture init()
{
final Future ret = new Future();
if(component.getConfiguration()!=null)
{
ConfigurationInfo conf = component.getModel().getConfiguration(component.getConfiguration());
final ComponentInstanceInfo[] components = conf.getComponentInstances();
createInitialComponents(components).addResultListener(createResultListener(
new ExceptionDelegationResultListener, Void>(ret)
{
public void customResultAvailable(List cids)
{
ret.setResult(null);
}
}));
}
else
{
ret.setResult(null);
}
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;
}
/**
* Get the file name of a component type.
* @param ctype The component type.
* @return The file name of this component type.
*/
public String getComponentFilename(final String ctype)
{
String ret = null;
SubcomponentTypeInfo[] subcomps = getComponent().getModel().getSubcomponentTypes();
for(int i=0; ret==null && i getFileName(String ctype)
{
return new Future(getComponentFilename(ctype));
}
/**
* Get the local type name of this component as defined in the parent.
* @return The type of this component type.
*/
public String getLocalType()
{
return getComponent().getDescription().getLocalType();
}
/**
* Starts a new POJO-component.
*
* @param pojocomponent The pojo object used as component.
* @return The id of the component and the results after the component has been killed.
*/
public IFuture addComponent(Object pojocomponent)
{
CreationInfo ci = new CreationInfo().setPojo(pojocomponent);
return getComponent().createComponent(ci, null);
}
/**
* Starts a new component.
*
* @param infos Start information.
* @return The id of the component and the results after the component has been killed.
*/
public IFuture createComponent(CreationInfo info)
{
return getComponent().createComponent(info, null);
}
/**
* Starts a new component while continuously receiving status events (create, result updates, termination).
*
* @param infos Start information.
* @return Status events.
* /
public ISubscriptionIntermediateFuture createComponentWithEvents(CreationInfo info)
{
final SubscriptionIntermediateDelegationFuture ret = new SubscriptionIntermediateDelegationFuture<>();
final boolean keepsusp = Boolean.TRUE.equals(info.getSuspend());
info.setSuspend(true);
createComponent(info).addResultListener(new IResultListener()
{
public void resultAvailable(IExternalAccess result)
{
info.setSuspend(keepsusp);
ISubscriptionIntermediateFuture fut = SComponentManagementService.listenToComponent(result.getId(), component);
FutureFunctionality.connectDelegationFuture(ret, fut);
if (!keepsusp)
result.resumeComponent();
}
public void exceptionOccurred(Exception exception)
{
ret.setException(exception);
}
});
SFuture.avoidCallTimeouts(ret, component);
return ret;
}*/
public ISubscriptionIntermediateFuture createComponentWithEvents(CreationInfo info)
{
try
{
info = PlatformComponent.prepare(info);
}
catch(Exception e)
{
return new SubscriptionIntermediateFuture<>(e);
}
return SComponentManagementService.createComponent(info, info.getName(), info.getFilename(), getInternalAccess());
}
/**
* Starts a set of new components, in order of dependencies.
*
* @param infos Start information.
* @return The id of the component and the results after the component has been killed.
*/
public IIntermediateFuture createComponents(final CreationInfo... infos)
{
if (infos == null || infos.length == 0)
return new IntermediateFuture<>(new IllegalArgumentException("Creation infos must not be null or empty."));
FutureBarrier>> modelbar = new FutureBarrier<>();
if(debug)
System.out.println("createComponents: " + component + " " + Arrays.toString(infos));
final Map>>> tmpmodelmap = new HashMap<>();
for (int i = 0; i < infos.length; ++i)
{
IFuture>> fut =
SComponentManagementService.loadModel(infos[i].getFilename(), infos[i], component);
tmpmodelmap.put(i, fut);
modelbar.addFuture(fut);
}
final IntermediateFuture ret = new IntermediateFuture<>();
modelbar.waitFor().addResultListener(new IResultListener()
{
public void exceptionOccurred(Exception exception)
{
ret.setException(exception);
}
public void resultAvailable(Void result)
{
List> sysinfos = null;
List> userinfos = new ArrayList<>();
for(int i = 0; i < infos.length; ++i)
{
IModelInfo model = tmpmodelmap.get(i).get().getFirstEntity();
// if (isSystemComponent(model))
if (SComponentManagementService.isSystemComponent(model, infos[i], component.getId()))
{
if (sysinfos == null)
sysinfos = new ArrayList<>();
sysinfos.add(new Tuple2(infos[i], model));
continue;
}
userinfos.add(new Tuple2(infos[i], model));
}
if(debug)
{
System.out.println(component + " starting system subcomponents: " + (sysinfos == null ? "[]" : Arrays.toString(sysinfos.toArray())));
System.out.println(component + " starting user subcomponents: " + Arrays.toString(userinfos.toArray()));
}
if(sysinfos != null)
{
if(!component.getDescription().isSystemComponent())
{
ret.setException(new IllegalArgumentException(component.toString() + " attempted to start system component without being a system component."));
return;
}
doCreateComponents(sysinfos).addResultListener(new IntermediateDefaultResultListener()
{
public void intermediateResultAvailable(IExternalAccess result)
{
ret.addIntermediateResult(result);
};
public void finished()
{
if (userinfos.size() > 0)
doCreateComponents(userinfos).addResultListener(new IntermediateDelegationResultListener<>(ret));
else
ret.setFinished();
}
public void exceptionOccurred(Exception exception)
{
ret.setException(exception);
}
});
}
else
{
if(userinfos.size() > 0)
doCreateComponents(userinfos).addResultListener(new IntermediateDelegationResultListener<>(ret));
else
ret.setFinished();
}
}
});
return ret;
}
/**
* Stops a set of components, in order of dependencies.
*
* @param cids The component identifiers.
* @return The id of the component and the results after the component has been killed.
*/
public IIntermediateFuture>> killComponents(IComponentIdentifier... cids)
{
if(cids == null || cids.length == 0)
return new IntermediateFuture>>(new IllegalArgumentException("Component identifiers must not be null or empty."));
// boolean subsonly = true;
// for (IComponentIdentifier cid : cids)
// {
// if (!component.getId().equals(cid.getParent()))
// subsonly = false;
// }
// if (subsonly)
// return killLocalComponents(cids);
final IntermediateFuture>> ret = new IntermediateFuture<>();
final List exceptions = new ArrayList<>();
boolean suicide = false;
Set killset = new HashSet<>(Arrays.asList(cids));
Map> killparents = new HashMap<>();
// Enable debug on parent, if any child is in debug set.
debug = debug | killset.stream().anyMatch(cid ->
{
IComponentDescription child = SComponentManagementService.internalGetComponentDescription(cid);
return child!=null && PlatformComponent._BROKEN.contains(child.getModelName());
});
if(debug)
{
component.getLogger().severe("Killing subcomponents0: "+component+", "+killset);
ret.addResultListener(new IResultListener>>>()
{
@Override
public void resultAvailable(Collection>> result)
{
component.getLogger().severe("Killing subcomponents0a done: "+component);
}
@Override
public void exceptionOccurred(Exception exception)
{
component.getLogger().severe("Killing subcomponents0b failed: "+component+"\n"+SUtil.getExceptionStacktrace(exception));
}
});
}
idloop:
for(IComponentIdentifier cid : cids)
{
IComponentIdentifier parent = cid.getParent();
while (parent != null)
{
if (killset.contains(parent))
continue idloop;
parent = parent.getParent();
}
if(component.getId().equals(cid))
{
suicide = true;
continue;
}
IComponentIdentifier kp = cid.getParent();
if(kp == null)
kp = cid;
Set kpset = killparents.get(kp);
if (kpset == null)
{
kpset = new LinkedHashSet<>();
killparents.put(kp, kpset);
}
kpset.add(cid);
}
Set locals = killparents.remove(component.getId());
if (suicide)
locals = null;
FutureBarrier compkillbar = new FutureBarrier<>();
for(Map.Entry> entry : killparents.entrySet())
{
if(entry.getValue().size() > 0)
{
IExternalAccess exta = component.getExternalAccess(entry.getKey());
Future donefut = new Future<>();
compkillbar.addFuture(donefut);
if(debug)
{
component.getLogger().severe("Killing subcomponents1: "+component+", "+entry.getValue());
}
exta.killComponents(entry.getValue().toArray(new IComponentIdentifier[entry.getValue().size()])).addResultListener(new IntermediateDefaultResultListener>>()
{
public void exceptionOccurred(Exception exception)
{
if(debug)
{
component.getLogger().severe("Killing subcomponents2 failed: "+component+", "+entry.getValue()+"\n"+SUtil.getExceptionStacktrace(exception));
}
if (exception instanceof MultiException)
exceptions.addAll(Arrays.asList(((MultiException)exception).getCauses()));
else
exceptions.add(exception);
donefut.setResult(null);
}
public void intermediateResultAvailable(Tuple2> result)
{
if(debug)
{
component.getLogger().severe("Killing subcomponents3: "+component+", "+entry.getValue()+", killed: "+result.getFirstEntity());
}
ret.addIntermediateResult(result);
}
public void finished()
{
if(debug)
{
component.getLogger().severe("Killing subcomponents4 finished: "+component+", "+entry.getValue());
}
donefut.setResult(null);
}
});
}
}
if(locals != null)
{
Future donefut = new Future<>();
compkillbar.addFuture(donefut);
if(debug)
{
component.getLogger().severe("Killing subcomponents5 locals: "+component+", "+locals);
donefut.addResultListener(new IResultListener()
{
@Override
public void resultAvailable(Void result)
{
component.getLogger().severe("Killing subcomponents5a locals done: "+component+", "+exceptions);
}
@Override
public void exceptionOccurred(Exception exception)
{
component.getLogger().severe("Killing subcomponents5b locals failed: "+component+"\n"+SUtil.getExceptionStacktrace(exception));
}
});
}
killLocalComponents(locals.toArray(new IComponentIdentifier[locals.size()])).addResultListener(new IntermediateDefaultResultListener>>()
{
public void exceptionOccurred(Exception exception)
{
if(debug)
{
component.getLogger().severe("Killing subcomponents5c locals failed: "+component+"\n"+SUtil.getExceptionStacktrace(exception));
}
if(exception instanceof MultiException)
exceptions.addAll(Arrays.asList(((MultiException)exception).getCauses()));
else
exceptions.add(exception);
donefut.setResult(null);
}
public void intermediateResultAvailable(Tuple2> result)
{
ret.addIntermediateResult(result);
}
public void finished()
{
donefut.setResult(null);
}
});
}
if(suicide)
{
Future donefut = new Future<>();
compkillbar.addFuture(donefut);
component.killComponent().addResultListener(new IResultListener>()
{
public void resultAvailable(Map result)
{
ret.addIntermediateResult(new Tuple2>(component.getId(), result));
donefut.setResult(null);
}
public void exceptionOccurred(Exception exception)
{
if (exception instanceof MultiException)
exceptions.addAll(Arrays.asList(((MultiException)exception).getCauses()));
else
exceptions.add(exception);
donefut.setResult(null);
}
});
}
compkillbar.waitFor().addResultListener(new IResultListener()
{
public void resultAvailable(Void result)
{
if(exceptions.size() > 0)
ret.setException(new MultiException(exceptions));
else
ret.setFinished();
}
public void exceptionOccurred(Exception exception)
{
}
});
return ret;
}
// /**
// * Starts a new child as subcomponent.
// *
// * @param infos Start information.
// * @return The id of the component and the results after the component has been killed.
// */
// public IFuture createChild(CreationInfo info)
// {
// if (info.getParent() != null && !component.getId().equals(info.getParent()))
// return new Future<>(new IllegalArgumentException("Subcomponent cannot be created if parent is specified: " + info + ", specified parent " + info.getParent()));
//
// info.setParent(component.getId());
// return component.createComponent(info, null);
// }
protected IIntermediateFuture doCreateComponents(List> infos)
{
final IntermediateFuture ret = new IntermediateFuture<>();
DependencyResolver dr = new DependencyResolver<>();
final MultiCollection instances = new MultiCollection<>();
// boolean lineardeps = true;
// for (Tuple2 tup : infos)
// {
// IModelInfo model = tup.getSecondEntity();
// if (!SUtil.arrayEmptyOrNull(model.getPredecessors()) ||
// !SUtil.arrayEmptyOrNull(model.getSuccessors()))
// {
// lineardeps = false;
// break;
// }
// }
boolean lineardeps = false;
if(debug)
System.out.println("Starting subcomponent set for " + component + " uses linear dependencies: " + lineardeps);
// for (Map.Entry>>> entry : modelmap.entrySet())
for(int i = 0; i < infos.size(); ++i)
{
String[] prevdep = lineardeps && i > 0 ? new String[] { infos.get(i - 1).getSecondEntity().getFullName() } : null;
addComponentToLevels(dr, infos.get(i).getFirstEntity(), infos.get(i).getSecondEntity(), instances, prevdep);
}
final List> levels = dr.resolveDependenciesWithLevel();
int[] levelnum = new int[1];
levelnum[0] = -1;
// System.out.println("LEVELS " + levels.size());
// int iii = 0;
// for (Set level : levels)
// {
// System.out.println("Level " + iii + ": " + Arrays.toString(level.toArray()));
// ++iii;
// }
IResultListener levelrl = new IResultListener()
{
public void exceptionOccurred(Exception exception)
{
ret.setExceptionIfUndone(exception);
}
public void resultAvailable(Void result)
{
// if (levels.size() > 1)
// {
// System.out.println("LEVELS: " + Arrays.toString(levels.toArray()));
// for (Set level : levels)
// System.out.println(Arrays.toString(level.toArray()));
// System.out.println("################### WARNING: MORE THAN ONE LEVEL ####################");
// SUtil.sleep(2000);
// }
++levelnum[0];
if (levelnum[0] < levels.size())
{
FutureBarrier levelbar = new FutureBarrier<>();
Set level = levels.get(levelnum[0]);
for (String mname : level)
{
Collection insts = instances.get(mname);
if (insts != null)
{
for (CreationInfo inst : insts)
{
IFuture createfut = createComponent(inst);
levelbar.addFuture(createfut);
createfut.addResultListener(new IResultListener()
{
public void exceptionOccurred(Exception exception)
{
ret.setExceptionIfUndone(exception);
}
public void resultAvailable(IExternalAccess result)
{
if (debug)
System.out.println("Started: " + result);
ret.addIntermediateResultIfUndone(result);
};
});
}
}
else if (debug)
{
System.out.println("Skipping unresolvable dependency: " + mname);
}
}
levelbar.waitFor().addResultListener(this);
}
else
{
if (!ret.isDone())
ret.setFinished();
}
}
};
levelrl.resultAvailable(null);
return ret;
}
/**
* Stops a set of components, in order of dependencies.
*
* @param cids The component identifiers.
* @return The id of the component and the results after the component has been killed.
*/
protected IIntermediateFuture>> killLocalComponents(IComponentIdentifier... cids)
{
if (cids == null || cids.length == 0)
return new IntermediateFuture>>(new IllegalArgumentException("Component identifiers must not be null or empty."));
try
{
debug = debug | Arrays.asList(cids).stream().anyMatch(id ->
SComponentManagementService.internalGetComponentDescription(id)!=null
&& PlatformComponent._BROKEN.contains(SComponentManagementService.internalGetComponentDescription(id).getModelName()));
if(debug)
{
component.getLogger().severe("killLocalComponents00: "+component+", "+SUtil.arrayToString(cids));
}
}
catch(Throwable e)
{
debug = true;
component.getLogger().severe("killLocalComponents00a: "+component+", "+SUtil.arrayToString(cids)+"\n"+SUtil.getExceptionStacktrace(e));
}
final IntermediateFuture>> ret = new IntermediateFuture<>();
final List sysinfos = new ArrayList<>();
final List userinfos = new ArrayList<>();
for (int i = 0; i < cids.length; ++i)
{
IComponentDescription desc = SComponentManagementService.getDescription(cids[i]);
if(desc!=null && desc.isSystemComponent())
{
sysinfos.add(cids[i]);
}
else if(desc!=null)
{
userinfos.add(cids[i]);
}
// else ignore when component already terminated
}
if (userinfos.size() > 0)
{
if(debug)
{
component.getLogger().severe("killLocalComponents0 user " + component+ ", " + userinfos);
}
doKillComponents(userinfos).addResultListener(new IntermediateDefaultResultListener>>()
{
public void intermediateResultAvailable(Tuple2> result)
{
ret.addIntermediateResult(result);
}
public void exceptionOccurred(Exception exception)
{
if(debug)
{
component.getLogger().severe("User kill failed: "+component+"\n"+SUtil.getExceptionStacktrace(exception));
}
ret.setException(exception);
}
public void finished()
{
if(debug)
{
component.getLogger().severe("User kill done, killing sysagents..." + sysinfos.size());
}
if (!ret.isDone())
{
if (sysinfos.size() > 0)
doKillComponents(sysinfos).addResultListener(new IntermediateDelegationResultListener<>(ret));
else
ret.setFinished();
}
}
});
}
else
{
if (sysinfos.size() > 0)
doKillComponents(sysinfos).addResultListener(new IntermediateDelegationResultListener<>(ret));
else
ret.setFinished();
}
return ret;
}
protected IIntermediateFuture>> doKillComponents(List cids)
{
final IntermediateFuture>> ret = new IntermediateFuture<>();
final MultiCollection instances = new MultiCollection<>();
getShutdownLevels(instances, cids).addResultListener(new IResultListener>>()
{
public void resultAvailable(List> levels)
{
int[] levelnum = new int[1];
levelnum[0] = -1;
IResultListener levelrl = new IResultListener()
{
public void exceptionOccurred(Exception exception)
{
ret.setExceptionIfUndone(exception);
}
public void resultAvailable(Void result)
{
++levelnum[0];
final List exceptions = new ArrayList<>();
if (levelnum[0] < levels.size())
{
FutureBarrier> levelbar = new FutureBarrier<>();
Set level = levels.get(levelnum[0]);
for (String mname : level)
{
Collection insts = instances.get(mname);
if (insts != null)
{
for (IComponentIdentifier inst : insts)
{
IFuture> killfut = null;
IExternalAccess tmpexta = null;
try
{
tmpexta = SComponentManagementService.getExternalAccess(inst, component);
}
catch (Exception e)
{
exceptions.add(e);
continue;
}
final IExternalAccess exta = tmpexta;
if (exta != null)
{
if(debug)
{
component.getLogger().severe("doKillComponents2: start kill: " + inst+", "+IComponentIdentifier.LOCAL.get());
}
try
{
killfut = exta.killComponent();
}
catch(ComponentTerminatedException e)
{
// ignore
if(debug)
{
component.getLogger().severe("doKillComponents2a: kill failed: " + inst+"\n"+SUtil.getExceptionStacktrace(e));
}
}
}
if(killfut!=null)
{
// Copy future to filter out ComponentTerminatedException
Future> killfut2 = new Future>();
levelbar.addFuture(killfut2);
killfut.addResultListener(new IResultListener>()
{
public void exceptionOccurred(Exception exception)
{
// Ignore if already killed from outside during parent shutdown in progress
if(exception instanceof ComponentTerminatedException)
{
killfut2.setResult(null);
}
else
{
if(debug)
{
component.getLogger().severe("doKillComponents3: kill failed: " + inst+"\n"+SUtil.getExceptionStacktrace(exception));
}
exceptions.add(exception);
killfut2.setException(exception);
}
}
public void resultAvailable(Map result)
{
killfut2.setResult(result);
if(debug)
{
component.getLogger().severe("doKillComponents4: kill succeedeed: " + inst);
}
ret.addIntermediateResultIfUndone(new Tuple2>(inst, result));
};
});
}
}
}
}
levelbar.waitFor().addResultListener(this);
}
else
{
if (!ret.isDone())
{
if (exceptions.size() > 0)
ret.setException(new MultiException(exceptions));
else
ret.setFinished();
}
}
}
};
levelrl.resultAvailable(null);
}
public void exceptionOccurred(Exception exception)
{
ret.setExceptionIfUndone(exception);
}
});
return ret;
}
/**
* Gets the ordered shutdown levels for a number of components.
*
* @param instances Empty lookup map type->instance (will be filled by the method.
* @param cids The component identifiers.
* @return Levels containing types defining shutdown order.
*/
protected IFuture>> getShutdownLevels(final MultiCollection instances, List cids)
{
try {
if(debug)
{
component.getLogger().severe("getShutdownLevels0: "+instances+", "+cids);
}
if (cids == null || cids.size() == 0)
return new Future>>(new IllegalArgumentException("Component identifiers must not be null or empty."));
final Future>> ret = new Future<>();
FutureBarrier modelbar = new FutureBarrier<>();
final Map> modelmap = new HashMap<>();
for (int i = 0; i < cids.size(); ++i)
{
if(debug)
{
component.getLogger().severe("getShutdownLevels1: getModelAsync0 "+component+", "+i);
}
try
{
IExternalAccess exta = component.getExternalAccess(cids.get(i));
IFuture fut = exta.getModelAsync();
modelmap.put(i, fut);
modelbar.addFuture(fut);
if(debug)
{
component.getLogger().severe("getShutdownLevels1: getModelAsync1 "+component+", "+exta);
}
}
catch(Exception e)
{
// Ignore when component killed itself in mean time.
if(debug)
{
component.getLogger().severe("getShutdownLevels1a: getModelAsync1 failed "+component+"\n"+SUtil.getExceptionStacktrace(e));
}
}
}
modelbar.waitFor().addResultListener(new ExceptionDelegationResultListener>>(ret)
{
public void customResultAvailable(Void result)
{
if(debug)
{
component.getLogger().severe("getShutdownLevels2: getModelAsync done "+component);
}
// boolean lineardeps = true;
// for (Map.Entry> entry : modelmap.entrySet())
// {
// IModelInfo model = entry.getValue().get();
// if (!SUtil.arrayEmptyOrNull(model.getPredecessors()) ||
// !SUtil.arrayEmptyOrNull(model.getSuccessors()))
// {
// lineardeps = false;
// break;
// }
// }
boolean lineardeps = false;
DependencyResolver dr = new DependencyResolver<>();
IModelInfo prev = null;
for (Map.Entry> entry : modelmap.entrySet())
{
String[] prevdep = lineardeps && prev != null ? new String[] { prev.getFullName() } : null;
try
{
addComponentToLevels(dr, cids.get(entry.getKey()), entry.getValue().get(), instances, prevdep);
}
catch (Exception e)
{
ret.setException(e);
return;
}
prev = entry.getValue().get();
}
List> levels = dr.resolveDependenciesWithLevel();
Collections.reverse(levels);
ret.setResult(levels);
}
});
return ret;
}
catch(Throwable t)
{
// if(debug)
{
component.getLogger().severe("getShutdownLevelsO: failed "+component+"\n"+SUtil.getExceptionStacktrace(t));
}
throw SUtil.throwUnchecked(t);
}
}
/**
* Create the initial subcomponents.
*/
protected IFuture> createInitialComponents(final ComponentInstanceInfo[] components)
{
// System.out.println("create subcompos: ");
// for(ComponentInstanceInfo cii: components)
// {
// System.out.println(cii.getName()+" "+cii.getTypeName());
// }
final Future res = new Future();
final List cinfos = new ArrayList();
// IComponentManagementService cms = getComponent().getFeature(IRequiredServicesFeature.class).getLocalService(new ServiceQuery<>(IComponentManagementService.class));
// NOTE: in current implementation application waits for subcomponents
// to be finished and cms implements a hack to get the external
// access of an uninited parent.
// (NOTE1: parent cannot wait for subcomponents to be all created
// before setting itself inited=true, because subcomponents need
// the parent external access.)
// (NOTE2: subcomponents must be created one by one as they
// might depend on each other (e.g. bdi factory must be there for jcc)).
// createInitialComponent(components, component.getModel(), 0, res, cids);
createInitialCreationInfos(components, component.getModel(), 0, res, cinfos);
final Future> ret = new Future>();
res.addResultListener(new ExceptionDelegationResultListener>(ret)
{
public void customResultAvailable(Void result)
{
if (cinfos != null && !cinfos.isEmpty())
{
createComponents(cinfos.toArray(new CreationInfo[cinfos.size()])).addResultListener(new ExceptionDelegationResultListener, List>(ret)
{
public void customResultAvailable(Collection result)
{
List cids = new ArrayList<>();
for (IExternalAccess exta : SUtil.notNull(result))
cids.add(exta.getId());
ret.setResult(cids);
}
});
}
else
{
ret.setResult(null);
}
}
});
return ret;
}
/**
* Search for components matching the given description.
* @return An array of matching component descriptions.
*/
public IFuture searchComponents(IComponentDescription adesc, ISearchConstraints con)
{
return getComponent().searchComponents(adesc, con);
}
/**
* Create a subcomponent.
* @param component The instance info.
*/
// public IFuture createChild(final ComponentInstanceInfo component)
// {
// final Future ret = new Future();
// createComponents(new ComponentInstanceInfo[]{component}).addResultListener(createResultListener(
// new ExceptionDelegationResultListener, IComponentIdentifier>(ret)
// {
// public void customResultAvailable(List cids)
// {
// ret.setResult(cids.get(0));
// }
// }));
// return ret;
// }
/**
* Create initial subcomponents.
*/
protected void createInitialCreationInfos(final ComponentInstanceInfo[] components, final IModelInfo model, final int i, final Future fut, final List cinfos)
{
if(i0)
// System.out.println("create comp: "+components[i].getName());
IResultListener crl = new CollectionResultListener(num, false,
component.getFeature(IExecutionFeature.class).createResultListener(new ExceptionDelegationResultListener, Void>(fut)
{
public void customResultAvailable(Collection result)
{
// if(num>0)
// System.out.println("created comp: "+components[i].getName());
cinfos.addAll(result);
createInitialCreationInfos(components, model, i+1, fut, cinfos);
}
}));
for(int j=0; j()
// {
// public void resultAvailable(IExternalAccess result)
// {
// crl.resultAvailable(result.getId());
// }
//
// public void exceptionOccurred(Exception exception)
// {
// crl.exceptionOccurred(exception);
// }
// });
// cms.createComponent(getName(components[i], model, j+1), getFilename(components[i], model),
// new CreationInfo(components[i].getConfiguration(), getArguments(components[i], model), component.getId(),
// suspend, master, daemon, autoshutdown, synchronous, persistable, monitoring, model.getAllImports(), bindings, null),
// null).addResultListener(crl);
}
else
{
crl.exceptionOccurred(new RuntimeException("No such component type: "+components[i].getTypeName()));
}
}
}
else
{
fut.setResult(null);
}
}
/**
* Get the number of components to start.
* Allows filename to be dynamically evaluated.
* @return The number.
*/
protected String getFilename(ComponentInstanceInfo component, IModelInfo model)
{
String ret = null;
SubcomponentTypeInfo si = component.getType(model);
ret = (String)SJavaParser.evaluateExpressionPotentially(si.getFilename(), model.getAllImports(), this.component.getFetcher(), this.component.getClassLoader());
// if(si.getFilename()!=null && si.getFilename().startsWith("%{"))
// {
// try
// {
// ret = (String)SJavaParser.evaluateExpression(si.getFilename().substring(2, si.getFilename().length()-1), model.getAllImports(), this.component.getFetcher(), this.component.getClassLoader());
// }
// catch(Exception e)
// {
// ret = si.getFilename();
// }
// }
// else
// {
// ret = si.getFilename();
// }
return ret;
}
/**
* Get the number of components to start.
* @return The number.
*/
protected int getNumber(ComponentInstanceInfo component, IModelInfo model)
{
Object ret = component.getNumber()!=null? SJavaParser.evaluateExpression(component.getNumber(), model.getAllImports(), this.component.getFetcher(), this.component.getClassLoader()): null;
return ret instanceof Integer? ((Integer)ret).intValue(): 1;
}
/**
* Get the name of components to start.
* @return The name.
*/
protected String getName(ComponentInstanceInfo component, IModelInfo model, int cnt)
{
String ret = component.getName();
if(ret!=null)
{
SimpleValueFetcher fetcher = new SimpleValueFetcher(this.component.getFetcher());
fetcher.setValue("$n", Integer.valueOf(cnt));
try
{
if(SJavaParser.isExpressionString(component.getName()))
ret = (String)SJavaParser.evaluateExpressionPotentially(component.getName(), model.getAllImports(), fetcher, this.component.getClassLoader());
else
ret = (String)SJavaParser.evaluateExpression(component.getName(), model.getAllImports(), fetcher, this.component.getClassLoader());
if(ret==null)
ret = component.getName();
}
catch(RuntimeException e)
{
}
}
return ret;
}
/**
* Get the arguments.
* @return The arguments as a map of name-value pairs.
*/
protected Map getArguments(ComponentInstanceInfo component, IModelInfo model)
{
Map ret = null;
UnparsedExpression[] arguments = component.getArguments();
UnparsedExpression argumentsexp = component.getArgumentsExpression();
if(arguments.length>0)
{
ret = new HashMap();
for(int i=0; i0)
{
Object val = SJavaParser.evaluateExpression(arguments[i].getValue(), model.getAllImports(), this.component.getFetcher(), this.component.getClassLoader());
ret.put(arguments[i].getName(), val);
}
}
}
else if(argumentsexp!=null && argumentsexp.getValue()!=null && argumentsexp.getValue().length()>0)
{
// todo: language
ret = (Map)SJavaParser.evaluateExpression(argumentsexp.getValue(), model.getAllImports(), this.component.getFetcher(), this.component.getClassLoader());
}
return ret;
}
//-------- IInternalSubcomponentsFeature interface -------
/**
* Called, when a subcomponent has been created.
*/
public IFuture componentCreated(final IComponentDescription desc)
{
// Throw component events for extensions (envsupport)
final IMonitoringComponentFeature mon = getComponent().getFeature0(IMonitoringComponentFeature.class);
if(mon!=null)
{
return getComponent().getFeature(IExecutionFeature.class).scheduleStep(new ImmediateComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
Future ret = new Future();
if(mon.hasEventTargets(PublishTarget.TOALL, PublishEventLevel.COARSE))
{
// desc.getCause()
MonitoringEvent me = new MonitoringEvent(desc.getName(), desc.getCreationTime(),
MonitoringEvent.TYPE_COMPONENT_CREATED, desc.getCreationTime(), PublishEventLevel.COARSE);
me.setProperty("details", desc);
// for extensions only
mon.publishEvent(me, PublishTarget.TOALL) .addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
return ret;
}
});
}
else
{
return IFuture.DONE;
}
}
/**
* Called, when a subcomponent has been removed.
*/
public IFuture componentRemoved(final IComponentDescription desc)
{
// Throw component events for extensions (envsupport)
final IMonitoringComponentFeature mon = getComponent().getFeature0(IMonitoringComponentFeature.class);
if(mon!=null)
{
return getComponent().getFeature(IExecutionFeature.class).scheduleStep(new ImmediateComponentStep()
{
public IFuture execute(IInternalAccess ia)
{
Future ret = new Future();
if(mon.hasEventTargets(PublishTarget.TOALL, PublishEventLevel.COARSE))
{
// desc.getCause()
long time = getComponent().getFeature(IRequiredServicesFeature.class).getLocalService(new ServiceQuery<>(IClockService.class)).getTime();
MonitoringEvent me = new MonitoringEvent(desc.getName(), desc.getCreationTime(),
MonitoringEvent.TYPE_COMPONENT_DISPOSED, time, PublishEventLevel.COARSE);
me.setProperty("details", desc);
// for extensions only
mon.publishEvent(me, PublishTarget.TOALL) .addResultListener(new DelegationResultListener(ret));
}
else
{
ret.setResult(null);
}
return ret;
}
});
}
else
{
return IFuture.DONE;
}
}
/**
* Create a result listener that is executed on the
* component thread.
*/
public IResultListener createResultListener(IResultListener listener)
{
return getComponent().getFeature(IExecutionFeature.class).createResultListener(listener);
}
/**
* Test if the current thread is an external thread.
*/
protected boolean isExternalThread()
{
return !getComponent().getFeature(IExecutionFeature.class).isComponentThread();
}
/**
* Get the childcount.
* @return the childcount.
*/
public int getChildcount()
{
return ((CMSComponentDescription)getComponent().getDescription()).getChildren().length;
// return childcount;
}
// /**
// * Set the child count.
// * @param childcount the childcount to set.
// */
// public void setChildcount(int childcount)
// {
// this.childcount = childcount;
// }
// /**
// * Inc the child count.
// */
// public int incChildcount()
// {
// return ++this.childcount;
// }
//
// /**
// * Dec the child count.
// */
// public int decChildcount()
// {
// return childcount>0? --childcount: childcount;
// }
/**
* Get the children (if any) component identifiers.
* @param type The local child type.
* @param parent The parent (null for this).
* @return The children component identifiers.
*/
public IFuture getChildren(String type, IComponentIdentifier parent)
{
return getComponent().getChildren(type, parent);
}
/**
* Get the local type name of this component as defined in the parent.
* @return The type of this component type.
*/
public IFuture getLocalTypeAsync()
{
return new Future(getLocalType());
}
/**
* Add a components to the dependency resolver to build start levels.
* Components of the same level can be started in parallel.
*/
protected void addComponentToLevels(DependencyResolver dr, T instanceinfo, IModelInfo minfo, MultiCollection instances, String... addpredecessors)
{
try
{
String cname = minfo.getFullName();
dr.addNode(cname);
String[] pres = minfo.getPredecessors();
if(pres!=null)
{
for(String pre: pres)
dr.addDependency(cname, (String)pre);
}
if (addpredecessors != null)
{
for (String addpredecessor : addpredecessors)
dr.addDependency(cname, addpredecessor);
}
Object[] sucs = minfo.getSuccessors();
if(sucs!=null)
{
for(Object suc: sucs)
dr.addDependency((String)suc, cname);
}
// no predecessors
if(debug && (pres==null || pres.length==0))
System.err.println("NO PREDECESSORS: " + cname + " " + (pres == null ? "null" : Arrays.toString(pres)));
instances.add(cname, instanceinfo);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}