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 Node astNode = (Node)vmproxyhash.get(key);
168 if (astNode != null)
169 {
170 if (astNode.getType() == ParserTreeConstants.JJTREFERENCE)
171 {
172 ASTReference ref = (ASTReference)astNode;
173 if (ref.jjtGetNumChildren() > 0)
174 {
175 ref.setValue(innerContext, value);
176 return null;
177 }
178 else
179 {
180 return innerContext.put(ref.getRootString(), value);
181 }
182 }
183 }
184
185 Object old = localcontext.put(key, value);
186 if (!forceLocal)
187 {
188 old = super.put(key, value);
189 }
190 return old;
191 }
192
193
194
195
196
197
198
199
200 public Object get(String key)
201 {
202 Object o = localcontext.get(key);
203 if (o != null)
204 {
205 return o;
206 }
207
208 Node astNode = (Node) vmproxyhash.get(key);
209
210 if (astNode != null)
211 {
212 int type = astNode.getType();
213
214
215
216 if (type == ParserTreeConstants.JJTREFERENCE)
217 {
218 ASTReference ref = (ASTReference) astNode;
219
220 if (ref.jjtGetNumChildren() > 0)
221 {
222 return ref.execute(null, innerContext);
223 }
224 else
225 {
226 Object obj = innerContext.get(ref.getRootString());
227 if (obj == null && ref.strictRef)
228 {
229 if (!innerContext.containsKey(ref.getRootString()))
230 {
231 throw new MethodInvocationException("Parameter '" + ref.getRootString()
232 + "' not defined", null, key, ref.getTemplateName(),
233 ref.getLine(), ref.getColumn());
234 }
235 }
236 return obj;
237 }
238 }
239 else if (type == ParserTreeConstants.JJTTEXT)
240 {
241
242 try
243 {
244 StringWriter writer = new StringWriter();
245 astNode.render(innerContext, writer);
246 return writer.toString();
247 }
248 catch (RuntimeException e)
249 {
250 throw e;
251 }
252 catch (Exception e)
253 {
254 String msg = "ProxyVMContext.get() : error rendering reference";
255 rsvc.getLog().error(msg, e);
256 throw new VelocityException(msg, e);
257 }
258 }
259 else
260 {
261
262 return astNode.value(innerContext);
263 }
264 }
265
266 return super.get(key);
267 }
268
269
270
271
272 public boolean containsKey(Object key)
273 {
274 return vmproxyhash.containsKey(key)
275 || localcontext.containsKey(key)
276 || super.containsKey(key);
277 }
278
279
280
281
282 public Object[] getKeys()
283 {
284 if (localcontext.isEmpty())
285 {
286 return vmproxyhash.keySet().toArray();
287 }
288 else if (vmproxyhash.isEmpty())
289 {
290 return localcontext.keySet().toArray();
291 }
292
293 HashSet keys = new HashSet(localcontext.keySet());
294 keys.addAll(vmproxyhash.keySet());
295 return keys.toArray();
296 }
297
298
299
300
301 public Object remove(Object key)
302 {
303 Object loc = localcontext.remove(key);
304 Object arg = vmproxyhash.remove(key);
305 Object glo = null;
306 if (!localContextScope)
307 {
308 glo = super.remove(key);
309 }
310 if (loc != null)
311 {
312 return loc;
313 }
314 return glo;
315 }
316
317 }