package org.python.pydev.debug.model; import java.lang.ref.WeakReference; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IVariable; import org.python.pydev.debug.model.remote.GetVariableCommand; public class ContainerOfVariables { private volatile IVariable[] variables; private WeakReference<IVariablesContainerParent> parent; private volatile boolean onAskGetNewVars = true; private final static Object lock = new Object(); private volatile boolean gettingInitialVariables = false; private final VariablesLoader variablesLoader; public IVariable[] getInternalVariables() { return this.variables; } public ContainerOfVariables(IVariablesContainerParent parent, boolean addGlobalsVarible) { this.parent = new WeakReference<IVariablesContainerParent>(parent); this.variablesLoader = new VariablesLoader(this, addGlobalsVarible); } /* default */ PyVariable[] setVariables(PyVariable[] newVars) { IVariable[] oldVars = this.variables; if (newVars == oldVars) { return newVars; } IVariablesContainerParent p = this.parent.get(); if (p == null) { return newVars; } AbstractDebugTarget target = p.getTarget(); this.variables = newVars; if (!gettingInitialVariables) { if (target != null) { target.fireEvent(new DebugEvent(p, DebugEvent.CHANGE, DebugEvent.CONTENT)); } } return newVars; } public IVariable[] getVariables() throws DebugException { // System.out.println("get variables: " + super.toString() + " initial: " + this.variables); if (onAskGetNewVars) { synchronized (lock) { //double check idiom for accessing onAskGetNewVars. if (onAskGetNewVars) { gettingInitialVariables = true; try { PyVariable[] vars = variablesLoader.fetchVariables(); setVariables(vars); // Important: only set to false after variables have been set. onAskGetNewVars = false; } finally { gettingInitialVariables = false; } } } } return this.variables; } public void forceGetNewVariables() { this.onAskGetNewVars = true; IVariablesContainerParent p = this.parent.get(); if (p == null) { return; } AbstractDebugTarget target = p.getTarget(); if (target != null) { // I.e.: if we do a new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT), the selection // of the editor is redone (thus, if the user uses F2 it'd get back to the current breakpoint // location because it'd be reselected). target.fireEvent(new DebugEvent(p, DebugEvent.CHANGE, DebugEvent.UNSPECIFIED)); } } public AbstractDebugTarget getTarget() { IVariablesContainerParent p = this.parent.get(); if (p == null) { return null; } return p.getTarget(); } public IVariableLocator getLocator() { IVariablesContainerParent p = this.parent.get(); if (p == null) { return null; } return p; } public GetVariableCommand getVariableCommand(AbstractDebugTarget target) { IVariablesContainerParent p = this.parent.get(); if (p == null) { return null; } return p.getVariableCommand(target); } public IVariableLocator getGlobalLocator() { IVariablesContainerParent p = this.parent.get(); if (p == null) { return null; } return p.getGlobalLocator(); } }