File: ProtectedFunctionMapper.java

package info (click to toggle)
tomcat7 7.0.56-3%2Bdeb8u11
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 35,688 kB
  • ctags: 41,823
  • sloc: java: 249,464; xml: 51,553; jsp: 3,037; sh: 1,361; perl: 269; makefile: 195
file content (201 lines) | stat: -rw-r--r-- 7,606 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jasper.runtime;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;

import javax.servlet.jsp.el.FunctionMapper;

import org.apache.jasper.security.SecurityUtil;

/**
 * Maps EL functions to their Java method counterparts. Keeps the actual Method
 * objects protected so that JSP pages can't indirectly do reflection.
 * 
 * @author Mark Roth
 * @author Kin-man Chung
 */
public final class ProtectedFunctionMapper extends javax.el.FunctionMapper
        implements FunctionMapper {

    /**
     * Maps "prefix:name" to java.lang.Method objects.
     */
    private HashMap<String,Method> fnmap = null;

    /**
     * If there is only one function in the map, this is the Method for it.
     */
    private Method theMethod = null;

    /**
     * Constructor has protected access.
     */
    private ProtectedFunctionMapper() {
    }

    /**
     * Generated Servlet and Tag Handler implementations call this method to
     * retrieve an instance of the ProtectedFunctionMapper. This is necessary
     * since generated code does not have access to create instances of classes
     * in this package.
     * 
     * @return A new protected function mapper.
     */
    public static ProtectedFunctionMapper getInstance() {
        ProtectedFunctionMapper funcMapper;
        if (SecurityUtil.isPackageProtectionEnabled()) {
            funcMapper = AccessController.doPrivileged(
                    new PrivilegedAction<ProtectedFunctionMapper>() {
                        @Override
                        public ProtectedFunctionMapper run() {
                            return new ProtectedFunctionMapper();
                        }
                    });
        } else {
            funcMapper = new ProtectedFunctionMapper();
        }
        funcMapper.fnmap = new HashMap<String,Method>();
        return funcMapper;
    }

    /**
     * Stores a mapping from the given EL function prefix and name to the given
     * Java method.
     * 
     * @param fnQName
     *            The EL function qualified name (including prefix)
     * @param c
     *            The class containing the Java method
     * @param methodName
     *            The name of the Java method
     * @param args
     *            The arguments of the Java method
     * @throws RuntimeException
     *             if no method with the given signature could be found.
     */
    public void mapFunction(String fnQName, final Class<?> c,
            final String methodName, final Class<?>[] args) {
        java.lang.reflect.Method method;
        if (SecurityUtil.isPackageProtectionEnabled()) {
            try {
                method = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Method>() {
                            @Override
                            public Method run() throws Exception {
                                return c.getDeclaredMethod(methodName, args);
                            }
                        });
            } catch (PrivilegedActionException ex) {
                throw new RuntimeException(
                        "Invalid function mapping - no such method: "
                                + ex.getException().getMessage());
            }
        } else {
            try {
                method = c.getDeclaredMethod(methodName, args);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(
                        "Invalid function mapping - no such method: "
                                + e.getMessage());
            }
        }

        this.fnmap.put(fnQName, method);
    }

    /**
     * Creates an instance for this class, and stores the Method for the given
     * EL function prefix and name. This method is used for the case when there
     * is only one function in the EL expression.
     * 
     * @param fnQName
     *            The EL function qualified name (including prefix)
     * @param c
     *            The class containing the Java method
     * @param methodName
     *            The name of the Java method
     * @param args
     *            The arguments of the Java method
     * @throws RuntimeException
     *             if no method with the given signature could be found.
     */
    public static ProtectedFunctionMapper getMapForFunction(String fnQName,
            final Class<?> c, final String methodName, final Class<?>[] args) {
        java.lang.reflect.Method method;
        ProtectedFunctionMapper funcMapper;
        if (SecurityUtil.isPackageProtectionEnabled()) {
            funcMapper = AccessController.doPrivileged(
                    new PrivilegedAction<ProtectedFunctionMapper>() {
                        @Override
                        public ProtectedFunctionMapper run() {
                            return new ProtectedFunctionMapper();
                        }
                    });

            try {
                method = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Method>() {
                            @Override
                            public Method run() throws Exception {
                                return c.getDeclaredMethod(methodName, args);
                            }
                        });
            } catch (PrivilegedActionException ex) {
                throw new RuntimeException(
                        "Invalid function mapping - no such method: "
                                + ex.getException().getMessage());
            }
        } else {
            funcMapper = new ProtectedFunctionMapper();
            try {
                method = c.getDeclaredMethod(methodName, args);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(
                        "Invalid function mapping - no such method: "
                                + e.getMessage());
            }
        }
        funcMapper.theMethod = method;
        return funcMapper;
    }

    /**
     * Resolves the specified local name and prefix into a Java.lang.Method.
     * Returns null if the prefix and local name are not found.
     * 
     * @param prefix
     *            the prefix of the function
     * @param localName
     *            the short name of the function
     * @return the result of the method mapping. Null means no entry found.
     */
    @Override
    @Deprecated
    public Method resolveFunction(String prefix, String localName) {
        if (this.fnmap != null) {
            return this.fnmap.get(prefix + ":" + localName);
        }
        return theMethod;
    }
}