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.HashMap;
23 import java.util.Map;
24 import java.util.Vector;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.velocity.Template;
28 import org.apache.velocity.runtime.directive.Directive;
29 import org.apache.velocity.runtime.directive.Macro;
30 import org.apache.velocity.runtime.directive.VelocimacroProxy;
31 import org.apache.velocity.runtime.log.LogDisplayWrapper;
32
33
34
35
36
37
38
39
40
41 public class VelocimacroFactory
42 {
43
44
45
46 private final RuntimeServices rsvc;
47
48
49
50
51 private final LogDisplayWrapper log;
52
53
54
55
56
57 private VelocimacroManager vmManager = null;
58
59
60
61
62
63 private boolean replaceAllowed = false;
64
65
66
67
68
69
70
71 private boolean addNewAllowed = true;
72
73
74
75
76 private boolean templateLocal = false;
77
78
79
80
81
82 private boolean autoReloadLibrary = false;
83
84
85
86
87 private Vector macroLibVec = null;
88
89
90
91
92
93 private Map libModMap;
94
95
96
97
98
99
100 public VelocimacroFactory(final RuntimeServices rsvc)
101 {
102 this.rsvc = rsvc;
103 this.log = new LogDisplayWrapper(rsvc.getLog(), "Velocimacro : ",
104 rsvc.getBoolean(RuntimeConstants.VM_MESSAGES_ON, true));
105
106
107
108
109
110 libModMap = new HashMap();
111 vmManager = new VelocimacroManager(rsvc);
112 }
113
114
115
116
117
118 public void initVelocimacro()
119 {
120
121
122
123 synchronized(this)
124 {
125 log.trace("initialization starting.");
126
127
128
129
130 setReplacementPermission(true);
131
132
133
134
135
136 vmManager.setNamespaceUsage(false);
137
138
139
140
141
142
143
144 Object libfiles = rsvc.getProperty(RuntimeConstants.VM_LIBRARY);
145
146 if (libfiles == null)
147 {
148 log.debug("\"" + RuntimeConstants.VM_LIBRARY +
149 "\" is not set. Trying default library: " +
150 RuntimeConstants.VM_LIBRARY_DEFAULT);
151
152
153 if (rsvc.getLoaderNameForResource(RuntimeConstants.VM_LIBRARY_DEFAULT) != null)
154 {
155 libfiles = RuntimeConstants.VM_LIBRARY_DEFAULT;
156 }
157 else
158 {
159 log.debug("Default library not found.");
160 }
161 }
162
163 if(libfiles != null)
164 {
165 if (libfiles instanceof Vector)
166 {
167 macroLibVec = (Vector) libfiles;
168 }
169 else if (libfiles instanceof String)
170 {
171 macroLibVec = new Vector();
172 macroLibVec.addElement(libfiles);
173 }
174
175 for(int i = 0; i < macroLibVec.size(); i++)
176 {
177 String lib = (String) macroLibVec.elementAt(i);
178
179
180
181
182
183 if (StringUtils.isNotEmpty(lib))
184 {
185
186
187
188
189
190 vmManager.setRegisterFromLib(true);
191
192 log.debug("adding VMs from VM library : " + lib);
193
194 try
195 {
196 Template template = rsvc.getTemplate(lib);
197
198
199
200
201
202
203
204 Twonk twonk = new Twonk();
205 twonk.template = template;
206 twonk.modificationTime = template.getLastModified();
207 libModMap.put(lib, twonk);
208 }
209 catch (Exception e)
210 {
211 log.error(true, "Velocimacro : Error using VM library : " + lib, e);
212 }
213
214 log.trace("VM library registration complete.");
215
216 vmManager.setRegisterFromLib(false);
217 }
218 }
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232 setAddMacroPermission(true);
233
234 if (!rsvc.getBoolean( RuntimeConstants.VM_PERM_ALLOW_INLINE, true))
235 {
236 setAddMacroPermission(false);
237
238 log.info("allowInline = false : VMs can NOT be defined inline in templates");
239 }
240 else
241 {
242 log.debug("allowInline = true : VMs can be defined inline in templates");
243 }
244
245
246
247
248
249
250
251 setReplacementPermission(false);
252
253 if (rsvc.getBoolean(
254 RuntimeConstants.VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL, false))
255 {
256 setReplacementPermission(true);
257
258 log.info("allowInlineToOverride = true : VMs " +
259 "defined inline may replace previous VM definitions");
260 }
261 else
262 {
263 log.debug("allowInlineToOverride = false : VMs " +
264 "defined inline may NOT replace previous VM definitions");
265 }
266
267
268
269
270
271 vmManager.setNamespaceUsage(true);
272
273
274
275
276 setTemplateLocalInline(rsvc.getBoolean(
277 RuntimeConstants.VM_PERM_INLINE_LOCAL, false));
278
279 if (getTemplateLocalInline())
280 {
281 log.info("allowInlineLocal = true : VMs " +
282 "defined inline will be local to their defining template only.");
283 }
284 else
285 {
286 log.debug("allowInlineLocal = false : VMs " +
287 "defined inline will be global in scope if allowed.");
288 }
289
290 vmManager.setTemplateLocalInlineVM(getTemplateLocalInline());
291
292
293
294
295 setAutoload(rsvc.getBoolean(RuntimeConstants.VM_LIBRARY_AUTORELOAD, false));
296
297 if (getAutoload())
298 {
299 log.info("autoload on : VM system " +
300 "will automatically reload global library macros");
301 }
302 else
303 {
304 log.debug("autoload off : VM system " +
305 "will not automatically reload global library macros");
306 }
307
308 log.trace("Velocimacro : initialization complete.");
309 }
310 }
311
312
313
314
315
316
317
318
319
320
321 public boolean addVelocimacro(String name, String macroBody,
322 String argArray[], String sourceTemplate)
323 {
324
325
326
327
328
329
330 if (name == null || macroBody == null || argArray == null ||
331 sourceTemplate == null)
332 {
333 log.warn("VM addition rejected : programmer error : arg null");
334 return false;
335 }
336
337
338
339
340
341 if (!canAddVelocimacro(name, sourceTemplate))
342 {
343 return false;
344 }
345
346
347
348
349 synchronized(this)
350 {
351 vmManager.addVM(name, macroBody, argArray, sourceTemplate);
352 }
353
354
355
356
357 StringBuffer msg = new StringBuffer("added ");
358 Macro.macroToString(msg, argArray);
359 msg.append(" : source = ").append(sourceTemplate);
360 log.info(msg.toString());
361
362 return true;
363 }
364
365
366
367
368
369
370
371
372
373 private synchronized boolean canAddVelocimacro(String name, String sourceTemplate)
374 {
375
376
377
378
379
380 if (getAutoload() && (macroLibVec != null))
381 {
382
383
384
385
386 for(int i = 0; i < macroLibVec.size(); i++)
387 {
388 String lib = (String) macroLibVec.elementAt(i);
389
390 if (lib.equals(sourceTemplate))
391 {
392 return true;
393 }
394 }
395 }
396
397
398
399
400
401
402
403 if (!addNewAllowed)
404 {
405 log.warn("VM addition rejected : "+name+" : inline VMs not allowed.");
406 return false;
407 }
408
409
410
411
412 if (!templateLocal)
413 {
414
415
416
417
418
419
420
421
422 if (isVelocimacro(name, sourceTemplate) && !replaceAllowed)
423 {
424 log.warn("VM addition rejected : "+name+" : inline not allowed to replace existing VM");
425 return false;
426 }
427 }
428
429 return true;
430 }
431
432
433
434
435
436
437
438 public boolean isVelocimacro(String vm , String sourceTemplate)
439 {
440 synchronized(this)
441 {
442
443
444
445
446 if (vmManager.get(vm, sourceTemplate) != null)
447 return true;
448 }
449 return false;
450 }
451
452
453
454
455
456
457
458
459
460 public Directive getVelocimacro(String vmName, String sourceTemplate)
461 {
462 VelocimacroProxy vp = null;
463
464 synchronized(this)
465 {
466
467
468
469
470 vp = vmManager.get(vmName, sourceTemplate);
471
472
473
474
475
476
477 if (vp != null && getAutoload())
478 {
479
480
481
482
483
484 String lib = vmManager.getLibraryName(vmName, sourceTemplate);
485
486 if (lib != null)
487 {
488 try
489 {
490
491
492
493
494 Twonk tw = (Twonk) libModMap.get(lib);
495
496 if (tw != null)
497 {
498 Template template = tw.template;
499
500
501
502
503
504
505
506
507 long tt = tw.modificationTime;
508 long ft = template.getResourceLoader().getLastModified(template);
509
510 if (ft > tt)
511 {
512 log.debug("auto-reloading VMs from VM library : "+lib);
513
514
515
516
517
518
519
520
521
522 tw.modificationTime = ft;
523
524 template = rsvc.getTemplate(lib);
525
526
527
528
529
530 tw.template = template;
531 tw.modificationTime = template.getLastModified();
532
533
534
535
536
537
538 }
539 }
540 }
541 catch (Exception e)
542 {
543 log.error(true, "Velocimacro : Error using VM library : "+lib, e);
544 }
545
546
547
548
549
550 vp = vmManager.get(vmName, sourceTemplate);
551 }
552 }
553 }
554
555 return vp;
556 }
557
558
559
560
561
562
563 public boolean dumpVMNamespace(String namespace)
564 {
565 return vmManager.dumpNamespace(namespace);
566 }
567
568
569
570
571
572
573
574 private void setTemplateLocalInline(boolean b)
575 {
576 templateLocal = b;
577 }
578
579 private boolean getTemplateLocalInline()
580 {
581 return templateLocal;
582 }
583
584
585
586
587 private boolean setAddMacroPermission(final boolean addNewAllowed)
588 {
589 boolean b = this.addNewAllowed;
590 this.addNewAllowed = addNewAllowed;
591 return b;
592 }
593
594
595
596
597
598 private boolean setReplacementPermission(boolean arg)
599 {
600 boolean b = replaceAllowed;
601 replaceAllowed = arg;
602 return b;
603 }
604
605
606
607
608
609 private void setAutoload(boolean b)
610 {
611 autoReloadLibrary = b;
612 }
613
614
615
616
617
618 private boolean getAutoload()
619 {
620 return autoReloadLibrary;
621 }
622
623
624
625
626
627
628
629
630
631 private static class Twonk
632 {
633
634 public Template template;
635
636
637 public long modificationTime;
638 }
639 }
640
641
642
643
644
645
646