View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.xml.rule;
5   
6   import static org.junit.Assert.assertEquals;
7   import static org.junit.Assert.assertNotNull;
8   
9   import java.io.StringReader;
10  import java.util.ArrayList;
11  import java.util.HashMap;
12  import java.util.List;
13  import java.util.Map;
14  
15  import net.sourceforge.pmd.RuleContext;
16  import net.sourceforge.pmd.lang.Language;
17  import net.sourceforge.pmd.lang.Parser;
18  import net.sourceforge.pmd.lang.ast.Node;
19  import net.sourceforge.pmd.lang.xml.XmlParserOptions;
20  import net.sourceforge.pmd.lang.xml.ast.XmlNode;
21  
22  import org.junit.Test;
23  import org.w3c.dom.Attr;
24  import org.w3c.dom.CharacterData;
25  import org.w3c.dom.Comment;
26  import org.w3c.dom.Document;
27  import org.w3c.dom.DocumentType;
28  import org.w3c.dom.Element;
29  import org.w3c.dom.Entity;
30  import org.w3c.dom.EntityReference;
31  import org.w3c.dom.Notation;
32  import org.w3c.dom.ProcessingInstruction;
33  import org.w3c.dom.Text;
34  
35  public class AbstractDomXmlRuleTest {
36  
37  	@Test
38  	public void testVisit() throws Exception {
39  		String source = "<?xml version=\"1.0\"?><?mypi?><!DOCTYPE testDoc [<!ENTITY entity \"e\">]><!--Comment--><foo abc=\"abc\"><bar>TEXT</bar><![CDATA[cdata!]]>&gt;&entity;&lt;</foo>";
40  		XmlParserOptions parserOptions = new XmlParserOptions();
41  		parserOptions.setExpandEntityReferences(false);
42  		Parser parser = Language.XML.getDefaultVersion()
43  				.getLanguageVersionHandler().getParser(parserOptions);
44  		XmlNode xmlNode = (XmlNode) parser
45  				.parse(null, new StringReader(source));
46  		List<XmlNode> nodes = new ArrayList<XmlNode>();
47  		nodes.add(xmlNode);
48  
49  		MyRule rule = new MyRule();
50  		rule.apply(nodes, null);
51  
52  		List<org.w3c.dom.Node> visited = rule.visitedNodes.get("Attr");
53  		assertEquals(1, visited.size());
54  		assertEquals("abc", visited.get(0).getLocalName());
55  
56  		visited = rule.visitedNodes.get("CharacterData");
57  		assertEquals(1, visited.size());
58  		assertEquals("cdata!", ((CharacterData) visited.get(0)).getData());
59  
60  		visited = rule.visitedNodes.get("Comment");
61  		assertEquals("Comment", ((Comment) visited.get(0)).getData());
62  
63  		visited = rule.visitedNodes.get("Document");
64  		assertEquals(1, visited.size());
65  
66  		visited = rule.visitedNodes.get("DocumentType");
67  		assertEquals("testDoc", ((DocumentType) visited.get(0)).getName());
68  
69  		visited = rule.visitedNodes.get("Element");
70  		assertEquals(2, visited.size());
71  		assertEquals("foo", visited.get(0).getLocalName());
72  		assertEquals("bar", visited.get(1).getLocalName());
73  
74  		// TODO Figure out how to trigger this.
75  		// visited = rule.visitedNodes.get("Entity");
76  		// assertEquals(0, visited.size());
77  
78  		visited = rule.visitedNodes.get("EntityReference");
79  		assertEquals(3, visited.size());
80  		assertEquals("gt", ((EntityReference) visited.get(0)).getNodeName());
81          assertEquals("entity", ((EntityReference) visited.get(1)).getNodeName());
82          assertEquals("lt", ((EntityReference) visited.get(2)).getNodeName());
83  
84  		// TODO Figure out how to trigger this.
85  		// visited = rule.visitedNodes.get("Notation");
86  		// assertEquals(0, visited.size());
87  
88  		visited = rule.visitedNodes.get("ProcessingInstruction");
89  		assertEquals(1, visited.size());
90  		assertEquals("mypi",
91  				((ProcessingInstruction) visited.get(0)).getTarget());
92  
93  		visited = rule.visitedNodes.get("Text");
94  		assertEquals(2, visited.size());
95  		assertEquals("TEXT", ((Text) visited.get(0)).getData());
96  		assertEquals("e", ((Text) visited.get(1)).getData());
97  	}
98  
99  	@Test
100 	public void dtdIsNotLookedUp() {
101 		String source = "<!DOCTYPE struts-config PUBLIC "
102 				+ " \"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN \" "
103 				+ " \"http://jakarta.inexistinghost.org/struts/dtds/struts-config_1_1.dtd\" >"
104 				+ "<struts-config/>";
105 		XmlParserOptions parserOptions = new XmlParserOptions();
106 		parserOptions.setLookupDescriptorDoc(false);
107 		Parser parser = Language.XML.getDefaultVersion()
108 				.getLanguageVersionHandler().getParser(parserOptions);
109 		XmlNode xmlNode = (XmlNode) parser
110 				.parse(null, new StringReader(source));
111 		// no exception should be thrown
112 
113 		MyRule rule = new MyRule();
114 		List<XmlNode> nodes = new ArrayList<XmlNode>();
115 		nodes.add(xmlNode);
116 		rule.apply(nodes, null);
117 				
118 		// first element is still parsed
119 		assertNotNull(rule.visitedNodes.get("Element"));
120 
121 	}
122 
123 	@Test
124 	public void xsdIsNotLookedUp() {
125 		String source = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
126 				+ "<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\" "
127 				+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
128 				+ "xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.inexisting.com/xml/ns/javaee/web-app_2_5.xsd\" "
129 				+ "version=\"2.5\">" + "</web-app>";
130 		XmlParserOptions parserOptions = new XmlParserOptions();
131 		Parser parser = Language.XML.getDefaultVersion()
132 				.getLanguageVersionHandler().getParser(parserOptions);
133 		XmlNode xmlNode = (XmlNode) parser
134 				.parse(null, new StringReader(source));
135 		// no exception should be thrown
136 		// first element is still parsed
137 		MyRule rule = new MyRule();
138 		List<XmlNode> nodes = new ArrayList<XmlNode>();
139 		nodes.add(xmlNode);
140 		rule.apply(nodes, null);
141 		
142 		assertNotNull(rule.visitedNodes.get("Element"));
143 
144 	}
145 
146 	private static class MyRule extends AbstractDomXmlRule {
147 		final Map<String, List<org.w3c.dom.Node>> visitedNodes = new HashMap<String, List<org.w3c.dom.Node>>();
148 
149 		public MyRule() {
150 			
151 		}
152 
153 		private void visit(String key, org.w3c.dom.Node node) {
154 			List<org.w3c.dom.Node> nodes = visitedNodes.get(key);
155 			if (nodes == null) {
156 				nodes = new ArrayList<org.w3c.dom.Node>();
157 				visitedNodes.put(key, nodes);
158 			}
159 			nodes.add(node);
160 		}
161 
162 		@Override
163 		public void apply(List<? extends Node> nodes, RuleContext ctx) {
164 			super.apply(nodes, ctx);
165 		}
166 
167 		@Override
168 		protected void visit(XmlNode node, Attr attr, RuleContext ctx) {
169 			visit("Attr", attr);
170 			super.visit(node, attr, ctx);
171 		}
172 
173 		@Override
174 		protected void visit(XmlNode node, CharacterData characterData,
175 				RuleContext ctx) {
176 			visit("CharacterData", characterData);
177 			super.visit(node, characterData, ctx);
178 		}
179 
180 		@Override
181 		protected void visit(XmlNode node, Comment comment, RuleContext ctx) {
182 			visit("Comment", comment);
183 			super.visit(node, comment, ctx);
184 		}
185 
186 		@Override
187 		protected void visit(XmlNode node, Document document, RuleContext ctx) {
188 			visit("Document", document);
189 			super.visit(node, document, ctx);
190 		}
191 
192 		@Override
193 		protected void visit(XmlNode node, DocumentType documentType,
194 				RuleContext ctx) {
195 			visit("DocumentType", documentType);
196 			super.visit(node, documentType, ctx);
197 		}
198 
199 		@Override
200 		protected void visit(XmlNode node, Element element, RuleContext ctx) {
201 			visit("Element", element);
202 			super.visit(node, element, ctx);
203 		}
204 
205 		@Override
206 		protected void visit(XmlNode node, Entity entity, RuleContext ctx) {
207 			visit("Entity", entity);
208 			super.visit(node, entity, ctx);
209 		}
210 
211 		@Override
212 		protected void visit(XmlNode node, EntityReference entityReference,
213 				RuleContext ctx) {
214 			visit("EntityReference", entityReference);
215 			super.visit(node, entityReference, ctx);
216 		}
217 
218 		@Override
219 		protected void visit(XmlNode node, Notation notation, RuleContext ctx) {
220 			visit("Notation", notation);
221 			super.visit(node, notation, ctx);
222 		}
223 
224 		@Override
225 		protected void visit(XmlNode node,
226 				ProcessingInstruction processingInstruction, RuleContext ctx) {
227 			visit("ProcessingInstruction", processingInstruction);
228 			super.visit(node, processingInstruction, ctx);
229 		}
230 
231 		@Override
232 		protected void visit(XmlNode node, Text text, RuleContext ctx) {
233 			visit("Text", text);
234 			super.visit(node, text, ctx);
235 		}
236 	}
237 
238 	public static junit.framework.Test suite() {
239 		return new junit.framework.JUnit4TestAdapter(
240 				AbstractDomXmlRuleTest.class);
241 	}
242 }