in src/main/java/org/apache/commons/ognl/ASTProperty.java [385:617]
public String toSetSourceString( OgnlContext context, Object target )
{
String result = "";
Method m = null;
if ( context.getCurrentObject() == null )
{
throw new UnsupportedCompilationException( "Current target is null." );
}
/*
* System.out.println("astproperty(setter) is indexed? : " + isIndexedAccess() + " child: " +
* _children[0].getClass().getName() + " target: " + target.getClass().getName() + " children length: " +
* _children.length);
*/
try
{
Node child = children[0];
if ( isIndexedAccess() )
{
Object value = child.getValue( context, context.getRoot() );
if ( value == null )
{
throw new UnsupportedCompilationException(
"Value passed as indexed property is null, can't enhance statement to bytecode." );
}
String srcString = getSourceString( context, child );
// System.out.println("astproperty setter using indexed value " + value + " and srcString: " +
// srcString);
if ( context.get( "_indexedMethod" ) == null ) {
PropertyAccessor propertyAccessor = OgnlRuntime.getPropertyAccessor( target.getClass() );
Object currentObject = context.getCurrentObject();
if ( child instanceof ASTConst && currentObject instanceof Number)
{
context.setCurrentType( OgnlRuntime.getPrimitiveWrapperClass( currentObject.getClass() ) );
}
Object indexValue = propertyAccessor.getProperty( context, target, value );
result = lastChild( context )
? propertyAccessor.getSourceSetter( context, target, srcString )
: propertyAccessor.getSourceAccessor( context, target, srcString );
/*
* System.out.println("ASTProperty using propertyaccessor and isLastChild? " + lastChild(context) +
* " generated source of: " + result + " using accessor class: " + p.getClass().getName());
*/
// result = p.getSourceAccessor(context, target, srcString);
getterClass = context.getCurrentType();
context.setCurrentObject( indexValue );
/*
* PropertyAccessor p = OgnlRuntime.getPropertyAccessor(target.getClass()); if
* (ASTConst.class.isInstance(_children[0]) && Number.class.isInstance(context.getCurrentObject()))
* {
* context.setCurrentType(OgnlRuntime.getPrimitiveWrapperClass(context.getCurrentObject().getClass(
* ))); } result = p.getSourceSetter(context, target, srcString); context.setCurrentObject(value);
* context.setCurrentType(getterClass);
*/
return result;
}
m = (Method) context.remove( "_indexedMethod" );
PropertyDescriptor pd = (PropertyDescriptor) context.remove( "_indexedDescriptor" );
boolean lastChild = lastChild( context );
if ( lastChild )
{
m = getIndexedWriteMethod( pd );
if ( m == null )
{
throw new UnsupportedCompilationException(
"Indexed property has no corresponding write method." );
}
}
setterClass = m.getParameterTypes()[0];
Object indexedValue = null;
if ( !lastChild )
{
indexedValue = OgnlRuntime.callMethod( context, target, m.getName(), new Object[]{ value } );
}
context.setCurrentType( setterClass );
context.setCurrentAccessor(
OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
if ( !lastChild )
{
context.setCurrentObject( indexedValue );
return "." + m.getName() + "(" + srcString + ")";
}
return "." + m.getName() + "(" + srcString + ", $3)";
}
String name = ( (ASTConst) child ).getValue().toString();
// System.out.println(" astprop(setter) : trying to set " + name + " on object target " +
// context.getCurrentObject().getClass().getName());
target = getTarget( context, target, name );
PropertyDescriptor pd = OgnlRuntime.getPropertyDescriptor(
OgnlRuntime.getCompiler( context ).getInterfaceClass( context.getCurrentObject().getClass() ), name );
if ( pd != null )
{
Method pdMethod = lastChild( context ) ? pd.getWriteMethod() : pd.getReadMethod();
if ( pdMethod != null && !context.getMemberAccess().isAccessible( context, context.getCurrentObject(),
pdMethod, name ) )
{
throw new UnsupportedCompilationException(
"Member access forbidden for property " + name + " on class "
+ context.getCurrentObject().getClass() );
}
}
if ( pd != null && this.getIndexedPropertyType( context, context.getCurrentObject() ) > 0 )
{
// if an indexed method accessor need to use special property descriptors to find methods
if ( pd instanceof IndexedPropertyDescriptor )
{
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
m = lastChild( context ) ? ipd.getIndexedWriteMethod() : ipd.getIndexedReadMethod();
}
else
{
if ( !(pd instanceof ObjectIndexedPropertyDescriptor) ) {
throw new OgnlException( "property '" + name + "' is not an indexed property" );
}
ObjectIndexedPropertyDescriptor opd = (ObjectIndexedPropertyDescriptor) pd;
m = lastChild( context ) ? opd.getIndexedWriteMethod() : opd.getIndexedReadMethod();
}
if ( parent == null )
{
// the above pd will be the wrong result sometimes, such as methods like getValue(int) vs String[]
// getValue()
m = OgnlRuntime.getWriteMethod( context.getCurrentObject().getClass(), name );
Class parm = m.getParameterTypes()[0];
String cast = parm.isArray() ? ExpressionCompiler.getCastString( parm ) : parm.getName();
result = m.getName() + "((" + cast + ")$3)";
setterClass = parm;
}
else
{
context.put( "_indexedMethod", m );
context.put( "_indexedDescriptor", pd );
}
}
else
{
PropertyAccessor pa = OgnlRuntime.getPropertyAccessor( context.getCurrentObject().getClass() );
/*
* System.out.println("astproperty trying to set " + name + " on object target: " +
* context.getCurrentObject().getClass().getName() + " using propertyaccessor type: " + pa);
*/
if ( target != null )
{
setterClass = target.getClass();
}
if ( parent != null && pd != null && pa == null )
{
m = pd.getReadMethod();
result = m.getName() + "()";
}
else
{
if ( context.getCurrentObject().getClass().isArray() )
{
result = "";
}
else if ( pa != null )
{
Object currObj = context.getCurrentObject();
// Class currType = context.getCurrentType();
// Class prevType = context.getPreviousType();
String srcString = child.toGetSourceString( context, context.getRoot() );
if ( child instanceof ASTConst && context.getCurrentObject() instanceof String)
{
srcString = "\"" + srcString + "\"";
}
context.setCurrentObject( currObj );
// context.setCurrentType(currType);
// context.setPreviousType(prevType);
if ( !lastChild( context ) )
{
result = pa.getSourceAccessor( context, context.getCurrentObject(), srcString );
}
else
{
result = pa.getSourceSetter( context, context.getCurrentObject(), srcString );
}
getterClass = context.getCurrentType();
}
}
}
}
catch ( Throwable t )
{
throw OgnlOps.castToRuntime( t );
}
context.setCurrentObject( target );
if ( m != null )
{
context.setCurrentType( m.getReturnType() );
context.setCurrentAccessor(
OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
}
return result;
}