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 }