/
FacesELResolver.java
133 lines (111 loc) · 3.9 KB
/
FacesELResolver.java
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
/*
* Copyright 2019 OmniFaces
*
* Licensed 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.omnifaces.el;
import static java.beans.Introspector.decapitalize;
import static org.omnifaces.util.Utils.isOneInstanceOf;
import static org.omnifaces.util.Utils.startsWithOneOf;
import java.beans.FeatureDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.PropertyNotFoundException;
import org.omnifaces.util.Faces;
/**
* This EL resolver basically creates an implicit object <code>#{faces}</code> in EL scope.
* <p>
* All methods of {@link Faces} utility class which start with "get" or "is", and take no parameters, and return
* either <code>String</code> or <code>boolean</code>, and are not related to response nor to session or flash (for
* which already implicit EL objects <code>#{session}</code> and <code>#{flash}</code> exist), will be available as
* properties of the implicit object <code>#{faces}</code>. Examples are:
* <pre>
* #{faces.development}
* #{faces.serverInfo}
* #{faces.ajaxRequest}
* #{faces.requestBaseURL}
* #{faces.requestURLWithQueryString}
* </pre>
*
* @author Bauke Scholtz
* @see Faces
* @since 2.6
*/
public class FacesELResolver extends ELResolver {
private static final Map<String, Method> FACES_PROPERTIES = new ConcurrentHashMap<>();
static {
for (Method method : Faces.class.getDeclaredMethods()) {
if (method.getParameterTypes().length > 0 || !isOneInstanceOf(method.getReturnType(), String.class, boolean.class)) {
continue;
}
String name = method.getName();
if (startsWithOneOf(name, "get", "is")) {
String property = decapitalize(name.replaceFirst("(get|is)", ""));
if (!startsWithOneOf(property, "response", "session", "flash")) {
FACES_PROPERTIES.put(property, method);
}
}
}
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return (base == this) ? Object.class : null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
if (base == null && "faces".equals(property)) {
context.setPropertyResolved(true);
return getClass();
}
else if (base == this && property != null) {
context.setPropertyResolved(true);
return getCommonPropertyType(context, base);
}
return null;
}
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (base == null && "faces".equals(property)) {
context.setPropertyResolved(true);
return this;
}
else if (base == this && property != null) {
Method method = FACES_PROPERTIES.get(property);
if (method == null) {
throw new PropertyNotFoundException("#{faces." + property + "} does not exist.");
}
context.setPropertyResolved(true);
try {
return method.invoke(null);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
return null;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object val) {
// NOOP.
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
}