001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.plugins.pmd;
021
022 import java.io.IOException;
023 import java.io.StringWriter;
024 import java.io.Writer;
025 import java.util.ArrayList;
026 import java.util.List;
027
028 import org.jdom.CDATA;
029 import org.jdom.Document;
030 import org.jdom.Element;
031 import org.jdom.output.Format;
032 import org.jdom.output.XMLOutputter;
033 import org.sonar.api.profiles.ProfileExporter;
034 import org.sonar.api.profiles.RulesProfile;
035 import org.sonar.api.resources.Java;
036 import org.sonar.api.rules.ActiveRule;
037 import org.sonar.api.rules.ActiveRuleParam;
038 import org.sonar.api.utils.SonarException;
039 import org.sonar.plugins.pmd.xml.PmdProperty;
040 import org.sonar.plugins.pmd.xml.PmdRule;
041 import org.sonar.plugins.pmd.xml.PmdRuleset;
042
043 public class PmdProfileExporter extends ProfileExporter {
044
045 public PmdProfileExporter() {
046 super(PmdConstants.REPOSITORY_KEY, PmdConstants.PLUGIN_NAME);
047 setSupportedLanguages(Java.KEY);
048 setMimeType("application/xml");
049 }
050
051 @Override
052 public void exportProfile(RulesProfile profile, Writer writer) {
053 try {
054 PmdRuleset tree = createPmdRuleset(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY), profile.getName());
055 String xmlModules = exportPmdRulesetToXml(tree);
056 writer.append(xmlModules);
057 } catch (IOException e) {
058 throw new SonarException("Fail to export the profile " + profile, e);
059 }
060 }
061
062 protected PmdRuleset createPmdRuleset(List<ActiveRule> activeRules, String profileName) {
063 PmdRuleset ruleset = new PmdRuleset(profileName);
064 for (ActiveRule activeRule : activeRules) {
065 if (activeRule.getRule().getRepositoryKey().equals(PmdConstants.REPOSITORY_KEY)) {
066 String configKey = activeRule.getRule().getConfigKey();
067 PmdRule rule = new PmdRule(configKey, PmdLevelUtils.toLevel(activeRule.getSeverity()));
068 if (activeRule.getActiveRuleParams() != null && !activeRule.getActiveRuleParams().isEmpty()) {
069 List<PmdProperty> properties = new ArrayList<PmdProperty>();
070 for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
071 properties.add(new PmdProperty(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue()));
072 }
073 rule.setProperties(properties);
074 }
075 ruleset.addRule(rule);
076 processXPathRule(activeRule.getRuleKey(), rule);
077 }
078 }
079 return ruleset;
080 }
081
082 protected void processXPathRule(String sonarRuleKey, PmdRule rule) {
083 if (PmdConstants.XPATH_CLASS.equals(rule.getRef())) {
084 rule.setRef(null);
085 PmdProperty xpathMessage = rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM);
086 if (xpathMessage == null) {
087 throw new SonarException("Property '" + PmdConstants.XPATH_MESSAGE_PARAM + "' should be set for PMD rule " + sonarRuleKey);
088 }
089 rule.setMessage(xpathMessage.getValue());
090 rule.removeProperty(PmdConstants.XPATH_MESSAGE_PARAM);
091 PmdProperty xpathExp = rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM);
092 if (xpathExp == null) {
093 throw new SonarException("Property '" + PmdConstants.XPATH_EXPRESSION_PARAM + "' should be set for PMD rule " + sonarRuleKey);
094 }
095 xpathExp.setCdataValue(xpathExp.getValue());
096 rule.setClazz(PmdConstants.XPATH_CLASS);
097 rule.setName(sonarRuleKey);
098 }
099 }
100
101 protected String exportPmdRulesetToXml(PmdRuleset pmdRuleset) {
102 Element eltRuleset = new Element("ruleset");
103 for (PmdRule pmdRule : pmdRuleset.getPmdRules()) {
104 Element eltRule = new Element("rule");
105 addAttribute(eltRule, "ref", pmdRule.getRef());
106 addAttribute(eltRule, "class", pmdRule.getClazz());
107 addAttribute(eltRule, "message", pmdRule.getMessage());
108 addAttribute(eltRule, "name", pmdRule.getName());
109 addChild(eltRule, "priority", pmdRule.getPriority());
110 if (pmdRule.hasProperties()) {
111 Element eltProperties = new Element("properties");
112 eltRule.addContent(eltProperties);
113 for (PmdProperty prop : pmdRule.getProperties()) {
114 Element eltProperty = new Element("property");
115 eltProperty.setAttribute("name", prop.getName());
116 if (prop.isCdataValue()) {
117 Element eltValue = new Element("value");
118 eltValue.addContent(new CDATA(prop.getCdataValue()));
119 eltProperty.addContent(eltValue);
120 } else {
121 eltProperty.setAttribute("value", prop.getValue());
122 }
123 eltProperties.addContent(eltProperty);
124 }
125 }
126 eltRuleset.addContent(eltRule);
127 }
128 XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
129 StringWriter xml = new StringWriter();
130 try {
131 serializer.output(new Document(eltRuleset), xml);
132 } catch (IOException e) {
133 throw new SonarException("A exception occured while generating the PMD configuration file.", e);
134 }
135 return xml.toString();
136 }
137
138 private void addChild(Element elt, String name, String text) {
139 if (text != null) {
140 elt.addContent(new Element(name).setText(text));
141 }
142 }
143
144 private void addAttribute(Element elt, String name, String value) {
145 if (value != null) {
146 elt.setAttribute(name, value);
147 }
148 }
149 }