package hudson.plugins.rubymetricfu; import hudson.plugins.rubymetricfu.dataset.FlayMetricDataSetBuilder; import hudson.plugins.rubymetricfu.dataset.FlogMetricDataSetBuilder; import hudson.plugins.rubymetricfu.dataset.RcovMetricDataSetBuilder; import hudson.model.AbstractBuild; import hudson.model.HealthReportingAction; import hudson.model.Result; import hudson.util.ColorPalette; import hudson.util.ShiftedCategoryAxis; import java.awt.BasicStroke; import java.awt.Color; import java.io.IOException; import java.util.Calendar; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.LineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.data.category.CategoryDataset; import org.jfree.ui.RectangleEdge; import org.jfree.ui.RectangleInsets; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import hudson.util.ChartUtil; import hudson.model.AbstractBuild; import hudson.model.HealthReport; import hudson.plugins.rubymetricfu.model.MetricFuResults; import hudson.util.DataSetBuilder; @SuppressWarnings("unchecked") public class RubyMetricsBuildAction implements HealthReportingAction { private final MetricFuResults results; protected final AbstractBuild<?, ?> owner; public RubyMetricsBuildAction(AbstractBuild<?, ?> owner, MetricFuResults results) { this.owner = owner; this.results = results; } public RubyMetricsBuildAction getPreviousResult() { AbstractBuild<?, ?> b = owner; while (true) { b = b.getPreviousBuild(); if (b == null) { return null; } if (b.getResult() == Result.FAILURE) { continue; } RubyMetricsBuildAction r = b.getAction(this.getClass()); if (r != null) { return r; } } } public AbstractBuild<?, ?> getOwner() { return owner; } public HealthReport getBuildHealth() { return null; } public MetricFuResults getResults() { return results; } public String getDisplayName() { return "Ruby Metrics Report"; } public String getIconFileName() { return "graph.gif"; } public String getUrlName() { return "rubymetricfu"; } public void doFlayGraph(StaplerRequest req, StaplerResponse rsp) throws IOException { FlayMetricDataSetBuilder builder = new FlayMetricDataSetBuilder(); doGraph(req, rsp, builder.buildDataSet(this)); } public void doFlogGraph(StaplerRequest req, StaplerResponse rsp) throws IOException { FlogMetricDataSetBuilder builder = new FlogMetricDataSetBuilder(); doGraph(req, rsp, builder.buildDataSet(this)); } public void doRcovGraph(StaplerRequest req, StaplerResponse rsp) throws IOException { RcovMetricDataSetBuilder builder = new RcovMetricDataSetBuilder(); doGraph(req, rsp, builder.buildDataSet(this)); } private void doGraph(StaplerRequest req, StaplerResponse rsp, CategoryDataset data) throws IOException { ifAwtProblemRedirect(req, rsp); if (shouldGenerateGraph(req, rsp)){ ChartUtil.generateGraph(req, rsp, createChart(data, ""), 500, 200); } } private void ifAwtProblemRedirect(StaplerRequest req, StaplerResponse rsp) throws IOException{ if (ChartUtil.awtProblem) { rsp.sendRedirect2(req.getContextPath() + "/images/headless.png"); } } private boolean shouldGenerateGraph(StaplerRequest req, StaplerResponse rsp){ if (ChartUtil.awtProblem) { return false; } Calendar t = owner.getTimestamp(); if (req.checkIfModified(t, rsp)) { return false; // up to date } return true; } private JFreeChart createChart(CategoryDataset dataset, String rangeAxisLabel) { final JFreeChart chart = ChartFactory.createLineChart( null, // chart title null, // unused rangeAxisLabel, // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation true, // include legend true, // tooltips false // urls ); // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART... final LegendTitle legend = chart.getLegend(); legend.setPosition(RectangleEdge.RIGHT); chart.setBackgroundPaint(Color.white); final CategoryPlot plot = chart.getCategoryPlot(); // plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0)); plot.setBackgroundPaint(Color.WHITE); plot.setOutlinePaint(null); plot.setRangeGridlinesVisible(true); plot.setRangeGridlinePaint(Color.black); CategoryAxis domainAxis = new ShiftedCategoryAxis(null); plot.setDomainAxis(domainAxis); domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); domainAxis.setLowerMargin(0.0); domainAxis.setUpperMargin(0.0); domainAxis.setCategoryMargin(0.0); final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createStandardTickUnits()); final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer(); renderer.setBaseStroke(new BasicStroke(2.0f)); renderer.setShapesVisible(true); renderer.setLinesVisible(true); ColorPalette.apply(renderer); // crop extra space around the graph plot.setInsets(new RectangleInsets(5.0, 0, 0, 5.0)); return chart; } }