001 package org.hackystat.sensor.ant.jdepend; 002 003 import java.io.File; 004 import java.util.ArrayList; 005 import java.util.Date; 006 import java.util.HashMap; 007 import java.util.List; 008 import java.util.Map; 009 010 import javax.xml.bind.JAXBContext; 011 import javax.xml.bind.Unmarshaller; 012 import javax.xml.datatype.XMLGregorianCalendar; 013 014 import org.apache.tools.ant.BuildException; 015 import org.hackystat.sensor.ant.jdepend.jaxb.JDepend; 016 import org.hackystat.sensor.ant.task.HackystatSensorTask; 017 import org.hackystat.utilities.tstamp.Tstamp; 018 import org.hackystat.sensor.ant.jdepend.jaxb.Package; 019 020 /** 021 * Implements an Ant task that parses the XML files generated by JDepend. The Ant Task sends the 022 * Coupling data to a Hackystat server. 023 * 024 * @author Philip Johnson 025 */ 026 public class JDependSensor extends HackystatSensorTask { 027 028 /** The name of this tool. */ 029 private static String tool = "JDepend"; 030 031 /** Initialize a new instance of a JdependSensor. */ 032 public JDependSensor() { 033 super(tool); 034 } 035 036 /** 037 * Initialize a new instance of a JDependSensor for testing purposes. 038 * 039 * @param host The SensorBase host URL. 040 * @param email The SensorBase email to use. 041 * @param password The SensorBase password to use. 042 */ 043 public JDependSensor(String host, String email, String password) { 044 super(host, email, password, tool); 045 } 046 047 /** 048 * Parses the JDepend XML file and sends the resulting Coupling data to the SensorBase server. 049 * 050 * @throws BuildException If there is an error. 051 */ 052 @Override 053 public void executeInternal() throws BuildException { 054 this.setupSensorShell(); 055 int numberOfEntries = 0; 056 Date startTime = new Date(); 057 for (File dataFile : getDataFiles()) { 058 try { 059 verboseInfo("Processing JDepend file: " + dataFile); 060 numberOfEntries += this.processJDependXmlFile(dataFile); 061 } 062 catch (Exception e) { 063 signalError("Failure processing: " + dataFile, e); 064 } 065 } 066 // We've collected the data, now send it. 067 this.sendAndQuit(); 068 summaryInfo(startTime, "Coupling", numberOfEntries); 069 } 070 071 /** 072 * Processes the JDepend XML data file, generating sensor data. 073 * 074 * @param xmlFile The file containing the JavaNCSS data. 075 * @return The number of FileMetrics instances generated. 076 * @throws BuildException If problems occur. 077 */ 078 int processJDependXmlFile(File xmlFile) throws BuildException { 079 // The start time for all entries will be approximated by the XML file's last mod time. 080 // Use the TstampSet to make it unique. 081 long startTime = xmlFile.lastModified(); 082 int count = 0; 083 try { 084 JAXBContext context = JAXBContext 085 .newInstance(org.hackystat.sensor.ant.jdepend.jaxb.ObjectFactory.class); 086 Unmarshaller unmarshaller = context.createUnmarshaller(); 087 088 // JDepend report. 089 JDepend jdepend = (JDepend) unmarshaller.unmarshal(xmlFile); 090 // Construct the mapping from Java file paths to their CCN data. 091 Package2Path package2path = new Package2Path(getSourceFiles()); 092 List<Package> packageElements = new ArrayList<Package>(); 093 if ((jdepend.getPackages() != null) && 094 (jdepend.getPackages().getPackage() != null)) { 095 packageElements = jdepend.getPackages().getPackage(); 096 } 097 098 for (Package packageElement : packageElements) { 099 String resource = package2path.getPath(packageElement.getName()); 100 if ((packageElement.getStats() != null) && (resource != null)) { 101 long tstamp = this.tstampSet.getUniqueTstamp(startTime); 102 XMLGregorianCalendar tstampXml = Tstamp.makeTimestamp(tstamp); 103 XMLGregorianCalendar runtimeXml = Tstamp.makeTimestamp(this.runtime); 104 // Create the sensor data instance key/value map. 105 Map<String, String> keyValMap = new HashMap<String, String>(); 106 // Required for all sensor data 107 keyValMap.put("Tool", tool); 108 keyValMap.put("SensorDataType", "Coupling"); 109 keyValMap.put("Runtime", runtimeXml.toString()); 110 keyValMap.put("Timestamp", tstampXml.toString()); 111 keyValMap.put("Resource", resource); 112 // Expected for "Coupling" sensor data. 113 keyValMap.put("Type", "package"); 114 keyValMap.put("Afferent", String.valueOf(packageElement.getStats().getCa().intValue())); 115 keyValMap.put("Efferent", String.valueOf(packageElement.getStats().getCe().intValue())); 116 // add data to sensorshell 117 this.sensorShell.add(keyValMap); 118 count++; 119 } 120 } 121 return count; 122 } 123 catch (Throwable e) { 124 throw new BuildException(errMsgPrefix + "Failure: " + e.getMessage(), e); 125 } 126 } 127 }