blob: c0188450b487bfcc36f7299e1a9dd022c70e507a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
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.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IDebugTarget;
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.core.model.ITerminate;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.DebugPluginImages;
import org.eclipse.debug.internal.ui.DebugUIMessages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.contexts.IDebugContextListener;
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.action.Action;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
/**
* Action for adding memory block.
*
* @since 3.0
*/
public class AddMemoryBlockAction extends Action implements IDebugContextListener, IDebugEventSetListener{
protected IAdaptable fCurrentContext = null;
protected IMemoryBlock fLastMemoryBlock;
private boolean fAddDefaultRenderings = true;
protected IMemoryRenderingSite fSite;
public AddMemoryBlockAction(IMemoryRenderingSite site)
{
initialize(site);
}
/**
* @param addDefaultRenderings - specify if the action should add
* default renderings for the new memory block when it is run
*/
AddMemoryBlockAction(IMemoryRenderingSite site, boolean addDefaultRenderings)
{
initialize(site);
fAddDefaultRenderings = addDefaultRenderings;
}
/**
*
*/
private void initialize(IMemoryRenderingSite site) {
setText(DebugUIMessages.AddMemoryBlockAction_title);
doInitialization(site);
}
public AddMemoryBlockAction(String text, int style, IMemoryRenderingSite site)
{
super(text, style);
doInitialization(site);
}
/**
*
*/
private void doInitialization(IMemoryRenderingSite site) {
fSite = site;
setToolTipText(DebugUIMessages.AddMemoryBlockAction_tooltip);
setImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_MONITOR_EXPRESSION));
setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_LCL_MONITOR_EXPRESSION));
setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_MONITOR_EXPRESSION));
PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".addMemoryMonitorAction_context"); //$NON-NLS-1$
// listen for context changed
DebugUITools.getDebugContextManager().getContextService(site.getSite().getWorkbenchWindow()).addDebugContextListener(this);
// get current context
fCurrentContext = DebugUITools.getDebugContext();
// set up enablement based on current selection
updateAction(fCurrentContext);
DebugPlugin.getDefault().addDebugEventListener(this);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IAction#run()
*/
public void run() {
boolean exit = false;
String prefillExp = null;
String prefillLength = null;
while (!exit)
{
exit = true;
Object elem = DebugUITools.getDebugContext();
IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(elem);
if (retrieval == null)
return;
Shell shell= DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
// create dialog to ask for expression/address to block
MonitorMemoryBlockDialog dialog = new MonitorMemoryBlockDialog(shell, retrieval, prefillExp, prefillLength);
dialog.open();
int returnCode = dialog.getReturnCode();
if (returnCode == Window.CANCEL)
{
return;
}
// get expression entered in dialog
String input = dialog.getExpression();
// remember expression and length
prefillExp = input;
prefillLength = dialog.getLength();
ArrayList expressions = new ArrayList();
if (input.length() == 0)
{
expressions.add(IInternalDebugCoreConstants.EMPTY_STRING);
}
else
{
StringTokenizer tokenizer = new StringTokenizer(input, ","); //$NON-NLS-1$
while (tokenizer.hasMoreTokens())
{
expressions.add(tokenizer.nextToken());
}
}
final String[] expressionsArray = (String[])expressions.toArray(new String[expressions.size()]);
exit = true;
final boolean finalExit = exit;
final Object finalElement = elem;
final IMemoryBlockRetrieval finalRetrieval = retrieval;
final MonitorMemoryBlockDialog finalDialog = dialog;
Job job = new Job("Add Memory Block") { //$NON-NLS-1$
protected IStatus run(IProgressMonitor monitor) {
addMemoryBlocks(finalExit, finalElement, finalRetrieval, finalDialog, expressionsArray);
return Status.OK_STATUS;
}};
job.setSystem(true);
job.schedule();
}
}
/**
* @param exit
* @param elem
* @param standardMemRetrieval
* @param dialog
* @param expressionsArray
* @return
*/
private boolean addMemoryBlocks(boolean exit, Object elem, IMemoryBlockRetrieval standardMemRetrieval, MonitorMemoryBlockDialog dialog, final String[] expressionsArray) {
for (int i=0; i<expressionsArray.length; i++)
{
String expression = expressionsArray[i].trim();
try {
if (standardMemRetrieval instanceof IMemoryBlockRetrievalExtension)
{
// if the debug session supports IMemoryBlockExtensionRetrieval
IMemoryBlockRetrievalExtension memRetrieval = (IMemoryBlockRetrievalExtension)standardMemRetrieval;
// get extended memory block with the expression entered
IMemoryBlockExtension memBlock = memRetrieval.getExtendedMemoryBlock(expression, elem);
// add block to memory block manager
if (memBlock != null)
{
fLastMemoryBlock = memBlock;
IMemoryBlock[] memArray = new IMemoryBlock[]{memBlock};
MemoryViewUtil.getMemoryBlockManager().addMemoryBlocks(memArray);
if (fAddDefaultRenderings)
addDefaultRenderings(memBlock);
}
else
{
// open error if it failed to retrieve a memory block
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_noMemoryBlock, null);
exit = false;
}
}
else
{
// if the debug session does not support IMemoryBlockExtensionRetrieval
expression = expression.toUpperCase();
String hexPrefix = "0X"; //$NON-NLS-1$
if (expression.startsWith(hexPrefix))
{
expression = expression.substring(hexPrefix.length());
}
// convert the expression to an address
BigInteger address = new BigInteger(expression, 16);
long longAddress = address.longValue();
// get the length of memory to block
String strLength = dialog.getLength();
long length = Long.parseLong(strLength);
// must monitor at least one line
if (length <= 0)
{
String message = DebugUIMessages.AddMemoryBlockAction_failed + "\n" + DebugUIMessages.AddMemoryBlockAction_input_invalid; //$NON-NLS-1$
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, message, null);
exit = false;
continue;
}
// get standard memory block
IMemoryBlock memBlock = standardMemRetrieval.getMemoryBlock(longAddress, length);
// make sure the memory block returned is not an instance of IMemoryBlockExtension
if (memBlock instanceof IMemoryBlockExtension)
{
Status status = new Status(IStatus.WARNING, DebugUIPlugin.getUniqueIdentifier(), 0,
"IMemoryBlockRetrieval returns IMemoryBlockExtension. This may result in unexpected behavior.", null); //$NON-NLS-1$
DebugUIPlugin.log(status);
}
if (memBlock != null)
{
// add memory block to memory block manager
fLastMemoryBlock = memBlock;
IMemoryBlock[] memArray = new IMemoryBlock[]{memBlock};
MemoryViewUtil.getMemoryBlockManager().addMemoryBlocks(memArray);
if (fAddDefaultRenderings)
addDefaultRenderings(memBlock);
}
else
{
// otherwise open up an error doalog
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_noMemoryBlock, null);
exit = false;
}
}
} catch (DebugException e1) {
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_failed, e1);
exit = false;
}
catch(NumberFormatException e2)
{
String message = DebugUIMessages.AddMemoryBlockAction_failed + "\n" + DebugUIMessages.AddMemoryBlockAction_input_invalid; //$NON-NLS-1$
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, message, null);
exit = false;
}
}
return exit;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
*/
public void handleDebugEvents(DebugEvent[] events) {
for (int i=0; i < events.length; i++)
handleDebugEvent(events[i]);
}
private void handleDebugEvent(DebugEvent event)
{
// update action enablement based on debug event
Object src = event.getSource();
IDebugTarget srcDT = null;
IDebugTarget selectionDT = null;
if (event.getKind() == DebugEvent.TERMINATE)
{
if (src instanceof ITerminate && src instanceof IDebugElement)
{
srcDT = ((IDebugElement)src).getDebugTarget();
}
if (fCurrentContext instanceof IDebugElement)
{
selectionDT = ((IDebugElement)fCurrentContext).getDebugTarget();
}
// disable action if the debug target is terminated.
if (srcDT == selectionDT)
{
setEnabled(false);
}
}
// handle change event from memory block retrieval object
// to allow non-standard debug models to update the action
else if (event.getKind() == DebugEvent.CHANGE && event.getDetail() == DebugEvent.STATE)
{
Object evtSrc = event.getSource();
if (evtSrc == MemoryViewUtil.getMemoryBlockRetrieval(fCurrentContext))
updateAction(fCurrentContext);
}
}
/**
* Return the last memory block added to memory block manager via this action.
* @return Returns the fLastMemoryBlock.
*/
public IMemoryBlock getLastMemoryBlock() {
return fLastMemoryBlock;
}
protected void dispose() {
// remove listeners
DebugPlugin.getDefault().removeDebugEventListener(this);
DebugUITools.getDebugContextManager().getContextService(fSite.getSite().getWorkbenchWindow()).removeDebugContextListener(this);
}
private void addDefaultRenderings(IMemoryBlock memoryBlock)
{
IMemoryRenderingType primaryType = DebugUITools.getMemoryRenderingManager().getPrimaryRenderingType(memoryBlock);
IMemoryRenderingType renderingTypes[] = DebugUITools.getMemoryRenderingManager().getDefaultRenderingTypes(memoryBlock);
// create primary rendering
try {
if (primaryType != null)
{
createRenderingInContainer(memoryBlock, primaryType, IDebugUIConstants.ID_RENDERING_VIEW_PANE_1);
}
else if (renderingTypes.length > 0)
{
primaryType = renderingTypes[0];
createRenderingInContainer(memoryBlock, renderingTypes[0], IDebugUIConstants.ID_RENDERING_VIEW_PANE_1);
}
} catch (CoreException e1) {
DebugUIPlugin.log(e1);
}
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, renderingTypes[i], IDebugUIConstants.ID_RENDERING_VIEW_PANE_2);
} catch (CoreException e) {
DebugUIPlugin.log(e);
}
}
}
/**
* @param memoryBlock
* @param primaryType
* @throws CoreException
*/
private void createRenderingInContainer(IMemoryBlock memoryBlock, IMemoryRenderingType primaryType, String paneId) throws CoreException {
IMemoryRendering rendering = primaryType.createRendering();
IMemoryRenderingContainer container = fSite.getContainer(paneId);
rendering.init(container, memoryBlock);
container.addMemoryRendering(rendering);
}
protected MemoryView getMemoryView()
{
if (fSite instanceof MemoryView)
return (MemoryView)fSite;
return null;
}
protected void updateAction(final Object debugContext)
{
Job job = new Job("Update Add Memory Block Action") { //$NON-NLS-1$
protected IStatus run(IProgressMonitor monitor) {
setEnabled(MemoryViewUtil.isValidContext(debugContext));
return Status.OK_STATUS;
}};
job.setSystem(true);
job.schedule();
}
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener#contextEvent(org.eclipse.debug.internal.ui.contexts.provisional.DebugContextEvent)
*/
public void debugContextChanged(DebugContextEvent event) {
if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) {
IAdaptable context = DebugUITools.getDebugContext();
updateAction(context);
fCurrentContext = context;
}
}
}