blob: a9d2cbd08b3a3eeb24e9cec4a8ed29189fd4e091 [file] [log] [blame]
package org.eclipse.ease.modules.platform;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.ease.modules.ScriptParameter;
import org.eclipse.ease.modules.WrapToScript;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.services.IEvaluationService;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
/**
* Provides global platform functions like preferences, event bus or the command framework.
*/
public class PlatformModule {
/**
* Event handler to wait for a given topic.
*/
private static class WaitingEventHandler implements EventHandler {
private Event fEvent = null;
@Override
public synchronized void handleEvent(final Event event) {
fEvent = event;
notify();
}
}
/** Module identifier. */
public static final String MODULE_ID = "/System/Platform";
/**
* Adapt object to target type. Try to get an adapter for an object.
*
* @param source
* object to adapt
* @param target
* target class to adapt to
* @return adapted object or <code>null</code>
*/
@WrapToScript
public static Object adapt(final Object source, final Class<?> target) {
return Platform.getAdapterManager().getAdapter(source, target);
}
/**
* Get a platform service.
*
* @param type
* service type
* @return service instance or <code>null</code>
*/
@WrapToScript
public static Object getService(final Class<?> type) {
return PlatformUI.getWorkbench().getService(type);
}
/**
* Execute a command from the command framework. As we have no UI available, we do not pass a control to the command. Hence HandlerUtil.getActive...
* commands will very likely fail.
*
* @param commandId
* full id of the command to execute
* @param parameters
* command parameters
* @throws ExecutionException
* If the handler has problems executing this command.
* @throws NotDefinedException
* If the command you are trying to execute is not defined.
* @throws NotEnabledException
* If the command you are trying to execute is not enabled.
* @throws NotHandledException
* If there is no handler.
*/
@WrapToScript
public static void executeCommand(final String commandId, @ScriptParameter(defaultValue = ScriptParameter.NULL) final Map<String, String> parameters)
throws ExecutionException, NotDefinedException, NotEnabledException, NotHandledException {
final Map<String, String> commandParameters = (parameters != null) ? parameters : new HashMap<>();
final ICommandService commandService = (ICommandService) getService(ICommandService.class);
final IEvaluationService evaluationService = (IEvaluationService) getService(IEvaluationService.class);
final Command command = commandService.getCommand(commandId);
command.executeWithChecks(new ExecutionEvent(command, commandParameters, null, evaluationService.getCurrentState()));
}
/**
* Get a system property value
*
* @param key
* key to query
* @return system property for <i>key</i>
*/
@WrapToScript
public static String getSystemProperty(final String key) {
return System.getProperty(key);
}
/**
* Run an external process. The process is started in the background and a {@link FutureX} object is returned. Query the result for finished state, output
* and error streams of the executed process.
*
* @param name
* program to run (with full path if necessary)
* @param args
* program arguments
* @return process object to track proces execution
* @throws IOException
* if an I/O error occurs
*/
@WrapToScript
public static Process runProcess(final String name, @ScriptParameter(defaultValue = ScriptParameter.NULL) final String[] args) throws IOException {
final List<String> arguments = new ArrayList<>();
arguments.add(name);
if (args != null) {
for (final String arg : args)
arguments.add(arg);
}
final ProcessBuilder builder = new ProcessBuilder(arguments);
return builder.start();
}
/**
* Read a preferences value. The <i>defaultValue</i> is optional, but contains type information if used. Provide instances of Boolean, Integer, Double,
* Float, Long, byte[], or String to get the appropriate return value of same type.
*
* @param node
* node to read from
* @param key
* key name to read from
* @param defaultValue
* default value to use, if value is not set
* @return preference value or <code>null</code>
*/
@WrapToScript
public static Object readPreferences(final String node, final String key, @ScriptParameter(defaultValue = "") final Object defaultValue) {
final IEclipsePreferences root = InstanceScope.INSTANCE.getNode(node);
if (root != null) {
if (defaultValue instanceof Boolean)
return root.getBoolean(key, (Boolean) defaultValue);
else if (defaultValue instanceof Integer)
return root.getInt(key, (Integer) defaultValue);
else if (defaultValue instanceof Double)
return root.getDouble(key, (Double) defaultValue);
else if (defaultValue instanceof Float)
return root.getFloat(key, (Float) defaultValue);
else if (defaultValue instanceof Long)
return root.getLong(key, (Long) defaultValue);
else if (defaultValue instanceof byte[])
return root.getByteArray(key, (byte[]) defaultValue);
else
return root.get(key, (defaultValue != null) ? defaultValue.toString() : "");
}
return null;
}
/**
* Set a preferences value. Valid types for <i>value</i> are: Boolean, Integer, Double, Float, Long, byte[], and String.
*
* @param node
* node to write to
* @param key
* key to store to
* @param value
* value to store
*/
@WrapToScript
public static void writePreferences(final String node, final String key, final Object value) {
final IEclipsePreferences root = InstanceScope.INSTANCE.getNode(node);
if (root != null) {
if (value instanceof Boolean)
root.putBoolean(key, (Boolean) value);
else if (value instanceof Integer)
root.putInt(key, (Integer) value);
else if (value instanceof Double)
root.putDouble(key, (Double) value);
else if (value instanceof Float)
root.putFloat(key, (Float) value);
else if (value instanceof Long)
root.putLong(key, (Long) value);
else if (value instanceof byte[])
root.putByteArray(key, (byte[]) value);
else
root.put(key, (value != null) ? value.toString() : "");
}
}
/**
* Post an event on the event broker. If <i>delay</i> is set, the event will be posted after the given amount of time asynchronously. In any case this
* method returns immediately.
*
* @param topic
* topic to post
* @param data
* topic data
* @param delay
* delay to post this even in [ms]
*/
@WrapToScript
public static void postEvent(final String topic, final @ScriptParameter(defaultValue = ScriptParameter.NULL) Object data,
@ScriptParameter(defaultValue = "0") final long delay) {
if (delay > 0) {
final Job job = new Job("Post event") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
postEvent(topic, data, 0);
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule(delay);
} else {
final IEventBroker service = PlatformUI.getWorkbench().getService(IEventBroker.class);
if (service != null)
service.post(topic, data);
else
throw new RuntimeException("Broker service not available");
}
}
/**
* Wait for a given event on the event bus.
*
* @param topic
* topic to subscribe for
* @param timeout
* maximum time to wait for event in [ms]. Use 0 to wait without timeout.
* @return posted event or <code>null</code> in case of a timeout
* @throws InterruptedException
* when the script thread gets interrupted
*/
@WrapToScript
public static Event waitForEvent(final String topic, @ScriptParameter(defaultValue = "0") final long timeout) throws InterruptedException {
final IEventBroker service = PlatformUI.getWorkbench().getService(IEventBroker.class);
if (service != null) {
final WaitingEventHandler handler = new WaitingEventHandler();
synchronized (handler) {
service.subscribe(topic, handler);
handler.wait(timeout);
service.unsubscribe(handler);
return handler.fEvent;
}
} else
throw new RuntimeException("Broker service not available");
}
}