/* * Copyright (C) 2000 - 2012 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ * $Id: CFContext.java 2374 2013-06-10 22:14:24Z alan $ */ package com.naryx.tagfusion.cfm.parser; /** * Execution context for evaluating cfscript statements and expressions. * The execution context comprises the global scope list, the local scope list, * the current function hierarchy, and the current source _line and _col. */ import java.util.Map; import java.util.Stack; import com.naryx.tagfusion.cfm.engine.cfData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; import com.naryx.tagfusion.cfm.parser.script.userDefinedFunction; public class CFContext extends cfData implements java.io.Serializable { private static final long serialVersionUID = 1L; private CFGlobalScopeInterface _globalScope; private CFCallStack _callStack; private Stack<CFCallStack> callStackStack; private int _line; private int _col; private cfSession cfsession; // This is set by every expression evaluation routine - we need it for the // "eval()" builtin public cfData _lastExpr; public CFContext(CFGlobalScopeInterface globalScope, com.naryx.tagfusion.cfm.engine.cfSession _session) { _globalScope = globalScope; _callStack = new CFCallStack(); callStackStack = new Stack<CFCallStack>(); _line = 0; _col = 0; _lastExpr = CFUndefinedValue.UNDEFINED; cfsession = _session; } public CFCallStack getCallStack() { return _callStack; } public Stack<CFCallStack> getCallStackStack() { return callStackStack; } public cfSession getSession() { return cfsession; } public void setSession( cfSession _session ) { cfsession = _session; } public void enterCustomTag() { callStackStack.push( _callStack ); _callStack = new CFCallStack(); } public void leaveCustomTag() { _callStack = callStackStack.pop(); } /** UDF specific functions **/ public boolean containsFunction( String _function ) { return ( getUDF( _function ) != null ); } public userDefinedFunction getUDF( String _function ) { try { cfData udf = null; if ( !_callStack.isEmpty() ) { if ( ( (CFCallScope) _callStack.localScope().peek() ).containsVar( _function ) ) { udf = _callStack.localScope().get( _function, this ); udf = ( (cfLData) udf ).Get( this ); } } if ( udf == null ) { udf = cfsession.getData( _function ); } if ( ( udf != null ) && ( udf instanceof userDefinedFunction ) ) return (userDefinedFunction) udf; } catch ( Exception e ) { /* * shouldn't fail, provided udf is added to the session by cfScript and * _function exists in udf */ } return null; } public void putUDF( String _functionName, userDefinedFunction _function ) { try { cfsession.setData( _functionName, _function ); // put function into variables scope } catch ( Exception e ) { /* shouldn't fail */ } } /** getting variables **/ public cfData get( String name ) throws cfmRunTimeException { return get( name, true ); } // Return an lval for the given identifier public cfData get( String name, boolean _doquerysearch ) throws cfmRunTimeException { cfData val = null; // try the local scope if ( !_callStack.isEmpty() ) { if ( _callStack.localScope().peek().containsVar( name ) ) { return _callStack.localScope().get( name, this ); } } // then try the global scope if ( val == null ) val = _globalScope.get( name, true, this, _doquerysearch ); return val; } // Return an lval for a local variable regardless of existence (used for "var" // declarations) // If there is no local scope then this is done in the outermost global scope. public cfLData getLocal( String name ) { cfLData val = null; // try the local scope try { if ( !_callStack.isEmpty() ) val = _callStack.localScope().peekFirst().get( name, true, this ); } catch ( cfmRunTimeException e ) { /* this should never occur */ } return val; } // for use by CFDUMP public Map<String, cfData> getLocalScope() { if ( !_callStack.isEmpty() ) { return _callStack.localScope().peekFirst().getScopeMap(); } return null; } public boolean containsLocal( String name ) { // try the local scope if ( !_callStack.isEmpty() ) { return _callStack.localScope().peekFirst().containsVar( name ); } return false; } public void pushCall( CFCall call ) { _callStack.push( call ); } public void popCall() { if ( !_callStack.empty() ) _callStack.pop(); } public boolean isCallEmpty() { return _callStack.isEmpty(); } public void setLineCol( int line, int col ) { _line = line; _col = col; } public int getLine() { return _line; } public int getCol() { return _col; } public String toString() { return ""; // might want to put scope print out here } public void dump( cfSession Session ) { Session.write( " " ); } }