1
2
3
4 package net.sourceforge.pmd;
5
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Properties;
15 import java.util.Set;
16 import java.util.logging.Level;
17 import java.util.logging.Logger;
18
19 import javax.xml.parsers.DocumentBuilder;
20 import javax.xml.parsers.DocumentBuilderFactory;
21 import javax.xml.parsers.ParserConfigurationException;
22
23 import net.sourceforge.pmd.lang.Language;
24 import net.sourceforge.pmd.lang.LanguageRegistry;
25 import net.sourceforge.pmd.lang.LanguageVersion;
26 import net.sourceforge.pmd.lang.rule.MockRule;
27 import net.sourceforge.pmd.lang.rule.RuleReference;
28 import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper;
29 import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil;
30 import net.sourceforge.pmd.util.ResourceLoader;
31 import net.sourceforge.pmd.util.StringUtil;
32
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35 import org.w3c.dom.Node;
36 import org.w3c.dom.NodeList;
37 import org.xml.sax.SAXException;
38
39
40
41
42
43
44
45 public class RuleSetFactory {
46
47 private static final Logger LOG = Logger.getLogger(RuleSetFactory.class.getName());
48
49 private ClassLoader classLoader = RuleSetFactory.class.getClassLoader();
50 private RulePriority minimumPriority = RulePriority.LOW;
51 private boolean warnDeprecated = false;
52
53
54
55
56
57
58 public void setClassLoader(ClassLoader classLoader) {
59 this.classLoader = classLoader;
60 }
61
62
63
64
65
66
67
68 public void setMinimumPriority(RulePriority minimumPriority) {
69 this.minimumPriority = minimumPriority;
70 }
71
72
73
74
75
76
77
78 public void setWarnDeprecated(boolean warnDeprecated) {
79 this.warnDeprecated = warnDeprecated;
80 }
81
82
83
84
85
86
87
88 public Iterator<RuleSet> getRegisteredRuleSets() throws RuleSetNotFoundException {
89 String rulesetsProperties = null;
90 try {
91 List<RuleSetReferenceId> ruleSetReferenceIds = new ArrayList<RuleSetReferenceId>();
92 for (Language language : LanguageRegistry.findWithRuleSupport()) {
93 Properties props = new Properties();
94 rulesetsProperties = "rulesets/" + language.getTerseName() + "/rulesets.properties";
95 props.load(ResourceLoader.loadResourceAsStream(rulesetsProperties));
96 String rulesetFilenames = props.getProperty("rulesets.filenames");
97 ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames));
98 }
99 return createRuleSets(ruleSetReferenceIds).getRuleSetsIterator();
100 } catch (IOException ioe) {
101 throw new RuntimeException("Couldn't find " + rulesetsProperties
102 + "; please ensure that the rulesets directory is on the classpath. The current classpath is: "
103 + System.getProperty("java.class.path"));
104 }
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118 public synchronized RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException {
119 return createRuleSets(RuleSetReferenceId.parse(referenceString));
120 }
121
122
123
124
125
126
127
128
129
130
131 public synchronized RuleSets createRuleSets(List<RuleSetReferenceId> ruleSetReferenceIds)
132 throws RuleSetNotFoundException {
133 RuleSets ruleSets = new RuleSets();
134 for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) {
135 RuleSet ruleSet = createRuleSet(ruleSetReferenceId);
136 ruleSets.addRuleSet(ruleSet);
137 }
138 return ruleSets;
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152 public synchronized RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException {
153 List<RuleSetReferenceId> references = RuleSetReferenceId.parse(referenceString);
154 if (references.isEmpty()) {
155 throw new RuleSetNotFoundException("No RuleSetReferenceId can be parsed from the string: <"
156 + referenceString + ">");
157 }
158 return createRuleSet(references.get(0));
159 }
160
161
162
163
164
165
166
167
168
169
170 public synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException {
171 return createRuleSet(ruleSetReferenceId, false);
172 }
173
174 private synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId,
175 boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException {
176 return parseRuleSetNode(ruleSetReferenceId, ruleSetReferenceId.getInputStream(this.classLoader),
177 withDeprecatedRuleReferences);
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 private Rule createRule(RuleSetReferenceId ruleSetReferenceId, boolean withDeprecatedRuleReferences)
196 throws RuleSetNotFoundException {
197 if (ruleSetReferenceId.isAllRules()) {
198 throw new IllegalArgumentException("Cannot parse a single Rule from an all Rule RuleSet reference: <"
199 + ruleSetReferenceId + ">.");
200 }
201 RuleSet ruleSet = createRuleSet(ruleSetReferenceId, withDeprecatedRuleReferences);
202 return ruleSet.getRuleByName(ruleSetReferenceId.getRuleName());
203 }
204
205
206
207
208
209
210
211
212
213
214
215 private RuleSet parseRuleSetNode(RuleSetReferenceId ruleSetReferenceId, InputStream inputStream,
216 boolean withDeprecatedRuleReferences) {
217 if (!ruleSetReferenceId.isExternal()) {
218 throw new IllegalArgumentException("Cannot parse a RuleSet from a non-external reference: <"
219 + ruleSetReferenceId + ">.");
220 }
221 try {
222 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
223 Document document = builder.parse(inputStream);
224 Element ruleSetElement = document.getDocumentElement();
225
226 RuleSet ruleSet = new RuleSet();
227 ruleSet.setFileName(ruleSetReferenceId.getRuleSetFileName());
228 ruleSet.setName(ruleSetElement.getAttribute("name"));
229
230 NodeList nodeList = ruleSetElement.getChildNodes();
231 for (int i = 0; i < nodeList.getLength(); i++) {
232 Node node = nodeList.item(i);
233 if (node.getNodeType() == Node.ELEMENT_NODE) {
234 String nodeName = node.getNodeName();
235 if ("description".equals(nodeName)) {
236 ruleSet.setDescription(parseTextNode(node));
237 } else if ("include-pattern".equals(nodeName)) {
238 ruleSet.addIncludePattern(parseTextNode(node));
239 } else if ("exclude-pattern".equals(nodeName)) {
240 ruleSet.addExcludePattern(parseTextNode(node));
241 } else if ("rule".equals(nodeName)) {
242 parseRuleNode(ruleSetReferenceId, ruleSet, node, withDeprecatedRuleReferences);
243 } else {
244 throw new IllegalArgumentException("Unexpected element <" + node.getNodeName()
245 + "> encountered as child of <ruleset> element.");
246 }
247 }
248 }
249
250 return ruleSet;
251 } catch (ClassNotFoundException cnfe) {
252 return classNotFoundProblem(cnfe);
253 } catch (InstantiationException ie) {
254 return classNotFoundProblem(ie);
255 } catch (IllegalAccessException iae) {
256 return classNotFoundProblem(iae);
257 } catch (ParserConfigurationException pce) {
258 return classNotFoundProblem(pce);
259 } catch (RuleSetNotFoundException rsnfe) {
260 return classNotFoundProblem(rsnfe);
261 } catch (IOException ioe) {
262 return classNotFoundProblem(ioe);
263 } catch (SAXException se) {
264 return classNotFoundProblem(se);
265 }
266 }
267
268 private static RuleSet classNotFoundProblem(Exception ex) throws RuntimeException {
269 ex.printStackTrace();
270 throw new RuntimeException("Couldn't find the class " + ex.getMessage());
271 }
272
273
274
275
276
277
278
279
280
281
282
283 private void parseRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode,
284 boolean withDeprecatedRuleReferences) throws ClassNotFoundException, InstantiationException,
285 IllegalAccessException, RuleSetNotFoundException {
286 Element ruleElement = (Element) ruleNode;
287 String ref = ruleElement.getAttribute("ref");
288 if (ref.endsWith("xml")) {
289 parseRuleSetReferenceNode(ruleSetReferenceId, ruleSet, ruleElement, ref);
290 } else if (StringUtil.isEmpty(ref)) {
291 parseSingleRuleNode(ruleSetReferenceId, ruleSet, ruleNode);
292 } else {
293 parseRuleReferenceNode(ruleSetReferenceId, ruleSet, ruleNode, ref, withDeprecatedRuleReferences);
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309 private void parseRuleSetReferenceNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Element ruleElement,
310 String ref) throws RuleSetNotFoundException {
311 RuleSetReference ruleSetReference = new RuleSetReference();
312 ruleSetReference.setAllRules(true);
313 ruleSetReference.setRuleSetFileName(ref);
314 String priority = null;
315 NodeList childNodes = ruleElement.getChildNodes();
316 Set<String> excludedRulesCheck = new HashSet<String>();
317 for (int i = 0; i < childNodes.getLength(); i++) {
318 Node child = childNodes.item(i);
319 if (isElementNode(child, "exclude")) {
320 Element excludeElement = (Element) child;
321 String excludedRuleName = excludeElement.getAttribute("name");
322 ruleSetReference.addExclude(excludedRuleName);
323 excludedRulesCheck.add(excludedRuleName);
324 } else if (isElementNode(child, "priority")) {
325 priority = parseTextNode(child).trim();
326 }
327 }
328
329 RuleSetFactory ruleSetFactory = new RuleSetFactory();
330 ruleSetFactory.setClassLoader(classLoader);
331 RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0));
332 for (Rule rule : otherRuleSet.getRules()) {
333 excludedRulesCheck.remove(rule.getName());
334 if (!ruleSetReference.getExcludes().contains(rule.getName())
335 && rule.getPriority().compareTo(minimumPriority) <= 0 && !rule.isDeprecated()) {
336 RuleReference ruleReference = new RuleReference();
337 ruleReference.setRuleSetReference(ruleSetReference);
338 ruleReference.setRule(rule);
339 ruleSet.addRuleIfNotExists(ruleReference);
340
341
342 if (priority != null) {
343 ruleReference.setPriority(RulePriority.valueOf(Integer.parseInt(priority)));
344 }
345 }
346 }
347 if (!excludedRulesCheck.isEmpty()) {
348 throw new IllegalArgumentException("Unable to exclude rules " + excludedRulesCheck
349 + "; perhaps the rule name is mispelled?");
350 }
351 }
352
353
354
355
356
357
358
359
360
361
362 private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode)
363 throws ClassNotFoundException, InstantiationException, IllegalAccessException {
364 Element ruleElement = (Element) ruleNode;
365
366
367
368 if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName())
369 && !isRuleName(ruleElement, ruleSetReferenceId.getRuleName())) {
370 return;
371 }
372
373 String attribute = ruleElement.getAttribute("class");
374 if (attribute == null || "".equals(attribute)) {
375 throw new IllegalArgumentException("The 'class' field of rule can't be null, nor empty.");
376 }
377 Rule rule = (Rule) classLoader.loadClass(attribute).newInstance();
378 rule.setName(ruleElement.getAttribute("name"));
379
380 if (ruleElement.hasAttribute("language")) {
381 String languageName = ruleElement.getAttribute("language");
382 Language language = LanguageRegistry.findLanguageByTerseName(languageName);
383 if (language == null) {
384 throw new IllegalArgumentException("Unknown Language '" + languageName + "' for Rule " + rule.getName()
385 + ", supported Languages are "
386 + LanguageRegistry.commaSeparatedTerseNamesForLanguage(LanguageRegistry.findWithRuleSupport()));
387 }
388 rule.setLanguage(language);
389 }
390
391 Language language = rule.getLanguage();
392 if (language == null) {
393 throw new IllegalArgumentException("Rule " + rule.getName()
394 + " does not have a Language; missing 'language' attribute?");
395 }
396
397 if (ruleElement.hasAttribute("minimumLanguageVersion")) {
398 String minimumLanguageVersionName = ruleElement.getAttribute("minimumLanguageVersion");
399 LanguageVersion minimumLanguageVersion = language.getVersion(minimumLanguageVersionName);
400 if (minimumLanguageVersion == null) {
401 throw new IllegalArgumentException("Unknown minimum Language Version '" + minimumLanguageVersionName
402 + "' for Language '" + language.getTerseName() + "' for Rule " + rule.getName()
403 + "; supported Language Versions are: "
404 + LanguageRegistry.commaSeparatedTerseNamesForLanguageVersion(language.getVersions()));
405 }
406 rule.setMinimumLanguageVersion(minimumLanguageVersion);
407 }
408
409 if (ruleElement.hasAttribute("maximumLanguageVersion")) {
410 String maximumLanguageVersionName = ruleElement.getAttribute("maximumLanguageVersion");
411 LanguageVersion maximumLanguageVersion = language.getVersion(maximumLanguageVersionName);
412 if (maximumLanguageVersion == null) {
413 throw new IllegalArgumentException("Unknown maximum Language Version '" + maximumLanguageVersionName
414 + "' for Language '" + language.getTerseName() + "' for Rule " + rule.getName()
415 + "; supported Language Versions are: "
416 + LanguageRegistry.commaSeparatedTerseNamesForLanguageVersion(language.getVersions()));
417 }
418 rule.setMaximumLanguageVersion(maximumLanguageVersion);
419 }
420
421 if (rule.getMinimumLanguageVersion() != null && rule.getMaximumLanguageVersion() != null) {
422 throw new IllegalArgumentException("The minimum Language Version '"
423 + rule.getMinimumLanguageVersion().getTerseName()
424 + "' must be prior to the maximum Language Version '"
425 + rule.getMaximumLanguageVersion().getTerseName() + "' for Rule " + rule.getName()
426 + "; perhaps swap them around?");
427 }
428
429 String since = ruleElement.getAttribute("since");
430 if (StringUtil.isNotEmpty(since)) {
431 rule.setSince(since);
432 }
433 rule.setMessage(ruleElement.getAttribute("message"));
434 rule.setRuleSetName(ruleSet.getName());
435 rule.setExternalInfoUrl(ruleElement.getAttribute("externalInfoUrl"));
436
437 if (hasAttributeSetTrue(ruleElement, "dfa")) {
438 rule.setUsesDFA();
439 }
440
441 if (hasAttributeSetTrue(ruleElement, "typeResolution")) {
442 rule.setUsesTypeResolution();
443 }
444
445 final NodeList nodeList = ruleElement.getChildNodes();
446 for (int i = 0; i < nodeList.getLength(); i++) {
447 Node node = nodeList.item(i);
448 if (node.getNodeType() != Node.ELEMENT_NODE) {
449 continue;
450 }
451 String nodeName = node.getNodeName();
452 if (nodeName.equals("description")) {
453 rule.setDescription(parseTextNode(node));
454 } else if (nodeName.equals("example")) {
455 rule.addExample(parseTextNode(node));
456 } else if (nodeName.equals("priority")) {
457 rule.setPriority(RulePriority.valueOf(Integer.parseInt(parseTextNode(node).trim())));
458 } else if (nodeName.equals("properties")) {
459 parsePropertiesNode(rule, node);
460 } else {
461 throw new IllegalArgumentException("Unexpected element <" + nodeName
462 + "> encountered as child of <rule> element for Rule " + rule.getName());
463 }
464
465 }
466 if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName())
467 || rule.getPriority().compareTo(minimumPriority) <= 0) {
468 ruleSet.addRule(rule);
469 }
470 }
471
472 private static boolean hasAttributeSetTrue(Element element, String attributeId) {
473 return element.hasAttribute(attributeId) && "true".equalsIgnoreCase(element.getAttribute(attributeId));
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489 private void parseRuleReferenceNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode,
490 String ref, boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException {
491 Element ruleElement = (Element) ruleNode;
492
493
494
495 if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName())
496 && !isRuleName(ruleElement, ruleSetReferenceId.getRuleName())) {
497 return;
498 }
499
500 RuleSetFactory ruleSetFactory = new RuleSetFactory();
501 ruleSetFactory.setClassLoader(classLoader);
502
503 boolean isSameRuleSet = false;
504 RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0);
505 if (!otherRuleSetReferenceId.isExternal()
506 && containsRule(ruleSetReferenceId, otherRuleSetReferenceId.getRuleName())) {
507 otherRuleSetReferenceId = new RuleSetReferenceId(ref, ruleSetReferenceId);
508 isSameRuleSet = true;
509 }
510 Rule referencedRule = ruleSetFactory.createRule(otherRuleSetReferenceId, true);
511
512
513
514
515
516 if (referencedRule == null) {
517 throw new IllegalArgumentException("Unable to find referenced rule "
518 + otherRuleSetReferenceId.getRuleName() + "; perhaps the rule name is mispelled?");
519 }
520
521 if (warnDeprecated && referencedRule.isDeprecated()) {
522 if (referencedRule instanceof RuleReference) {
523 RuleReference ruleReference = (RuleReference) referencedRule;
524 if (LOG.isLoggable(Level.WARNING)) {
525 LOG.warning("Use Rule name " + ruleReference.getRuleSetReference().getRuleSetFileName() + "/"
526 + ruleReference.getOriginalName() + " instead of the deprecated Rule name "
527 + otherRuleSetReferenceId
528 + ". Future versions of PMD will remove support for this deprecated Rule name usage.");
529 }
530 } else if (referencedRule instanceof MockRule) {
531 if (LOG.isLoggable(Level.WARNING)) {
532 LOG.warning("Discontinue using Rule name " + otherRuleSetReferenceId
533 + " as it has been removed from PMD and no longer functions."
534 + " Future versions of PMD will remove support for this Rule.");
535 }
536 } else {
537 if (LOG.isLoggable(Level.WARNING)) {
538 LOG.warning("Discontinue using Rule name " + otherRuleSetReferenceId
539 + " as it is scheduled for removal from PMD."
540 + " Future versions of PMD will remove support for this Rule.");
541 }
542 }
543 }
544
545 RuleSetReference ruleSetReference = new RuleSetReference();
546 ruleSetReference.setAllRules(false);
547 ruleSetReference.setRuleSetFileName(otherRuleSetReferenceId.getRuleSetFileName());
548
549 RuleReference ruleReference = new RuleReference();
550 ruleReference.setRuleSetReference(ruleSetReference);
551 ruleReference.setRule(referencedRule);
552
553 if (ruleElement.hasAttribute("deprecated")) {
554 ruleReference.setDeprecated(Boolean.parseBoolean(ruleElement.getAttribute("deprecated")));
555 }
556 if (ruleElement.hasAttribute("name")) {
557 ruleReference.setName(ruleElement.getAttribute("name"));
558 }
559 if (ruleElement.hasAttribute("message")) {
560 ruleReference.setMessage(ruleElement.getAttribute("message"));
561 }
562 if (ruleElement.hasAttribute("externalInfoUrl")) {
563 ruleReference.setExternalInfoUrl(ruleElement.getAttribute("externalInfoUrl"));
564 }
565 for (int i = 0; i < ruleElement.getChildNodes().getLength(); i++) {
566 Node node = ruleElement.getChildNodes().item(i);
567 if (node.getNodeType() == Node.ELEMENT_NODE) {
568 if (node.getNodeName().equals("description")) {
569 ruleReference.setDescription(parseTextNode(node));
570 } else if (node.getNodeName().equals("example")) {
571 ruleReference.addExample(parseTextNode(node));
572 } else if (node.getNodeName().equals("priority")) {
573 ruleReference.setPriority(RulePriority.valueOf(Integer.parseInt(parseTextNode(node))));
574 } else if (node.getNodeName().equals("properties")) {
575 parsePropertiesNode(ruleReference, node);
576 } else {
577 throw new IllegalArgumentException("Unexpected element <" + node.getNodeName()
578 + "> encountered as child of <rule> element for Rule " + ruleReference.getName());
579 }
580 }
581 }
582
583 if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName())
584 || referencedRule.getPriority().compareTo(minimumPriority) <= 0) {
585 if (withDeprecatedRuleReferences || !isSameRuleSet || !ruleReference.isDeprecated()) {
586 ruleSet.addRuleReplaceIfExists(ruleReference);
587 }
588 }
589 }
590
591
592
593
594
595
596
597
598 private boolean containsRule(RuleSetReferenceId ruleSetReferenceId, String ruleName) {
599 boolean found = false;
600 try {
601 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
602 Document document = builder.parse(ruleSetReferenceId.getInputStream(classLoader));
603 Element ruleSetElement = document.getDocumentElement();
604
605 NodeList rules = ruleSetElement.getElementsByTagName("rule");
606 for (int i = 0; i < rules.getLength(); i++) {
607 Element rule = (Element) rules.item(i);
608 if (rule.hasAttribute("name")) {
609 if (rule.getAttribute("name").equals(ruleName)) {
610 found = true;
611 break;
612 }
613 }
614 }
615 } catch (Exception e) {
616 throw new RuntimeException(e);
617 }
618
619 return found;
620 }
621
622 private static boolean isElementNode(Node node, String name) {
623 return node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals(name);
624 }
625
626
627
628
629
630
631
632 private static void parsePropertiesNode(Rule rule, Node propertiesNode) {
633 for (int i = 0; i < propertiesNode.getChildNodes().getLength(); i++) {
634 Node node = propertiesNode.getChildNodes().item(i);
635 if (isElementNode(node, "property")) {
636 parsePropertyNodeBR(rule, node);
637 }
638 }
639 }
640
641 private static String valueFrom(Node parentNode) {
642
643 final NodeList nodeList = parentNode.getChildNodes();
644
645 for (int i = 0; i < nodeList.getLength(); i++) {
646 Node node = nodeList.item(i);
647 if (isElementNode(node, "value")) {
648 return parseTextNode(node);
649 }
650 }
651 return null;
652 }
653
654
655
656
657
658
659
660 @SuppressWarnings("unchecked")
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 private static void setValue(Rule rule, PropertyDescriptor desc, String strValue) {
700 Object realValue = desc.valueFrom(strValue);
701 rule.setProperty(desc, realValue);
702 }
703
704 @SuppressWarnings("unchecked")
705 private static void parsePropertyNodeBR(Rule rule, Node propertyNode) {
706
707 Element propertyElement = (Element) propertyNode;
708 String typeId = propertyElement.getAttribute(PropertyDescriptorFields.TYPE);
709 String strValue = propertyElement.getAttribute(PropertyDescriptorFields.VALUE);
710 if (StringUtil.isEmpty(strValue)) {
711 strValue = valueFrom(propertyElement);
712 }
713
714
715 if (StringUtil.isEmpty(typeId)) {
716 String name = propertyElement.getAttribute(PropertyDescriptorFields.NAME);
717
718 PropertyDescriptor<?> propertyDescriptor = rule.getPropertyDescriptor(name);
719 if (propertyDescriptor == null) {
720 throw new IllegalArgumentException("Cannot set non-existant property '" + name + "' on Rule "
721 + rule.getName());
722 } else {
723 setValue(rule, propertyDescriptor, strValue);
724 }
725 return;
726 }
727
728 net.sourceforge.pmd.PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId);
729 if (pdFactory == null) {
730 throw new RuntimeException("No property descriptor factory for type: " + typeId);
731 }
732
733 Map<String, Boolean> valueKeys = pdFactory.expectedFields();
734 Map<String, String> values = new HashMap<String, String>(valueKeys.size());
735
736
737 for (Map.Entry<String, Boolean> entry : valueKeys.entrySet()) {
738 String valueStr = propertyElement.getAttribute(entry.getKey());
739 if (entry.getValue() && StringUtil.isEmpty(valueStr)) {
740 System.out.println("Missing required value for: " + entry.getKey());
741
742
743 }
744 values.put(entry.getKey(), valueStr);
745 }
746
747 PropertyDescriptor<?> desc = pdFactory.createWith(values);
748 PropertyDescriptorWrapper<?> wrapper = new PropertyDescriptorWrapper(desc);
749
750 rule.definePropertyDescriptor(wrapper);
751 setValue(rule, desc, strValue);
752 }
753
754
755
756
757
758
759
760 private static String parseTextNode(Node node) {
761
762 final int nodeCount = node.getChildNodes().getLength();
763 if (nodeCount == 0) {
764 return "";
765 }
766
767 StringBuilder buffer = new StringBuilder();
768
769 for (int i = 0; i < nodeCount; i++) {
770 Node childNode = node.getChildNodes().item(i);
771 if (childNode.getNodeType() == Node.CDATA_SECTION_NODE || childNode.getNodeType() == Node.TEXT_NODE) {
772 buffer.append(childNode.getNodeValue());
773 }
774 }
775 return buffer.toString();
776 }
777
778
779
780
781
782
783
784
785
786
787 private boolean isRuleName(Element ruleElement, String ruleName) {
788 if (ruleElement.hasAttribute("name")) {
789 return ruleElement.getAttribute("name").equals(ruleName);
790 } else if (ruleElement.hasAttribute("ref")) {
791 RuleSetReferenceId ruleSetReferenceId = RuleSetReferenceId.parse(ruleElement.getAttribute("ref")).get(0);
792 return ruleSetReferenceId.getRuleName() != null && ruleSetReferenceId.getRuleName().equals(ruleName);
793 } else {
794 return false;
795 }
796 }
797 }