package com.netifera.platform.kernel.internal.probe;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.osgi.service.component.ComponentContext;
import com.netifera.platform.api.channels.IChannelConnecter;
import com.netifera.platform.api.channels.IChannelRegistry;
import com.netifera.platform.api.dispatcher.DispatchException;
import com.netifera.platform.api.dispatcher.DispatchMismatchException;
import com.netifera.platform.api.dispatcher.IClientDispatcher;
import com.netifera.platform.api.dispatcher.IMessageDispatcher;
import com.netifera.platform.api.dispatcher.IMessageDispatcherService;
import com.netifera.platform.api.dispatcher.IMessageHandler;
import com.netifera.platform.api.dispatcher.IMessenger;
import com.netifera.platform.api.dispatcher.IProbeMessage;
import com.netifera.platform.api.events.EventListenerManager;
import com.netifera.platform.api.events.IEvent;
import com.netifera.platform.api.events.IEventHandler;
import com.netifera.platform.api.log.ILogManager;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.api.model.AbstractEntity;
import com.netifera.platform.api.model.IEntity;
import com.netifera.platform.api.model.IModelPredicate;
import com.netifera.platform.api.model.IModelService;
import com.netifera.platform.api.model.IWorkspace;
import com.netifera.platform.api.probe.IProbe;
import com.netifera.platform.api.probe.IProbeManagerService;
import com.netifera.platform.api.tasks.ITaskClient;
import com.netifera.platform.api.tasks.ITaskOutput;
import com.netifera.platform.api.tasks.ITaskStatus;
import com.netifera.platform.api.tasks.TaskOutputMessage;
import com.netifera.platform.model.ModelUpdate;
import com.netifera.platform.model.ProbeEntity;
import com.netifera.platform.tasks.messages.TaskChangedMessage;
/**
* This service manages probes on the client side.
*/
public class ProbeManagerService implements IProbeManagerService {
public static final int LOCAL_PROBE_ID = 0;
private IModelService modelService;
private final Set<ProbeClient> probeSet =
Collections.synchronizedSet(new HashSet<ProbeClient>());
private ILogger logger;
private IClientDispatcher clientDispatcher;
private IChannelRegistry channelRegistry;
private final EventListenerManager eventManager = new EventListenerManager();
public ProbeClient getLocalProbe() {
return getProbeById(LOCAL_PROBE_ID);
}
public List<IProbe> getProbeList() {
return new ArrayList<IProbe>(probeSet);
}
public ProbeClient getProbeById(long probeId) {
synchronized(probeSet) {
for(ProbeClient probe : probeSet) {
if(probe.getProbeId() == probeId)
return probe;
}
return null;
}
}
private IWorkspace getWorkspace() {
if(modelService.getCurrentWorkspace() == null) {
throw new IllegalStateException("Cannot initialize probe manager because no workspace is currently open");
}
return modelService.getCurrentWorkspace();
}
private void initialize() {
logger.debug("Initializing ProbeManagerService");
/* Make sure the current workspace has saved a local probe entity */
final List<ProbeEntity> results = getWorkspace().findByPredicate(ProbeEntity.class,
new IModelPredicate<ProbeEntity>() {
public boolean match(ProbeEntity candidate) {
return candidate.getProbeId() == LOCAL_PROBE_ID;
}
});
/* if not, create it */
if(results.isEmpty()) {
createLocalProbeEntity();
}
for(ProbeEntity p : getWorkspace().findAll(ProbeEntity.class)) {
logger.debug("Adding probe with probe id: " + p.getProbeId() + " entity id: " + p.getId());
ProbeClient probe = new ProbeClient(this, p, logger);
probeSet.add(probe);
}
ProbeClient localProbe = getLocalProbe();
if(localProbe == null) {
throw new IllegalStateException("Local probe does not exist in model");
}
localProbe.connect();
}
/*
* This is where the local probe entity is created if it doesn't already exist in the currently opened workspace
*/
private ProbeEntity createLocalProbeEntity() {
logger.debug("Creating local probe entity");
final ProbeEntity entity = new ProbeEntity(getWorkspace(), 0);
entity.setProbeId(LOCAL_PROBE_ID);
entity.setLocal(true);
entity.setName("Local Probe");
entity.setChannelConfig("local");
entity.save();
return entity;
}
public IProbe createProbe(IEntity hostEntity, String name, String config, long spaceId) {
final ProbeEntity entity = new ProbeEntity(getWorkspace(), hostEntity);
entity.setLocal(false);
entity.setName(name);
entity.setChannelConfig(config);
entity.setProbeId(modelService.getCurrentWorkspace().generateProbeId());
entity.save();
((AbstractEntity)hostEntity).addTag("Controlled");
((AbstractEntity)hostEntity).update();
// ((AbstractEntity)hostEntity).addToSpace(spaceId);
final ProbeClient probe = new ProbeClient(this, entity, logger);
probeSet.add(probe);
eventManager.fireEvent(new IEvent() {});
if(spaceId > 0)
entity.addToSpace(spaceId);
return probe;
}
public IProbe createProbe(String name, String config) {
logger.debug("Creating probe named " + name);
final ProbeEntity entity = new ProbeEntity(getWorkspace(), 0);
entity.setLocal(false);
entity.setName(name);
entity.setChannelConfig(config);
entity.setProbeId(modelService.getCurrentWorkspace().generateProbeId());
entity.save();
final ProbeClient probe = new ProbeClient(this, entity, logger);
probeSet.add(probe);
eventManager.fireEvent(new IEvent() {});
return probe;
}
void fireChangeEvent() {
eventManager.fireEvent(new IEvent() {});
}
public void addProbeChangeListener(IEventHandler handler) {
eventManager.addListener(handler);
}
public void removeProbeChangeListener(IEventHandler handler) {
eventManager.removeListener(handler);
}
IChannelConnecter createChannelConnecter(String config) {
return channelRegistry.createConnecter(config);
}
private void registerHandlers(IMessageDispatcher dispatcher) {
IMessageHandler handler = new IMessageHandler() {
public void call(IMessenger messenger, IProbeMessage message)
throws DispatchException {
final ITaskClient taskClient = messenger.getProbe().getTaskClient();
if(message instanceof TaskChangedMessage) {
taskChangedHandler(taskClient, (TaskChangedMessage) message);
} else if (message instanceof TaskOutputMessage) {
taskOutputHandler(taskClient, (TaskOutputMessage) message);
} else if (message instanceof ModelUpdate) {
modelUpdateHandler(messenger, (ModelUpdate)message);
} else {
throw new DispatchMismatchException(message);
}
}
};
dispatcher.registerMessageHandler(TaskChangedMessage.ID, handler);
dispatcher.registerMessageHandler(TaskOutputMessage.ID, handler);
dispatcher.registerMessageHandler(ModelUpdate.ID, handler);
}
private void taskChangedHandler(ITaskClient taskClient, TaskChangedMessage message) {
for(ITaskStatus record : message.getTaskList())
taskClient.taskChanged(record);
}
private void taskOutputHandler(ITaskClient taskClient, TaskOutputMessage message) {
for(ITaskOutput output : message.getTaskOutput())
taskClient.addMessage(output);
}
private void modelUpdateHandler(IMessenger messenger, ModelUpdate update) {
ProbeClient probe = (ProbeClient) messenger.getProbe();
probe.processModelUpdate(update);
}
/* OSGi service */
private IEventHandler handler;
protected void activate(ComponentContext ctx) {
handler = new IEventHandler() {
public void handleEvent(IEvent event) {
initialize();
}
};
if(modelService.addWorkspaceOpenListener(handler))
initialize();
}
protected void deactivate(ComponentContext ctx) {
modelService.removeWorkspaceOpenListener(handler);
}
protected void setModelService(IModelService modelService) {
this.modelService = modelService;
}
protected void unsetModelService(IModelService modelService) {
this.modelService = null;
}
protected void setLogManager(ILogManager logManager) {
logger = logManager.getLogger("Probe Manager");
}
protected void unsetLogManager(ILogManager logManager) {
logger = null;
}
protected void setDispatcher(IMessageDispatcherService dispatcher) {
clientDispatcher = dispatcher.getClientDispatcher();
registerHandlers(clientDispatcher);
}
protected void unsetDispatcher(IMessageDispatcherService dispatcher) {
clientDispatcher = null;
}
protected void setChannelRegistry(IChannelRegistry channelRegistry) {
this.channelRegistry = channelRegistry;
}
protected void unsetChannelRegistry(IChannelRegistry channelRegistry) {
this.channelRegistry = null;
}
}