Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Stieber2013-10-31 05:18:11 -0400
committerUwe Stieber2013-11-02 04:18:45 -0400
commitfe4801d772c40bfe3684f487cc67dc41d601c2ef (patch)
tree7e98d488f759ddfb706a4cfe13029e86e7f661d2 /target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core
parent9e0db973ab4f294e5c99f9171670d1176a9b304b (diff)
downloadorg.eclipse.tcf-fe4801d772c40bfe3684f487cc67dc41d601c2ef.tar.gz
org.eclipse.tcf-fe4801d772c40bfe3684f487cc67dc41d601c2ef.tar.xz
org.eclipse.tcf-fe4801d772c40bfe3684f487cc67dc41d601c2ef.zip
Target Explorer: Rework processes runtime model refresh services/RuntimeModelRefreshService.java
- Fix: Refreshed context properties and children not merged reliable into model - Introduced runtime model refresh service delegates. Allows to refresh target specific properties. - Separate non-UI delegates from UI delegates. Introduced IDelegateService for non-UI delegates.
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/META-INF/MANIFEST.MF1
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/activator/CoreBundleActivator.java35
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/IProcessContextNode.java2
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelRefreshService.java45
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelUpdateService.java30
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/listener/ModelListener.java37
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/nodes/ProcessContextNode.java2
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/RuntimeModel.java6
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelRefreshService.java655
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelUpdateService.java264
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.java2
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.properties2
12 files changed, 393 insertions, 688 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/META-INF/MANIFEST.MF
index 180fede13..18705b77a 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/META-INF/MANIFEST.MF
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/META-INF/MANIFEST.MF
@@ -30,6 +30,7 @@ Export-Package: org.eclipse.tcf.te.tcf.processes.core.activator;x-internal:=true
org.eclipse.tcf.te.tcf.processes.core.model.interfaces,
org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime,
org.eclipse.tcf.te.tcf.processes.core.model.internal.factory;x-internal:=true,
+ org.eclipse.tcf.te.tcf.processes.core.model.listener,
org.eclipse.tcf.te.tcf.processes.core.model.nodes,
org.eclipse.tcf.te.tcf.processes.core.model.properties,
org.eclipse.tcf.te.tcf.processes.core.model.runtime,
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/activator/CoreBundleActivator.java
index ec80202ba..aed90e597 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/activator/CoreBundleActivator.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/activator/CoreBundleActivator.java
@@ -10,7 +10,12 @@
package org.eclipse.tcf.te.tcf.processes.core.activator;
import org.eclipse.core.runtime.Plugin;
+import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.eclipse.tcf.te.tcf.locator.interfaces.IModelListener;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.model.Model;
+import org.eclipse.tcf.te.tcf.processes.core.model.listener.ModelListener;
import org.osgi.framework.BundleContext;
/**
@@ -21,6 +26,8 @@ public class CoreBundleActivator extends Plugin {
private static BundleContext context;
// The trace handler instance
private static volatile TraceHandler traceHandler;
+ // The locator model listener instance
+ /* default */ IModelListener listener;
// The shared instance
private static CoreBundleActivator plugin;
@@ -72,6 +79,20 @@ public class CoreBundleActivator extends Plugin {
public void start(BundleContext bundleContext) throws Exception {
CoreBundleActivator.context = bundleContext;
plugin = this;
+
+ // Create the model listener instance
+ listener = new ModelListener();
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ if (listener == null) return;
+ // Register the model listener with the locator model
+ Model.getModel().addListener(listener);
+ }
+ };
+
+ Protocol.invokeLater(runnable);
}
/* (non-Javadoc)
@@ -81,6 +102,20 @@ public class CoreBundleActivator extends Plugin {
public void stop(BundleContext bundleContext) throws Exception {
CoreBundleActivator.context = null;
plugin = null;
+
+ // Remove the model listener from the locator model
+ if (listener != null) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ ILocatorModel model = Model.getModel(true);
+ if (model != null) model.removeListener(listener);
+ listener = null;
+ }
+ };
+ if (Protocol.isDispatchThread()) runnable.run();
+ else Protocol.invokeAndWait(runnable);
+ }
}
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/IProcessContextNode.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/IProcessContextNode.java
index 13cd5d500..0f4828c4c 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/IProcessContextNode.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/IProcessContextNode.java
@@ -20,7 +20,7 @@ public interface IProcessContextNode extends IContainerModelNode {
/**
* Process context node types
*/
- public enum TYPE { Process, Thread }
+ public enum TYPE { Unknown, Process, Thread }
/**
* Set the type of the context node.
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelRefreshService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelRefreshService.java
index 58966d510..ff12de9f7 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelRefreshService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelRefreshService.java
@@ -9,8 +9,10 @@
*******************************************************************************/
package org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime;
+import org.eclipse.tcf.protocol.IChannel;
import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService;
+import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode;
/**
* Interface to be implemented by processes runtime model refresh services.
@@ -18,6 +20,49 @@ import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshServic
public interface IRuntimeModelRefreshService extends IModelRefreshService {
/**
+ * Interface to be implemented by processes runtime model refresh service delegates.
+ */
+ public static interface IDelegate {
+
+ /**
+ * Called from the processes runtime model refresh service after having queried the
+ * system monitor and the process context objects. Can be used to initialize the node
+ * type.
+ * <p>
+ * This method is invoked before {@link #postRefreshContext(IChannel, IProcessContextNode, ICallback)}.
+ * <p>
+ * <b>Note:</b> The method must be called in the TCF event dispatch thread.
+ *
+ * @param parentContextId The parent context id or <code>null</code> for the root context.
+ * @param node The process context node. Must not be <code>null</code>.
+ */
+ public void setNodeType(String parentContextId, IProcessContextNode node);
+
+ /**
+ * Called from the processes runtime model refresh service after having queried the
+ * system monitor and the process context objects. Can be used to initiate additional
+ * context node specific queries.
+ * <p>
+ * This method is invoked after {@link #setNodeType(IProcessContextNode)}.
+ * <p>
+ * <b>Note:</b> The method must be called in the TCF event dispatch thread.
+ *
+ * @param channel An open channel. Must not be <code>null</code>.
+ * @param node The process context node. Must not be <code>null</code>.
+ * @param callback The callback to invoke once the operation is completed. Must not be <code>null</code>.
+ */
+ public void postRefreshContext(IChannel channel, IProcessContextNode node, ICallback callback);
+
+ /**
+ * Returns the list of property names the delegate may add to a given process
+ * context node while executing {@link #postRefreshContext(IChannel, IProcessContextNode, ICallback)}.
+ *
+ * @return The list of managed property name or <code>null</code>.
+ */
+ public String[] getManagedPropertyNames();
+ }
+
+ /**
* Auto refresh the content of the model from the top. It search for
* all nodes with query state "done" and refresh them one by one.
*
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelUpdateService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelUpdateService.java
new file mode 100644
index 000000000..51ba24c0e
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelUpdateService.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime;
+
+import org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode;
+import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService;
+
+/**
+ * Interface to be implemented by processes runtime model update services.
+ */
+public interface IRuntimeModelUpdateService extends IModelUpdateService {
+
+ /**
+ * Merge the child tree of the given source container with the child tree
+ * of the given destination container.
+ *
+ * @param dst The destination container. Must not be <code>null</code>.
+ * @param src The source container. Must not be <code>null</code>.
+ *
+ * @return <code>True</code> if the destination container changed, <code>false</code> otherwise.
+ */
+ public void updateChildren(IContainerModelNode dst, IContainerModelNode src);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/listener/ModelListener.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/listener/ModelListener.java
new file mode 100644
index 000000000..e5d979468
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/listener/ModelListener.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.te.tcf.processes.core.model.listener;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel;
+import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
+import org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter;
+import org.eclipse.tcf.te.tcf.processes.core.model.ModelManager;
+
+/**
+ * Locator model listener implementation.
+ */
+public class ModelListener extends ModelAdapter {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.locator.listener.ModelAdapter#locatorModelChanged(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel, org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel, boolean)
+ */
+ @Override
+ public void locatorModelChanged(ILocatorModel model, IPeerModel peer, boolean added) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ if (peer == null) return;
+
+ if (!added) {
+ // Dispose possibly associated models
+ ModelManager.disposeRuntimeModel(peer);
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/nodes/ProcessContextNode.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/nodes/ProcessContextNode.java
index 97937c75f..0dc33b65f 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/nodes/ProcessContextNode.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/nodes/ProcessContextNode.java
@@ -40,7 +40,7 @@ public class ProcessContextNode extends ContainerModelNode implements IProcessCo
private ISysMonitor.SysMonitorContext sContext = null;
// The node type
- private TYPE type = TYPE.Process;
+ private TYPE type = TYPE.Unknown;
// Context nodes needs asynchronous refreshes
private final IAsyncRefreshableCtx refreshableCtxAdapter = new AsyncRefreshableCtxAdapter();
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/RuntimeModel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/RuntimeModel.java
index 3d321e24b..bb328915c 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/RuntimeModel.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/RuntimeModel.java
@@ -33,6 +33,7 @@ import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelLookupService;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelRefreshService;
+import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelUpdateService;
import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelChannelService;
import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelLookupService;
import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelRefreshService;
@@ -57,7 +58,7 @@ public final class RuntimeModel extends ContainerModelNode implements IRuntimeMo
// Reference to the lookup service
private final IRuntimeModelLookupService lookupService = new RuntimeModelLookupService(this);
// Reference to the update service
- private final IModelUpdateService updateService = new RuntimeModelUpdateService(this);
+ private final IRuntimeModelUpdateService updateService = new RuntimeModelUpdateService(this);
// Reference to the channel service
private final IModelChannelService channelService = new RuntimeModelChannelService(this);
@@ -144,6 +145,9 @@ public final class RuntimeModel extends ContainerModelNode implements IRuntimeMo
if (IModelLookupService.class.equals(adapter)) {
return lookupService;
}
+ if (IRuntimeModelUpdateService.class.equals(adapter)) {
+ return updateService;
+ }
if (IModelUpdateService.class.equals(adapter)) {
return updateService;
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelRefreshService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelRefreshService.java
deleted file mode 100644
index d61cf2803..000000000
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelRefreshService.java
+++ /dev/null
@@ -1,655 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012, 2013 Wind River Systems, Inc. and others. All rights reserved.
- * This program and the accompanying materials are made available under the terms
- * of the Eclipse Public License v1.0 which accompanies this distribution, and is
- * available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-package org.eclipse.tcf.te.tcf.processes.core.model.runtime.services;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.tcf.protocol.IChannel;
-import org.eclipse.tcf.protocol.IToken;
-import org.eclipse.tcf.protocol.Protocol;
-import org.eclipse.tcf.services.IProcesses;
-import org.eclipse.tcf.services.IProcessesV1;
-import org.eclipse.tcf.services.ISysMonitor;
-import org.eclipse.tcf.services.ISysMonitor.SysMonitorContext;
-import org.eclipse.tcf.te.core.async.AsyncCallbackCollector;
-import org.eclipse.tcf.te.runtime.callback.Callback;
-import org.eclipse.tcf.te.runtime.events.ChangeEvent;
-import org.eclipse.tcf.te.runtime.events.EventManager;
-import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
-import org.eclipse.tcf.te.runtime.model.PendingOperationModelNode;
-import org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode;
-import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
-import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx;
-import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryState;
-import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryType;
-import org.eclipse.tcf.te.tcf.core.async.CallbackInvocationDelegate;
-import org.eclipse.tcf.te.tcf.core.model.interfaces.IModel;
-import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelChannelService;
-import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService;
-import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService;
-import org.eclipse.tcf.te.tcf.core.model.services.AbstractModelService;
-import org.eclipse.tcf.te.tcf.processes.core.activator.CoreBundleActivator;
-import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode;
-import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode.TYPE;
-import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNodeProperties;
-import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel;
-import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelRefreshService;
-import org.eclipse.tcf.te.tcf.processes.core.model.nodes.PendingOperationNode;
-
-/**
- * Runtime model refresh service implementation.
- */
-public class RuntimeModelRefreshService extends AbstractModelService<IRuntimeModel> implements IRuntimeModelRefreshService {
-
- /**
- * Constructor.
- *
- * @param model The parent model. Must not be <code>null</code>.
- */
- public RuntimeModelRefreshService(IRuntimeModel model) {
- super(model);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService#refresh(org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void refresh(ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- refresh(NONE, callback);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService#refresh(int, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void refresh(final int flags, final ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
-
- // Get the parent model
- final IRuntimeModel model = getModel();
-
- // If the parent model is already disposed, the service will drop out immediately
- if (model.isDisposed()) {
- if (callback != null) callback.done(this, Status.OK_STATUS);
- return;
- }
-
- final IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)model.getAdapter(IAsyncRefreshableCtx.class);
- final AtomicBoolean resetPendingNode = new AtomicBoolean(false);
- if (refreshable != null && refreshable.getQueryState(QueryType.CHILD_LIST) != QueryState.IN_PROGRESS) {
- resetPendingNode.set(true);
- // Mark the refresh as in progress
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.IN_PROGRESS);
- // Create a new pending operation node and associate it with the refreshable
- PendingOperationModelNode pendingNode = new PendingOperationNode();
- pendingNode.setParent(model);
- refreshable.setPendingOperationNode(pendingNode);
- // Trigger a refresh of the view content.
- ChangeEvent event = new ChangeEvent(model, IContainerModelNode.NOTIFY_CHANGED, null, null);
- EventManager.getInstance().fireEvent(event);
- }
-
- // Get the list of old children (update node instances where possible)
- final List<IProcessContextNode> oldChildren = model.getChildren(IProcessContextNode.class);
-
- // Refresh the process contexts from the agent
- refreshContextChildren(oldChildren, model, null, 2, new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- final AtomicBoolean isDisposed = new AtomicBoolean();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- isDisposed.set(model.isDisposed());
- }
- };
- if (Protocol.isDispatchThread()) runnable.run();
- else Protocol.invokeAndWait(runnable);
-
- if (!isDisposed.get()) {
- // If there are remaining old children, remove them from the model (non-recursive)
- for (IProcessContextNode oldChild : oldChildren) model.getService(IModelUpdateService.class).remove(oldChild);
- }
-
- if (refreshable != null && resetPendingNode.get()) {
- resetPendingNode.set(false);
- // Mark the refresh as done
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.DONE);
- // Reset the pending operation node
- refreshable.setPendingOperationNode(null);
- // Trigger a refresh of the view content.
- ChangeEvent event = new ChangeEvent(model, IContainerModelNode.NOTIFY_CHANGED, null, null);
- EventManager.getInstance().fireEvent(event);
- }
-
- // Invoke the callback
- if (callback != null) callback.done(this, Status.OK_STATUS);
- }
- });
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService#refresh(org.eclipse.tcf.te.runtime.model.interfaces.IModelNode, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void refresh(IModelNode node, ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- refresh(node, NONE, callback);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService#refresh(org.eclipse.tcf.te.runtime.model.interfaces.IModelNode, int, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void refresh(IModelNode node, int flags, ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
-
- // Get the parent model
- final IRuntimeModel model = getModel();
-
- // If the parent model is already disposed, the service will drop out immediately
- if (model.isDisposed() || !(node instanceof IProcessContextNode)) {
- if (callback != null) callback.done(this, Status.OK_STATUS);
- return;
- }
-
- // Perform the refresh of the node
- doRefresh(model, node, 2, callback);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelRefreshService#autoRefresh(org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
- */
- @Override
- public void autoRefresh(ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
-
- // Get the parent model
- final IRuntimeModel model = getModel();
-
- // If the parent model is already disposed, the service will drop out immediately
- if (model.isDisposed()) {
- if (callback != null) callback.done(this, Status.OK_STATUS);
- return;
- }
-
- // Create the callback collector to fire once all refresh operations are completed
- final AsyncCallbackCollector collector = new AsyncCallbackCollector(callback, new CallbackInvocationDelegate());
-
- // Get the first level of children and check if they are need to be refreshed
- List<IProcessContextNode> children = model.getChildren(IProcessContextNode.class);
- if (children.size() > 0) {
- // Initiate the refresh of the children
- doAutoRefresh(model, children.toArray(new IProcessContextNode[children.size()]), 0, collector);
- }
-
- // Mark the collector initialization done
- collector.initDone();
- }
-
- /**
- * Performs the auto refresh of the given nodes.
- *
- * @param model The runtime model. Must not be <code>null</code>.
- * @param nodes The nodes. Must not be <code>null</code>.
- * @param index The index of the node to refresh within the nodes array. Must be greater or equal than 0 and less than the array length.
- * @param collector The callback collector. Must not be <code>null</code>.
- */
- protected void doAutoRefresh(final IRuntimeModel model, final IProcessContextNode[] nodes, final int index, final AsyncCallbackCollector collector) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(model);
- Assert.isNotNull(nodes);
- Assert.isTrue(index >= 0 && index < nodes.length);
- Assert.isNotNull(collector);
-
- final IProcessContextNode node = nodes[index];
-
- // Get the asynchronous refresh context adapter
- final IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)node.getAdapter(IAsyncRefreshableCtx.class);
- if (refreshable != null) {
- // Schedule a refresh if the node got refreshed before
- if (refreshable.getQueryState(QueryType.CHILD_LIST).equals(QueryState.DONE)) {
- // Create a new callback for the collector to wait for
- final ICallback callback = new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- // We need a reference to the outer callback (== this)
- final ICallback outerCallback = this;
- // Create the inner callback
- final ICallback innerCallback = new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- // More nodes to process?
- int newIndex = index + 1;
- if (newIndex < nodes.length) {
- doAutoRefresh(model, nodes, newIndex, collector);
- }
- // Remove the outer callback from the collector
- collector.removeCallback(outerCallback);
- }
- };
-
- // If the node has children, process them first
- List<IProcessContextNode> children = node.getChildren(IProcessContextNode.class);
- if (children.size() > 0) {
- // Create a new callback collector for processing the children
- final AsyncCallbackCollector childCollector = new AsyncCallbackCollector(innerCallback, new CallbackInvocationDelegate());
- // Initiate the refresh of the children
- doAutoRefresh(model, children.toArray(new IProcessContextNode[children.size()]), 0, childCollector);
- // Mark the collector initialization done
- childCollector.initDone();
- } else {
- // Invoke the inner callback right away
- innerCallback.done(this, Status.OK_STATUS);
- }
- }
- };
- collector.addCallback(callback);
- // Refresh the node (only node and the direct children)
- doRefresh(model, node, 1, callback);
- }
- }
- }
-
- /**
- * Performs the refresh of the given model node.
- *
- * @param model The runtime model. Must not be <code>null</code>.
- * @param node The node. Must not be <code>null</code>.
- * @param depth Until which depth the tree gets refreshed.
- * @param callback The callback to invoke once the refresh operation finished, or <code>null</code>.
- */
- protected void doRefresh(final IRuntimeModel model, final IModelNode node, final int depth, final ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(model);
- Assert.isNotNull(node);
-
- // Refresh the process context from the agent
- refreshContext(model, node, new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- if (status.getSeverity() == IStatus.ERROR) {
- if (callback != null) callback.done(caller, status);
- return;
- }
-
- // Get the list of old children (update node instances where possible)
- final List<IProcessContextNode> oldChildren = ((IProcessContextNode)node).getChildren(IProcessContextNode.class);
-
- // Refresh the children of the process context node from the agent
- refreshContextChildren(oldChildren, model, (IProcessContextNode)node, depth, new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- final AtomicBoolean isDisposed = new AtomicBoolean();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- isDisposed.set(model.isDisposed());
- }
- };
- if (Protocol.isDispatchThread()) runnable.run();
- else Protocol.invokeAndWait(runnable);
-
- if (!isDisposed.get()) {
- // If there are remaining old children, remove them from the parent node (recursive)
- for (IProcessContextNode oldChild : oldChildren) ((IProcessContextNode)node).remove(oldChild, true);
- }
-
- // Invoke the callback
- if (callback != null) callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- });
- }
- });
- }
-
- /**
- * Process the given map of process contexts and update the given model.
- *
- * @param contexts The map of contexts to process. Must not be <code>null</code>.
- * @param oldChildren The list of old children. Must not be <code>null</code>.
- * @param model The model. Must not be <code>null</code>.
- * @param parent The parent context node or <code>null</code>.
- */
- protected void processContexts(Map<UUID, IProcessContextNode> contexts, List<IProcessContextNode> oldChildren, IModel model, IProcessContextNode parent) {
- Assert.isNotNull(contexts);
- Assert.isNotNull(oldChildren);
- Assert.isNotNull(model);
-
- for (Entry<UUID, IProcessContextNode> entry : contexts.entrySet()) {
- // Get the context instance for the current id
- IProcessContextNode candidate = entry.getValue();
- // Try to find an existing context node first
- IModelNode[] nodes = model.getService(IModelLookupService.class).lkupModelNodesById(candidate.getStringProperty(IModelNode.PROPERTY_ID));
- // If found, update the context node properties from the new one
- if (nodes.length > 0) {
- for (IModelNode node : nodes) {
- model.getService(IModelUpdateService.class).update(node, candidate);
- oldChildren.remove(node);
- }
- } else {
- if (parent == null) {
- model.getService(IModelUpdateService.class).add(candidate);
- } else {
- // Validate the the children are added to the real parent node
- nodes = model.getService(IModelLookupService.class).lkupModelNodesById(parent.getStringProperty(IModelNode.PROPERTY_ID));
- if (nodes.length > 0) {
- // In fact we should have found just one parent
- Assert.isTrue(nodes.length == 1);
- Assert.isTrue(nodes[0] instanceof IProcessContextNode);
- // Add to the real parent node
- ((IProcessContextNode)nodes[0]).add(candidate);
- } else {
- // Add to the passed in parent node
- parent.add(candidate);
- }
- }
- }
- }
- }
-
- /**
- * Refresh the given process context node.
- *
- * @param model The runtime model. Must not be <code>null</code>.
- * @param node The node. Must not be <code>null</code>.
- * @param callback The callback to invoke once the refresh operation finished, or <code>null</code>.
- */
- protected void refreshContext(final IRuntimeModel model, final IModelNode node, final ICallback callback) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- Assert.isNotNull(model);
- Assert.isNotNull(node);
-
- // Get an open channel
- IModelChannelService channelService = getModel().getService(IModelChannelService.class);
- channelService.openChannel(new IModelChannelService.DoneOpenChannel() {
- @Override
- public void doneOpenChannel(Throwable error, final IChannel channel) {
- if (error == null) {
- final IProcesses service = channel.getRemoteService(IProcesses.class);
- Assert.isNotNull(service);
- final IProcessesV1 serviceV1 = channel.getRemoteService(IProcessesV1.class);
- final ISysMonitor sysMonService = channel.getRemoteService(ISysMonitor.class);
- Assert.isNotNull(sysMonService);
- final String contextId = ((IProcessContextNode)node).getStringProperty(IModelNode.PROPERTY_ID);
- sysMonService.getContext(contextId, new ISysMonitor.DoneGetContext() {
- @Override
- public void doneGetContext(IToken token, Exception error, SysMonitorContext context) {
- ((IProcessContextNode)node).setSysMonitorContext(context);
-
- // Get the command line of the context
- sysMonService.getCommandLine(contextId, new ISysMonitor.DoneGetCommandLine() {
- @Override
- public void doneGetCommandLine(IToken token, Exception error, String[] cmd_line) {
- node.setProperty(IProcessContextNodeProperties.PROPERTY_CMD_LINE, error == null ? cmd_line : null);
-
- // Get the process context
- service.getContext(contextId, new IProcesses.DoneGetContext() {
- @Override
- public void doneGetContext(IToken token, Exception error, IProcesses.ProcessContext context) {
- ((IProcessContextNode)node).setProcessContext(context);
- if (serviceV1 != null && context != null) {
- serviceV1.getCapabilities(context.getID(), new IProcessesV1.DoneGetCapabilities() {
- @Override
- public void doneGetCapabilities(IToken token, Exception error, Map<String, Object> properties) {
- ((IProcessContextNode)node).setProperty(IProcessContextNodeProperties.PROPERTY_CAPABILITIES, properties);
-
- callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- });
- }
- else
- callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- });
- }
- });
- }
- });
- } else {
- callback.done(RuntimeModelRefreshService.this, new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), error.getLocalizedMessage(), error));
- }
- }
- });
- }
-
- /**
- * Refresh the children of the given process context node.
- *
- * @param oldChildren The list of old children. Must not be <code>null</code>.
- * @param model The model. Must not be <code>null</code>.
- * @param parent The parent context node or <code>null</code>.
- * @param depth Until which depth the tree gets refreshed.
- * @param callback The callback to invoke at the end of the operation. Must not be <code>null</code>.
- */
- protected void refreshContextChildren(final List<IProcessContextNode> oldChildren, final IModel model, final IProcessContextNode parent, final int depth, final ICallback callback) {
- Assert.isNotNull(oldChildren);
- Assert.isNotNull(model);
- Assert.isNotNull(callback);
-
- // Make sure that the callback is invoked even for unexpected cases
- try {
- // The map of contexts created from the agents response
- final Map<UUID, IProcessContextNode> contexts = new HashMap<UUID, IProcessContextNode>();
-
- // Get an open channel
- IModelChannelService channelService = getModel().getService(IModelChannelService.class);
- channelService.openChannel(new IModelChannelService.DoneOpenChannel() {
- @Override
- public void doneOpenChannel(Throwable error, final IChannel channel) {
- if (error == null) {
- // Determine the parent context id
- String parentContextId = null;
- if (parent != null) parentContextId = parent.getStringProperty(IModelNode.PROPERTY_ID);
-
- // Get the required services
- final IProcesses service = channel.getRemoteService(IProcesses.class);
- final IProcessesV1 serviceV1 = channel.getRemoteService(IProcessesV1.class);
- final ISysMonitor sysMonService = channel.getRemoteService(ISysMonitor.class);
-
- // At least the processes and the system monitor service must be available
- if (service == null || sysMonService == null) {
- callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- return;
- }
-
- sysMonService.getChildren(parentContextId, new ISysMonitor.DoneGetChildren() {
- @Override
- public void doneGetChildren(IToken token, Exception error, String[] context_ids) {
- if (error == null) {
- if (context_ids != null && context_ids.length > 0) {
- final AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
- if (status.getSeverity() == IStatus.OK) {
- // Process the read process contexts
- if (!contexts.isEmpty()) processContexts(contexts, oldChildren, model, parent);
- callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- } else {
- callback.done(RuntimeModelRefreshService.this, new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), status.getMessage(), status.getException()));
- }
- }
- }, new CallbackInvocationDelegate());
-
- // Loop the returned context id's and query the context data
- for (String id : context_ids) {
- final String contextId = id;
- final ICallback innerCallback = new AsyncCallbackCollector.SimpleCollectorCallback(collector);
- sysMonService.getContext(contextId, new ISysMonitor.DoneGetContext() {
- @Override
- public void doneGetContext(IToken token, Exception error, SysMonitorContext context) {
- // Ignore errors. Some of the context might be OS context we do not have
- // permissions to read the properties from.
- if (context != null) {
- final IProcessContextNode node = createContextNodeFrom(context);
- Assert.isNotNull(node);
- node.setType(parent == null ? TYPE.Process : TYPE.Thread);
- contexts.put(node.getUUID(), node);
-
- // Get the command line of the context
- sysMonService.getCommandLine(contextId, new ISysMonitor.DoneGetCommandLine() {
- @Override
- public void doneGetCommandLine(IToken token, Exception error, String[] cmd_line) {
- node.setProperty(IProcessContextNodeProperties.PROPERTY_CMD_LINE, error == null ? cmd_line : null);
-
- // Query the corresponding process context
- service.getContext(contextId, new IProcesses.DoneGetContext() {
- @Override
- public void doneGetContext(IToken token, Exception error, IProcesses.ProcessContext context) {
- // Errors are ignored
- node.setProcessContext(context);
-
- if (context != null) node.setProperty(IProcessContextNodeProperties.PROPERTY_NAME, context.getName());
-
- if (serviceV1 != null && context != null) {
- serviceV1.getCapabilities(context.getID(), new IProcessesV1.DoneGetCapabilities() {
- @Override
- public void doneGetCapabilities(IToken token, Exception error, Map<String, Object> properties) {
- node.setProperty(IProcessContextNodeProperties.PROPERTY_CAPABILITIES, properties);
- // Get the asynchronous refresh context adapter
- final IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)node.getAdapter(IAsyncRefreshableCtx.class);
-
- // Refresh the children of the node if the depth is still larger than 0
- if (depth - 1 > 0 && (refreshable == null || !refreshable.getQueryState(QueryType.CHILD_LIST).equals(QueryState.IN_PROGRESS))) {
- if (refreshable != null) {
- // Mark the refresh as in progress
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.IN_PROGRESS);
- // Create a new pending operation node and associate it with the refreshable
- PendingOperationModelNode pendingNode = new PendingOperationNode();
- pendingNode.setParent(node);
- refreshable.setPendingOperationNode(pendingNode);
- }
-
- // Don't send change events while refreshing
- final boolean changed = node.setChangeEventsEnabled(false);
- // Initiate the refresh
- List<IProcessContextNode> oldChildren = node.getChildren(IProcessContextNode.class);
- refreshContextChildren(oldChildren, model, node, depth - 1, new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- // Mark the refresh as done
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.DONE);
- // Reset the pending operation node
- refreshable.setPendingOperationNode(null);
- // Re-enable the change events if they had been enabled before
- if (changed) node.setChangeEventsEnabled(true);
- // Trigger a refresh of the view content
- ChangeEvent event = new ChangeEvent(node, IContainerModelNode.NOTIFY_CHANGED, null, null);
- EventManager.getInstance().fireEvent(event);
- // Finally invoke the callback
- innerCallback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- });
- } else {
- innerCallback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- }
- });
- }
- else {
- // Get the asynchronous refresh context adapter
- final IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)node.getAdapter(IAsyncRefreshableCtx.class);
-
- // Refresh the children of the node if the depth is still larger than 0
- if (depth - 1 > 0 && (refreshable == null || !refreshable.getQueryState(QueryType.CHILD_LIST).equals(QueryState.IN_PROGRESS))) {
- if (refreshable != null) {
- // Mark the refresh as in progress
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.IN_PROGRESS);
- // Create a new pending operation node and associate it with the refreshable
- PendingOperationModelNode pendingNode = new PendingOperationNode();
- pendingNode.setParent(node);
- refreshable.setPendingOperationNode(pendingNode);
- }
-
- // Don't send change events while refreshing
- final boolean changed = node.setChangeEventsEnabled(false);
- // Initiate the refresh
- List<IProcessContextNode> oldChildren = node.getChildren(IProcessContextNode.class);
- refreshContextChildren(oldChildren, model, node, depth - 1, new Callback() {
- @Override
- protected void internalDone(Object caller, IStatus status) {
- // Mark the refresh as done
- refreshable.setQueryState(QueryType.CHILD_LIST, QueryState.DONE);
- // Reset the pending operation node
- refreshable.setPendingOperationNode(null);
- // Re-enable the change events if they had been enabled before
- if (changed) node.setChangeEventsEnabled(true);
- // Trigger a refresh of the view content
- ChangeEvent event = new ChangeEvent(node, IContainerModelNode.NOTIFY_CHANGED, null, null);
- EventManager.getInstance().fireEvent(event);
- // Finally invoke the callback
- innerCallback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- });
- } else {
- innerCallback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
-
- }
- }
- });
- }
- });
- } else {
- innerCallback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- }
- });
- }
-
- collector.initDone();
- } else {
- callback.done(RuntimeModelRefreshService.this, Status.OK_STATUS);
- }
- } else {
- callback.done(RuntimeModelRefreshService.this, new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), error.getLocalizedMessage(), error));
- }
- }
- });
- } else {
- callback.done(RuntimeModelRefreshService.this, new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), error.getLocalizedMessage(), error));
- }
-
- }
- });
- } catch (Throwable e) {
- callback.done(RuntimeModelRefreshService.this, new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getLocalizedMessage(), e));
- }
- }
-
- /**
- * Create a context node instance from the given process context.
- *
- * @param context The system monitor context. Must not be <code>null</code>.
- * @return The context node instance.
- */
- public IProcessContextNode createContextNodeFrom(SysMonitorContext context) {
- Assert.isNotNull(context);
-
- // Create a context node and associate the given context
- IProcessContextNode node = getModel().getFactory().newInstance(IProcessContextNode.class);
- node.setSysMonitorContext(context);
-
- // Re-create the context properties from the context
- node.setProperty(IProcessContextNodeProperties.PROPERTY_ID, context.getID());
-
- return node;
- }
-}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelUpdateService.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelUpdateService.java
index ed28c16d2..2db351e91 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelUpdateService.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelUpdateService.java
@@ -9,22 +9,32 @@
*******************************************************************************/
package org.eclipse.tcf.te.tcf.processes.core.model.runtime.services;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IProcesses;
+import org.eclipse.tcf.services.ISysMonitor;
import org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode;
import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryState;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryType;
-import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService;
+import org.eclipse.tcf.te.runtime.services.ServiceManager;
+import org.eclipse.tcf.te.runtime.services.interfaces.IDelegateService;
import org.eclipse.tcf.te.tcf.core.model.services.AbstractModelService;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNodeProperties;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel;
+import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelRefreshService;
+import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelUpdateService;
/**
* Runtime model update service implementation.
*/
-public class RuntimeModelUpdateService extends AbstractModelService<IRuntimeModel> implements IModelUpdateService {
+public class RuntimeModelUpdateService extends AbstractModelService<IRuntimeModel> implements IRuntimeModelUpdateService {
/**
* Constructor.
@@ -40,6 +50,7 @@ public class RuntimeModelUpdateService extends AbstractModelService<IRuntimeMode
*/
@Override
public void add(IModelNode node) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
Assert.isNotNull(node);
getModel().add(node);
}
@@ -49,62 +60,255 @@ public class RuntimeModelUpdateService extends AbstractModelService<IRuntimeMode
*/
@Override
public void remove(IModelNode node) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
Assert.isNotNull(node);
Assert.isNotNull(node.getParent());
node.getParent().remove(node, false);
}
/* (non-Javadoc)
- * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService#update(org.eclipse.tcf.te.runtime.model.interfaces.IModelNode, org.eclipse.tcf.te.runtime.model.interfaces.IModelNode)
+ * @see org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelUpdateService#updateChildren(org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode, org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode)
*/
@Override
- public void update(IModelNode dst, IModelNode src) {
+ public void updateChildren(IContainerModelNode dst, IContainerModelNode src) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
Assert.isNotNull(dst);
Assert.isNotNull(src);
- boolean eventEnablementChanged = dst.setChangeEventsEnabled(false);
- boolean dstNodeChanged = false;
+ boolean dstNodeChanged = __updateChildren(dst, src);
- for (String key : src.getProperties().keySet()) {
- dstNodeChanged |= dst.setProperty(key, src.getProperty(key));
+ // Fire a properties changed event if the destination node changed
+ if (dstNodeChanged) {
+ dst.fireChangeEvent(IContainerModelNode.NOTIFY_CHANGED, null, dst.getProperties());
}
+ }
+
+ /**
+ * Lookup a node with the given id in the given list.
+ *
+ * @param id The node id. Must not be <code>null</code>.
+ * @param list The list. Must not be <code>null</code>.
+ *
+ * @return The matching process context node or <code>null</code> if not found.
+ */
+ /* default */ IProcessContextNode findInList(String id, List<IProcessContextNode> list) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(id);
+ Assert.isNotNull(list);
+
+ IProcessContextNode node = null;
+
+ for (IProcessContextNode candidate : list) {
+ if (id.equals(candidate.getStringProperty(IProcessContextNodeProperties.PROPERTY_ID))) {
+ node = candidate;
+ break;
+ }
+ }
+
+ return node;
+ }
+
+ /**
+ * Update the child tree of the destination container from the given source container.
+ *
+ * @param dst The destination container. Must not be <code>null</code>.
+ * @param src The source container. Must not be <code>null</code>.
+ *
+ * @return <code>True</code> if the destination container changed, <code>false</code> otherwise.
+ */
+ /* default */ boolean __updateChildren(IContainerModelNode dst, IContainerModelNode src) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(dst);
+ Assert.isNotNull(src);
+
+ boolean dstNodeChanged = false;
+ // Get the asynchronous refreshable contexts of the nodes
IAsyncRefreshableCtx dstRefreshable = (IAsyncRefreshableCtx)dst.getAdapter(IAsyncRefreshableCtx.class);
+ Assert.isNotNull(dstRefreshable);
IAsyncRefreshableCtx srcRefreshable = (IAsyncRefreshableCtx)src.getAdapter(IAsyncRefreshableCtx.class);
- if (dstRefreshable != null && srcRefreshable != null) {
- if (srcRefreshable.getQueryState(QueryType.CONTEXT) == QueryState.IN_PROGRESS || srcRefreshable.getQueryState(QueryType.CHILD_LIST) == QueryState.IN_PROGRESS) {
- dstRefreshable.setPendingOperationNode(srcRefreshable.getPendingOperationNode());
- }
- Assert.isTrue(srcRefreshable.getQueryState(QueryType.CONTEXT) != QueryState.IN_PROGRESS, "Context query of node '" + src.getName() + "' in progress while updating model."); //$NON-NLS-1$ //$NON-NLS-2$
- if (srcRefreshable.getQueryState(QueryType.CONTEXT) == QueryState.DONE) {
- dstRefreshable.setQueryState(QueryType.CONTEXT, srcRefreshable.getQueryState(QueryType.CONTEXT));
- }
- Assert.isTrue(srcRefreshable.getQueryState(QueryType.CHILD_LIST) != QueryState.IN_PROGRESS, "Child list query of node '" + src.getName() + "' in progress while updating model."); //$NON-NLS-1$ //$NON-NLS-2$
- if (srcRefreshable.getQueryState(QueryType.CHILD_LIST) == QueryState.DONE) {
- dstRefreshable.setQueryState(QueryType.CHILD_LIST, srcRefreshable.getQueryState(QueryType.CHILD_LIST));
- if (dst instanceof IContainerModelNode) {
- ((IContainerModelNode)dst).clear();
- if (src instanceof IContainerModelNode) {
- for (IModelNode child : ((IContainerModelNode)src).getChildren()) {
- ((IContainerModelNode)dst).add(child);
- }
+ Assert.isNotNull(srcRefreshable);
+
+ // Synchronize the refreshable states
+ Assert.isTrue(srcRefreshable.getQueryState(QueryType.CONTEXT) != QueryState.IN_PROGRESS, "Context query of node '" + src.getName() + "' in progress while updating model."); //$NON-NLS-1$ //$NON-NLS-2$
+ if (srcRefreshable.getQueryState(QueryType.CONTEXT) == QueryState.DONE && dstRefreshable.getQueryState(QueryType.CONTEXT) != QueryState.DONE) {
+ dstRefreshable.setQueryState(QueryType.CONTEXT, QueryState.DONE);
+ dstNodeChanged |= true;
+ }
+ Assert.isTrue(srcRefreshable.getQueryState(QueryType.CHILD_LIST) != QueryState.IN_PROGRESS, "Child list query of node '" + src.getName() + "' in progress while updating model."); //$NON-NLS-1$ //$NON-NLS-2$
+ if (srcRefreshable.getQueryState(QueryType.CHILD_LIST) == QueryState.DONE && dstRefreshable.getQueryState(QueryType.CHILD_LIST) != QueryState.DONE) {
+ dstRefreshable.setQueryState(QueryType.CHILD_LIST, QueryState.DONE);
+ dstNodeChanged |= true;
+ }
+
+ // If the refreshable state of the source container is PENDING, than we are done here
+ if (srcRefreshable.getQueryState(QueryType.CHILD_LIST) == QueryState.PENDING) {
+ return dstNodeChanged;
+ }
+
+ // Get the list of old children (update node instances where possible)
+ final List<IProcessContextNode> oldChildren = dst.getChildren(IProcessContextNode.class);
+
+ // Disable notifications while updating the child list
+ boolean eventEnablementChanged = dst.setChangeEventsEnabled(false);
+
+ // Get the list of new children
+ final List<IProcessContextNode> newChildren = src.getChildren(IProcessContextNode.class);
+
+ // Loop the list of new children and lookup a matching node in the list of old children
+ for (IProcessContextNode candidate : newChildren) {
+ String id = candidate.getStringProperty(IProcessContextNodeProperties.PROPERTY_ID);
+ if (id == null) continue;
+ // Find the old process context node
+ IProcessContextNode oldNode = findInList(id, oldChildren);
+ if (oldNode != null) {
+ // Remove the old node from the old children list
+ oldChildren.remove(oldNode);
+ // Update the properties of the old node from the new node
+ dstNodeChanged |= __updateProperties(oldNode, candidate);
+ // If the child list of the new node is valid, update the child list
+ IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)candidate.getAdapter(IAsyncRefreshableCtx.class);
+ Assert.isNotNull(refreshable);
+ if (refreshable.getQueryState(QueryType.CONTEXT) == QueryState.DONE) {
+ // Update the child tree of the old node from the new node
+ dstNodeChanged |= __updateChildren(oldNode, candidate);
+ }
+ } else {
+ if (candidate.getParent() == null) {
+ // Parent not set -> Add the new child node
+ dstNodeChanged |= dst.add(candidate);
+ } else {
+ // Parent set -> Create a copy of the new node
+ IProcessContextNode copy = getModel().getFactory().newInstance(IProcessContextNode.class);
+ __updateProperties(copy, candidate);
+ IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)candidate.getAdapter(IAsyncRefreshableCtx.class);
+ Assert.isNotNull(refreshable);
+ if (refreshable.getQueryState(QueryType.CONTEXT) == QueryState.DONE) {
+ __updateChildren(copy, candidate);
}
+ // Add the copy of the new node
+ dstNodeChanged |= dst.add(copy);
}
}
}
- if (dst instanceof IProcessContextNode && src instanceof IProcessContextNode) {
- ((IProcessContextNode)dst).setSysMonitorContext(((IProcessContextNode)src).getSysMonitorContext());
- ((IProcessContextNode)dst).setProcessContext(((IProcessContextNode)src).getProcessContext());
- dst.setProperty(IProcessContextNodeProperties.PROPERTY_CMD_LINE, src.getProperty(IProcessContextNodeProperties.PROPERTY_CMD_LINE));
+ // If there are remaining old children, remove them (non-recursive)
+ for (IProcessContextNode oldChild : oldChildren) {
+ dstNodeChanged |= dst.remove(oldChild, false);
+ }
+
+ // Re-enable the change events
+ if (eventEnablementChanged) dst.setChangeEventsEnabled(true);
+
+ return dstNodeChanged;
+ }
+
+ /**
+ * Update the destination node properties from the given source node.
+ * <p>
+ * <b>Note:</b> This method does not update the child tree. Use {@link #updateChildren(IContainerModelNode, IContainerModelNode)}
+ * for updating the child tree.
+ *
+ * @param dst The destination node. Must not be <code>null</code>.
+ * @param src The source node. Must not be <code>null</code>.
+ *
+ * @return <code>True</code> if the properties of the destination node changed, <code>false</code> otherwise.
+ */
+ /* default */ boolean __updateProperties(IProcessContextNode dst, IProcessContextNode src) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(dst);
+ Assert.isNotNull(src);
+
+ boolean eventEnablementChanged = dst.setChangeEventsEnabled(false);
+ boolean dstNodeChanged = false;
+
+ // Update the properties of the destination node from the source node
+ for (String key : src.getProperties().keySet()) {
+ dstNodeChanged |= dst.setProperty(key, src.getProperty(key));
+ }
+
+ // Make sure that old properties are removed from the destination node.
+ // Collect the list of property names to check for removal
+ List<String> managedPropertyNames = new ArrayList<String>();
+ managedPropertyNames.add(IProcessContextNodeProperties.PROPERTY_ID);
+ managedPropertyNames.add(IProcessContextNodeProperties.PROPERTY_NAME);
+
+ // Determine if a delegate is registered
+ IDelegateService service = ServiceManager.getInstance().getService(dst, IDelegateService.class, false);
+ IRuntimeModelRefreshService.IDelegate delegate = service != null ? service.getDelegate(dst, IRuntimeModelRefreshService.IDelegate.class) : null;
+
+ if (delegate == null && getModel().getService(IRuntimeModelRefreshService.class) instanceof RuntimeModelRefreshService) {
+ delegate = ((RuntimeModelRefreshService)getModel().getService(IRuntimeModelRefreshService.class)).defaultDelegate;
+ }
+ if (delegate != null) {
+ String[] candidates = delegate.getManagedPropertyNames();
+ if (candidates != null) managedPropertyNames.addAll(Arrays.asList(candidates));
+ }
+
+ // Clean up the destination node
+ for (String managedPropertyName : managedPropertyNames) {
+ if (src.isProperty(managedPropertyName, null)) {
+ dstNodeChanged |= dst.setProperty(managedPropertyName, null);
+ }
+ }
+
+ // Update the system monitor context object (if necessary)
+ ISysMonitor.SysMonitorContext s1 = dst.getSysMonitorContext();
+ ISysMonitor.SysMonitorContext s2 = src.getSysMonitorContext();
+ if ((s1 == null && s2 != null) || (s1 != null && s2 == null) || !s1.equals(s2)) {
+ dst.setSysMonitorContext(src.getSysMonitorContext());
+ dstNodeChanged |= true;
+ }
+
+ // Update the process context object (if necessary)
+ IProcesses.ProcessContext p1 = dst.getProcessContext();
+ IProcesses.ProcessContext p2 = src.getProcessContext();
+ if ((p1 == null && p2 != null) || (p1 != null && p2 == null) || !p1.equals(p2)) {
+ dst.setProcessContext(src.getProcessContext());
+ dstNodeChanged |= true;
+ }
+
+ // Update the node type (if necessary)
+ if (dst.getType() != src.getType()) {
+ dst.setType(src.getType());
+ dstNodeChanged |= true;
}
// Re-enable the change events
if (eventEnablementChanged) dst.setChangeEventsEnabled(true);
+ return dstNodeChanged;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService#update(org.eclipse.tcf.te.runtime.model.interfaces.IModelNode, org.eclipse.tcf.te.runtime.model.interfaces.IModelNode)
+ */
+ @Override
+ public void update(IModelNode dst, IModelNode src) {
+ Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$
+ Assert.isNotNull(dst);
+ Assert.isNotNull(src);
+
+ // The nodes to update must be process context nodes
+ if (!(dst instanceof IProcessContextNode) || !(src instanceof IProcessContextNode)) {
+ return;
+ }
+
+ // Update the nodes only if the id's are matching
+ String dstContextId = dst.getStringProperty(IProcessContextNodeProperties.PROPERTY_ID);
+ String srcContextId = src.getStringProperty(IProcessContextNodeProperties.PROPERTY_ID);
+ if ((dstContextId == null && srcContextId != null) || (dstContextId != null && srcContextId == null) || !dstContextId.equals(srcContextId)) {
+ return;
+ }
+
+ boolean dstNodeChanged = __updateProperties((IProcessContextNode)dst, (IProcessContextNode)src);
+ if (dst instanceof IContainerModelNode && src instanceof IContainerModelNode) {
+ dstNodeChanged |= __updateChildren((IContainerModelNode)dst, (IContainerModelNode)src);
+ }
+
// Fire a properties changed event if the destination node changed
if (dstNodeChanged) {
- dst.fireChangeEvent("properties", null, dst.getProperties()); //$NON-NLS-1$
+ dst.fireChangeEvent(IContainerModelNode.NOTIFY_CHANGED, null, null);
}
}
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.java
index 231162619..84040c5c9 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.java
@@ -69,4 +69,6 @@ public class Messages extends NLS {
public static String TerminateStep_error_terminate;
public static String TerminateStep_error_getContext;
public static String TerminateStep_error_openChannel;
+
+ public static String RuntimeModelRefreshService_error_channelClosed;
}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.properties
index dd06d09dc..bbbec851f 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.properties
+++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/nls/Messages.properties
@@ -48,3 +48,5 @@ TerminateStep_error_title=Error
TerminateStep_error_terminate=Failed to terminate context: {0}
TerminateStep_error_getContext=Failed to get context: {0}
TerminateStep_error_openChannel=Failed to open channel: {0}
+
+RuntimeModelRefreshService_error_channelClosed=Refresh failed. Channel is closed.

Back to the top