1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.compiler;
19
20 import org.apache.struts2.jasper.Constants;
21 import org.apache.struts2.jasper.JasperException;
22 import org.xml.sax.Attributes;
23
24 import javax.servlet.jsp.el.FunctionMapper;
25 import javax.servlet.jsp.tagext.*;
26 import java.lang.reflect.Method;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.Hashtable;
30 import java.util.Iterator;
31
32 /***
33 * Performs validation on the page elements. Attributes are checked for
34 * mandatory presence, entry value validity, and consistency. As a
35 * side effect, some page global value (such as those from page direcitves)
36 * are stored, for later use.
37 *
38 * @author Kin-man Chung
39 * @author Jan Luehe
40 * @author Shawn Bayern
41 * @author Mark Roth
42 */
43 class Validator {
44
45 /***
46 * A visitor to validate and extract page directive info
47 */
48 static class DirectiveVisitor extends Node.Visitor {
49
50 private PageInfo pageInfo;
51 private ErrorDispatcher err;
52
53 private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
54 new JspUtil.ValidAttribute("language"),
55 new JspUtil.ValidAttribute("extends"),
56 new JspUtil.ValidAttribute("import"),
57 new JspUtil.ValidAttribute("session"),
58 new JspUtil.ValidAttribute("buffer"),
59 new JspUtil.ValidAttribute("autoFlush"),
60 new JspUtil.ValidAttribute("isThreadSafe"),
61 new JspUtil.ValidAttribute("info"),
62 new JspUtil.ValidAttribute("errorPage"),
63 new JspUtil.ValidAttribute("isErrorPage"),
64 new JspUtil.ValidAttribute("contentType"),
65 new JspUtil.ValidAttribute("pageEncoding"),
66 new JspUtil.ValidAttribute("isELIgnored")
67 };
68
69 private boolean pageEncodingSeen = false;
70
71
72
73
74 DirectiveVisitor(Compiler compiler) throws JasperException {
75 this.pageInfo = compiler.getPageInfo();
76 this.err = compiler.getErrorDispatcher();
77 }
78
79 public void visit(Node.IncludeDirective n) throws JasperException {
80
81
82 boolean pageEncodingSeenSave = pageEncodingSeen;
83 pageEncodingSeen = false;
84 visitBody(n);
85 pageEncodingSeen = pageEncodingSeenSave;
86 }
87
88 public void visit(Node.PageDirective n) throws JasperException {
89
90 JspUtil.checkAttributes("Page directive", n,
91 pageDirectiveAttrs, err);
92
93
94 Attributes attrs = n.getAttributes();
95 for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
96 String attr = attrs.getQName(i);
97 String value = attrs.getValue(i);
98
99 if ("language".equals(attr)) {
100 if (pageInfo.getLanguage(false) == null) {
101 pageInfo.setLanguage(value, n, err, true);
102 } else if (!pageInfo.getLanguage(false).equals(value)) {
103 err.jspError(n, "jsp.error.page.conflict.language",
104 pageInfo.getLanguage(false), value);
105 }
106 } else if ("extends".equals(attr)) {
107 if (pageInfo.getExtends(false) == null) {
108 pageInfo.setExtends(value, n);
109 } else if (!pageInfo.getExtends(false).equals(value)) {
110 err.jspError(n, "jsp.error.page.conflict.extends",
111 pageInfo.getExtends(false), value);
112 }
113 } else if ("contentType".equals(attr)) {
114 if (pageInfo.getContentType() == null) {
115 pageInfo.setContentType(value);
116 } else if (!pageInfo.getContentType().equals(value)) {
117 err.jspError(n, "jsp.error.page.conflict.contenttype",
118 pageInfo.getContentType(), value);
119 }
120 } else if ("session".equals(attr)) {
121 if (pageInfo.getSession() == null) {
122 pageInfo.setSession(value, n, err);
123 } else if (!pageInfo.getSession().equals(value)) {
124 err.jspError(n, "jsp.error.page.conflict.session",
125 pageInfo.getSession(), value);
126 }
127 } else if ("buffer".equals(attr)) {
128 if (pageInfo.getBufferValue() == null) {
129 pageInfo.setBufferValue(value, n, err);
130 } else if (!pageInfo.getBufferValue().equals(value)) {
131 err.jspError(n, "jsp.error.page.conflict.buffer",
132 pageInfo.getBufferValue(), value);
133 }
134 } else if ("autoFlush".equals(attr)) {
135 if (pageInfo.getAutoFlush() == null) {
136 pageInfo.setAutoFlush(value, n, err);
137 } else if (!pageInfo.getAutoFlush().equals(value)) {
138 err.jspError(n, "jsp.error.page.conflict.autoflush",
139 pageInfo.getAutoFlush(), value);
140 }
141 } else if ("isThreadSafe".equals(attr)) {
142 if (pageInfo.getIsThreadSafe() == null) {
143 pageInfo.setIsThreadSafe(value, n, err);
144 } else if (!pageInfo.getIsThreadSafe().equals(value)) {
145 err.jspError(n, "jsp.error.page.conflict.isthreadsafe",
146 pageInfo.getIsThreadSafe(), value);
147 }
148 } else if ("isELIgnored".equals(attr)) {
149 if (pageInfo.getIsELIgnored() == null) {
150 pageInfo.setIsELIgnored(value, n, err, true);
151 } else if (!pageInfo.getIsELIgnored().equals(value)) {
152 err.jspError(n, "jsp.error.page.conflict.iselignored",
153 pageInfo.getIsELIgnored(), value);
154 }
155 } else if ("isErrorPage".equals(attr)) {
156 if (pageInfo.getIsErrorPage() == null) {
157 pageInfo.setIsErrorPage(value, n, err);
158 } else if (!pageInfo.getIsErrorPage().equals(value)) {
159 err.jspError(n, "jsp.error.page.conflict.iserrorpage",
160 pageInfo.getIsErrorPage(), value);
161 }
162 } else if ("errorPage".equals(attr)) {
163 if (pageInfo.getErrorPage() == null) {
164 pageInfo.setErrorPage(value);
165 } else if (!pageInfo.getErrorPage().equals(value)) {
166 err.jspError(n, "jsp.error.page.conflict.errorpage",
167 pageInfo.getErrorPage(), value);
168 }
169 } else if ("info".equals(attr)) {
170 if (pageInfo.getInfo() == null) {
171 pageInfo.setInfo(value);
172 } else if (!pageInfo.getInfo().equals(value)) {
173 err.jspError(n, "jsp.error.page.conflict.info",
174 pageInfo.getInfo(), value);
175 }
176 } else if ("pageEncoding".equals(attr)) {
177 if (pageEncodingSeen)
178 err.jspError(n, "jsp.error.page.multi.pageencoding");
179
180 pageEncodingSeen = true;
181 comparePageEncodings(value, n);
182 }
183 }
184
185
186 if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
187 err.jspError(n, "jsp.error.page.badCombo");
188
189
190
191 pageInfo.addImports(n.getImports());
192 }
193
194 public void visit(Node.TagDirective n) throws JasperException {
195
196
197
198
199
200
201 Attributes attrs = n.getAttributes();
202 for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
203 String attr = attrs.getQName(i);
204 String value = attrs.getValue(i);
205
206 if ("language".equals(attr)) {
207 if (pageInfo.getLanguage(false) == null) {
208 pageInfo.setLanguage(value, n, err, false);
209 } else if (!pageInfo.getLanguage(false).equals(value)) {
210 err.jspError(n, "jsp.error.tag.conflict.language",
211 pageInfo.getLanguage(false), value);
212 }
213 } else if ("isELIgnored".equals(attr)) {
214 if (pageInfo.getIsELIgnored() == null) {
215 pageInfo.setIsELIgnored(value, n, err, false);
216 } else if (!pageInfo.getIsELIgnored().equals(value)) {
217 err.jspError(n, "jsp.error.tag.conflict.iselignored",
218 pageInfo.getIsELIgnored(), value);
219 }
220 } else if ("pageEncoding".equals(attr)) {
221 if (pageEncodingSeen)
222 err.jspError(n, "jsp.error.tag.multi.pageencoding");
223 pageEncodingSeen = true;
224 n.getRoot().setPageEncoding(value);
225 }
226 }
227
228
229
230 pageInfo.addImports(n.getImports());
231 }
232
233 public void visit(Node.AttributeDirective n) throws JasperException {
234
235
236
237 }
238
239 public void visit(Node.VariableDirective n) throws JasperException {
240
241
242
243 }
244
245
246
247
248
249
250
251
252
253
254
255 private void comparePageEncodings(String pageDirEnc,
256 Node.PageDirective pageDir)
257 throws JasperException {
258
259 Node.Root root = pageDir.getRoot();
260 String configEnc = root.getJspConfigPageEncoding();
261
262
263
264
265
266
267
268 if (configEnc != null && !pageDirEnc.equals(configEnc)
269 && (!pageDirEnc.startsWith("UTF-16")
270 || !configEnc.startsWith("UTF-16"))) {
271 err.jspError(pageDir,
272 "jsp.error.config_pagedir_encoding_mismatch",
273 configEnc, pageDirEnc);
274 }
275
276
277
278
279
280
281
282
283 if (root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) {
284 String pageEnc = root.getPageEncoding();
285 if (!pageDirEnc.equals(pageEnc)
286 && (!pageDirEnc.startsWith("UTF-16")
287 || !pageEnc.startsWith("UTF-16"))) {
288 err.jspError(pageDir,
289 "jsp.error.prolog_pagedir_encoding_mismatch",
290 pageEnc, pageDirEnc);
291 }
292 }
293 }
294 }
295
296 /***
297 * A visitor for validating nodes other than page directives
298 */
299 static class ValidateVisitor extends Node.Visitor {
300
301 private PageInfo pageInfo;
302 private ErrorDispatcher err;
303 private ClassLoader loader;
304
305 private static final JspUtil.ValidAttribute[] jspRootAttrs = {
306 new JspUtil.ValidAttribute("xsi:schemaLocation"),
307 new JspUtil.ValidAttribute("version", true)};
308
309 private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = {
310 new JspUtil.ValidAttribute("file", true)};
311
312 private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
313 new JspUtil.ValidAttribute("uri"),
314 new JspUtil.ValidAttribute("tagdir"),
315 new JspUtil.ValidAttribute("prefix", true)};
316
317 private static final JspUtil.ValidAttribute[] includeActionAttrs = {
318 new JspUtil.ValidAttribute("page", true, true),
319 new JspUtil.ValidAttribute("flush")};
320
321 private static final JspUtil.ValidAttribute[] paramActionAttrs = {
322 new JspUtil.ValidAttribute("name", true),
323 new JspUtil.ValidAttribute("value", true, true)};
324
325 private static final JspUtil.ValidAttribute[] forwardActionAttrs = {
326 new JspUtil.ValidAttribute("page", true, true)};
327
328 private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
329 new JspUtil.ValidAttribute("name", true),
330 new JspUtil.ValidAttribute("property", true)};
331
332 private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
333 new JspUtil.ValidAttribute("name", true),
334 new JspUtil.ValidAttribute("property", true),
335 new JspUtil.ValidAttribute("value", false, true),
336 new JspUtil.ValidAttribute("param")};
337
338 private static final JspUtil.ValidAttribute[] useBeanAttrs = {
339 new JspUtil.ValidAttribute("id", true),
340 new JspUtil.ValidAttribute("scope"),
341 new JspUtil.ValidAttribute("class"),
342 new JspUtil.ValidAttribute("type"),
343 new JspUtil.ValidAttribute("beanName", false, true)};
344
345 private static final JspUtil.ValidAttribute[] plugInAttrs = {
346 new JspUtil.ValidAttribute("type", true),
347 new JspUtil.ValidAttribute("code", true),
348 new JspUtil.ValidAttribute("codebase"),
349 new JspUtil.ValidAttribute("align"),
350 new JspUtil.ValidAttribute("archive"),
351 new JspUtil.ValidAttribute("height", false, true),
352 new JspUtil.ValidAttribute("hspace"),
353 new JspUtil.ValidAttribute("jreversion"),
354 new JspUtil.ValidAttribute("name"),
355 new JspUtil.ValidAttribute("vspace"),
356 new JspUtil.ValidAttribute("width", false, true),
357 new JspUtil.ValidAttribute("nspluginurl"),
358 new JspUtil.ValidAttribute("iepluginurl")};
359
360 private static final JspUtil.ValidAttribute[] attributeAttrs = {
361 new JspUtil.ValidAttribute("name", true),
362 new JspUtil.ValidAttribute("trim")};
363
364 private static final JspUtil.ValidAttribute[] invokeAttrs = {
365 new JspUtil.ValidAttribute("fragment", true),
366 new JspUtil.ValidAttribute("var"),
367 new JspUtil.ValidAttribute("varReader"),
368 new JspUtil.ValidAttribute("scope")};
369
370 private static final JspUtil.ValidAttribute[] doBodyAttrs = {
371 new JspUtil.ValidAttribute("var"),
372 new JspUtil.ValidAttribute("varReader"),
373 new JspUtil.ValidAttribute("scope")};
374
375 private static final JspUtil.ValidAttribute[] jspOutputAttrs = {
376 new JspUtil.ValidAttribute("omit-xml-declaration"),
377 new JspUtil.ValidAttribute("doctype-root-element"),
378 new JspUtil.ValidAttribute("doctype-public"),
379 new JspUtil.ValidAttribute("doctype-system")};
380
381
382
383
384 ValidateVisitor(Compiler compiler) {
385 this.pageInfo = compiler.getPageInfo();
386 this.err = compiler.getErrorDispatcher();
387 this.loader = compiler.getCompilationContext().getClassLoader();
388 }
389
390 public void visit(Node.JspRoot n) throws JasperException {
391 JspUtil.checkAttributes("Jsp:root", n,
392 jspRootAttrs, err);
393 String version = n.getTextAttribute("version");
394 if (!version.equals("1.2") && !version.equals("2.0")) {
395 err.jspError(n, "jsp.error.jsproot.version.invalid", version);
396 }
397 visitBody(n);
398 }
399
400 public void visit(Node.IncludeDirective n) throws JasperException {
401 JspUtil.checkAttributes("Include directive", n,
402 includeDirectiveAttrs, err);
403 visitBody(n);
404 }
405
406 public void visit(Node.TaglibDirective n) throws JasperException {
407 JspUtil.checkAttributes("Taglib directive", n,
408 taglibDirectiveAttrs, err);
409
410 String uri = n.getAttributeValue("uri");
411 String tagdir = n.getAttributeValue("tagdir");
412 if (uri == null && tagdir == null) {
413 err.jspError(n, "jsp.error.taglibDirective.missing.location");
414 }
415 if (uri != null && tagdir != null) {
416 err.jspError(n, "jsp.error.taglibDirective.both_uri_and_tagdir");
417 }
418 }
419
420 public void visit(Node.ParamAction n) throws JasperException {
421 JspUtil.checkAttributes("Param action", n,
422 paramActionAttrs, err);
423
424
425 throwErrorIfExpression(n, "name", "jsp:param");
426 n.setValue(getJspAttribute("value", null, null,
427 n.getAttributeValue("value"),
428 java.lang.String.class,
429 n, false));
430 visitBody(n);
431 }
432
433 public void visit(Node.ParamsAction n) throws JasperException {
434
435 Node.Nodes subElems = n.getBody();
436 if (subElems == null) {
437 err.jspError(n, "jsp.error.params.emptyBody");
438 }
439 visitBody(n);
440 }
441
442 public void visit(Node.IncludeAction n) throws JasperException {
443 JspUtil.checkAttributes("Include action", n,
444 includeActionAttrs, err);
445 n.setPage(getJspAttribute("page", null, null,
446 n.getAttributeValue("page"),
447 java.lang.String.class, n, false));
448 visitBody(n);
449 }
450
451 ;
452
453 public void visit(Node.ForwardAction n) throws JasperException {
454 JspUtil.checkAttributes("Forward", n,
455 forwardActionAttrs, err);
456 n.setPage(getJspAttribute("page", null, null,
457 n.getAttributeValue("page"),
458 java.lang.String.class, n, false));
459 visitBody(n);
460 }
461
462 public void visit(Node.GetProperty n) throws JasperException {
463 JspUtil.checkAttributes("GetProperty", n,
464 getPropertyAttrs, err);
465 }
466
467 public void visit(Node.SetProperty n) throws JasperException {
468 JspUtil.checkAttributes("SetProperty", n,
469 setPropertyAttrs, err);
470 String property = n.getTextAttribute("property");
471 String param = n.getTextAttribute("param");
472 String value = n.getAttributeValue("value");
473
474 n.setValue(getJspAttribute("value", null, null, value,
475 java.lang.Object.class, n, false));
476
477 boolean valueSpecified = n.getValue() != null;
478
479 if ("*".equals(property)) {
480 if (param != null || valueSpecified)
481 err.jspError(n, "jsp.error.setProperty.invalid");
482
483 } else if (param != null && valueSpecified) {
484 err.jspError(n, "jsp.error.setProperty.invalid");
485 }
486
487 visitBody(n);
488 }
489
490 public void visit(Node.UseBean n) throws JasperException {
491 JspUtil.checkAttributes("UseBean", n,
492 useBeanAttrs, err);
493
494 String name = n.getTextAttribute("id");
495 String scope = n.getTextAttribute("scope");
496 JspUtil.checkScope(scope, n, err);
497 String className = n.getTextAttribute("class");
498 String type = n.getTextAttribute("type");
499 BeanRepository beanInfo = pageInfo.getBeanRepository();
500
501 if (className == null && type == null)
502 err.jspError(n, "jsp.error.usebean.missingType");
503
504 if (beanInfo.checkVariable(name))
505 err.jspError(n, "jsp.error.usebean.duplicate");
506
507 if ("session".equals(scope) && !pageInfo.isSession())
508 err.jspError(n, "jsp.error.usebean.noSession");
509
510 Node.JspAttribute jattr
511 = getJspAttribute("beanName", null, null,
512 n.getAttributeValue("beanName"),
513 java.lang.String.class, n, false);
514 n.setBeanName(jattr);
515 if (className != null && jattr != null)
516 err.jspError(n, "jsp.error.usebean.notBoth");
517
518 if (className == null)
519 className = type;
520
521 beanInfo.addBean(n, name, className, scope);
522
523 visitBody(n);
524 }
525
526 public void visit(Node.PlugIn n) throws JasperException {
527 JspUtil.checkAttributes("Plugin", n, plugInAttrs, err);
528
529 throwErrorIfExpression(n, "type", "jsp:plugin");
530 throwErrorIfExpression(n, "code", "jsp:plugin");
531 throwErrorIfExpression(n, "codebase", "jsp:plugin");
532 throwErrorIfExpression(n, "align", "jsp:plugin");
533 throwErrorIfExpression(n, "archive", "jsp:plugin");
534 throwErrorIfExpression(n, "hspace", "jsp:plugin");
535 throwErrorIfExpression(n, "jreversion", "jsp:plugin");
536 throwErrorIfExpression(n, "name", "jsp:plugin");
537 throwErrorIfExpression(n, "vspace", "jsp:plugin");
538 throwErrorIfExpression(n, "nspluginurl", "jsp:plugin");
539 throwErrorIfExpression(n, "iepluginurl", "jsp:plugin");
540
541 String type = n.getTextAttribute("type");
542 if (type == null)
543 err.jspError(n, "jsp.error.plugin.notype");
544 if (!type.equals("bean") && !type.equals("applet"))
545 err.jspError(n, "jsp.error.plugin.badtype");
546 if (n.getTextAttribute("code") == null)
547 err.jspError(n, "jsp.error.plugin.nocode");
548
549 Node.JspAttribute width
550 = getJspAttribute("width", null, null,
551 n.getAttributeValue("width"),
552 java.lang.String.class, n, false);
553 n.setWidth(width);
554
555 Node.JspAttribute height
556 = getJspAttribute("height", null, null,
557 n.getAttributeValue("height"),
558 java.lang.String.class, n, false);
559 n.setHeight(height);
560
561 visitBody(n);
562 }
563
564 public void visit(Node.NamedAttribute n) throws JasperException {
565 JspUtil.checkAttributes("Attribute", n,
566 attributeAttrs, err);
567 visitBody(n);
568 }
569
570 public void visit(Node.JspBody n) throws JasperException {
571 visitBody(n);
572 }
573
574 public void visit(Node.Declaration n) throws JasperException {
575 if (pageInfo.isScriptingInvalid()) {
576 err.jspError(n.getStart(), "jsp.error.no.scriptlets");
577 }
578 }
579
580 public void visit(Node.Expression n) throws JasperException {
581 if (pageInfo.isScriptingInvalid()) {
582 err.jspError(n.getStart(), "jsp.error.no.scriptlets");
583 }
584 }
585
586 public void visit(Node.Scriptlet n) throws JasperException {
587 if (pageInfo.isScriptingInvalid()) {
588 err.jspError(n.getStart(), "jsp.error.no.scriptlets");
589 }
590 }
591
592 public void visit(Node.ELExpression n) throws JasperException {
593 if (!pageInfo.isELIgnored()) {
594 String expressions = "${" + new String(n.getText()) + "}";
595 ELNode.Nodes el = ELParser.parse(expressions);
596 validateFunctions(el, n);
597 JspUtil.validateExpressions(
598 n.getStart(),
599 expressions,
600 java.lang.String.class,
601
602 getFunctionMapper(el),
603 err);
604 n.setEL(el);
605 }
606 }
607
608 public void visit(Node.UninterpretedTag n) throws JasperException {
609 if (n.getNamedAttributeNodes().size() != 0) {
610 err.jspError(n, "jsp.error.namedAttribute.invalidUse");
611 }
612
613 Attributes attrs = n.getAttributes();
614 if (attrs != null) {
615 int attrSize = attrs.getLength();
616 Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize];
617 for (int i = 0; i < attrSize; i++) {
618 jspAttrs[i] = getJspAttribute(attrs.getQName(i),
619 attrs.getURI(i),
620 attrs.getLocalName(i),
621 attrs.getValue(i),
622 java.lang.Object.class,
623 n,
624 false);
625 }
626 n.setJspAttributes(jspAttrs);
627 }
628
629 visitBody(n);
630 }
631
632 public void visit(Node.CustomTag n) throws JasperException {
633
634 TagInfo tagInfo = n.getTagInfo();
635 if (tagInfo == null) {
636 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
637 }
638
639
640
641
642 if (n.implementsSimpleTag() &&
643 tagInfo.getBodyContent().equalsIgnoreCase(TagInfo.BODY_CONTENT_JSP)) {
644 err.jspError(n, "jsp.error.simpletag.badbodycontent",
645 tagInfo.getTagClassName());
646 }
647
648
649
650
651
652
653 if (tagInfo.hasDynamicAttributes()
654 && !n.implementsDynamicAttributes()) {
655 err.jspError(n, "jsp.error.dynamic.attributes.not.implemented",
656 n.getQName());
657 }
658
659
660
661
662
663
664
665 TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
666 String customActionUri = n.getURI();
667 Attributes attrs = n.getAttributes();
668 int attrsSize = (attrs == null) ? 0 : attrs.getLength();
669 for (int i = 0; i < tldAttrs.length; i++) {
670 String attr = null;
671 if (attrs != null) {
672 attr = attrs.getValue(tldAttrs[i].getName());
673 if (attr == null) {
674 attr = attrs.getValue(customActionUri,
675 tldAttrs[i].getName());
676 }
677 }
678 Node.NamedAttribute na =
679 n.getNamedAttributeNode(tldAttrs[i].getName());
680
681 if (tldAttrs[i].isRequired() && attr == null && na == null) {
682 err.jspError(n, "jsp.error.missing_attribute",
683 tldAttrs[i].getName(), n.getLocalName());
684 }
685 if (attr != null && na != null) {
686 err.jspError(n, "jsp.error.duplicate.name.jspattribute",
687 tldAttrs[i].getName());
688 }
689 }
690
691 Node.Nodes naNodes = n.getNamedAttributeNodes();
692 int jspAttrsSize = naNodes.size() + attrsSize;
693 Node.JspAttribute[] jspAttrs = null;
694 if (jspAttrsSize > 0) {
695 jspAttrs = new Node.JspAttribute[jspAttrsSize];
696 }
697 Hashtable tagDataAttrs = new Hashtable(attrsSize);
698
699 checkXmlAttributes(n, jspAttrs, tagDataAttrs);
700 checkNamedAttributes(n, jspAttrs, attrsSize, tagDataAttrs);
701
702 TagData tagData = new TagData(tagDataAttrs);
703
704
705
706
707 TagExtraInfo tei = tagInfo.getTagExtraInfo();
708 if (tei != null
709 && tei.getVariableInfo(tagData) != null
710 && tei.getVariableInfo(tagData).length > 0
711 && tagInfo.getTagVariableInfos().length > 0) {
712 err.jspError("jsp.error.non_null_tei_and_var_subelems",
713 n.getQName());
714 }
715
716 n.setTagData(tagData);
717 n.setJspAttributes(jspAttrs);
718
719 visitBody(n);
720 }
721
722 public void visit(Node.JspElement n) throws JasperException {
723
724 Attributes attrs = n.getAttributes();
725 if (attrs == null) {
726 err.jspError(n, "jsp.error.jspelement.missing.name");
727 }
728 int xmlAttrLen = attrs.getLength();
729
730 Node.Nodes namedAttrs = n.getNamedAttributeNodes();
731
732
733
734 int jspAttrSize = xmlAttrLen - 1 + namedAttrs.size();
735
736 Node.JspAttribute[] jspAttrs = new Node.JspAttribute[jspAttrSize];
737 int jspAttrIndex = 0;
738
739
740 for (int i = 0; i < xmlAttrLen; i++) {
741 if ("name".equals(attrs.getLocalName(i))) {
742 n.setNameAttribute(getJspAttribute(attrs.getQName(i),
743 attrs.getURI(i),
744 attrs.getLocalName(i),
745 attrs.getValue(i),
746 java.lang.String.class,
747 n,
748 false));
749 } else {
750 if (jspAttrIndex < jspAttrSize) {
751 jspAttrs[jspAttrIndex++]
752 = getJspAttribute(attrs.getQName(i),
753 attrs.getURI(i),
754 attrs.getLocalName(i),
755 attrs.getValue(i),
756 java.lang.Object.class,
757 n,
758 false);
759 }
760 }
761 }
762 if (n.getNameAttribute() == null) {
763 err.jspError(n, "jsp.error.jspelement.missing.name");
764 }
765
766
767 for (int i = 0; i < namedAttrs.size(); i++) {
768 Node.NamedAttribute na =
769 (Node.NamedAttribute) namedAttrs.getNode(i);
770 jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na, false);
771 }
772
773 n.setJspAttributes(jspAttrs);
774
775 visitBody(n);
776 }
777
778 public void visit(Node.JspOutput n) throws JasperException {
779 JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs, err);
780
781 if (n.getBody() != null) {
782 err.jspError(n, "jsp.error.jspoutput.nonemptybody");
783 }
784
785 String omitXmlDecl = n.getAttributeValue("omit-xml-declaration");
786 String doctypeName = n.getAttributeValue("doctype-root-element");
787 String doctypePublic = n.getAttributeValue("doctype-public");
788 String doctypeSystem = n.getAttributeValue("doctype-system");
789
790 String omitXmlDeclOld = pageInfo.getOmitXmlDecl();
791 String doctypeNameOld = pageInfo.getDoctypeName();
792 String doctypePublicOld = pageInfo.getDoctypePublic();
793 String doctypeSystemOld = pageInfo.getDoctypeSystem();
794
795 if (omitXmlDecl != null && omitXmlDeclOld != null &&
796 !omitXmlDecl.equals(omitXmlDeclOld)) {
797 err.jspError(n, "jsp.error.jspoutput.conflict",
798 "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl);
799 }
800
801 if (doctypeName != null && doctypeNameOld != null &&
802 !doctypeName.equals(doctypeNameOld)) {
803 err.jspError(n, "jsp.error.jspoutput.conflict",
804 "doctype-root-element", doctypeNameOld, doctypeName);
805 }
806
807 if (doctypePublic != null && doctypePublicOld != null &&
808 !doctypePublic.equals(doctypePublicOld)) {
809 err.jspError(n, "jsp.error.jspoutput.conflict",
810 "doctype-public", doctypePublicOld, doctypePublic);
811 }
812
813 if (doctypeSystem != null && doctypeSystemOld != null &&
814 !doctypeSystem.equals(doctypeSystemOld)) {
815 err.jspError(n, "jsp.error.jspoutput.conflict",
816 "doctype-system", doctypeSystemOld, doctypeSystem);
817 }
818
819 if (doctypeName == null && doctypeSystem != null ||
820 doctypeName != null && doctypeSystem == null) {
821 err.jspError(n, "jsp.error.jspoutput.doctypenamesystem");
822 }
823
824 if (doctypePublic != null && doctypeSystem == null) {
825 err.jspError(n, "jsp.error.jspoutput.doctypepulicsystem");
826 }
827
828 if (omitXmlDecl != null) {
829 pageInfo.setOmitXmlDecl(omitXmlDecl);
830 }
831 if (doctypeName != null) {
832 pageInfo.setDoctypeName(doctypeName);
833 }
834 if (doctypeSystem != null) {
835 pageInfo.setDoctypeSystem(doctypeSystem);
836 }
837 if (doctypePublic != null) {
838 pageInfo.setDoctypePublic(doctypePublic);
839 }
840 }
841
842 public void visit(Node.InvokeAction n) throws JasperException {
843
844 JspUtil.checkAttributes("Invoke", n, invokeAttrs, err);
845
846 String scope = n.getTextAttribute("scope");
847 JspUtil.checkScope(scope, n, err);
848
849 String var = n.getTextAttribute("var");
850 String varReader = n.getTextAttribute("varReader");
851 if (scope != null && var == null && varReader == null) {
852 err.jspError(n, "jsp.error.missing_var_or_varReader");
853 }
854 if (var != null && varReader != null) {
855 err.jspError(n, "jsp.error.var_and_varReader");
856 }
857 }
858
859 public void visit(Node.DoBodyAction n) throws JasperException {
860
861 JspUtil.checkAttributes("DoBody", n, doBodyAttrs, err);
862
863 String scope = n.getTextAttribute("scope");
864 JspUtil.checkScope(scope, n, err);
865
866 String var = n.getTextAttribute("var");
867 String varReader = n.getTextAttribute("varReader");
868 if (scope != null && var == null && varReader == null) {
869 err.jspError(n, "jsp.error.missing_var_or_varReader");
870 }
871 if (var != null && varReader != null) {
872 err.jspError(n, "jsp.error.var_and_varReader");
873 }
874 }
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897 private void checkXmlAttributes(Node.CustomTag n,
898 Node.JspAttribute[] jspAttrs,
899 Hashtable tagDataAttrs)
900 throws JasperException {
901
902 TagInfo tagInfo = n.getTagInfo();
903 if (tagInfo == null) {
904 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
905 }
906 TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
907 Attributes attrs = n.getAttributes();
908
909 for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
910 boolean found = false;
911 for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) {
912 if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
913 && (attrs.getURI(i) == null
914 || attrs.getURI(i).length() == 0
915 || attrs.getURI(i).equals(n.getURI()))) {
916 if (tldAttrs[j].canBeRequestTime()) {
917 Class expectedType = String.class;
918 try {
919 String typeStr = tldAttrs[j].getTypeName();
920 if (tldAttrs[j].isFragment()) {
921 expectedType = JspFragment.class;
922 } else if (typeStr != null) {
923 expectedType = JspUtil.toClass(typeStr,
924 loader);
925 }
926 jspAttrs[i]
927 = getJspAttribute(attrs.getQName(i),
928 attrs.getURI(i),
929 attrs.getLocalName(i),
930 attrs.getValue(i),
931 expectedType,
932 n,
933 false);
934 } catch (ClassNotFoundException e) {
935 err.jspError(n,
936 "jsp.error.unknown_attribute_type",
937 tldAttrs[j].getName(),
938 tldAttrs[j].getTypeName());
939 }
940 } else {
941
942
943 if (isExpression(n, attrs.getValue(i))) {
944 err.jspError(n,
945 "jsp.error.attribute.custom.non_rt_with_expr",
946 tldAttrs[j].getName());
947 }
948 jspAttrs[i]
949 = new Node.JspAttribute(attrs.getQName(i),
950 attrs.getURI(i),
951 attrs.getLocalName(i),
952 attrs.getValue(i),
953 false,
954 null,
955 false);
956 }
957 if (isExpression(n, attrs.getValue(i))) {
958 tagDataAttrs.put(attrs.getQName(i),
959 TagData.REQUEST_TIME_VALUE);
960 } else {
961 tagDataAttrs.put(attrs.getQName(i),
962 attrs.getValue(i));
963 }
964 found = true;
965 break;
966 }
967 }
968 if (!found) {
969 if (tagInfo.hasDynamicAttributes()) {
970 jspAttrs[i] = getJspAttribute(attrs.getQName(i),
971 attrs.getURI(i),
972 attrs.getLocalName(i),
973 attrs.getValue(i),
974 java.lang.Object.class,
975 n,
976 true);
977 } else {
978 err.jspError(n, "jsp.error.bad_attribute",
979 attrs.getQName(i), n.getLocalName());
980 }
981 }
982 }
983 }
984
985
986
987
988
989 private void checkNamedAttributes(Node.CustomTag n,
990 Node.JspAttribute[] jspAttrs,
991 int start,
992 Hashtable tagDataAttrs)
993 throws JasperException {
994
995 TagInfo tagInfo = n.getTagInfo();
996 if (tagInfo == null) {
997 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
998 }
999 TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
1000 Node.Nodes naNodes = n.getNamedAttributeNodes();
1001
1002 for (int i = 0; i < naNodes.size(); i++) {
1003 Node.NamedAttribute na = (Node.NamedAttribute)
1004 naNodes.getNode(i);
1005 boolean found = false;
1006 for (int j = 0; j < tldAttrs.length; j++) {
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 String attrPrefix = na.getPrefix();
1017 if (na.getLocalName().equals(tldAttrs[j].getName())
1018 && (attrPrefix == null || attrPrefix.length() == 0
1019 || attrPrefix.equals(n.getPrefix()))) {
1020 jspAttrs[start + i] = new Node.JspAttribute(na, false);
1021 NamedAttributeVisitor nav = null;
1022 if (na.getBody() != null) {
1023 nav = new NamedAttributeVisitor();
1024 na.getBody().visit(nav);
1025 }
1026 if (nav != null && nav.hasDynamicContent()) {
1027 tagDataAttrs.put(na.getName(),
1028 TagData.REQUEST_TIME_VALUE);
1029 } else {
1030 tagDataAttrs.put(na.getName(), na.getText());
1031 }
1032 found = true;
1033 break;
1034 }
1035 }
1036 if (!found) {
1037 if (tagInfo.hasDynamicAttributes()) {
1038 jspAttrs[start + i] = new Node.JspAttribute(na, true);
1039 } else {
1040 err.jspError(n, "jsp.error.bad_attribute",
1041 na.getName(), n.getLocalName());
1042 }
1043 }
1044 }
1045 }
1046
1047 /***
1048 * Preprocess attributes that can be expressions. Expression
1049 * delimiters are stripped.
1050 * <p/>
1051 * If value is null, checks if there are any
1052 * NamedAttribute subelements in the tree node, and if so,
1053 * constructs a JspAttribute out of a child NamedAttribute node.
1054 */
1055 private Node.JspAttribute getJspAttribute(String qName,
1056 String uri,
1057 String localName,
1058 String value,
1059 Class expectedType,
1060 Node n,
1061 boolean dynamic)
1062 throws JasperException {
1063
1064 Node.JspAttribute result = null;
1065
1066
1067
1068
1069
1070 if (value != null) {
1071 if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) {
1072 result = new Node.JspAttribute(
1073 qName,
1074 uri,
1075 localName,
1076 value.substring(2, value.length() - 1),
1077 true,
1078 null,
1079 dynamic);
1080 } else if (!n.getRoot().isXmlSyntax() && value.startsWith("<%=")) {
1081 result = new Node.JspAttribute(
1082 qName,
1083 uri,
1084 localName,
1085 value.substring(3, value.length() - 2),
1086 true,
1087 null,
1088 dynamic);
1089 } else {
1090
1091
1092
1093
1094
1095
1096 ELNode.Nodes el = ELParser.parse(value);
1097 if (el.containsEL() && !pageInfo.isELIgnored()) {
1098 validateFunctions(el, n);
1099 JspUtil.validateExpressions(
1100 n.getStart(),
1101 value,
1102 expectedType,
1103 getFunctionMapper(el),
1104 this.err);
1105
1106
1107 result = new Node.JspAttribute(qName, uri, localName,
1108 value, false, el,
1109 dynamic);
1110 } else {
1111 value = value.replace(Constants.HACK_CHAR, '$');
1112 result = new Node.JspAttribute(qName, uri, localName,
1113 value, false, null,
1114 dynamic);
1115 }
1116 }
1117 } else {
1118
1119
1120
1121
1122 Node.NamedAttribute namedAttributeNode =
1123 n.getNamedAttributeNode(qName);
1124 if (namedAttributeNode != null) {
1125 result = new Node.JspAttribute(namedAttributeNode,
1126 dynamic);
1127 }
1128 }
1129
1130 return result;
1131 }
1132
1133
1134
1135
1136
1137 private boolean isExpression(Node n, String value) {
1138 if ((n.getRoot().isXmlSyntax() && value.startsWith("%="))
1139 || (!n.getRoot().isXmlSyntax() && value.startsWith("<%="))
1140 || (value.indexOf("${") != -1 && !pageInfo.isELIgnored()))
1141 return true;
1142 else
1143 return false;
1144 }
1145
1146
1147
1148
1149
1150
1151 private void throwErrorIfExpression(Node n, String attrName,
1152 String actionName)
1153 throws JasperException {
1154 if (n.getAttributes() != null
1155 && n.getAttributes().getValue(attrName) != null
1156 && isExpression(n, n.getAttributes().getValue(attrName))) {
1157 err.jspError(n,
1158 "jsp.error.attribute.standard.non_rt_with_expr",
1159 attrName, actionName);
1160 }
1161 }
1162
1163 private static class NamedAttributeVisitor extends Node.Visitor {
1164 private boolean hasDynamicContent;
1165
1166 public void doVisit(Node n) throws JasperException {
1167 if (!(n instanceof Node.JspText)
1168 && !(n instanceof Node.TemplateText)) {
1169 hasDynamicContent = true;
1170 }
1171 visitBody(n);
1172 }
1173
1174 public boolean hasDynamicContent() {
1175 return hasDynamicContent;
1176 }
1177 }
1178
1179 private String findUri(String prefix, Node n) {
1180
1181 for (Node p = n; p != null; p = p.getParent()) {
1182 Attributes attrs = p.getTaglibAttributes();
1183 if (attrs == null) {
1184 continue;
1185 }
1186 for (int i = 0; i < attrs.getLength(); i++) {
1187 String name = attrs.getQName(i);
1188 int k = name.indexOf(':');
1189 if (prefix == null && k < 0) {
1190
1191 return attrs.getValue(i);
1192 }
1193 if (prefix != null && k >= 0 &&
1194 prefix.equals(name.substring(k + 1))) {
1195 return attrs.getValue(i);
1196 }
1197 }
1198 }
1199 return null;
1200 }
1201
1202 /***
1203 * Validate functions in EL expressions
1204 */
1205 private void validateFunctions(ELNode.Nodes el, Node n)
1206 throws JasperException {
1207
1208 class FVVisitor extends ELNode.Visitor {
1209
1210 Node n;
1211
1212 FVVisitor(Node n) {
1213 this.n = n;
1214 }
1215
1216 public void visit(ELNode.Function func) throws JasperException {
1217 String prefix = func.getPrefix();
1218 String function = func.getName();
1219 String uri = null;
1220
1221 if (n.getRoot().isXmlSyntax()) {
1222 uri = findUri(prefix, n);
1223 } else if (prefix != null) {
1224 uri = pageInfo.getURI(prefix);
1225 }
1226
1227 if (uri == null) {
1228 if (prefix == null) {
1229 err.jspError(n, "jsp.error.noFunctionPrefix",
1230 function);
1231 } else {
1232 err.jspError(n,
1233 "jsp.error.attribute.invalidPrefix", prefix);
1234 }
1235 }
1236 TagLibraryInfo taglib = pageInfo.getTaglib(uri);
1237 FunctionInfo funcInfo = null;
1238 if (taglib != null) {
1239 funcInfo = taglib.getFunction(function);
1240 }
1241 if (funcInfo == null) {
1242 err.jspError(n, "jsp.error.noFunction", function);
1243 }
1244
1245 func.setUri(uri);
1246 func.setFunctionInfo(funcInfo);
1247 processSignature(func);
1248 }
1249 }
1250
1251 el.visit(new FVVisitor(n));
1252 }
1253
1254 private void processSignature(ELNode.Function func)
1255 throws JasperException {
1256 func.setMethodName(getMethod(func));
1257 func.setParameters(getParameters(func));
1258 }
1259
1260 /***
1261 * Get the method name from the signature.
1262 */
1263 private String getMethod(ELNode.Function func)
1264 throws JasperException {
1265 FunctionInfo funcInfo = func.getFunctionInfo();
1266 String signature = funcInfo.getFunctionSignature();
1267
1268 int start = signature.indexOf(' ');
1269 if (start < 0) {
1270 err.jspError("jsp.error.tld.fn.invalid.signature",
1271 func.getPrefix(), func.getName());
1272 }
1273 int end = signature.indexOf('(');
1274 if (end < 0) {
1275 err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected",
1276 func.getPrefix(), func.getName());
1277 }
1278 return signature.substring(start + 1, end).trim();
1279 }
1280
1281 /***
1282 * Get the parameters types from the function signature.
1283 *
1284 * @return An array of parameter class names
1285 */
1286 private String[] getParameters(ELNode.Function func)
1287 throws JasperException {
1288 FunctionInfo funcInfo = func.getFunctionInfo();
1289 String signature = funcInfo.getFunctionSignature();
1290 ArrayList params = new ArrayList();
1291
1292
1293
1294 int start = signature.indexOf('(') + 1;
1295 boolean lastArg = false;
1296 while (true) {
1297 int p = signature.indexOf(',', start);
1298 if (p < 0) {
1299 p = signature.indexOf(')', start);
1300 if (p < 0) {
1301 err.jspError("jsp.error.tld.fn.invalid.signature",
1302 func.getPrefix(), func.getName());
1303 }
1304 lastArg = true;
1305 }
1306 String arg = signature.substring(start, p).trim();
1307 if (!"".equals(arg)) {
1308 params.add(arg);
1309 }
1310 if (lastArg) {
1311 break;
1312 }
1313 start = p + 1;
1314 }
1315 return (String[]) params.toArray(new String[params.size()]);
1316 }
1317
1318 private FunctionMapper getFunctionMapper(ELNode.Nodes el)
1319 throws JasperException {
1320
1321 class ValidateFunctionMapper implements FunctionMapper {
1322
1323 private HashMap fnmap = new java.util.HashMap();
1324
1325 public void mapFunction(String fnQName, Method method) {
1326 fnmap.put(fnQName, method);
1327 }
1328
1329 public Method resolveFunction(String prefix,
1330 String localName) {
1331 return (Method) this.fnmap.get(prefix + ":" + localName);
1332 }
1333 }
1334
1335 class MapperELVisitor extends ELNode.Visitor {
1336 ValidateFunctionMapper fmapper;
1337
1338 MapperELVisitor(ValidateFunctionMapper fmapper) {
1339 this.fmapper = fmapper;
1340 }
1341
1342 public void visit(ELNode.Function n) throws JasperException {
1343
1344 Class c = null;
1345 Method method = null;
1346 try {
1347 c = loader.loadClass(
1348 n.getFunctionInfo().getFunctionClass());
1349 } catch (ClassNotFoundException e) {
1350 err.jspError("jsp.error.function.classnotfound",
1351 n.getFunctionInfo().getFunctionClass(),
1352 n.getPrefix() + ':' + n.getName(),
1353 e.getMessage());
1354 }
1355 String paramTypes[] = n.getParameters();
1356 int size = paramTypes.length;
1357 Class params[] = new Class[size];
1358 int i = 0;
1359 try {
1360 for (i = 0; i < size; i++) {
1361 params[i] = JspUtil.toClass(paramTypes[i], loader);
1362 }
1363 method = c.getDeclaredMethod(n.getMethodName(),
1364 params);
1365 } catch (ClassNotFoundException e) {
1366 err.jspError("jsp.error.signature.classnotfound",
1367 paramTypes[i],
1368 n.getPrefix() + ':' + n.getName(),
1369 e.getMessage());
1370 } catch (NoSuchMethodException e) {
1371 err.jspError("jsp.error.noFunctionMethod",
1372 n.getMethodName(), n.getName(),
1373 c.getName());
1374 }
1375 fmapper.mapFunction(n.getPrefix() + ':' + n.getName(),
1376 method);
1377 }
1378 }
1379
1380 ValidateFunctionMapper fmapper = new ValidateFunctionMapper();
1381 el.visit(new MapperELVisitor(fmapper));
1382 return fmapper;
1383 }
1384 }
1385
1386 /***
1387 * A visitor for validating TagExtraInfo classes of all tags
1388 */
1389 static class TagExtraInfoVisitor extends Node.Visitor {
1390
1391 private ErrorDispatcher err;
1392
1393
1394
1395
1396 TagExtraInfoVisitor(Compiler compiler) {
1397 this.err = compiler.getErrorDispatcher();
1398 }
1399
1400 public void visit(Node.CustomTag n) throws JasperException {
1401 TagInfo tagInfo = n.getTagInfo();
1402 if (tagInfo == null) {
1403 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
1404 }
1405
1406 ValidationMessage[] errors = tagInfo.validate(n.getTagData());
1407 if (errors != null && errors.length != 0) {
1408 StringBuffer errMsg = new StringBuffer();
1409 errMsg.append("<h3>");
1410 errMsg.append(Localizer.getMessage(
1411 "jsp.error.tei.invalid.attributes", n.getQName()));
1412 errMsg.append("</h3>");
1413 for (int i = 0; i < errors.length; i++) {
1414 errMsg.append("<p>");
1415 if (errors[i].getId() != null) {
1416 errMsg.append(errors[i].getId());
1417 errMsg.append(": ");
1418 }
1419 errMsg.append(errors[i].getMessage());
1420 errMsg.append("</p>");
1421 }
1422
1423 err.jspError(n, errMsg.toString());
1424 }
1425
1426 visitBody(n);
1427 }
1428 }
1429
1430 public static void validate(Compiler compiler,
1431 Node.Nodes page) throws JasperException {
1432
1433
1434
1435
1436
1437 page.visit(new DirectiveVisitor(compiler));
1438
1439
1440 PageInfo pageInfo = compiler.getPageInfo();
1441 String contentType = pageInfo.getContentType();
1442
1443 if (contentType == null || contentType.indexOf("charset=") < 0) {
1444 boolean isXml = page.getRoot().isXmlSyntax();
1445 String defaultType;
1446 if (contentType == null) {
1447 defaultType = isXml ? "text/xml" : "text/html";
1448 } else {
1449 defaultType = contentType;
1450 }
1451
1452 String charset = null;
1453 if (isXml) {
1454 charset = "UTF-8";
1455 } else {
1456 if (!page.getRoot().isDefaultPageEncoding()) {
1457 charset = page.getRoot().getPageEncoding();
1458 }
1459 }
1460
1461 if (charset != null) {
1462 pageInfo.setContentType(defaultType + ";charset=" + charset);
1463 } else {
1464 pageInfo.setContentType(defaultType);
1465 }
1466 }
1467
1468
1469
1470
1471
1472
1473
1474 page.visit(new ValidateVisitor(compiler));
1475
1476
1477
1478
1479
1480 validateXmlView(new PageDataImpl(page, compiler), compiler);
1481
1482
1483
1484
1485
1486 page.visit(new TagExtraInfoVisitor(compiler));
1487
1488 }
1489
1490
1491 //**********************************************************************
1492 // Private (utility) methods
1493
1494 /**
1495 * Validate XML view against the TagLibraryValidator classes of all
1496 * imported tag libraries.
1497 */
1498 private static void validateXmlView(PageData xmlView, Compiler compiler)
1499 throws JasperException {
1500
1501 StringBuffer errMsg = null;
1502 ErrorDispatcher errDisp = compiler.getErrorDispatcher();
1503
1504 for (Iterator iter = compiler.getPageInfo().getTaglibs().iterator();
1505 iter.hasNext();) {
1506
1507 Object o = iter.next();
1508 if (!(o instanceof TagLibraryInfoImpl))
1509 continue;
1510 TagLibraryInfoImpl tli = (TagLibraryInfoImpl) o;
1511
1512 ValidationMessage[] errors = tli.validate(xmlView);
1513 if ((errors != null) && (errors.length != 0)) {
1514 if (errMsg == null) {
1515 errMsg = new StringBuffer();
1516 }
1517 errMsg.append("<h3>");
1518 errMsg.append(Localizer.getMessage("jsp.error.tlv.invalid.page",
1519 tli.getShortName(),
1520 compiler.getPageInfo().getJspFile()));
1521 errMsg.append("</h3>");
1522 for (int i = 0; i < errors.length; i++) {
1523 if (errors[i] != null) {
1524 errMsg.append("<p>");
1525 errMsg.append(errors[i].getId());
1526 errMsg.append(": ");
1527 errMsg.append(errors[i].getMessage());
1528 errMsg.append("</p>");
1529 }
1530 }
1531 }
1532 }
1533
1534 if (errMsg != null) {
1535 errDisp.jspError(errMsg.toString());
1536 }
1537 }
1538 }
1539