📄 parser.java
字号:
// There's a "<jsp:body" before the ETag
// First, parse <jsp:attribute> elements:
parseNamedAttributes(parent);
result = true;
}
if (reader.matchesOptionalSpacesFollowedBy("<jsp:body")) {
// ActionBody
parseJspBody(parent, bodyType);
reader.skipSpaces();
if (!reader.matchesETag(tag)) {
err.jspError(reader.mark(), "jsp.error.unterminated", "<"
+ tag);
}
result = true;
} else if (result && !reader.matchesETag(tag)) {
// If we have <jsp:attribute> but something other than
// <jsp:body> or the end tag, translation error.
err.jspError(reader.mark(), "jsp.error.jspbody.required", "<"
+ tag);
}
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",
"<jsp:invoke");
}
parseInvoke(parent);
} else if (reader.matches(DOBODY_ACTION)) {
if (!isTagFile) {
err.jspError(reader.mark(), "jsp.error.action.isnottagfile",
"<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 "${" 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 == '$' || ch == '#') {
if (!reader.hasMoreInput()) {
ttext.write(ch);
break;
}
if (reader.nextChar() == '{') {
reader.pushChar();
reader.pushChar();
break;
}
ttext.write(ch);
reader.pushChar();
continue;
} else if (ch == '\\') {
if (!reader.hasMoreInput()) {
ttext.write('\\');
break;
}
char next = (char) reader.peekChar();
// Looking for \% or \$ or \#
// TODO: only recognize \$ or \# if isELIgnored is false, but since
// it can be set in a page directive, it cannot be determined
// here. Argh! (which is the way it should be since we shouldn't
// convolude multiple steps at once and create confusing parsers...)
if (next == '%' || 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",
"<jsp:text>");
}
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 == '\\') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -