RuleSetFactoryTest xref

View Javadoc
1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 
3  */
4 package net.sourceforge.pmd;
5 
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertNotNull;
9 import static org.junit.Assert.assertNotSame;
10 import static org.junit.Assert.assertNull;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13 
14 import java.io.BufferedReader;
15 import java.io.ByteArrayInputStream;
16 import java.io.ByteArrayOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Properties;
24 import java.util.Set;
25 import java.util.StringTokenizer;
26 
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.parsers.SAXParser;
29 import javax.xml.parsers.SAXParserFactory;
30 
31 import junit.framework.Assert;
32 import junit.framework.JUnit4TestAdapter;
33 import net.sourceforge.pmd.lang.Language;
34 import net.sourceforge.pmd.lang.LanguageVersion;
35 import net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedLocalVariableRule;
36 import net.sourceforge.pmd.lang.rule.RuleReference;
37 import net.sourceforge.pmd.lang.rule.XPathRule;
38 import net.sourceforge.pmd.util.ResourceLoader;
39 
40 import org.junit.BeforeClass;
41 import org.junit.Test;
42 import org.xml.sax.InputSource;
43 import org.xml.sax.SAXException;
44 import org.xml.sax.SAXParseException;
45 import org.xml.sax.helpers.DefaultHandler;
46 
47 public class RuleSetFactoryTest {
48 	private static SAXParserFactory saxParserFactory;
49 	private static ValidateDefaultHandler validateDefaultHandlerXsd;
50 	private static ValidateDefaultHandler validateDefaultHandlerDtd;
51 	private static SAXParser saxParser;
52 	
53 	@BeforeClass
54 	public static void init() throws Exception {
55 	saxParserFactory = SAXParserFactory.newInstance();
56 	saxParserFactory.setValidating(true);
57 	saxParserFactory.setNamespaceAware(true);
58 	
59 		// Hope we're using Xerces, or this may not work!
60 		// Note: Features are listed here
61 		// http://xerces.apache.org/xerces2-j/features.html
62 		saxParserFactory.setFeature("http://xml.org/sax/features/validation",
63 				true);
64 		saxParserFactory.setFeature(
65 				"http://apache.org/xml/features/validation/schema", true);
66 		saxParserFactory
67 				.setFeature(
68 						"http://apache.org/xml/features/validation/schema-full-checking",
69 						true);
70 	
71 	validateDefaultHandlerXsd = new ValidateDefaultHandler("src/main/resources/ruleset_2_0_0.xsd");
72 	validateDefaultHandlerDtd = new ValidateDefaultHandler("src/main/resources/ruleset_2_0_0.dtd");
73 	
74 	saxParser = saxParserFactory.newSAXParser();
75 	}
76 	
77 	@Test
78 	public void testRuleSetFileName() throws RuleSetNotFoundException {
79 		RuleSet rs = loadRuleSet(EMPTY_RULESET);
80 		assertNull("RuleSet file name not expected", rs.getFileName());
81 
82 		RuleSetFactory rsf = new RuleSetFactory();
83 		rs = rsf.createRuleSet("rulesets/java/basic.xml");
84 		assertEquals("wrong RuleSet file name", rs.getFileName(),
85 				"rulesets/java/basic.xml");
86 	}
87 
88 	@Test
89 	public void testNoRuleSetFileName() throws RuleSetNotFoundException {
90 		RuleSet rs = loadRuleSet(EMPTY_RULESET);
91 		assertNull("RuleSet file name not expected", rs.getFileName());
92 	}
93 
94 	@Test
95 	public void testRefs() throws Throwable {
96 		InputStream in = ResourceLoader.loadResourceAsStream(
97 				"rulesets/java/migrating_to_15.xml", this.getClass()
98 						.getClassLoader());
99 		if (in == null) {
100 			throw new RuleSetNotFoundException(
101 					"Can't find resource Make sure the resource is a valid file or URL or is on the CLASSPATH. Here's the current classpath: "
102 							+ System.getProperty("java.class.path"));
103 		}
104 		RuleSetFactory rsf = new RuleSetFactory();
105 		RuleSet rs = rsf.createRuleSet("rulesets/java/migrating_to_15.xml");
106 		assertNotNull(rs.getRuleByName("AvoidEnumAsIdentifier"));
107 	}
108 
109 	@Test
110 	public void testExtendedReferences() throws Exception {
111 	 InputStream in = ResourceLoader.loadResourceAsStream("net/sourceforge/pmd/rulesets/reference-ruleset.xml",
112 		 this.getClass().getClassLoader());
113 	 Assert.assertNotNull("Test ruleset not found - can't continue with test!", in);
114 
115 	 RuleSetFactory rsf = new RuleSetFactory();
116 	 RuleSets rs = rsf.createRuleSets("net/sourceforge/pmd/rulesets/reference-ruleset.xml");
117 	 // added by referencing a complete ruleset (java-basic)
118 	 assertNotNull(rs.getRuleByName("JumbledIncrementer"));
119 	 assertNotNull(rs.getRuleByName("ForLoopShouldBeWhileLoop"));
120 	 assertNotNull(rs.getRuleByName("OverrideBothEqualsAndHashcode"));
121 
122 	 // added by specific reference
123 	 assertNotNull(rs.getRuleByName("UnusedLocalVariable"));
124 	 assertNotNull(rs.getRuleByName("DuplicateImports"));
125 	 // this is from java-unusedcode, but not referenced
126 	 assertNull(rs.getRuleByName("UnusedPrivateField"));
127 
128 	 Rule emptyCatchBlock = rs.getRuleByName("EmptyCatchBlock");
129 	 assertNotNull(emptyCatchBlock);
130 
131 	 Rule collapsibleIfStatements = rs.getRuleByName("CollapsibleIfStatements");
132 	 assertEquals("Just combine them!", collapsibleIfStatements.getMessage());
133 	 // assert that CollapsibleIfStatements is only once added to the ruleset, so that it really
134 	 // overwrites the configuration inherited from java/basic.xml
135 	 assertEquals(1, countRule(rs, "CollapsibleIfStatements"));
136 
137 	 Rule cyclomaticComplexity = rs.getRuleByName("CyclomaticComplexity");
138 	 assertNotNull(cyclomaticComplexity);
139 	 PropertyDescriptor<?> prop = cyclomaticComplexity.getPropertyDescriptor("reportLevel");
140 	 Object property = cyclomaticComplexity.getProperty(prop);
141 	 assertEquals("5", String.valueOf(property));
142 
143 	 // included from braces
144 	 assertNotNull(rs.getRuleByName("IfStmtsMustUseBraces"));
145 	 // excluded from braces
146 	 assertNull(rs.getRuleByName("WhileLoopsMustUseBraces"));
147 
148 	 // overridden to 5
149 	 Rule simplifyBooleanExpressions = rs.getRuleByName("SimplifyBooleanExpressions");
150 	 assertNotNull(simplifyBooleanExpressions);
151 	 assertEquals(5, simplifyBooleanExpressions.getPriority().getPriority());
152 	 assertEquals(1, countRule(rs, "SimplifyBooleanExpressions"));
153 	 // priority overridden for whole design group
154 	 Rule useUtilityClass = rs.getRuleByName("UseUtilityClass");
155 	 assertNotNull(useUtilityClass);
156 	 assertEquals(2, useUtilityClass.getPriority().getPriority());
157 	 Rule simplifyBooleanReturns = rs.getRuleByName("SimplifyBooleanReturns");
158 	 assertNotNull(simplifyBooleanReturns);
159 	 assertEquals(2, simplifyBooleanReturns.getPriority().getPriority());
160 	}
161 
162 private int countRule(RuleSets rs, String ruleName) {
163 int count = 0;
164 	 for (Rule r : rs.getAllRules()) {
165 	 if (ruleName.equals(r.getName())) {
166 	 count++;
167 	 }
168 	 }
169 return count;
170 }
171 
172 	@Test(expected = RuleSetNotFoundException.class)
173 	public void testRuleSetNotFound() throws RuleSetNotFoundException {
174 		RuleSetFactory rsf = new RuleSetFactory();
175 		rsf.createRuleSet("fooooo");
176 	}
177 
178 	@Test
179 	public void testCreateEmptyRuleSet() throws RuleSetNotFoundException {
180 		RuleSet rs = loadRuleSet(EMPTY_RULESET);
181 		assertEquals("test", rs.getName());
182 		assertEquals(0, rs.size());
183 	}
184 
185 	@Test
186 	public void testSingleRule() throws RuleSetNotFoundException {
187 		RuleSet rs = loadRuleSet(SINGLE_RULE);
188 		assertEquals(1, rs.size());
189 		Rule r = rs.getRules().iterator().next();
190 		assertEquals("MockRuleName", r.getName());
191 		assertEquals("net.sourceforge.pmd.lang.rule.MockRule", r.getRuleClass());
192 		assertEquals("avoid the mock rule", r.getMessage());
193 	}
194 
195 	@Test
196 	public void testMultipleRules() throws RuleSetNotFoundException {
197 		RuleSet rs = loadRuleSet(MULTIPLE_RULES);
198 		assertEquals(2, rs.size());
199 		Set<String> expected = new HashSet<String>();
200 		expected.add("MockRuleName1");
201 		expected.add("MockRuleName2");
202 		for (Rule rule : rs.getRules()) {
203 			assertTrue(expected.contains(rule.getName()));
204 		}
205 	}
206 
207 	@Test
208 	public void testSingleRuleWithPriority() throws RuleSetNotFoundException {
209 		assertEquals(RulePriority.MEDIUM, loadFirstRule(PRIORITY).getPriority());
210 	}
211 
212 	@Test
213 	@SuppressWarnings("unchecked")
214 	public void testProps() throws RuleSetNotFoundException {
215 		Rule r = loadFirstRule(PROPERTIES);
216 		assertEquals("bar", r.getProperty((PropertyDescriptor<String>) r.getPropertyDescriptor("fooString")));
217 		assertEquals(new Integer(3), r.getProperty((PropertyDescriptor<Integer>) r.getPropertyDescriptor("fooInt")));
218 		assertTrue(r.getProperty((PropertyDescriptor<Boolean>) r.getPropertyDescriptor("fooBoolean")));
219 		assertEquals(3.0d, r.getProperty((PropertyDescriptor<Double>) r.getPropertyDescriptor("fooDouble")), 0.05);
220 		assertNull(r.getPropertyDescriptor("BuggleFish"));
221 		assertNotSame(r.getDescription().indexOf("testdesc2"), -1);
222 	}
223 
224 	@Test
225 	@SuppressWarnings("unchecked")
226 	public void testXPath() throws RuleSetNotFoundException {
227 		Rule r = loadFirstRule(XPATH);
228 		PropertyDescriptor<String> xpathProperty = (PropertyDescriptor<String>) r.getPropertyDescriptor("xpath");
229 		assertNotNull("xpath property descriptor", xpathProperty);
230 		assertNotSame(r.getProperty(xpathProperty).indexOf(" //Block "), -1);
231 	}
232 
233 	@Test
234 	public void testFacadesOffByDefault() throws RuleSetNotFoundException {
235 		Rule r = loadFirstRule(XPATH);
236 		assertFalse(r.usesDFA());
237 	}
238 
239 	@Test
240 	public void testDFAFlag() throws RuleSetNotFoundException {
241 		assertTrue(loadFirstRule(DFA).usesDFA());
242 	}
243 
244 	@Test
245 	public void testExternalReferenceOverride() throws RuleSetNotFoundException {
246 		Rule r = loadFirstRule(REF_OVERRIDE);
247 		assertEquals("TestNameOverride", r.getName());
248 		assertEquals("Test message override", r.getMessage());
249 		assertEquals("Test description override", r.getDescription());
250 		assertEquals("Test that both example are stored", 2, r.getExamples().size());
251 		assertEquals("Test example override", r.getExamples().get(1));
252 		assertEquals(RulePriority.MEDIUM, r.getPriority());
253 		PropertyDescriptor<?> test2Descriptor = r.getPropertyDescriptor("test2");
254 		assertNotNull("test2 descriptor", test2Descriptor);
255 		assertEquals("override2", r.getProperty(test2Descriptor));
256 		PropertyDescriptor<?> test3Descriptor = r.getPropertyDescriptor("test3");
257 		assertNotNull("test3 descriptor", test3Descriptor);
258 		assertEquals("override3", r.getProperty(test3Descriptor));
259 		PropertyDescriptor<?> test4Descriptor = r.getPropertyDescriptor("test4");
260 		assertNotNull("test3 descriptor", test4Descriptor);
261 		assertEquals("new property", r.getProperty(test4Descriptor));
262 	}
263 
264 	@Test
265 	public void testReferenceInternalToInternal()
266 			throws RuleSetNotFoundException {
267 		RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_INTERNAL);
268 
269 		Rule rule = ruleSet.getRuleByName("MockRuleName");
270 		assertNotNull("Could not find Rule MockRuleName", rule);
271 
272 		Rule ruleRef = ruleSet.getRuleByName("MockRuleNameRef");
273 		assertNotNull("Could not find Rule MockRuleNameRef", ruleRef);
274 	}
275 
276 	@Test
277 	public void testReferenceInternalToInternalChain()
278 			throws RuleSetNotFoundException {
279 		RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_INTERNAL_CHAIN);
280 
281 		Rule rule = ruleSet.getRuleByName("MockRuleName");
282 		assertNotNull("Could not find Rule MockRuleName", rule);
283 
284 		Rule ruleRef = ruleSet.getRuleByName("MockRuleNameRef");
285 		assertNotNull("Could not find Rule MockRuleNameRef", ruleRef);
286 
287 		Rule ruleRefRef = ruleSet.getRuleByName("MockRuleNameRefRef");
288 		assertNotNull("Could not find Rule MockRuleNameRefRef", ruleRefRef);
289 	}
290 
291 	@Test
292 	public void testReferenceInternalToExternal()
293 			throws RuleSetNotFoundException {
294 		RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_EXTERNAL);
295 
296 		Rule rule = ruleSet.getRuleByName("ExternalRefRuleName");
297 		assertNotNull("Could not find Rule ExternalRefRuleName", rule);
298 
299 		Rule ruleRef = ruleSet.getRuleByName("ExternalRefRuleNameRef");
300 		assertNotNull("Could not find Rule ExternalRefRuleNameRef", ruleRef);
301 	}
302 
303 	@Test
304 	public void testReferenceInternalToExternalChain()
305 			throws RuleSetNotFoundException {
306 		RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_EXTERNAL_CHAIN);
307 
308 		Rule rule = ruleSet.getRuleByName("ExternalRefRuleName");
309 		assertNotNull("Could not find Rule ExternalRefRuleName", rule);
310 
311 		Rule ruleRef = ruleSet.getRuleByName("ExternalRefRuleNameRef");
312 		assertNotNull("Could not find Rule ExternalRefRuleNameRef", ruleRef);
313 
314 		Rule ruleRefRef = ruleSet.getRuleByName("ExternalRefRuleNameRefRef");
315 		assertNotNull("Could not find Rule ExternalRefRuleNameRefRef",
316 				ruleRefRef);
317 	}
318 
319 	@Test
320 	public void testReferencePriority() throws RuleSetNotFoundException {
321 		RuleSetFactory rsf = new RuleSetFactory();
322 
323 		rsf.setMinimumPriority(RulePriority.LOW);
324 		RuleSet ruleSet = rsf
325 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
326 		assertEquals("Number of Rules", 3, ruleSet.getRules().size());
327 		assertNotNull(ruleSet.getRuleByName("MockRuleName"));
328 		assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
329 		assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
330 
331 		rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
332 		ruleSet = rsf
333 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
334 		assertEquals("Number of Rules", 2, ruleSet.getRules().size());
335 		assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
336 		assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
337 
338 		rsf.setMinimumPriority(RulePriority.HIGH);
339 		ruleSet = rsf
340 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
341 		assertEquals("Number of Rules", 1, ruleSet.getRules().size());
342 		assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
343 
344 		rsf.setMinimumPriority(RulePriority.LOW);
345 		ruleSet = rsf
346 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
347 		assertEquals("Number of Rules", 3, ruleSet.getRules().size());
348 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleName"));
349 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
350 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
351 
352 		rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
353 		ruleSet = rsf
354 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
355 		assertEquals("Number of Rules", 2, ruleSet.getRules().size());
356 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
357 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
358 
359 		rsf.setMinimumPriority(RulePriority.HIGH);
360 		ruleSet = rsf
361 				.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
362 		assertEquals("Number of Rules", 1, ruleSet.getRules().size());
363 		assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
364 	}
365 
366 	@Test
367 	public void testOverrideMessage() throws RuleSetNotFoundException {
368 		Rule r = loadFirstRule(REF_OVERRIDE_ORIGINAL_NAME);
369 		assertEquals("TestMessageOverride", r.getMessage());
370 	}
371 
372 	@Test
373 	public void testOverrideMessageOneElem() throws RuleSetNotFoundException {
374 		Rule r = loadFirstRule(REF_OVERRIDE_ORIGINAL_NAME_ONE_ELEM);
375 		assertEquals("TestMessageOverride", r.getMessage());
376 	}
377 
378 	@Test(expected = IllegalArgumentException.class)
379 	public void testIncorrectExternalRef() throws IllegalArgumentException,
380 			RuleSetNotFoundException {
381 		loadFirstRule(REF_MISPELLED_XREF);
382 	}
383 
384 	@Test
385 	public void testSetPriority() throws RuleSetNotFoundException {
386 		RuleSetFactory rsf = new RuleSetFactory();
387 		rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
388 		assertEquals(0, rsf
389 				.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
390 		rsf.setMinimumPriority(RulePriority.MEDIUM_LOW);
391 		assertEquals(1, rsf
392 				.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
393 	}
394 
395 	@Test
396 	public void testLanguage() throws RuleSetNotFoundException {
397 		Rule r = loadFirstRule(LANGUAGE);
398 		assertEquals(Language.JAVA, r.getLanguage());
399 	}
400 
401 	@Test(expected = IllegalArgumentException.class)
402 	public void testIncorrectLanguage() throws RuleSetNotFoundException {
403 		loadFirstRule(INCORRECT_LANGUAGE);
404 	}
405 
406 	@Test
407 	public void testMinimumLanugageVersion() throws RuleSetNotFoundException {
408 		Rule r = loadFirstRule(MINIMUM_LANGUAGE_VERSION);
409 		assertEquals(LanguageVersion.JAVA_14, r.getMinimumLanguageVersion());
410 	}
411 
412 	@Test(expected = IllegalArgumentException.class)
413 	public void testIncorrectMinimumLanugageVersion()
414 			throws RuleSetNotFoundException {
415 		loadFirstRule(INCORRECT_MINIMUM_LANGUAGE_VERSION);
416 	}
417 
418 	@Test
419 	public void testMaximumLanugageVersion() throws RuleSetNotFoundException {
420 		Rule r = loadFirstRule(MAXIMUM_LANGUAGE_VERSION);
421 		assertEquals(LanguageVersion.JAVA_17, r.getMaximumLanguageVersion());
422 	}
423 
424 	@Test(expected = IllegalArgumentException.class)
425 	public void testIncorrectMaximumLanugageVersion()
426 			throws RuleSetNotFoundException {
427 		loadFirstRule(INCORRECT_MAXIMUM_LANGUAGE_VERSION);
428 	}
429 
430 	@Test(expected = IllegalArgumentException.class)
431 	public void testInvertedMinimumMaximumLanugageVersions()
432 			throws RuleSetNotFoundException {
433 		loadFirstRule(INVERTED_MINIMUM_MAXIMUM_LANGUAGE_VERSIONS);
434 	}
435 
436 	@Test
437 	public void testDirectDeprecatedRule() throws RuleSetNotFoundException {
438 		Rule r = loadFirstRule(DIRECT_DEPRECATED_RULE);
439 		assertNotNull("Direct Deprecated Rule", r);
440 	}
441 
442 	@Test
443 	public void testReferenceToDeprecatedRule() throws RuleSetNotFoundException {
444 		Rule r = loadFirstRule(REFERENCE_TO_DEPRECATED_RULE);
445 		assertNotNull("Reference to Deprecated Rule", r);
446 		assertTrue("Rule Reference", r instanceof RuleReference);
447 		assertFalse("Not deprecated", r.isDeprecated());
448 		assertTrue("Original Rule Deprecated", ((RuleReference) r).getRule()
449 				.isDeprecated());
450 		assertEquals("Rule name", r.getName(), DEPRECATED_RULE_NAME);
451 	}
452 
453 	@Test
454 	public void testRuleSetReferenceWithDeprecatedRule()
455 			throws RuleSetNotFoundException {
456 		RuleSet ruleSet = loadRuleSet(REFERENCE_TO_RULESET_WITH_DEPRECATED_RULE);
457 		assertNotNull("RuleSet", ruleSet);
458 		assertFalse("RuleSet empty", ruleSet.getRules().isEmpty());
459 		// No deprecated Rules should be loaded when loading an entire RuleSet
460 		// by reference.
461 		Rule r = ruleSet.getRuleByName(DEPRECATED_RULE_NAME);
462 		assertNull("Deprecated Rule Reference", r);
463 		for (Rule rule : ruleSet.getRules()) {
464 			assertFalse("Rule not deprecated", rule.isDeprecated());
465 		}
466 	}
467 
468 	@Test
469 	public void testExternalReferences() throws RuleSetNotFoundException {
470 		RuleSet rs = loadRuleSet(EXTERNAL_REFERENCE_RULE_SET);
471 		assertEquals(1, rs.size());
472 		assertEquals(UnusedLocalVariableRule.class.getName(), rs.getRuleByName(
473 				"UnusedLocalVariable").getRuleClass());
474 	}
475 
476 	@Test
477 	public void testIncludeExcludePatterns() throws RuleSetNotFoundException {
478 		RuleSet ruleSet = loadRuleSet(INCLUDE_EXCLUDE_RULESET);
479 
480 		assertNotNull("Include patterns", ruleSet.getIncludePatterns());
481 		assertEquals("Include patterns size", 2, ruleSet.getIncludePatterns()
482 				.size());
483 		assertEquals("Include pattern #1", "include1", ruleSet
484 				.getIncludePatterns().get(0));
485 		assertEquals("Include pattern #2", "include2", ruleSet
486 				.getIncludePatterns().get(1));
487 
488 		assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
489 		assertEquals("Exclude patterns size", 3, ruleSet.getExcludePatterns()
490 				.size());
491 		assertEquals("Exclude pattern #1", "exclude1", ruleSet
492 				.getExcludePatterns().get(0));
493 		assertEquals("Exclude pattern #2", "exclude2", ruleSet
494 				.getExcludePatterns().get(1));
495 		assertEquals("Exclude pattern #3", "exclude3", ruleSet
496 				.getExcludePatterns().get(2));
497 	}
498 
499 	@Test
500 	public void testAllPMDBuiltInRulesMeetConventions() throws IOException,
501 			RuleSetNotFoundException, ParserConfigurationException,
502 			SAXException {
503 		int invalidSinceAttributes = 0;
504 		int invalidExternalInfoURL = 0;
505 		int invalidClassName = 0;
506 		int invalidRegexSuppress = 0;
507 		int invalidXPathSuppress = 0;
508 		String messages = "";
509 		List<String> ruleSetFileNames = getRuleSetFileNames();
510 		for (String fileName : ruleSetFileNames) {
511 			RuleSet ruleSet = loadRuleSetByFileName(fileName);
512 			for (Rule rule : ruleSet.getRules()) {
513 
514 				// Skip references
515 				if (rule instanceof RuleReference) {
516 					continue;
517 				}
518 
519 				Language language = rule.getLanguage();
520 				String group = fileName
521 						.substring(fileName.lastIndexOf('/') + 1);
522 				group = group.substring(0, group.indexOf(".xml"));
523 				if (group.indexOf('-') >= 0) {
524 					group = group.substring(0, group.indexOf('-'));
525 				}
526 
527 				// Is since missing ?
528 				if (rule.getSince() == null) {
529 					invalidSinceAttributes++;
530 					messages += "Rule " + fileName + "/" + rule.getName()
531 							+ " is missing 'since' attribute" + PMD.EOL;
532 				}
533 				// Is URL valid ?
534 				if (rule.getExternalInfoUrl() == null
535 						|| "".equalsIgnoreCase(rule.getExternalInfoUrl())) {
536 					invalidExternalInfoURL++;
537 					messages += "Rule " + fileName + "/" + rule.getName()
538 							+ " is missing 'externalInfoURL' attribute"
539 							+ PMD.EOL;
540 				} else {
541 					String expectedExternalInfoURL = "http://pmd.sourceforge.net/.+/rules/"
542 							+ fileName.replaceAll("rulesets/", "").replaceAll(
543 									".xml", "") + ".html#" + rule.getName();
544 					if (rule.getExternalInfoUrl() == null
545 						|| !rule.getExternalInfoUrl().matches(expectedExternalInfoURL)) {
546 						invalidExternalInfoURL++;
547 						messages += "Rule "
548 								+ fileName
549 								+ "/"
550 								+ rule.getName()
551 								+ " seems to have an invalid 'externalInfoURL' value ("
552 								+ rule.getExternalInfoUrl()
553 								+ "), it should be:" + expectedExternalInfoURL
554 								+ PMD.EOL;
555 					}
556 				}
557 				// Proper class name/packaging?
558 				String expectedClassName = "net.sourceforge.pmd.lang."
559 						+ language.getTerseName() + ".rule." + group + "."
560 						+ rule.getName() + "Rule";
561 				if (!rule.getRuleClass().equals(expectedClassName)
562 						&& !rule.getRuleClass().equals(
563 								XPathRule.class.getName())) {
564 					invalidClassName++;
565 					messages += "Rule " + fileName + "/" + rule.getName()
566 							+ " seems to have an invalid 'class' value ("
567 							+ rule.getRuleClass() + "), it should be:"
568 							+ expectedClassName + PMD.EOL;
569 				}
570 				// Should not have violation suppress regex property
571 				if (rule.getProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR) != null) {
572 					invalidRegexSuppress++;
573 					messages += "Rule "
574 							+ fileName
575 							+ "/"
576 							+ rule.getName()
577 							+ " should not have '"
578 							+ Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
579 							+ "', this is intended for end user customization only."
580 							+ PMD.EOL;
581 				}
582 				// Should not have violation suppress xpath property
583 				if (rule.getProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR) != null) {
584 					invalidXPathSuppress++;
585 					messages += "Rule "
586 							+ fileName
587 							+ "/"
588 							+ rule.getName()
589 							+ " should not have '"
590 							+ Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
591 							+ "', this is intended for end user customization only."
592 							+ PMD.EOL;
593 				}
594 			}
595 		}
596 		// We do this at the end to ensure we test ALL the rules before failing
597 		// the test
598 		if (invalidSinceAttributes > 0 || invalidExternalInfoURL > 0
599 				|| invalidClassName > 0 || invalidRegexSuppress > 0
600 				|| invalidXPathSuppress > 0) {
601 			fail("All built-in PMD rules need 'since' attribute ("
602 					+ invalidSinceAttributes
603 					+ " are missing), a proper ExternalURLInfo ("
604 					+ invalidExternalInfoURL
605 					+ " are invalid), a class name meeting conventions ("
606 					+ invalidClassName + " are invalid), no '"
607 					+ Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
608 					+ "' property (" + invalidRegexSuppress
609 					+ " are invalid), and no '"
610 					+ Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
611 					+ "' property (" + invalidXPathSuppress + " are invalid)"
612 					+ PMD.EOL + messages);
613 		}
614 	}
615 
616 	@Test
617 	public void testXmlSchema() throws IOException, RuleSetNotFoundException,
618 			ParserConfigurationException, SAXException {
619 		boolean allValid = true;
620 		List<String> ruleSetFileNames = getRuleSetFileNames();
621 		for (String fileName : ruleSetFileNames) {
622 			boolean valid = validateAgainstSchema(fileName);
623 			allValid = allValid && valid;
624 		}
625 		assertTrue("All XML must parse without producing validation messages.",
626 				allValid);
627 	}
628 
629 	@Test
630 	public void testDtd() throws IOException, RuleSetNotFoundException,
631 			ParserConfigurationException, SAXException {
632 		boolean allValid = true;
633 		List<String> ruleSetFileNames = getRuleSetFileNames();
634 		for (String fileName : ruleSetFileNames) {
635 			boolean valid = validateAgainstDtd(fileName);
636 			allValid = allValid && valid;
637 		}
638 		assertTrue("All XML must parse without producing validation messages.",
639 				allValid);
640 	}
641 
642 	@Test
643 	public void testReadWriteRoundTrip() throws IOException,
644 			RuleSetNotFoundException, ParserConfigurationException,
645 			SAXException {
646 
647 		List<String> ruleSetFileNames = getRuleSetFileNames();
648 		for (String fileName : ruleSetFileNames) {
649 			testRuleSet(fileName);
650 		}
651 	}
652 
653 	public void testRuleSet(String fileName) throws IOException,
654 			RuleSetNotFoundException, ParserConfigurationException,
655 			SAXException {
656 
657 		// Load original XML
658 //		String xml1 = readFullyToString(ResourceLoader.loadResourceAsStream(fileName));
659 //		System.out.println("xml1: " + xml1);
660 
661 		// Load the original RuleSet
662 		RuleSet ruleSet1 = loadRuleSetByFileName(fileName);
663 
664 		// Write to XML, first time
665 		ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();
666 		RuleSetWriter writer1 = new RuleSetWriter(outputStream1);
667 		writer1.write(ruleSet1);
668 		writer1.close();
669 		String xml2 = new String(outputStream1.toByteArray());
670 		// System.out.println("xml2: " + xml2);
671 
672 		// Read RuleSet from XML, first time
673 		RuleSetFactory ruleSetFactory = new RuleSetFactory();
674 		RuleSet ruleSet2 = ruleSetFactory
675 				.createRuleSet(createRuleSetReferenceId(xml2));
676 
677 		// Do write/read a 2nd time, just to be sure
678 
679 		// Write to XML, second time
680 		ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
681 		RuleSetWriter writer2 = new RuleSetWriter(outputStream2);
682 		writer2.write(ruleSet2);
683 		writer2.close();
684 		String xml3 = new String(outputStream2.toByteArray());
685 		// System.out.println("xml3: " + xml3);
686 
687 		// Read RuleSet from XML, second time
688 		RuleSet ruleSet3 = ruleSetFactory
689 				.createRuleSet(createRuleSetReferenceId(xml3));
690 
691 		// The 2 written XMLs should all be valid w.r.t Schema/DTD
692 		assertTrue(
693 				"1st roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
694 				validateAgainstSchema(new ByteArrayInputStream(xml2.getBytes())));
695 		assertTrue(
696 				"2nd roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
697 				validateAgainstSchema(new ByteArrayInputStream(xml3.getBytes())));
698 		assertTrue("1st roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
699 				validateAgainstDtd(new ByteArrayInputStream(xml2.getBytes())));
700 		assertTrue("2nd roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
701 				validateAgainstDtd(new ByteArrayInputStream(xml3.getBytes())));
702 
703 		// All 3 versions of the RuleSet should be the same
704 		assertEqualsRuleSet(
705 				"Original RuleSet and 1st roundtrip Ruleset not the same (filename: " + fileName + ")",
706 				ruleSet1, ruleSet2);
707 		assertEqualsRuleSet(
708 				"1st roundtrip Ruleset and 2nd roundtrip RuleSet not the same (filename: " + fileName + ")",
709 				ruleSet2, ruleSet3);
710 
711 		// It's hard to compare the XML DOMs. At least the roundtrip ones should
712 		// textually be the same.
713 		assertEquals("1st roundtrip RuleSet XML and 2nd roundtrip RuleSet XML (filename: " + fileName + ")",
714 				xml2, xml3);
715 	}
716 
717 	private void assertEqualsRuleSet(String message, RuleSet ruleSet1,
718 			RuleSet ruleSet2) {
719 		assertEquals(message + ", RuleSet name", ruleSet1.getName(), ruleSet2
720 				.getName());
721 		assertEquals(message + ", RuleSet description", ruleSet1
722 				.getDescription(), ruleSet2.getDescription());
723 		assertEquals(message + ", RuleSet exclude patterns", ruleSet1
724 				.getExcludePatterns(), ruleSet2.getExcludePatterns());
725 		assertEquals(message + ", RuleSet include patterns", ruleSet1
726 				.getIncludePatterns(), ruleSet2.getIncludePatterns());
727 		assertEquals(message + ", RuleSet rule count", ruleSet1.getRules()
728 				.size(), ruleSet2.getRules().size());
729 
730 		for (int i = 0; i < ruleSet1.getRules().size(); i++) {
731 			Rule rule1 = ((List<Rule>) ruleSet1.getRules()).get(i);
732 			Rule rule2 = ((List<Rule>) ruleSet2.getRules()).get(i);
733 
734 			assertFalse(message + ", Different RuleReference",
735 					rule1 instanceof RuleReference
736 							&& !(rule2 instanceof RuleReference)
737 							|| !(rule1 instanceof RuleReference)
738 							&& rule2 instanceof RuleReference);
739 
740 			if (rule1 instanceof RuleReference) {
741 				RuleReference ruleReference1 = (RuleReference) rule1;
742 				RuleReference ruleReference2 = (RuleReference) rule2;
743 				assertEquals(message + ", RuleReference overridden language",
744 						ruleReference1.getOverriddenLanguage(), ruleReference2
745 								.getOverriddenLanguage());
746 				assertEquals(
747 						message
748 								+ ", RuleReference overridden minimum language version",
749 						ruleReference1.getOverriddenMinimumLanguageVersion(),
750 						ruleReference2.getOverriddenMinimumLanguageVersion());
751 				assertEquals(
752 						message
753 								+ ", RuleReference overridden maximum language version",
754 						ruleReference1.getOverriddenMaximumLanguageVersion(),
755 						ruleReference2.getOverriddenMaximumLanguageVersion());
756 				assertEquals(message + ", RuleReference overridden deprecated",
757 						ruleReference1.isOverriddenDeprecated(), ruleReference2
758 								.isOverriddenDeprecated());
759 				assertEquals(message + ", RuleReference overridden name",
760 						ruleReference1.getOverriddenName(), ruleReference2
761 								.getOverriddenName());
762 				assertEquals(
763 						message + ", RuleReference overridden description",
764 						ruleReference1.getOverriddenDescription(),
765 						ruleReference2.getOverriddenDescription());
766 				assertEquals(message + ", RuleReference overridden message",
767 						ruleReference1.getOverriddenMessage(), ruleReference2
768 								.getOverriddenMessage());
769 				assertEquals(message
770 						+ ", RuleReference overridden external info url",
771 						ruleReference1.getOverriddenExternalInfoUrl(),
772 						ruleReference2.getOverriddenExternalInfoUrl());
773 				assertEquals(message + ", RuleReference overridden priority",
774 						ruleReference1.getOverriddenPriority(), ruleReference2
775 								.getOverriddenPriority());
776 				assertEquals(message + ", RuleReference overridden examples",
777 						ruleReference1.getOverriddenExamples(), ruleReference2
778 								.getOverriddenExamples());
779 			}
780 
781 			assertEquals(message + ", Rule name", rule1.getName(), rule2
782 					.getName());
783 			assertEquals(message + ", Rule class", rule1.getRuleClass(), rule2
784 					.getRuleClass());
785 			assertEquals(message + ", Rule description " + rule1.getName(),
786 					rule1.getDescription(), rule2.getDescription());
787 			assertEquals(message + ", Rule message", rule1.getMessage(), rule2
788 					.getMessage());
789 			assertEquals(message + ", Rule external info url", rule1
790 					.getExternalInfoUrl(), rule2.getExternalInfoUrl());
791 			assertEquals(message + ", Rule priority", rule1.getPriority(),
792 					rule2.getPriority());
793 			assertEquals(message + ", Rule examples", rule1.getExamples(),
794 					rule2.getExamples());
795 
796 			List<PropertyDescriptor<?>> propertyDescriptors1 = rule1
797 					.getPropertyDescriptors();
798 			List<PropertyDescriptor<?>> propertyDescriptors2 = rule2
799 					.getPropertyDescriptors();
800 			try {
801 				assertEquals(message + ", Rule property descriptor ",
802 						propertyDescriptors1, propertyDescriptors2);
803 			} catch (Error e) {
804 				throw e;
805 			}
806 			for (int j = 0; j < propertyDescriptors1.size(); j++) {
807 				assertEquals(message + ", Rule property value " + j, rule1
808 						.getProperty(propertyDescriptors1.get(j)), rule2
809 						.getProperty(propertyDescriptors2.get(j)));
810 			}
811 			assertEquals(message + ", Rule property descriptor count",
812 					propertyDescriptors1.size(), propertyDescriptors2.size());
813 		}
814 	}
815 
816 	private boolean validateAgainstSchema(String fileName) throws IOException,
817 			RuleSetNotFoundException, ParserConfigurationException,
818 			SAXException {
819 		InputStream inputStream = loadResourceAsStream(fileName);
820 		boolean valid = validateAgainstSchema(inputStream);
821 		if (!valid) {
822 			System.err.println("Validation against XML Schema failed for: "
823 					+ fileName);
824 		}
825 		return valid;
826 	}
827 
828 	private boolean validateAgainstSchema(InputStream inputStream)
829 			throws IOException, RuleSetNotFoundException,
830 			ParserConfigurationException, SAXException {
831 		
832 		saxParser.parse(inputStream, validateDefaultHandlerXsd.resetValid());
833 		inputStream.close();
834 		return validateDefaultHandlerXsd.isValid();
835 	}
836 
837 	private boolean validateAgainstDtd(String fileName) throws IOException,
838 			RuleSetNotFoundException, ParserConfigurationException,
839 			SAXException {
840 		InputStream inputStream = loadResourceAsStream(fileName);
841 		boolean valid = validateAgainstDtd(inputStream);
842 		if (!valid) {
843 			System.err
844 					.println("Validation against DTD failed for: " + fileName);
845 		}
846 		return valid;
847 	}
848 
849 	private boolean validateAgainstDtd(InputStream inputStream)
850 			throws IOException, RuleSetNotFoundException,
851 			ParserConfigurationException, SAXException {
852 		
853 		// Read file into memory
854 		String file = readFullyToString(inputStream);
855 
856 		// Remove XML Schema stuff, replace with DTD
857 		file = file.replaceAll("<\\?xml [ a-zA-Z0-9=\".-]*\\?>", "");
858 		file = file.replaceAll(
859 				"xmlns=\"" + RuleSetWriter.RULESET_NS_URI + "\"", "");
860 		file = file.replaceAll(
861 				"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
862 		file = file
863 				.replaceAll(
864 						"xsi:schemaLocation=\"" + RuleSetWriter.RULESET_NS_URI + " http://pmd.sourceforge.net/ruleset_2_0_0.xsd\"",
865 						"");
866 
867 		file = "<?xml version=\"1.0\"?>" + PMD.EOL
868 				+ "<!DOCTYPE ruleset SYSTEM \"file://"
869 				+ System.getProperty("user.dir") + "/src/main/resources/ruleset_2_0_0.dtd\">"
870 				+ PMD.EOL + file;
871 
872 		inputStream = new ByteArrayInputStream(file.getBytes());
873 
874 		saxParser.parse(inputStream, validateDefaultHandlerDtd.resetValid());
875 		inputStream.close();
876 		return validateDefaultHandlerDtd.isValid();
877 	}
878 
879 	private String readFullyToString(InputStream inputStream)
880 			throws IOException {
881 		StringBuilder buf = new StringBuilder(64 * 1024);
882 		BufferedReader reader = new BufferedReader(new InputStreamReader(
883 				inputStream));
884 		String line;
885 		while ((line = reader.readLine()) != null) {
886 			buf.append(line);
887 			buf.append(PMD.EOL);
888 		}
889 		reader.close();
890 		return buf.toString();
891 	}
892 
893 	// Gets all test PMD Ruleset XML files
894 private List<String> getRuleSetFileNames() throws IOException,
895 RuleSetNotFoundException {
896 List<String> result = new ArrayList<String>();
897 
898 for (Language language : Language.values()) {
899 result.addAll(getRuleSetFileNames(language.getTerseName()));
900 }
901 
902 return result;
903 }
904 
905 private List<String> getRuleSetFileNames(String language) throws IOException, RuleSetNotFoundException {
906 List<String> ruleSetFileNames = new ArrayList<String>();
907 try {
908 Properties properties = new Properties();
909 properties.load(ResourceLoader.loadResourceAsStream("rulesets/" + language + "/rulesets.properties"));
910 String fileNames = properties.getProperty("rulesets.filenames");
911 StringTokenizer st = new StringTokenizer(fileNames, ",");
912 while (st.hasMoreTokens()) {
913 ruleSetFileNames.add(st.nextToken());
914 }
915 } catch (RuleSetNotFoundException e) {
916 // this might happen if a language is only support by CPD, but not by PMD
917 System.err.println("No ruleset found for language " + language);
918 }
919 return ruleSetFileNames;
920 }
921 
922 	private static class ValidateDefaultHandler extends DefaultHandler {
923 		private final String validateDocument;
924 		private boolean valid = true;
925 
926 		public ValidateDefaultHandler(String validateDocument) {
927 			this.validateDocument = validateDocument;
928 		}
929 		
930 		public ValidateDefaultHandler resetValid() {
931 			valid = true;
932 			return this;
933 		}
934 
935 		public boolean isValid() {
936 			return valid;
937 		}
938 
939 		@Override
940 		public void error(SAXParseException e) throws SAXException {
941 			log("Error", e);
942 		}
943 
944 		@Override
945 		public void fatalError(SAXParseException e) throws SAXException {
946 			log("FatalError", e);
947 		}
948 
949 		@Override
950 		public void warning(SAXParseException e) throws SAXException {
951 			log("Warning", e);
952 		}
953 
954 		private void log(String prefix, SAXParseException e) {
955 			String message = prefix + " at (" + e.getLineNumber() + ", " + e.getColumnNumber() + "): " + e.getMessage();
956 			System.err.println(message);
957 			valid = false;
958 		}
959 
960 		@Override
961 		public InputSource resolveEntity(String publicId, String systemId)
962 				throws IOException, SAXException {
963 			if ("http://pmd.sourceforge.net/ruleset_2_0_0.xsd".equals(systemId)
964 					|| systemId.endsWith("ruleset_2_0_0.dtd")) {
965 				try {
966 					InputStream inputStream = loadResourceAsStream(validateDocument);
967 					return new InputSource(inputStream);
968 				} catch (RuleSetNotFoundException e) {
969 					System.err.println(e.getMessage());
970 					throw new IOException(e.getMessage());
971 				}
972 			}
973 			throw new IllegalArgumentException(
974 					"No clue how to handle: publicId=" + publicId
975 							+ ", systemId=" + systemId);
976 		}
977 	}
978 
979 	private static InputStream loadResourceAsStream(String resource)
980 			throws RuleSetNotFoundException {
981 		InputStream inputStream = ResourceLoader.loadResourceAsStream(resource,
982 				RuleSetFactoryTest.class.getClassLoader());
983 		if (inputStream == null) {
984 			throw new RuleSetNotFoundException(
985 					"Can't find resource "
986 							+ resource
987 							+ " Make sure the resource is a valid file or URL or is on the CLASSPATH. Here's the current classpath: "
988 							+ System.getProperty("java.class.path"));
989 		}
990 		return inputStream;
991 	}
992 
993 	private static final String REF_OVERRIDE_ORIGINAL_NAME = "<?xml version=\"1.0\"?>"
994 			+ PMD.EOL
995 			+ "<ruleset name=\"test\">"
996 			+ PMD.EOL
997 			+ " <description>testdesc</description>"
998 			+ PMD.EOL
999 			+ " <rule "
1000 			+ PMD.EOL
1001 			+ " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"> "
1002 			+ PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
1003 
1004 	private static final String REF_MISPELLED_XREF = "<?xml version=\"1.0\"?>"
1005 			+ PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1006 			+ " <description>testdesc</description>" + PMD.EOL + " <rule "
1007 			+ PMD.EOL
1008 			+ " ref=\"rulesets/java/unusedcode.xml/FooUnusedLocalVariable\"> "
1009 			+ PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
1010 
1011 	private static final String REF_OVERRIDE_ORIGINAL_NAME_ONE_ELEM = "<?xml version=\"1.0\"?>"
1012 			+ PMD.EOL
1013 			+ "<ruleset name=\"test\">"
1014 			+ PMD.EOL
1015 			+ " <description>testdesc</description>"
1016 			+ PMD.EOL
1017 			+ " <rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"/> "
1018 			+ PMD.EOL + "</ruleset>";
1019 
1020 	private static final String REF_OVERRIDE = "<?xml version=\"1.0\"?>"
1021 			+ PMD.EOL
1022 			+ "<ruleset name=\"test\">"
1023 			+ PMD.EOL
1024 			+ " <description>testdesc</description>"
1025 			+ PMD.EOL
1026 			+ " <rule "
1027 			+ PMD.EOL
1028 			+ " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" "
1029 			+ PMD.EOL
1030 			+ " name=\"TestNameOverride\" "
1031 			+ PMD.EOL
1032 			+ " message=\"Test message override\"> "
1033 			+ PMD.EOL
1034 			+ " <description>Test description override</description>"
1035 			+ PMD.EOL
1036 			+ " <example>Test example override</example>"
1037 			+ PMD.EOL
1038 			+ " <priority>3</priority>"
1039 			+ PMD.EOL
1040 			+ " <properties>"
1041 			+ PMD.EOL
1042 			+ " <property name=\"test2\" description=\"test2\" type=\"String\" value=\"override2\"/>"
1043 			+ PMD.EOL
1044 			+ " <property name=\"test3\" description=\"test3\" type=\"String\"><value>override3</value></property>"
1045 			+ PMD.EOL
1046 			+ " <property name=\"test4\" description=\"test4\" type=\"String\" value=\"new property\"/>"
1047 			+ PMD.EOL + " </properties>" + PMD.EOL + " </rule>" + PMD.EOL
1048 			+ "</ruleset>";
1049 
1050 	private static final String REF_INTERNAL_TO_INTERNAL = "<?xml version=\"1.0\"?>"
1051 			+ PMD.EOL
1052 			+ "<ruleset name=\"test\">"
1053 			+ PMD.EOL
1054 			+ " <description>testdesc</description>"
1055 			+ PMD.EOL
1056 			+ "<rule "
1057 			+ PMD.EOL
1058 			+ "name=\"MockRuleName\" "
1059 			+ PMD.EOL
1060 			+ "message=\"avoid the mock rule\" "
1061 			+ PMD.EOL
1062 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1063 			+ PMD.EOL
1064 			+ "</rule>"
1065 			+ " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"/> "
1066 			+ PMD.EOL + "</ruleset>";
1067 
1068 	private static final String REF_INTERNAL_TO_INTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
1069 			+ PMD.EOL
1070 			+ "<ruleset name=\"test\">"
1071 			+ PMD.EOL
1072 			+ " <description>testdesc</description>"
1073 			+ PMD.EOL
1074 			+ "<rule "
1075 			+ PMD.EOL
1076 			+ "name=\"MockRuleName\" "
1077 			+ PMD.EOL
1078 			+ "message=\"avoid the mock rule\" "
1079 			+ PMD.EOL
1080 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1081 			+ PMD.EOL
1082 			+ "</rule>"
1083 			+ " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"><priority>2</priority></rule> "
1084 			+ PMD.EOL
1085 			+ " <rule ref=\"MockRuleNameRef\" name=\"MockRuleNameRefRef\"><priority>1</priority></rule> "
1086 			+ PMD.EOL + "</ruleset>";
1087 
1088 	private static final String REF_INTERNAL_TO_EXTERNAL = "<?xml version=\"1.0\"?>"
1089 			+ PMD.EOL
1090 			+ "<ruleset name=\"test\">"
1091 			+ PMD.EOL
1092 			+ " <description>testdesc</description>"
1093 			+ PMD.EOL
1094 			+ "<rule "
1095 			+ PMD.EOL
1096 			+ "name=\"ExternalRefRuleName\" "
1097 			+ PMD.EOL
1098 			+ "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1099 			+ PMD.EOL
1100 			+ " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"/> "
1101 			+ PMD.EOL + "</ruleset>";
1102 
1103 	private static final String REF_INTERNAL_TO_EXTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
1104 			+ PMD.EOL
1105 			+ "<ruleset name=\"test\">"
1106 			+ PMD.EOL
1107 			+ " <description>testdesc</description>"
1108 			+ PMD.EOL
1109 			+ "<rule "
1110 			+ PMD.EOL
1111 			+ "name=\"ExternalRefRuleName\" "
1112 			+ PMD.EOL
1113 			+ "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1114 			+ PMD.EOL
1115 			+ " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"><priority>2</priority></rule> "
1116 			+ PMD.EOL
1117 			+ " <rule ref=\"ExternalRefRuleNameRef\" name=\"ExternalRefRuleNameRefRef\"><priority>1</priority></rule> "
1118 			+ PMD.EOL + "</ruleset>";
1119 
1120 	private static final String EMPTY_RULESET = "<?xml version=\"1.0\"?>"
1121 			+ PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1122 			+ "<description>testdesc</description>" + PMD.EOL + "</ruleset>";
1123 
1124 	private static final String SINGLE_RULE = "<?xml version=\"1.0\"?>"
1125 			+ PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1126 			+ "<description>testdesc</description>" + PMD.EOL + "<rule "
1127 			+ PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1128 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1129 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1130 			+ "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1131 
1132 	private static final String MULTIPLE_RULES = "<?xml version=\"1.0\"?>"
1133 			+ PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1134 			+ "<description>testdesc</description>" + PMD.EOL
1135 			+ "<rule name=\"MockRuleName1\" " + PMD.EOL
1136 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1137 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1138 			+ "</rule>" + PMD.EOL + "<rule name=\"MockRuleName2\" " + PMD.EOL
1139 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1140 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1141 			+ "</rule></ruleset>";
1142 
1143 	private static final String PROPERTIES = "<?xml version=\"1.0\"?>"
1144 			+ PMD.EOL
1145 			+ "<ruleset name=\"test\">"
1146 			+ PMD.EOL
1147 			+ "<description>testdesc</description>"
1148 			+ PMD.EOL
1149 			+ "<rule name=\"MockRuleName\" "
1150 			+ PMD.EOL
1151 			+ "message=\"avoid the mock rule\" "
1152 			+ PMD.EOL
1153 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1154 			+ PMD.EOL
1155 			+ "<description>testdesc2</description>"
1156 			+ PMD.EOL
1157 			+ "<properties>"
1158 			+ PMD.EOL
1159 			+ "<property name=\"fooBoolean\" description=\"test\" type=\"Boolean\" value=\"true\" />"
1160 			+ PMD.EOL
1161 			+ "<property name=\"fooChar\" description=\"test\" type=\"Character\" value=\"B\" />"
1162 			+ PMD.EOL
1163 			+ "<property name=\"fooInt\" description=\"test\" type=\"Integer\" min=\"1\" max=\"10\" value=\"3\" />"
1164 			+ PMD.EOL
1165 			+ "<property name=\"fooFloat\" description=\"test\" type=\"Float\" min=\"1.0\" max=\"1.0\" value=\"1.0\" />"
1166 			+ PMD.EOL
1167 			+ "<property name=\"fooDouble\" description=\"test\" type=\"Double\" min=\"1.0\" max=\"9.0\" value=\"3.0\" />"
1168 			+ PMD.EOL
1169 			+ "<property name=\"fooString\" description=\"test\" type=\"String\" value=\"bar\" />"
1170 			+ PMD.EOL + "</properties>" + PMD.EOL + "</rule></ruleset>";
1171 
1172 	private static final String XPATH = "<?xml version=\"1.0\"?>" + PMD.EOL
1173 			+ "<ruleset name=\"test\">" + PMD.EOL
1174 			+ "<description>testdesc</description>" + PMD.EOL
1175 			+ "<rule name=\"MockRuleName\" " + PMD.EOL
1176 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1177 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1178 			+ "<priority>3</priority>" + PMD.EOL + PMD.EOL
1179 			+ "<description>testdesc2</description>" + PMD.EOL + "<properties>"
1180 			+ PMD.EOL
1181 			+ "<property name=\"xpath\" description=\"test\" type=\"String\">"
1182 			+ PMD.EOL + "<value>" + PMD.EOL + "<![CDATA[ //Block ]]>" + PMD.EOL
1183 			+ "</value>" + PMD.EOL + "</property>" + PMD.EOL + "</properties>"
1184 			+ PMD.EOL + "</rule></ruleset>";
1185 
1186 	private static final String PRIORITY = "<?xml version=\"1.0\"?>" + PMD.EOL
1187 			+ "<ruleset name=\"test\">" + PMD.EOL
1188 			+ "<description>testdesc</description>" + PMD.EOL + "<rule "
1189 			+ PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1190 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1191 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1192 			+ "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1193 
1194 	private static final String LANGUAGE = "<?xml version=\"1.0\"?>"
1195 			+ PMD.EOL
1196 			+ "<ruleset name=\"test\">"
1197 			+ PMD.EOL
1198 			+ "<description>testdesc</description>"
1199 			+ PMD.EOL
1200 			+ "<rule "
1201 			+ PMD.EOL
1202 			+ "name=\"MockRuleName\" "
1203 			+ PMD.EOL
1204 			+ "message=\"avoid the mock rule\" "
1205 			+ PMD.EOL
1206 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\" language=\"java\">"
1207 			+ PMD.EOL + "</rule></ruleset>";
1208 
1209 	private static final String INCORRECT_LANGUAGE = "<?xml version=\"1.0\"?>"
1210 			+ PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1211 			+ "<description>testdesc</description>" + PMD.EOL + "<rule "
1212 			+ PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1213 			+ "message=\"avoid the mock rule\" " + PMD.EOL
1214 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\"" + PMD.EOL
1215 			+ " language=\"bogus\">" + PMD.EOL + "</rule></ruleset>";
1216 
1217 	private static final String MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1218 			+ PMD.EOL
1219 			+ "<ruleset name=\"test\">"
1220 			+ PMD.EOL
1221 			+ "<description>testdesc</description>"
1222 			+ PMD.EOL
1223 			+ "<rule "
1224 			+ PMD.EOL
1225 			+ "name=\"MockRuleName\" "
1226 			+ PMD.EOL
1227 			+ "message=\"avoid the mock rule\" "
1228 			+ PMD.EOL
1229 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1230 			+ PMD.EOL
1231 			+ " language=\"java\""
1232 			+ PMD.EOL
1233 			+ " minimumLanguageVersion=\"1.4\">"
1234 			+ PMD.EOL
1235 			+ "</rule></ruleset>";
1236 
1237 	private static final String INCORRECT_MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1238 			+ PMD.EOL
1239 			+ "<ruleset name=\"test\">"
1240 			+ PMD.EOL
1241 			+ "<description>testdesc</description>"
1242 			+ PMD.EOL
1243 			+ "<rule "
1244 			+ PMD.EOL
1245 			+ "name=\"MockRuleName\" "
1246 			+ PMD.EOL
1247 			+ "message=\"avoid the mock rule\" "
1248 			+ PMD.EOL
1249 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1250 			+ PMD.EOL
1251 			+ " language=\"java\""
1252 			+ PMD.EOL
1253 			+ " minimumLanguageVersion=\"bogus\">"
1254 			+ PMD.EOL
1255 			+ "</rule></ruleset>";
1256 
1257 	private static final String MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1258 			+ PMD.EOL
1259 			+ "<ruleset name=\"test\">"
1260 			+ PMD.EOL
1261 			+ "<description>testdesc</description>"
1262 			+ PMD.EOL
1263 			+ "<rule "
1264 			+ PMD.EOL
1265 			+ "name=\"MockRuleName\" "
1266 			+ PMD.EOL
1267 			+ "message=\"avoid the mock rule\" "
1268 			+ PMD.EOL
1269 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1270 			+ PMD.EOL
1271 			+ " language=\"java\""
1272 			+ PMD.EOL
1273 			+ " maximumLanguageVersion=\"1.7\">"
1274 			+ PMD.EOL
1275 			+ "</rule></ruleset>";
1276 
1277 	private static final String INCORRECT_MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1278 			+ PMD.EOL
1279 			+ "<ruleset name=\"test\">"
1280 			+ PMD.EOL
1281 			+ "<description>testdesc</description>"
1282 			+ PMD.EOL
1283 			+ "<rule "
1284 			+ PMD.EOL
1285 			+ "name=\"MockRuleName\" "
1286 			+ PMD.EOL
1287 			+ "message=\"avoid the mock rule\" "
1288 			+ PMD.EOL
1289 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1290 			+ PMD.EOL
1291 			+ " language=\"java\""
1292 			+ PMD.EOL
1293 			+ " maximumLanguageVersion=\"bogus\">"
1294 			+ PMD.EOL
1295 			+ "</rule></ruleset>";
1296 
1297 	private static final String INVERTED_MINIMUM_MAXIMUM_LANGUAGE_VERSIONS = "<?xml version=\"1.0\"?>"
1298 			+ PMD.EOL
1299 			+ "<ruleset name=\"test\">"
1300 			+ PMD.EOL
1301 			+ "<description>testdesc</description>"
1302 			+ PMD.EOL
1303 			+ "<rule "
1304 			+ PMD.EOL
1305 			+ "name=\"MockRuleName\" "
1306 			+ PMD.EOL
1307 			+ "message=\"avoid the mock rule\" "
1308 			+ PMD.EOL
1309 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\" "
1310 			+ PMD.EOL
1311 			+ "language=\"java\""
1312 			+ PMD.EOL
1313 			+ " minimumLanguageVersion=\"1.7\""
1314 			+ PMD.EOL
1315 			+ "maximumLanguageVersion=\"1.4\">"
1316 			+ PMD.EOL
1317 			+ "</rule></ruleset>";
1318 
1319 	private static final String DIRECT_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1320 			+ PMD.EOL
1321 			+ "<ruleset name=\"test\">"
1322 			+ PMD.EOL
1323 			+ "<description>testdesc</description>"
1324 			+ PMD.EOL
1325 			+ "<rule "
1326 			+ PMD.EOL
1327 			+ "name=\"MockRuleName\" "
1328 			+ PMD.EOL
1329 			+ "message=\"avoid the mock rule\" "
1330 			+ PMD.EOL
1331 			+ "class=\"net.sourceforge.pmd.lang.rule.MockRule\" deprecated=\"true\">"
1332 			+ PMD.EOL + "</rule></ruleset>";
1333 
1334 	// Note: Update this RuleSet name to a different RuleSet with deprecated
1335 	// Rules when the Rules are finally removed.
1336 	private static final String DEPRECATED_RULE_RULESET_NAME = "rulesets/java/basic.xml";
1337 
1338 	// Note: Update this Rule name to a different deprecated Rule when the one
1339 	// listed here is finally removed.
1340 	private static final String DEPRECATED_RULE_NAME = "EmptyCatchBlock";
1341 
1342 	private static final String REFERENCE_TO_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1343 			+ PMD.EOL
1344 			+ "<ruleset name=\"test\">"
1345 			+ PMD.EOL
1346 			+ "<description>testdesc</description>"
1347 			+ PMD.EOL
1348 			+ "<rule "
1349 			+ PMD.EOL
1350 			+ "ref=\""
1351 			+ DEPRECATED_RULE_RULESET_NAME
1352 			+ "/"
1353 			+ DEPRECATED_RULE_NAME + "\">" + PMD.EOL + "</rule></ruleset>";
1354 
1355 	private static final String REFERENCE_TO_RULESET_WITH_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1356 			+ PMD.EOL
1357 			+ "<ruleset name=\"test\">"
1358 			+ PMD.EOL
1359 			+ "<description>testdesc</description>"
1360 			+ PMD.EOL
1361 			+ "<rule "
1362 			+ PMD.EOL
1363 			+ "ref=\""
1364 			+ DEPRECATED_RULE_RULESET_NAME
1365 			+ "\">"
1366 			+ PMD.EOL + "</rule></ruleset>";
1367 
1368 	private static final String DFA = "<?xml version=\"1.0\"?>" + PMD.EOL
1369 			+ "<ruleset name=\"test\">" + PMD.EOL
1370 			+ "<description>testdesc</description>" + PMD.EOL + "<rule "
1371 			+ PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1372 			+ "message=\"avoid the mock rule\" " + PMD.EOL + "dfa=\"true\" "
1373 			+ PMD.EOL + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1374 			+ "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1375 
1376 	private static final String INCLUDE_EXCLUDE_RULESET = "<?xml version=\"1.0\"?>"
1377 			+ PMD.EOL
1378 			+ "<ruleset name=\"test\">"
1379 			+ PMD.EOL
1380 			+ "<description>testdesc</description>"
1381 			+ PMD.EOL
1382 			+ "<include-pattern>include1</include-pattern>"
1383 			+ PMD.EOL
1384 			+ "<include-pattern>include2</include-pattern>"
1385 			+ PMD.EOL
1386 			+ "<exclude-pattern>exclude1</exclude-pattern>"
1387 			+ PMD.EOL
1388 			+ "<exclude-pattern>exclude2</exclude-pattern>"
1389 			+ PMD.EOL
1390 			+ "<exclude-pattern>exclude3</exclude-pattern>"
1391 			+ PMD.EOL
1392 			+ "</ruleset>";
1393 
1394 	private static final String EXTERNAL_REFERENCE_RULE_SET = "<?xml version=\"1.0\"?>"
1395 			+ PMD.EOL
1396 			+ "<ruleset name=\"test\">"
1397 			+ PMD.EOL
1398 			+ "<description>testdesc</description>"
1399 			+ PMD.EOL
1400 			+ "<rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1401 			+ PMD.EOL + "</ruleset>";
1402 
1403 	private Rule loadFirstRule(String ruleSetXml)
1404 			throws RuleSetNotFoundException {
1405 		RuleSet rs = loadRuleSet(ruleSetXml);
1406 		return rs.getRules().iterator().next();
1407 	}
1408 
1409 	private RuleSet loadRuleSetByFileName(String ruleSetFileName)
1410 			throws RuleSetNotFoundException {
1411 		RuleSetFactory rsf = new RuleSetFactory();
1412 		return rsf.createRuleSet(ruleSetFileName);
1413 	}
1414 
1415 	private RuleSet loadRuleSet(String ruleSetXml)
1416 			throws RuleSetNotFoundException {
1417 		RuleSetFactory rsf = new RuleSetFactory();
1418 		return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml));
1419 	}
1420 
1421 	private static RuleSetReferenceId createRuleSetReferenceId(
1422 			final String ruleSetXml) {
1423 		return new RuleSetReferenceId(null) {
1424 			@Override
1425 			public InputStream getInputStream(ClassLoader classLoader)
1426 					throws RuleSetNotFoundException {
1427 				return new ByteArrayInputStream(ruleSetXml.getBytes());
1428 			}
1429 		};
1430 	}
1431 
1432 	public static junit.framework.Test suite() {
1433 		return new JUnit4TestAdapter(RuleSetFactoryTest.class);
1434 	}
1435 
1436 }

AltStyle によって変換されたページ (->オリジナル) /