Package org.apache.jasper.compiler

Source Code of org.apache.jasper.compiler.Validator$TagExtraInfoVisitor

/*
* $Header: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Validator.java,v 1.11.2.2 2003/02/10 17:06:11 luehe Exp $
* $Revision: 1.11.2.2 $
* $Date: 2003/02/10 17:06:11 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution, if
*    any, must include the following acknowlegement: 
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowlegement may appear in the software itself,
*    if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
*    Foundation" must not be used to endorse or promote products derived
*    from this software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
*    nor may "Apache" appear in their names without prior written
*    permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;

import java.util.Hashtable;
import java.util.Enumeration;
import javax.servlet.jsp.tagext.PageData;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import javax.servlet.jsp.tagext.ValidationMessage;
import org.apache.jasper.JasperException;
import org.xml.sax.Attributes;

/**
* Performs validation on the page elements.  Attributes are checked for
* mandatory presence, entry value validity, and consistency.  As a
* side effect, some page global value (such as those from page direcitves)
* are stored, for later use.
*
* @author Kin-man Chung
* @author Jan Luehe
*/
public class Validator {

    /**
     * A visitor to validate and extract page directive info
     */
    static class PageDirectiveVisitor extends Node.Visitor {

  private PageInfo pageInfo;
  private ErrorDispatcher err;

  private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
      new JspUtil.ValidAttribute("language"),
      new JspUtil.ValidAttribute("extends"),
      new JspUtil.ValidAttribute("import"),
      new JspUtil.ValidAttribute("session"),
      new JspUtil.ValidAttribute("buffer"),
      new JspUtil.ValidAttribute("autoFlush"),
      new JspUtil.ValidAttribute("isThreadSafe"),
      new JspUtil.ValidAttribute("info"),
      new JspUtil.ValidAttribute("errorPage"),
      new JspUtil.ValidAttribute("isErrorPage"),
      new JspUtil.ValidAttribute("contentType"),
      new JspUtil.ValidAttribute("pageEncoding") };

  private boolean languageSeen = false;
  private boolean extendsSeen = false;
  private boolean sessionSeen = false;
   private boolean bufferSeen = false;
  private boolean autoFlushSeen = false;
  private boolean isThreadSafeSeen = false;
  private boolean errorPageSeen = false;
  private boolean isErrorPageSeen = false;
  private boolean contentTypeSeen = false;
  private boolean infoSeen = false;
  private boolean pageEncodingSeen = false;

  /*
   * Constructor
   */
  PageDirectiveVisitor(Compiler compiler) {
      this.pageInfo = compiler.getPageInfo();
      this.err = compiler.getErrorDispatcher();
  }

  public void visit(Node.PageDirective n) throws JasperException {   

      JspUtil.checkAttributes("Page directive", n.getAttributes(),
            pageDirectiveAttrs, n.getStart(), err);

      // JSP.2.10.1
      Attributes attrs = n.getAttributes();
      for (int i = 0; i < attrs.getLength(); i++) {
    String attr = attrs.getQName(i);
    String value = attrs.getValue(i);

    if ("language".equals(attr)) {
        if (languageSeen)
      err.jspError(n, "jsp.error.page.multiple.language");
        languageSeen = true;
        if (!"java".equalsIgnoreCase(value))
      err.jspError(n, "jsp.error.language.nonjava");
        pageInfo.setLanguage(value);
    } else if ("extends".equals(attr)) {
        if (extendsSeen)
      err.jspError(n, "jsp.error.page.multiple.extends");
        extendsSeen = true;
        pageInfo.setExtends(value);
        /*
         * If page superclass is top level class (i.e. not in a
         * pkg) explicitly import it. If this is not done, the
         * compiler will assume the extended class is in the same
         * pkg as the generated servlet.
         */
        if (value.indexOf('.') < 0)
      n.addImport(value);
    } else if ("contentType".equals(attr)) {
        if (contentTypeSeen)
      err.jspError(n, "jsp.error.page.multiple.contenttypes");
        contentTypeSeen = true;
        pageInfo.setContentType(value);
    } else if ("session".equals(attr)) {
        if (sessionSeen)
      err.jspError(n, "jsp.error.session.multiple");
        sessionSeen = true;
        if ("true".equalsIgnoreCase(value))
      pageInfo.setSession(true);
        else if ("false".equalsIgnoreCase(value))
      pageInfo.setSession(false);
        else
      err.jspError(n, "jsp.error.session.invalid");
    } else if ("buffer".equals(attr)) {
        if (bufferSeen)
      err.jspError(n, "jsp.error.page.multiple.buffer");
        bufferSeen = true;

        if ("none".equalsIgnoreCase(value))
      pageInfo.setBuffer(0);
        else {
      if (value == null || !value.endsWith("kb"))
          err.jspError(n, "jsp.error.buffer.invalid");

      try {
          Integer k = new Integer(
              value.substring(0, value.length()-2));
          pageInfo.setBuffer(k.intValue()*1024);
      } catch (NumberFormatException e) {
          err.jspError(n, "jsp.error.buffer.invalid");
      }
        }
    } else if ("autoFlush".equals(attr)) {
        if (autoFlushSeen)
      err.jspError(n, "jsp.error.page.multiple.autoflush");
        autoFlushSeen = true;
        if ("true".equalsIgnoreCase(value))
      pageInfo.setAutoFlush(true);
        else if ("false".equalsIgnoreCase(value))
      pageInfo.setAutoFlush(false);
        else
      err.jspError(n, "jsp.error.autoFlush.invalid");
    } else if ("isThreadSafe".equals(attr)) {
        if (isThreadSafeSeen)
      err.jspError(n, "jsp.error.page.multiple.threadsafe");
        isThreadSafeSeen = true;
        if ("true".equalsIgnoreCase(value))
      pageInfo.setThreadSafe(true);
        else if ("false".equalsIgnoreCase(value))
      pageInfo.setThreadSafe(false);
        else
      err.jspError(n, "jsp.error.isThreadSafe.invalid");
    } else if ("isErrorPage".equals(attr)) {
        if (isErrorPageSeen)
      err.jspError(n, "jsp.error.page.multiple.iserrorpage");
        isErrorPageSeen = true;
        if ("true".equalsIgnoreCase(value))
      pageInfo.setIsErrorPage(true);
        else if ("false".equalsIgnoreCase(value))
      pageInfo.setIsErrorPage(false);
        else
      err.jspError(n, "jsp.error.isErrorPage.invalid");
    } else if ("errorPage".equals(attr)) {
        if (errorPageSeen)
      err.jspError(n, "jsp.error.page.multiple.errorpage");
        errorPageSeen = true;
        pageInfo.setErrorPage(value);
    } else if ("info".equals(attr)) {
        if (infoSeen)
      err.jspError(n, "jsp.error.info.multiple");
        infoSeen = true;
    } else if ("pageEncoding".equals(attr)) {
        if (pageEncodingSeen)
      err.jspError(n, "jsp.error.page.multiple.pageencoding");
        pageEncodingSeen = true;
        pageInfo.setPageEncoding(value);
    }
      }

      // Check for bad combinations
      if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
    err.jspError(n, "jsp.error.page.badCombo");

      // Attributes for imports for this node have been processed by
      // the parsers, just add them to pageInfo.
      pageInfo.addImports(n.getImports());
  }
    }

    /**
     * A visitor for validating nodes other than page directives
     */
    static class ValidateVisitor extends Node.Visitor {

  private PageInfo pageInfo;
  private ErrorDispatcher err;

  private static final JspUtil.ValidAttribute[] jspRootAttrs = {
      new JspUtil.ValidAttribute("version", true) };

  private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = {
      new JspUtil.ValidAttribute("file", true) };

  private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
      new JspUtil.ValidAttribute("uri", true),
      new JspUtil.ValidAttribute("prefix", true) };

  private static final JspUtil.ValidAttribute[] includeActionAttrs = {
      new JspUtil.ValidAttribute("page", true),
      new JspUtil.ValidAttribute("flush") };

  private static final JspUtil.ValidAttribute[] paramActionAttrs = {
      new JspUtil.ValidAttribute("name", true),
      new JspUtil.ValidAttribute("value", true) };

  private static final JspUtil.ValidAttribute[] forwardActionAttrs = {
      new JspUtil.ValidAttribute("page", true) };

  private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
      new JspUtil.ValidAttribute("name", true),
      new JspUtil.ValidAttribute("property", true) };

  private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
      new JspUtil.ValidAttribute("name", true),
      new JspUtil.ValidAttribute("property", true),
      new JspUtil.ValidAttribute("value"),
      new JspUtil.ValidAttribute("param") };

  private static final JspUtil.ValidAttribute[] useBeanAttrs = {
      new JspUtil.ValidAttribute("id", true),
      new JspUtil.ValidAttribute("scope"),
      new JspUtil.ValidAttribute("class"),
      new JspUtil.ValidAttribute("type"),
      new JspUtil.ValidAttribute("beanName") };

  private static final JspUtil.ValidAttribute[] plugInAttrs = {
      new JspUtil.ValidAttribute("type",true),
      new JspUtil.ValidAttribute("code", true),
      new JspUtil.ValidAttribute("codebase"),
      new JspUtil.ValidAttribute("align"),
      new JspUtil.ValidAttribute("archive"),
      new JspUtil.ValidAttribute("height"),
      new JspUtil.ValidAttribute("hspace"),
      new JspUtil.ValidAttribute("jreversion"),
      new JspUtil.ValidAttribute("name"),
      new JspUtil.ValidAttribute("vspace"),
      new JspUtil.ValidAttribute("width"),
      new JspUtil.ValidAttribute("nspluginurl"),
      new JspUtil.ValidAttribute("iepluginurl") };

  /*
   * Constructor
   */
  ValidateVisitor(Compiler compiler) {
      this.pageInfo = compiler.getPageInfo();
      this.err = compiler.getErrorDispatcher();
  }

  public void visit(Node.JspRoot n) throws JasperException {
      JspUtil.checkAttributes("Jsp:root", n.getAttributes(),
            jspRootAttrs, n.getStart(), err);
      visitBody(n);
  }

  public void visit(Node.IncludeDirective n) throws JasperException {
      JspUtil.checkAttributes("Include directive", n.getAttributes(),
            includeDirectiveAttrs, n.getStart(), err);
      visitBody(n);
  }

  public void visit(Node.TaglibDirective n) throws JasperException {
      JspUtil.checkAttributes("Taglib directive", n.getAttributes(),
            taglibDirectiveAttrs, n.getStart(), err);
  }

  public void visit(Node.ParamAction n) throws JasperException {
      JspUtil.checkAttributes("Param action", n.getAttributes(),
            paramActionAttrs, n.getStart(), err);
      n.setValue(getJspAttribute("value", n.getAttributeValue("value"),
               n.isXmlSyntax()));
  }

  public void visit(Node.IncludeAction n) throws JasperException {
      JspUtil.checkAttributes("Include action", n.getAttributes(),
            includeActionAttrs, n.getStart(), err);
      n.setPage(getJspAttribute("page", n.getAttributeValue("page"),
              n.isXmlSyntax()));
      visitBody(n);
        };

  public void visit(Node.ForwardAction n) throws JasperException {
            JspUtil.checkAttributes("Forward", n.getAttributes(),
            forwardActionAttrs, n.getStart(), err);
      n.setPage(getJspAttribute("page", n.getAttributeValue("page"),
              n.isXmlSyntax()));
      visitBody(n);
  }

  public void visit(Node.GetProperty n) throws JasperException {
      JspUtil.checkAttributes("GetProperty", n.getAttributes(),
            getPropertyAttrs, n.getStart(), err);
  }

  public void visit(Node.SetProperty n) throws JasperException {
      JspUtil.checkAttributes("SetProperty", n.getAttributes(),
            setPropertyAttrs, n.getStart(), err);
      String name = n.getAttributeValue("name");
      String property = n.getAttributeValue("property");
      String param = n.getAttributeValue("param");
      String value = n.getAttributeValue("value");

      if ("*".equals(property)) {
    if (param != null || value != null)
        err.jspError(n, "jsp.error.setProperty.invalid");
   
      } else if (param != null && value != null) {
    err.jspError(n, "jsp.error.setProperty.invalid");
      }
      n.setValue(getJspAttribute("value", value, n.isXmlSyntax()));
  }

  public void visit(Node.UseBean n) throws JasperException {
      JspUtil.checkAttributes("UseBean", n.getAttributes(),
            useBeanAttrs, n.getStart(), err);

      String name = n.getAttributeValue ("id");
      String scope = n.getAttributeValue ("scope");
      String className = n.getAttributeValue ("class");
      String type = n.getAttributeValue ("type");
      BeanRepository beanInfo = pageInfo.getBeanRepository();

      if (className == null && type == null)
    err.jspError(n, "jsp.error.useBean.missingType");

      if (beanInfo.checkVariable(name))
    err.jspError(n, "jsp.error.useBean.duplicate");

      if ("session".equals(scope) && !pageInfo.isSession())
    err.jspError(n, "jsp.error.useBean.noSession");

      Node.JspAttribute jattr
    = getJspAttribute("beanName", n.getAttributeValue("beanName"),
          n.isXmlSyntax());
      n.setBeanName(jattr);
      if (className != null && jattr != null)
    err.jspError(n, "jsp.error.useBean.notBoth");

      if (className == null)
    className = type;

      if (scope == null || scope.equals("page")) {
    beanInfo.addPageBean(name, className);
      } else if (scope.equals("request")) {
    beanInfo.addRequestBean(name, className);
      } else if (scope.equals("session")) {
    beanInfo.addSessionBean(name,className);
      } else if (scope.equals("application")) {
    beanInfo.addApplicationBean(name,className);
      } else
    err.jspError(n, "jsp.error.useBean.badScope");

      visitBody(n);
  }

  public void visit(Node.PlugIn n) throws JasperException {
      JspUtil.checkAttributes("Plugin", n.getAttributes(),
            plugInAttrs, n.getStart(), err);

      String type = n.getAttributeValue("type");
      if (type == null)
    err.jspError(n, "jsp.error.plugin.notype");
      if (!type.equals("bean") && !type.equals("applet"))
    err.jspError(n, "jsp.error.plugin.badtype");
      if (n.getAttributeValue("code") == null)
    err.jspError(n, "jsp.error.plugin.nocode");

      n.setHeight(getJspAttribute("height", n.getAttributeValue("height"),
              n.isXmlSyntax()));
      n.setWidth(getJspAttribute("width", n.getAttributeValue("width"),
              n.isXmlSyntax()));
      visitBody(n);
  }

  public void visit(Node.CustomTag n) throws JasperException {
      TagLibraryInfo tagLibInfo = (TagLibraryInfo)
    pageInfo.getTagLibraries().get(n.getPrefix());
      TagInfo tagInfo = tagLibInfo.getTag(n.getShortName());
      if (tagInfo == null) {
    err.jspError(n, "jsp.error.missing.tagInfo", n.getName());
      }

      /*
       * Make sure all required attributes are present
       */
      TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
      Attributes attrs = n.getAttributes();
      for (int i=0; i<tldAttrs.length; i++) {
    if (tldAttrs[i].isRequired()
        && attrs.getValue(tldAttrs[i].getName()) == null) {
        err.jspError(n, "jsp.error.missing_attribute",
         tldAttrs[i].getName(), n.getShortName());
    }
      }

      /*
       * Make sure there are no invalid attributes
       */
      Hashtable tagDataAttrs = new Hashtable(attrs.getLength());
      Node.JspAttribute[] jspAttrs
    = new Node.JspAttribute[attrs.getLength()];
      for (int i=0; i<attrs.getLength(); i++) {
    boolean found = false;
    for (int j=0; j<tldAttrs.length; j++) {
        if (attrs.getQName(i).equals(tldAttrs[j].getName())) {
      if (tldAttrs[j].canBeRequestTime()) {
          jspAttrs[i]
        = getJspAttribute(attrs.getQName(i),
              attrs.getValue(i),
              n.isXmlSyntax());
      } else {
          jspAttrs[i]
        = new Node.JspAttribute(attrs.getQName(i),
              attrs.getValue(i),
              false);
      }
      if (jspAttrs[i].isExpression()) {
          tagDataAttrs.put(attrs.getQName(i),
               TagData.REQUEST_TIME_VALUE);
      } else {
          tagDataAttrs.put(attrs.getQName(i),
               attrs.getValue(i));
      }
      found = true;
      break;
        }
    }
    if (!found) {
        err.jspError(n, "jsp.error.bad_attribute",
         attrs.getQName(i));
    }
      }

      TagData tagData = new TagData(tagDataAttrs);
      n.setTagData(tagData);
      n.setJspAttributes(jspAttrs);

      visitBody(n);
  }

  /**
   * Preprocess attributes that can be expressions.  Expression
   * delimiters are stripped.
   */
  private Node.JspAttribute getJspAttribute(String name,
              String value,
              boolean isXml) {
      // XXX Is it an error to see "%=foo%" in non-Xml page?
      // (We won't see "<%=foo%> in xml page because '<' is not a
      // valid attribute value in xml).

      if (value == null)
    return null;

      if (isXml && value.startsWith("%=")) {
    return new Node.JspAttribute(name,
               value.substring(2,
                   value.length()-1),
               true);
      }

      if (!isXml && value.startsWith("<%=")) {
    return new Node.JspAttribute(name,
               value.substring(3,
                   value.length()-2),
               true);
      }

      return new Node.JspAttribute(name, value, false);
  }
    }

    /**
     * A visitor for validating TagExtraInfo classes of all tags
     */
    static class TagExtraInfoVisitor extends Node.Visitor {

  private PageInfo pageInfo;
  private ErrorDispatcher err;

  /*
   * Constructor
   */
  TagExtraInfoVisitor(Compiler compiler) {
      this.pageInfo = compiler.getPageInfo();
      this.err = compiler.getErrorDispatcher();
  }

  public void visit(Node.CustomTag n) throws JasperException {
      TagLibraryInfo tagLibInfo = (TagLibraryInfo)
    pageInfo.getTagLibraries().get(n.getPrefix());
      TagInfo tagInfo = tagLibInfo.getTag(n.getShortName());
      if (tagInfo == null) {
    err.jspError(n, "jsp.error.missing.tagInfo", n.getName());
      }

      if (!tagInfo.isValid(n.getTagData())) {
    err.jspError(n, "jsp.error.invalid.attributes");
      }

      visitBody(n);
  }
    }

    public static void validate(Compiler compiler,
        Node.Nodes page) throws JasperException {

  /*
   * Visit the page directives first, as they are global to the page
   * and are position independent.
   */
  page.visit(new PageDirectiveVisitor(compiler));

  // Determine the default output content type, per errata_a
  // http://jcp.org/aboutJava/communityprocess/maintenance/jsr053/errata_1_2_a_20020321.html
  PageInfo pageInfo = compiler.getPageInfo();
  String contentType = pageInfo.getContentType();
  if (contentType == null || contentType.indexOf("charset=") < 0) {
      boolean isXml = page.getRoot().isXmlSyntax();
      String defaultType;
      if (contentType == null) {
    defaultType = isXml? "text/xml": "text/html";
      } else {
    defaultType = contentType;
      }
      String charset = pageInfo.getPageEncoding();
      if (charset == null)
    charset = isXml? "UTF-8": "ISO-8859-1";
      pageInfo.setContentType(defaultType + ";charset=" + charset);
  }

  /*
   * Validate all other nodes.
   * This validation step includes checking a custom tag's mandatory and
   * optional attributes against information in the TLD (first validation
   * step for custom tags according to JSP.10.5).
   */
  page.visit(new ValidateVisitor(compiler));

  /*
   * Invoke TagLibraryValidator classes of all imported tags
   * (second validation step for custom tags according to JSP.10.5).
   */
  validateXmlView(new PageDataImpl(page), compiler);

  /*
   * Invoke TagExtraInfo method isValid() for all imported tags
   * (third validation step for custom tags according to JSP.10.5).
   */
  page.visit(new TagExtraInfoVisitor(compiler));

    }


    //*********************************************************************
    // Private (utility) methods

    /**
     * Validate XML view against the TagLibraryValidator classes of all
     * imported tag libraries.
     */
    private static void validateXmlView(PageData xmlView, Compiler compiler)
          throws JasperException {

  StringBuffer errMsg = null;
  ErrorDispatcher errDisp = compiler.getErrorDispatcher();

        Enumeration enum = compiler.getPageInfo().getTagLibraries().elements();
        while (enum.hasMoreElements()) {
            TagLibraryInfo tli = (TagLibraryInfo) enum.nextElement();
      ValidationMessage[] errors
    = ((TagLibraryInfoImpl) tli).validate(xmlView);
            if ((errors != null) && (errors.length != 0)) {
                if (errMsg == null) {
        errMsg = new StringBuffer();
    }
                errMsg.append("<h3>");
                errMsg.append(errDisp.getString("jsp.error.tlv.invalid.page",
            tli.getShortName()));
                errMsg.append("</h3>");
                for (int i=0; i<errors.length; i++) {
                    errMsg.append("<p>");
                    errMsg.append(errors[i].getId());
                    errMsg.append(": ");
                    errMsg.append(errors[i].getMessage());
                    errMsg.append("</p>");
                }
            }
        }

  if (errMsg != null) {
            errDisp.jspError(errMsg.toString());
  }
    }
}

TOP

Related Classes of org.apache.jasper.compiler.Validator$TagExtraInfoVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.