/******************************************************************************* * Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved. * This program and the accompanying materials are made available under the terms * of the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tm.te.tcf.processes.ui.internal.handler; import java.util.Iterator; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.tm.tcf.protocol.IChannel; import org.eclipse.tm.tcf.protocol.IPeer; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.te.runtime.interfaces.properties.IPropertiesContainer; import org.eclipse.tm.te.runtime.properties.PropertiesContainer; import org.eclipse.tm.te.runtime.statushandler.StatusHandlerManager; import org.eclipse.tm.te.runtime.statushandler.interfaces.IStatusHandler; import org.eclipse.tm.te.runtime.statushandler.interfaces.IStatusHandlerConstants; import org.eclipse.tm.te.tcf.core.Tcf; import org.eclipse.tm.te.tcf.core.interfaces.IChannelManager; import org.eclipse.tm.te.tcf.locator.interfaces.nodes.IPeerModel; import org.eclipse.tm.te.tcf.processes.ui.activator.UIPlugin; import org.eclipse.tm.te.tcf.processes.ui.internal.help.IContextHelpIds; import org.eclipse.tm.te.tcf.processes.ui.nls.Messages; import org.eclipse.tm.te.ui.swt.DisplayUtil; import org.eclipse.ui.handlers.HandlerUtil; /** * Abstract channel command handler implementation. */ public abstract class AbstractChannelCommandHandler extends AbstractHandler { /* (non-Javadoc) * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ @Override public Object execute(final ExecutionEvent event) throws ExecutionException { // Get the active menu selection ISelection activeSelection = HandlerUtil.getActiveMenuSelection(event); // The selection is expected to be a structured exception if (activeSelection instanceof IStructuredSelection && !activeSelection.isEmpty()) { IStructuredSelection selection = (IStructuredSelection)activeSelection; // Loop the selection Iterator<?> iterator = selection.iterator(); while (iterator.hasNext()) { Object element = iterator.next(); // The selected element is expected to be a peer node if (element instanceof IPeerModel) { final IPeerModel node = (IPeerModel)element; IPeer peer = node.getPeer(); // If the peer is available, we can open a channel to the remote peer if (peer != null) { // Get the channel Tcf.getChannelManager().openChannel(peer, new IChannelManager.DoneOpenChannel() { @Override public void doneOpenChannel(final Throwable error, final IChannel channel) { if (error == null) { // Invoke the execute within the UI thread again. Runnable runnable = new Runnable() { @Override public void run() { execute(event, channel, node, new DoneExecute() { @Override public void doneExecute(IStatus status, Object result) { if (status.getSeverity() != IStatus.OK && status.getSeverity() != IStatus.CANCEL) { handleException(channel, new CoreException(status)); } else { // Close the channel if (channel != null) { final IChannel finChannel = channel; if (Protocol.isDispatchThread()) { finChannel.close(); } else { Protocol.invokeAndWait(new Runnable() { @Override public void run() { finChannel.close(); } }); } } } } }); } }; DisplayUtil.safeAsyncExec(runnable); } else { handleException(channel, error); } } }); } } } } return null; } /** * Executes the command handler logic. * * @param event The execution event. Must be not <code>null</code>. * @param channel The channel. Must be not <code>null</code>. * @param node The selected node. Must be not <code>null</code>. * @param callback The callback to invoke if the execution finished. Must be not <code>null</code>. */ protected abstract void execute(ExecutionEvent event, IChannel channel, IPeerModel node, DoneExecute callback); /** * Client call back interface for execute(...). */ public static interface DoneExecute { /** * Called when execute(...) got finished. * * @param status The execution status. Must not be <code>null</code>. * @param result The execution result or <code>null</code>. */ public void doneExecute(IStatus status, Object result); } /** * Closes the given channel and handle the given exception. * * @param channel The channel instance or <code>null</code>. * @param exception The exception to handle. Must be not <code>null</code>. */ protected void handleException(IChannel channel, Throwable exception) { Assert.isNotNull(exception); // Close the backend channel if (channel != null) { final IChannel finChannel = channel; if (Protocol.isDispatchThread()) { finChannel.close(); } else { Protocol.invokeAndWait(new Runnable() { @Override public void run() { finChannel.close(); } }); } } // Get the status handler IStatusHandler[] handler = StatusHandlerManager.getInstance().getHandler(getClass()); if (handler != null && handler.length > 0) { // If the exception is a core exception, we can pass on the status object to the handler IStatus status = null; if (exception instanceof CoreException) ((CoreException)exception).getStatus(); else { // Construct the status from the exception status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), 0, exception.getLocalizedMessage(), exception); } // Handle the status (Take the first status handler in the list) if (status != null) { IPropertiesContainer data = new PropertiesContainer(); data.setProperty(IStatusHandlerConstants.PROPERTY_TITLE, getStatusDialogTitle()); data.setProperty(IStatusHandlerConstants.PROPERTY_CONTEXT_HELP_ID, getStatusDialogContextHelpId()); data.setProperty(IStatusHandlerConstants.PROPERTY_DONT_ASK_AGAIN_ID, getStatusDialogDontAskAgainKey()); data.setProperty(IStatusHandlerConstants.PROPERTY_CALLER, this); handler[0].handleStatus(status, data, null); } } } /** * Returns the title to be used for the status dialog in case of * an execution failure. * * @return The status dialog title. */ protected String getStatusDialogTitle() { return Messages.AbstractChannelCommandHandler_statusDialog_title; } /** * Returns the context help id to be used for the status dialog in case * of an execution failure. * * @return The context help id or <code>null</code>. */ protected String getStatusDialogContextHelpId() { return IContextHelpIds.CHANNEL_COMMAND_HANDLER_STATUS_DIALOG; } /** * Returns the don't ask again key to be used for the status dialog in * case of an execution failure. * * @return The don't ask again key or <code>null</code>. */ protected String getStatusDialogDontAskAgainKey() { return null; } }