KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jasper > compiler > Validator


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.jasper.compiler;
19
20 import java.lang.reflect.Method JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Iterator JavaDoc;
25
26 import javax.el.ELException;
27 import javax.el.ExpressionFactory;
28 import javax.el.FunctionMapper;
29 import javax.servlet.jsp.tagext.FunctionInfo JavaDoc;
30 import javax.servlet.jsp.tagext.JspFragment JavaDoc;
31 import javax.servlet.jsp.tagext.PageData JavaDoc;
32 import javax.servlet.jsp.tagext.TagAttributeInfo JavaDoc;
33 import javax.servlet.jsp.tagext.TagData JavaDoc;
34 import javax.servlet.jsp.tagext.TagExtraInfo JavaDoc;
35 import javax.servlet.jsp.tagext.TagInfo JavaDoc;
36 import javax.servlet.jsp.tagext.TagLibraryInfo JavaDoc;
37 import javax.servlet.jsp.tagext.ValidationMessage JavaDoc;
38
39 import org.apache.el.lang.ELSupport;
40 import org.apache.jasper.Constants;
41 import org.apache.jasper.JasperException;
42 import org.apache.jasper.el.ELContextImpl;
43 import org.xml.sax.Attributes JavaDoc;
44
45 /**
46  * Performs validation on the page elements. Attributes are checked for
47  * mandatory presence, entry value validity, and consistency. As a side effect,
48  * some page global value (such as those from page direcitves) are stored, for
49  * later use.
50  *
51  * @author Kin-man Chung
52  * @author Jan Luehe
53  * @author Shawn Bayern
54  * @author Mark Roth
55  */

56 class Validator {
57
58     /**
59      * A visitor to validate and extract page directive info
60      */

61     static class DirectiveVisitor extends Node.Visitor {
62
63         private PageInfo pageInfo;
64
65         private ErrorDispatcher err;
66
67         private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
68             new JspUtil.ValidAttribute("language"),
69             new JspUtil.ValidAttribute("extends"),
70             new JspUtil.ValidAttribute("import"),
71             new JspUtil.ValidAttribute("session"),
72             new JspUtil.ValidAttribute("buffer"),
73             new JspUtil.ValidAttribute("autoFlush"),
74             new JspUtil.ValidAttribute("isThreadSafe"),
75             new JspUtil.ValidAttribute("info"),
76             new JspUtil.ValidAttribute("errorPage"),
77             new JspUtil.ValidAttribute("isErrorPage"),
78             new JspUtil.ValidAttribute("contentType"),
79             new JspUtil.ValidAttribute("pageEncoding"),
80             new JspUtil.ValidAttribute("isELIgnored"),
81             new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"),
82             new JspUtil.ValidAttribute("trimDirectiveWhitespaces")
83         };
84
85         private boolean pageEncodingSeen = false;
86
87         /*
88          * Constructor
89          */

90         DirectiveVisitor(Compiler JavaDoc compiler) throws JasperException {
91             this.pageInfo = compiler.getPageInfo();
92             this.err = compiler.getErrorDispatcher();
93         }
94
95         public void visit(Node.IncludeDirective n) throws JasperException {
96             // Since pageDirectiveSeen flag only applies to the Current page
97
// save it here and restore it after the file is included.
98
boolean pageEncodingSeenSave = pageEncodingSeen;
99             pageEncodingSeen = false;
100             visitBody(n);
101             pageEncodingSeen = pageEncodingSeenSave;
102         }
103
104         public void visit(Node.PageDirective n) throws JasperException {
105
106             JspUtil.checkAttributes("Page directive", n, pageDirectiveAttrs,
107                     err);
108
109             // JSP.2.10.1
110
Attributes JavaDoc attrs = n.getAttributes();
111             for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
112                 String JavaDoc attr = attrs.getQName(i);
113                 String JavaDoc value = attrs.getValue(i);
114
115                 if ("language".equals(attr)) {
116                     if (pageInfo.getLanguage(false) == null) {
117                         pageInfo.setLanguage(value, n, err, true);
118                     } else if (!pageInfo.getLanguage(false).equals(value)) {
119                         err.jspError(n, "jsp.error.page.conflict.language",
120                                 pageInfo.getLanguage(false), value);
121                     }
122                 } else if ("extends".equals(attr)) {
123                     if (pageInfo.getExtends(false) == null) {
124                         pageInfo.setExtends(value, n);
125                     } else if (!pageInfo.getExtends(false).equals(value)) {
126                         err.jspError(n, "jsp.error.page.conflict.extends",
127                                 pageInfo.getExtends(false), value);
128                     }
129                 } else if ("contentType".equals(attr)) {
130                     if (pageInfo.getContentType() == null) {
131                         pageInfo.setContentType(value);
132                     } else if (!pageInfo.getContentType().equals(value)) {
133                         err.jspError(n, "jsp.error.page.conflict.contenttype",
134                                 pageInfo.getContentType(), value);
135                     }
136                 } else if ("session".equals(attr)) {
137                     if (pageInfo.getSession() == null) {
138                         pageInfo.setSession(value, n, err);
139                     } else if (!pageInfo.getSession().equals(value)) {
140                         err.jspError(n, "jsp.error.page.conflict.session",
141                                 pageInfo.getSession(), value);
142                     }
143                 } else if ("buffer".equals(attr)) {
144                     if (pageInfo.getBufferValue() == null) {
145                         pageInfo.setBufferValue(value, n, err);
146                     } else if (!pageInfo.getBufferValue().equals(value)) {
147                         err.jspError(n, "jsp.error.page.conflict.buffer",
148                                 pageInfo.getBufferValue(), value);
149                     }
150                 } else if ("autoFlush".equals(attr)) {
151                     if (pageInfo.getAutoFlush() == null) {
152                         pageInfo.setAutoFlush(value, n, err);
153                     } else if (!pageInfo.getAutoFlush().equals(value)) {
154                         err.jspError(n, "jsp.error.page.conflict.autoflush",
155                                 pageInfo.getAutoFlush(), value);
156                     }
157                 } else if ("isThreadSafe".equals(attr)) {
158                     if (pageInfo.getIsThreadSafe() == null) {
159                         pageInfo.setIsThreadSafe(value, n, err);
160                     } else if (!pageInfo.getIsThreadSafe().equals(value)) {
161                         err.jspError(n, "jsp.error.page.conflict.isthreadsafe",
162                                 pageInfo.getIsThreadSafe(), value);
163                     }
164                 } else if ("isELIgnored".equals(attr)) {
165                     if (pageInfo.getIsELIgnored() == null) {
166                         pageInfo.setIsELIgnored(value, n, err, true);
167                     } else if (!pageInfo.getIsELIgnored().equals(value)) {
168                         err.jspError(n, "jsp.error.page.conflict.iselignored",
169                                 pageInfo.getIsELIgnored(), value);
170                     }
171                 } else if ("isErrorPage".equals(attr)) {
172                     if (pageInfo.getIsErrorPage() == null) {
173                         pageInfo.setIsErrorPage(value, n, err);
174                     } else if (!pageInfo.getIsErrorPage().equals(value)) {
175                         err.jspError(n, "jsp.error.page.conflict.iserrorpage",
176                                 pageInfo.getIsErrorPage(), value);
177                     }
178                 } else if ("errorPage".equals(attr)) {
179                     if (pageInfo.getErrorPage() == null) {
180                         pageInfo.setErrorPage(value);
181                     } else if (!pageInfo.getErrorPage().equals(value)) {
182                         err.jspError(n, "jsp.error.page.conflict.errorpage",
183                                 pageInfo.getErrorPage(), value);
184                     }
185                 } else if ("info".equals(attr)) {
186                     if (pageInfo.getInfo() == null) {
187                         pageInfo.setInfo(value);
188                     } else if (!pageInfo.getInfo().equals(value)) {
189                         err.jspError(n, "jsp.error.page.conflict.info",
190                                 pageInfo.getInfo(), value);
191                     }
192                 } else if ("pageEncoding".equals(attr)) {
193                     if (pageEncodingSeen)
194                         err.jspError(n, "jsp.error.page.multi.pageencoding");
195                     // 'pageEncoding' can occur at most once per file
196
pageEncodingSeen = true;
197                     String JavaDoc actual = comparePageEncodings(value, n);
198                     n.getRoot().setPageEncoding(actual);
199                 } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) {
200                     if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
201                         pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n,
202                                 err, true);
203                     } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral()
204                             .equals(value)) {
205                         err
206                                 .jspError(
207                                         n,
208                                         "jsp.error.page.conflict.deferredsyntaxallowedasliteral",
209                                         pageInfo
210                                                 .getDeferredSyntaxAllowedAsLiteral(),
211                                         value);
212                     }
213                 } else if ("trimDirectiveWhitespaces".equals(attr)) {
214                     if (pageInfo.getTrimDirectiveWhitespaces() == null) {
215                         pageInfo.setTrimDirectiveWhitespaces(value, n, err,
216                                 true);
217                     } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(
218                             value)) {
219                         err
220                                 .jspError(
221                                         n,
222                                         "jsp.error.page.conflict.trimdirectivewhitespaces",
223                                         pageInfo.getTrimDirectiveWhitespaces(),
224                                         value);
225                     }
226                 }
227             }
228
229             // Check for bad combinations
230
if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
231                 err.jspError(n, "jsp.error.page.badCombo");
232
233             // Attributes for imports for this node have been processed by
234
// the parsers, just add them to pageInfo.
235
pageInfo.addImports(n.getImports());
236         }
237
238         public void visit(Node.TagDirective n) throws JasperException {
239             // Note: Most of the validation is done in TagFileProcessor
240
// when it created a TagInfo object from the
241
// tag file in which the directive appeared.
242

243             // This method does additional processing to collect page info
244

245             Attributes JavaDoc attrs = n.getAttributes();
246             for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
247                 String JavaDoc attr = attrs.getQName(i);
248                 String JavaDoc value = attrs.getValue(i);
249
250                 if ("language".equals(attr)) {
251                     if (pageInfo.getLanguage(false) == null) {
252                         pageInfo.setLanguage(value, n, err, false);
253                     } else if (!pageInfo.getLanguage(false).equals(value)) {
254                         err.jspError(n, "jsp.error.tag.conflict.language",
255                                 pageInfo.getLanguage(false), value);
256                     }
257                 } else if ("isELIgnored".equals(attr)) {
258                     if (pageInfo.getIsELIgnored() == null) {
259                         pageInfo.setIsELIgnored(value, n, err, false);
260                     } else if (!pageInfo.getIsELIgnored().equals(value)) {
261                         err.jspError(n, "jsp.error.tag.conflict.iselignored",
262                                 pageInfo.getIsELIgnored(), value);
263                     }
264                 } else if ("pageEncoding".equals(attr)) {
265                     if (pageEncodingSeen)
266                         err.jspError(n, "jsp.error.tag.multi.pageencoding");
267                     pageEncodingSeen = true;
268                     compareTagEncodings(value, n);
269                     n.getRoot().setPageEncoding(value);
270                 } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) {
271                     if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
272                         pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n,
273                                 err, false);
274                     } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral()
275                             .equals(value)) {
276                         err
277                                 .jspError(
278                                         n,
279                                         "jsp.error.tag.conflict.deferredsyntaxallowedasliteral",
280                                         pageInfo
281                                                 .getDeferredSyntaxAllowedAsLiteral(),
282                                         value);
283                     }
284                 } else if ("trimDirectiveWhitespaces".equals(attr)) {
285                     if (pageInfo.getTrimDirectiveWhitespaces() == null) {
286                         pageInfo.setTrimDirectiveWhitespaces(value, n, err,
287                                 false);
288                     } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(
289                             value)) {
290                         err
291                                 .jspError(
292                                         n,
293                                         "jsp.error.tag.conflict.trimdirectivewhitespaces",
294                                         pageInfo.getTrimDirectiveWhitespaces(),
295                                         value);
296                     }
297                 }
298             }
299
300             // Attributes for imports for this node have been processed by
301
// the parsers, just add them to pageInfo.
302
pageInfo.addImports(n.getImports());
303         }
304
305         public void visit(Node.AttributeDirective n) throws JasperException {
306             // Do nothing, since this attribute directive has already been
307
// validated by TagFileProcessor when it created a TagInfo object
308
// from the tag file in which the directive appeared
309
}
310
311         public void visit(Node.VariableDirective n) throws JasperException {
312             // Do nothing, since this variable directive has already been
313
// validated by TagFileProcessor when it created a TagInfo object
314
// from the tag file in which the directive appeared
315
}
316
317         /*
318          * Compares page encodings specified in various places, and throws
319          * exception in case of page encoding mismatch.
320          *
321          * @param pageDirEnc The value of the pageEncoding attribute of the page
322          * directive @param pageDir The page directive node
323          *
324          * @throws JasperException in case of page encoding mismatch
325          */

326         private String JavaDoc comparePageEncodings(String JavaDoc pageDirEnc,
327                 Node.PageDirective pageDir) throws JasperException {
328
329             Node.Root root = pageDir.getRoot();
330             String JavaDoc configEnc = root.getJspConfigPageEncoding();
331
332             /*
333              * Compare the 'pageEncoding' attribute of the page directive with
334              * the encoding specified in the JSP config element whose URL
335              * pattern matches this page. Treat "UTF-16", "UTF-16BE", and
336              * "UTF-16LE" as identical.
337              */

338             if (configEnc != null) {
339                 if (!pageDirEnc.equals(configEnc)
340                         && (!pageDirEnc.startsWith("UTF-16") || !configEnc
341                                 .startsWith("UTF-16"))) {
342                     err.jspError(pageDir,
343                             "jsp.error.config_pagedir_encoding_mismatch",
344                             configEnc, pageDirEnc);
345                 } else {
346                     return configEnc;
347                 }
348             }
349
350             /*
351              * Compare the 'pageEncoding' attribute of the page directive with
352              * the encoding specified in the XML prolog (only for XML syntax,
353              * and only if JSP document contains XML prolog with encoding
354              * declaration). Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as
355              * identical.
356              */

357             if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) {
358                 String JavaDoc pageEnc = root.getPageEncoding();
359                 if (!pageDirEnc.equals(pageEnc)
360                         && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
361                                 .startsWith("UTF-16"))) {
362                     err.jspError(pageDir,
363                             "jsp.error.prolog_pagedir_encoding_mismatch",
364                             pageEnc, pageDirEnc);
365                 } else {
366                     return pageEnc;
367                 }
368             }
369             
370             return pageDirEnc;
371         }
372         
373         /*
374          * Compares page encodings specified in various places, and throws
375          * exception in case of page encoding mismatch.
376          *
377          * @param pageDirEnc The value of the pageEncoding attribute of the page
378          * directive @param pageDir The page directive node
379          *
380          * @throws JasperException in case of page encoding mismatch
381          */

382         private void compareTagEncodings(String JavaDoc pageDirEnc,
383                 Node.TagDirective pageDir) throws JasperException {
384
385             Node.Root root = pageDir.getRoot();
386
387             /*
388              * Compare the 'pageEncoding' attribute of the page directive with
389              * the encoding specified in the XML prolog (only for XML syntax,
390              * and only if JSP document contains XML prolog with encoding
391              * declaration). Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as
392              * identical.
393              */

394             if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) {
395                 String JavaDoc pageEnc = root.getPageEncoding();
396                 if (!pageDirEnc.equals(pageEnc)
397                         && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
398                                 .startsWith("UTF-16"))) {
399                     err.jspError(pageDir,
400                             "jsp.error.prolog_pagedir_encoding_mismatch",
401                             pageEnc, pageDirEnc);
402                 }
403             }
404         }
405
406     }
407
408     /**
409      * A visitor for validating nodes other than page directives
410      */

411     static class ValidateVisitor extends Node.Visitor {
412
413         private PageInfo pageInfo;
414
415         private ErrorDispatcher err;
416
417         private TagInfo JavaDoc tagInfo;
418
419         private ClassLoader JavaDoc loader;
420
421         private final StringBuffer JavaDoc buf = new StringBuffer JavaDoc(32);
422
423         private static final JspUtil.ValidAttribute[] jspRootAttrs = {
424                 new JspUtil.ValidAttribute("xsi:schemaLocation"),
425                 new JspUtil.ValidAttribute("version", true) };
426
427         private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { new JspUtil.ValidAttribute(
428                 "file", true) };
429
430         private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
431                 new JspUtil.ValidAttribute("uri"),
432                 new JspUtil.ValidAttribute("tagdir"),
433                 new JspUtil.ValidAttribute("prefix", true) };
434
435         private static final JspUtil.ValidAttribute[] includeActionAttrs = {
436                 new JspUtil.ValidAttribute("page", true, true),
437                 new JspUtil.ValidAttribute("flush") };
438
439         private static final JspUtil.ValidAttribute[] paramActionAttrs = {
440                 new JspUtil.ValidAttribute("name", true),
441                 new JspUtil.ValidAttribute("value", true, true) };
442
443         private static final JspUtil.ValidAttribute[] forwardActionAttrs = { new JspUtil.ValidAttribute(
444                 "page", true, true) };
445
446         private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
447                 new JspUtil.ValidAttribute("name", true),
448                 new JspUtil.ValidAttribute("property", true) };
449
450         private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
451                 new JspUtil.ValidAttribute("name", true),
452                 new JspUtil.ValidAttribute("property", true),
453                 new JspUtil.ValidAttribute("value", false, true),
454                 new JspUtil.ValidAttribute("param") };
455
456         private static final JspUtil.ValidAttribute[] useBeanAttrs = {
457                 new JspUtil.ValidAttribute("id", true),
458                 new JspUtil.ValidAttribute("scope"),
459                 new JspUtil.ValidAttribute("class"),
460                 new JspUtil.ValidAttribute("type"),
461                 new JspUtil.ValidAttribute("beanName", false, true) };
462
463         private static final JspUtil.ValidAttribute[] plugInAttrs = {
464                 new JspUtil.ValidAttribute("type", true),
465                 new JspUtil.ValidAttribute("code", true),
466                 new JspUtil.ValidAttribute("codebase"),
467                 new JspUtil.ValidAttribute("align"),
468                 new JspUtil.ValidAttribute("archive"),
469                 new JspUtil.ValidAttribute("height", false, true),
470                 new JspUtil.ValidAttribute("hspace"),
471                 new JspUtil.ValidAttribute("jreversion"),
472                 new JspUtil.ValidAttribute("name"),
473                 new JspUtil.ValidAttribute("vspace"),
474                 new JspUtil.ValidAttribute("width", false, true),
475                 new JspUtil.ValidAttribute("nspluginurl"),
476                 new JspUtil.ValidAttribute("iepluginurl") };
477
478         private static final JspUtil.ValidAttribute[] attributeAttrs = {
479                 new JspUtil.ValidAttribute("name", true),
480                 new JspUtil.ValidAttribute("trim") };
481
482         private static final JspUtil.ValidAttribute[] invokeAttrs = {
483                 new JspUtil.ValidAttribute("fragment", true),
484                 new JspUtil.ValidAttribute("var"),
485                 new JspUtil.ValidAttribute("varReader"),
486                 new JspUtil.ValidAttribute("scope") };
487
488         private static final JspUtil.ValidAttribute[] doBodyAttrs = {
489                 new JspUtil.ValidAttribute("var"),
490                 new JspUtil.ValidAttribute("varReader"),
491                 new JspUtil.ValidAttribute("scope") };
492
493         private static final JspUtil.ValidAttribute[] jspOutputAttrs = {
494                 new JspUtil.ValidAttribute("omit-xml-declaration"),
495                 new JspUtil.ValidAttribute("doctype-root-element"),
496                 new JspUtil.ValidAttribute("doctype-public"),
497                 new JspUtil.ValidAttribute("doctype-system") };
498
499         /*
500          * Constructor
501          */

502         ValidateVisitor(Compiler JavaDoc compiler) {
503             this.pageInfo = compiler.getPageInfo();
504             this.err = compiler.getErrorDispatcher();
505             this.tagInfo = compiler.getCompilationContext().getTagInfo();
506             this.loader = compiler.getCompilationContext().getClassLoader();
507         }
508
509         public void visit(Node.JspRoot n) throws JasperException {
510             JspUtil.checkAttributes("Jsp:root", n, jspRootAttrs, err);
511             String JavaDoc version = n.getTextAttribute("version");
512             if (!version.equals("1.2") && !version.equals("2.0")) {
513                 err.jspError(n, "jsp.error.jsproot.version.invalid", version);
514             }
515             visitBody(n);
516         }
517
518         public void visit(Node.IncludeDirective n) throws JasperException {
519             JspUtil.checkAttributes("Include directive", n,
520                     includeDirectiveAttrs, err);
521             visitBody(n);
522         }
523
524         public void visit(Node.TaglibDirective n) throws JasperException {
525             JspUtil.checkAttributes("Taglib directive", n,
526                     taglibDirectiveAttrs, err);
527             // Either 'uri' or 'tagdir' attribute must be specified
528
String JavaDoc uri = n.getAttributeValue("uri");
529             String JavaDoc tagdir = n.getAttributeValue("tagdir");
530             if (uri == null && tagdir == null) {
531                 err.jspError(n, "jsp.error.taglibDirective.missing.location");
532             }
533             if (uri != null && tagdir != null) {
534                 err
535                         .jspError(n,
536                                 "jsp.error.taglibDirective.both_uri_and_tagdir");
537             }
538         }
539
540         public void visit(Node.ParamAction n) throws JasperException {
541             JspUtil.checkAttributes("Param action", n, paramActionAttrs, err);
542             // make sure the value of the 'name' attribute is not a
543
// request-time expression
544
throwErrorIfExpression(n, "name", "jsp:param");
545             n.setValue(getJspAttribute(null, "value", null, null, n
546                     .getAttributeValue("value"), java.lang.String JavaDoc.class, n,
547                     false));
548             visitBody(n);
549         }
550
551         public void visit(Node.ParamsAction n) throws JasperException {
552             // Make sure we've got at least one nested jsp:param
553
Node.Nodes subElems = n.getBody();
554             if (subElems == null) {
555                 err.jspError(n, "jsp.error.params.emptyBody");
556             }
557             visitBody(n);
558         }
559
560         public void visit(Node.IncludeAction n) throws JasperException {
561             JspUtil.checkAttributes("Include action", n, includeActionAttrs,
562                     err);
563             n.setPage(getJspAttribute(null, "page", null, null, n
564                     .getAttributeValue("page"), java.lang.String JavaDoc.class, n,
565                     false));
566             visitBody(n);
567         };
568
569         public void visit(Node.ForwardAction n) throws JasperException {
570             JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err);
571             n.setPage(getJspAttribute(null, "page", null, null, n
572                     .getAttributeValue("page"), java.lang.String JavaDoc.class, n,
573                     false));
574             visitBody(n);
575         }
576
577         public void visit(Node.GetProperty n) throws JasperException {
578             JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs, err);
579         }
580
581         public void visit(Node.SetProperty n) throws JasperException {
582             JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs, err);
583             String JavaDoc property = n.getTextAttribute("property");
584             String JavaDoc param = n.getTextAttribute("param");
585             String JavaDoc value = n.getAttributeValue("value");
586
587             n.setValue(getJspAttribute(null, "value", null, null, value,
588                     java.lang.Object JavaDoc.class, n, false));
589
590             boolean valueSpecified = n.getValue() != null;
591
592             if ("*".equals(property)) {
593                 if (param != null || valueSpecified)
594                     err.jspError(n, "jsp.error.setProperty.invalid");
595
596             } else if (param != null && valueSpecified) {
597                 err.jspError(n, "jsp.error.setProperty.invalid");
598             }
599
600             visitBody(n);
601         }
602
603         public void visit(Node.UseBean n) throws JasperException {
604             JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err);
605
606       &nb