parser.java

来自「精通tomcat书籍原代码,希望大家共同学习」· Java 代码 · 共 1,859 行 · 第 1/5 页

JAVA
1,859
字号
        
        return result;
    }

    /*
     * Params ::=  `>' S?
     *              (   ( `<jsp:body>'
     *                    ( ( S? Param+ S? `</jsp:body>' )
     *                      | <TRANSLATION_ERROR>
     *                    )
     *                  )
     *                | Param+
     *              )
     *              '</jsp:params>'
     */
    private void parseJspParams(Node parent) throws JasperException {
	Node jspParamsNode = new Node.ParamsAction(start, parent);
	parseOptionalBody(jspParamsNode, "jsp:params",
			  JAVAX_BODY_CONTENT_PARAM );
    }

    /*
     * Fallback ::=   '/>'
     *               | ( `>' S? `<jsp:body>'
     *                   (   ( S?
     *                         ( Char* - ( Char* `</jsp:body>' ) )
     *                         `</jsp:body>' S?
     *                       )
     *                     | <TRANSLATION_ERROR>
     *                   )
     *                   `</jsp:fallback>'
     *                 )
     *               | ( '>'
     *                   ( Char* - ( Char* '</jsp:fallback>' ) )
     *                   '</jsp:fallback>'
     *                 )
     */
    private void parseFallBack(Node parent) throws JasperException {
	Node fallBackNode = new Node.FallBackAction(start, parent);
	parseOptionalBody(fallBackNode, "jsp:fallback", 
			  JAVAX_BODY_CONTENT_TEMPLATE_TEXT);
    }

    /*
     * For Plugin:
     * StdActionContent ::= Attributes PluginBody
     *
     * PluginBody ::=   EmptyBody 
     *                | ( '>' S? ( '<jsp:attribute' NamedAttributes )?
     *                    '<jsp:body'
     *                    ( JspBodyPluginTags | <TRANSLATION_ERROR> )
     *                    S? ETag
     *                  )
     *                | ( '>' S? PluginTags ETag )
     *
     * EmptyBody ::=   '/>'
     *               | ( '>' ETag )
     *               | ( '>' S? '<jsp:attribute' NamedAttributes ETag )
     *
     */
    private void parsePlugin(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();
        
	Node pluginNode = new Node.PlugIn(attrs, start, parent);
        
        parseOptionalBody( pluginNode, "jsp:plugin", 
            JAVAX_BODY_CONTENT_PLUGIN );
    }

    /*
     * PluginTags ::= ( '<jsp:params' Params S? )?
     *                ( '<jsp:fallback' Fallback? S? )?
     */
    private void parsePluginTags( Node parent ) throws JasperException {
        reader.skipSpaces();
        
        if( reader.matches( "<jsp:params" ) ) {
            parseJspParams( parent );
            reader.skipSpaces();
        }
        
        if( reader.matches( "<jsp:fallback" ) ) {
            parseFallBack( parent );
            reader.skipSpaces();
        }
    }
        
    /*
     * StandardAction ::=   'include'       StdActionContent
     *                    | 'forward'       StdActionContent
     *                    | 'invoke'        StdActionContent
     *                    | 'doBody'        StdActionContent
     *                    | 'getProperty'   StdActionContent
     *                    | 'setProperty'   StdActionContent
     *                    | 'useBean'       StdActionContent
     *                    | 'plugin'        StdActionContent
     *                    | 'element'       StdActionContent
     */
    private void parseStandardAction(Node parent) throws JasperException {
	Mark start = reader.mark();

	if (reader.matches(INCLUDE_ACTION)) {
	    parseInclude(parent);
	} else if (reader.matches(FORWARD_ACTION)) {
	    parseForward(parent);
	} else if (reader.matches(INVOKE_ACTION)) {
	    if (!isTagFile) {
		err.jspError(reader.mark(), "jsp.error.action.isnottagfile",
			     "&lt;jsp:invoke");
	    }
	    parseInvoke(parent);
	} else if (reader.matches(DOBODY_ACTION)) {
	    if (!isTagFile) {
		err.jspError(reader.mark(), "jsp.error.action.isnottagfile",
			     "&lt;jsp:doBody");
	    }
	    parseDoBody(parent);
	} else if (reader.matches(GET_PROPERTY_ACTION)) {
	    parseGetProperty(parent);
	} else if (reader.matches(SET_PROPERTY_ACTION)) {
	    parseSetProperty(parent);
	} else if (reader.matches(USE_BEAN_ACTION)) {
	    parseUseBean(parent);
	} else if (reader.matches(PLUGIN_ACTION)) {
	    parsePlugin(parent);
	} else if (reader.matches(ELEMENT_ACTION)) {
	    parseElement(parent);
	} else if (reader.matches(ATTRIBUTE_ACTION)) {
	    err.jspError(start, "jsp.error.namedAttribute.invalidUse");
	} else if (reader.matches(BODY_ACTION)) {
	    err.jspError(start, "jsp.error.jspbody.invalidUse");
	} else if (reader.matches(FALLBACK_ACTION)) {
	    err.jspError(start, "jsp.error.fallback.invalidUse");
	} else if (reader.matches(PARAMS_ACTION)) {
	    err.jspError(start, "jsp.error.params.invalidUse");
	} else if (reader.matches(PARAM_ACTION)) {
	    err.jspError(start, "jsp.error.param.invalidUse");
	} else if (reader.matches(OUTPUT_ACTION)) {
	    err.jspError(start, "jsp.error.jspoutput.invalidUse");
	} else {
	    err.jspError(start, "jsp.error.badStandardAction");
	}
    }

    /*
     * # '<' CustomAction CustomActionBody
     *
     * CustomAction ::= TagPrefix ':' CustomActionName
     *
     * TagPrefix ::= Name
     *
     * CustomActionName ::= Name
     *
     * CustomActionBody ::=   ( Attributes CustomActionEnd )
     *                      | <TRANSLATION_ERROR>
     *
     * Attributes ::= ( S Attribute )* S?
     *
     * CustomActionEnd ::=   CustomActionTagDependent
     *                     | CustomActionJSPContent
     *                     | CustomActionScriptlessContent
     *
     * CustomActionTagDependent ::= TagDependentOptionalBody
     *
     * CustomActionJSPContent ::= OptionalBody
     *
     * CustomActionScriptlessContent ::= ScriptlessOptionalBody
     */
    private boolean parseCustomTag(Node parent) throws JasperException {

	if (reader.peekChar() != '<') {
	    return false;
	}

        // Parse 'CustomAction' production (tag prefix and custom action name)
	reader.nextChar();	// skip '<'
	String tagName = reader.parseToken(false);
	int i = tagName.indexOf(':');
	if (i == -1) {
	    reader.reset(start);
	    return false;
	}

	String prefix = tagName.substring(0, i);
	String shortTagName = tagName.substring(i+1);

	// Check if this is a user-defined tag.
	String uri = pageInfo.getURI(prefix);
        if (uri == null) {
	    reader.reset(start);
            // Remember the prefix for later error checking
            pageInfo.putNonCustomTagPrefix(prefix, reader.mark());
	    return false;
	}

        TagLibraryInfo tagLibInfo = pageInfo.getTaglib(uri);
	TagInfo tagInfo = tagLibInfo.getTag(shortTagName);
	TagFileInfo tagFileInfo = tagLibInfo.getTagFile(shortTagName);
	if (tagInfo == null && tagFileInfo == null) {
	    err.jspError(start, "jsp.error.bad_tag", shortTagName, prefix);
	}
	Class tagHandlerClass = null;
	if (tagInfo != null) {
	    // Must be a classic tag, load it here.
	    // tag files will be loaded later, in TagFileProcessor
	    String handlerClassName = tagInfo.getTagClassName();
	    try {
	        tagHandlerClass = ctxt.getClassLoader().loadClass(handlerClassName);
	    } catch (Exception e) {
	        err.jspError(start, "jsp.error.loadclass.taghandler",
			     handlerClassName, tagName);
	    }
	}

        // Parse 'CustomActionBody' production:
        // At this point we are committed - if anything fails, we produce
        // a translation error.

        // Parse 'Attributes' production:
	Attributes attrs = parseAttributes();
	reader.skipSpaces();
	
        // Parse 'CustomActionEnd' production:
	if (reader.matches("/>")) {
	    if (tagInfo != null) {
		new Node.CustomTag(tagName, prefix, shortTagName, uri, attrs,
				   start, parent, tagInfo, tagHandlerClass);
	    } else {
		new Node.CustomTag(tagName, prefix, shortTagName, uri, attrs,
				   start, parent, tagFileInfo);
	    }
	    return true;
	}
	
        // Now we parse one of 'CustomActionTagDependent', 
        // 'CustomActionJSPContent', or 'CustomActionScriptlessContent'.
        // depending on body-content in TLD.

	// Looking for a body, it still can be empty; but if there is a
	// a tag body, its syntax would be dependent on the type of
	// body content declared in the TLD.
	String bc;
	if (tagInfo != null) {
	    bc = tagInfo.getBodyContent();
	} else {
	    bc = tagFileInfo.getTagInfo().getBodyContent();
	}

	Node tagNode = null;
	if (tagInfo != null) {
	    tagNode = new Node.CustomTag(tagName, prefix, shortTagName, uri,
					 attrs, start, parent, tagInfo,
					 tagHandlerClass);
	} else {
	    tagNode = new Node.CustomTag(tagName, prefix, shortTagName, uri,
					 attrs, start, parent, tagFileInfo);
	}

	parseOptionalBody( tagNode, tagName, bc );

	return true;
    }

    /*
     * Parse for a template text string until '<' or "${" is encountered, 
     * recognizing escape sequences "\%" and "\$".
     */
    private void parseTemplateText(Node parent) throws JasperException {

	if (!reader.hasMoreInput())
	    return;

	CharArrayWriter ttext = new CharArrayWriter();
	// Output the first character
	int ch = reader.nextChar();
        if (ch == '\\') {
            reader.pushChar();
        } else {
            ttext.write(ch);
        }

	while (reader.hasMoreInput()) {
	    ch = reader.nextChar();
	    if (ch == '<') {
                reader.pushChar();
                break;
            }
	    else if( ch == '$' ) {
		if (!reader.hasMoreInput()) {
		    ttext.write('$');
		    break;
                }
		ch = reader.nextChar();
		if (ch == '{') {
		    reader.pushChar();
		    reader.pushChar();
		    break;
		}
		ttext.write('$');
		reader.pushChar();
		continue;
	    }
	    else if (ch == '\\') {
		if (!reader.hasMoreInput()) {
		    ttext.write('\\');
		    break;
		}
                char next = (char)reader.peekChar();
                // Looking for \% or \$
                // TODO: only recognize \$ if isELIgnored is false, but since
                // it can be set in a page directive, it cannot be determined
                // here.  Argh!
                if (next == '%' || next == '$') {
                    ch = reader.nextChar();
                }
	    }
	    ttext.write(ch);
	}
	new Node.TemplateText(ttext.toString(), start, parent);
    }
    
    /*
     * XMLTemplateText ::=   ( S? '/>' )
     *                     | ( S? '>'
     *                         ( ( Char* - ( Char* ( '<' | '${' ) ) )
     *                           ( '${' ELExpressionBody )?
     *                           CDSect?
     *                         )* ETag
     *                       )
     *                     | <TRANSLATION_ERROR>
     */
    private void parseXMLTemplateText(Node parent) throws JasperException {
        reader.skipSpaces();
        if( !reader.matches( "/>" ) ) {
            if( !reader.matches( ">" ) ) {
                err.jspError(start, "jsp.error.unterminated",
                    "&lt;jsp:text&gt;" );
            }
            CharArrayWriter ttext = new CharArrayWriter();
            while (reader.hasMoreInput()) {
        	int ch = reader.nextChar();
                if( ch == '<' ) {
                    // Check for <![CDATA[
                    if (!reader.matches("![CDATA[")) {
                        break;
                    }
                    start = reader.mark();
                    Mark stop = reader.skipUntil("]]>");
                    if (stop == null) {
                        err.jspError(start, "jsp.error.unterminated", "CDATA");
                    }
                    String text = reader.getText(start, stop);
                    ttext.write(text, 0, text.length());
                }
                else if( ch == '\\') {
                    if (!reader.hasMoreInput()) {
                        ttext.write('\\');
                        break;
		    }
                    ch = reader.nextChar();
                    if (ch != '$' ) {
                        ttext.write('\\');
                    }
                    ttext.write(ch);
                }
                else if( ch == '$' ) {
                    if (!reader.hasMoreInput()) {
                        ttext.write('$');
                        break;
                    }
                    ch = reader.nextChar();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?