diff options
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core')
3 files changed, 134 insertions, 90 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/steps/AttachStep.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/steps/AttachStep.java index 57b334213..a803f87a9 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/steps/AttachStep.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.processes.core/src/org/eclipse/tcf/te/tcf/processes/core/model/steps/AttachStep.java @@ -9,6 +9,10 @@ *******************************************************************************/ package org.eclipse.tcf.te.tcf.processes.core.model.steps; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -18,6 +22,7 @@ import org.eclipse.tcf.protocol.IToken; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.services.IProcesses; import org.eclipse.tcf.services.IProcesses.ProcessContext; +import org.eclipse.tcf.te.core.async.AsyncCallbackCollector; import org.eclipse.tcf.te.runtime.callback.Callback; import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; @@ -29,6 +34,7 @@ import org.eclipse.tcf.te.runtime.statushandler.StatusHandlerManager; import org.eclipse.tcf.te.runtime.statushandler.interfaces.IStatusHandler; import org.eclipse.tcf.te.runtime.statushandler.interfaces.IStatusHandlerConstants; import org.eclipse.tcf.te.tcf.core.Tcf; +import org.eclipse.tcf.te.tcf.core.async.CallbackInvocationDelegate; import org.eclipse.tcf.te.tcf.core.interfaces.IChannelManager; import org.eclipse.tcf.te.tcf.core.model.interfaces.IModel; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService; @@ -44,111 +50,143 @@ import org.eclipse.tcf.te.tcf.processes.core.nls.Messages; public class AttachStep { /** - * Attach to the given process context. + * Attach to the given list of process context nodes of the given peer model node. * <p> * <b>Note:</b> This method must be called from within the TCF dispatch thread. * - * @param node The context. Must not be <code>null</code>. + * @param peerModel The peer model. Must not be <code>null</code>. + * @param nodes The list of process context nodes. Must not be <code>null</code>. * @param callback The callback to invoke once the operation completed, or<code>null</code>. */ - public void executeAttach(final IProcessContextNode node, final ICallback callback) { + public void executeAttach(final IPeerModel peerModel, final IProcessContextNode[] nodes, final ICallback callback) { Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ - Assert.isNotNull(node); - - // If the context is already attached, there is nothing to do - if (node.getProcessContext() != null && !node.getProcessContext().isAttached()) { - IPeerModel peerNode = (IPeerModel)node.getAdapter(IPeerModel.class); - if (peerNode != null) { - // Determine the debug service to attach to the peer node - IDebugService dbgService = ServiceManager.getInstance().getService(peerNode, IDebugService.class, false); - if (dbgService != null) { - // Attach to the peer node first - dbgService.attach(peerNode, new PropertiesContainer(), null, new Callback() { - @Override - protected void internalDone(Object caller, IStatus status) { - callback.setProperty("launch", getProperty("launch")); //$NON-NLS-1$ //$NON-NLS-2$ - Runnable runnable = new Runnable() { - @Override - public void run() { - doAttach(node, callback); - } - }; - if (Protocol.isDispatchThread()) runnable.run(); - else Protocol.invokeLater(runnable); - } - }); - } else { - doAttach(node, callback); - } - } else { - onError(node, Messages.AttachStep_error_connect, null, callback); + Assert.isNotNull(peerModel); + Assert.isNotNull(nodes); + + // Determine if we have to execute the attach at all + final List<IProcessContextNode> nodesToAttach = new ArrayList<IProcessContextNode>(); + for (IProcessContextNode node : nodes) { + IPeerModel parentPeerModel = (IPeerModel)node.getAdapter(IPeerModel.class); + if (!peerModel.equals(parentPeerModel)) continue; + + // If not yet attached, we have to attach to it + if (node.getProcessContext() != null && !node.getProcessContext().isAttached()) { + if (!nodesToAttach.contains(node)) nodesToAttach.add(node); } - } else { - if (node.getProcessContext() == null) { - onError(node, Messages.AttachStep_error_connect, null, callback); + } + + // Anything to attach? + if (!nodesToAttach.isEmpty()) { + // Determine the debug service to attach to the peer node + IDebugService dbgService = ServiceManager.getInstance().getService(peerModel, IDebugService.class, false); + if (dbgService != null) { + // Attach to the peer node first + dbgService.attach(peerModel, new PropertiesContainer(), null, new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + callback.setProperty("launch", getProperty("launch")); //$NON-NLS-1$ //$NON-NLS-2$ + Runnable runnable = new Runnable() { + @Override + public void run() { + doAttach(peerModel, Collections.unmodifiableList(nodesToAttach), callback); + } + }; + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }); } else { - onDone(callback); + doAttach(peerModel, Collections.unmodifiableList(nodesToAttach), callback); } + } else { + onDone(callback); } + } /** - * Opens a channel and perform the attach to the given context node. + * Opens a channel and perform the attach to the given process context nodes. * <p> * <b>Note:</b> This method must be called from within the TCF dispatch thread. * - * @param node The context node. Must not be <code>null</code>. + * @param peerModel The peer model. Must not be <code>null</code>. + * @param nodes The process context node. Must not be <code>null</code>. * @param callback The callback to invoke once the operation completed, or<code>null</code>. */ - protected void doAttach(final IProcessContextNode node, final ICallback callback) { + protected void doAttach(final IPeerModel peerModel, final List<IProcessContextNode> nodes, final ICallback callback) { Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ - Assert.isNotNull(node); - - // Determine the peer model node - final IPeerModel peerNode = (IPeerModel)node.getAdapter(IPeerModel.class); - - // Open a channel - Tcf.getChannelManager().openChannel(peerNode.getPeer(), null, new IChannelManager.DoneOpenChannel() { - @Override - public void doneOpenChannel(final Throwable error, final IChannel channel) { - if (error == null) { - final IProcesses service = channel.getRemoteService(IProcesses.class); - if (service != null) { - service.getContext(node.getStringProperty(IModelNode.PROPERTY_ID), new IProcesses.DoneGetContext() { - @Override - public void doneGetContext(IToken token, Exception error, ProcessContext context) { - if (error == null && context != null) { - context.attach(new IProcesses.DoneCommand() { - @Override - public void doneCommand(IToken token, Exception error) { - if (error == null) { - // We are attached now, trigger a refresh of the node - IModel model = node.getParent(IModel.class); - Assert.isNotNull(model); - model.getService(IModelRefreshService.class).refresh(node, new Callback() { - @Override - protected void internalDone(Object caller, IStatus status) { - onDone(callback); + Assert.isNotNull(peerModel); + Assert.isNotNull(nodes); + + // Loop the nodes and attach to them + if (!nodes.isEmpty()) { + // Open a channel + Tcf.getChannelManager().openChannel(peerModel.getPeer(), null, new IChannelManager.DoneOpenChannel() { + @Override + public void doneOpenChannel(final Throwable error, final IChannel channel) { + if (error == null) { + final IProcesses service = channel.getRemoteService(IProcesses.class); + if (service != null) { + // Create the callback collector + AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + if (status.getSeverity() == IStatus.ERROR) { + onError(peerModel, status.getMessage(), status.getException(), callback); + } else { + onDone(callback); + } + } + }, new CallbackInvocationDelegate()); + + for (final IProcessContextNode node: nodes) { + final ICallback callback2 = new AsyncCallbackCollector.SimpleCollectorCallback(collector); + service.getContext(node.getStringProperty(IModelNode.PROPERTY_ID), new IProcesses.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (error == null && context != null) { + context.attach(new IProcesses.DoneCommand() { + @Override + public void doneCommand(IToken token, Exception error) { + if (error == null) { + // We are attached now, trigger a refresh of the node + IModel model = node.getParent(IModel.class); + Assert.isNotNull(model); + model.getService(IModelRefreshService.class).refresh(node, new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + callback2.done(AttachStep.this, Status.OK_STATUS); + } + }); + } else { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.AttachStep_error_attach, node.getName()), error); + callback2.done(AttachStep.this, status); } - }); - } else { - onError(node, Messages.AttachStep_error_attach, error, callback); - } + } + }); + } else { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + NLS.bind(Messages.AttachStep_error_getContext, node.getName()), error); + callback2.done(AttachStep.this, status); } - }); - } else { - onError(node, Messages.AttachStep_error_getContext, error, callback); - } + } + }); } - }); + + // Mark the collector initialization done + collector.initDone(); + } else { + onError(peerModel, NLS.bind(Messages.AttachStep_error_missingService, peerModel.getName()), null, callback); + } } else { - onError(node, Messages.AttachStep_error_connect, null, callback); + onError(peerModel, NLS.bind(Messages.AttachStep_error_openChannel, peerModel.getName()), error, callback); } - } else { - onError(node, Messages.AttachStep_error_openChannel, error, callback); } - } - }); + }); + } else { + onDone(callback); + } } /** @@ -170,8 +208,12 @@ public class AttachStep { } String fullMessage = message; - if (fullMessage != null) fullMessage = NLS.bind(fullMessage, detailMessage != null ? detailMessage : ""); //$NON-NLS-1$ - else fullMessage = detailMessage; + if (fullMessage != null && detailMessage != null) { + fullMessage += NLS.bind(Messages.AttachStep_error_possibleCause, detailMessage); + } + else if (fullMessage == null) { + fullMessage = detailMessage; + } if (fullMessage != null) { IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), fullMessage, error); 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 76a103c07..231162619 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others. All rights reserved. + * Copyright (c) 2011, 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 @@ -52,10 +52,11 @@ public class Messages extends NLS { public static String PendingOperation_label; - public static String AttachStep_error_connect; - public static String AttachStep_error_attach; - public static String AttachStep_error_getContext; + public static String AttachStep_error_possibleCause; + public static String AttachStep_error_missingService; public static String AttachStep_error_openChannel; + public static String AttachStep_error_getContext; + public static String AttachStep_error_attach; public static String AttachStep_error_title; public static String DetachStep_error_title; 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 4c2f77404..dd06d09dc 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 @@ -31,10 +31,11 @@ ProcessStreamReaderRunnable_error_appendFailed=Failed to append data from stream PendingOperation_label=Pending... -AttachStep_error_connect=Failed to attach to context: {0} -AttachStep_error_attach=Failed to attach context: {0} -AttachStep_error_getContext=Failed to get context: {0} -AttachStep_error_openChannel=Failed to open channel: {0} +AttachStep_error_possibleCause=\n\nPossible Cause:\n{0} +AttachStep_error_missingService=Failed to attach to selected context(s). The required service is missing on target ''{0}''. +AttachStep_error_openChannel=Failed to attach to selected context(s). A channel to target ''{0}'' cannot be opened. +AttachStep_error_getContext=Failed to query properties for context ''{0}''. +AttachStep_error_attach=Failed to attach to context ''{0}''. AttachStep_error_title=Error DetachStep_error_title=Error |