1 package org.apache.velocity.tools.struts;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29 import javax.servlet.ServletContext;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpSession;
32 import org.apache.commons.validator.Field;
33 import org.apache.commons.validator.Form;
34 import org.apache.commons.validator.ValidatorAction;
35 import org.apache.commons.validator.ValidatorResources;
36 import org.apache.commons.validator.Var;
37 import org.apache.struts.Globals;
38 import org.apache.struts.config.ActionConfig;
39 import org.apache.struts.config.ModuleConfig;
40 import org.apache.struts.util.MessageResources;
41 import org.apache.struts.util.ModuleUtils;
42 import org.apache.struts.validator.Resources;
43 import org.apache.struts.validator.ValidatorPlugIn;
44 import org.apache.velocity.tools.Scope;
45 import org.apache.velocity.tools.config.DefaultKey;
46 import org.apache.velocity.tools.config.ValidScope;
47 import org.apache.velocity.tools.view.ViewContext;
48 import org.apache.velocity.tools.view.ViewToolContext;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 @DefaultKey("validator")
78 @ValidScope(Scope.REQUEST)
79 public class ValidatorTool
80 {
81
82
83 protected ViewContext context;
84
85
86 protected ServletContext app;
87
88
89 protected HttpServletRequest request;
90
91
92 protected HttpSession session;
93
94
95 protected ValidatorResources resources;
96
97
98 private static final String HTML_BEGIN_COMMENT = "\n<!-- Begin \n";
99 private static final String HTML_END_COMMENT = "//End --> \n";
100
101 private boolean xhtml = false;
102
103 private boolean htmlComment = true;
104 private boolean cdata = true;
105 private String formName = null;
106 private String methodName = null;
107 private String src = null;
108 private int page = 0;
109
110
111
112
113
114
115
116 protected String jsFormName = null;
117
118
119
120
121
122
123
124 private static final Comparator actionComparator = new Comparator() {
125 public int compare(Object o1, Object o2) {
126
127 ValidatorAction va1 = (ValidatorAction) o1;
128 ValidatorAction va2 = (ValidatorAction) o2;
129
130 if ((va1.getDepends() == null || va1.getDepends().length() == 0)
131 && (va2.getDepends() == null || va2.getDepends().length() == 0)) {
132 return 0;
133
134 } else if (
135 (va1.getDepends() != null && va1.getDepends().length() > 0)
136 && (va2.getDepends() == null || va2.getDepends().length() == 0)) {
137 return 1;
138
139 } else if (
140 (va1.getDepends() == null || va1.getDepends().length() == 0)
141 && (va2.getDepends() != null && va2.getDepends().length() > 0)) {
142 return -1;
143
144 } else {
145 return va1.getDependencyList().size() - va2.getDependencyList().size();
146 }
147 }
148 };
149
150
151 @Deprecated
152 public void init(Object obj)
153 {
154 if (obj instanceof ViewContext)
155 {
156 this.context = (ViewContext)obj;
157 this.request = context.getRequest();
158 this.session = request.getSession(false);
159 this.app = context.getServletContext();
160 }
161 }
162
163
164
165
166
167
168
169 public void configure(Map params)
170 {
171 this.context = (ViewContext)params.get(ViewToolContext.CONTEXT_KEY);
172 this.request = (HttpServletRequest)params.get(ViewContext.REQUEST);
173 this.session = request.getSession(false);
174 this.app = (ServletContext)params.get(ViewContext.SERVLET_CONTEXT_KEY);
175
176 Boolean b = (Boolean)params.get("XHTML");
177 if (b != null)
178 {
179 this.xhtml = b.booleanValue();
180 }
181
182
183 ActionConfig config =
184 (ActionConfig)request.getAttribute(Globals.MAPPING_KEY);
185 if (config != null)
186 {
187
188 this.formName = config.getAttribute();
189 }
190
191 ModuleConfig mconfig = ModuleUtils.getInstance().getModuleConfig(request, app);
192 this.resources = (ValidatorResources)app.getAttribute(ValidatorPlugIn.
193 VALIDATOR_KEY +
194 mconfig.getPrefix());
195
196 }
197
198
199
200
201
202
203
204
205
206
207
208 public int getPage()
209 {
210 return page;
211 }
212
213
214
215
216
217
218
219
220 public void setPage(int page)
221 {
222 this.page = page;
223 }
224
225
226
227
228
229
230
231
232
233 public String getMethod()
234 {
235 return methodName;
236 }
237
238
239
240
241
242
243
244
245
246 public void setMethod(String methodName)
247 {
248 this.methodName = methodName;
249 }
250
251
252
253
254
255
256
257
258 public boolean getHtmlComment()
259 {
260 return this.htmlComment;
261 }
262
263
264
265
266
267
268
269
270 public void setHtmlComment(boolean htmlComment)
271 {
272 this.htmlComment = htmlComment;
273 }
274
275
276
277
278
279
280
281 public String getSrc()
282 {
283 return src;
284 }
285
286
287
288
289
290
291
292
293
294 public void setSrc(String src)
295 {
296 this.src = src;
297 }
298
299
300
301
302
303
304 public boolean getCdata()
305 {
306 return cdata;
307 }
308
309
310
311
312
313 public void setCdata(boolean cdata)
314 {
315 this.cdata = cdata;
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329 public String getJavascript() throws Exception
330 {
331 return getJavascript(this.formName);
332 }
333
334
335
336
337
338
339
340
341
342 public String getJavascript(String formName) throws Exception
343 {
344 this.formName = formName;
345 return getJavascript(formName, true);
346 }
347
348
349
350
351
352
353
354
355
356
357 public String getDynamicJavascript() throws Exception
358 {
359 return getDynamicJavascript(this.formName);
360 }
361
362
363
364
365
366
367
368
369
370 public String getStaticJavascript() throws Exception
371 {
372 StringBuilder results = new StringBuilder();
373
374 results.append(getStartElement());
375 if (this.htmlComment)
376 {
377 results.append(HTML_BEGIN_COMMENT);
378 }
379 results.append(getJavascriptStaticMethods(resources));
380 results.append(getJavascriptEnd());
381
382 return results.toString();
383 }
384
385
386
387
388
389
390
391
392
393
394
395 public String getDynamicJavascript(String formName) throws Exception
396 {
397 this.formName = formName;
398 return getJavascript(formName, false);
399 }
400
401
402
403
404
405
406
407
408
409
410 protected String getJavascript(String formName, boolean getStatic) throws Exception
411 {
412 StringBuilder results = new StringBuilder();
413
414 Locale locale = StrutsUtils.getLocale(request, session);
415
416 Form form = resources.getForm(locale, formName);
417 if (form != null)
418 {
419 results.append(getDynamicJavascript(resources, locale, form));
420 }
421
422 if(getStatic)
423 {
424 results.append(getJavascriptStaticMethods(resources));
425 }
426
427 if (form != null)
428 {
429 results.append(getJavascriptEnd());
430 }
431
432 return results.toString();
433 }
434
435
436
437
438
439
440
441
442
443
444
445 protected String getDynamicJavascript(ValidatorResources resources,
446 Locale locale,
447 Form form)
448 {
449 StringBuilder results = new StringBuilder();
450
451 MessageResources messages =
452 StrutsUtils.getMessageResources(request, app);
453
454 List actions = createActionList(resources, form);
455
456 final String methods = createMethods(actions);
457
458 String formName = form.getName();
459
460 jsFormName = formName;
461 if(jsFormName.charAt(0) == '/') {
462 String mappingName = StrutsUtils.getActionMappingName(jsFormName);
463 ModuleConfig mconfig = ModuleUtils.getInstance().getModuleConfig(request, app);
464
465 ActionConfig mapping = (ActionConfig) mconfig.findActionConfig(mappingName);
466 if (mapping == null) {
467 throw new NullPointerException("Cannot retrieve mapping for action " + mappingName);
468 }
469 jsFormName = mapping.getAttribute();
470 }
471
472 results.append(getJavascriptBegin(methods));
473
474 for (Iterator i = actions.iterator(); i.hasNext();)
475 {
476 ValidatorAction va = (ValidatorAction)i.next();
477 int jscriptVar = 0;
478 String functionName = null;
479
480 if (va.getJsFunctionName() != null && va.getJsFunctionName().length() > 0)
481 {
482 functionName = va.getJsFunctionName();
483 }
484 else
485 {
486 functionName = va.getName();
487 }
488
489 results.append(" function ");
490 results.append(jsFormName);
491 results.append("_");
492 results.append(functionName);
493 results.append(" () { \n");
494
495 for (Iterator x = form.getFields().iterator(); x.hasNext();)
496 {
497 Field field = (Field)x.next();
498
499
500
501
502 if (field.isIndexed()
503 || field.getPage() != page
504 || !field.isDependency(va.getName()))
505 {
506 continue;
507 }
508
509 String message = Resources.getMessage(app, request, messages,
510 locale, va, field);
511
512 message = (message != null) ? message : "";
513
514
515
516 results.append(" this.a");
517 results.append(jscriptVar++);
518 results.append(" = new Array(\"");
519 results.append(field.getKey());
520 results.append("\", \"");
521 results.append(escapeJavascript(message));
522 results.append("\", new Function (\"varName\", \"");
523
524 Map<String,Var> vars = (Map<String,Var>)field.getVars();
525
526 for (Map.Entry<String,Var> entry : vars.entrySet())
527 {
528 String varName = entry.getKey();
529 Var var = entry.getValue();
530 String varValue =
531 Resources.getVarValue(var, app, request, false);
532 String jsType = var.getJsType();
533
534
535 if (varName.startsWith("field"))
536 {
537 continue;
538 }
539
540
541 results.append("this.");
542 results.append(varName);
543
544 String escapedVarValue = escapeJavascript(varValue);
545
546 if (Var.JSTYPE_INT.equalsIgnoreCase(jsType))
547 {
548 results.append("=");
549 results.append(escapedVarValue);
550 results.append("; ");
551 }
552 else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType))
553 {
554 results.append("=/");
555 results.append(escapedVarValue);
556 results.append("/; ");
557 }
558 else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType))
559 {
560 results.append("='");
561 results.append(escapedVarValue);
562 results.append("'; ");
563 }
564
565
566 else if ("mask".equalsIgnoreCase(varName))
567 {
568 results.append("=/");
569 results.append(escapedVarValue);
570 results.append("/; ");
571 }
572 else
573 {
574 results.append("='");
575 results.append(escapedVarValue);
576 results.append("'; ");
577 }
578 }
579 results.append(" return this[varName];\"));\n");
580 }
581 results.append(" } \n\n");
582 }
583 return results.toString();
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600 protected String escapeJavascript(String str)
601 {
602 if (str == null)
603 {
604 return null;
605 }
606 int length = str.length();
607 if (length == 0)
608 {
609 return str;
610 }
611
612
613 StringBuilder out = new StringBuilder(length + 4);
614
615 for (int i=0; i < length; i++)
616 {
617 char c = str.charAt(i);
618 if (c == '"' ||
619 c == '\'' ||
620 c == '\\' ||
621 c == '\n' ||
622 c == '\r')
623 {
624 out.append('\\');
625 }
626 out.append(c);
627 }
628 return out.toString();
629 }
630
631
632
633
634
635
636
637 protected String createMethods(List actions)
638 {
639 String methodOperator = " && ";
640
641 StringBuilder methods = null;
642 for (Iterator i = actions.iterator(); i.hasNext();)
643 {
644 ValidatorAction va = (ValidatorAction)i.next();
645 if (methods == null)
646 {
647 methods = new StringBuilder(va.getMethod());
648 }
649 else
650 {
651 methods.append(methodOperator);
652 methods.append(va.getMethod());
653 }
654 methods.append("(form)");
655 }
656 return methods.toString();
657 }
658
659
660
661
662
663
664
665
666
667 protected List createActionList(ValidatorResources resources, Form form)
668 {
669 List actionMethods = new ArrayList();
670
671 for (Iterator i = form.getFields().iterator(); i.hasNext();)
672 {
673 Field field = (Field)i.next();
674 for (Iterator x = field.getDependencyList().iterator(); x.hasNext();)
675 {
676 Object o = x.next();
677 if (o != null && !actionMethods.contains(o))
678 {
679 actionMethods.add(o);
680 }
681 }
682 }
683
684 List actions = new ArrayList();
685
686
687 for (Iterator i = actionMethods.iterator(); i.hasNext();)
688 {
689 String depends = (String) i.next();
690 ValidatorAction va = resources.getValidatorAction(depends);
691
692
693 if (va == null)
694 {
695 throw new NullPointerException(
696 "Depends string \"" + depends +
697 "\" was not found in validator-rules.xml.");
698 }
699
700 String javascript = va.getJavascript();
701 if (javascript != null && javascript.length() > 0)
702 {
703 actions.add(va);
704 }
705 else
706 {
707 i.remove();
708 }
709 }
710
711 Collections.sort(actions, actionComparator);
712 return actions;
713 }
714
715
716
717
718
719
720
721
722 protected String getJavascriptBegin(String methods)
723 {
724 StringBuilder sb = new StringBuilder();
725 String name = jsFormName.replace('/', '_');
726 name = jsFormName.substring(0, 1).toUpperCase() +
727 jsFormName.substring(1, jsFormName.length());
728
729 sb.append(this.getStartElement());
730
731 if (this.xhtml && this.cdata)
732 {
733 sb.append("<![CDATA[\r\n");
734 }
735
736 if (!this.xhtml && this.htmlComment)
737 {
738 sb.append(HTML_BEGIN_COMMENT);
739 }
740 sb.append("\n var bCancel = false; \n\n");
741
742 if (methodName == null || methodName.length() == 0)
743 {
744 sb.append(" function validate");
745 sb.append(name);
746 }
747 else
748 {
749 sb.append(" function ");
750 sb.append(methodName);
751 }
752 sb.append("(form) {\n");
753 sb.append(" if (bCancel) \n");
754 sb.append(" return true; \n");
755 sb.append(" else \n");
756
757
758 if (methods == null || methods.length() == 0)
759 {
760 sb.append(" return true; \n");
761 }
762 else
763 {
764
765 sb.append(" var formValidationResult;\n");
766 sb.append(" formValidationResult = " + methods + "; \n");
767 sb.append(" return (formValidationResult == 1);\n");
768
769 }
770 sb.append(" } \n\n");
771
772 return sb.toString();
773 }
774
775
776
777
778
779
780 protected String getJavascriptStaticMethods(ValidatorResources resources)
781 {
782 StringBuilder sb = new StringBuilder("\n\n");
783
784 Iterator actions = resources.getValidatorActions().values().iterator();
785 while (actions.hasNext())
786 {
787 ValidatorAction va = (ValidatorAction) actions.next();
788 if (va != null)
789 {
790 String javascript = va.getJavascript();
791 if (javascript != null && javascript.length() > 0)
792 {
793 sb.append(javascript);
794 sb.append("\n");
795 }
796 }
797 }
798 return sb.toString();
799 }
800
801
802
803
804
805
806
807 protected String getJavascriptEnd()
808 {
809 StringBuilder sb = new StringBuilder();
810 sb.append("\n");
811
812 if (!this.xhtml && this.htmlComment)
813 {
814 sb.append(HTML_END_COMMENT);
815 }
816
817 if (this.xhtml && this.cdata)
818 {
819 sb.append("]]>\r\n");
820 }
821 sb.append("</script>\n\n");
822
823 return sb.toString();
824 }
825
826
827
828
829
830
831
832 private String getStartElement()
833 {
834 StringBuilder start = new StringBuilder("<script type=\"text/javascript\"");
835
836
837 if (!this.xhtml)
838 {
839 start.append(" language=\"Javascript1.1\"");
840 }
841
842 if (this.src != null)
843 {
844 start.append(" src=\"" + src + "\"");
845 }
846
847 start.append("> \n");
848 return start.toString();
849 }
850
851 }