Add support for Unicode for JSP/JSF.

Add support to not parse body of <script> for JSP/JSF.
Add new NoInlineScript rule for JSP/JSF.

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/4.2.x@7015 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Ryan Gustafson
2009-12-05 22:34:45 +00:00
parent f67056e7d7
commit 8fe5a0d780
16 changed files with 3932 additions and 2978 deletions

View File

@ -392,8 +392,16 @@
<delete file="src/net/sourceforge/pmd/jsp/ast/ParseException.java" />
<delete file="src/net/sourceforge/pmd/jsp/ast/CharStream.java" />
<jjtree target="etc/grammar/JspParser.jjt" outputdirectory="src/net/sourceforge/pmd/jsp/ast/" javacchome="${javacc-home.path}" />
<!-- Generate Unicode w/o Unicode Escapes CharStream implementation -->
<javacc static="false" usercharstream="false" unicodeinput="true" javaunicodeescape="false" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
<replace file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" token="public class SimpleCharStream" value="public class JspCharStream implements CharStream" />
<replace file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" token="public SimpleCharStream" value="public JspCharStream" />
<move file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" tofile="src/net/sourceforge/pmd/jsp/ast/JspCharStream.java"/>
<delete file="src/net/sourceforge/pmd/jsp/ast/JspParser.java" />
<!-- Ensure generated using CharStream interface -->
<javacc static="false" usercharstream="true" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
<javacc static="false" usercharstream="true" unicodeinput="true" javaunicodeescape="false" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
<delete file="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" />
<replace file="src/net/sourceforge/pmd/jsp/ast/JspParserTokenManager.java" token="throw new Error" value="throw new RuntimeException" />

View File

@ -13,6 +13,8 @@ Fixed bug 2904832 - Type resolution not working for ASTType when using an inner
Correct -benchmark reporting of Rule visits via the RuleChain
Fix issue with Type Resolution incorrectly handling of Classes with same name as a java.lang Class.
The JSP/JSF parser can now parse Unicode input.
The JSP/JSP parser can now handle <script>...</script> tags. The AST HtmlScript node contains the content.
Dependencies updates: asm updated to 3.2
@ -23,6 +25,7 @@ New rule:
Controversial : AvoidLiteralsInIfCondition (patch 2591627), UseConcurrentHashMap
StrictExceptions : AvoidCatchingGenericException, AvoidLosingExceptionInformation
Naming : GenericsNaming
JSP: NoInlineScript
February 08, 2009 - 4.2.5:

View File

@ -1,13 +1,15 @@
/* JSP Parser for PMD.
/* JSP Parser for PMD.
* It supports supports more-or-less well written JSP files.
* The JSP Document style is supported, except for inline DTD.
* The JSP Page style (<% ... %>) is supported.
* Java code is not parsed.
* Script code inside <script> ... </script> is not parsed.
*/
options {
USER_CHAR_STREAM = true;
NODE_USES_PARSER=true;
UNICODE_INPUT=true;
IGNORE_CASE = true;
STATIC = false;
@ -19,7 +21,7 @@ options {
PARSER_BEGIN(JspParser)
/**
* JSP Parser for PMD.
* @author Pieter Application Engineers NV/SA http://www.ae.be
* @author Pieter – Application Engineers NV/SA – http://www.ae.be
*/
package net.sourceforge.pmd.jsp.ast;
@ -78,6 +80,7 @@ PARSER_END(JspParser)
* - JspExpressionState : inside an expression <%= ... %>
* - JspDeclarationState : inside a declaration <%! ... %>
* - JspCommentState : inside a comment <%-- ... --%>
* - HtmlScriptContentState : inside an HTML script <script> ... </script>
*/
@ -263,6 +266,18 @@ PARSER_END(JspParser)
| < COMMENT_TEXT: (~[]) >
}
<HtmlScriptContentState> TOKEN :
{
<HTML_SCRIPT_CONTENT: (~[]) >
| <HTML_SCRIPT_END_TAG : "</script" | "</Script" | "</SCRIPT">
{
// We've done a custom lookahead for the closing </script> and found it.
// Put it back into the input stream, so it can be processed normally.
input_stream.backup(8);
image.setLength(image.length() - 8); // kill the "<script"
matchedToken.image = image.toString();
} : AfterTagState
}
/** ******************************************************************** */
/** ************************* JSP GRAMMAR **************************** */
@ -498,9 +513,20 @@ void Element() :
(Attribute())*
(
(<TAG_END>
{ jjtThis.setEmpty(false); }
{
jjtThis.setEmpty(false);
// Content in a <script> element needs special treatment (like a comment or CDataSection).
// Tell the TokenManager to start looking for the body of a script element. In this
// state all text will be consumed by the next token up to the closing </script> tag.
// This is a context sensitive switch for the token manager, not something one can
// express using normal JavaCC syntax. Hence the hoop jumping.
if ("script".equalsIgnoreCase(startTagName.image)) {
token_source.SwitchTo(HtmlScriptContentState);
}
}
(Content())?
(HtmlScript() | Content())?
<ENDTAG_START>
endTagName = <TAG_NAME>
@ -645,3 +671,16 @@ void DoctypeExternalId() :
{ jjtThis.setUri(quoteContent(systemLiteral.image)); }
)
}
void HtmlScript() :
{
StringBuffer content = new StringBuffer();
Token t;
}
{
(t = <HTML_SCRIPT_CONTENT> { content.append(t.image); })*
<HTML_SCRIPT_END_TAG>
{
jjtThis.setImage(content.toString().trim());
}
}

View File

@ -1,6 +1,13 @@
package test.net.sourceforge.pmd.jsp.ast;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import net.sourceforge.pmd.jsp.ast.ASTAttribute;
import net.sourceforge.pmd.jsp.ast.ASTAttributeValue;
import net.sourceforge.pmd.jsp.ast.ASTCData;
@ -8,14 +15,9 @@ import net.sourceforge.pmd.jsp.ast.ASTCommentTag;
import net.sourceforge.pmd.jsp.ast.ASTDoctypeDeclaration;
import net.sourceforge.pmd.jsp.ast.ASTDoctypeExternalId;
import net.sourceforge.pmd.jsp.ast.ASTElement;
import net.sourceforge.pmd.jsp.ast.ASTHtmlScript;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* Test parsing of a JSP in document style, by checking the generated AST.
*
@ -156,6 +158,17 @@ public class JspDocStyleTest extends AbstractJspNodesTst {
ASTCommentTag comment = (ASTCommentTag) comments.iterator().next();
assertEquals("Correct comment content expected!", "comment", comment.getImage());
}
/**
* Test parsing of HTML <script> element.
*/
@Test
public void testHtmlScript() {
Set scripts = getNodes(ASTHtmlScript.class, TEST_HTML_SCRIPT);
assertEquals("One script expected!", 1, scripts.size());
ASTHtmlScript script = (ASTHtmlScript) scripts.iterator().next();
assertEquals("Correct script content expected!", "Script!", script.getImage());
}
private static final String TEST_SIMPLEST_HTML = "<html/>";
@ -173,6 +186,9 @@ public class JspDocStyleTest extends AbstractJspNodesTst {
private static final String TEST_ATTRIBUTE_VALUE_CONTAINING_HASH =
"<tag:if something=\"#yes#\" foo=\"CREATE\"> <a href=\"#\">foo</a> </tag:if>";
private static final String TEST_HTML_SCRIPT =
"<html><head><script>Script!</script></head></html>";
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(JspDocStyleTest.class);
}

View File

@ -0,0 +1,17 @@
package test.net.sourceforge.pmd.jsp.rules;
import org.junit.Before;
import test.net.sourceforge.pmd.testframework.SimpleAggregatorTst;
public class NoInlineScriptTest extends SimpleAggregatorTst {
@Before
public void setUp() {
addRule("jsp", "NoInlineScript");
}
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(NoInlineScriptTest.class);
}
}

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-code>
<description><![CDATA[
A violation.
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
<html><head><script>Some script</script></head></html>
]]></code>
<source-type>jsp</source-type>
</test-code>
<test-code>
<description><![CDATA[
A violation.
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
<html><head><script src="script location">Some script</script></head></html>
]]></code>
<source-type>jsp</source-type>
</test-code>
<test-code>
<description><![CDATA[
Ok, no 'src' with empty body.
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
<html><head><script></script></head></html>
]]></code>
<source-type>jsp</source-type>
</test-code>
<test-code>
<description><![CDATA[
Ok, only 'src' with empty whitespace body.
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
<html><head><script src="script location"> </script></head></html>
]]></code>
<source-type>jsp</source-type>
</test-code>
<test-code>
<description><![CDATA[
Ok, only 'src' without body.
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
<html><head><script src="script location"/></head></html>
]]></code>
<source-type>jsp</source-type>
</test-code>
</test-data>

View File

@ -261,7 +261,39 @@ and
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" />
]]>
</example>
</rule>
<rule
name="NoInlineScript"
class="net.sourceforge.pmd.rules.XPathRule"
message="Avoiding inlining HTML script content"
externalInfoUrl="http://pmd.sourceforge.net/rules/basic-jsp.html#JspEncoding">
<description>
<![CDATA[
Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the <script> element.
Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth.
]]>
</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//HtmlScript[@Image != '']
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
Most browsers should be able to interpret the following headers:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" />
]]>
</example>
</rule>

View File

@ -0,0 +1,20 @@
/* Generated By:JJTree: Do not edit this line. ASTHtmlScript.java Version 4.1 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY= */
package net.sourceforge.pmd.jsp.ast;
public class ASTHtmlScript extends SimpleNode {
public ASTHtmlScript(int id) {
super(id);
}
public ASTHtmlScript(JspParser p, int id) {
super(p, id);
}
/** Accept the visitor. **/
public Object jjtAccept(JspParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
}
/* JavaCC - OriginalChecksum=8170f25fd45a522c3d56439f6d24e048 (do not edit this line) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* Generated By:JJTree&JavaCC: Do not edit this line. JspParserConstants.java */
/**
* JSP Parser for PMD.
* @author Pieter � Application Engineers NV/SA � http://www.ae.be
* @author Pieter – Application Engineers NV/SA – http://www.ae.be
*/
package net.sourceforge.pmd.jsp.ast;
@ -163,41 +163,47 @@ public interface JspParserConstants {
int COMMENT_END = 75;
/** RegularExpression Id. */
int COMMENT_TEXT = 76;
/** RegularExpression Id. */
int HTML_SCRIPT_CONTENT = 77;
/** RegularExpression Id. */
int HTML_SCRIPT_END_TAG = 78;
/** Lexical state. */
int CommentState = 0;
int HtmlScriptContentState = 0;
/** Lexical state. */
int AttrValueBetweenDoubleQuotesState = 1;
int CommentState = 1;
/** Lexical state. */
int AttrValueBetweenSingleQuotesState = 2;
int AttrValueBetweenDoubleQuotesState = 2;
/** Lexical state. */
int StartTagState = 3;
int AttrValueBetweenSingleQuotesState = 3;
/** Lexical state. */
int CDataState = 4;
int StartTagState = 4;
/** Lexical state. */
int DocTypeExternalIdState = 5;
int CDataState = 5;
/** Lexical state. */
int DocTypeState = 6;
int DocTypeExternalIdState = 6;
/** Lexical state. */
int JspCommentState = 7;
int DocTypeState = 7;
/** Lexical state. */
int JspDeclarationState = 8;
int JspCommentState = 8;
/** Lexical state. */
int JspExpressionState = 9;
int JspDeclarationState = 9;
/** Lexical state. */
int JspScriptletState = 10;
int JspExpressionState = 10;
/** Lexical state. */
int InTagState = 11;
int JspScriptletState = 11;
/** Lexical state. */
int AfterTagState = 12;
int InTagState = 12;
/** Lexical state. */
int AttrValueState = 13;
int AfterTagState = 13;
/** Lexical state. */
int JspDirectiveAttributesState = 14;
int AttrValueState = 14;
/** Lexical state. */
int JspDirectiveState = 15;
int JspDirectiveAttributesState = 15;
/** Lexical state. */
int DEFAULT = 16;
int JspDirectiveState = 16;
/** Lexical state. */
int DEFAULT = 17;
/** Literal token values. */
String[] tokenImage = {
@ -278,6 +284,8 @@ public interface JspParserConstants {
"<DOLLAR_OR_HASH_DOUBLE_QUOTE>",
"<COMMENT_END>",
"<COMMENT_TEXT>",
"<HTML_SCRIPT_CONTENT>",
"<HTML_SCRIPT_END_TAG>",
};
}

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@ public interface JspParserTreeConstants
public int JJTDECLARATION = 19;
public int JJTDOCTYPEDECLARATION = 20;
public int JJTDOCTYPEEXTERNALID = 21;
public int JJTHTMLSCRIPT = 22;
public String[] jjtNodeName = {
@ -50,6 +51,7 @@ public interface JspParserTreeConstants
"Declaration",
"DoctypeDeclaration",
"DoctypeExternalId",
"HtmlScript",
};
}
/* JavaCC - OriginalChecksum=d7bde07aef0db02727c15b118c4c677f (do not edit this line) */
/* JavaCC - OriginalChecksum=e88447ad3f3129b84d706554cb6c3195 (do not edit this line) */

View File

@ -25,5 +25,6 @@ public interface JspParserVisitor
public Object visit(ASTDeclaration node, Object data);
public Object visit(ASTDoctypeDeclaration node, Object data);
public Object visit(ASTDoctypeExternalId node, Object data);
public Object visit(ASTHtmlScript node, Object data);
}
/* JavaCC - OriginalChecksum=85c3652943205ef4624387751f8ca0e6 (do not edit this line) */
/* JavaCC - OriginalChecksum=04069d9511f38dbdc673d112c08dd375 (do not edit this line) */

View File

@ -92,4 +92,7 @@ public class JspParserVisitorAdapter implements JspParserVisitor {
return visit((SimpleNode) node, data);
}
public Object visit(ASTHtmlScript node, Object data) {
return visit((SimpleNode) node, data);
}
}

View File

@ -22,6 +22,7 @@ import net.sourceforge.pmd.jsp.ast.ASTDoctypeDeclaration;
import net.sourceforge.pmd.jsp.ast.ASTDoctypeExternalId;
import net.sourceforge.pmd.jsp.ast.ASTElExpression;
import net.sourceforge.pmd.jsp.ast.ASTElement;
import net.sourceforge.pmd.jsp.ast.ASTHtmlScript;
import net.sourceforge.pmd.jsp.ast.ASTJspComment;
import net.sourceforge.pmd.jsp.ast.ASTJspDeclaration;
import net.sourceforge.pmd.jsp.ast.ASTJspDirective;
@ -45,7 +46,7 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
/**
* Adds a violation to the report.
*
*
* @param data
* the RuleContext
* @param node
@ -58,7 +59,7 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
/**
* Adds a violation to the report.
*
*
* @param data
* the RuleContext
* @param node
@ -75,7 +76,7 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
/**
* Adds a violation to the report.
*
*
* @param data
* the RuleContext
* @param node
@ -92,7 +93,7 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
/**
* Adds a violation to the report.
*
*
* @param data
* the RuleContext
* @param node
@ -213,4 +214,8 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
public Object visit(ASTDoctypeExternalId node, Object data) {
return visit((SimpleNode)node, data);
}
public Object visit(ASTHtmlScript node, Object data) {
return visit((SimpleNode)node, data);
}
}