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