bundles/org.apache.jasper.glassfish/src/org/apache/jasper/compiler/Parser.java
private void parseOptionalBody( Node parent, String tag, String bodyType ) 
        throws JasperException 
    {
	if (reader.matches("/>")) {
	    // EmptyBody
	    return;
	}

	if (!reader.matches(">")) {
	    err.jspError(reader.mark(), "jsp.error.unterminated",
			 "&lt;" + tag );
	}
        
        if( reader.matchesETag( tag ) ) {
            // EmptyBody
            return;
        }
        
        if( !parseJspAttributeAndBody( parent, tag, bodyType ) ) {
            // Must be ( '>' # Body ETag )
            parseBody(parent, tag, bodyType );
        }
    }
private void parseOptionalBody( Node parent, String tag, String bodyType ) 
        throws JasperException 
    {
	if (reader.matches("/>")) {
	    // EmptyBody
	    return;
	}

	if (!reader.matches(">")) {
	    err.jspError(reader.mark(), "jsp.error.unterminated",
			 "&lt;" + tag );
	}
        
        if( reader.matchesETag( tag ) ) {
            // EmptyBody
            return;
        }
        
        if( !parseJspAttributeAndBody( parent, tag, bodyType ) ) {
            // Must be ( '>' # Body ETag )
            parseBody(parent, tag, bodyType );
        }
    }
/*
Parses OptionalBody, but also reused to parse bodies for plugin
and param since the syntax is identical (the only thing that
differs substantially is how to process the body, and thus
we accept the body type as a parameter).

OptionalBody ::= EmptyBody | ActionBody

ScriptlessOptionalBody ::= EmptyBody | ScriptlessActionBody

TagDependentOptionalBody ::= EmptyBody | TagDependentActionBody

EmptyBody ::=   '/>'
| ( '>' ETag )
| ( '>' S? '<jsp:attribute' NamedAttributes ETag )

ActionBody ::=   JspAttributeAndBody
| ( '>' Body ETag )

ScriptlessActionBody ::=   JspAttributeAndBody
| ( '>' ScriptlessBody ETag )

TagDependentActionBody ::=   JspAttributeAndBody
| ( '>' TagDependentBody ETag )