001 package org.apache.commons.ognl; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import org.apache.commons.ognl.enhance.ExpressionCompiler; 023 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler; 024 import org.apache.commons.ognl.enhance.UnsupportedCompilationException; 025 026 import java.lang.reflect.Method; 027 028 /** 029 * $Id: ASTStaticMethod.java 1194869 2011-10-29 11:10:16Z mcucchiara $ 030 * 031 * @author Luke Blanshard (blanshlu@netscape.net) 032 * @author Drew Davidson (drew@ognl.org) 033 */ 034 public class ASTStaticMethod 035 extends SimpleNode 036 implements NodeType 037 { 038 039 private String className; 040 041 private String methodName; 042 043 private Class getterClass; 044 045 public ASTStaticMethod( int id ) 046 { 047 super( id ); 048 } 049 050 public ASTStaticMethod( OgnlParser p, int id ) 051 { 052 super( p, id ); 053 } 054 055 /** 056 * Called from parser action. 057 */ 058 void init( String className, String methodName ) 059 { 060 this.className = className; 061 this.methodName = methodName; 062 } 063 064 protected Object getValueBody( OgnlContext context, Object source ) 065 throws OgnlException 066 { 067 ObjectArrayPool objectArrayPool = OgnlRuntime.getObjectArrayPool(); 068 Object[] args = objectArrayPool.create( jjtGetNumChildren() ); 069 Object root = context.getRoot(); 070 071 try 072 { 073 for ( int i = 0, icount = args.length; i < icount; ++i ) 074 { 075 args[i] = children[i].getValue( context, root ); 076 } 077 078 return OgnlRuntime.callStaticMethod( context, className, methodName, args ); 079 } 080 finally 081 { 082 objectArrayPool.recycle( args ); 083 } 084 } 085 086 public Class getGetterClass() 087 { 088 return getterClass; 089 } 090 091 public Class getSetterClass() 092 { 093 return getterClass; 094 } 095 096 public String toGetSourceString( OgnlContext context, Object target ) 097 { 098 String result = className + "#" + methodName + "("; 099 100 try 101 { 102 Class clazz = OgnlRuntime.classForName( context, className ); 103 Method m = OgnlRuntime.getMethod( context, clazz, methodName, children, true ); 104 105 if ( clazz == null || m == null ) 106 { 107 throw new UnsupportedCompilationException( 108 "Unable to find class/method combo " + className + " / " + methodName ); 109 } 110 111 if ( !context.getMemberAccess().isAccessible( context, clazz, m, methodName ) ) 112 { 113 throw new UnsupportedCompilationException( 114 "Method is not accessible, check your jvm runtime security settings. " + "For static class method " 115 + className + " / " + methodName ); 116 } 117 118 OgnlExpressionCompiler compiler = OgnlRuntime.getCompiler( context ); 119 if ( ( children != null ) && ( children.length > 0 ) ) 120 { 121 Class[] parms = m.getParameterTypes(); 122 123 for ( int i = 0; i < children.length; i++ ) 124 { 125 if ( i > 0 ) 126 { 127 result = result + ", "; 128 } 129 130 Class prevType = context.getCurrentType(); 131 132 Node child = children[i]; 133 Object root = context.getRoot(); 134 135 String parmString = ASTMethodUtil.getParmString( context, root, child, prevType ); 136 137 Class valueClass = ASTMethodUtil.getValueClass( context, root, child ); 138 139 if ( valueClass != parms[i] ) 140 { 141 if ( parms[i].isArray() ) 142 { 143 parmString = compiler.createLocalReference( context, "(" + ExpressionCompiler.getCastString( 144 parms[i] ) + ")org.apache.commons.ognl.OgnlOps.toArray(" + parmString + ", " 145 + parms[i].getComponentType().getName() + ".class, true)", parms[i] ); 146 147 } 148 else if ( parms[i].isPrimitive() ) 149 { 150 Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass( parms[i] ); 151 152 parmString = compiler.createLocalReference( context, "((" + wrapClass.getName() 153 + ")org.apache.commons.ognl.OgnlOps.convertValue(" + parmString + "," 154 + wrapClass.getName() + ".class, true))." + OgnlRuntime.getNumericValueGetter( 155 wrapClass ), parms[i] ); 156 157 } 158 else if ( parms[i] != Object.class ) 159 { 160 parmString = compiler.createLocalReference( context, "(" + parms[i].getName() 161 + ")org.apache.commons.ognl.OgnlOps.convertValue(" + parmString + "," 162 + parms[i].getName() + ".class)", parms[i] ); 163 } 164 else if ( ( NodeType.class.isInstance( child ) && ( (NodeType) child ).getGetterClass() != null 165 && Number.class.isAssignableFrom( ( (NodeType) child ).getGetterClass() ) ) 166 || valueClass.isPrimitive() ) 167 { 168 parmString = " ($w) " + parmString; 169 } 170 else if ( valueClass.isPrimitive() ) 171 { 172 parmString = "($w) " + parmString; 173 } 174 } 175 176 result += parmString; 177 } 178 } 179 180 result += ")"; 181 182 try 183 { 184 Object contextObj = getValueBody( context, target ); 185 context.setCurrentObject( contextObj ); 186 } 187 catch ( Throwable t ) 188 { 189 // ignore 190 } 191 192 if ( m != null ) 193 { 194 getterClass = m.getReturnType(); 195 196 context.setCurrentType( m.getReturnType() ); 197 context.setCurrentAccessor( compiler.getSuperOrInterfaceClass( m, m.getDeclaringClass() ) ); 198 } 199 200 } 201 catch ( Throwable t ) 202 { 203 throw OgnlOps.castToRuntime( t ); 204 } 205 206 return result; 207 } 208 209 public String toSetSourceString( OgnlContext context, Object target ) 210 { 211 return toGetSourceString( context, target ); 212 } 213 214 public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data ) 215 throws OgnlException 216 { 217 return visitor.visit( this, data ); 218 } 219 220 /** 221 * Get the class name for this method. 222 * 223 * @return the class name. 224 * @since 4.0 225 */ 226 public String getClassName() 227 { 228 return className; 229 } 230 231 /** 232 * Get the method name for this method. 233 * 234 * @return the method name. 235 * @since 4.0 236 */ 237 public String getMethodName() 238 { 239 return methodName; 240 } 241 }