/*******************************************************************************
* Copyright (c) 2014, 2015 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.locator.utils;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.tcf.protocol.IPeer;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.callback.Callback;
import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.runtime.services.ServiceManager;
import org.eclipse.tcf.te.runtime.services.interfaces.IService;
import org.eclipse.tcf.te.runtime.services.interfaces.ISimulatorService;
import org.eclipse.tcf.te.tcf.core.interfaces.IPeerProperties;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
/**
* Simulator related utilities.
*/
public final class SimulatorUtils {
/**
* Result of getSimulatorService.
*/
public static class Result {
public ISimulatorService service;
public String id;
public String settings;
}
/**
* Returns if or if the given peer model has the simulator enabled or not.
*
* @param peerNode The peer model node. Must not be <code>null</code>.
* @return <code>True</code> if the simulator is enabled, <code>false</code> otherwise.
*/
public static boolean isSimulatorEnabled(final IPeerNode peerNode) {
Assert.isNotNull(peerNode);
final AtomicBoolean isEnabled = new AtomicBoolean(false);
Runnable runnable = new Runnable() {
@Override
public void run() {
String subType = peerNode.getPeer().getAttributes().get(IPeerProperties.PROP_SUBTYPE);
if (subType != null) {
isEnabled.set(subType.equals(IPeerProperties.SUBTYPE_SIM));
}
}
};
if (Protocol.isDispatchThread()) runnable.run();
else Protocol.invokeAndWait(runnable);
return isEnabled.get();
}
/**
* Returns the simulator service and the settings for the simulator launch.
* If no simulator service is configured in the peer
* or the configured service is not available, <code>null</code> will be returned.
*
* @param peerNode The peer model node. Must not be <code>null</code>.
* @return The {@link Result} containing the simulator service and the settings or <code>null</code>.
*/
public static Result getSimulatorService(final IPeerNode peerNode) {
Assert.isNotNull(peerNode);
Result result = null;
IPeer peer = peerNode.getPeer();
if (peer != null) {
if (isSimulatorEnabled(peerNode)) {
String type = peer.getAttributes().get(IPeerProperties.PROP_SIM_TYPE);
IService[] services = ServiceManager.getInstance().getServices(peerNode, ISimulatorService.class, false);
for (IService service : services) {
Assert.isTrue(service instanceof ISimulatorService);
// Get the UI service which is associated with the simulator service
String id = service.getId();
if (id != null && id.equals(type)) {
result = new Result();
result.service = (ISimulatorService)service;
result.id = id;
result.settings = peer.getAttributes().get(IPeerProperties.PROP_SIM_PROPERTIES);
break;
}
}
}
}
return result;
}
/**
* Returns the simulator service and the settings for the simulator launch.
* If no simulator service is configured in the peer
* or the configured service is not available, <code>null</code> will be returned.
*
* @param peerNode The peer model node. Must not be <code>null</code>.
* @return The {@link Result} containing the simulator service and the settings or <code>null</code>.
*/
public static ISimulatorService getSimulatorService(final Object context, final String type) {
Assert.isNotNull(context);
IService[] services = ServiceManager.getInstance().getServices(context, ISimulatorService.class, false);
for (IService service : services) {
Assert.isTrue(service instanceof ISimulatorService);
// Get the UI service which is associated with the simulator service
String id = service.getId();
if (id != null && id.equals(type)) {
return (ISimulatorService)service;
}
}
return null;
}
/**
* Starts the simulator if the simulator launch is enabled for the given peer
* model node and the configured simulator service type is available. In any
* other cases, the given callback is invoked immediately.
*
* @param peerNode The peer model node. Must not be <code>null</code>.
* @param monitor The progress monitor.
* @param callback The callback to invoke if finished. Must not be <code>null</code>.
*/
public static void start(final IPeerNode peerNode, final IProgressMonitor monitor, final ICallback callback) {
Assert.isNotNull(peerNode);
Assert.isNotNull(callback);
// Determine if we have to start a simulator first
final Result result = getSimulatorService(peerNode);
if (result != null && result.service != null) {
// Check if the simulator is already running
result.service.isRunning(peerNode, result.settings, new Callback() {
@Override
protected void internalDone(Object caller, IStatus status) {
Object cbResult = getResult();
if (cbResult instanceof Boolean && !((Boolean)cbResult).booleanValue()) {
// Start the simulator
result.service.start(peerNode, result.settings, new Callback() {
@Override
protected void internalDone(Object caller, IStatus status) {
setUsedRunningSimulator(peerNode, false);
callback.setResult(new Boolean(status.isOK()));
callback.done(caller, status);
}
}, monitor);
} else {
// Try to use running simulator
result.service.useRunning(peerNode, result.settings, new Callback() {
@Override
protected void internalDone(Object caller, IStatus status) {
setUsedRunningSimulator(peerNode, true);
callback.setResult(new Boolean(status.isOK()));
callback.done(caller, status);
}
}, monitor);
}
}
}, monitor);
} else {
setUsedRunningSimulator(peerNode, false);
callback.setResult(Boolean.FALSE);
callback.done(null, Status.OK_STATUS);
}
}
protected static void setUsedRunningSimulator(final IPeerNode peerNode, final boolean usedRunning) {
Protocol.invokeAndWait(new Runnable() {
@Override
public void run() {
peerNode.setProperty(SimulatorUtils.class.getSimpleName() + ".usedRunning", usedRunning ? new Boolean(usedRunning) : null); //$NON-NLS-1$
}
});
}
protected static boolean getUsedRunningSimulator(final IPeerNode peerNode) {
final AtomicBoolean usedRunning = new AtomicBoolean(false);
Protocol.invokeAndWait(new Runnable() {
@Override
public void run() {
usedRunning.set(peerNode.getBooleanProperty(SimulatorUtils.class.getSimpleName() + ".usedRunning")); //$NON-NLS-1$
}
});
return usedRunning.get();
}
/**
* Stops the simulator if the simulator launch is enabled for the given peer
* model node and the configured simulator service type is available. In any
* other cases, the given callback is invoked immediately.
*
* @param peerNode The peer model node. Must not be <code>null</code>.
* @param monitor The progress monitor.
* @param callback The callback to invoke if finished. Must not be <code>null</code>.
*/
public static void stop(final IPeerNode peerNode, final IProgressMonitor monitor, final ICallback callback) {
Assert.isNotNull(peerNode);
Assert.isNotNull(callback);
// Get the associated simulator service
final Result result = getSimulatorService(peerNode);
if (result != null && result.service != null && !getUsedRunningSimulator(peerNode)) {
setUsedRunningSimulator(peerNode, false);
// Determine if the simulator is at all running
result.service.isRunning(peerNode, result.settings, new Callback() {
@Override
protected void internalDone(Object caller, IStatus status) {
Object cbResult = getResult();
if (cbResult instanceof Boolean && ((Boolean)cbResult).booleanValue()) {
// Stop the simulator
result.service.stop(peerNode, result.settings, new Callback(callback) {
@Override
protected void internalDone(Object caller, IStatus status) {
callback.done(caller, status);
}
}, monitor);
} else {
result.service.cleanup(peerNode, result.settings);
callback.done(null, Status.OK_STATUS);
}
}
}, monitor);
} else {
setUsedRunningSimulator(peerNode, false);
callback.done(null, Status.OK_STATUS);
}
}
}