package hudson.plugins.violations.types.stylecop; import java.io.FileInputStream; import java.io.IOException; import java.io.File; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import hudson.plugins.violations.ViolationsParser; import hudson.plugins.violations.model.FullBuildModel; import hudson.plugins.violations.model.FullFileModel; import hudson.plugins.violations.model.Severity; import hudson.plugins.violations.types.fxcop.XmlElementUtil; import hudson.plugins.violations.util.AbsoluteFileFinder; import hudson.plugins.violations.model.Violation; import hudson.plugins.violations.parse.ParseUtil; /** * Parses a StyleCop (http://code.msdn.microsoft.com/sourceanalysis/) xml report file. * */ public class StyleCopParser implements ViolationsParser { static final String TYPE_NAME = "stylecop"; private FullBuildModel model; private File reportParentFile; private File projectPath; public void parse( FullBuildModel model, File projectPath, String fileName, String[] sourcePaths) throws IOException { this.projectPath = projectPath; this.model = model; this.reportParentFile = new File(fileName).getParentFile(); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder; try { docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse(new FileInputStream(new File(projectPath, fileName))); // Pre v4.3 uses SourceAnalysisViolations as the parent node name NodeList mainNode = doc.getElementsByTagName("SourceAnalysisViolations"); if (mainNode.getLength() == 0) { // v4.3 uses StyleCopViolations as the parent node name mainNode = doc.getElementsByTagName("StyleCopViolations"); } Element rootElement = (Element) mainNode.item(0); parseViolations(XmlElementUtil.getNamedChildElements(rootElement, "Violation")); findSourceFiles(model, projectPath.getPath(), sourcePaths); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (SAXException se) { throw new IOException(se); } } /** * Go through all violations and see if the source files can be found. * @param model model containing all violations * @param workspace the workspace * @param sourcePaths the optional source paths */ private void findSourceFiles(FullBuildModel model, String workspace, String[] sourcePaths) { AbsoluteFileFinder finder = new AbsoluteFileFinder(); finder.addSourcePath(workspace); if (sourcePaths != null) { finder.addSourcePaths(sourcePaths); } Map<String, FullFileModel> fileModelMap = model.getFileModelMap(); for (String key : fileModelMap.keySet()) { FullFileModel fileModel = fileModelMap.get(key); File sourceFile = finder.getFileForName(fileModel.getDisplayName()); if (sourceFile != null) { fileModel.setSourceFile(sourceFile); fileModel.setLastModified(sourceFile.lastModified()); } } } /*** * Returns the value for the named attribute if it exists * @param element the element to check for an attribute * @param name the name of the attribute * @return the value of the attribute; "" if there is no such attribute. */ private String getString(Element element, String name) { if (element.hasAttribute(name)) { return element.getAttribute(name); } else { return ""; } } /** * Parse the Violation tag and add it to the build model * @param elements list of Violation tags */ private void parseViolations(List<Element> elements) throws IOException { for (Element element : elements) { Violation violation = new Violation(); violation.setLine(getString(element, "LineNumber")); violation.setMessage(element.getTextContent() + " (" + getString(element, "RuleId") + ")"); violation.setSeverity(Severity.MEDIUM); violation.setSeverityLevel(Severity.MEDIUM_VALUE); violation.setType(TYPE_NAME); String temp = getString(element, "RuleNamespace"); int i = temp.lastIndexOf('.'); if (i != -1) { violation.setSource(temp.substring(i)); } else { violation.setSource(getString(element,"RuleId")); } // Add the violation to the model String displayName; if (reportParentFile == null) { displayName = ParseUtil.resolveAbsoluteName( projectPath, getString(element,"Source")); } else { displayName = reportParentFile.getPath() + File.separator + getString(element,"Source"); } FullFileModel fileModel = model.getFileModel(displayName); fileModel.addViolation(violation); } } }