/*******************************************************************************
* Copyright (c) 2000, 2008 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
* Alena Laskavaia (QNX) - Bug 221224
*******************************************************************************/
package org.eclipse.cdt.debug.mi.core.cdi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.model.ICDIExpression;
import org.eclipse.cdt.debug.core.cdi.model.ICDIVariable;
import org.eclipse.cdt.debug.mi.core.MIException;
import org.eclipse.cdt.debug.mi.core.MISession;
import org.eclipse.cdt.debug.mi.core.cdi.model.Expression;
import org.eclipse.cdt.debug.mi.core.cdi.model.LocalVariable;
import org.eclipse.cdt.debug.mi.core.cdi.model.StackFrame;
import org.eclipse.cdt.debug.mi.core.cdi.model.Target;
import org.eclipse.cdt.debug.mi.core.cdi.model.Thread;
import org.eclipse.cdt.debug.mi.core.cdi.model.Variable;
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
import org.eclipse.cdt.debug.mi.core.command.MIVarCreate;
import org.eclipse.cdt.debug.mi.core.command.MIVarDelete;
import org.eclipse.cdt.debug.mi.core.command.MIVarUpdate;
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
import org.eclipse.cdt.debug.mi.core.event.MIVarChangedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIVarDeletedEvent;
import org.eclipse.cdt.debug.mi.core.output.MIVar;
import org.eclipse.cdt.debug.mi.core.output.MIVarChange;
import org.eclipse.cdt.debug.mi.core.output.MIVarCreateInfo;
import org.eclipse.cdt.debug.mi.core.output.MIVarUpdateInfo;
/**
*/
public class ExpressionManager extends Manager {
final static ICDIExpression[] EMPTY_EXPRESSIONS = {};
Map expMap;
Map varMap;
MIVarChange[] noChanges = new MIVarChange[0];
public ExpressionManager(Session session) {
super(session, true);
expMap = new Hashtable();
varMap = new Hashtable();
}
synchronized List getExpressionList(Target target) {
List expList = (List)expMap.get(target);
if (expList == null) {
expList = Collections.synchronizedList(new ArrayList());
expMap.put(target, expList);
}
return expList;
}
synchronized List getVariableList(Target target) {
List varList = (List)varMap.get(target);
if (varList == null) {
varList = Collections.synchronizedList(new ArrayList());
varMap.put(target, varList);
}
return varList;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIExpressionManager#createExpression(String)
*/
public ICDIExpression createExpression(Target target, String name) throws CDIException {
Expression expression = new Expression(target, name);
List exprList = getExpressionList(target);
exprList.add(expression);
return expression;
}
public ICDIExpression[] getExpressions(Target target) throws CDIException {
List expList = (List) expMap.get(target);
if (expList != null) {
return (ICDIExpression[])expList.toArray(EMPTY_EXPRESSIONS);
}
return EMPTY_EXPRESSIONS;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIExpressionManager#removeExpression(ICDIExpression)
*/
public void destroyExpressions(Target target, ICDIExpression[] expressions) throws CDIException {
List expList = getExpressionList(target);
for (int i = 0; i < expressions.length; ++i) {
expList.remove(expressions[i]);
}
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIExpressionManager#removeExpression(ICDIExpression)
*/
public void destroyAllExpressions(Target target) throws CDIException {
ICDIExpression[] expressions = getExpressions(target);
destroyExpressions(target, expressions);
}
public void update(Target target) throws CDIException {
// deleteAllVariables(target);
List eventList = new ArrayList();
MISession mi = target.getMISession();
CommandFactory factory = mi.getCommandFactory();
List varList = getVariableList(target);
Variable[] variables = (Variable[]) varList.toArray(new Variable[varList.size()]);
for (int i = 0; i < variables.length; i++) {
Variable variable = variables[i];
String varName = variable.getMIVar().getVarName();
MIVarChange[] changes = noChanges;
MIVarUpdate update = factory.createMIVarUpdate(varName);
MIVarUpdateInfo info = null;
try {
mi.postCommand(update);
} catch (MIException e) {
throw new MI2CDIException(e);
}
boolean timedout = false;
try {
info = update.getMIVarUpdateInfo();
if (info == null) {
timedout = true;
throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$
}
changes = info.getMIVarChanges();
} catch (MIException e) {
if (timedout) {
throw new MI2CDIException(e);
}
eventList.add(new MIVarDeletedEvent(mi, varName));
}
for (int j = 0; j < changes.length; j++) {
String n = changes[j].getVarName();
if (changes[j].isInScope()) {
eventList.add(new MIVarChangedEvent(mi, n));
} else {
deleteVariable(variable);
eventList.add(new MIVarDeletedEvent(mi, n));
}
}
}
MIEvent[] events = (MIEvent[]) eventList.toArray(new MIEvent[0]);
mi.fireEvents(events);
}
/**
* @param miSession
* @param varName
* @return
*/
public Variable getVariable(MISession miSession, String varName) {
Session session = (Session)getSession();
Target target = session.getTarget(miSession);
List varList = getVariableList(target);
Variable[] vars = (Variable[])varList.toArray(new Variable[0]);
for (int i = 0; i < vars.length; i++) {
try {
if (vars[i].getMIVar().getVarName().equals(varName)) {
return vars[i];
}
Variable v = vars[i].getChild(varName);
if (v != null) {
return v;
}
} catch (CDIException e) {
// ignore
}
}
return null;
}
public Variable createVariable(StackFrame frame, String code) throws CDIException {
Target target = (Target)frame.getTarget();
Thread currentThread = (Thread)target.getCurrentThread();
StackFrame currentFrame = currentThread.getCurrentStackFrame();
synchronized(target.getLock()) {
try {
target.setCurrentThread(frame.getThread(), false);
((Thread)frame.getThread()).setCurrentStackFrame(frame, false);
MISession mi = target.getMISession();
CommandFactory factory = mi.getCommandFactory();
MIVarCreate var = factory.createMIVarCreate(code);
mi.postCommand(var);
MIVarCreateInfo info = var.getMIVarCreateInfo();
if (info == null) {
throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$
}
Variable variable = new LocalVariable(target, null, frame, code, null, 0, 0, info.getMIVar());
List varList = getVariableList(target);
varList.add(variable);
return variable;
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
target.setCurrentThread(currentThread, false);
currentThread.setCurrentStackFrame(currentFrame, false);
}
}
}
/**
* Remove variable form the maintained cache list.
* @param miSession
* @param varName
* @return
*/
public Variable removeVariableFromList(MISession miSession, String varName) {
Variable var = getVariable(miSession, varName);
if (var != null) {
Target target = ((Session)getSession()).getTarget(miSession);
List varList = getVariableList(target);
varList.remove(var);
return var;
}
return null;
}
public void deleteAllVariables(Target target) throws CDIException {
List varList = getVariableList(target);
Variable[] variables = (Variable[]) varList.toArray(new Variable[varList.size()]);
for (int i = 0; i < variables.length; ++i) {
deleteVariable(variables[i]);
}
}
/**
* Get rid of the underlying variable.
*/
public void deleteVariable(Variable variable) throws CDIException {
Target target = (Target)variable.getTarget();
MISession miSession = target.getMISession();
MIVar miVar = variable.getMIVar();
//remove the underlying var-object now.
CommandFactory factory = miSession.getCommandFactory();
MIVarDelete var = factory.createMIVarDelete(miVar.getVarName());
try {
miSession.postCommand(var);
var.getMIInfo();
} catch (MIException e) {
//throw new MI2CDIException(e);
}
List varList = getVariableList(target);
varList.remove(variable);
// remove any children
ICDIVariable[] children = variable.children;
if (children != null) {
for (int i = 0; i < children.length; ++i) {
if (children[0] instanceof Variable) {
Variable child = (Variable)children[i];
MIVarDeletedEvent event = new MIVarDeletedEvent(miSession, child.getMIVar().getVarName());
miSession.fireEvent(event);
}
}
}
miSession.fireEvent(new MIVarDeletedEvent(miSession, variable.getMIVar().getVarName()));
}
}