From fe4801d772c40bfe3684f487cc67dc41d601c2ef Mon Sep 17 00:00:00 2001 From: Uwe Stieber Date: Thu, 31 Oct 2013 10:18:11 +0100 Subject: 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. --- .../META-INF/MANIFEST.MF | 1 + .../core/activator/CoreBundleActivator.java | 35 ++ .../core/model/interfaces/IProcessContextNode.java | 2 +- .../runtime/IRuntimeModelRefreshService.java | 45 ++ .../runtime/IRuntimeModelUpdateService.java | 30 + .../core/model/listener/ModelListener.java | 37 ++ .../core/model/nodes/ProcessContextNode.java | 2 +- .../processes/core/model/runtime/RuntimeModel.java | 6 +- .../services/RuntimeModelRefreshService.java | 655 --------------------- .../services/RuntimeModelUpdateService.java | 264 ++++++++- .../tcf/te/tcf/processes/core/nls/Messages.java | 2 + .../te/tcf/processes/core/nls/Messages.properties | 2 + 12 files changed, 393 insertions(+), 688 deletions(-) create mode 100644 target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/interfaces/runtime/IRuntimeModelUpdateService.java create mode 100644 target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/listener/ModelListener.java delete mode 100644 target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/runtime/services/RuntimeModelRefreshService.java (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core') 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,14 +9,59 @@ *******************************************************************************/ 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. */ 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. + *
+ * This method is invoked before {@link #postRefreshContext(IChannel, IProcessContextNode, ICallback)}. + *
+ * Note: The method must be called in the TCF event dispatch thread.
+ *
+ * @param parentContextId The parent context id or null
for the root context.
+ * @param node The process context node. Must not be null
.
+ */
+ 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.
+ *
+ * This method is invoked after {@link #setNodeType(IProcessContextNode)}. + *
+ * Note: The method must be called in the TCF event dispatch thread.
+ *
+ * @param channel An open channel. Must not be
+ * Note: 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 null
.
+ * @param node The process context node. Must not be null
.
+ * @param callback The callback to invoke once the operation is completed. Must not be null
.
+ */
+ 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 null
.
+ */
+ 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 null
.
+ * @param src The source container. Must not be null
.
+ *
+ * @return True
if the destination container changed, false
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 AbstractModelServicenull
.
- */
- 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 Listnull
.
- * @param nodes The nodes. Must not be null
.
- * @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 null
.
- */
- 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
- Listnull
.
- * @param node The node. Must not be null
.
- * @param depth Until which depth the tree gets refreshed.
- * @param callback The callback to invoke once the refresh operation finished, or null
.
- */
- 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 Listnull
.
- * @param oldChildren The list of old children. Must not be null
.
- * @param model The model. Must not be null
.
- * @param parent The parent context node or null
.
- */
- protected void processContexts(Mapnull
.
- * @param node The node. Must not be null
.
- * @param callback The callback to invoke once the refresh operation finished, or null
.
- */
- 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, Mapnull
.
- * @param model The model. Must not be null
.
- * @param parent The parent context node or null
.
- * @param depth Until which depth the tree gets refreshed.
- * @param callback The callback to invoke at the end of the operation. Must not be null
.
- */
- protected void refreshContextChildren(final Listnull
.
- * @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 AbstractModelServicenull
.
+ *
+ * @return The matching process context node or null
if not found.
+ */
+ /* default */ IProcessContextNode findInList(String id, Listnull
.
+ * @param src The source container. Must not be null
.
+ *
+ * @return True
if the destination container changed, false
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 Listnull
.
+ * @param src The source node. Must not be null
.
+ *
+ * @return True
if the properties of the destination node changed, false
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