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 }