/******************************************************************************* * Copyright (c) 2010, 2013 Nokia 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: * Nokia - Initial API and implementation * Marc Khouzam (Ericsson) - Allow to disable ViewMemory handler (bug 418710) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.model.IViewInMemory; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData.BasicType; import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMNode.VariableExpressionVMC; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.IMemoryBlockRetrieval; import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.memory.IMemoryRendering; import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; import org.eclipse.debug.ui.memory.IMemoryRenderingSite; import org.eclipse.debug.ui.memory.IMemoryRenderingType; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.ISources; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; /** * DSF version of handler for viewing variable in memory view command. * */ public class DsfViewMemoryHandler extends AbstractHandler { private VariableExpressionVMC[] fMemoryViewables = new VariableExpressionVMC[0]; protected VariableExpressionVMC[] getMemoryViewables() { return fMemoryViewables; } protected void setMemoryViewables(VariableExpressionVMC[] viewableMemoryITems) { fMemoryViewables = viewableMemoryITems; } @Override public void setEnabled(Object evaluationContext) { VariableExpressionVMC[] viewableMemoryITems = getMemoryViewables(evaluationContext); setBaseEnabled(viewableMemoryITems.length > 0); setMemoryViewables(viewableMemoryITems); } /* * (non-Javadoc) * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { if (getMemoryViewables() == null || getMemoryViewables().length == 0) { return null; } showInMemoryView(getMemoryViewables()); return null; } private VariableExpressionVMC[] getMemoryViewables(Object evaluationContext) { List<VariableExpressionVMC> viewableMemoryItems = new ArrayList<VariableExpressionVMC>(); if (evaluationContext instanceof IEvaluationContext) { Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME); if (s instanceof IStructuredSelection) { Iterator<?> iter = ((IStructuredSelection)s).iterator(); while(iter.hasNext()) { Object obj = iter.next(); if (obj instanceof VariableExpressionVMC) { Object element = DebugPlugin.getAdapter(obj, IViewInMemory.class); if (element != null) { if (((IViewInMemory)element).canViewInMemory()) { viewableMemoryItems.add((VariableExpressionVMC)obj); } } } } } } return viewableMemoryItems.toArray(new VariableExpressionVMC[viewableMemoryItems.size()]); } private void addDefaultRenderings(IMemoryBlock memoryBlock, IMemoryRenderingSite memRendSite) { // This method was mostly lifted from the platform's AddMemoryBlockAction IMemoryRenderingType primaryType = DebugUITools.getMemoryRenderingManager().getPrimaryRenderingType(memoryBlock); IMemoryRenderingType renderingTypes[] = DebugUITools.getMemoryRenderingManager().getDefaultRenderingTypes(memoryBlock); try { if (primaryType != null) { createRenderingInContainer(memoryBlock, memRendSite, primaryType, IDebugUIConstants.ID_RENDERING_VIEW_PANE_1); } else if (renderingTypes.length > 0) { primaryType = renderingTypes[0]; createRenderingInContainer(memoryBlock, memRendSite, renderingTypes[0], IDebugUIConstants.ID_RENDERING_VIEW_PANE_1); } } catch (CoreException e) { DsfUIPlugin.logErrorMessage(e.getMessage()); } for (int i = 0; i < renderingTypes.length; i++) { try { boolean create = true; if (primaryType != null) { if (primaryType.getId().equals(renderingTypes[i].getId())) create = false; } if (create) createRenderingInContainer(memoryBlock, memRendSite, renderingTypes[i], IDebugUIConstants.ID_RENDERING_VIEW_PANE_2); } catch (CoreException e) { DsfUIPlugin.logErrorMessage(e.getMessage()); } } } private void createRenderingInContainer(IMemoryBlock memoryBlock, IMemoryRenderingSite memRendSite, IMemoryRenderingType primaryType, String paneId) throws CoreException { // This method was mostly lifted from the platform's AddMemoryBlockAction IMemoryRendering rendering = primaryType.createRendering(); IMemoryRenderingContainer container = memRendSite.getContainer(paneId); rendering.init(container, memoryBlock); container.addMemoryRendering(rendering); } private void renderMemoryBlock(IMemoryBlockExtension memBlock, IMemoryRenderingSite memRendSite) { IMemoryBlock[] memArray = new IMemoryBlock[] { memBlock }; DebugPlugin.getDefault().getMemoryBlockManager().addMemoryBlocks(memArray); addDefaultRenderings(memBlock, memRendSite); } private IStatus showExpressionInMemoryView(VariableExpressionVMC context, IExpressionDMData exprData, IMemoryRenderingSite memRendSite) { BasicType type = exprData.getBasicType(); String exprString; if (type == BasicType.array || type == BasicType.pointer) { exprString = context.getExpression(); } else { exprString = "&(" + context.getExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } try { IDMContext dmc = context.getDMContext(); IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) context.getAdapter(IMemoryBlockRetrieval.class); if (retrieval == null && context instanceof IDebugElement) retrieval = ((IDebugElement)context).getDebugTarget(); if (retrieval == null || !(retrieval instanceof IMemoryBlockRetrievalExtension)) return Status.OK_STATUS; IMemoryBlockRetrievalExtension dsfRetrieval = (IMemoryBlockRetrievalExtension) retrieval; IMemoryBlockExtension memBlock = dsfRetrieval.getExtendedMemoryBlock(exprString, dmc); renderMemoryBlock(memBlock, memRendSite); return Status.OK_STATUS; } catch (DebugException e) { return DsfUIPlugin.newErrorStatus(IStatus.OK, "Can't view memory on " + exprString, e); //$NON-NLS-1$ } } private void showInMemoryView(VariableExpressionVMC contexts[]) { try { IWorkbenchPage page = DsfUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewPart memoryView = page.showView(IDebugUIConstants.ID_MEMORY_VIEW, null, IWorkbenchPage.VIEW_ACTIVATE); final IMemoryRenderingSite memRendSite = (IMemoryRenderingSite) memoryView; for (final VariableExpressionVMC context : contexts) { final IExpressionDMContext dmc = DMContexts.getAncestorOfType(context.getDMContext(), IExpressionDMContext.class); if (dmc == null) { continue; } final DsfSession session = DsfSession.getSession(context.getDMContext().getSessionId()); if (session == null) { continue; } final DsfExecutor executor = session.getExecutor(); if (executor == null) { continue; } executor.execute(new DsfRunnable() { @Override public void run() { DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId()); IExpressions service = tracker.getService(IExpressions.class); tracker.dispose(); if (service != null) { service.getExpressionData(dmc, new DataRequestMonitor<IExpressionDMData>(executor, null) { @Override protected void handleSuccess() { final IExpressionDMData exprData = getData(); if (exprData != null) { Job job = new Job("View Memory") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { return showExpressionInMemoryView(context, exprData, memRendSite); } }; job.setSystem(true); job.schedule(); } } }); } } }); } } catch (PartInitException e) { DsfUIPlugin.log(e); } catch (RejectedExecutionException e) { DsfUIPlugin.log(e); } } }