1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.view.facelets.el;
20
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import javax.el.ELException;
25 import javax.el.ValueExpression;
26 import javax.el.VariableMapper;
27 import javax.faces.FacesWrapper;
28
29 /**
30 * Utility class for wrapping another VariableMapper with a new context, represented by a {@link java.util.Map Map}.
31 * Modifications occur to the Map instance, but resolve against the wrapped VariableMapper if the Map doesn't contain
32 * the ValueExpression requested.
33 *
34 * @author Jacob Hookom
35 * @version $Id$
36 */
37 public final class VariableMapperWrapper extends VariableMapperBase implements FacesWrapper<VariableMapper>
38 {
39
40 private final VariableMapper _target;
41
42 private final VariableMapperBase _targetBase;
43
44 private Map<String, ValueExpression> _vars;
45
46 //private final boolean _checkTargetBase;
47
48 public boolean _trackResolveVariables;
49
50 public boolean _variableResolved;
51
52 /**
53 *
54 */
55 public VariableMapperWrapper(VariableMapper orig)
56 {
57 super();
58 _target = orig;
59 _targetBase = (orig instanceof VariableMapperBase) ? (VariableMapperBase) orig : null;
60 //_checkTargetBase = true;
61 _trackResolveVariables = false;
62 _variableResolved = false;
63 }
64
65 /**
66 * First tries to resolve agains the inner Map, then the wrapped ValueExpression.
67 *
68 * @see javax.el.VariableMapper#resolveVariable(java.lang.String)
69 */
70 public ValueExpression resolveVariable(String variable)
71 {
72 ValueExpression ve = null;
73 try
74 {
75 if (_vars != null)
76 {
77 ve = (ValueExpression) _vars.get(variable);
78
79 // Is this code in a block that wants to cache
80 // the resulting expression(s) and variable has been resolved?
81 if (_trackResolveVariables && ve != null)
82 {
83 _variableResolved = true;
84 }
85 }
86
87 if (ve == null)
88 {
89 return _target.resolveVariable(variable);
90 }
91
92 return ve;
93 }
94 catch (StackOverflowError e)
95 {
96 throw new ELException("Could not Resolve Variable [Overflow]: " + variable, e);
97 }
98 }
99
100 /**
101 * Set the ValueExpression on the inner Map instance.
102 *
103 * @see javax.el.VariableMapper#setVariable(java.lang.String, javax.el.ValueExpression)
104 */
105 public ValueExpression setVariable(String variable, ValueExpression expression)
106 {
107 if (_vars == null)
108 {
109 _vars = new HashMap<String, ValueExpression>();
110 }
111
112 return _vars.put(variable, expression);
113 }
114
115 @Override
116 public boolean isAnyFaceletsVariableResolved()
117 {
118 if (_trackResolveVariables)
119 {
120 if (_variableResolved)
121 {
122 //Force EL creation!
123 return true;
124 }
125 else
126 {
127 //Otherwise check parent variable mapper
128 //if (_checkTargetBase)
129 //{
130 if (_targetBase != null)
131 {
132 return _targetBase.isAnyFaceletsVariableResolved();
133 }
134 else
135 {
136 // Another VariableMapper not extending from the base one was used.
137 // (that's the reason why _targetBase is null).
138 // It is not possible to be sure the EL expression could use that mapper,
139 // so return true to force EL expression creation.
140 return true;
141 }
142 //}
143 //else
144 //{
145 // If no check for targetBase is required, we are in a context that suppose there will not
146 // be variables resolved that could affect the expressions. So return false, indicating
147 // the resulting expression can be cached.
148 //return false;
149 //}
150 }
151 }
152 else
153 {
154 // Force expression creation, because the call is outside caching block.
155 return true;
156 }
157 }
158
159 public VariableMapper getWrapped()
160 {
161 return _target;
162 }
163
164 @Override
165 public void beforeConstructELExpression()
166 {
167 _trackResolveVariables = true;
168 _variableResolved = false;
169 //if (_checkTargetBase && _targetBase != null)
170 if (_targetBase != null)
171 {
172 _targetBase.beforeConstructELExpression();
173 }
174 }
175
176 @Override
177 public void afterConstructELExpression()
178 {
179 //if (_checkTargetBase && _targetBase != null)
180 if (_targetBase != null)
181 {
182 _targetBase.afterConstructELExpression();
183 }
184 _trackResolveVariables = false;
185 _variableResolved = false;
186 }
187 }