SSL Parser.java
Interaktion und PortierbarkeitJAVA
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.jasper.compiler;
/** * This class implements a parser for a JSP page (non-xml view). JSP page * grammar is included here for reference. The token '#' that appears in the * production indicates the current input token location in the production. * * @author Kin-man Chung * @author Shawn Bayern * @author Mark Roth
*/
class Parser implements TagConstants {
privatefinal ParserController parserController;
privatefinal JspCompilationContext ctxt;
privatefinal JspReader reader;
private Mark start;
privatefinal ErrorDispatcher err;
privateint scriptlessCount;
privatefinalboolean isTagFile;
privatefinalboolean directivesOnly;
privatefinal Jar jar;
privatefinal PageInfo pageInfo;
// Virtual body content types, to make parsing a little easier. // These are not accessible from outside the parser. privatestaticfinal String JAVAX_BODY_CONTENT_PARAM = "JAVAX_BODY_CONTENT_PARAM";
/** * The main entry for Parser * * @param pc The ParseController, use for getting other objects in compiler * and for parsing included pages * @param reader To read the page * @param parent The parent node to this page, null for top level page * @param isTagFile Is the page being parsed a tag file? * @param directivesOnly Should only directives be parsed? * @param jar JAR, if any, that this page was loaded from * @param pageEnc The encoding of the source * @param jspConfigPageEnc The encoding for the page * @param isDefaultPageEncoding Is the page encoding the default? * @param isBomPresent Is a BOM present in the source * @return list of nodes representing the parsed page * * @throws JasperException If an error occurs during parsing
*/ publicstatic Node.Nodes parse(ParserController pc, JspReader reader,
Node parent, boolean isTagFile, boolean directivesOnly,
Jar jar, String pageEnc, String jspConfigPageEnc, boolean isDefaultPageEncoding, boolean isBomPresent) throws JasperException {
Parser parser = new Parser(pc, reader, isTagFile, directivesOnly, jar);
/** * Parse Attributes for a reader, provided for external use * * @param pc The parser * @param reader The source * * @return The parsed attributes * * @throws JasperException If an error occurs during parsing
*/ publicstatic Attributes parseAttributes(ParserController pc,
JspReader reader) throws JasperException {
Parser tmpParser = new Parser(pc, reader, false, false, null); return tmpParser.parseAttributes(true);
}
/** * Attribute ::= Name S? Eq S? ( '"<%=' RTAttributeValueDouble | '"' * AttributeValueDouble | "'<%=" RTAttributeValueSingle | "'" * AttributeValueSingle } Note: JSP and XML spec does not allow while spaces * around Eq. It is added to be backward compatible with Tomcat, and with * other xml parsers.
*/ privateboolean parseAttribute(AttributesImpl attrs) throws JasperException {
// Get the qualified name
String qName = parseName(); if (qName == null) { returnfalse;
}
boolean ignoreEL = pageInfo.isELIgnored();
// Determine prefix and local name components
String localName = qName;
String uri = ""; int index = qName.indexOf(':'); if (index != -1) {
String prefix = qName.substring(0, index);
uri = pageInfo.getURI(prefix); if (uri == null) {
err.jspError(reader.mark(), "jsp.error.attribute.invalidPrefix", prefix);
}
localName = qName.substring(index + 1);
}
reader.skipSpaces(); if (!reader.matches("=")) {
err.jspError(reader.mark(), "jsp.error.attribute.noequal");
}
// If watch is longer than 1 character this is a scripting // expression and EL is always ignored boolean isElIgnored =
pageInfo.isELIgnored() || watch.length() > 1;
/* * Parses a page directive with the following syntax: PageDirective ::= ( S * Attribute)*
*/ privatevoid parsePageDirective(Node parent) throws JasperException {
Attributes attrs = parseAttributes(true);
Node.PageDirective n = new Node.PageDirective(attrs, start, parent);
/* * A page directive may contain multiple 'import' attributes, each of * which consists of a comma-separated list of package names. Store each * list with the node, where it is parsed.
*/ for (int i = 0; i < attrs.getLength(); i++) { if ("import".equals(attrs.getQName(i))) {
n.addImport(attrs.getValue(i));
}
}
}
/* * Parses an include directive with the following syntax: IncludeDirective * ::= ( S Attribute)*
*/ privatevoid parseIncludeDirective(Node parent) throws JasperException {
Attributes attrs = parseAttributes();
// Included file expanded here
Node includeNode = new Node.IncludeDirective(attrs, start, parent);
processIncludeDirective(attrs.getValue("file"), includeNode);
}
/** * Add a list of files. This is used for implementing include-prelude and * include-coda of jsp-config element in web.xml
*/ privatevoid addInclude(Node parent, Collection<String> files) throws JasperException { if (files != null) { for (String file : files) {
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute("", "file", "file", "CDATA", file);
// Create a dummy Include directive node
Node includeNode = new Node.IncludeDirective(attrs, reader
.mark(), parent);
processIncludeDirective(file, includeNode);
}
}
}
/* * Parses a taglib directive with the following syntax: Directive ::= ( S * Attribute)*
*/ privatevoid parseTaglibDirective(Node parent) throws JasperException {
/* * Parses a tag directive with the following syntax: PageDirective ::= ( S * Attribute)*
*/ privatevoid parseTagDirective(Node parent) throws JasperException {
Attributes attrs = parseAttributes(true);
Node.TagDirective n = new Node.TagDirective(attrs, start, parent);
/* * A page directive may contain multiple 'import' attributes, each of * which consists of a comma-separated list of package names. Store each * list with the node, where it is parsed.
*/ for (int i = 0; i < attrs.getLength(); i++) { if ("import".equals(attrs.getQName(i))) {
n.addImport(attrs.getValue(i));
}
}
}
/* * Parses a attribute directive with the following syntax: * AttributeDirective ::= ( S Attribute)*
*/ privatevoid parseAttributeDirective(Node parent) throws JasperException {
Attributes attrs = parseAttributes();
@SuppressWarnings("unused")
Node unused = new Node.AttributeDirective(attrs, start, parent);
}
/* * Parses a variable directive with the following syntax: * PageDirective ::= ( S Attribute)*
*/ privatevoid parseVariableDirective(Node parent) throws JasperException {
Attributes attrs = parseAttributes();
@SuppressWarnings("unused")
Node unused = new Node.VariableDirective(attrs, start, parent);
}
if (reader.matchesOptionalSpacesFollowedBy(")) { // ActionBody
parseJspBody(parent, bodyType);
reader.skipSpaces(); if (!reader.matchesETag(tag)) {
err.jspError(reader.mark(), "jsp.error.unterminated", "<"
+ tag);
}
result = true;
} elseif (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);
}
// 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); returnfalse;
}
// Check if this is a user-defined tag.
String uri = pageInfo.getURI(prefix); if (uri == null) { if (pageInfo.isErrorOnUndeclaredNamespace()) {
err.jspError(start, "jsp.error.undeclared_namespace", prefix);
} else {
reader.reset(start); // Remember the prefix for later error checking
pageInfo.putNonCustomTagPrefix(prefix, reader.mark()); returnfalse;
}
}
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.
// 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();
}
/* * Parse for a template text string until '<' or "${" or "#{" is encountered, * recognizing escape sequences "<\%", "\$", and "\#". * * Note: JSP uses '\$' as an escape for '$' and '\#' for '#' whereas EL uses * '\${' for '${' and '\#{' for '#{'. We are processing JSP template * test here so the JSP escapes apply.
*/ privatevoid parseTemplateText(Node parent) {
if (!reader.hasMoreInput()) { return;
}
CharArrayWriter ttext = new CharArrayWriter();
int ch = reader.nextChar(); while (ch != -1) { if (ch == '<') { // Check for "<\%" if (reader.peekChar(0) == '\\' && reader.peekChar(1) == '%') {
ttext.write(ch); // Swallow the \
reader.nextChar();
ttext.write(reader.nextChar());
} else { if (ttext.size() == 0) {
ttext.write(ch);
} else {
reader.pushChar(); break;
}
}
} elseif (ch == '\\' && !pageInfo.isELIgnored()) { int next = reader.peekChar(0); if (next == '$' || next == '#') {
ttext.write(reader.nextChar());
} else {
ttext.write(ch);
}
} elseif ((ch == '$' || ch == '#' && !pageInfo.isDeferredSyntaxAllowedAsLiteral()) &&
!pageInfo.isELIgnored()) { if (reader.peekChar(0) == '{') {
reader.pushChar(); break;
} else {
ttext.write(ch);
}
} else {
ttext.write(ch);
}
ch = reader.nextChar();
}
@SuppressWarnings("unused")
Node unused = new Node.TemplateText(ttext.toString(), start, parent);
}
/* * XMLTemplateText ::= ( S? '/>' ) | ( S? '>' ( ( Char* - ( Char* ( '<' | * '${' ) ) ) ( '${' ELExpressionBody )? CDSect? )* ETag ) | * <TRANSLATION_ERROR>
*/ privatevoid 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(); int ch = reader.nextChar(); while (ch != -1) { 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());
} elseif (ch == '\\') { int next = reader.peekChar(0); if (next == '$' || next =='#') {
ttext.write(reader.nextChar());
} else {
ttext.write('\\');
}
} elseif (ch == '$' || ch == '#') { if (reader.peekChar(0) == '{') { // Swallow the '{'
reader.nextChar();
// Create a template text node
@SuppressWarnings("unused")
Node unused = new Node.TemplateText(
ttext.toString(), start, parent);
// Mark and parse the EL expression and create its node:
parseELExpression(parent, (char) ch);
reader.skipSpaces(); if (!reader.matches("/>")) { if (!reader.matches(">")) {
err.jspError(start, "jsp.error.unterminated", "<jsp:body");
}
parseBody(bodyNode, "jsp:body", bodyType);
}
}
/* * Parse the body as JSP content. @param tag The name of the tag whose end * tag would terminate the body @param bodyType One of the TagInfo body * types
*/ privatevoid parseBody(Node parent, String tag, String bodyType) throws JasperException { if (bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_TAG_DEPENDENT)) {
parseTagDependentBody(parent, tag);
} elseif (bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_EMPTY)) { if (!reader.matchesETag(tag)) {
err.jspError(start, "jasper.error.emptybodycontent.nonempty",
tag);
}
} elseif (bodyType == JAVAX_BODY_CONTENT_PLUGIN) { // (note the == since we won't recognize JAVAX_* // from outside this module).
parsePluginTags(parent); if (!reader.matchesETag(tag)) {
err.jspError(reader.mark(), "jsp.error.unterminated", "<"
+ tag);
}
} elseif (bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_JSP)
|| bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)
|| (bodyType == JAVAX_BODY_CONTENT_PARAM)
|| (bodyType == JAVAX_BODY_CONTENT_TEMPLATE_TEXT)) { while (reader.hasMoreInput()) { if (reader.matchesETag(tag)) { return;
}
// Check for nested jsp:body or jsp:attribute if (tag.equals("jsp:body") || tag.equals("jsp:attribute")) { if (reader.matches(")) {
err.jspError(reader.mark(), "jsp.error.nested.jspattribute");
} elseif (reader.matches(")) {
err.jspError(reader.mark(), "jsp.error.nested.jspbody");
}
}
if (bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_JSP)) {
parseElements(parent);
} elseif (bodyType
.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)) {
parseElementsScriptless(parent);
} elseif (bodyType == JAVAX_BODY_CONTENT_PARAM) { // (note the == since we won't recognize JAVAX_* // from outside this module).
reader.skipSpaces();
parseParam(parent);
} elseif (bodyType == JAVAX_BODY_CONTENT_TEMPLATE_TEXT) {
parseElementsTemplateText(parent);
}
}
err.jspError(start, "jsp.error.unterminated", "<" + tag);
} else {
err.jspError(start, "jasper.error.bad.bodycontent.type");
}
}
/* * Parses named attributes.
*/ privatevoid parseNamedAttributes(Node parent) throws JasperException { do {
Mark start = reader.mark();
Attributes attrs = parseAttributes();
Node.NamedAttribute namedAttributeNode = new Node.NamedAttribute(
attrs, start, parent);
reader.skipSpaces(); if (!reader.matches("/>")) { if (!reader.matches(">")) {
err.jspError(start, "jsp.error.unterminated", "<jsp:attribute");
} if (namedAttributeNode.isTrim()) {
reader.skipSpaces();
}
parseBody(namedAttributeNode, "jsp:attribute",
getAttributeBodyType(parent, attrs.getValue("name"))); if (namedAttributeNode.isTrim()) {
Node.Nodes subElems = namedAttributeNode.getBody();
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.68 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.