package hudson.plugins.dbcharts; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.ProminentProjectAction; import hudson.util.ChartUtil; import hudson.util.ShiftedCategoryAxis; import java.awt.Color; import java.awt.Font; import java.awt.Paint; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Shape; import java.io.IOException; import java.io.PrintWriter; import java.sql.SQLException; import java.util.List; import java.util.logging.Logger; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartRenderingInfo; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.chart.entity.CategoryItemEntity; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.EntityCollection; import org.jfree.chart.imagemap.ImageMapUtilities; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.DefaultDrawingSupplier; import org.jfree.chart.plot.DrawingSupplier; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.jdbc.JDBCCategoryDataset; import org.jfree.ui.RectangleInsets; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; public class DbChartAction implements Action { private static final Logger logger=Logger.getLogger( DbChartAction.class.getCanonicalName()); // private final AbstractProject<?,?> project; private final DbChartPublisher publisher; /** All plots share the same JFreeChart drawing supplier object. */ private static final DrawingSupplier supplier = new DefaultDrawingSupplier( DefaultDrawingSupplier.DEFAULT_PAINT_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE, DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE, // the plot data points are a small diamond shape new Shape[] { new Polygon(new int[] {3, 0, -3, 0}, new int[] {0, 4, 0, -4}, 4) } ); public DbChartAction( AbstractProject<?,?> project, DbChartPublisher publisher ) { super(); logger.info( "DbChartAction created for project:"+project); // / this.project = project; this.publisher = publisher; } public String getDisplayName() { // return "Db Chart"; return null; } public String getIconFileName() { return null;//"folder.gif"; } public String getUrlName() { return "dbCharts"; } public List<Chart> getCharts(){ logger.info( "getCharts().size="+publisher.getCharts().size() ); return publisher.getCharts(); } public Chart getChartByName(String name){ for(Chart c:getCharts()){ if (name.equals( c.name )){ return c; } } return null; } /** * Display the trend map. Delegates to the the associated * {@link ResultAction}. * * @param request * Stapler request * @param response * Stapler response * @throws IOException * in case of an error * @throws SQLException * @throws ClassNotFoundException */ public void doTrendMap(final StaplerRequest request, final StaplerResponse response) throws IOException, ClassNotFoundException, SQLException { Chart chartParams=getChartByName( request.getParameter( "chart" ) ); JFreeChart chart=buildChart(chartParams); ChartRenderingInfo info = new ChartRenderingInfo(); chart.createBufferedImage(chartParams.width,chartParams.height,info); EntityCollection entities = info.getEntityCollection(); if (entities != null) { int count = entities.getEntityCount(); for (int i = count - 1; i >= 0; i--) { ChartEntity entity = entities.getEntity(i); logger.info("Entity "+entity); if (entity instanceof CategoryItemEntity ){ CategoryItemEntity cie=(CategoryItemEntity) entity; logger.info(" - area:"+cie.getArea().getBounds()); logger.info(" - shapeCords:"+cie.getShapeCoords()); logger.info(" - columnKey:"+cie.getColumnKey() +" "+cie.getColumnKey().getClass().toString()); logger.info(" - rowKey:"+cie.getRowKey()+" "+cie.getRowKey().getClass().toString()); logger.info(" - columnIndex:"+cie.getDataset().getColumnIndex( cie.getColumnKey() )); logger.info(" - rowIndex:"+cie.getDataset().getRowIndex( cie.getRowKey() )); } } } Rectangle dataArea=info.getPlotInfo().getDataArea().getBounds(); logger.info("chartArea:"+info.getChartArea()); logger.info("dataArea:"+dataArea); logger.info("plotArea:"+info.getPlotInfo().getPlotArea()); final int categoriesCount=chart.getCategoryPlot().getCategories().size(); StringBuilder[] buffers=new StringBuilder[categoriesCount]; Integer[] starts=new Integer[categoriesCount]; Integer[] ends=new Integer[categoriesCount]; if (entities != null) { int count = entities.getEntityCount(); for (int i = count - 1; i >= 0; i--) { ChartEntity entity = entities.getEntity(i); if (entity instanceof CategoryItemEntity ){ CategoryItemEntity cie=(CategoryItemEntity) entity; int columnIndex=cie.getDataset().getColumnIndex( cie.getColumnKey() ); int rowIndex=cie.getDataset().getRowIndex( cie.getRowKey() ); if (buffers[columnIndex]==null){ buffers[columnIndex]=new StringBuilder(cie.getColumnKey()+": "); starts[columnIndex]=cie.getArea().getBounds().x; ends[columnIndex]=cie.getArea().getBounds().x+cie.getArea().getBounds().width; } buffers[columnIndex].append(" "+cie.getRowKey()+"="+cie.getDataset().getValue( rowIndex,columnIndex)); } } } response.setContentType("text/plain;charset=UTF-8"); PrintWriter ps=response.getWriter(); ps.println("<map id='map' name='map'>"); int last_start=dataArea.getBounds().x; for(int i=0; i<categoriesCount; i++){ int new_last_start= (i<categoriesCount-1)? (ends[i]+starts[i+1])/2 :(ends[i]+dataArea.x+dataArea.width)/2; ps.print(" <area shape='rect' coords='" +last_start+","+dataArea.y+"," +new_last_start+"," +(dataArea.y+dataArea.height)+"' "); ps.print(" title='"+ImageMapUtilities.htmlEscape(buffers[i].toString())+"'"); ps.println(" alt='' nohref='nohref' />"); last_start=new_last_start; } ps.println("</map>"); } /** * Display the trend graph. Delegates to the the associated * {@link ResultAction}. * * @param request * Stapler request * @param response * Stapler response * @throws IOException * in case of an error in * {@link ResultAction#doGraph(StaplerRequest, StaplerResponse, int)} */ public void doTrend(final StaplerRequest request, final StaplerResponse response) throws IOException { Chart c=getChartByName( request.getParameter("chart" ) ); try { ChartUtil.generateGraph( request, response, buildChart(c), c.width, c.height); } catch ( ClassNotFoundException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( SQLException e ) { // TODO Auto-generated catch block e.printStackTrace(); } } private JFreeChart buildChart(Chart c) throws ClassNotFoundException, SQLException { JDBCCategoryDataset dataset=new JDBCCategoryDataset(c.getJDBCConnection().url,c.getJDBCConnection().getDriver(),c.getJDBCConnection().user,c.getJDBCConnection().passwd); dataset.executeQuery(c.sqlQuery); JFreeChart chart=ChartFactory.createLineChart( c.title, c.categoryAxisLabel,c.valuesAxisLabel, dataset, PlotOrientation.VERTICAL, true, true, false ); final CategoryPlot plot = chart.getCategoryPlot(); plot.setDomainGridlinePaint(Color.black); plot.setRangeGridlinePaint(Color.black); plot.setDrawingSupplier(supplier); plot.setBackgroundPaint( Color.white ); chart.setBackgroundPaint( Color.white ); chart.getTitle().setFont( new Font( chart.getTitle().getFont().getName(), chart.getTitle().getFont().getStyle(), 12 ) ); CategoryAxis domainAxis = new ShiftedCategoryAxis(null); plot.setDomainAxis(domainAxis); domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); domainAxis.setMaximumCategoryLabelWidthRatio( 0.4f ); domainAxis.setLowerMargin(0.0); domainAxis.setUpperMargin(0.0); domainAxis.setCategoryMargin(0.0); plot.setInsets(new RectangleInsets(0,0,0,5.0)); return chart; } }