View Javadoc

1   package org.apache.commons.ognl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.commons.ognl.enhance.ExpressionCompiler;
23  import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
24  import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
25  
26  import java.lang.reflect.Method;
27  
28  /**
29   * $Id: ASTStaticMethod.java 1194869 2011-10-29 11:10:16Z mcucchiara $
30   *
31   * @author Luke Blanshard (blanshlu@netscape.net)
32   * @author Drew Davidson (drew@ognl.org)
33   */
34  public class ASTStaticMethod
35      extends SimpleNode
36      implements NodeType
37  {
38  
39      private String className;
40  
41      private String methodName;
42  
43      private Class getterClass;
44  
45      public ASTStaticMethod( int id )
46      {
47          super( id );
48      }
49  
50      public ASTStaticMethod( OgnlParser p, int id )
51      {
52          super( p, id );
53      }
54  
55      /**
56       * Called from parser action.
57       */
58      void init( String className, String methodName )
59      {
60          this.className = className;
61          this.methodName = methodName;
62      }
63  
64      protected Object getValueBody( OgnlContext context, Object source )
65          throws OgnlException
66      {
67          ObjectArrayPool objectArrayPool = OgnlRuntime.getObjectArrayPool();
68          Object[] args = objectArrayPool.create( jjtGetNumChildren() );
69          Object root = context.getRoot();
70  
71          try
72          {
73              for ( int i = 0, icount = args.length; i < icount; ++i )
74              {
75                  args[i] = children[i].getValue( context, root );
76              }
77  
78              return OgnlRuntime.callStaticMethod( context, className, methodName, args );
79          }
80          finally
81          {
82              objectArrayPool.recycle( args );
83          }
84      }
85  
86      public Class getGetterClass()
87      {
88          return getterClass;
89      }
90  
91      public Class getSetterClass()
92      {
93          return getterClass;
94      }
95  
96      public String toGetSourceString( OgnlContext context, Object target )
97      {
98          String result = className + "#" + methodName + "(";
99  
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 }