/*******************************************************************************
* 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);
}
}
}