View Javadoc

1   package org.apache.velocity.runtime.parser.node;
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 java.lang.reflect.InvocationTargetException;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.velocity.exception.VelocityException;
26  import org.apache.velocity.runtime.RuntimeLogger;
27  import org.apache.velocity.runtime.log.Log;
28  import org.apache.velocity.runtime.log.RuntimeLoggerLog;
29  import org.apache.velocity.util.introspection.Introspector;
30  
31  /**
32   * Returned the value of object property when executed.
33   */
34  public class PropertyExecutor extends AbstractExecutor
35  {
36      private final Introspector introspector;
37  
38      /**
39       * @param log
40       * @param introspector
41       * @param clazz
42       * @param property
43       * @since 1.5
44       */
45      public PropertyExecutor(final Log log, final Introspector introspector,
46              final Class clazz, final String property)
47      {
48          this.log = log;
49          this.introspector = introspector;
50  
51          // Don't allow passing in the empty string or null because
52          // it will either fail with a StringIndexOutOfBounds error
53          // or the introspector will get confused.
54          if (StringUtils.isNotEmpty(property))
55          {
56              discover(clazz, property);
57          }
58      }
59  
60      /**
61       * @param r
62       * @param introspector
63       * @param clazz
64       * @param property
65       * @deprecated RuntimeLogger is deprecated. Use the other constructor.
66       */
67      public PropertyExecutor(final RuntimeLogger r, final Introspector introspector,
68              final Class clazz, final String property)
69      {
70          this(new RuntimeLoggerLog(r), introspector, clazz, property);
71      }
72  
73      /**
74       * @return The current introspector.
75       * @since 1.5
76       */
77      protected Introspector getIntrospector()
78      {
79          return this.introspector;
80      }
81  
82      /**
83       * @param clazz
84       * @param property
85       */
86      protected void discover(final Class clazz, final String property)
87      {
88          /*
89           *  this is gross and linear, but it keeps it straightforward.
90           */
91  
92          try
93          {
94              Object [] params = {};
95  
96              StringBuffer sb = new StringBuffer("get");
97              sb.append(property);
98  
99              setMethod(introspector.getMethod(clazz, sb.toString(), params));
100 
101             if (!isAlive())
102             {
103                 /*
104                  *  now the convenience, flip the 1st character
105                  */
106 
107                 char c = sb.charAt(3);
108 
109                 if (Character.isLowerCase(c))
110                 {
111                     sb.setCharAt(3, Character.toUpperCase(c));
112                 }
113                 else
114                 {
115                     sb.setCharAt(3, Character.toLowerCase(c));
116                 }
117 
118                 setMethod(introspector.getMethod(clazz, sb.toString(), params));
119             }
120         }
121         /**
122          * pass through application level runtime exceptions
123          */
124         catch( RuntimeException e )
125         {
126             throw e;
127         }
128         catch(Exception e)
129         {
130             String msg = "Exception while looking for property getter for '" + property;
131             log.error(msg, e);
132             throw new VelocityException(msg, e);
133         }
134     }
135 
136     /**
137      * @see org.apache.velocity.runtime.parser.node.AbstractExecutor#execute(java.lang.Object)
138      */
139     public Object execute(Object o)
140         throws IllegalAccessException,  InvocationTargetException
141     {
142         return isAlive() ? getMethod().invoke(o, ((Object []) null)) : null;
143     }
144 }