diff options
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf')
29 files changed, 4263 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/activator/CoreBundleActivator.java new file mode 100644 index 000000000..6a3a94656 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/activator/CoreBundleActivator.java @@ -0,0 +1,71 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.activator;
+
+import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator implements BundleActivator {
+ // The bundle context
+ private static BundleContext context;
+ // The trace handler instance
+ private static TraceHandler traceHandler;
+
+ /**
+ * Returns the bundle context
+ *
+ * @return the bundle context
+ */
+ public static BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getContext() != null && getContext().getBundle() != null) {
+ return getContext().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the bundles trace handler.
+ *
+ * @return The bundles trace handler.
+ */
+ public static TraceHandler getTraceHandler() {
+ if (traceHandler == null) {
+ traceHandler = new TraceHandler(getUniqueIdentifier());
+ }
+ return traceHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = bundleContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java new file mode 100644 index 000000000..1b1cf7ec7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/callback/Callback.java @@ -0,0 +1,318 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.callback; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.IConditionTester; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; +import org.eclipse.tcf.te.runtime.utils.ProgressHelper; + +/** + * Default implementation of the <code>ICallback</code> interface. + */ +public class Callback extends PropertiesContainer implements ICallback { + + protected static final String PROPERTY_PARENT_CALLBACK = "parentCallback"; //$NON-NLS-1$ + protected static final String PROPERTY_PROGRESS_MONITOR = "progressMonitor"; //$NON-NLS-1$ + protected static final String PROPERTY_PROGRESS_TICKS = "progressTicks"; //$NON-NLS-1$ + protected static final String PROPERTY_IS_DONE = "isDone"; //$NON-NLS-1$ + protected static final String PROPERTY_STATUS = "status"; //$NON-NLS-1$ + + /** + * Property: Asynchronous operations can store a result to the callback + * object they invoke once the operation has been finished. + */ + protected final String PROPERTY_RESULT = "result"; //$NON-NLS-1$ + + + private static final String[] PROPERTY_KEYS_NOT_TO_COPY = { + PROPERTY_PARENT_CALLBACK, PROPERTY_PROGRESS_MONITOR, + PROPERTY_PROGRESS_TICKS, PROPERTY_IS_DONE, PROPERTY_STATUS + }; + private static final List<String> PROPERTY_KEYS_NOT_TO_COPY_LIST = Arrays.asList(PROPERTY_KEYS_NOT_TO_COPY); + + /** + * Condition tester for ExecutorsUtil to check whether the callback is done + * or the {@link IProgressMonitor} is canceled. + */ + private class CallbackDoneConditionTester implements IConditionTester { + final ICallback callback; + final IProgressMonitor monitor; + + /** + * Constructor. + * + * @param callback + * The callback to check. Must not be <code>null</code>. + * @param monitor + * The progress monitor to check. + */ + public CallbackDoneConditionTester(ICallback callback, IProgressMonitor monitor) { + Assert.isNotNull(callback); + this.callback = callback; + this.monitor = monitor; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#isConditionFulfilled() + */ + @Override + public boolean isConditionFulfilled() { + if (monitor == null) { + return callback.isDone(); + } + return monitor.isCanceled() || callback.isDone(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.IConditionTester#cleanup() + */ + @Override + public void cleanup() { + } + } + + /** + * Constructor. + */ + public Callback() { + this(null); + } + + /** + * Constructor to wrap a parent callback. + * + * @param parentCallback + * The parent callback. + */ + public Callback(ICallback parentCallback) { + this(null, -1, parentCallback); + } + + /** + * Constructor to handle a progress monitor. + * + * @param monitor + * The progress monitor. + * @param ticksToUse + * The ticks to add when done. + */ + public Callback(IProgressMonitor monitor, int ticksToUse) { + this(monitor, ticksToUse, null); + } + + /** + * Constructor to handle a progress monitor and wrap a parent callback. + * + * @param monitor + * The progress monitor. + * @param ticksToUse + * The ticks to add when done. + * @param parentCallback + * The parent callback. + */ + public Callback(IProgressMonitor monitor, int ticksToUse, ICallback parentCallback) { + super(); + setProperty(PROPERTY_PARENT_CALLBACK, parentCallback); + setProperty(PROPERTY_PROGRESS_MONITOR, monitor); + setProperty(PROPERTY_PROGRESS_TICKS, ticksToUse); + } + + /** + * Get a condition tester for this callback. + * + * @param monitor + * The progress monitor or <code>null</code>. + * @return The condition tester. + */ + public final IConditionTester getDoneConditionTester(IProgressMonitor monitor) { + return new CallbackDoneConditionTester(this, monitor); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#done(java.lang.Object, org.eclipse.core.runtime.IStatus) + */ + @Override + public final void done(Object caller, IStatus status) { + Assert.isNotNull(status); + + if (isDone()) { + CoreBundleActivator.getTraceHandler().trace("WARNING: callback called twice!!", 1, this); //$NON-NLS-1$ + return; + } + + status = checkStatusIntegrity(status); + + setProperty(PROPERTY_IS_DONE, true); + setProperty(PROPERTY_STATUS, status); + + ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK); + if (parentCallback != null && parentCallback.isDone()) { + CoreBundleActivator.getTraceHandler().trace("WARNING: parent callback called twice!!", 1, this); //$NON-NLS-1$ + } + + internalDone(caller, status); + + if (isDone()) { + if (getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) { + IProgressMonitor progress = ((IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR)); + if (!progress.isCanceled() && getStatus().getSeverity() != IStatus.CANCEL) { + int ticks = getIntProperty(PROPERTY_PROGRESS_TICKS); + if (ticks > 0) { + progress.worked(ticks); + } else if (ticks == ProgressHelper.PROGRESS_DONE) { + progress.done(); + } + } + } + + parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK); + if (parentCallback != null && !parentCallback.isDone()) { + copyProperties(this, parentCallback); + if (!ProgressHelper.isCancelOrError(this, + getStatus(), + (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR), + parentCallback)) { + parentCallback.done(caller, getStatus()); + } + } + } + } + + /** + * Copy the properties from the given source callback to the given + * destination callback. + * + * @param source + * The source callback. Must not be <code>null</code>. + * @param destination + * The destination callback. Must not be <code>null</code> and + * not yet done. + */ + public static final void copyProperties(ICallback source, ICallback destination) { + Assert.isNotNull(source); + Assert.isNotNull(destination); + Assert.isTrue(!destination.isDone()); + + for (String key : source.getProperties().keySet()) { + if (!PROPERTY_KEYS_NOT_TO_COPY_LIST.contains(key)) { + destination.setProperty(key, source.getProperty(key)); + } + } + Assert.isTrue(!destination.isDone()); + } + + /** + * Checks the status integrity. + * + * @param status + * The status or <code>null</code>. + * @return The checked status. + */ + private IStatus checkStatusIntegrity(IStatus status) { + if (status == null) status = Status.OK_STATUS; + + if (status.getSeverity() == IStatus.CANCEL && status.getException() == null) { + status = new Status(IStatus.CANCEL, status.getPlugin(), + status.getMessage(), new OperationCanceledException(status.getMessage())); + } + + if (status.getSeverity() == IStatus.WARNING && status.getException() == null) { + status = new Status(IStatus.WARNING, status.getPlugin(), + status.getMessage(), new Exception(status.getMessage())); + } + + if (status.getSeverity() == IStatus.ERROR && status.getException() == null) { + status = new Status(IStatus.ERROR, status.getPlugin(), + status.getMessage(), new Exception(status.getMessage())); + } + + return status; + } + + /** + * Return the progress monitor or <code>null</code>. + */ + protected final IProgressMonitor getProgressMonitor() { + return (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR); + } + + /** + * Internal callback done. + * + * @param caller + * The caller. + * @param status + * The status. + */ + protected void internalDone(Object caller, IStatus status) { + } + + /** + * Return the result on done. + */ + public final IStatus getStatus() { + IStatus status = (IStatus) getProperty(PROPERTY_STATUS); + if (status == null && getProperty(PROPERTY_PROGRESS_MONITOR) instanceof IProgressMonitor) { + IProgressMonitor monitor = (IProgressMonitor) getProperty(PROPERTY_PROGRESS_MONITOR); + if (monitor.isCanceled()) { + return checkStatusIntegrity(Status.CANCEL_STATUS); + } + } + + return checkStatusIntegrity(status); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#isDone() + */ + @Override + public final boolean isDone() { + return getBooleanProperty(PROPERTY_IS_DONE); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#addParentCallback(org.eclipse.tcf.te.runtime.interfaces.callback.ICallback) + */ + @Override + public void addParentCallback(ICallback callback) { + if (getProperty(PROPERTY_PARENT_CALLBACK) instanceof ICallback) { + ICallback parentCallback = (ICallback) getProperty(PROPERTY_PARENT_CALLBACK); + parentCallback.addParentCallback(callback); + } else { + setProperty(PROPERTY_PARENT_CALLBACK, callback); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#setResult(java.lang.Object) + */ + @Override + public void setResult(Object result) { + setProperty(PROPERTY_RESULT, result); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.callback.ICallback#getResult() + */ + @Override + public Object getResult() { + return getProperty(PROPERTY_RESULT); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/ChangeEvent.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/ChangeEvent.java new file mode 100644 index 000000000..2d238950e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/ChangeEvent.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.events; + +import java.util.EventObject; + +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds; + +/** + * Common change event implementation. + */ +public class ChangeEvent extends EventObject { + private static final long serialVersionUID = -7859159130977760588L; + + private Object eventId; + private Object oldValue; + private Object newValue; + + /** + * Constructor. + * + * @param source The source object. Must not be <code>null</code>. + * @param eventId The event id. Must not be <code>null</code>. + * @param oldValue The old value. + * @param newValue The new value. + * + * @exception IllegalArgumentException if eventId == null. + */ + public ChangeEvent(Object source, Object eventId, Object oldValue, Object newValue) { + super(source); + + if (eventId == null) throw new IllegalArgumentException("null eventId"); //$NON-NLS-1$ + + this.eventId = eventId; + this.oldValue = oldValue; + this.newValue = newValue; + } + + /** + * Returns the event id. + * + * @return The event id. + */ + public final Object getEventId() { + return eventId; + } + + /** + * Returns the old value. + * + * @return The old value or <code>null</code>. + */ + public final Object getOldValue() { + return oldValue; + } + + /** + * Returns the new value. + * + * @return The new value or <code>null</code>. + */ + public final Object getNewValue() { + return newValue; + } + + /* + * Formats a value due to its type. + */ + private Object formatValue(Object value) { + Object formattedValue = value; + if (value != null && value.getClass().isArray()) { + StringBuilder str = new StringBuilder(); + str.append("{"); //$NON-NLS-1$ + for (int i = 0; i < ((Object[]) value).length; i++) { + if (i > 0) str.append(","); //$NON-NLS-1$ + str.append(formatValue(((Object[]) value)[i])); + } + str.append("}"); //$NON-NLS-1$ + formattedValue = str.toString(); + } + return formattedValue; + } + + /* + * (non-Javadoc) + * @see java.util.EventObject#toString() + */ + @Override + public String toString() { + StringBuilder toString = new StringBuilder(getClass().getName()); + + String prefix = ""; //$NON-NLS-1$ + // if tracing the event, formating them a little bit better readable. + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_EVENTS)) + prefix = "\n\t\t"; //$NON-NLS-1$ + + toString.append(prefix + "{eventId="); //$NON-NLS-1$ + toString.append(eventId); + toString.append("," + prefix + "source="); //$NON-NLS-1$ //$NON-NLS-2$ + toString.append(source); + toString.append("," + prefix + "oldValue="); //$NON-NLS-1$ //$NON-NLS-2$ + toString.append(formatValue(oldValue)); + toString.append("," + prefix + "newValue="); //$NON-NLS-1$ //$NON-NLS-2$ + toString.append(formatValue(newValue)); + toString.append("}"); //$NON-NLS-1$ + + return toString.toString(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/DisposedEvent.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/DisposedEvent.java new file mode 100644 index 000000000..7b0df0619 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/DisposedEvent.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.events; + +import java.util.EventObject; + +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds; + +/** + * Event used to signal the disposal of an element. + */ +public class DisposedEvent extends EventObject { + private static final long serialVersionUID = -8900361742097122798L; + + private final Object data; + + /** + * Constructor. + * + * @param source The event source. Must not be <code>null</code>. + * <p> + * The event source is expected to be of type {@link CTabItem}. + * + * @param data The custom data object or <code>null</code>. + */ + public DisposedEvent(Object source, Object data) { + super(source); + this.data = data; + } + + /** + * Returns the custom data object associated with the disposed terminal console. + * + * @return The custom data object or <code>null</code>. + */ + public final Object getData() { + return data; + } + + /* (non-Javadoc) + * @see java.util.EventObject#toString() + */ + @Override + public String toString() { + StringBuffer toString = new StringBuffer(getClass().getName()); + + String prefix = ""; //$NON-NLS-1$ + // if debugging the event, formating them a little bit better readable. + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(1, ITraceIds.TRACE_EVENTS)) + prefix = "\n\t\t"; //$NON-NLS-1$ + + toString.append(prefix + "{source="); //$NON-NLS-1$ + toString.append(source); + toString.append("}"); //$NON-NLS-1$ + + return toString.toString(); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/EventManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/EventManager.java new file mode 100644 index 000000000..3cd413306 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/events/EventManager.java @@ -0,0 +1,533 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.events; + +import java.util.ArrayList; +import java.util.EventListener; +import java.util.EventObject; +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.events.IEventFireDelegate; +import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener; +import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds; +import org.osgi.framework.Bundle; + + +/** + * The event manager implementation. + */ +public final class EventManager { + // Flag to remember if the extension point has been processed. + private boolean extensionPointProcessed; + // The list of registered listeners. + private final List<ListenerListEntry> listeners = new ArrayList<ListenerListEntry>(); + + /** + * Runnable implementation to fire a given event to a given listener. + */ + protected static class FireRunnable implements Runnable { + private final IEventListener listener; + private final EventObject event; + + /** + * Constructor. + * + * @param listener The event listener. Must not be <code>null</code>. + * @param event The event. Must not be <code>null</code>. + */ + public FireRunnable(IEventListener listener, EventObject event) { + Assert.isNotNull(listener); + Assert.isNotNull(event); + this.listener = listener; + this.event = event; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + listener.eventFired(event); + } + } + + /** + * Listener list entry. + * <p> + * Each entry contains a reference to the listener and a list of valid source classes. + * If an event source can be casted to one of the classes the listener is invoked. + */ + private class ListenerListEntry { + private final IEventListener listener; + private final Object[] eventSources; + private final Class<?>[] eventTypes; + + /** + * Constructor. + * + * @param listener The listener. + * @param eventType The event type the listener is interested in. + * @param eventSource The source type for which events should be fired to the listener. + */ + protected ListenerListEntry(IEventListener listener, Class<?> eventType, Object eventSource) { + this(listener, eventType == null ? null : new Class[] { eventType }, eventSource == null ? null : new Object[] { eventSource }); + } + + /** + * Constructor. + * + * @param listener The listener. + * @param eventTypes The event types the listener is interested in. + * @param eventSources The source types for which events should be fired to the listener. + */ + protected ListenerListEntry(IEventListener listener, Class<?>[] eventTypes, Object[] eventSources) { + this.listener = listener; + if (eventTypes == null || eventTypes.length == 0) { + this.eventTypes = null; + } else { + this.eventTypes = eventTypes; + } + if (eventSources == null || eventSources.length == 0) { + this.eventSources = null; + } else { + this.eventSources = eventSources; + } + } + + /** + * Get the listener of this entry. + */ + protected EventListener getListener() { + return listener; + } + + /** + * Check whether the listener wants to be called for changes of the source. + * The check is made through <code>instanceof</code>. + * + * @param source The source of the event. + * @return True, if the source can be casted to one of the registered event source types + * or no event sources are registered. + */ + protected boolean listensTo(EventObject event) { + boolean types = (eventTypes == null || eventTypes.length == 0); + boolean sources = (eventSources == null || eventSources.length == 0); + + int t = 0; + while (!types && eventTypes != null && t < eventTypes.length) { + types = eventTypes[t].isInstance(event); + t++; + } + + int s = 0; + while (!sources && eventSources != null && s < eventSources.length) { + Object eventSource = eventSources[s]; + if (eventSource instanceof Class<?>) { + Class<?> eventSourceClass = (Class<?>)eventSource; + sources = eventSourceClass.isInstance(event.getSource()); + } else { + sources = eventSource == event.getSource(); + } + s++; + } + + return types && sources; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof ListenerListEntry) { + ListenerListEntry other = (ListenerListEntry)obj; + return this.getListener() == other.getListener(); + } + return false; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getClass().getName() + "{" + //$NON-NLS-1$ + "listener=" + listener + //$NON-NLS-1$ + ",eventTypes=" + eventTypes + //$NON-NLS-1$ + ",eventSources=" + eventSources + //$NON-NLS-1$ + "}"; //$NON-NLS-1$ + } + } + + /* + * Thread save singleton instance creation. + */ + private static class LazyInstance { + public static EventManager instance = new EventManager(); + } + + /** + * Private Constructor. + */ + EventManager() { + extensionPointProcessed = false; + } + + /** + * Returns the singleton instance for the event manager. + */ + public static EventManager getInstance() { + return LazyInstance.instance; + } + + /** + * Add a change listener to listen to a single event. + * + * @param listener The listener to add. + * @param eventType The event type this listeners wants to be invoked. + */ + public void addEventListener(IEventListener listener, Class<?> eventType) { + addEventListener(listener, eventType != null ? new Class[] { eventType } : null, null); + } + + /** + * Add a change listener to listen to multiple events. + * + * @param listener The listener to add. + * @param eventTypes The event types this listeners wants to be invoked. + */ + public void addEventListener(IEventListener listener, Class<?>[] eventTypes) { + addEventListener(listener, eventTypes, null); + } + + /** + * Add a change listener to listen to event from the specified event + * source. If the listener instance had been registered already, the listener + * event sources are updated + * + * @param listener The listener to add. + * @param eventType The event type this listeners wants to be invoked. + * @param eventSource The event source type this listeners wants to be invoked. + */ + public void addEventListener(IEventListener listener, Class<?> eventType, Object eventSource) { + addEventListener(listener, eventType != null ? new Class[] { eventType } : null, eventSource != null ? new Object[] { eventSource } : null); + } + + /** + * Add a change listener to listen to events from the specified event + * sources. If the listener instance had been registered already, the listener + * event sources are updated + * + * @param listener The listener to add. + * @param eventType The event type this listeners wants to be invoked. + * @param eventSources The event sources type this listeners wants to be invoked. + */ + public void addEventListener(IEventListener listener, Class<?> eventType, Object[] eventSources) { + addEventListener(listener, eventType != null ? new Class[] { eventType } : null, eventSources); + } + + /** + * Add a change listener to listen to event from the specified event + * sources. If the listener instance had been registered already, the listener + * event sources are updated + * + * @param listener The listener to add. + * @param eventTypes The event types this listeners wants to be invoked. + * @param eventSources The event source types this listeners wants to be invoked. + */ + public void addEventListener(IEventListener listener, Class<?>[] eventTypes, Object[] eventSources) { + ListenerListEntry listEntry = new ListenerListEntry(listener, eventTypes, eventSources); + // We must assure that the existing list entries can _never_ change! + synchronized (listeners) { + if (listeners.contains(listEntry)) { + listeners.remove(listEntry); + } + listeners.add(listEntry); + } + } + + /** + * Remove a change listener for all event types and sources. + * + * @param listener The listener to remove. + */ + public void removeEventListener(IEventListener listener) { + ListenerListEntry listEntry = new ListenerListEntry(listener, (Class<?>)null, (Object)null); + listeners.remove(listEntry); + } + + /** + * Remove all change listeners for all event types and sources. + */ + public void clear() { + listeners.clear(); + extensionPointProcessed = false; + } + + /** + * Notify all registered listeners. + * + * @param event The event. Must not be <code>null</code> + */ + public void fireEvent(final EventObject event) { + Assert.isNotNull(event); + + synchronized (this) { + // if the extension point has not been processed till here, now we have to do + if (!extensionPointProcessed) { + addExtensionPointNotificationListeners(); + extensionPointProcessed = true; + } + } + + // Based on the current listener listener list, compile a list of event + // listeners to where this event would have been send to in a synchronous invocation scheme. + List<ListenerListEntry> affected = new ArrayList<ListenerListEntry>(); + + // Get the array of registered event listeners. + ListenerListEntry[] registered = listeners.toArray(new ListenerListEntry[listeners.size()]); + + for (ListenerListEntry listEntry : registered) { + // ignore listeners not listening to the event type and source + if (listEntry.listensTo(event)) { + affected.add(listEntry); + } + } + + // If no current listener is affected, return now immediately + if (affected.size() == 0) { + return; + } + + // Loop over the list of affected listeners and fire the event. + // If the affected listener is a fire delegate -> use it itself to fire the event + for (ListenerListEntry listEntry : affected) { + if (!(listEntry.getListener() instanceof IEventListener)) { + continue; + } + // Create the runnable to use for executing the event firing + Runnable runnable = new FireRunnable((IEventListener)listEntry.getListener(), event); + // Check on how to fire the runnable + if (listEntry.getListener() instanceof IEventFireDelegate) { + // The listener is a fire delegate -> use it itself to fire the runnable + ((IEventFireDelegate)listEntry.getListener()).fire(runnable); + } else { + // Listener isn't a fire delegate -> fire the runnable directly + runnable.run(); + } + } + } + + /* + * Register change listeners defined by extension. + */ + private void addExtensionPointNotificationListeners() { + IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint("org.eclipse.tcf.te.runtime.eventListeners"); //$NON-NLS-1$ + if (ep != null) { + IExtension[] extensions = ep.getExtensions(); + if (extensions != null && extensions.length > 0) { + for (IExtension extension : extensions) { + IConfigurationElement[] configElements = extension.getConfigurationElements(); + if (configElements != null && configElements.length > 0) { + for (IConfigurationElement configElement : configElements) { + String name = configElement.getName(); + if ("eventListener".equals(name)) { //$NON-NLS-1$ + // try to read the "eventType" and "eventSourceType" configuration elements if any. + List<Class<?>> eventTypes = new ArrayList<Class<?>>(); + List<Class<?>> eventSourceTypes = new ArrayList<Class<?>>(); + + IConfigurationElement[] children = configElement.getChildren(); + for (IConfigurationElement child : children) { + if ("eventType".equals(child.getName())) { //$NON-NLS-1$ + // The event types, we have to instantiate here as we need the class object! + try { + // First we try to instantiate the class using our own local class loader. + // This trick can avoid activating the contributing plugin if we can load + // the class ourself. + // First we try to instantiate the class using our own context + String className = child.getAttribute("class"); //$NON-NLS-1$ + if (className == null || className.trim().length() == 0) { + continue; + } + + String bundleId = child.getAttribute("bundleId"); //$NON-NLS-1$ + + // If a bundle id got specified, use the specified bundle to load the service class + Bundle bundle = bundleId != null ? bundle = Platform.getBundle(bundleId) : null; + // If we don't have a bundle to load from yet, fallback to the declaring bundle + if (bundle == null) bundle = Platform.getBundle(child.getDeclaringExtension().getNamespaceIdentifier()); + // And finally, use our own bundle to load the class. This fallback is expected + // to never be used. + if (bundle == null) bundle = CoreBundleActivator.getContext().getBundle(); + + // Try to load the event type class now + Class<?> eventType = bundle != null ? bundle.loadClass(className) : Class.forName(className); + if (!eventTypes.contains(eventType)) { + eventTypes.add(eventType); + } + } catch (Exception ex) { + if (isTracingEnabled()) + CoreBundleActivator.getTraceHandler().trace("Error instantiating event listener event type object instance: " + child.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_EVENTS, IStatus.ERROR, this); + } + } + + if ("eventSourceType".equals(child.getName())) { //$NON-NLS-1$ + // The event source types, we have to instantiate here as we need the class object! + try { + // First we try to instantiate the class using our own local class loader. + // This trick can avoid activating the contributing plugin if we can load + // the class ourself. + // First we try to instantiate the class using our own context + String className = child.getAttribute("class"); //$NON-NLS-1$ + if (className == null || className.trim().length() == 0) { + continue; + } + + String bundleId = child.getAttribute("bundleId"); //$NON-NLS-1$ + + // If a bundle id got specified, use the specified bundle to load the service class + Bundle bundle = bundleId != null ? bundle = Platform.getBundle(bundleId) : null; + // If we don't have a bundle to load from yet, fallback to the declaring bundle + if (bundle == null) bundle = Platform.getBundle(child.getDeclaringExtension().getNamespaceIdentifier()); + // And finally, use our own bundle to load the class. This fallback is expected + // to never be used. + if (bundle == null) bundle = CoreBundleActivator.getContext().getBundle(); + + // Try to load the event source type class now + Class<?> eventSourceType = bundle != null ? bundle.loadClass(className) : Class.forName(className); + if (!eventSourceTypes.contains(eventSourceType)) { + eventSourceTypes.add(eventSourceType); + } + } catch (Exception ex) { + if (isTracingEnabled()) + CoreBundleActivator.getTraceHandler().trace("Error instantiating event listener event source type object instance: " + child.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_EVENTS, IStatus.ERROR, this); + } + } + } + + // For extension point contributed event listeners, we use delegating + // event listener instances + IEventListener listener = new EventListenerProxy(configElement); + addEventListener(listener, + !eventTypes.isEmpty() ? eventTypes.toArray(new Class[eventTypes.size()]) : null, + !eventSourceTypes.isEmpty() ? eventSourceTypes.toArray(new Class[eventSourceTypes.size()]) : null + ); + + if (isTracingEnabled()) + CoreBundleActivator.getTraceHandler().trace("Add extension point change listener: " + configElement.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_EVENTS, IStatus.INFO, this); + } + } + } + } + } + } + } + + /** + * Internal class used to delay the instantiation and plugin activation of + * event listeners which are contributed via extension point till they + * are really fired. + */ + private class EventListenerProxy implements IEventListener, IEventFireDelegate { + private final IConfigurationElement configElement; + private IEventListener delegate; + + /** + * Constructor. + * + * @param configElement The contributing configuration element of the encapsulated event listener. + * Must not be <code>null</code>. + */ + public EventListenerProxy(IConfigurationElement configElement) { + Assert.isNotNull(configElement); + this.configElement = configElement; + delegate = null; + } + + /** + * Returns the event listener delegate and instantiate the delegate + * if not yet done. + * + * @return The event listener delegate or <code>null</code> if the instantiation fails. + */ + private IEventListener getDelegate() { + if (delegate == null) { + // Check the contributing plug-in state + boolean forcePluginActivation = Boolean.parseBoolean(configElement.getAttribute("forcePluginActivation")); //$NON-NLS-1$ + if (!forcePluginActivation) { + Bundle bundle = Platform.getBundle(configElement.getContributor().getName()); + forcePluginActivation = bundle != null ? bundle.getState() == Bundle.ACTIVE : false; + } + // Load the event listener implementation class if plugin activations is allowed. + if (forcePluginActivation) { + try { + Object executable = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (executable instanceof IEventListener) { + delegate = (IEventListener)executable; + } + } catch (Exception ex) { + if (isTracingEnabled()) + CoreBundleActivator.getTraceHandler().trace("Error instantiating extension point event listener: " + configElement.getAttribute("class") //$NON-NLS-1$ //$NON-NLS-2$ + + "(Possible Cause: " + ex.getLocalizedMessage() + ")", //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_EVENTS, IStatus.ERROR, this); + } + } + } + + return delegate; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventListener#eventFired(java.util.EventObject) + */ + @Override + public void eventFired(EventObject event) { + Assert.isNotNull(event); + // Get the delegate (may force instantiation) + IEventListener delegate = getDelegate(); + // And pass on the event to the delegate if we got a valid delegate + if (delegate != null) delegate.eventFired(event); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventFireDelegate#fire(java.lang.Runnable) + */ + @Override + public void fire(Runnable runnable) { + Assert.isNotNull(runnable); + // Pass on to the delegate if the delegate itself is an fire delegate, + if (getDelegate() instanceof IEventFireDelegate) { + ((IEventFireDelegate)getDelegate()).fire(runnable); + } + else { + runnable.run(); + } + } + } + + /** + * Return <code>true</code> if the tracing mode is enabled for the + * event manager and trace messages shall be printed to the debug console. + */ + public static boolean isTracingEnabled() { + return CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_EVENTS); + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/AbstractExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/AbstractExtensionPointManager.java new file mode 100644 index 000000000..336f3b0c5 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/AbstractExtensionPointManager.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.extensions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.nls.Messages; + +/** + * Abstract extension point manager implementation. + */ +public abstract class AbstractExtensionPointManager<V> { + // Flag to mark the extension point manager initialized (extensions loaded). + private boolean initialized = false; + // The map of loaded extension listed by their unique id's + private Map<String, ExecutableExtensionProxy<V>> extensionsMap = new LinkedHashMap<String, ExecutableExtensionProxy<V>>(); + // The extension point comparator + private ExtensionPointComparator comparator = null; + + /** + * Constructor. + */ + public AbstractExtensionPointManager() { + } + + /** + * Returns if or if not the extension point manager got initialized already. + * <p> + * Initialized means that the manager read the extensions for the managed extension point. + * + * @return <code>True</code> if already initialized, <code>false</code> otherwise. + */ + protected boolean isInitialized() { + return initialized; + } + + /** + * Sets if or if not the extension point manager is initialized. + * <p> + * Initialized means that the manager has read the extensions for the managed extension point. + * + * @return <code>True</code> to set the extension point manager is initialized, <code>false</code> otherwise. + */ + protected void setInitialized(boolean initialized) { + this.initialized = initialized; + } + + /** + * Returns the map of managed extensions. If not loaded before, + * this methods trigger the loading of the extensions to the managed + * extension point. + * + * @return The map of extensions. + */ + protected Map<String, ExecutableExtensionProxy<V>> getExtensions() { + // Load and store the extensions thread-safe! + synchronized (extensionsMap) { + if (!isInitialized()) { loadExtensions(); setInitialized(true); } + } + return extensionsMap; + } + + /** + * Returns the extensions of the specified extension point sorted. + * <p> + * For the order of the extensions, see {@link ExtensionPointComparator}. + * + * @param point The extension point. Must be not <code>null</code>. + * @return The extensions in sorted order or an empty array if the extension point has no extensions. + */ + protected IExtension[] getExtensionsSorted(IExtensionPoint point) { + assert point != null; + + List<IExtension> extensions = new ArrayList<IExtension>(Arrays.asList(point.getExtensions())); + if (extensions.size() > 0) { + Collections.sort(extensions, getExtensionPointComparator()); + } + + return extensions.toArray(new IExtension[extensions.size()]); + } + + /** + * Returns the extension point comparator instance. If not available, + * {@link #doCreateExtensionPointComparator()} is called to create a new instance. + * + * @return The extension point comparator or <code>null</code> if the instance creation fails. + */ + protected final ExtensionPointComparator getExtensionPointComparator() { + if (comparator == null) { + comparator = doCreateExtensionPointComparator(); + } + return comparator; + } + + /** + * Creates a new extension point comparator instance. + * + * @return The extension point comparator instance. + */ + protected ExtensionPointComparator doCreateExtensionPointComparator() { + return new ExtensionPointComparator(); + } + + /** + * Returns the extension point id to read. The method + * must return never <code>null</code>. + * + * @return The extension point id. + */ + protected abstract String getExtensionPointId(); + + /** + * Returns the configuration element name. The method + * must return never <code>null</code>. + * + * @return The configuration element name. + */ + protected abstract String getConfigurationElementName(); + + /** + * Creates the extension proxy instance. + * + * @param element The configuration element of the extension. Must not be <code>null</code>. + * @return The extension proxy instance. + * + * @throws CoreException If the extension proxy instantiation failed. + */ + protected ExecutableExtensionProxy<V> doCreateExtensionProxy(IConfigurationElement element) throws CoreException { + Assert.isNotNull(element); + return new ExecutableExtensionProxy<V>(element); + } + + /** + * Store the given extension to the given extensions store. Checks if an extension with the same id does exist + * already and throws an exception in this case. + * + * @param extensions The extensions store. Must not be <code>null</code>. + * @param candidate The extension. Must not be <code>null</code>. + * @param element The configuration element. Must not be <code>null</code>. + * + * @throws CoreException In case a extension with the same id as the given extension already exist. + */ + protected void doStoreExtensionTo(Map<String, ExecutableExtensionProxy<V>> extensions, ExecutableExtensionProxy<V> candidate, IConfigurationElement element) throws CoreException { + Assert.isNotNull(extensions); + Assert.isNotNull(candidate); + Assert.isNotNull(element); + + // If no extension with this id had been registered before, register now. + if (!extensions.containsKey(candidate.getId())) { + extensions.put(candidate.getId(), candidate); + } + else { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_duplicateExtension, candidate.getId(), element.getContributor().getName()), + null)); + } + } + + /** + * Loads the extensions for the managed extension point. + */ + protected void loadExtensions() { + // If already initialized, this method will do nothing. + if (isInitialized()) return; + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint point = registry.getExtensionPoint(getExtensionPointId()); + if (point != null) { + IExtension[] extensions = getExtensionsSorted(point); + for (IExtension extension : extensions) { + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (IConfigurationElement element : elements) { + if (getConfigurationElementName().equals(element.getName())) { + try { + ExecutableExtensionProxy<V> candidate = doCreateExtensionProxy(element); + if (candidate.getId() != null) { + doStoreExtensionTo(extensionsMap, candidate, element); + } else { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", element.getAttribute("label")), //$NON-NLS-1$ //$NON-NLS-2$ + null)); + } + } catch (CoreException e) { + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.Extension_error_invalidExtensionPoint, element.getDeclaringExtension().getUniqueIdentifier()), e)); + } + } + } + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtension.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtension.java new file mode 100644 index 000000000..3859e43b7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtension.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.extensions; + +import java.util.Hashtable; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension; +import org.eclipse.tcf.te.runtime.nls.Messages; + +/** + * Executable extension implementation. + */ +public class ExecutableExtension extends PlatformObject implements IExecutableExtension { + // The mandatory id of the extension + private String id = null; + // The label of the extension + private String label = null; + // The description of the extension + private String description = null; + + /** + * Clone the initialization data to the given executable extension instance. + * + * @param other The destination executable extension instance. Must not be <code>null</code>. + */ + public void cloneInitializationData(ExecutableExtension other) { + Assert.isNotNull(other); + other.id = id; + other.label = label; + other.description = description; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) + */ + @Override + public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + if (config != null) doSetInitializationData(config, propertyName, data); + } + + /** + * Executes the {@link #setInitializationData(IConfigurationElement, String, Object)}. + * + * @param config The configuration element. Must not be <code>null</code>. + * @param propertyName The name of an attribute of the configuration element used on the <code>createExecutableExtension(String)<code> call. + * This argument can be used in the cases where a single configuration element is used to define multiple + * executable extensions. + * @param data Adapter data in the form of a String, a {@link Hashtable}, or <code>null</code>. + * + * @throws CoreException - if error(s) detected during initialization processing + */ + public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { + Assert.isNotNull(config); + + // Initialize the id field by reading the <id> extension attribute. + // Throws an exception if the id is empty or null. + id = config != null ? config.getAttribute("id") : null; //$NON-NLS-1$ + if (id == null || (id != null && "".equals(id.trim()))) { //$NON-NLS-1$ + throw createMissingMandatoryAttributeException("id", config.getContributor().getName()); //$NON-NLS-1$ + } + + // Try the "label" attribute first + label = config != null ? config.getAttribute("label") : null; //$NON-NLS-1$ + // If "label" is not found or empty, try the "name" attribute as fallback + if (label == null || "".equals(label.trim())) { //$NON-NLS-1$ + label = config != null ? config.getAttribute("name") : null; //$NON-NLS-1$ + } + + // Read the description text from the "<description>" child element + IConfigurationElement[] children = config != null ? config.getChildren("description") : null; //$NON-NLS-1$ + // Only one description element is allow. All other will be ignored + if (children != null && children.length > 0) { + IConfigurationElement element = children[0]; + description = element.getValue(); + } + } + + /** + * Creates a new {@link CoreException} to be thrown if a mandatory extension attribute + * is missing. + * + * @param attributeName The attribute name. Must not be <code>null</code>. + * @param extensionId The extension id. Must not be <code>null</code>. + * + * @return The {@link CoreException} instance. + */ + protected CoreException createMissingMandatoryAttributeException(String attributeName, String extensionId) { + Assert.isNotNull(attributeName); + Assert.isNotNull(extensionId); + + return new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, attributeName, extensionId), + null)); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension#getId() + */ + @Override + public String getId() { + return id; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension#getLabel() + */ + @Override + public String getLabel() { + return label != null ? label.trim() : ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension#getDescription() + */ + @Override + public String getDescription() { + return description != null ? description.trim() : ""; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtensionProxy.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtensionProxy.java new file mode 100644 index 000000000..3b3100195 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExecutableExtensionProxy.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.extensions; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.nls.Messages; + + +/** + * Executable extension proxy implementation. + */ +public class ExecutableExtensionProxy<V> { + // The extension instance. Created on first access + private V instance; + // The configuration element + private final IConfigurationElement element; + // The unique id of the extension. + private String id; + + /** + * Constructor. + * + * @param element The configuration element. Must not be <code>null</code>. + * @throws CoreException In case the configuration element attribute <i>id</i> is <code>null</code> or empty. + */ + public ExecutableExtensionProxy(IConfigurationElement element) throws CoreException { + Assert.isNotNull(element); + this.element = element; + + // Extract the extension attributes + id = element.getAttribute("id"); //$NON-NLS-1$ + if (id == null || id.trim().length() == 0) { + throw new CoreException(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + 0, + NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", element.getContributor().getName()), //$NON-NLS-1$ + null)); + } + + instance = null; + } + + /** + * Constructor. + * + * @param id The id for this instance. + * @param instance The instance to add to proxy. + */ + public ExecutableExtensionProxy(String id, V instance) { + Assert.isNotNull(id); + Assert.isNotNull(instance); + this.id = id; + this.instance = instance; + this.element = null; + } + + /** + * Returns the extensions unique id. + * + * @return The unique id. + */ + public String getId() { + return id; + } + + /** + * Returns the configuration element for this extension. + * + * @return The configuration element. + */ + public IConfigurationElement getConfigurationElement() { + return element; + } + + /** + * Reset the extension instance to <code>null</code> and force the + * creation of a new extension instance on the next {@link #getInstance()} + * method invocation. + * + * @return The current extension instance or <code>null</code> if none. + */ + public V reset() { + V oldExtension = instance; + instance = null; + return oldExtension; + } + + /** + * Returns the extension class instance. The contributing + * plug-in will be activated if not yet activated anyway. + * + * @return The extension class instance or <code>null</code> if the instantiation fails. + */ + public V getInstance() { + if (instance == null) instance = newInstance(); + return instance; + } + + /** + * Returns always a new extension class instance which is different + * to what {@link #getInstance()} would return. + * + * @return A new extension class instance or <code>null</code> if the instantiation fails. + */ + public V newInstance() { + IConfigurationElement element = getConfigurationElement(); + Assert.isNotNull(element); + + // The "class" to load can be specified either as attribute or as child element + String attributeName = getExecutableExtensionAttributeName() != null ? getExecutableExtensionAttributeName() : "class"; //$NON-NLS-1$ + if (element != null && (element.getAttribute(attributeName) != null || element.getChildren(attributeName).length > 0)) { + try { + return (V)element.createExecutableExtension(attributeName); + } catch (Exception e) { + // Possible exceptions: CoreException, ClassCastException. + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(new Status(IStatus.ERROR, + CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.Extension_error_invalidExtensionPoint, element.getDeclaringExtension().getUniqueIdentifier()), e)); + } + } + return null; + } + + /** + * Return the attribute name for the executable extension. + */ + protected String getExecutableExtensionAttributeName() { + return "class"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + // Proxie's are equal if they have encapsulate an element + // with the same unique id + if (obj instanceof ExecutableExtensionProxy<?>) { + return getId().equals(((ExecutableExtensionProxy<?>)obj).getId()); + } + return super.equals(obj); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // The hash code of a proxy is the one from the id + return getId().hashCode(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExtensionPointComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExtensionPointComparator.java new file mode 100644 index 000000000..df602dd1d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/extensions/ExtensionPointComparator.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.extensions; + +import java.util.Comparator; + +import org.eclipse.core.runtime.IExtension; + +/** + * Extension point comparator implementation. + * <p> + * The comparator assure that extension are read in a predictable order. + * <p> + * The order of the extensions is defined as following:<br> + * <ul><li>Extensions contributed by Target Explorer plug-ins (<code>org.eclipse.tcf.te.*</code>) + * in ascending alphabetic order and</li> + * <li>Extensions contributed by any other plug-in in ascending alphabetic order.</li> + * <li>Extensions contributed by the same plug-in in ascending alphabetic order by the + * extensions unique id</li> + */ +public class ExtensionPointComparator implements Comparator<IExtension> { + private final static String TARGET_EXPLORER_PLUGINS_PATTERN = "org.eclipse.tcf.te."; //$NON-NLS-1$ + + /* (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(IExtension o1, IExtension o2) { + // We ignore any comparisation with null and + if (o1 == null || o2 == null) return 0; + // Check if it is the exact same element + if (o1 == o2) return 0; + + // The extensions are compared by the unique id of the contributing plugin first + String contributor1 = o1.getContributor().getName(); + String contributor2 = o2.getContributor().getName(); + + // Contributions from Target Explorer plug-ins comes before 3rdParty plug-ins + if (contributor1.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN) && !contributor2.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN)) + return -1; + if (!contributor1.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN) && contributor2.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN)) + return 1; + if (contributor1.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN) && contributor2.startsWith(TARGET_EXPLORER_PLUGINS_PATTERN)) { + int value = contributor1.compareTo(contributor2); + // Within the same plug-in, the extension are sorted by their unique id (if available) + if (value == 0 && o1.getUniqueIdentifier() != null && o2.getUniqueIdentifier() != null) + return o1.getUniqueIdentifier().compareTo(o2.getUniqueIdentifier()); + // Otherwise, just return the comparisation result from the contributors + return value; + } + + // Contributions from all other plug-ins are sorted alphabetical + int value = contributor1.compareTo(contributor2); + // Within the same plug-in, the extension are sorted by their unique id (if available) + if (value == 0 && o1.getUniqueIdentifier() != null && o2.getUniqueIdentifier() != null) + return o1.getUniqueIdentifier().compareTo(o2.getUniqueIdentifier()); + // Otherwise, just return the comparisation result from the contributors + return value; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/IConditionTester.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/IConditionTester.java new file mode 100644 index 000000000..7edfc79dd --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/IConditionTester.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.interfaces; + +/** + * This interface must be implemented by callers of the executors utilities + * <code>wait</code> method. + * <p> + * The call to <code>isConditionFulfilled</code> must return <code>true</code> only + * if the desired condition, the caller want's to wait for, has been completely fulfilled! + */ +public interface IConditionTester { + /** + * Returns <code>true</code> if the desired condition, the caller want's to wait + * for, has been completely fulfilled. + */ + public boolean isConditionFulfilled(); + + /** + * Condition tester clean up. This method is called before any waiter method will + * be finally left. + */ + public void cleanup(); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/ISharedConstants.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/ISharedConstants.java new file mode 100644 index 000000000..dba2d0842 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/ISharedConstants.java @@ -0,0 +1,24 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.interfaces;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+/**
+ * Shared constants.
+ */
+public interface ISharedConstants {
+
+ /**
+ * Local time format presenting full time format including milliseconds.
+ */
+ public final static DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS"); //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/callback/ICallback.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/callback/ICallback.java new file mode 100644 index 000000000..5514c31ef --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/callback/ICallback.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.interfaces.callback; + +import javax.security.auth.callback.Callback; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; + + +/** + * Generic callback interface for asynchronous calls. + * + * @noimplement Not intended to be implemented by clients, use {@link Callback} as base implementation instead. + * @noextend + */ +public interface ICallback extends IPropertiesContainer { + + /** + * Returns if or if not the callbacks <code>done</code> method + * was called already. + * + * @return <code>True</code> if {@link #done(Object, IStatus)} was called already, <code>false</code> otherwise. + */ + public boolean isDone(); + + /** + * Callback method invoked when a request is completed. + * + * @param caller + * The caller or <code>null</code>. + * @param status + * The status. Must not be <code>null</code>. + */ + public void done(Object caller, IStatus status); + + /** + * Add an additional parent callback to the end of the parent callback list. + * + * @param callback + * The parent callback. Must not be <code>null</code>. + */ + public void addParentCallback(ICallback callback); + + /** + * Sets the result of an asynchronous operation to be carried by + * the callback object. + * + * @param result The result object or <code>null</code>. + */ + public void setResult(Object result); + + /** + * Gets the result of an asynchronous operation which is carried by + * the callback object. + * + * @return The result object or <code>null</code>. + */ + public Object getResult(); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventFireDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventFireDelegate.java new file mode 100644 index 000000000..305550280 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventFireDelegate.java @@ -0,0 +1,31 @@ +/** + * IWRNotificationFireDelegateListener.java + * Created on Sep 14, 2006 + * + * Copyright (c) 2006 - 2009 Wind River Systems, Inc. + * + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Wind River license agreement. + */ +package org.eclipse.tcf.te.runtime.interfaces.events; + +/** + * Common interface for notification fire delegate listeners.<br> + * If a notification listener additionally implements this interface, the notification + * manager will call the {@link #fire(Runnable)} method to delegate the thread + * handling. + * + * @author tobias.schwarz@windriver.com + */ +public interface IEventFireDelegate { + + /** + * Fire the given runnable. If the given runnable is <code>null</code>, + * the method should return immediatelly. The implementator of the + * interface is responsible for the thread-handling. + * + * @param runnable The runnable that should be started for notification or <code>null</code>. + */ + public void fire(final Runnable runnable); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventListener.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventListener.java new file mode 100644 index 000000000..23ed2b413 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/events/IEventListener.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.interfaces.events; + +import java.util.EventListener; +import java.util.EventObject; + +/** + * Interface to be implemented by event listeners. + */ +public interface IEventListener extends EventListener{ + + /** + * Invoked by the event manager if the event listener registration + * applies for the given event object. + * + * @param event The event. Must not be <code>null</code>. + */ + public void eventFired(EventObject event); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/extensions/IExecutableExtension.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/extensions/IExecutableExtension.java new file mode 100644 index 000000000..4b8de1540 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/extensions/IExecutableExtension.java @@ -0,0 +1,39 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.interfaces.extensions;
+
+
+/**
+ * Executable extension public interface declaration.
+ */
+public interface IExecutableExtension extends org.eclipse.core.runtime.IExecutableExtension {
+
+ /**
+ * Returns the unique id of the extension. The returned
+ * id must be never <code>null</code> or an empty string.
+ *
+ * @return The unique id.
+ */
+ public String getId();
+
+ /**
+ * Returns the label or UI name of the extension.
+ *
+ * @return The label or UI name. An empty string if not set.
+ */
+ public String getLabel();
+
+ /**
+ * Returns the description of the extension.
+ *
+ * @return The description or an empty string.
+ */
+ public String getDescription();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/properties/IPropertiesContainer.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/properties/IPropertiesContainer.java new file mode 100644 index 000000000..be8e13cf9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/properties/IPropertiesContainer.java @@ -0,0 +1,285 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.interfaces.properties; + +import java.util.Map; +import java.util.UUID; + +import org.eclipse.core.runtime.IAdaptable; + +/** + * A generic properties container. + */ +public interface IPropertiesContainer extends IAdaptable { + + /** + * Returns the unique identified of the properties container. + * + * @return The unique identifier. + */ + public UUID getUUID(); + + /** + * Set if or if not firing change events is enabled. + * + * @param param enabled <code>True</code> to enable the change events, <code>false</code> to disable the change events. + * @return <code>True</code> if the enablement has changed, <code>false</code> if not. + */ + public boolean setChangeEventsEnabled(boolean enabled); + + /** + * Returns if or if not firing change events is enabled. + * + * @return <code>True</code> if change events are enabled, <code>false</code> if disabled. + */ + public boolean changeEventsEnabled(); + + /** + * Set the properties from the given map. Calling this method + * will overwrite all previous set properties. + * + * @param properties The map of properties to set. Must not be <code>null</code>. + */ + public void setProperties(Map<String, Object> properties); + + /** + * Stores the property under the given property key using the given property value. + * If the current property value is equal to the given property value, no store + * operation will be executed. If the property value is not <code>null</code> and + * is different from the current property value, the new value will be written to + * the property store and a property change event is fired. If the property value + * is <code>null</code>, the property key and the currently stored value are removed + * from the property store. + * + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + */ + public boolean setProperty(String key, Object value); + + /** + * Stores the property under the given property key using the given long + * property value. The given long value is transformed to an <code>Long</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, long value); + + /** + * Stores the property under the given property key using the given integer + * property value. The given integer value is transformed to an <code>Integer</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, int value); + + /** + * Stores the property under the given property key using the given boolean + * property value. The given boolean value is transformed to an <code>Boolean</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, boolean value); + + /** + * Stores the property under the given property key using the given float + * property value. The given float value is transformed to an <code>Float</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, float value); + + /** + * Stores the property under the given property key using the given double + * property value. The given double value is transformed to an <code>Double</code> + * object and stored to the properties store via <code>setProperty(java.lang.String, java.lang.Object)</code>. + * + * @param key The property key. Must not be <code>null</code>! + * @param value The property value. + * @return <code>true</code> if the property value had been applied to the property store, <code>false</code> otherwise. + * + * @see <code>setProperty(java.lang.String, java.lang.Object)</code> + */ + public boolean setProperty(String key, double value); + + /** + * Return all properties. The result map is read-only. + * + * @return A map containing all properties. + */ + public Map<String, Object> getProperties(); + + /** + * Queries the property value stored under the given property key. If the property + * does not exist, <code>null</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value or <code>null</code>. + */ + public Object getProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.String</code>, the property value casted to + * <code>java.lang.String</code> is returned. In all other cases, <code>null</code> + * is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value casted <code>java.lang.String</code> or <code>null</code>. + */ + public String getStringProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Long</code>, the property value converted + * to an long value is returned. In all other cases, <code>-1</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value converted to a long value or <code>-1</code>. + */ + public long getLongProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Integer</code>, the property value converted + * to an integer value is returned. In all other cases, <code>-1</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value converted to an integer value or <code>-1</code>. + */ + public int getIntProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Boolean</code>, the property value converted + * to an boolean value is returned. In all other cases, <code>false</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value converted to an boolean value or <code>false</code>. + */ + public boolean getBooleanProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Float</code>, the property value converted + * to an float value is returned. In all other cases, <code>Float.NaN</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value converted to a float value or <code>Float.NaN</code>. + */ + public float getFloatProperty(String key); + + /** + * Queries the property value stored under the given property key. If the property + * exist and is of type <code>java.lang.Double</code>, the property value converted + * to an double value is returned. In all other cases, <code>Double.NaN</code> is returned. + * + * @param key The property key. Must not be <code>null</code>! + * @return The stored property value converted to a double value or <code>Double.NaN</code>. + */ + public double getDoubleProperty(String key); + + /** + * Remove all properties from the properties store. The method does not fire any + * properties changed event. + */ + public void clearProperties(); + + /** + * Test if the property value stored under the given property is equal ignoring the case to the given + * expected string value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property string value. + * @return <code>true</code> if the expected string value is equal ignoring the case to the stored property value, <code>false</code> otherwise. + */ + public boolean isPropertyIgnoreCase(String key, String value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, Object value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, long value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, int value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, boolean value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, float value); + + /** + * Test if the property value stored under the given property is equal to the given + * expected value. + * + * @param key The property key. Must not be <code>null</code>. + * @param value The expected property value. + * @return <code>true</code> if the expected value is equal to the stored property value, <code>false</code> otherwise. + */ + public boolean isProperty(String key, double value); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/tracing/ITraceIds.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/tracing/ITraceIds.java new file mode 100644 index 000000000..f9fe03e7c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/tracing/ITraceIds.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.interfaces.tracing; + +/** + * Runtime plug-in trace slot identifiers. + */ +public interface ITraceIds { + + /** + * If activated, trace information about event dispatching is printed out. + */ + public static final String TRACE_EVENTS = "trace/events"; //$NON-NLS-1$ + + /** + * If activated, trace information about asynchronous callbacks is printed out. + */ + public static final String TRACE_CALLBACKS = "trace/callbacks"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/workingsets/IWorkingSetElement.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/workingsets/IWorkingSetElement.java new file mode 100644 index 000000000..fdeba61e1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/interfaces/workingsets/IWorkingSetElement.java @@ -0,0 +1,31 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.interfaces.workingsets;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ * Interface to be implemented by root elements contributed to the
+ * Target Explorer tree view which can be added to a working set as
+ * root element.
+ */
+public interface IWorkingSetElement extends IAdaptable {
+
+ /**
+ * Returns the working set element id.
+ * <p>
+ * The working set element id must be unique and persisted through out multiple session. This id
+ * is used to identify the working set element at restarting the Target Explorer after a session
+ * shutdown.
+ *
+ * @return The working set element id.
+ */
+ public String getElementId();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/DebugEventListener.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/DebugEventListener.java new file mode 100644 index 000000000..ab56d02ee --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/DebugEventListener.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.internal; + +import java.util.EventObject; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener; +import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds; + +/** + * Event listener for internal debugging purpose. + */ +public class DebugEventListener implements IEventListener { + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventListener#eventFired(java.util.EventObject) + */ + @Override + public void eventFired(EventObject event) { + if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_EVENTS)) + CoreBundleActivator.getTraceHandler().trace("thread=[" + Thread.currentThread().getName() + "]\n\t" + event.toString(), //$NON-NLS-1$ //$NON-NLS-2$ + 0, ITraceIds.TRACE_EVENTS, IStatus.INFO, this); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PreferencesPropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PreferencesPropertyTester.java new file mode 100644 index 000000000..7b9f164a1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PreferencesPropertyTester.java @@ -0,0 +1,76 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.internal;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.preferences.ScopedEclipsePreferences;
+
+/**
+ * Preferences property tester implementation.
+ */
+public class PreferencesPropertyTester extends PropertyTester {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
+ */
+ @Override
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+ // The preferences property tester is not extending a specific object type.
+ // The tester ignores the given receiver object.
+
+ if ("preference".equals(property)) { //$NON-NLS-1$
+ String bundleId = CoreBundleActivator.getUniqueIdentifier();
+ String key = null;
+
+ // Search the args for bundle id, the preference type and the preference key
+ for (Object candidate : args) {
+ // We cannot handle arguments other than strings
+ if (!(candidate instanceof String)) continue;
+
+ String arg = (String)candidate;
+
+ // bundleId=<id>
+ if (arg.toLowerCase().startsWith("bundleid")) { //$NON-NLS-1$
+ String[] tokens = arg.split("=", 2); //$NON-NLS-1$
+ // Check if the given bundle id really resolves to an installed bundle
+ if (tokens.length == 2 && tokens[1] != null && Platform.getBundle(tokens[1].trim()) != null) {
+ bundleId = tokens[1].trim();
+ }
+ }
+
+ // key=<preference key>
+ if (arg.toLowerCase().startsWith("key")) { //$NON-NLS-1$
+ String[] tokens = arg.split("=", 2); //$NON-NLS-1$
+ // Check for the key not being empty or null
+ if (tokens.length == 2 && tokens[1] != null && !"".equals(tokens[1].trim())) { //$NON-NLS-1$
+ key = tokens[1].trim();
+ }
+ }
+ }
+
+ // Lookup the preference
+ if (key != null) {
+ // Check the preference within the instance and default scope
+ ScopedEclipsePreferences preferences = new ScopedEclipsePreferences(bundleId);
+ // If the expected value is not specified or "null", check if the preference
+ // key is set or not. Return "true" if the key is not set.
+ if (expectedValue == null || "null".equals(expectedValue)) return !preferences.containsKey(key); //$NON-NLS-1$
+
+ // Always check against the string value
+ return expectedValue.toString().equals(preferences.getString(key));
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PropertiesContainerPropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PropertiesContainerPropertyTester.java new file mode 100644 index 000000000..34f1bf449 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/internal/PropertiesContainerPropertyTester.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.internal; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.runtime.Assert; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; + +/** + * Property tester implementation for objects of type {@link IPropertiesContainer}. + */ +public class PropertiesContainerPropertyTester extends PropertyTester { + + /* (non-Javadoc) + * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object) + */ + @Override + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + // The receiver is expected to be a properties container + if (receiver instanceof IPropertiesContainer) { + + if ("isProperty".equals(property)) { // //$NON-NLS-1$ + // Test for an individual property within the property container + return testIsProperty((IPropertiesContainer)receiver, args, expectedValue); + } + } + return false; + } + + /** + * Test the specific model node properties. + * + * @param node The properties container. Must not be <code>null</code>. + * @param args The property arguments. + * @param expectedValue The expected value. + * + * @return <code>True</code> if the property to test has the expected value, <code>false</code> otherwise. + */ + protected boolean testIsProperty(IPropertiesContainer node, Object[] args, Object expectedValue) { + Assert.isNotNull(node); + + if (args != null && args.length > 0 && args[0] instanceof String) { + return node.isProperty((String)args[0], expectedValue); + } + + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java new file mode 100644 index 000000000..bd95b364f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.nls; + +import org.eclipse.osgi.util.NLS; + +/** + * Target Explorer Runtime plugin externalized strings management. + */ +public class Messages extends NLS { + + // The plug-in resource bundle name + private static final String BUNDLE_NAME = "org.eclipse.tcf.te.runtime.nls.Messages"; //$NON-NLS-1$ + + /** + * Static constructor. + */ + static { + // Load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + // **** Declare externalized string id's down here ***** + + public static String Extension_error_missingRequiredAttribute; + public static String Extension_error_duplicateExtension; + public static String Extension_error_invalidExtensionPoint; +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties new file mode 100644 index 000000000..f8468eb14 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/nls/Messages.properties @@ -0,0 +1,8 @@ +# +# org.eclipse.tcf.te.runtime +# Externalized Strings. +# + +Extension_error_missingRequiredAttribute=Required attribute "{0}" missing for extension "{1}"! +Extension_error_duplicateExtension=Duplicate extension with id ''{0}''. Ignoring duplicated contribution from contributor ''{1}''! +Extension_error_invalidExtensionPoint=Failed to instantiate the executable extension from extension point ''{0}''. diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/preferences/ScopedEclipsePreferences.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/preferences/ScopedEclipsePreferences.java new file mode 100644 index 000000000..cfb68e4fa --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/preferences/ScopedEclipsePreferences.java @@ -0,0 +1,459 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.preferences; + +import java.io.OutputStream; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.core.runtime.preferences.IPreferenceFilter; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Helper class to handle scoped Eclipse preferences for plug-in's. Scoped + * preferences means a given preference context plus the default preferences + * scope. + * <p> + * On changes a {@link PreferenceChangeEvent} is sent to inform all listeners of the change. + * + * @see IEclipsePreferences + * @see IEclipsePreferences.PreferenceChangeEvent + * @see IEclipsePreferences.IPreferenceChangeListener + */ +public class ScopedEclipsePreferences { + /** + * The preferences scope qualifier. + */ + private final String qualifier; + + /** + * The default scope preference node. + */ + protected final IEclipsePreferences defaultPrefs; + + /** + * The context scope preference node. + */ + protected final IEclipsePreferences contextScopePrefs; + + /** + * The registered preference change listeners. + */ + private final ListenerList listeners = new ListenerList(); + + /** + * Constructor. + * <p> + * Initialize the scoped preferences with a new instance scope for the given qualifier. The default + * scope is determined by calling <code>DefaultScope().getNode(qualifier)</code>. + * + * @param qualifier The qualifier for the preferences (in example the unique identifier of a plugin). Must not be <code>null</code>. + */ + public ScopedEclipsePreferences(String qualifier) { + this(InstanceScope.INSTANCE, qualifier); + } + + /** + * Constructor. + * <p> + * Initialize the scoped preferences with the given scope. The default scope + * is determined by calling <code>DefaultScope().getNode(qualifier)</code>. + * + * @param context The preference scope context. Must not be <code>null</code>. + * @param qualifier The qualifier for the preferences (in example the unique identifier of a plugin). Must not be <code>null</code>. + */ + public ScopedEclipsePreferences(IScopeContext context, String qualifier) { + Assert.isNotNull(context); + Assert.isNotNull(qualifier); + this.qualifier = qualifier; + defaultPrefs = DefaultScope.INSTANCE.getNode(getQualifier()); + contextScopePrefs = context.getNode(getQualifier()); + } + + /** + * Returns the qualifier that is used to get the preferences. + * For plugin preferences, this is the unique identifier of the plugin. + */ + protected final String getQualifier() { + return qualifier; + } + + /** + * Exports the preferences to the stream. + * <p> + * <b>Note:</b> The stream will be closed after the export. + * + * @param stream The stream to where preferences and defaults should be exported. + */ + public void exportPreferences(OutputStream stream) { + Assert.isNotNull(stream); + try { + IPreferenceFilter filter = new IPreferenceFilter() { + /* (non-Javadoc) + * @see org.eclipse.core.runtime.preferences.IPreferenceFilter#getScopes() + */ + @Override + public String[] getScopes() { + return new String[] { InstanceScope.SCOPE }; + } + /* (non-Javadoc) + * @see org.eclipse.core.runtime.preferences.IPreferenceFilter#getMapping(java.lang.String) + */ + @Override + public Map getMapping(String scope) { + return null; + } + }; + + Platform.getPreferencesService().exportPreferences(contextScopePrefs, new IPreferenceFilter[] { filter }, stream); + stream.close(); + } + catch (Exception e) { + } + } + + /** + * Check whether a key is set or not. + * + * @param key The key to check. + * @return <code>null</code> if the key does not exist. + */ + public boolean containsKey(String key) { + return Platform.getPreferencesService().getString(getQualifier(), key, null, null) != null; + } + + /** + * Get a String preference value. + * + * @param key The preference key. + * @return The value of the preference key or the default value if not set. + */ + public final String getString(String key) { + return Platform.getPreferencesService().getString(getQualifier(), key, null, null); + } + + /** + * Get a boolean preference value. + * + * @param key The preference key. + * @return The value of the preference key or the default value if not set. + */ + public final boolean getBoolean(String key) { + return Platform.getPreferencesService().getBoolean(getQualifier(), key, false, null); + } + + /** + * Get an int preference value. + * + * @param key The preference key. + * @return The value of the preference key or the default value if not set. + */ + public final int getInt(String key) { + return Platform.getPreferencesService().getInt(getQualifier(), key, 0, null); + } + + /** + * Get a long preference value. + * + * @param key The preference key. + * @return The value of the preference key or the default value if not set. + */ + public final long getLong(String key) { + return Platform.getPreferencesService().getLong(getQualifier(), key, 0, null); + } + + /** + * Get a default String preference value. + * + * @param key The preference key. + * @return The default value of the preference key or <code>null</code>. + */ + public final String getDefaultString(String key) { + return defaultPrefs.get(key, null); + } + + /** + * Get a default boolean preference value. + * + * @param key The preference key. + * @return The default value of the preference key or <code>null</code>. + */ + public final boolean getDefaultBoolean(String key) { + return defaultPrefs.getBoolean(key, false); + } + + /** + * Get a default int preference value. + * + * @param key The preference key. + * @return The default value of the preference key or <code>null</code>. + */ + public final int getDefaultInt(String key) { + return defaultPrefs.getInt(key, 0); + } + + /** + * Get a default long preference value. + * + * @param key The preference key. + * @return The default value of the preference key or <code>null</code>. + */ + public final long getDefaultLong(String key) { + return defaultPrefs.getLong(key, 0); + } + + /** + * Set a String preference value. If the value is <code>null</code> or is equal to + * the default value, the entry will be removed. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. + * + * @param key The preference key. + * @return The value of the preference key. + */ + public void putString(String key, String value) { + String defValue = defaultPrefs.get(key, null); + String instValue = getString(key); + if (value == null || value.equals(defValue)) { + contextScopePrefs.remove(key); + flushAndNotify(contextScopePrefs, key, instValue, defValue); + } + else if (!value.equals(instValue)) { + contextScopePrefs.put(key, value); + flushAndNotify(contextScopePrefs, key, instValue, value); + } + } + + /** + * Set a boolean preference value. If the value is equal the default value, + * the entry will be removed. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. + * + * @param key The preference key. + * @return The value of the preference key. + */ + public void putBoolean(String key, boolean value) { + boolean defValue = defaultPrefs.getBoolean(key, false); + boolean instValue = getBoolean(key); + if (value == defValue) { + contextScopePrefs.remove(key); + flushAndNotify(contextScopePrefs, key, Boolean.toString(instValue), Boolean.toString(defValue)); + } + else if (value != instValue) { + contextScopePrefs.putBoolean(key, value); + flushAndNotify(contextScopePrefs, key, Boolean.toString(instValue), Boolean.toString(value)); + } + } + + /** + * Set an int preference value. If the value is equal to the default value, + * the entry will be removed. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. The old + * and new values are string representation in base 10. + * + * @param key The preference key. + * @return The value of the preference key. + */ + public void putInt(String key, int value) { + int defValue = defaultPrefs.getInt(key, 0); + int instValue = getInt(key); + if (value == defValue) { + contextScopePrefs.remove(key); + flushAndNotify(contextScopePrefs, key, Integer.toString(instValue), Integer.toString(defValue)); + } + else if (value != instValue) { + contextScopePrefs.putInt(key, value); + flushAndNotify(contextScopePrefs, key, Integer.toString(instValue), Integer.toString(value)); + } + } + + /** + * Set a long preference value. If the given value is equal to the default + * value, the entry will be removed. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. The old + * and new values are string representation in base 10. + * + * @param key The preference key. + * @return The value of the preference key. + */ + public void putLong(String key, long value) { + long defValue = defaultPrefs.getLong(key, 0); + long instValue = getLong(key); + if (value == defValue) { + contextScopePrefs.remove(key); + flushAndNotify(contextScopePrefs, key, Long.toString(instValue), Long.toString(defValue)); + } + else if (value != instValue) { + contextScopePrefs.putLong(key, value); + flushAndNotify(contextScopePrefs, key, Long.toString(instValue), Long.toString(value)); + } + } + + /** + * Set a default String preference value. If the given value is <code>null</code>, + * the entry will be removed. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. + * + * @param key The preference key. + * @return The default value of the preference key. + */ + public void putDefaultString(String key, String value) { + String defValue = defaultPrefs.get(key, null); + if (value == null) { + defaultPrefs.remove(key); + flushAndNotify(defaultPrefs, key, defValue, null); + } + else if (!value.equals(defValue)) { + defaultPrefs.put(key, value); + flushAndNotify(defaultPrefs, key, defValue, value); + } + } + + /** + * Set a default boolean preference value. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. + * + * @param key The preference key. + * @return The default value of the preference key. + */ + public void putDefaultBoolean(String key, boolean value) { + boolean defValue = defaultPrefs.getBoolean(key, false); + if (value != defValue) { + defaultPrefs.putBoolean(key, value); + flushAndNotify(defaultPrefs, key, Boolean.toString(defValue), Boolean.toString(value)); + } + } + + /** + * Set a default int preference value. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. The old + * and new values are string representation in base 10. + * + * @param key The preference key. + * @return The default value of the preference key. + */ + public void putDefaultInt(String key, int value) { + int defValue = defaultPrefs.getInt(key, 0); + if (value != defValue) { + defaultPrefs.putInt(key, value); + flushAndNotify(defaultPrefs, key, Integer.toString(defValue), Integer.toString(value)); + } + } + + /** + * Set a default long preference value. + * <p> + * A {@link PreferenceChangeEvent} is fired, if the value has changed. The old + * and new values are string representation in base 10. + * + * @param key The preference key. + * @return The default value of the preference key. + */ + public void putDefaultLong(String key, long value) { + long defValue = defaultPrefs.getLong(key, 0); + if (value != defValue) { + defaultPrefs.putLong(key, value); + flushAndNotify(defaultPrefs, key, Long.toString(defValue), Long.toString(value)); + } + } + + /** + * Write back the changes to the store and notify all listeners about the changed key. + * + * @param node The preference node which has changed. Must not be <code>null</code>. + * @param key The key of the changed preference. Must not be <code>null</code>. + * @param oldValue The old value as a {@link String}, or <code>null</code>. + * @param newValue The new value as a {@link String}, or <code>null</code>. + */ + protected final void flushAndNotify(IEclipsePreferences node, String key, String oldValue, String newValue) { + // Flush the preferences to the persistence store + try { node.flush(); } catch (BackingStoreException e) { /* Ignored on purpose */ } + + // Notify the listeners + firePreferenceEvent(node, key, oldValue, newValue); + } + + /** + * Register the given listener to receive notifications of preference changes to this node. + * Calling this method multiple times with the same listener has no effect. The given listener + * argument must not be <code>null</code>. + * + * @param listener The preference change listener. Must not be <code>null</code>. + */ + public void addPreferenceChangeListener(IPreferenceChangeListener listener) { + Assert.isNotNull(listener); + listeners.add(listener); + } + + /** + * De-register the given listener from receiving notifications of preference changes + * to this node. Calling this method multiple times with the same listener has no + * effect. The given listener argument must not be <code>null</code>. + * + * @param listener The preference change listener. Must not be <code>null</code>. + */ + public void removePreferenceChangeListener(IPreferenceChangeListener listener) { + Assert.isNotNull(listener); + listeners.remove(listener); + } + + /** + * Convenience method for notifying the registered preference change listeners. + * + * @param node The preference node which has changed. Must not be <code>null</code>. + * @param key The key of the changed preference. Must not be <code>null</code>. + * @param oldValue The old value as a {@link String}, or <code>null</code>. + * @param newValue The new value as a {@link String}, or <code>null</code>. + */ + protected void firePreferenceEvent(IEclipsePreferences node, String key, String oldValue, String newValue) { + Assert.isNotNull(node); + Assert.isNotNull(key); + + // If no listener is registered, we are done here + if (listeners.isEmpty()) return; + + // Get the list or currently registered listeners + Object[] l = listeners.getListeners(); + // Create the preference change event + final PreferenceChangeEvent event = new PreferenceChangeEvent(node, key, oldValue, newValue); + for (int i = 0; i < l.length; i++) { + final IPreferenceChangeListener listener = (IPreferenceChangeListener) l[i]; + ISafeRunnable job = new ISafeRunnable() { + @Override + public void handleException(Throwable exception) { + // already logged in Platform#run() + } + + @Override + public void run() throws Exception { + listener.preferenceChange(event); + } + }; + SafeRunner.run(job); + } + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/properties/PropertiesContainer.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/properties/PropertiesContainer.java new file mode 100644 index 000000000..261243275 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/properties/PropertiesContainer.java @@ -0,0 +1,532 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.properties;
+
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.events.ChangeEvent;
+import org.eclipse.tcf.te.runtime.events.EventManager;
+import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
+import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds;
+
+/**
+ * A generic properties container implementation.
+ * <p>
+ * <b>Note:</b> The properties container implementation is not thread-safe. Clients requiring
+ * a thread-safe implementation should subclass the properties container and
+ * overwrite {@link #checkThreadAccess()}.
+ */
+public class PropertiesContainer extends PlatformObject implements IPropertiesContainer {
+ // Used to have a simple check that the random generated UUID isn't
+ // the same if objects of this type are created very rapidly.
+ private static UUID LAST_UUID_GENERATED = null;
+
+ // The unique node id
+ private final UUID uniqueId;
+
+ // The flag to remember the notification enablement
+ private boolean changeEventsEnabled = false;
+
+ /**
+ * The custom properties map. The keys are always strings, the value might be any object.
+ */
+ private Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+ /**
+ * Constructor.
+ */
+ public PropertiesContainer() {
+ super();
+
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+
+ // Initialize the unique node id.
+ UUID uuid = UUID.randomUUID();
+ while (LAST_UUID_GENERATED != null && LAST_UUID_GENERATED.equals(uuid)) {
+ uuid = UUID.randomUUID();
+ }
+ LAST_UUID_GENERATED = uuid;
+ uniqueId = LAST_UUID_GENERATED;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getUUID()
+ */
+ @Override
+ public final UUID getUUID() {
+ return uniqueId;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PropertiesContainer) {
+ return uniqueId.equals(((PropertiesContainer)obj).uniqueId);
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return uniqueId.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+
+ buffer.append("UUID=" + uniqueId.toString()); //$NON-NLS-1$
+
+ // print the first level of the properties map only
+ buffer.append(", properties={"); //$NON-NLS-1$
+ for (String key : properties.keySet()) {
+ buffer.append(key);
+ buffer.append("="); //$NON-NLS-1$
+
+ Object value = properties.get(key);
+ if (value instanceof Map || value instanceof IPropertiesContainer) {
+ buffer.append("{...}"); //$NON-NLS-1$
+ } else {
+ buffer.append(value);
+ }
+
+ buffer.append(", "); //$NON-NLS-1$
+ }
+ if (buffer.toString().endsWith(", ")) { //$NON-NLS-1$
+ buffer.deleteCharAt(buffer.length() - 1);
+ buffer.deleteCharAt(buffer.length() - 1);
+ }
+ buffer.append("}"); //$NON-NLS-1$
+
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.nodes.IPropertiesContainer#setChangeEventsEnabled(boolean)
+ */
+ @Override
+ public final boolean setChangeEventsEnabled(boolean enabled) {
+ boolean changed = changeEventsEnabled != enabled;
+ if (changed) changeEventsEnabled = enabled;
+ return changed;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.nodes.IPropertiesContainer#changeEventsEnabled()
+ */
+ @Override
+ public final boolean changeEventsEnabled() {
+ return changeEventsEnabled;
+ }
+
+ /**
+ * Creates a new property change notification event object. The event object is initialized
+ * with the given parameter.
+ * <p>
+ * This method is typically called from {@link #setProperty(String, Object)} in case the
+ * property changed it's value. <code>Null</code> is returned if no event should be fired.
+ *
+ * @param source The source object. Must not be <code>null</code>.
+ * @param key The property key. Must not be <code>null</code>.
+ * @param oldValue The old properties value.
+ * @param newValue The new properties value.
+ *
+ * @return The new property change notification event instance or <code>null</code>.
+ */
+ public final EventObject newEvent(Object source, String key, Object oldValue, Object newValue) {
+ Assert.isNotNull(source);
+ Assert.isNotNull(key);
+
+ // Check if the event is dropped
+ if (dropEvent(source, key, oldValue, newValue)) {
+ // Log the event dropping if tracing is enabled
+ if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITraceIds.TRACE_EVENTS)) {
+ CoreBundleActivator.getTraceHandler().trace("Drop event notification (not created change event)\n\t\t" + //$NON-NLS-1$
+ "for eventId = " + key + ",\n\t\t" + //$NON-NLS-1$ //$NON-NLS-2$
+ "currentValue = " + oldValue + ",\n\t\t" + //$NON-NLS-1$ //$NON-NLS-2$
+ "newValue = " + newValue, //$NON-NLS-1$
+ 0, ITraceIds.TRACE_EVENTS, IStatus.WARNING, this);
+ }
+ return null;
+ }
+
+ // Create the notification event instance.
+ return newEventDelegate(source, key, oldValue, newValue);
+ }
+
+ /**
+ * Creates a new property change notification event object instance.
+ * <p>
+ * This method is typically called from {@link #newEvent(Object, String, Object, Object)}
+ * if notifications are enabled.
+ *
+ * @param source The source object. Must not be <code>null</code>.
+ * @param key The property key. Must not be <code>null</code>.
+ * @param oldValue The old properties value.
+ * @param newValue The new properties value.
+ *
+ * @return The new property change notification event instance or <code>null</code>.
+ */
+ protected EventObject newEventDelegate(Object source, String key, Object oldValue, Object newValue) {
+ Assert.isNotNull(source);
+ Assert.isNotNull(key);
+ return new ChangeEvent(source, key, oldValue, newValue);
+ }
+
+ /**
+ * Returns if or if not notifying the given property change has to be dropped.
+ *
+ * @param source The source object. Must not be <code>null</code>.
+ * @param key The property key. Must not be <code>null</code>.
+ * @param oldValue The old properties value.
+ * @param newValue The new properties value.
+ *
+ * @return <code>True</code> if dropping the property change notification, <code>false</code> if notifying the property change.
+ */
+ protected boolean dropEvent(Object source, String key, Object oldValue, Object newValue) {
+ Assert.isNotNull(source);
+ Assert.isNotNull(key);
+ return !changeEventsEnabled || key.endsWith(".silent"); //$NON-NLS-1$
+ }
+
+ /**
+ * Checks if the access to the properties container happens in
+ * a privileged thread.
+ * <p>
+ * The default implementation returns always <code>true</code>. Overwrite
+ * to implement thread-safe properties container access.
+ *
+ * @return <code>True</code> if the access to the properties container is allowed, <code>false</code> otherwise.
+ */
+ protected boolean checkThreadAccess() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getProperties()
+ */
+ @Override
+ public Map<String, Object> getProperties() {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ return Collections.unmodifiableMap(new HashMap<String, Object>(properties));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getProperty(java.lang.String)
+ */
+ @Override
+ public Object getProperty(String key) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ return properties.get(key);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getBooleanProperty(java.lang.String)
+ */
+ @Override
+ public final boolean getBooleanProperty(String key) {
+ Object value = getProperty(key);
+ if (value instanceof Boolean) {
+ return ((Boolean)value).booleanValue();
+ }
+ if (value instanceof String) {
+ String val = ((String)value).trim();
+ return "TRUE".equalsIgnoreCase(val) || "1".equals(val) || "Y".equalsIgnoreCase(val) || //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "JA".equalsIgnoreCase(val) || "YES".equalsIgnoreCase(val); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getLongProperty(java.lang.String)
+ */
+ @Override
+ public final long getLongProperty(String key) {
+ Object value = getProperty(key);
+ if (value instanceof Long) {
+ return ((Long)value).longValue();
+ }
+ else if (value instanceof Integer) {
+ return ((Integer)value).intValue();
+ }
+ else if (value != null) {
+ try {
+ return Long.decode(value.toString()).longValue();
+ }
+ catch (Exception e) {}
+ }
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getIntProperty(java.lang.String)
+ */
+ @Override
+ public final int getIntProperty(String key) {
+ Object value = getProperty(key);
+ try {
+ return value instanceof Integer ? ((Integer)value).intValue() :
+ (value != null ? Integer.decode(value.toString()).intValue() : -1);
+ }
+ catch (Exception e) {
+ return -1;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getStringProperty(java.lang.String)
+ */
+ @Override
+ public final String getStringProperty(String key) {
+ Object value = getProperty(key);
+ return value instanceof String ? (String)value :
+ (value != null ? value.toString() : null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getFloatProperty(java.lang.String)
+ */
+ @Override
+ public final float getFloatProperty(String key) {
+ Object value = getProperty(key);
+ try {
+ return value instanceof Float ? ((Float)value).floatValue() :
+ (value != null ? Float.parseFloat(value.toString()) : Float.NaN);
+ }
+ catch (Exception e) {
+ return Float.NaN;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#getDoubleProperty(java.lang.String)
+ */
+ @Override
+ public final double getDoubleProperty(String key) {
+ Object value = getProperty(key);
+ try {
+ return value instanceof Double ? ((Double)value).doubleValue() :
+ (value != null ? Double.parseDouble(value.toString()) : Double.NaN);
+ }
+ catch (Exception e) {
+ return Double.NaN;
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperties(java.util.Map)
+ */
+ @Override
+ public final void setProperties(Map<String, Object> properties) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(properties);
+
+ this.properties.clear();
+ this.properties.putAll(properties);
+
+ postSetProperties(properties);
+ }
+
+ /**
+ * Method hook called by {@link #setProperties(Map)} just before the
+ * method returns to the caller.
+ *
+ * @param properties The map of properties set. Must not be <code>null</code>.
+ */
+ protected void postSetProperties(Map<String, Object> properties) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(properties);
+
+ EventObject event = newEvent(this, "properties", null, properties); //$NON-NLS-1$
+ if (event != null) EventManager.getInstance().fireEvent(event);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, boolean)
+ */
+ @Override
+ public final boolean setProperty(String key, boolean value) {
+ boolean oldValue = getBooleanProperty(key);
+ if (oldValue != value) {
+ return setProperty(key, Boolean.valueOf(value));
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, long)
+ */
+ @Override
+ public final boolean setProperty(String key, long value) {
+ long oldValue = getLongProperty(key);
+ if (oldValue != value) {
+ return setProperty(key, Long.valueOf(value));
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, int)
+ */
+ @Override
+ public final boolean setProperty(String key, int value) {
+ int oldValue = getIntProperty(key);
+ if (oldValue != value) {
+ return setProperty(key, Integer.valueOf(value));
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, float)
+ */
+ @Override
+ public final boolean setProperty(String key, float value) {
+ float oldValue = getFloatProperty(key);
+ if (oldValue != value) {
+ return setProperty(key, Float.valueOf(value));
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, double)
+ */
+ @Override
+ public final boolean setProperty(String key, double value) {
+ double oldValue = getDoubleProperty(key);
+ if (oldValue != value) {
+ return setProperty(key, Double.valueOf(value));
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#setProperty(java.lang.String, java.lang.Object)
+ */
+ @Override
+ public boolean setProperty(String key, Object value) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(key);
+
+ Object oldValue = properties.get(key);
+ if ((oldValue == null && value != null) || (oldValue != null && !oldValue.equals(value))) {
+ if (value != null) {
+ properties.put(key, value);
+ } else {
+ properties.remove(key);
+ }
+ postSetProperty(key, value, oldValue);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Method hook called by {@link #setProperty(String, Object)} in case the value
+ * of the given property changed and just before the method returns to the caller.
+ *
+ * @param key The property key. Must not be <code>null</code>.
+ * @param value The property value.
+ * @param oldValue The old property value.
+ */
+ public void postSetProperty(String key, Object value, Object oldValue) {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(key);
+
+ EventObject event = newEvent(this, key, oldValue, value);
+ if (event != null) EventManager.getInstance().fireEvent(event);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#clearProperties()
+ */
+ @Override
+ public final void clearProperties() {
+ Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$
+ properties.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, long)
+ */
+ @Override
+ public final boolean isProperty(String key, long value) {
+ return getLongProperty(key) == value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, boolean)
+ */
+ @Override
+ public final boolean isProperty(String key, boolean value) {
+ return getBooleanProperty(key) == value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, int)
+ */
+ @Override
+ public final boolean isProperty(String key, int value) {
+ return getIntProperty(key) == value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, float)
+ */
+ @Override
+ public final boolean isProperty(String key, float value) {
+ return getFloatProperty(key) == value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, double)
+ */
+ @Override
+ public final boolean isProperty(String key, double value) {
+ return getDoubleProperty(key) == value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isPropertyIgnoreCase(java.lang.String, java.lang.String)
+ */
+ @Override
+ public final boolean isPropertyIgnoreCase(String key, String value) {
+ String property = getStringProperty(key);
+ return (property == null && value == null) || (property != null && property.equalsIgnoreCase(value));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.IPropertiesContainer#isProperty(java.lang.String, java.lang.Object)
+ */
+ @Override
+ public final boolean isProperty(String key, Object value) {
+ Object property = getProperty(key);
+ return (property == null && value == null) || (property != null && property.equals(value));
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java new file mode 100644 index 000000000..12e1df46e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/tracing/TraceHandler.java @@ -0,0 +1,275 @@ +/*******************************************************************************
+ * Copyright (c) 2011 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.runtime.tracing;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * Helper class to handle tracing using the platforms debug capabilities.
+ */
+public class TraceHandler {
+ /**
+ * The bundle identifier.
+ */
+ private final String identifier;
+
+ /**
+ * The tracer instance.
+ */
+ private Tracer tracer = null;
+
+ /**
+ * The tracer is responsible for writing the trace message to the desired
+ * output media.
+ */
+ protected static class Tracer {
+
+ /**
+ * The bundle identifier.
+ */
+ private final String fIdentifier;
+
+ /**
+ * The qualifier for the default "<bundle identifier>/debugmode"
+ * tracing slot.
+ */
+ private final String fDebugModeQualifier;
+
+ /**
+ * Constructor.
+ *
+ * @param identifier The bundle identifier. Must not be <code>null</code>.
+ */
+ public Tracer(String identifier) {
+ Assert.isNotNull(identifier);
+ fIdentifier = identifier;
+
+ // Initialize the debug mode qualifier
+ fDebugModeQualifier = fIdentifier + "/debugmode"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the value of the debug mode tracing slot.
+ * <p>
+ * If not set, or the value is not an {@link Integer}, the method returns <code>0</code>.
+ *
+ * @return The debug mode value.
+ */
+ protected int getDebugMode() {
+ try {
+ String mode = Platform.getDebugOption(fDebugModeQualifier);
+ if (mode != null && Integer.decode(mode).intValue() > 0) {
+ return Integer.decode(mode).intValue();
+ }
+ } catch (NumberFormatException e) { /* ignored on purpose */ }
+
+ return 0;
+ }
+
+ /**
+ * Check if the specified trace slot is enabled.
+ *
+ * @param slotId The name of the slot.
+ * @return <code>true</code> if the slot is defined and enabled, <code>false</code> otherwise.
+ */
+ protected boolean isSlotEnabled(String slotId) {
+ return fIdentifier != null ? Boolean.parseBoolean(Platform.getDebugOption(fIdentifier + "/" + slotId)) : false; //$NON-NLS-1$
+ }
+
+ /**
+ * Check if tracing is enabled for given mode and slot.
+ *
+ * @param debugMode The debug mode for the current debug.
+ * @param slotId The name of the slot.
+ *
+ * @return <code>true</code> if the debug should be written, <code>false</code> otherwise.
+ */
+ protected final boolean isEnabled(int debugMode, String slotId) {
+ return getDebugMode() < 0 ||
+ (debugMode <= getDebugMode() &&
+ (slotId == null || slotId.trim().length() == 0 || isSlotEnabled(slotId)));
+ }
+
+ /**
+ * Format the trace message.
+ *
+ * @param message The trace message.
+ * @param debugMode The debug mode.
+ * @param slotId The name of the slot.
+ * @param severity The severity. See {@link IStatus} for valid severity values.
+ * @param clazz The class that calls this tracer.
+ *
+ * @see IStatus
+ */
+ protected String getFormattedDebugMessage(String message, int debugMode, String slotId, int severity, Object clazz) {
+ StringBuffer debug = new StringBuffer();
+ if (slotId != null || clazz != null) {
+ if (clazz != null) {
+ String name = clazz instanceof Class<?> ? ((Class<?>)clazz).getSimpleName() : clazz.getClass().getSimpleName();
+ debug.append((name != null && name.trim().length() > 0) ? name.trim() : clazz instanceof Class<?> ? ((Class<?>)clazz).getName() : clazz.getClass().getName());
+ }
+ if (slotId != null) {
+ debug.append(" at "); //$NON-NLS-1$
+ debug.append(slotId);
+ }
+ if (debugMode >= 0) {
+ debug.append(" (Mode "); //$NON-NLS-1$
+ debug.append(debugMode);
+ debug.append(')');
+ }
+ debug.append('\n');
+ debug.append('\t');
+ }
+ debug.append(message);
+
+ return debug.toString();
+ }
+
+ /**
+ * Write the trace message.
+ *
+ * @param message The trace message.
+ * @param debugMode The debug mode.
+ * @param slotId The name of the slot.
+ * @param severity The severity. See {@link IStatus} for valid severity values.
+ * @param clazz The class that calls this tracer.
+ *
+ * @see IStatus
+ */
+ protected void write(String message, int debugMode, String slotId, int severity, Object clazz) {
+ String formattedMessage = getFormattedDebugMessage(message, debugMode, slotId, severity, clazz);
+ if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
+ System.err.println(formattedMessage);
+ }
+ else {
+ System.out.println(formattedMessage);
+ }
+ }
+
+ /**
+ * Trace the given message with the given debug mode and slot.
+ *
+ * @param message The trace message.
+ * @param debugMode The debug mode.
+ * @param slotId The name of the slot.
+ * @param severity The severity. See {@link IStatus} for valid severity values.
+ * @param clazz The class that calls this tracer.
+ *
+ * @see IStatus
+ */
+ public final void trace(String message, int debugMode, String slotId, int severity, Object clazz) {
+ if (isEnabled(debugMode, slotId)) {
+ write(message, debugMode, slotId, severity, clazz);
+ }
+ }
+ }
+
+ /**
+ * Constructor.
+ * <p>
+ * Initializes the tracing handler with the given bundle identifier.
+ *
+ * @param identifier The bundle identifier. Must not be <code>null</code>.
+ */
+ public TraceHandler(String identifier) {
+ Assert.isNotNull(identifier);
+ this.identifier = identifier;
+ }
+
+ /**
+ * Returns the identifier.
+ */
+ protected final String getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * Returns the tracer instance. Create a new tracer instance
+ * on first invokation.
+ *
+ * @return The tracer instance.
+ */
+ protected Tracer getTracer() {
+ if (tracer == null) {
+ tracer = new Tracer(identifier);
+ }
+ return tracer;
+ }
+
+ /**
+ * Check whether a trace slot is enabled with the given debug mode.
+ *
+ * @param debugMode The debug mode
+ * @param slotId The name of the slot.
+ *
+ * @return <code>true</code> if the slot is enabled, <code>false</code> otherwise.
+ */
+ public final boolean isSlotEnabled(int debugMode, String slotId) {
+ return getTracer().isEnabled(debugMode, slotId);
+ }
+
+ /**
+ * Trace the given message.
+ * <p>
+ * The message severity will be {@link IStatus#INFO} and the message will be
+ * traced unconditionally.
+ *
+ * @param message The message.
+ * @param clazz The class that calls this tracer or <code>null</code>.
+ */
+ public final void trace(String message, Object clazz) {
+ getTracer().trace(message, 0, null, IStatus.INFO, clazz);
+ }
+
+ /**
+ * Trace the given message.
+ * <p>
+ * The message severity will be {@link IStatus#INFO}.
+ *
+ * @param message The message.
+ * @param debugMode The minimum debug mode that has to be set to write out the message.
+ * @param clazz The class that calls this tracer or <code>null</code>.
+ */
+ public final void trace(String message, int debugMode, Object clazz) {
+ getTracer().trace(message, debugMode, null, IStatus.INFO, clazz);
+ }
+
+ /**
+ * Trace the given message.
+ * <p>
+ * The message severity will be {@link IStatus#INFO} and the debug mode
+ * will default to <code>0</code>.
+ *
+ * @param message The message.
+ * @param slotId The slot that has to be enabled to write out the message.
+ * @param clazz The class that calls this tracer or <code>null</code>.
+ */
+ public final void trace(String message, String slotId, Object clazz) {
+ getTracer().trace(message, 0, slotId, IStatus.INFO, clazz);
+ }
+
+ /**
+ * Trace the given message.
+ *
+ * @param message The message.
+ * @param debugMode The minimum debug mode that has to be set to write out the message.
+ * @param slotId The slot that has to be enabled to write out the message.
+ * @param severity The severity. See {@link IStatus} for valid severity values.
+ * @param clazz The class that calls this tracer or <code>null</code>.
+ *
+ * @see IStatus
+ */
+ public final void trace(String message, int debugMode, String slotId, int severity, Object clazz) {
+ getTracer().trace(message, debugMode, slotId, severity, clazz);
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Host.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Host.java new file mode 100644 index 000000000..1fb00f631 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Host.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.io.IOException; + +/** + * Determine the current host environment. + */ +public final class Host { + private static Boolean isWindowsHost = null; + private static Boolean isInteractive = null; + private static Boolean isHeadless = null; + private static Boolean isLinuxHost = null; + + /** + * Method looking up the current host (once) and returning a boolean indicating whether the host + * is Unix(false) or Windows(true). + * + * @return boolean true if running on Windows host + */ + public static boolean isWindowsHost() { + if (isWindowsHost == null) { + if (System.getProperty("os.name", "").toLowerCase().startsWith("windows")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + isWindowsHost = Boolean.TRUE; + } + else { + isWindowsHost = Boolean.FALSE; + } + } + return isWindowsHost.booleanValue(); + } + + /** + * Method looking up the current host (once) and returning a boolean indicating whether the host + * is Linux(true) or something else (false). + * + * @return boolean true if running on Linux host + */ + public static boolean isLinuxHost() { + if (isLinuxHost == null) { + if (System.getProperty("os.name", "").toLowerCase().startsWith("linux")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + isLinuxHost = Boolean.TRUE; + } + else { + isLinuxHost = Boolean.FALSE; + } + } + return isLinuxHost.booleanValue(); + } + + /** + * Returns the content of the release file which exists in every linux distribution in /etc. + * e.g. /etc/redhat-release . The file holds information about the distribution itself. + * + * @return String containing the first line of the linux distri's release file. e.g. Red Hat + * Enterprise Linux WS release 4 (Nahant Update 3) + */ + public static String getLinuxRelease() { + String firstLine = "Unknown"; //$NON-NLS-1$ + File etcdir = new File("/etc");//$NON-NLS-1$ + String[] list = etcdir.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + String[] distStrings = { "fedora-release", //$NON-NLS-1$ + "redhat-release", //$NON-NLS-1$ + "SuSE-release", //$NON-NLS-1$ + "lsb-release" }; //$NON-NLS-1$ + // Strip path information: + String f = new File(name).getName(); + String filter; + for (String distString : distStrings) { + filter = distString; + if (f.equalsIgnoreCase(filter)) { + return true; + } + } + return false; + } + }); + + if (list == null || list.length == 0) { + return "Unknown"; //$NON-NLS-1$ + } + String entry = list[0]; + + if (Boolean.getBoolean("shell.debug")) { //$NON-NLS-1$ + System.out.println("UtilityEnvironment#getLinuxRelease: reading file: " + etcdir + "/" + entry); //$NON-NLS-1$ //$NON-NLS-2$ + } + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(new File(etcdir + "/" + entry))); //$NON-NLS-1$ + // In case of "lsb-release" we have to look for the line starting with + // "DISTRIB_DESCRIPTION" + if ("lsb-release".equalsIgnoreCase(entry)) { //$NON-NLS-1$ + while (firstLine != null && !firstLine.toUpperCase() + .startsWith("DISTRIB_DESCRIPTION")) { //$NON-NLS-1$ + if (Boolean.getBoolean("shell.debug")) { //$NON-NLS-1$ + System.out.println("UtilityEnvironment#getLinuxRelease: firstLine='" + firstLine + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + firstLine = reader.readLine(); + } + } + else { + // Just read the first line + firstLine = reader.readLine(); + } + } + catch (IOException ioe) { + firstLine = "Unknown"; //$NON-NLS-1$ + } + finally { + if (reader != null) { + try { + reader.close(); + } + catch (IOException ex) { + // silently ignored + } + } + } + + firstLine = firstLine != null ? firstLine : "Unknown"; //$NON-NLS-1$ + + if (Boolean.getBoolean("shell.debug")) { //$NON-NLS-1$ + System.out.println("UtilityEnvironment#getLinuxRelease: return value='" + firstLine + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + return firstLine; + } + + /** + * Check if running interactive (default) or in batch mode (e.g. during unit tests). + * + * @return boolean <code>true</code> if running in interactive mode (default) or + * <code>false</code> if not (-DNOINTERACTIVE=true). + */ + public static boolean isInteractive() { + if (isInteractive == null) { + boolean batchMode = Boolean.valueOf(System.getProperty("NOINTERACTIVE")).booleanValue(); //$NON-NLS-1$ + isInteractive = Boolean.valueOf(!batchMode); + } + return isInteractive.booleanValue(); + } + + /** + * Check if running in headless mode or with full UI. + * + * @return <code>true</code> if running in headless mode, <code>false</code> otherwise. + */ + public static boolean isHeadless() { + if (isHeadless == null) { + String headless = System.getProperty("HEADLESS"); //$NON-NLS-1$ + isHeadless = Boolean.valueOf(headless); + } + return isHeadless.booleanValue(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/ProgressHelper.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/ProgressHelper.java new file mode 100644 index 000000000..b57290401 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/ProgressHelper.java @@ -0,0 +1,317 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.utils; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.runtime.interfaces.tracing.ITraceIds; + +/** + * Helper implementation to deal with progress monitors and callbacks. + */ +public final class ProgressHelper { + + public static final int PROGRESS_DONE = 0; + public static final int PROGRESS_NONE = -1; + + /** + * Checks if there was an error or the operation was canceled. + * + * @param caller + * The caller or <code>null</code>. + * @param status + * The status. <code>null</code> if status should not be checked. + * @param progress + * The progress monitor. <code>null</code> if cancel should not + * be checked. + * @param callback + * The callback to call on cancel or error. + * + * @return <code>false</code> if everything is OK. + */ + public static final boolean isCancelOrError(Object caller, IStatus status, IProgressMonitor progress, ICallback callback) { + if (status == null) status = Status.OK_STATUS; + + if (!status.isOK() || (progress != null && progress.isCanceled())) { + if (status.getSeverity() == IStatus.CANCEL || (progress != null && progress.isCanceled())) { + status = new Status(IStatus.CANCEL, status.getPlugin(), + status.getCode(), status.getMessage(), + new OperationCanceledException()); + } else if (status.getSeverity() == IStatus.ERROR) { + Throwable e = status.getException(); + try { + throw e; + } catch (Throwable thrown) { + e = thrown; + } + CoreBundleActivator.getTraceHandler().trace( + status.getMessage(), + 1, + ITraceIds.TRACE_CALLBACKS, + status.getSeverity(), + caller != null ? caller.getClass() : ProgressHelper.class); + status = new Status(IStatus.ERROR, status.getPlugin(), status.getCode(), status.getMessage(), e); + } + + if (callback != null) { + if (caller instanceof ICallback) { + Callback.copyProperties((ICallback) caller, callback); + } + callback.done(caller, status); + } + return true; + } + return false; + } + + /** + * Checks if the operation was canceled. + * + * @param caller + * The caller or <code>null</code>. + * @param progress + * The progress monitor. Must not be <code>null</code> + * @param callback + * The callback to call on cancel or error. + * + * @return <code>false</code> if everything is OK. + */ + public static final boolean isCancel(Object caller, IProgressMonitor progress, ICallback callback) { + Assert.isNotNull(progress); + return isCancel(caller, null, progress, callback); + } + + /** + * Checks if the operation was canceled. + * + * @param caller + * The caller or <code>null</code>. + * @param status + * The status. Must not be <code>null</code>. + * @param callback + * The callback to call on cancel or error. + * + * @return <code>false</code> if everything is OK. + */ + public static final boolean isCancel(Object caller, IStatus status, ICallback callback) { + Assert.isNotNull(status); + return isCancel(caller, status, null, callback); + } + + /** + * Checks if the operation was canceled. + * + * @param caller + * The caller or <code>null</code>. + * @param status + * The status. <code>null</code> if status should not be checked. + * @param progress + * The progress monitor. <code>null</code> if cancel should not + * be checked. + * @param callback + * The callback to call on cancel or error. + * + * @return <code>false</code> if everything is OK. + */ + public static final boolean isCancel(Object caller, IStatus status, IProgressMonitor progress, ICallback callback) { + if (status == null) status = Status.OK_STATUS; + + if (status.getSeverity() == IStatus.CANCEL || (progress != null && progress.isCanceled())) { + status = new Status(IStatus.CANCEL, status.getPlugin(), + status.getCode(), status.getMessage(), + new OperationCanceledException()); + + if (callback != null) { + if (caller instanceof ICallback) { + Callback.copyProperties((ICallback) caller, callback); + } + callback.done(caller, status); + } + return true; + } + return false; + } + + /** + * Checks if there was an error. + * + * @param caller + * The caller or <code>null</code>. + * @param status + * The status. <code>null</code> if status should not be checked. + * @param callback + * The callback to call on cancel or error. + * + * @return <code>false</code> if everything is OK. + */ + public static final boolean isError(Object caller, IStatus status, ICallback callback) { + if (status == null) status = Status.OK_STATUS; + + if (!status.isOK() && status.getSeverity() != IStatus.CANCEL) { + if (status.getSeverity() == IStatus.ERROR) { + Throwable e = status.getException(); + try { + throw e; + } catch (Throwable thrown) { + e = thrown; + } + CoreBundleActivator.getTraceHandler().trace( + status.getMessage(), + 1, + ITraceIds.TRACE_CALLBACKS, + status.getSeverity(), + caller != null ? caller.getClass() : ProgressHelper.class); + status = new Status(IStatus.ERROR, status.getPlugin(), status.getCode(), status.getMessage(), e); + } + + if (callback != null) { + if (caller instanceof ICallback) { + Callback.copyProperties((ICallback) caller, callback); + } + callback.done(caller, status); + } + return true; + } + return false; + } + + /** + * Wraps the given progress monitor into a {@link SubProgressMonitor}. If + * the given monitor is <code>null</code>, a {@link NullProgressMonitor} is returned. + * + * @param progress + * The global progress monitor or <code>null</code>. + * @param ticksToUse + * The ticks to use. + * + * @return The progress monitor to use. + */ + public static final IProgressMonitor getProgressMonitor(IProgressMonitor progress, int ticksToUse) { + if (progress != null) { + progress = new SubProgressMonitor(progress, ticksToUse, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + } else { + progress = new NullProgressMonitor(); + } + return progress; + } + + /** + * Start a task. + * + * @param progress + * The progress monitor or <code>null</code>. + * @param name + * The name (label) of the task. + * @param ticks + * The ticks for this task. + */ + public static final void beginTask(IProgressMonitor progress, String name, int ticks) { + if (progress != null) { + progress.beginTask("", ticks); //$NON-NLS-1$ + progress.setTaskName(name); + } + } + + /** + * Set a new task name. + * + * @param progress + * The progress monitor or <code>null</code>. + * @param taskName + * The name (label) of the task. + */ + public static final void setTaskName(IProgressMonitor progress, String taskName) { + if (progress != null) { + progress.setTaskName(taskName); + } + } + + /** + * Set a new sub task name. + * + * @param progress + * The progress monitor or <code>null</code>. + * @param subTask + * The name (label) of the sub task. + */ + public static final void setSubTaskName(IProgressMonitor progress, + String subTaskName) { + if (progress != null) { + progress.subTask(subTaskName); + } + } + + /** + * Add the given amount of worked steps to the progress monitor. + * <p> + * If the given amount of worked steps is less or equal than 0, the method + * will do nothing. + * + * @param progress + * The progress monitor or <code>null</code>. + * @param worked + * The amount of worked steps. + */ + public static final void worked(IProgressMonitor progress, int worked) { + if (progress != null && !progress.isCanceled() && worked > 0) { + progress.worked(worked); + } + } + + /** + * Set the progress monitor done. + * + * @param progress + * The progress monitor or <code>null</code>. + */ + public static final void done(IProgressMonitor progress) { + if (progress != null) { + progress.setTaskName(""); //$NON-NLS-1$ + progress.subTask(""); //$NON-NLS-1$ + progress.done(); + } + } + + /** + * Set the progress monitor canceled. + * + * @param progress + * The progress monitor or <code>null</code>. + */ + public static final void cancel(IProgressMonitor progress) { + if (progress != null && !progress.isCanceled()) { + progress.setCanceled(true); + } + } + + /** + * Get the canceled state of the progress monitor. + * + * @param progress + * The progress monitor or <code>null</code>. + * + * @return <code>True</code> if the progress monitor is not + * <code>null</code> and if the progress monitor is canceled. + */ + public static final boolean isCanceled(IProgressMonitor progress) { + if (progress != null) { + return progress.isCanceled(); + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/StatusHelper.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/StatusHelper.java new file mode 100644 index 000000000..b8aa731f1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/StatusHelper.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 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.runtime.utils; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; + +/** + * Helper implementation to deal with status objects and throwable's. + */ +public final class StatusHelper { + + /** + * Converts a throwable to an IStatus (OK, CANCEL, ERROR). + * + * @param error The throwable or <code>null</code>. + * @return The status. + */ + public static final IStatus getStatus(Throwable error) { + if (error == null) return Status.OK_STATUS; + + int severity = IStatus.ERROR; + if (error instanceof CoreException && ((CoreException)error).getStatus() != null) { + return ((CoreException)error).getStatus(); + } + else if (error instanceof OperationCanceledException) { + severity = IStatus.CANCEL; + } + + String message = error.getLocalizedMessage(); + if (message == null) message = error.getMessage(); + + return new Status(severity, CoreBundleActivator.getUniqueIdentifier(), message != null ? message : error.toString(), error); + } +} |