1 package org.apache.velocity.context;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.StringWriter;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.velocity.app.event.EventCartridge;
29 import org.apache.velocity.exception.MethodInvocationException;
30 import org.apache.velocity.exception.VelocityException;
31 import org.apache.velocity.runtime.RuntimeServices;
32 import org.apache.velocity.runtime.parser.ParserTreeConstants;
33 import org.apache.velocity.runtime.parser.node.ASTReference;
34 import org.apache.velocity.runtime.parser.node.Node;
35 import org.apache.velocity.runtime.resource.Resource;
36 import org.apache.velocity.util.introspection.IntrospectionCacheData;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class ProxyVMContext extends ChainedInternalContextAdapter
54 {
55
56 Map vmproxyhash = new HashMap(8, 0.8f);
57
58
59 Map localcontext = new HashMap(8, 0.8f);;
60
61
62 private boolean localContextScope;
63
64
65 private RuntimeServices rsvc;
66
67
68
69
70
71
72 public ProxyVMContext(InternalContextAdapter inner,
73 RuntimeServices rsvc,
74 boolean localContextScope)
75 {
76 super(inner);
77
78 this.localContextScope = localContextScope;
79 this.rsvc = rsvc;
80 }
81
82
83
84
85
86
87
88
89
90
91
92 public void addVMProxyArg(InternalContextAdapter context,
93 String macroArgumentName,
94 String literalMacroArgumentName,
95 Node argumentValue) throws MethodInvocationException
96 {
97 if (isConstant(argumentValue))
98 {
99 localcontext.put(macroArgumentName, argumentValue.value(context));
100 }
101 else
102 {
103 vmproxyhash.put(macroArgumentName, argumentValue);
104 localcontext.put(literalMacroArgumentName, argumentValue);
105 }
106 }
107
108
109
110
111
112
113
114
115
116 private boolean isConstant(Node node)
117 {
118 switch (node.getType())
119 {
120 case ParserTreeConstants.JJTINTEGERRANGE:
121 case ParserTreeConstants.JJTREFERENCE:
122 case ParserTreeConstants.JJTOBJECTARRAY:
123 case ParserTreeConstants.JJTMAP:
124 case ParserTreeConstants.JJTSTRINGLITERAL:
125 case ParserTreeConstants.JJTTEXT:
126 return (false);
127 default:
128 return (true);
129 }
130 }
131
132
133
134
135
136
137
138
139 public Object put(final String key, final Object value)
140 {
141 return put(key, value, localContextScope);
142 }
143
144
145
146
147
148
149
150
151
152 public Object localPut(final String key, final Object value)
153 {
154 return put(key, value, true);
155 }
156
157
158
159
160
161
162
163
164
165 protected Object put(final String key, final Object value, final boolean forceLocal)
166 {
167 Object old = localcontext.put(key, value);
168 if (!forceLocal)
169 {
170 old = super.put(key, value);
171 }
172 return old;
173 }
174
175
176
177
178
179
180
181
182 public Object get(String key)
183 {
184 Object o = localcontext.get(key);
185 if (o != null)
186 {
187 return o;
188 }
189
190 Node astNode = (Node) vmproxyhash.get(key);
191
192 if (astNode != null)
193 {
194 int type = astNode.getType();
195
196
197
198 if (type == ParserTreeConstants.JJTREFERENCE)
199 {
200 ASTReference ref = (ASTReference) astNode;
201
202 if (ref.jjtGetNumChildren() > 0)
203 {
204 return ref.execute(null, innerContext);
205 }
206 else
207 {
208 Object obj = innerContext.get(ref.getRootString());
209 if (obj == null && ref.strictRef)
210 {
211 if (!innerContext.containsKey(ref.getRootString()))
212 {
213 throw new MethodInvocationException("Parameter '" + ref.getRootString()
214 + "' not defined", null, key, ref.getTemplateName(),
215 ref.getLine(), ref.getColumn());
216 }
217 }
218 return obj;
219 }
220 }
221 else if (type == ParserTreeConstants.JJTTEXT)
222 {
223
224 try
225 {
226 StringWriter writer = new StringWriter();
227 astNode.render(innerContext, writer);
228 return writer.toString();
229 }
230 catch (RuntimeException e)
231 {
232 throw e;
233 }
234 catch (Exception e)
235 {
236 String msg = "ProxyVMContext.get() : error rendering reference";
237 rsvc.getLog().error(msg, e);
238 throw new VelocityException(msg, e);
239 }
240 }
241 else
242 {
243
244 return astNode.value(innerContext);
245 }
246 }
247
248 return super.get(key);
249 }
250
251
252
253
254 public boolean containsKey(Object key)
255 {
256 return vmproxyhash.containsKey(key)
257 || localcontext.containsKey(key)
258 || super.containsKey(key);
259 }
260
261
262
263
264 public Object[] getKeys()
265 {
266 if (localcontext.isEmpty())
267 {
268 return vmproxyhash.keySet().toArray();
269 }
270 else if (vmproxyhash.isEmpty())
271 {
272 return localcontext.keySet().toArray();
273 }
274
275 HashSet keys = new HashSet(localcontext.keySet());
276 keys.addAll(vmproxyhash.keySet());
277 return keys.toArray();
278 }
279
280
281
282
283 public Object remove(Object key)
284 {
285 Object loc = localcontext.remove(key);
286 Object arg = vmproxyhash.remove(key);
287 Object glo = null;
288 if (!localContextScope)
289 {
290 glo = super.remove(key);
291 }
292 if (loc != null)
293 {
294 return loc;
295 }
296 return glo;
297 }
298
299 }