blob: 917469152825edc670b7523f085c9e5e2cf073e7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2012 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.ldt.debug.core.internal;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.dltk.dbgp.DbgpBaseCommands;
import org.eclipse.dltk.dbgp.DbgpRequest;
import org.eclipse.dltk.dbgp.IDbgpCommunicator;
import org.eclipse.dltk.dbgp.IDbgpFeature;
import org.eclipse.dltk.dbgp.IDbgpNotificationManager;
import org.eclipse.dltk.dbgp.IDbgpProperty;
import org.eclipse.dltk.dbgp.IDbgpRawListener;
import org.eclipse.dltk.dbgp.IDbgpSession;
import org.eclipse.dltk.dbgp.IDbgpSessionInfo;
import org.eclipse.dltk.dbgp.IDbgpStackLevel;
import org.eclipse.dltk.dbgp.IDbgpStatus;
import org.eclipse.dltk.dbgp.breakpoints.DbgpBreakpointConfig;
import org.eclipse.dltk.dbgp.breakpoints.IDbgpBreakpoint;
import org.eclipse.dltk.dbgp.commands.IDbgpContextCommands;
import org.eclipse.dltk.dbgp.commands.IDbgpCoreCommands;
import org.eclipse.dltk.dbgp.commands.IDbgpExtendedCommands;
import org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands;
import org.eclipse.dltk.dbgp.commands.IDbgpStackCommands;
import org.eclipse.dltk.dbgp.exceptions.DbgpDebuggingEngineException;
import org.eclipse.dltk.dbgp.exceptions.DbgpException;
import org.eclipse.dltk.dbgp.internal.IDbgpTerminationListener;
import org.eclipse.dltk.dbgp.internal.managers.IDbgpStreamManager;
import org.eclipse.dltk.dbgp.internal.utils.DbgpXmlEntityParser;
import org.eclipse.dltk.dbgp.internal.utils.DbgpXmlParser;
import org.eclipse.dltk.debug.core.IDebugOptions;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This is a proxy class for Lua coroutines which automatically binds the coroutine ID on necessary commands.
*/
@SuppressWarnings({ "restriction", "unchecked", "rawtypes" })
public class LuaCoroutineDbgpSession implements IDbgpSession {
private static final String COROUTINE_FLAG = "-o"; //$NON-NLS-1$
private IDbgpSession actualSession;
private LuaCoroutine coroutine;
private IDbgpCoreCommands proxyCoreCommands;
private class CoroutineStackCommands extends DbgpBaseCommands implements IDbgpStackCommands {
private static final String STACK_DEPTH_COMMAND = "stack_depth"; //$NON-NLS-1$
private static final String STACK_GET_COMMAND = "stack_get"; //$NON-NLS-1$
private static final String TAG_STACK = "stack"; //$NON-NLS-1$
private static final String ATTR_DEPTH = "depth"; //$NON-NLS-1$
private final Comparator levelComparator = new Comparator() {
public int compare(Object o1, Object o2) {
final IDbgpStackLevel level1 = (IDbgpStackLevel) o1;
final IDbgpStackLevel level2 = (IDbgpStackLevel) o2;
return level1.getLevel() - level2.getLevel();
}
};
/**
* @param communicator
*/
public CoroutineStackCommands(IDbgpCommunicator communicator) {
super(communicator);
}
protected int parseStackDepthResponse(Element response) throws DbgpDebuggingEngineException {
return Integer.parseInt(response.getAttribute(ATTR_DEPTH));
}
protected IDbgpStackLevel[] parseStackLevels(Element response) throws DbgpException {
NodeList nodes = response.getElementsByTagName(TAG_STACK);
IDbgpStackLevel[] list = new IDbgpStackLevel[nodes.getLength()];
for (int i = 0; i < nodes.getLength(); ++i) {
final Element level = (Element) nodes.item(i);
list[i] = DbgpXmlEntityParser.parseStackLevel(level);
}
Arrays.sort(list, levelComparator);
return list;
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpStackCommands#getStackDepth()
*/
@Override
public int getStackDepth() throws DbgpException {
DbgpRequest request = createRequest(STACK_DEPTH_COMMAND);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
return parseStackDepthResponse(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpStackCommands#getStackLevels()
*/
@Override
public IDbgpStackLevel[] getStackLevels() throws DbgpException {
DbgpRequest request = createRequest(STACK_GET_COMMAND);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
return parseStackLevels(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpStackCommands#getStackLevel(int)
*/
@Override
public IDbgpStackLevel getStackLevel(int stackDepth) throws DbgpException {
DbgpRequest request = createRequest(STACK_GET_COMMAND);
request.addOption("-d", stackDepth); //$NON-NLS-1$
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
IDbgpStackLevel[] levels = parseStackLevels(communicate(request));
return levels.length == 1 ? levels[0] : null;
}
}
private class CoroutineContextCommands extends DbgpBaseCommands implements IDbgpContextCommands {
private static final String CONTEXT_NAMES_COMMAND = "context_names"; //$NON-NLS-1$
private static final String CONTEXT_GET = "context_get"; //$NON-NLS-1$
private static final String TAG_CONTEXT = "context"; //$NON-NLS-1$
private static final String ATTR_NAME = "name"; //$NON-NLS-1$
private static final String ATTR_ID = "id"; //$NON-NLS-1$
public CoroutineContextCommands(IDbgpCommunicator communicator) {
super(communicator);
}
protected Map parseContextNamesResponse(Element response) throws DbgpException {
Map map = new HashMap();
NodeList contexts = response.getElementsByTagName(TAG_CONTEXT);
for (int i = 0; i < contexts.getLength(); ++i) {
Element context = (Element) contexts.item(i);
String name = context.getAttribute(ATTR_NAME);
Integer id = new Integer(context.getAttribute(ATTR_ID));
map.put(id, name);
}
return map;
}
protected IDbgpProperty[] parseContextPropertiesResponse(Element response) throws DbgpException {
NodeList properties = response.getChildNodes();
List list = new ArrayList();
for (int i = 0; i < properties.getLength(); ++i) {
Node item = properties.item(i);
if (item instanceof Element) {
if (item.getNodeName().equals(DbgpXmlEntityParser.TAG_PROPERTY)) {
list.add(DbgpXmlEntityParser.parseProperty((Element) item));
}
}
}
return (IDbgpProperty[]) list.toArray(new IDbgpProperty[list.size()]);
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpContextCommands#getContextNames(int)
*/
@Override
public Map getContextNames(int stackDepth) throws DbgpException {
DbgpRequest request = createRequest(CONTEXT_NAMES_COMMAND);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.addOption("-d", stackDepth); //$NON-NLS-1$
return parseContextNamesResponse(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpContextCommands#getContextProperties(int)
*/
@Override
public IDbgpProperty[] getContextProperties(int stackDepth) throws DbgpException {
DbgpRequest request = createRequest(CONTEXT_GET);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.addOption("-d", stackDepth); //$NON-NLS-1$
return parseContextPropertiesResponse(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpContextCommands#getContextProperties(int, int)
*/
@Override
public IDbgpProperty[] getContextProperties(int stackDepth, int contextId) throws DbgpException {
DbgpRequest request = createRequest(CONTEXT_GET);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.addOption("-d", stackDepth); //$NON-NLS-1$
request.addOption("-c", contextId); //$NON-NLS-1$
return parseContextPropertiesResponse(communicate(request));
}
}
private class CoroutinePropertyCommands extends DbgpBaseCommands implements IDbgpPropertyCommands {
private static final String PROPERTY_GET_COMMAND = "property_get"; //$NON-NLS-1$
private static final String PROPERTY_SET_COMMAND = "property_set"; //$NON-NLS-1$
/**
* @param communicator
*/
public CoroutinePropertyCommands(IDbgpCommunicator communicator) {
super(communicator);
}
protected IDbgpProperty parsePropertyResponse(Element response) throws DbgpException {
// TODO: check length!!!
NodeList properties = response.getElementsByTagName(DbgpXmlEntityParser.TAG_PROPERTY);
return DbgpXmlEntityParser.parseProperty((Element) properties.item(0));
}
protected IDbgpProperty getProperty(Integer page, String name, Integer stackDepth, Integer contextId) throws DbgpException {
DbgpRequest request = createRequest(PROPERTY_GET_COMMAND);
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.addOption("-n", name); //$NON-NLS-1$
if (stackDepth != null) {
request.addOption("-d", stackDepth); //$NON-NLS-1$
}
if (contextId != null) {
request.addOption("-c", contextId); //$NON-NLS-1$
}
if (page != null) {
request.addOption("-p", page); //$NON-NLS-1$
}
return parsePropertyResponse(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#getPropertyByKey(java.lang.String, java.lang.String)
*/
@Override
public IDbgpProperty getPropertyByKey(String name, String key) throws DbgpException {
DbgpRequest request = createRequest(PROPERTY_GET_COMMAND);
request.addOption("-n", name); //$NON-NLS-1$
request.addOption("-k", key); //$NON-NLS-1$
return parsePropertyResponse(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#getProperty(java.lang.String)
*/
@Override
public IDbgpProperty getProperty(String name) throws DbgpException {
return getProperty(null, name, null, null);
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#getProperty(java.lang.String, int)
*/
@Override
public IDbgpProperty getProperty(String name, int stackDepth) throws DbgpException {
return getProperty(null, name, stackDepth, null);
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#getProperty(java.lang.String, int, int)
*/
@Override
public IDbgpProperty getProperty(String name, int stackDepth, int contextId) throws DbgpException {
return getProperty(null, name, stackDepth, contextId);
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#getProperty(int, java.lang.String, int)
*/
@Override
public IDbgpProperty getProperty(int page, String name, int stackDepth) throws DbgpException {
return getProperty(page, name, stackDepth, null);
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#setProperty(org.eclipse.dltk.dbgp.IDbgpProperty)
*/
@Override
public boolean setProperty(IDbgpProperty property) throws DbgpException {
DbgpRequest request = createRequest(PROPERTY_SET_COMMAND);
request.addOption("-n", property.getName()); //$NON-NLS-1$
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.setData(property.getValue());
return DbgpXmlParser.parseSuccess(communicate(request));
}
/**
* @see org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands#setProperty(java.lang.String, int, java.lang.String)
*/
@Override
public boolean setProperty(String name, int stackDepth, String value) throws DbgpException {
DbgpRequest request = createRequest(PROPERTY_SET_COMMAND);
request.addOption("-n", name); //$NON-NLS-1$
request.addOption(COROUTINE_FLAG, coroutine.getCoroutineId());
request.addOption("-d", stackDepth); //$NON-NLS-1$
request.setData(value);
return DbgpXmlParser.parseSuccess(communicate(request));
}
}
private class CoroutineCoreCommands implements IDbgpCoreCommands {
private IDbgpCoreCommands actualCoreCommands;
private IDbgpStackCommands proxiedStackCommands;
private IDbgpContextCommands proxiedContextCommands;
private IDbgpPropertyCommands proxiedPropertyCommands;
/**
* @param actualCoreCommands
*/
public CoroutineCoreCommands() {
super();
this.actualCoreCommands = actualSession.getCoreCommands();
this.proxiedStackCommands = new CoroutineStackCommands(getCommunicator());
this.proxiedContextCommands = new CoroutineContextCommands(getCommunicator());
this.proxiedPropertyCommands = new CoroutinePropertyCommands(getCommunicator());
}
public String getSource(URI uri) throws DbgpException {
return actualCoreCommands.getSource(uri);
}
public IDbgpStatus getStatus() throws DbgpException {
return actualCoreCommands.getStatus();
}
public IDbgpStatus run() throws DbgpException {
return actualCoreCommands.run();
}
public String getSource(URI uri, int beginLine) throws DbgpException {
return actualCoreCommands.getSource(uri, beginLine);
}
public boolean configureStdout(int value) throws DbgpException {
return actualCoreCommands.configureStdout(value);
}
public boolean configureStderr(int value) throws DbgpException {
return actualCoreCommands.configureStderr(value);
}
public String getSource(URI uri, int beginLine, int endLine) throws DbgpException {
return actualCoreCommands.getSource(uri, beginLine, endLine);
}
public String setLineBreakpoint(URI uri, int lineNumber, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setLineBreakpoint(uri, lineNumber, config);
}
public IDbgpStatus stepInto() throws DbgpException {
return actualCoreCommands.stepInto();
}
public Map getTypeMap() throws DbgpException {
return actualCoreCommands.getTypeMap();
}
public String setCallBreakpoint(URI uri, String function, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setCallBreakpoint(uri, function, config);
}
public IDbgpStatus stepOver() throws DbgpException {
return actualCoreCommands.stepOver();
}
public String setReturnBreakpoint(URI uri, String function, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setReturnBreakpoint(uri, function, config);
}
public String setExceptionBreakpoint(String exception, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setExceptionBreakpoint(exception, config);
}
public String setConditionalBreakpoint(URI uri, int lineNumber, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setConditionalBreakpoint(uri, lineNumber, config);
}
public IDbgpStatus stepOut() throws DbgpException {
return actualCoreCommands.stepOut();
}
public String setConditionalBreakpoint(URI uri, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setConditionalBreakpoint(uri, config);
}
public IDbgpStatus stop() throws DbgpException {
return actualCoreCommands.stop();
}
public String setWatchBreakpoint(URI uri, int line, DbgpBreakpointConfig config) throws DbgpException {
return actualCoreCommands.setWatchBreakpoint(uri, line, config);
}
public void removeBreakpoint(String id) throws DbgpException {
actualCoreCommands.removeBreakpoint(id);
}
public void updateBreakpoint(String id, DbgpBreakpointConfig config) throws DbgpException {
actualCoreCommands.updateBreakpoint(id, config);
}
public IDbgpBreakpoint getBreakpoint(String id) throws DbgpException {
return actualCoreCommands.getBreakpoint(id);
}
public IDbgpStatus detach() throws DbgpException {
return actualCoreCommands.detach();
}
public IDbgpBreakpoint[] getBreakpoints() throws DbgpException {
return actualCoreCommands.getBreakpoints();
}
public IDbgpFeature getFeature(String featureName) throws DbgpException {
return actualCoreCommands.getFeature(featureName);
}
public boolean setFeature(String featureName, String featureValue) throws DbgpException {
return actualCoreCommands.setFeature(featureName, featureValue);
}
public int getStackDepth() throws DbgpException {
return proxiedStackCommands.getStackDepth();
}
public IDbgpStackLevel[] getStackLevels() throws DbgpException {
return proxiedStackCommands.getStackLevels();
}
public IDbgpStackLevel getStackLevel(int stackDepth) throws DbgpException {
return proxiedStackCommands.getStackLevel(stackDepth);
}
public Map getContextNames(int stackDepth) throws DbgpException {
return proxiedContextCommands.getContextNames(stackDepth);
}
public IDbgpProperty[] getContextProperties(int stackDepth) throws DbgpException {
return proxiedContextCommands.getContextProperties(stackDepth);
}
public IDbgpProperty[] getContextProperties(int stackDepth, int contextId) throws DbgpException {
return proxiedContextCommands.getContextProperties(stackDepth, contextId);
}
public IDbgpProperty getPropertyByKey(String name, String key) throws DbgpException {
return proxiedPropertyCommands.getPropertyByKey(name, key);
}
public IDbgpProperty getProperty(String name) throws DbgpException {
return proxiedPropertyCommands.getProperty(name);
}
public IDbgpProperty getProperty(String name, int stackDepth) throws DbgpException {
return proxiedPropertyCommands.getProperty(name, stackDepth);
}
public IDbgpProperty getProperty(String name, int stackDepth, int contextId) throws DbgpException {
return proxiedPropertyCommands.getProperty(name, stackDepth, contextId);
}
public IDbgpProperty getProperty(int page, String name, int stackDepth) throws DbgpException {
return proxiedPropertyCommands.getProperty(page, name, stackDepth);
}
public boolean setProperty(IDbgpProperty property) throws DbgpException {
return proxiedPropertyCommands.setProperty(property);
}
public boolean setProperty(String name, int stackDepth, String value) throws DbgpException {
return proxiedPropertyCommands.setProperty(name, stackDepth, value);
}
}
/**
* @param actualSession
* @param coroutine
*/
public LuaCoroutineDbgpSession(IDbgpSession actualSession, LuaCoroutine coroutine) {
super();
this.actualSession = actualSession;
this.coroutine = coroutine;
this.proxyCoreCommands = new CoroutineCoreCommands();
}
public void bindToCoroutine(LuaCoroutine newCoroutine) {
this.coroutine = newCoroutine;
}
public IDbgpCoreCommands getCoreCommands() {
return proxyCoreCommands;
}
// ***** PROXY METHODS *****
public void addTerminationListener(IDbgpTerminationListener listener) {
actualSession.addTerminationListener(listener);
}
public IDbgpExtendedCommands getExtendedCommands() {
return actualSession.getExtendedCommands();
}
public void removeTerminationListener(IDbgpTerminationListener listener) {
actualSession.removeTerminationListener(listener);
}
public Object get(Class type) {
return actualSession.get(type);
}
public IDebugOptions getDebugOptions() {
return actualSession.getDebugOptions();
}
public void configure(IDebugOptions debugOptions) {
actualSession.configure(debugOptions);
}
public void requestTermination() {
actualSession.requestTermination();
}
public void waitTerminated() throws InterruptedException {
actualSession.waitTerminated();
}
public IDbgpSessionInfo getInfo() {
return actualSession.getInfo();
}
public IDbgpStreamManager getStreamManager() {
return actualSession.getStreamManager();
}
public IDbgpNotificationManager getNotificationManager() {
return actualSession.getNotificationManager();
}
public void addRawListener(IDbgpRawListener listener) {
actualSession.addRawListener(listener);
}
public void removeRawListenr(IDbgpRawListener listener) {
actualSession.removeRawListenr(listener);
}
public IDbgpCommunicator getCommunicator() {
return actualSession.getCommunicator();
}
}