1
2
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.io.UnsupportedEncodingException;
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Properties;
25 import java.util.Set;
26 import java.util.StringTokenizer;
27
28 import javax.xml.parsers.ParserConfigurationException;
29 import javax.xml.parsers.SAXParser;
30 import javax.xml.parsers.SAXParserFactory;
31
32 import net.sourceforge.pmd.lang.Language;
33 import net.sourceforge.pmd.lang.LanguageVersion;
34 import net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedLocalVariableRule;
35 import net.sourceforge.pmd.lang.rule.RuleReference;
36 import net.sourceforge.pmd.lang.rule.XPathRule;
37 import net.sourceforge.pmd.util.ResourceLoader;
38
39 import org.junit.Assert;
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
60
61
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
118 assertNotNull(rs.getRuleByName("JumbledIncrementer"));
119 assertNotNull(rs.getRuleByName("ForLoopShouldBeWhileLoop"));
120 assertNotNull(rs.getRuleByName("OverrideBothEqualsAndHashcode"));
121
122
123 assertNotNull(rs.getRuleByName("UnusedLocalVariable"));
124 assertNotNull(rs.getRuleByName("DuplicateImports"));
125
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
134
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
144 assertNotNull(rs.getRuleByName("IfStmtsMustUseBraces"));
145
146 assertNull(rs.getRuleByName("WhileLoopsMustUseBraces"));
147
148
149 Rule simplifyBooleanExpressions = rs.getRuleByName("SimplifyBooleanExpressions");
150 assertNotNull(simplifyBooleanExpressions);
151 assertEquals(5, simplifyBooleanExpressions.getPriority().getPriority());
152 assertEquals(1, countRule(rs, "SimplifyBooleanExpressions"));
153
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
460
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
500
501
502
503 @Test(expected = RuntimeException.class)
504 public void testBug1202() throws Exception {
505 RuleSetReferenceId ref = createRuleSetReferenceId("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
506 "<ruleset>\n" +
507 " <rule ref=\"net.sourceforge.pmd.rules.XPathRule\">\n" +
508 " <priority>1</priority>\n" +
509 " <properties>\n" +
510 " <property name=\"xpath\" value=\"//TypeDeclaration\" />\n" +
511 " <property name=\"message\" value=\"Foo\" />\n" +
512 " </properties>\n" +
513 " </rule>\n" +
514 "</ruleset>\n");
515 RuleSetFactory ruleSetFactory = new RuleSetFactory();
516 ruleSetFactory.createRuleSet(ref);
517 }
518
519
520
521
522
523 @Test
524 public void testEmptyRuleSetFile() throws Exception {
525 RuleSetReferenceId ref = createRuleSetReferenceId("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
526 "\n" +
527 "<ruleset name=\"Custom ruleset\" xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n" +
528 " xmlns:xsi=\"http:www.w3.org/2001/XMLSchema-instance\"\n" +
529 " xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd\">\n" +
530 " <description>PMD Ruleset.</description>\n" +
531 "\n" +
532 " <exclude-pattern>.*Test.*</exclude-pattern>\n" +
533 "\n" +
534 "</ruleset>\n");
535 RuleSetFactory ruleSetFactory = new RuleSetFactory();
536 RuleSet ruleset = ruleSetFactory.createRuleSet(ref);
537 assertEquals(0, ruleset.getRules().size());
538 }
539
540
541
542
543
544 @Test(expected = IllegalArgumentException.class)
545 public void testWrongRuleNameReferenced() throws Exception {
546 RuleSetReferenceId ref = createRuleSetReferenceId("<?xml version=\"1.0\"?>\n" +
547 "<ruleset name=\"Custom ruleset for tests\"\n" +
548 " xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n" +
549 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
550 " xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd\">\n" +
551 " <description>Custom ruleset for tests</description>\n" +
552 " <rule ref=\"rulesets/java/basic.xml/ThisRuleDoesNotExist\"/>\n" +
553 "</ruleset>\n");
554 RuleSetFactory ruleSetFactory = new RuleSetFactory();
555 ruleSetFactory.createRuleSet(ref);
556 }
557
558
559
560
561
562 @Test(expected = IllegalArgumentException.class)
563 public void testWrongRuleNameExcluded() throws Exception {
564 RuleSetReferenceId ref = createRuleSetReferenceId("<?xml version=\"1.0\"?>\n" +
565 "<ruleset name=\"Custom ruleset for tests\"\n" +
566 " xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n" +
567 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
568 " xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd\">\n" +
569 " <description>Custom ruleset for tests</description>\n" +
570 " <rule ref=\"rulesets/java/basic.xml\">\n" +
571 " <exclude name=\"ThisRuleDoesNotExist\"/>\n" +
572 " </rule>\n" +
573 "</ruleset>\n");
574 RuleSetFactory ruleSetFactory = new RuleSetFactory();
575 ruleSetFactory.createRuleSet(ref);
576 }
577
578 @Test
579 public void testAllPMDBuiltInRulesMeetConventions() throws IOException,
580 RuleSetNotFoundException, ParserConfigurationException,
581 SAXException {
582 int invalidSinceAttributes = 0;
583 int invalidExternalInfoURL = 0;
584 int invalidClassName = 0;
585 int invalidRegexSuppress = 0;
586 int invalidXPathSuppress = 0;
587 String messages = "";
588 List<String> ruleSetFileNames = getRuleSetFileNames();
589 for (String fileName : ruleSetFileNames) {
590 RuleSet ruleSet = loadRuleSetByFileName(fileName);
591 for (Rule rule : ruleSet.getRules()) {
592
593
594 if (rule instanceof RuleReference) {
595 continue;
596 }
597
598 Language language = rule.getLanguage();
599 String group = fileName
600 .substring(fileName.lastIndexOf('/') + 1);
601 group = group.substring(0, group.indexOf(".xml"));
602 if (group.indexOf('-') >= 0) {
603 group = group.substring(0, group.indexOf('-'));
604 }
605
606
607 if (rule.getSince() == null) {
608 invalidSinceAttributes++;
609 messages += "Rule " + fileName + "/" + rule.getName()
610 + " is missing 'since' attribute" + PMD.EOL;
611 }
612
613 if (rule.getExternalInfoUrl() == null
614 || "".equalsIgnoreCase(rule.getExternalInfoUrl())) {
615 invalidExternalInfoURL++;
616 messages += "Rule " + fileName + "/" + rule.getName()
617 + " is missing 'externalInfoURL' attribute"
618 + PMD.EOL;
619 } else {
620 String expectedExternalInfoURL = "http://pmd.sourceforge.net/.+/rules/"
621 + fileName.replaceAll("rulesets/", "").replaceAll(
622 ".xml", "") + ".html#" + rule.getName();
623 if (rule.getExternalInfoUrl() == null
624 || !rule.getExternalInfoUrl().matches(expectedExternalInfoURL)) {
625 invalidExternalInfoURL++;
626 messages += "Rule "
627 + fileName
628 + "/"
629 + rule.getName()
630 + " seems to have an invalid 'externalInfoURL' value ("
631 + rule.getExternalInfoUrl()
632 + "), it should be:" + expectedExternalInfoURL
633 + PMD.EOL;
634 }
635 }
636
637 String expectedClassName = "net.sourceforge.pmd.lang."
638 + language.getTerseName() + ".rule." + group + "."
639 + rule.getName() + "Rule";
640 if (!rule.getRuleClass().equals(expectedClassName)
641 && !rule.getRuleClass().equals(
642 XPathRule.class.getName())) {
643 invalidClassName++;
644 messages += "Rule " + fileName + "/" + rule.getName()
645 + " seems to have an invalid 'class' value ("
646 + rule.getRuleClass() + "), it should be:"
647 + expectedClassName + PMD.EOL;
648 }
649
650 if (rule.getProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR) != null) {
651 invalidRegexSuppress++;
652 messages += "Rule "
653 + fileName
654 + "/"
655 + rule.getName()
656 + " should not have '"
657 + Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
658 + "', this is intended for end user customization only."
659 + PMD.EOL;
660 }
661
662 if (rule.getProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR) != null) {
663 invalidXPathSuppress++;
664 messages += "Rule "
665 + fileName
666 + "/"
667 + rule.getName()
668 + " should not have '"
669 + Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
670 + "', this is intended for end user customization only."
671 + PMD.EOL;
672 }
673 }
674 }
675
676
677 if (invalidSinceAttributes > 0 || invalidExternalInfoURL > 0
678 || invalidClassName > 0 || invalidRegexSuppress > 0
679 || invalidXPathSuppress > 0) {
680 fail("All built-in PMD rules need 'since' attribute ("
681 + invalidSinceAttributes
682 + " are missing), a proper ExternalURLInfo ("
683 + invalidExternalInfoURL
684 + " are invalid), a class name meeting conventions ("
685 + invalidClassName + " are invalid), no '"
686 + Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
687 + "' property (" + invalidRegexSuppress
688 + " are invalid), and no '"
689 + Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
690 + "' property (" + invalidXPathSuppress + " are invalid)"
691 + PMD.EOL + messages);
692 }
693 }
694
695 @Test
696 public void testXmlSchema() throws IOException, RuleSetNotFoundException,
697 ParserConfigurationException, SAXException {
698 boolean allValid = true;
699 List<String> ruleSetFileNames = getRuleSetFileNames();
700 for (String fileName : ruleSetFileNames) {
701 boolean valid = validateAgainstSchema(fileName);
702 allValid = allValid && valid;
703 }
704 assertTrue("All XML must parse without producing validation messages.",
705 allValid);
706 }
707
708 @Test
709 public void testDtd() throws IOException, RuleSetNotFoundException,
710 ParserConfigurationException, SAXException {
711 boolean allValid = true;
712 List<String> ruleSetFileNames = getRuleSetFileNames();
713 for (String fileName : ruleSetFileNames) {
714 boolean valid = validateAgainstDtd(fileName);
715 allValid = allValid && valid;
716 }
717 assertTrue("All XML must parse without producing validation messages.",
718 allValid);
719 }
720
721 @Test
722 public void testReadWriteRoundTrip() throws IOException,
723 RuleSetNotFoundException, ParserConfigurationException,
724 SAXException {
725
726 List<String> ruleSetFileNames = getRuleSetFileNames();
727 for (String fileName : ruleSetFileNames) {
728 testRuleSet(fileName);
729 }
730 }
731
732 private void testRuleSet(String fileName) throws IOException,
733 RuleSetNotFoundException, ParserConfigurationException,
734 SAXException {
735
736
737
738
739
740
741 RuleSet ruleSet1 = loadRuleSetByFileName(fileName);
742
743
744 ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();
745 RuleSetWriter writer1 = new RuleSetWriter(outputStream1);
746 writer1.write(ruleSet1);
747 writer1.close();
748 String xml2 = new String(outputStream1.toByteArray());
749
750
751
752 RuleSetFactory ruleSetFactory = new RuleSetFactory();
753 RuleSet ruleSet2 = ruleSetFactory
754 .createRuleSet(createRuleSetReferenceId(xml2));
755
756
757
758
759 ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
760 RuleSetWriter writer2 = new RuleSetWriter(outputStream2);
761 writer2.write(ruleSet2);
762 writer2.close();
763 String xml3 = new String(outputStream2.toByteArray());
764
765
766
767 RuleSet ruleSet3 = ruleSetFactory
768 .createRuleSet(createRuleSetReferenceId(xml3));
769
770
771 assertTrue(
772 "1st roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
773 validateAgainstSchema(new ByteArrayInputStream(xml2.getBytes())));
774 assertTrue(
775 "2nd roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
776 validateAgainstSchema(new ByteArrayInputStream(xml3.getBytes())));
777 assertTrue("1st roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
778 validateAgainstDtd(new ByteArrayInputStream(xml2.getBytes())));
779 assertTrue("2nd roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
780 validateAgainstDtd(new ByteArrayInputStream(xml3.getBytes())));
781
782
783 assertEqualsRuleSet(
784 "Original RuleSet and 1st roundtrip Ruleset not the same (filename: " + fileName + ")",
785 ruleSet1, ruleSet2);
786 assertEqualsRuleSet(
787 "1st roundtrip Ruleset and 2nd roundtrip RuleSet not the same (filename: " + fileName + ")",
788 ruleSet2, ruleSet3);
789
790
791
792 assertEquals("1st roundtrip RuleSet XML and 2nd roundtrip RuleSet XML (filename: " + fileName + ")",
793 xml2, xml3);
794 }
795
796 private void assertEqualsRuleSet(String message, RuleSet ruleSet1,
797 RuleSet ruleSet2) {
798 assertEquals(message + ", RuleSet name", ruleSet1.getName(), ruleSet2
799 .getName());
800 assertEquals(message + ", RuleSet description", ruleSet1
801 .getDescription(), ruleSet2.getDescription());
802 assertEquals(message + ", RuleSet exclude patterns", ruleSet1
803 .getExcludePatterns(), ruleSet2.getExcludePatterns());
804 assertEquals(message + ", RuleSet include patterns", ruleSet1
805 .getIncludePatterns(), ruleSet2.getIncludePatterns());
806 assertEquals(message + ", RuleSet rule count", ruleSet1.getRules()
807 .size(), ruleSet2.getRules().size());
808
809 for (int i = 0; i < ruleSet1.getRules().size(); i++) {
810 Rule rule1 = ((List<Rule>) ruleSet1.getRules()).get(i);
811 Rule rule2 = ((List<Rule>) ruleSet2.getRules()).get(i);
812
813 assertFalse(message + ", Different RuleReference",
814 rule1 instanceof RuleReference
815 && !(rule2 instanceof RuleReference)
816 || !(rule1 instanceof RuleReference)
817 && rule2 instanceof RuleReference);
818
819 if (rule1 instanceof RuleReference) {
820 RuleReference ruleReference1 = (RuleReference) rule1;
821 RuleReference ruleReference2 = (RuleReference) rule2;
822 assertEquals(message + ", RuleReference overridden language",
823 ruleReference1.getOverriddenLanguage(), ruleReference2
824 .getOverriddenLanguage());
825 assertEquals(
826 message
827 + ", RuleReference overridden minimum language version",
828 ruleReference1.getOverriddenMinimumLanguageVersion(),
829 ruleReference2.getOverriddenMinimumLanguageVersion());
830 assertEquals(
831 message
832 + ", RuleReference overridden maximum language version",
833 ruleReference1.getOverriddenMaximumLanguageVersion(),
834 ruleReference2.getOverriddenMaximumLanguageVersion());
835 assertEquals(message + ", RuleReference overridden deprecated",
836 ruleReference1.isOverriddenDeprecated(), ruleReference2
837 .isOverriddenDeprecated());
838 assertEquals(message + ", RuleReference overridden name",
839 ruleReference1.getOverriddenName(), ruleReference2
840 .getOverriddenName());
841 assertEquals(
842 message + ", RuleReference overridden description",
843 ruleReference1.getOverriddenDescription(),
844 ruleReference2.getOverriddenDescription());
845 assertEquals(message + ", RuleReference overridden message",
846 ruleReference1.getOverriddenMessage(), ruleReference2
847 .getOverriddenMessage());
848 assertEquals(message
849 + ", RuleReference overridden external info url",
850 ruleReference1.getOverriddenExternalInfoUrl(),
851 ruleReference2.getOverriddenExternalInfoUrl());
852 assertEquals(message + ", RuleReference overridden priority",
853 ruleReference1.getOverriddenPriority(), ruleReference2
854 .getOverriddenPriority());
855 assertEquals(message + ", RuleReference overridden examples",
856 ruleReference1.getOverriddenExamples(), ruleReference2
857 .getOverriddenExamples());
858 }
859
860 assertEquals(message + ", Rule name", rule1.getName(), rule2
861 .getName());
862 assertEquals(message + ", Rule class", rule1.getRuleClass(), rule2
863 .getRuleClass());
864 assertEquals(message + ", Rule description " + rule1.getName(),
865 rule1.getDescription(), rule2.getDescription());
866 assertEquals(message + ", Rule message", rule1.getMessage(), rule2
867 .getMessage());
868 assertEquals(message + ", Rule external info url", rule1
869 .getExternalInfoUrl(), rule2.getExternalInfoUrl());
870 assertEquals(message + ", Rule priority", rule1.getPriority(),
871 rule2.getPriority());
872 assertEquals(message + ", Rule examples", rule1.getExamples(),
873 rule2.getExamples());
874
875 List<PropertyDescriptor<?>> propertyDescriptors1 = rule1
876 .getPropertyDescriptors();
877 List<PropertyDescriptor<?>> propertyDescriptors2 = rule2
878 .getPropertyDescriptors();
879 try {
880 assertEquals(message + ", Rule property descriptor ",
881 propertyDescriptors1, propertyDescriptors2);
882 } catch (Error e) {
883 throw e;
884 }
885 for (int j = 0; j < propertyDescriptors1.size(); j++) {
886 assertEquals(message + ", Rule property value " + j, rule1
887 .getProperty(propertyDescriptors1.get(j)), rule2
888 .getProperty(propertyDescriptors2.get(j)));
889 }
890 assertEquals(message + ", Rule property descriptor count",
891 propertyDescriptors1.size(), propertyDescriptors2.size());
892 }
893 }
894
895 private boolean validateAgainstSchema(String fileName) throws IOException,
896 RuleSetNotFoundException, ParserConfigurationException,
897 SAXException {
898 InputStream inputStream = loadResourceAsStream(fileName);
899 boolean valid = validateAgainstSchema(inputStream);
900 if (!valid) {
901 System.err.println("Validation against XML Schema failed for: "
902 + fileName);
903 }
904 return valid;
905 }
906
907 private boolean validateAgainstSchema(InputStream inputStream)
908 throws IOException, RuleSetNotFoundException,
909 ParserConfigurationException, SAXException {
910
911 saxParser.parse(inputStream, validateDefaultHandlerXsd.resetValid());
912 inputStream.close();
913 return validateDefaultHandlerXsd.isValid();
914 }
915
916 private boolean validateAgainstDtd(String fileName) throws IOException,
917 RuleSetNotFoundException, ParserConfigurationException,
918 SAXException {
919 InputStream inputStream = loadResourceAsStream(fileName);
920 boolean valid = validateAgainstDtd(inputStream);
921 if (!valid) {
922 System.err
923 .println("Validation against DTD failed for: " + fileName);
924 }
925 return valid;
926 }
927
928 private boolean validateAgainstDtd(InputStream inputStream)
929 throws IOException, RuleSetNotFoundException,
930 ParserConfigurationException, SAXException {
931
932
933 String file = readFullyToString(inputStream);
934
935
936 file = file.replaceAll("<\\?xml [ a-zA-Z0-9=\".-]*\\?>", "");
937 file = file.replaceAll(
938 "xmlns=\"" + RuleSetWriter.RULESET_NS_URI + "\"", "");
939 file = file.replaceAll(
940 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
941 file = file
942 .replaceAll(
943 "xsi:schemaLocation=\"" + RuleSetWriter.RULESET_NS_URI + " http://pmd.sourceforge.net/ruleset_2_0_0.xsd\"",
944 "");
945
946 file = "<?xml version=\"1.0\"?>" + PMD.EOL
947 + "<!DOCTYPE ruleset SYSTEM \"file://"
948 + System.getProperty("user.dir") + "/src/main/resources/ruleset_2_0_0.dtd\">"
949 + PMD.EOL + file;
950
951 inputStream = new ByteArrayInputStream(file.getBytes());
952
953 saxParser.parse(inputStream, validateDefaultHandlerDtd.resetValid());
954 inputStream.close();
955 return validateDefaultHandlerDtd.isValid();
956 }
957
958 private String readFullyToString(InputStream inputStream)
959 throws IOException {
960 StringBuilder buf = new StringBuilder(64 * 1024);
961 BufferedReader reader = new BufferedReader(new InputStreamReader(
962 inputStream));
963 String line;
964 while ((line = reader.readLine()) != null) {
965 buf.append(line);
966 buf.append(PMD.EOL);
967 }
968 reader.close();
969 return buf.toString();
970 }
971
972
973 private List<String> getRuleSetFileNames() throws IOException,
974 RuleSetNotFoundException {
975 List<String> result = new ArrayList<String>();
976
977 for (Language language : Language.values()) {
978 result.addAll(getRuleSetFileNames(language.getTerseName()));
979 }
980
981 return result;
982 }
983
984 private List<String> getRuleSetFileNames(String language) throws IOException, RuleSetNotFoundException {
985 List<String> ruleSetFileNames = new ArrayList<String>();
986 try {
987 Properties properties = new Properties();
988 properties.load(ResourceLoader.loadResourceAsStream("rulesets/" + language + "/rulesets.properties"));
989 String fileNames = properties.getProperty("rulesets.filenames");
990 StringTokenizer st = new StringTokenizer(fileNames, ",");
991 while (st.hasMoreTokens()) {
992 ruleSetFileNames.add(st.nextToken());
993 }
994 } catch (RuleSetNotFoundException e) {
995
996 System.err.println("No ruleset found for language " + language);
997 }
998 return ruleSetFileNames;
999 }
1000
1001 private static class ValidateDefaultHandler extends DefaultHandler {
1002 private final String validateDocument;
1003 private boolean valid = true;
1004
1005 public ValidateDefaultHandler(String validateDocument) {
1006 this.validateDocument = validateDocument;
1007 }
1008
1009 public ValidateDefaultHandler resetValid() {
1010 valid = true;
1011 return this;
1012 }
1013
1014 public boolean isValid() {
1015 return valid;
1016 }
1017
1018 @Override
1019 public void error(SAXParseException e) throws SAXException {
1020 log("Error", e);
1021 }
1022
1023 @Override
1024 public void fatalError(SAXParseException e) throws SAXException {
1025 log("FatalError", e);
1026 }
1027
1028 @Override
1029 public void warning(SAXParseException e) throws SAXException {
1030 log("Warning", e);
1031 }
1032
1033 private void log(String prefix, SAXParseException e) {
1034 String message = prefix + " at (" + e.getLineNumber() + ", " + e.getColumnNumber() + "): " + e.getMessage();
1035 System.err.println(message);
1036 valid = false;
1037 }
1038
1039 @Override
1040 public InputSource resolveEntity(String publicId, String systemId)
1041 throws IOException, SAXException {
1042 if ("http://pmd.sourceforge.net/ruleset_2_0_0.xsd".equals(systemId)
1043 || systemId.endsWith("ruleset_2_0_0.dtd")) {
1044 try {
1045 InputStream inputStream = loadResourceAsStream(validateDocument);
1046 return new InputSource(inputStream);
1047 } catch (RuleSetNotFoundException e) {
1048 System.err.println(e.getMessage());
1049 throw new IOException(e.getMessage());
1050 }
1051 }
1052 throw new IllegalArgumentException(
1053 "No clue how to handle: publicId=" + publicId
1054 + ", systemId=" + systemId);
1055 }
1056 }
1057
1058 private static InputStream loadResourceAsStream(String resource)
1059 throws RuleSetNotFoundException {
1060 InputStream inputStream = ResourceLoader.loadResourceAsStream(resource,
1061 RuleSetFactoryTest.class.getClassLoader());
1062 if (inputStream == null) {
1063 throw new RuleSetNotFoundException(
1064 "Can't find resource "
1065 + resource
1066 + " Make sure the resource is a valid file or URL or is on the CLASSPATH. Here's the current classpath: "
1067 + System.getProperty("java.class.path"));
1068 }
1069 return inputStream;
1070 }
1071
1072 private static final String REF_OVERRIDE_ORIGINAL_NAME = "<?xml version=\"1.0\"?>"
1073 + PMD.EOL
1074 + "<ruleset name=\"test\">"
1075 + PMD.EOL
1076 + " <description>testdesc</description>"
1077 + PMD.EOL
1078 + " <rule "
1079 + PMD.EOL
1080 + " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"> "
1081 + PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
1082
1083 private static final String REF_MISPELLED_XREF = "<?xml version=\"1.0\"?>"
1084 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1085 + " <description>testdesc</description>" + PMD.EOL + " <rule "
1086 + PMD.EOL
1087 + " ref=\"rulesets/java/unusedcode.xml/FooUnusedLocalVariable\"> "
1088 + PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
1089
1090 private static final String REF_OVERRIDE_ORIGINAL_NAME_ONE_ELEM = "<?xml version=\"1.0\"?>"
1091 + PMD.EOL
1092 + "<ruleset name=\"test\">"
1093 + PMD.EOL
1094 + " <description>testdesc</description>"
1095 + PMD.EOL
1096 + " <rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"/> "
1097 + PMD.EOL + "</ruleset>";
1098
1099 private static final String REF_OVERRIDE = "<?xml version=\"1.0\"?>"
1100 + PMD.EOL
1101 + "<ruleset name=\"test\">"
1102 + PMD.EOL
1103 + " <description>testdesc</description>"
1104 + PMD.EOL
1105 + " <rule "
1106 + PMD.EOL
1107 + " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" "
1108 + PMD.EOL
1109 + " name=\"TestNameOverride\" "
1110 + PMD.EOL
1111 + " message=\"Test message override\"> "
1112 + PMD.EOL
1113 + " <description>Test description override</description>"
1114 + PMD.EOL
1115 + " <example>Test example override</example>"
1116 + PMD.EOL
1117 + " <priority>3</priority>"
1118 + PMD.EOL
1119 + " <properties>"
1120 + PMD.EOL
1121 + " <property name=\"test2\" description=\"test2\" type=\"String\" value=\"override2\"/>"
1122 + PMD.EOL
1123 + " <property name=\"test3\" description=\"test3\" type=\"String\"><value>override3</value></property>"
1124 + PMD.EOL
1125 + " <property name=\"test4\" description=\"test4\" type=\"String\" value=\"new property\"/>"
1126 + PMD.EOL + " </properties>" + PMD.EOL + " </rule>" + PMD.EOL
1127 + "</ruleset>";
1128
1129 private static final String REF_INTERNAL_TO_INTERNAL = "<?xml version=\"1.0\"?>"
1130 + PMD.EOL
1131 + "<ruleset name=\"test\">"
1132 + PMD.EOL
1133 + " <description>testdesc</description>"
1134 + PMD.EOL
1135 + "<rule "
1136 + PMD.EOL
1137 + "name=\"MockRuleName\" "
1138 + PMD.EOL
1139 + "message=\"avoid the mock rule\" "
1140 + PMD.EOL
1141 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1142 + PMD.EOL
1143 + "</rule>"
1144 + " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"/> "
1145 + PMD.EOL + "</ruleset>";
1146
1147 private static final String REF_INTERNAL_TO_INTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
1148 + PMD.EOL
1149 + "<ruleset name=\"test\">"
1150 + PMD.EOL
1151 + " <description>testdesc</description>"
1152 + PMD.EOL
1153 + "<rule "
1154 + PMD.EOL
1155 + "name=\"MockRuleName\" "
1156 + PMD.EOL
1157 + "message=\"avoid the mock rule\" "
1158 + PMD.EOL
1159 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1160 + PMD.EOL
1161 + "</rule>"
1162 + " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"><priority>2</priority></rule> "
1163 + PMD.EOL
1164 + " <rule ref=\"MockRuleNameRef\" name=\"MockRuleNameRefRef\"><priority>1</priority></rule> "
1165 + PMD.EOL + "</ruleset>";
1166
1167 private static final String REF_INTERNAL_TO_EXTERNAL = "<?xml version=\"1.0\"?>"
1168 + PMD.EOL
1169 + "<ruleset name=\"test\">"
1170 + PMD.EOL
1171 + " <description>testdesc</description>"
1172 + PMD.EOL
1173 + "<rule "
1174 + PMD.EOL
1175 + "name=\"ExternalRefRuleName\" "
1176 + PMD.EOL
1177 + "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1178 + PMD.EOL
1179 + " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"/> "
1180 + PMD.EOL + "</ruleset>";
1181
1182 private static final String REF_INTERNAL_TO_EXTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
1183 + PMD.EOL
1184 + "<ruleset name=\"test\">"
1185 + PMD.EOL
1186 + " <description>testdesc</description>"
1187 + PMD.EOL
1188 + "<rule "
1189 + PMD.EOL
1190 + "name=\"ExternalRefRuleName\" "
1191 + PMD.EOL
1192 + "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1193 + PMD.EOL
1194 + " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"><priority>2</priority></rule> "
1195 + PMD.EOL
1196 + " <rule ref=\"ExternalRefRuleNameRef\" name=\"ExternalRefRuleNameRefRef\"><priority>1</priority></rule> "
1197 + PMD.EOL + "</ruleset>";
1198
1199 private static final String EMPTY_RULESET = "<?xml version=\"1.0\"?>"
1200 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1201 + "<description>testdesc</description>" + PMD.EOL + "</ruleset>";
1202
1203 private static final String SINGLE_RULE = "<?xml version=\"1.0\"?>"
1204 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1205 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1206 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1207 + "message=\"avoid the mock rule\" " + PMD.EOL
1208 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1209 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1210
1211 private static final String MULTIPLE_RULES = "<?xml version=\"1.0\"?>"
1212 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1213 + "<description>testdesc</description>" + PMD.EOL
1214 + "<rule name=\"MockRuleName1\" " + PMD.EOL
1215 + "message=\"avoid the mock rule\" " + PMD.EOL
1216 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1217 + "</rule>" + PMD.EOL + "<rule name=\"MockRuleName2\" " + PMD.EOL
1218 + "message=\"avoid the mock rule\" " + PMD.EOL
1219 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1220 + "</rule></ruleset>";
1221
1222 private static final String PROPERTIES = "<?xml version=\"1.0\"?>"
1223 + PMD.EOL
1224 + "<ruleset name=\"test\">"
1225 + PMD.EOL
1226 + "<description>testdesc</description>"
1227 + PMD.EOL
1228 + "<rule name=\"MockRuleName\" "
1229 + PMD.EOL
1230 + "message=\"avoid the mock rule\" "
1231 + PMD.EOL
1232 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1233 + PMD.EOL
1234 + "<description>testdesc2</description>"
1235 + PMD.EOL
1236 + "<properties>"
1237 + PMD.EOL
1238 + "<property name=\"fooBoolean\" description=\"test\" type=\"Boolean\" value=\"true\" />"
1239 + PMD.EOL
1240 + "<property name=\"fooChar\" description=\"test\" type=\"Character\" value=\"B\" />"
1241 + PMD.EOL
1242 + "<property name=\"fooInt\" description=\"test\" type=\"Integer\" min=\"1\" max=\"10\" value=\"3\" />"
1243 + PMD.EOL
1244 + "<property name=\"fooFloat\" description=\"test\" type=\"Float\" min=\"1.0\" max=\"1.0\" value=\"1.0\" />"
1245 + PMD.EOL
1246 + "<property name=\"fooDouble\" description=\"test\" type=\"Double\" min=\"1.0\" max=\"9.0\" value=\"3.0\" />"
1247 + PMD.EOL
1248 + "<property name=\"fooString\" description=\"test\" type=\"String\" value=\"bar\" />"
1249 + PMD.EOL + "</properties>" + PMD.EOL + "</rule></ruleset>";
1250
1251 private static final String XPATH = "<?xml version=\"1.0\"?>" + PMD.EOL
1252 + "<ruleset name=\"test\">" + PMD.EOL
1253 + "<description>testdesc</description>" + PMD.EOL
1254 + "<rule name=\"MockRuleName\" " + PMD.EOL
1255 + "message=\"avoid the mock rule\" " + PMD.EOL
1256 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1257 + "<priority>3</priority>" + PMD.EOL + PMD.EOL
1258 + "<description>testdesc2</description>" + PMD.EOL + "<properties>"
1259 + PMD.EOL
1260 + "<property name=\"xpath\" description=\"test\" type=\"String\">"
1261 + PMD.EOL + "<value>" + PMD.EOL + "<![CDATA[ //Block ]]>" + PMD.EOL
1262 + "</value>" + PMD.EOL + "</property>" + PMD.EOL + "</properties>"
1263 + PMD.EOL + "</rule></ruleset>";
1264
1265 private static final String PRIORITY = "<?xml version=\"1.0\"?>" + PMD.EOL
1266 + "<ruleset name=\"test\">" + PMD.EOL
1267 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1268 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1269 + "message=\"avoid the mock rule\" " + PMD.EOL
1270 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1271 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1272
1273 private static final String LANGUAGE = "<?xml version=\"1.0\"?>"
1274 + PMD.EOL
1275 + "<ruleset name=\"test\">"
1276 + PMD.EOL
1277 + "<description>testdesc</description>"
1278 + PMD.EOL
1279 + "<rule "
1280 + PMD.EOL
1281 + "name=\"MockRuleName\" "
1282 + PMD.EOL
1283 + "message=\"avoid the mock rule\" "
1284 + PMD.EOL
1285 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" language=\"java\">"
1286 + PMD.EOL + "</rule></ruleset>";
1287
1288 private static final String INCORRECT_LANGUAGE = "<?xml version=\"1.0\"?>"
1289 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1290 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1291 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1292 + "message=\"avoid the mock rule\" " + PMD.EOL
1293 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\"" + PMD.EOL
1294 + " language=\"bogus\">" + PMD.EOL + "</rule></ruleset>";
1295
1296 private static final String MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1297 + PMD.EOL
1298 + "<ruleset name=\"test\">"
1299 + PMD.EOL
1300 + "<description>testdesc</description>"
1301 + PMD.EOL
1302 + "<rule "
1303 + PMD.EOL
1304 + "name=\"MockRuleName\" "
1305 + PMD.EOL
1306 + "message=\"avoid the mock rule\" "
1307 + PMD.EOL
1308 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1309 + PMD.EOL
1310 + " language=\"java\""
1311 + PMD.EOL
1312 + " minimumLanguageVersion=\"1.4\">"
1313 + PMD.EOL
1314 + "</rule></ruleset>";
1315
1316 private static final String INCORRECT_MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1317 + PMD.EOL
1318 + "<ruleset name=\"test\">"
1319 + PMD.EOL
1320 + "<description>testdesc</description>"
1321 + PMD.EOL
1322 + "<rule "
1323 + PMD.EOL
1324 + "name=\"MockRuleName\" "
1325 + PMD.EOL
1326 + "message=\"avoid the mock rule\" "
1327 + PMD.EOL
1328 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1329 + PMD.EOL
1330 + " language=\"java\""
1331 + PMD.EOL
1332 + " minimumLanguageVersion=\"bogus\">"
1333 + PMD.EOL
1334 + "</rule></ruleset>";
1335
1336 private static final String MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1337 + PMD.EOL
1338 + "<ruleset name=\"test\">"
1339 + PMD.EOL
1340 + "<description>testdesc</description>"
1341 + PMD.EOL
1342 + "<rule "
1343 + PMD.EOL
1344 + "name=\"MockRuleName\" "
1345 + PMD.EOL
1346 + "message=\"avoid the mock rule\" "
1347 + PMD.EOL
1348 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1349 + PMD.EOL
1350 + " language=\"java\""
1351 + PMD.EOL
1352 + " maximumLanguageVersion=\"1.7\">"
1353 + PMD.EOL
1354 + "</rule></ruleset>";
1355
1356 private static final String INCORRECT_MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1357 + PMD.EOL
1358 + "<ruleset name=\"test\">"
1359 + PMD.EOL
1360 + "<description>testdesc</description>"
1361 + PMD.EOL
1362 + "<rule "
1363 + PMD.EOL
1364 + "name=\"MockRuleName\" "
1365 + PMD.EOL
1366 + "message=\"avoid the mock rule\" "
1367 + PMD.EOL
1368 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1369 + PMD.EOL
1370 + " language=\"java\""
1371 + PMD.EOL
1372 + " maximumLanguageVersion=\"bogus\">"
1373 + PMD.EOL
1374 + "</rule></ruleset>";
1375
1376 private static final String INVERTED_MINIMUM_MAXIMUM_LANGUAGE_VERSIONS = "<?xml version=\"1.0\"?>"
1377 + PMD.EOL
1378 + "<ruleset name=\"test\">"
1379 + PMD.EOL
1380 + "<description>testdesc</description>"
1381 + PMD.EOL
1382 + "<rule "
1383 + PMD.EOL
1384 + "name=\"MockRuleName\" "
1385 + PMD.EOL
1386 + "message=\"avoid the mock rule\" "
1387 + PMD.EOL
1388 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" "
1389 + PMD.EOL
1390 + "language=\"java\""
1391 + PMD.EOL
1392 + " minimumLanguageVersion=\"1.7\""
1393 + PMD.EOL
1394 + "maximumLanguageVersion=\"1.4\">"
1395 + PMD.EOL
1396 + "</rule></ruleset>";
1397
1398 private static final String DIRECT_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1399 + PMD.EOL
1400 + "<ruleset name=\"test\">"
1401 + PMD.EOL
1402 + "<description>testdesc</description>"
1403 + PMD.EOL
1404 + "<rule "
1405 + PMD.EOL
1406 + "name=\"MockRuleName\" "
1407 + PMD.EOL
1408 + "message=\"avoid the mock rule\" "
1409 + PMD.EOL
1410 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" deprecated=\"true\">"
1411 + PMD.EOL + "</rule></ruleset>";
1412
1413
1414
1415 private static final String DEPRECATED_RULE_RULESET_NAME = "rulesets/java/basic.xml";
1416
1417
1418
1419 private static final String DEPRECATED_RULE_NAME = "EmptyCatchBlock";
1420
1421 private static final String REFERENCE_TO_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1422 + PMD.EOL
1423 + "<ruleset name=\"test\">"
1424 + PMD.EOL
1425 + "<description>testdesc</description>"
1426 + PMD.EOL
1427 + "<rule "
1428 + PMD.EOL
1429 + "ref=\""
1430 + DEPRECATED_RULE_RULESET_NAME
1431 + "/"
1432 + DEPRECATED_RULE_NAME + "\">" + PMD.EOL + "</rule></ruleset>";
1433
1434 private static final String REFERENCE_TO_RULESET_WITH_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1435 + PMD.EOL
1436 + "<ruleset name=\"test\">"
1437 + PMD.EOL
1438 + "<description>testdesc</description>"
1439 + PMD.EOL
1440 + "<rule "
1441 + PMD.EOL
1442 + "ref=\""
1443 + DEPRECATED_RULE_RULESET_NAME
1444 + "\">"
1445 + PMD.EOL + "</rule></ruleset>";
1446
1447 private static final String DFA = "<?xml version=\"1.0\"?>" + PMD.EOL
1448 + "<ruleset name=\"test\">" + PMD.EOL
1449 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1450 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1451 + "message=\"avoid the mock rule\" " + PMD.EOL + "dfa=\"true\" "
1452 + PMD.EOL + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1453 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1454
1455 private static final String INCLUDE_EXCLUDE_RULESET = "<?xml version=\"1.0\"?>"
1456 + PMD.EOL
1457 + "<ruleset name=\"test\">"
1458 + PMD.EOL
1459 + "<description>testdesc</description>"
1460 + PMD.EOL
1461 + "<include-pattern>include1</include-pattern>"
1462 + PMD.EOL
1463 + "<include-pattern>include2</include-pattern>"
1464 + PMD.EOL
1465 + "<exclude-pattern>exclude1</exclude-pattern>"
1466 + PMD.EOL
1467 + "<exclude-pattern>exclude2</exclude-pattern>"
1468 + PMD.EOL
1469 + "<exclude-pattern>exclude3</exclude-pattern>"
1470 + PMD.EOL
1471 + "</ruleset>";
1472
1473 private static final String EXTERNAL_REFERENCE_RULE_SET = "<?xml version=\"1.0\"?>"
1474 + PMD.EOL
1475 + "<ruleset name=\"test\">"
1476 + PMD.EOL
1477 + "<description>testdesc</description>"
1478 + PMD.EOL
1479 + "<rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1480 + PMD.EOL + "</ruleset>";
1481
1482 private Rule loadFirstRule(String ruleSetXml)
1483 throws RuleSetNotFoundException {
1484 RuleSet rs = loadRuleSet(ruleSetXml);
1485 return rs.getRules().iterator().next();
1486 }
1487
1488 private RuleSet loadRuleSetByFileName(String ruleSetFileName)
1489 throws RuleSetNotFoundException {
1490 RuleSetFactory rsf = new RuleSetFactory();
1491 return rsf.createRuleSet(ruleSetFileName);
1492 }
1493
1494 private RuleSet loadRuleSet(String ruleSetXml)
1495 throws RuleSetNotFoundException {
1496 RuleSetFactory rsf = new RuleSetFactory();
1497 return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml));
1498 }
1499
1500 private static RuleSetReferenceId createRuleSetReferenceId(final String ruleSetXml) {
1501 return new RuleSetReferenceId(null) {
1502 @Override
1503 public InputStream getInputStream(ClassLoader classLoader) throws RuleSetNotFoundException {
1504 try {
1505 return new ByteArrayInputStream(ruleSetXml.getBytes("UTF-8"));
1506 } catch (UnsupportedEncodingException e) {
1507 return null;
1508 }
1509 }
1510 };
1511 }
1512 }