1 package org.apache.velocity.runtime;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Map;
25 import java.util.Set;
26 import org.apache.velocity.runtime.directive.VelocimacroProxy;
27 import org.apache.velocity.runtime.parser.node.Node;
28 import org.apache.velocity.runtime.parser.node.SimpleNode;
29 import org.apache.velocity.util.MapFactory;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class VelocimacroManager
48 {
49 private static String GLOBAL_NAMESPACE = "";
50
51 private boolean registerFromLib = false;
52
53
54 private final Map namespaceHash = MapFactory.create(17, 0.5f, 20, false);
55
56
57 private final Map globalNamespace;
58
59
60 private final Set libraries = Collections.synchronizedSet(new HashSet());
61
62
63
64
65
66 private boolean namespacesOn = true;
67 private boolean inlineLocalMode = false;
68 private boolean inlineReplacesGlobal = false;
69
70
71
72
73 VelocimacroManager(RuntimeServices rsvc)
74 {
75
76
77
78
79 globalNamespace = addNamespace(GLOBAL_NAMESPACE);
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93 public boolean addVM(final String vmName, final Node macroBody, final String argArray[],
94 final String namespace, boolean canReplaceGlobalMacro)
95 {
96 if (macroBody == null)
97 {
98
99
100 throw new RuntimeException("Null AST for "+vmName+" in "+namespace);
101 }
102
103 MacroEntry me = new MacroEntry(vmName, macroBody, argArray, namespace);
104
105 me.setFromLibrary(registerFromLib);
106
107
108
109
110
111
112
113
114 boolean isLib = true;
115
116 MacroEntry exist = (MacroEntry) globalNamespace.get(vmName);
117
118 if (registerFromLib)
119 {
120 libraries.add(namespace);
121 }
122 else
123 {
124
125
126
127
128
129
130
131
132 isLib = libraries.contains(namespace);
133 }
134
135 if ( !isLib && usingNamespaces(namespace) )
136 {
137
138
139
140
141
142 Map local = getNamespace(namespace, true);
143 local.put(vmName, me);
144
145 return true;
146 }
147 else
148 {
149
150
151
152
153
154
155 if (exist != null)
156 {
157 me.setFromLibrary(exist.getFromLibrary());
158 }
159
160
161
162
163
164 globalNamespace.put(vmName, me);
165
166 return true;
167 }
168 }
169
170
171
172
173
174
175
176
177 public VelocimacroProxy get(final String vmName, final String namespace)
178 {
179 return(get(vmName, namespace, null));
180 }
181
182
183
184
185
186
187
188
189
190
191 public VelocimacroProxy get(final String vmName, final String namespace, final String renderingTemplate)
192 {
193 if( inlineReplacesGlobal && renderingTemplate != null )
194 {
195
196
197
198
199
200
201 Map local = getNamespace(renderingTemplate, false);
202 if (local != null)
203 {
204 MacroEntry me = (MacroEntry) local.get(vmName);
205
206 if (me != null)
207 {
208 return me.getProxy(namespace);
209 }
210 }
211 }
212
213 if (usingNamespaces(namespace))
214 {
215 Map local = getNamespace(namespace, false);
216
217
218
219
220
221 if (local != null)
222 {
223 MacroEntry me = (MacroEntry) local.get(vmName);
224
225 if (me != null)
226 {
227 return me.getProxy(namespace);
228 }
229 }
230 }
231
232
233
234
235
236
237 MacroEntry me = (MacroEntry) globalNamespace.get(vmName);
238
239 if (me != null)
240 {
241 return me.getProxy(namespace);
242 }
243
244 return null;
245 }
246
247
248
249
250
251
252
253
254
255 public boolean dumpNamespace(final String namespace)
256 {
257 synchronized(this)
258 {
259 if (usingNamespaces(namespace))
260 {
261 Map h = (Map) namespaceHash.remove(namespace);
262
263 if (h == null)
264 {
265 return false;
266 }
267
268 h.clear();
269
270 return true;
271 }
272
273 return false;
274 }
275 }
276
277
278
279
280
281
282
283
284 public void setNamespaceUsage(final boolean namespaceOn)
285 {
286 this.namespacesOn = namespaceOn;
287 }
288
289
290
291
292
293 public void setRegisterFromLib(final boolean registerFromLib)
294 {
295 this.registerFromLib = registerFromLib;
296 }
297
298
299
300
301
302
303 public void setTemplateLocalInlineVM(final boolean inlineLocalMode)
304 {
305 this.inlineLocalMode = inlineLocalMode;
306 }
307
308
309
310
311
312
313
314
315
316 private Map getNamespace(final String namespace, final boolean addIfNew)
317 {
318 Map h = (Map) namespaceHash.get(namespace);
319
320 if (h == null && addIfNew)
321 {
322 h = addNamespace(namespace);
323 }
324
325 return h;
326 }
327
328
329
330
331
332
333
334 private Map addNamespace(final String namespace)
335 {
336 Map h = MapFactory.create(17, 0.5f, 20, false);
337 Object oh;
338
339 if ((oh = namespaceHash.put(namespace, h)) != null)
340 {
341
342
343
344
345
346
347
348 namespaceHash.put(namespace, oh);
349
350
351
352
353 return null;
354 }
355
356 return h;
357 }
358
359
360
361
362
363
364
365 private boolean usingNamespaces(final String namespace)
366 {
367
368
369
370
371 if (!namespacesOn)
372 {
373 return false;
374 }
375
376
377
378
379
380 if (inlineLocalMode)
381 {
382 return true;
383 }
384
385 return false;
386 }
387
388
389
390
391
392
393
394 public String getLibraryName(final String vmName, final String namespace)
395 {
396 if (usingNamespaces(namespace))
397 {
398 Map local = getNamespace(namespace, false);
399
400
401
402
403
404
405
406 if ( local != null)
407 {
408 MacroEntry me = (MacroEntry) local.get(vmName);
409
410 if (me != null)
411 {
412 return null;
413 }
414 }
415 }
416
417
418
419
420
421
422 MacroEntry me = (MacroEntry) globalNamespace.get(vmName);
423
424 if (me != null)
425 {
426 return me.getSourceTemplate();
427 }
428
429 return null;
430 }
431
432
433
434
435 public void setInlineReplacesGlobal(boolean is)
436 {
437 inlineReplacesGlobal = is;
438 }
439
440
441
442
443
444 private static class MacroEntry
445 {
446 private final String vmName;
447 private final String[] argArray;
448 private final String sourceTemplate;
449 private SimpleNode nodeTree = null;
450 private boolean fromLibrary = false;
451 private VelocimacroProxy vp;
452
453 private MacroEntry(final String vmName, final Node macro,
454 final String argArray[], final String sourceTemplate)
455 {
456 this.vmName = vmName;
457 this.argArray = argArray;
458 this.nodeTree = (SimpleNode)macro;
459 this.sourceTemplate = sourceTemplate;
460
461 vp = new VelocimacroProxy();
462 vp.setName(this.vmName);
463 vp.setArgArray(this.argArray);
464 vp.setNodeTree(this.nodeTree);
465 }
466
467
468
469
470
471 public void setFromLibrary(final boolean fromLibrary)
472 {
473 this.fromLibrary = fromLibrary;
474 }
475
476
477
478
479
480 public boolean getFromLibrary()
481 {
482 return fromLibrary;
483 }
484
485
486
487
488
489 public SimpleNode getNodeTree()
490 {
491 return nodeTree;
492 }
493
494
495
496
497
498 public String getSourceTemplate()
499 {
500 return sourceTemplate;
501 }
502
503 VelocimacroProxy getProxy(final String namespace)
504 {
505
506
507
508
509 return vp;
510 }
511 }
512 }
513
514