001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.jasper.runtime;
018:
019: import java.util.HashMap;
020: import java.security.AccessController;
021: import java.security.PrivilegedAction;
022: import java.security.PrivilegedExceptionAction;
023: import java.security.PrivilegedActionException;
024: import java.lang.reflect.Method;
025: import javax.servlet.jsp.el.FunctionMapper;
026:
027: /**
028: * Maps EL functions to their Java method counterparts. Keeps the
029: * actual Method objects protected so that JSP pages can't indirectly
030: * do reflection.
031: *
032: * @author Mark Roth
033: * @author Kin-man Chung
034: */
035: public final class ProtectedFunctionMapper implements FunctionMapper {
036:
037: /**
038: * Maps "prefix:name" to java.lang.Method objects.
039: */
040: private HashMap fnmap = null;
041:
042: /**
043: * If there is only one function in the map, this is the Method for it.
044: */
045: private Method theMethod = null;
046:
047: /**
048: * Constructor has protected access.
049: */
050: private ProtectedFunctionMapper() {
051: }
052:
053: /**
054: * Generated Servlet and Tag Handler implementations call this
055: * method to retrieve an instance of the ProtectedFunctionMapper.
056: * This is necessary since generated code does not have access to
057: * create instances of classes in this package.
058: *
059: * @return A new protected function mapper.
060: */
061: public static ProtectedFunctionMapper getInstance() {
062: ProtectedFunctionMapper funcMapper;
063: if (System.getSecurityManager() != null) {
064: funcMapper = (ProtectedFunctionMapper) AccessController
065: .doPrivileged(new PrivilegedAction() {
066: public Object run() {
067: return new ProtectedFunctionMapper();
068: }
069: });
070: } else {
071: funcMapper = new ProtectedFunctionMapper();
072: }
073: funcMapper.fnmap = new java.util.HashMap();
074: return funcMapper;
075: }
076:
077: /**
078: * Stores a mapping from the given EL function prefix and name to
079: * the given Java method.
080: *
081: * @param fnQName The EL function qualified name (including prefix)
082: * @param c The class containing the Java method
083: * @param methodName The name of the Java method
084: * @param args The arguments of the Java method
085: * @throws RuntimeException if no method with the given signature
086: * could be found.
087: */
088: public void mapFunction(String fnQName, final Class c,
089: final String methodName, final Class[] args) {
090: java.lang.reflect.Method method;
091: if (System.getSecurityManager() != null) {
092: try {
093: method = (java.lang.reflect.Method) AccessController
094: .doPrivileged(new PrivilegedExceptionAction() {
095:
096: public Object run() throws Exception {
097: return c.getDeclaredMethod(methodName,
098: args);
099: }
100: });
101: } catch (PrivilegedActionException ex) {
102: throw new RuntimeException(
103: "Invalid function mapping - no such method: "
104: + ex.getException().getMessage());
105: }
106: } else {
107: try {
108: method = c.getDeclaredMethod(methodName, args);
109: } catch (NoSuchMethodException e) {
110: throw new RuntimeException(
111: "Invalid function mapping - no such method: "
112: + e.getMessage());
113: }
114: }
115:
116: this .fnmap.put(fnQName, method);
117: }
118:
119: /**
120: * Creates an instance for this class, and stores the Method for
121: * the given EL function prefix and name. This method is used for
122: * the case when there is only one function in the EL expression.
123: *
124: * @param fnQName The EL function qualified name (including prefix)
125: * @param c The class containing the Java method
126: * @param methodName The name of the Java method
127: * @param args The arguments of the Java method
128: * @throws RuntimeException if no method with the given signature
129: * could be found.
130: */
131: public static ProtectedFunctionMapper getMapForFunction(
132: String fnQName, final Class c, final String methodName,
133: final Class[] args) {
134: java.lang.reflect.Method method;
135: ProtectedFunctionMapper funcMapper;
136: if (System.getSecurityManager() != null) {
137: funcMapper = (ProtectedFunctionMapper) AccessController
138: .doPrivileged(new PrivilegedAction() {
139: public Object run() {
140: return new ProtectedFunctionMapper();
141: }
142: });
143:
144: try {
145: method = (java.lang.reflect.Method) AccessController
146: .doPrivileged(new PrivilegedExceptionAction() {
147:
148: public Object run() throws Exception {
149: return c.getDeclaredMethod(methodName,
150: args);
151: }
152: });
153: } catch (PrivilegedActionException ex) {
154: throw new RuntimeException(
155: "Invalid function mapping - no such method: "
156: + ex.getException().getMessage());
157: }
158: } else {
159: funcMapper = new ProtectedFunctionMapper();
160: try {
161: method = c.getDeclaredMethod(methodName, args);
162: } catch (NoSuchMethodException e) {
163: throw new RuntimeException(
164: "Invalid function mapping - no such method: "
165: + e.getMessage());
166: }
167: }
168: funcMapper.theMethod = method;
169: return funcMapper;
170: }
171:
172: /**
173: * Resolves the specified local name and prefix into a Java.lang.Method.
174: * Returns null if the prefix and local name are not found.
175: *
176: * @param prefix the prefix of the function
177: * @param localName the short name of the function
178: * @return the result of the method mapping. Null means no entry found.
179: **/
180: public Method resolveFunction(String prefix, String localName) {
181: if (this .fnmap != null) {
182: return (Method) this .fnmap.get(prefix + ":" + localName);
183: }
184: return theMethod;
185: }
186: }
|