gt: 		return invokeMethod( methodName, args, _context.getSession() );
context: /*
   *  Copyright (C) 2000 - 2008 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/
   */
  
  package com.naryx.tagfusion.cfm.engine;
  
  import java.io.Serializable;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Field;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.math.BigDecimal;
  import java.util.ArrayList;
  import java.util.List;
  
  import com.allaire.cfx.cfmlPage;
  import com.naryx.tagfusion.cfm.parser.CFContext;
  import com.naryx.tagfusion.cfm.tag.tagUtils;
  import com.naryx.tagfusion.cfx.cfmlPageContextImpl;
  import com.naryx.tagfusion.expression.function.xml.xmlFormat;
  import com.naryx.tagfusion.util.InstanceTrackingPrintWriter;
  
  /**
   * This class acts as a wrapper to a Java class accessed via CFObject.
   * The instance of the Java class isn't actually created until a method or
   * field is accessed thru' getData().
   *
   * Note that when a field is requested, what is returned is a cfJavaObjectFieldData
   * instance which is basically an indirect reference to the object field allowing
   * for the getting and setting of the value.
   *
   * There is no requirement for the setData methods to be implemented.
   *
   * The internal data objects have been marked tranisent for the purposes of caching
   * queries to disk.
   */
  
  
  public class cfJavaObjectData extends cfData implements java.io.Serializable {
  
  	static final long serialVersionUID = 1;
  
  	private static final javolution.util.FastSet<Class<?>> numericClassSet = new javolution.util.FastSet<Class<?>>( 11 );
  
  	static {
  		numericClassSet.add( Integer.class );
  		numericClassSet.add( int.class );
  		numericClassSet.add( Double.class );
  		numericClassSet.add( double.class );
  		numericClassSet.add( Float.class );
  		numericClassSet.add( float.class );
  		numericClassSet.add( Short.class );
  		numericClassSet.add( short.class );
  		numericClassSet.add( Long.class );
  		numericClassSet.add( long.class );
  		numericClassSet.add( Number.class );
  	}
  
  	transient protected Object instance;
  
  	/**
  	 * For performance reasons we're not going to look up the Class until we
  	 * actually need it. Therefore, never read the instanceClass attribute
  	 * directly, but always indirectly via the getInstanceClass() method.
  	 */
  	transient private Class<?> instanceClass;
  	transient private cfSession parentSession;		//--[ This is for the cfmlPageContext
  	transient private cfmlPageContextImpl thisPageContext;		//--[ This is for the cfmlPageContext
  
  	public cfJavaObjectData(Object _obj){
  		instance = _obj;
  	}// cfJavaObjectData()
  
  	public cfJavaObjectData( cfSession _session, Class<?> _class ){
  		instanceClass = _class;
  		parentSession = _session;
  	}// cfJavaObjectData()
  
  	// subclasses using this constructor MUST also invoke setInstance()
  	protected cfJavaObjectData(){
  		super();
  	}
  
  
  	public String getString() throws dataNotSupportedException {
  		if ( getDataType() == cfData.CFJAVAOBJECTDATA ){
  			try{
  				return getInstance().toString();
  			}catch( cfmRunTimeException e ){
  				throw new dataNotSupportedException( "Failed to instantiate object: " + e.getMessage() );
  			}
  		}
  		return super.getString();
  	}
  
  	public byte getDataType(){ return cfData.CFJAVAOBJECTDATA; }
  	public String getDataTypeName() { return "java object"; }
  
  	public Object getInstance() throws cfmRunTimeException {
  		if ( instance == null ) {
  			createInstance();
  		}
  		return instance;
  	}// getInstance()
  
  	public Object getUnderlyingInstance()
  	{
  		// Yes, even if it's null
  		return instance;
  	}
  
  	protected void setInstance(Object _inst){
  		instance = _inst;
  		instanceClass = null;
  	}// setInstance()
  
  	/**
  	 * For performance reasons we're not going to look up the Class until we
  	 * actually need it. Therefore, never read the instanceClass attribute
  	 * directly, but always indirectly via the getInstanceClass() method.
  	 */
  	public Class<?> getInstanceClass()
  	{
  		if ((instanceClass == null) && (instance != null))
  		{
  			instanceClass = instance.getClass();
  		}
  		return instanceClass;
  	}
  
  	public String getInstanceClassName()
  	{
  		Class<?> cls = getInstanceClass();
  		if (cls != null)
  			return cls.getName();
  		else if (instance != null)
  			return instance.getClass().getName();
  		else
  			return null;
  	}
  
  	public cfData getJavaData( cfData _field ) throws cfmRunTimeException{
  		if ( ( _field != null ) && ( _field.getDataType() == cfData.CFSTRINGDATA ) ) {
  			return getJavaData( ( (cfStringData) _field ).getString() );
  		}else{
  			throw new cfmRunTimeException( catchDataFactory.generalException( cfCatchData.TYPE_OBJECT,
  																																					"errorCode.runtimeError",
  																																				 	"cfdata.javaInvalidClass",
  																																				 	null ));
  		}
  
  	}// getData()
  
  
  	/**
  	 * Returns the field named '_field' performing a case-insensitive match
  	 */
  	private Field getField(Class<?> cls, String _field ) {
  		// we could attempt to do case sensitive match first with Class.getField( String )
  		// but the likely overhead of a created NoSuchFieldException is not worth it
  		Field [] allFields = cls.getFields();
  
  		for ( int i = 0; i < allFields.length; i++ ){
  			if ( allFields[i].getName().equalsIgnoreCase( _field ) ){
  				return allFields[i];
  			}
  		}
  		return null;
  	}
  
  
  
  	public cfData getJavaData( String _Field ) throws cfmRunTimeException{
  		Class<?> cls = getInstanceClass();
  
  		Exception exception = null;
  		try {
  			Field theField = getField(cls, _Field );
  			if ( theField != null ){
  
  				cfData converted = convertToCfData( theField );
  				return converted;
  			}
  		}catch( SecurityException e3 ){
  			exception = e3;
  		}
  
  
  		// either an exception was thrown or the field wasn't found
  		cfData fieldAsMethod = getFieldMethod(cls, _Field );
  		if ( fieldAsMethod != null ){
  			return fieldAsMethod;
  		}
  
  		if ( exception == null ){
  			exception = new NoSuchFieldException( _Field );
  		}
  
  		throw new cfmRunTimeException( catchDataFactory.javaMethodException( "errorCode.javaException",
  				exception.getClass().getName(), exception.getMessage(), exception));
  
  
  	}// getData()
  
    private cfData getFieldMethod(Class<?> cls, String _field ) {
      Method getMethod = null;
      Method setMethod = null;
  
      Method [] allMethods = cls.getMethods();
      String getMethName1 = "get" + _field;
      String getMethName3 = "is" + _field;
      List<Method> getMethods = new ArrayList<Method>();
  
      String setMethName1 = "set" + _field;
      List<Method> setMethods = new ArrayList<Method>();
  
      for ( int i = 0; i < allMethods.length; i++ ){
        String methName = allMethods[i].getName();
  			if ( ( getMethName1.equalsIgnoreCase( methName ) || 
  					getMethName3.equalsIgnoreCase( methName ) ) && 
  					allMethods[i].getParameterTypes().length == 0 )
  			{
  				getMethods.add( 0, allMethods[i] );
  			}
  			else if ( setMethName1.equalsIgnoreCase( methName ) && 
  					allMethods[i].getParameterTypes().length == 1 )
  			{
  				setMethods.add( 0, allMethods[i] );
  			}
  		}
  		
  		if ( getMethods.size() != 0 ){
  			getMethod = getMethods.get(0);
  		}
  		
  		if ( setMethods.size() != 0 ){
  			setMethod = setMethods.get(0);
  		}
  
  		if ( getMethod == null && setMethod == null ){
  			return null;
  		}
  
  		return new com.naryx.tagfusion.cfm.parser.cfJavaObjectFieldData( this, _field, getMethod, setMethod );
  	}
  
  	
  	public cfData getJavaData( javaMethodDataInterface _method, CFContext _context ) throws cfmRunTimeException{
  		String methodName = _method.getFunctionName();
  		List<cfData> args = _method.getEvaluatedArguments( _context, false );
  
  		if ( methodName.toLowerCase().equals( "init" ) ){
  			// bug #2359: if the instance already exists, see if there's an "init" method
  			if ( instance != null ){
  				try{
  					return invokeMethod( methodName, args, _context.getSession() );
  				}catch ( cfmRunTimeException ignore ) {} // failed to invoke "init" method, try constructor
  			}
  			
  			// handle init
  			if ( args.size() == 0 ){
  				createInstance();
  			}else{
  				createInstance( args, _context.getSession() );
  			}
  			return tagUtils.convertToCfData( instance );
  		}
  