Java tutorial
/** * $URL:$ * $Id:$ * * Copyright (c) 2006-2009 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package org.sakaiproject.sitestats.impl; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.text.DateFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.imageio.ImageIO; import lombok.Setter; import lombok.extern.apachecommons.CommonsLog; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.DateAxis; import org.jfree.chart.axis.DateTickMarkPosition; import org.jfree.chart.axis.DateTickUnit; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.labels.CategoryItemLabelGenerator; import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.CombinedDomainXYPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.chart.renderer.category.CategoryItemRenderer; import org.jfree.chart.renderer.category.LayeredBarRenderer; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.statistics.BoxAndWhiskerCategoryDataset; import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset; import org.jfree.data.time.Day; import org.jfree.data.time.Month; import org.jfree.data.time.MovingAverage; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.time.Week; import org.jfree.data.xy.IntervalXYDataset; import org.jfree.ui.RectangleInsets; import org.jfree.util.SortOrder; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.db.api.SqlReader; import org.sakaiproject.db.api.SqlService; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.sitestats.api.ServerWideReportManager; import org.sakaiproject.sitestats.api.ServerWideStatsRecord; import org.sakaiproject.sitestats.api.StatsManager; import org.sakaiproject.util.ResourceLoader; /** * Server Wide Report Manager handles running the database queries for each of the server wide reports. * * This currently provides limited support for the SST_ tables to be in a different database to the main Sakai database * so long as the credentials and URL are the same (except for the db name). It will do a cross database join onto that db. * * Configure via sakai.properties: * sitestats.externalDb.name=DB_NAME * * In addition to the normal settings for setting up external databases for the SST_ tables * */ @CommonsLog public class ServerWideReportManagerImpl implements ServerWideReportManager { /** Message bundle */ private static ResourceLoader msgs = new ResourceLoader("Messages"); @Setter private SqlService sqlService; @Setter private StatsManager statsManager; @Setter private UsageSessionService usageSessionService; @Setter private ServerConfigurationService serverConfigurationService; private String dbVendor; private String externalDbName; public void init() { //setup the vendor dbVendor = StringUtils .lowerCase(serverConfigurationService.getString("vendor@org.sakaiproject.db.api.SqlService", null)); log.info("ServerWideReportManagerImpl SQL queries configured to use: " + dbVendor); //setup the external db name for our cross db queries externalDbName = serverConfigurationService.getString("sitestats.externalDb.name", null); if (StringUtils.isNotBlank(externalDbName)) { log.info("ServerWideReportManagerImpl will query for Sitestats data in the external database: " + externalDbName); } else { log.info("ServerWideReportManagerImpl will query for Sitestats data in the main Sakai database"); } } public void destroy() { } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getMonthlyTotalLogins() */ public List<ServerWideStatsRecord> getMonthlyTotalLogins() { String mysql = "select STR_TO_DATE(date_format(ACTIVITY_DATE, '%Y-%m-01'),'%Y-%m-%d') as period," + " sum(ACTIVITY_COUNT) as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login'" + " group by 1"; String oracle = ("select TO_DATE(TO_CHAR(ACTIVITY_DATE, 'YYYY-MM-\"01\"'), 'YYYY-MM-DD') as period," + " sum(ACTIVITY_COUNT) as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login'" + " group by TO_DATE(TO_CHAR(ACTIVITY_DATE, 'YYYY-MM-\"01\"'), 'YYYY-MM-DD')"); List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getMonthlyTotalLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getMonthlyUniqueLogins() */ public List<ServerWideStatsRecord> getMonthlyUniqueLogins() { String mysql = "select STR_TO_DATE(date_format(LOGIN_DATE, '%Y-%m-01'),'%Y-%m-%d') as period," + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " group by 1"; String oracle = "select TO_DATE(TO_CHAR(LOGIN_DATE, 'YYYY-MM-\"01\"'),'YYYY-MM-DD') as period," + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " group by TO_DATE(TO_CHAR(LOGIN_DATE, 'YYYY-MM-\"01\"'),'YYYY-MM-DD')"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getMonthlyUniqueLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getWeeklyTotalLogins() */ public List<ServerWideStatsRecord> getWeeklyTotalLogins() { String mysql = "select STR_TO_DATE(concat(date_format(ACTIVITY_DATE, '%x-%v'), ' Monday'),'%x-%v %W') as week_start," + " sum(ACTIVITY_COUNT) as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login'" + " group by 1"; String oracle = "select next_day(ACTIVITY_DATE - 7, 2) as week_start," + " sum(ACTIVITY_COUNT) as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login'" + " group by next_day(ACTIVITY_DATE - 7, 2)"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getWeeklyTotalLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getWeeklyUniqueLogins() */ public List<ServerWideStatsRecord> getWeeklyUniqueLogins() { String mysql = "select STR_TO_DATE(concat(date_format(LOGIN_DATE, '%x-%v'), ' Monday'),'%x-%v %W') as week_start," + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " group by 1"; String oracle = "select next_day(LOGIN_DATE - 7, 2) as week_start," + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " group by next_day(LOGIN_DATE - 7, 2)"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getWeeklyUniqueLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getDailyTotalLogins() */ public List<ServerWideStatsRecord> getDailyTotalLogins() { String mysql = "select date(ACTIVITY_DATE) as session_date, " + " ACTIVITY_COUNT as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login' " + " and ACTIVITY_DATE > DATE_SUB(CURDATE(), INTERVAL 90 DAY)" + " group by 1"; String oracle = "select trunc(ACTIVITY_DATE, 'DDD') as session_date," + " sum(ACTIVITY_COUNT) as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.login' " + " and ACTIVITY_DATE > (SYSDATE - 90)" + " group by trunc(ACTIVITY_DATE, 'DDD')"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getDailyTotalLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } /* * (non-Javadoc) * @see org.sakaiproject.sitestats.api.ServerWideReportManager#getDailyUniqueLogins() */ public List<ServerWideStatsRecord> getDailyUniqueLogins() { String mysql = "select date(LOGIN_DATE) as session_date, " + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " where LOGIN_DATE > DATE_SUB(CURDATE(), INTERVAL 90 DAY)" + " group by 1"; String oracle = "select trunc(LOGIN_DATE, 'DDD') as session_date, " + " count(distinct user_id) as unique_users" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " where LOGIN_DATE > (SYSDATE - 90)" + " group by trunc(LOGIN_DATE, 'DDD')"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getDailyUniqueLogins() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } public List<ServerWideStatsRecord> getSiteCreatedDeletedStats(String period) { String mysqlPeriod = ""; if (period.equals("daily")) { mysqlPeriod = "date(ACTIVITY_DATE) as event_period"; } else if (period.equals("weekly")) { mysqlPeriod = "STR_TO_DATE(date_format(ACTIVITY_DATE, '%x-%v Monday'),'%x-%v %W') as event_period"; } else { // monthly mysqlPeriod = "STR_TO_DATE(date_format(ACTIVITY_DATE, '%Y-%m-01'),'%Y-%m-%d') as event_period"; } String mysql = "select " + mysqlPeriod + ", " + "sum(if(EVENT_ID = 'site.add',activity_count,0)) as site_created, " + "sum(if(EVENT_ID = 'site.del',activity_count,0)) as site_deleted " + "FROM " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS "; if (period.equals("daily")) { mysql = mysql + "where ACTIVITY_DATE > DATE_SUB(CURDATE(), INTERVAL 90 DAY) "; } mysql = mysql + "group by 1"; String oraclePeriod = ""; if (period.equals("daily")) { oraclePeriod = "trunc(ACTIVITY_DATE, 'DDD')"; } else if (period.equals("weekly")) { oraclePeriod = "next_day(ACTIVITY_DATE - 7, 2)"; } else { // monthly oraclePeriod = "TO_DATE(TO_CHAR(ACTIVITY_DATE, 'YYYY-MM-\"01\"'),'YYYY-MM-DD')"; } String oracle = "select " + oraclePeriod + " as event_period, " + "sum(decode(EVENT_ID, 'site.add',activity_count,0)) as site_created, " + "sum(decode(EVENT_ID, 'site.del',activity_count,0)) as site_deleted " + "FROM " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS "; if (period.equals("daily")) { oracle = oracle + "where ACTIVITY_DATE > (SYSDATE - 90) "; } oracle = oracle + "group by " + oraclePeriod; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); info.add(result.getLong(3)); } catch (SQLException e) { log.error("getSiteCreatedDeletedStats() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period if (result.size() > 0) { result.remove(result.size() - 1); } return result; } public List<ServerWideStatsRecord> getNewUserStats(String period) { String mysqlPeriod = ""; if (period.equals("daily")) { mysqlPeriod = "date(ACTIVITY_DATE) as event_period"; } else if (period.equals("weekly")) { mysqlPeriod = "STR_TO_DATE(date_format(ACTIVITY_DATE, '%x-%v Monday'),'%x-%v %W') as event_period"; } else { // monthly mysqlPeriod = "STR_TO_DATE(date_format(ACTIVITY_DATE, '%Y-%m-01'),'%Y-%m-%d') as event_period"; } String mysql = "select " + mysqlPeriod + ", " + " ACTIVITY_COUNT as new_user" + " FROM " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.add'"; if (period.equals("daily")) { mysql = mysql + " and ACTIVITY_DATE > DATE_SUB(CURDATE(), INTERVAL 90 DAY) "; } mysql = mysql + " group by 1"; String oraclePeriod = ""; if (period.equals("daily")) { oraclePeriod = "trunc(ACTIVITY_DATE, 'DDD')"; } else if (period.equals("weekly")) { oraclePeriod = "next_day(ACTIVITY_DATE - 7, 2)"; } else { // monthly oraclePeriod = "TO_DATE(TO_CHAR(ACTIVITY_DATE, 'YYYY-MM-\"01\"'),'YYYY-MM-DD')"; } String oracle = "select " + oraclePeriod + " as event_period, " + " sum(ACTIVITY_COUNT) as new_user" + " FROM " + getExternalDbNameAsPrefix() + "SST_SERVERSTATS" + " where EVENT_ID='user.add'"; if (period.equals("daily")) { oracle = oracle + " AND ACTIVITY_DATE > (SYSDATE - 90) "; } oracle = oracle + " group by " + oraclePeriod; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); } catch (SQLException e) { log.error("getNewUserStats() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period if (result.size() > 0) { result.remove(result.size() - 1); } return result; } public List<ServerWideStatsRecord> getTop20Activities() { String mysql = "SELECT event_id, " + "sum(if(event_date > DATE_SUB(CURDATE(), INTERVAL 7 DAY),1,0))/7 as last7, " + "sum(if(event_date > DATE_SUB(CURDATE(), INTERVAL 30 DAY),1,0))/30 as last30, " + "sum(if(event_date > DATE_SUB(CURDATE(), INTERVAL 365 DAY),1,0))/365 as last365 " + "FROM " + getExternalDbNameAsPrefix() + "SST_EVENTS " + "where event_id not in ('content.read', 'user.login', 'user.logout', 'pres.begin', 'pres.end', " + "'realm.upd', 'realm.add', 'realm.del', 'realm.upd.own', 'site.add', 'site.del', 'user.add', 'user.del') " + "and event_date > DATE_SUB(CURDATE(), INTERVAL 365 DAY) " + "group by 1 " + "order by 2 desc, 3 desc, 4 desc " + "LIMIT 20"; String oracle = "select * from" + " (SELECT event_id," + " sum(decode(sign(event_date - (SYSDATE - 7)), 1, 1, 0)) / 7 as last7," + " sum(decode(sign(event_date - (SYSDATE - 30)), 1, 1, 0)) / 30 as last30," + " sum(decode(sign(event_date - (SYSDATE - 365)), 1, 1, 0)) / 365 as last365" + " FROM " + getExternalDbNameAsPrefix() + "SST_EVENTS" + " where event_id not in ('content.read', 'user.login', 'user.logout', 'pres.begin', 'pres.end', 'realm.upd', 'realm.add', 'realm.del', 'realm.upd.own', 'site.add', 'site.del', 'user.add', 'user.del')" + " and event_date > (SYSDATE - 365)" + " group by event_id" + " order by last7 desc, last30 desc, last365 desc)" + " where rownum <= 20"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getString(1)); info.add(result.getDouble(2)); info.add(result.getDouble(3)); info.add(result.getDouble(4)); } catch (SQLException e) { log.error("getTop20Activities() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); return result; } public List<ServerWideStatsRecord> getWeeklyRegularUsers() { String mysql = "select s.week_start, sum(if(s.user_logins >= 5,1,0)) as five_plus, " + "sum(if(s.user_logins = 4,1,0)) as four, " + "sum(if(s.user_logins = 3,1,0)) as three, " + "sum(if(s.user_logins = 2,1,0)) as twice, " + "sum(if(s.user_logins = 1,1,0)) as once " + "from (select " + "STR_TO_DATE(concat(date_format(login_date, '%x-%v'), ' Monday'),'%x-%v %W') as week_start, " + "user_id, login_count as user_logins " + "from " + getExternalDbNameAsPrefix() + "SST_USERSTATS group by 1, 2) as s " + "group by 1"; String oracle = "select s.week_start," + " sum(decode(sign(s.user_logins - 4), 1, 1, 0)) as five_plus," + " sum(decode(s.user_logins, 4, 1, 0)) as four, " + " sum(decode(s.user_logins, 3, 1, 0)) as three, " + " sum(decode(s.user_logins, 2, 1, 0)) as twice, " + " sum(decode(s.user_logins, 1, 1, 0)) as once" + " from (select next_day(LOGIN_DATE - 7, 2) as week_start," + " user_id, login_count as user_logins" + " from " + getExternalDbNameAsPrefix() + "SST_USERSTATS" + " group by next_day(LOGIN_DATE - 7, 2), user_id, login_count) s" + " group by s.week_start"; List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getLong(2)); info.add(result.getLong(3)); info.add(result.getLong(4)); info.add(result.getLong(5)); info.add(result.getLong(6)); } catch (SQLException e) { log.error("getWeeklyRegularUsers() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); // remove the last entry, as it might not be a complete period result.remove(result.size() - 1); return result; } // this has not been reimplemented in STAT-299 because the data is not tracked at an hourly level // in any case, the data is only shown for a 30 day period so you could think about retaining the data for 30 days, perhaps. public List<ServerWideStatsRecord> getHourlyUsagePattern() { String mysql = "select date(SESSION_START) as session_date, " + "hour(session_start) as hour_start, " + "count(distinct SESSION_USER) as unique_users " + "from SAKAI_SESSION " + "where SESSION_START > DATE_SUB(CURDATE(), INTERVAL 30 DAY) " + "group by 1, 2"; String oracle = "select trunc(SESSION_START, 'DDD') as session_date," + " to_number(to_char(session_start, 'HH24')) as hour_start," + " count(distinct SESSION_USER) as unique_users" + " from SAKAI_SESSION" + " where SESSION_START > (SYSDATE - 30)" + " group by trunc(SESSION_START, 'DDD'), to_number(to_char(session_start, 'HH24'))"; // This query uses only the main Sakai database, so do not specify the connection as it might be external List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getDate(1)); info.add(result.getInt(2)); info.add(result.getLong(3)); } catch (SQLException e) { log.error("getHourlyUsagePattern() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); return result; } public List<ServerWideStatsRecord> getToolCount() { String mysql = "SELECT registration, count(*) as site_count " + "FROM SAKAI_SITE_TOOL " + "where site_id not like '~%' and site_id not like '!%' " + "group by 1 " + "order by 2 desc"; String oracle = "SELECT registration, count(*) as site_count" + " FROM SAKAI_SITE_TOOL" + " where site_id not like '~%' and site_id not like '!%'" + " group by registration" + " order by site_count desc"; // This query uses only the main Sakai database, so do not specify the connection as it might be external List result = sqlService.dbRead(getSqlForVendor(mysql, oracle), null, new SqlReader() { public Object readSqlResultRecord(ResultSet result) { ServerWideStatsRecord info = new ServerWideStatsRecordImpl(); try { info.add(result.getString(1)); info.add(result.getInt(2)); } catch (SQLException e) { log.error("getToolCount() exception: " + e.getClass() + ": " + e.getMessage()); return null; } return info; } }); return result; } public byte[] generateReportChart(String reportType, int width, int height) { if (reportType.equals(StatsManager.MONTHLY_LOGIN_REPORT)) { return createMonthlyLoginChart(width, height); } else if (reportType.equals(StatsManager.WEEKLY_LOGIN_REPORT)) { return createWeeklyLoginChart(width, height); } else if (reportType.equals(StatsManager.DAILY_LOGIN_REPORT)) { return createDailyLoginChart(width, height); } else if (reportType.equals(StatsManager.REGULAR_USERS_REPORT)) { CategoryDataset dataset = getRegularUsersDataSet(); if (dataset != null) { return generateStackedAreaChart(dataset, width, height); } else { return generateNoDataChart(width, height); } } else if (reportType.equals(StatsManager.HOURLY_USAGE_REPORT)) { BoxAndWhiskerCategoryDataset dataset = getHourlyUsageDataSet(); if (dataset != null) { return generateBoxAndWhiskerChart(dataset, width, height); } else { return generateNoDataChart(width, height); } } else if (reportType.equals(StatsManager.TOP_ACTIVITIES_REPORT)) { CategoryDataset dataset = getTopActivitiesDataSet(); if (dataset != null) { return generateLayeredBarChart(dataset, width, height); } else { return generateNoDataChart(width, height); } } else if (reportType.equals(StatsManager.TOOL_REPORT)) { return createToolAnalysisChart(width, height); } else { return generateNoDataChart(width, height); } } private IntervalXYDataset getMonthlyLoginsDataSet() { List<ServerWideStatsRecord> totalLogins = getMonthlyTotalLogins(); List<ServerWideStatsRecord> uniqueLogins = getMonthlyUniqueLogins(); if (totalLogins == null || uniqueLogins == null) { return null; } TimeSeries s1 = new TimeSeries(msgs.getString("legend_logins"), Month.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_unique_logins"), Month.class); for (ServerWideStatsRecord login : totalLogins) { Month month = new Month((Date) login.get(0)); s1.add(month, (Long) login.get(1)); } for (ServerWideStatsRecord login : uniqueLogins) { Month month = new Month((Date) login.get(0)); s2.add(month, (Long) login.get(1)); } TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); return dataset; } /* private IntervalXYDataset getMonthlyLoginsDataSet() { List<ServerWideStatsRecord> loginList = getMonthlyUniqueLogins(); if (loginList == null) { return null; } TimeSeries s2 = new TimeSeries (msgs.getString ("legend_unique_logins"), Month.class); for (ServerWideStatsRecord login : loginList) { Month month = new Month ((Date) login.get (0)); s2.add (month, (Long) login.get (1)); } TimeSeriesCollection dataset = new TimeSeriesCollection (); dataset.addSeries (s2); return dataset; } */ private IntervalXYDataset getWeeklyLoginsDataSet() { List<ServerWideStatsRecord> totalLogins = getWeeklyTotalLogins(); List<ServerWideStatsRecord> uniqueLogins = getWeeklyUniqueLogins(); if (totalLogins == null || uniqueLogins == null) { return null; } TimeSeries s1 = new TimeSeries(msgs.getString("legend_logins"), Week.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_unique_logins"), Week.class); for (ServerWideStatsRecord login : totalLogins) { Week week = new Week((Date) login.get(0)); s1.add(week, (Long) login.get(1)); } for (ServerWideStatsRecord login : uniqueLogins) { Week week = new Week((Date) login.get(0)); s2.add(week, (Long) login.get(1)); } TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); return dataset; } private IntervalXYDataset getDailyLoginsDataSet() { List<ServerWideStatsRecord> totalLogins = getDailyTotalLogins(); List<ServerWideStatsRecord> uniqueLogins = getDailyUniqueLogins(); if (totalLogins == null || uniqueLogins == null) { return null; } TimeSeries s1 = new TimeSeries(msgs.getString("legend_logins"), Day.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_unique_logins"), Day.class); for (ServerWideStatsRecord login : totalLogins) { Day day = new Day((Date) login.get(0)); s1.add(day, (Long) login.get(1)); } for (ServerWideStatsRecord login : uniqueLogins) { Day day = new Day((Date) login.get(0)); s2.add(day, (Long) login.get(1)); } TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); TimeSeries mavS1 = MovingAverage.createMovingAverage(s1, "7 day login moving average", 7, 7); dataset.addSeries(mavS1); TimeSeries mavS2 = MovingAverage.createMovingAverage(s2, "7 day unique login moving average", 7, 7); dataset.addSeries(mavS2); return dataset; } private IntervalXYDataset getMonthlySiteUserDataSet() { List<ServerWideStatsRecord> siteCreatedDeletedList = getSiteCreatedDeletedStats("monthly"); TimeSeriesCollection dataset = new TimeSeriesCollection(); if (siteCreatedDeletedList != null) { TimeSeries s1 = new TimeSeries(msgs.getString("legend_site_created"), Month.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_site_deleted"), Month.class); for (ServerWideStatsRecord login : siteCreatedDeletedList) { Month month = new Month((Date) login.get(0)); s1.add(month, (Long) login.get(1)); s2.add(month, (Long) login.get(2)); } dataset.addSeries(s1); dataset.addSeries(s2); } List<ServerWideStatsRecord> newUserList = getNewUserStats("monthly"); if (newUserList != null) { TimeSeries s3 = new TimeSeries(msgs.getString("legend_new_user"), Month.class); for (ServerWideStatsRecord login : newUserList) { Month month = new Month((Date) login.get(0)); s3.add(month, (Long) login.get(1)); } dataset.addSeries(s3); } return dataset; } private IntervalXYDataset getWeeklySiteUserDataSet() { List<ServerWideStatsRecord> siteCreatedDeletedList = getSiteCreatedDeletedStats("weekly"); TimeSeriesCollection dataset = new TimeSeriesCollection(); if (siteCreatedDeletedList != null) { TimeSeries s1 = new TimeSeries(msgs.getString("legend_site_created"), Week.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_site_deleted"), Week.class); for (ServerWideStatsRecord login : siteCreatedDeletedList) { Week week = new Week((Date) login.get(0)); s1.add(week, (Long) login.get(1)); s2.add(week, (Long) login.get(2)); } dataset.addSeries(s1); dataset.addSeries(s2); } List<ServerWideStatsRecord> newUserList = getNewUserStats("weekly"); if (newUserList != null) { TimeSeries s3 = new TimeSeries(msgs.getString("legend_new_user"), Week.class); for (ServerWideStatsRecord login : newUserList) { Week week = new Week((Date) login.get(0)); s3.add(week, (Long) login.get(1)); } dataset.addSeries(s3); } return dataset; } private IntervalXYDataset getDailySiteUserDataSet() { List<ServerWideStatsRecord> siteCreatedDeletedList = getSiteCreatedDeletedStats("daily"); TimeSeriesCollection dataset = new TimeSeriesCollection(); if (siteCreatedDeletedList != null) { TimeSeries s1 = new TimeSeries(msgs.getString("legend_site_created"), Day.class); TimeSeries s2 = new TimeSeries(msgs.getString("legend_site_deleted"), Day.class); for (ServerWideStatsRecord login : siteCreatedDeletedList) { Day day = new Day((Date) login.get(0)); s1.add(day, (Long) login.get(1)); s2.add(day, (Long) login.get(2)); } dataset.addSeries(s1); dataset.addSeries(s2); } List<ServerWideStatsRecord> newUserList = getNewUserStats("daily"); if (newUserList != null) { TimeSeries s3 = new TimeSeries(msgs.getString("legend_new_user"), Day.class); for (ServerWideStatsRecord login : newUserList) { Day day = new Day((Date) login.get(0)); s3.add(day, (Long) login.get(1)); } dataset.addSeries(s3); } return dataset; } private CategoryDataset getRegularUsersDataSet() { List<ServerWideStatsRecord> regularUsersList = getWeeklyRegularUsers(); if (regularUsersList == null) { return null; } DefaultCategoryDataset dataset = new DefaultCategoryDataset(); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); for (ServerWideStatsRecord regularUsers : regularUsersList) { Date weekStart = ((Date) regularUsers.get(0)); dataset.addValue((Long) regularUsers.get(1), "5+", formatter.format(weekStart)); dataset.addValue((Long) regularUsers.get(2), "4", formatter.format(weekStart)); dataset.addValue((Long) regularUsers.get(3), "3", formatter.format(weekStart)); dataset.addValue((Long) regularUsers.get(4), "2", formatter.format(weekStart)); dataset.addValue((Long) regularUsers.get(5), "1", formatter.format(weekStart)); } return dataset; } private BoxAndWhiskerCategoryDataset getHourlyUsageDataSet() { // log.info("Generating activityWeekBarDataSet"); List<ServerWideStatsRecord> hourlyUsagePattern = getHourlyUsagePattern(); if (hourlyUsagePattern == null) { return null; } DefaultBoxAndWhiskerCategoryDataset dataset = new DefaultBoxAndWhiskerCategoryDataset(); List[] hourList = new ArrayList[24]; for (int ii = 0; ii < 24; ii++) { hourList[ii] = new ArrayList(); } int totalDays = 0; Date prevDate = null; for (ServerWideStatsRecord regularUsers : hourlyUsagePattern) { Date currDate = (Date) regularUsers.get(0); if (!currDate.equals(prevDate)) { prevDate = currDate; totalDays++; } hourList[(Integer) regularUsers.get(1)].add((Long) regularUsers.get(2)); } for (int ii = 0; ii < 24; ii++) { // add zero counts, when no data for the day for (int jj = hourList[ii].size(); jj < totalDays; jj++) { hourList[ii].add(Long.valueOf(0)); } dataset.add(hourList[ii], "Last 30 days", "" + ii); } return dataset; } private CategoryDataset getTopActivitiesDataSet() { List<ServerWideStatsRecord> topActivitiesList = getTop20Activities(); if (topActivitiesList == null) { return null; } DefaultCategoryDataset dataset = new DefaultCategoryDataset(); for (ServerWideStatsRecord regularUsers : topActivitiesList) { String event = (String) regularUsers.get(0); dataset.addValue((Double) regularUsers.get(1), "last 7 days", event); dataset.addValue((Double) regularUsers.get(2), "last 30 days", event); dataset.addValue((Double) regularUsers.get(3), "last 365 days", event); } return dataset; } private CategoryDataset getToolAnalysisDataSet() { List<ServerWideStatsRecord> toolCountList = getToolCount(); if (toolCountList == null) { return null; } DefaultCategoryDataset dataset = new DefaultCategoryDataset(); for (ServerWideStatsRecord regularUsers : toolCountList) { String toolId = (String) regularUsers.get(0); dataset.addValue((Integer) regularUsers.get(1), "", toolId); } return dataset; } private byte[] createMonthlyLoginChart(int width, int height) { IntervalXYDataset dataset1 = getMonthlyLoginsDataSet(); IntervalXYDataset dataset3 = getMonthlySiteUserDataSet(); if ((dataset1 == null) || (dataset3 == null)) { return generateNoDataChart(width, height); } // create plot ... XYItemRenderer renderer1 = new XYLineAndShapeRenderer(true, false); renderer1.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer1.setSeriesPaint(0, Color.RED); DateAxis domainAxis = new DateAxis(""); domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.MONTH, 1, new SimpleDateFormat("yyyy-MM"))); domainAxis.setTickMarkPosition(DateTickMarkPosition.START); domainAxis.setVerticalTickLabels(true); domainAxis.setLowerMargin(0.01); domainAxis.setUpperMargin(0.01); NumberAxis axis1 = new NumberAxis("Total Logins"); axis1.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); axis1.setLabelPaint(Color.RED); axis1.setTickLabelPaint(Color.RED); XYPlot plot1 = new XYPlot(dataset1, null, axis1, renderer1); plot1.setBackgroundPaint(Color.lightGray); plot1.setDomainGridlinePaint(Color.white); plot1.setRangeGridlinePaint(Color.white); // AXIS 2 /* NumberAxis axis2 = new NumberAxis("Total Unique Users"); axis2.setStandardTickUnits (NumberAxis.createIntegerTickUnits ()); axis2.setLabelPaint(Color.BLUE); axis2.setTickLabelPaint(Color.BLUE); plot1.setRangeAxis(1, axis2); plot1.setDataset(1, dataset2); plot1.mapDatasetToRangeAxis(1, 1); XYItemRenderer renderer2 = new XYLineAndShapeRenderer(true, false); renderer2.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesPaint (0, Color.BLUE); plot1.setRenderer(1, renderer2); */ // add a third dataset and renderer... XYItemRenderer renderer3 = new XYLineAndShapeRenderer(true, false); renderer3.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer3.setSeriesStroke(1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer3.setSeriesStroke(2, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer3.setSeriesPaint(0, Color.GREEN); renderer3.setSeriesPaint(1, Color.BLACK); renderer3.setSeriesPaint(2, Color.CYAN); axis1 = new NumberAxis("count"); axis1.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYPlot plot2 = new XYPlot(dataset3, null, axis1, renderer3); plot2.setBackgroundPaint(Color.lightGray); plot2.setDomainGridlinePaint(Color.white); plot2.setRangeGridlinePaint(Color.white); CombinedDomainXYPlot cplot = new CombinedDomainXYPlot(domainAxis); cplot.add(plot1, 3); cplot.add(plot2, 2); cplot.setGap(8.0); cplot.setDomainGridlinePaint(Color.white); cplot.setDomainGridlinesVisible(true); // return a new chart containing the overlaid plot... JFreeChart chart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, cplot, false); LegendTitle legend = new LegendTitle(cplot); chart.addSubtitle(legend); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] createWeeklyLoginChart(int width, int height) { IntervalXYDataset dataset1 = getWeeklyLoginsDataSet(); IntervalXYDataset dataset2 = getWeeklySiteUserDataSet(); if ((dataset1 == null) || (dataset2 == null)) { return generateNoDataChart(width, height); } // create plot ... XYItemRenderer renderer1 = new XYLineAndShapeRenderer(true, false); renderer1.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer1.setSeriesStroke(1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer1.setSeriesPaint(0, Color.RED); renderer1.setSeriesPaint(0, Color.BLUE); DateAxis domainAxis = new DateAxis(""); domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 7, new SimpleDateFormat("yyyy-MM-dd"))); domainAxis.setTickMarkPosition(DateTickMarkPosition.START); domainAxis.setVerticalTickLabels(true); domainAxis.setLowerMargin(0.01); domainAxis.setUpperMargin(0.01); NumberAxis rangeAxis = new NumberAxis("count"); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYPlot plot1 = new XYPlot(dataset1, null, rangeAxis, renderer1); plot1.setBackgroundPaint(Color.lightGray); plot1.setDomainGridlinePaint(Color.white); plot1.setRangeGridlinePaint(Color.white); // add a second dataset and renderer... XYItemRenderer renderer2 = new XYLineAndShapeRenderer(true, false); renderer2.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesStroke(1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesStroke(2, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesPaint(0, Color.GREEN); renderer2.setSeriesPaint(1, Color.BLACK); renderer2.setSeriesPaint(2, Color.CYAN); rangeAxis = new NumberAxis("count"); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYPlot plot2 = new XYPlot(dataset2, null, rangeAxis, renderer2); plot2.setBackgroundPaint(Color.lightGray); plot2.setDomainGridlinePaint(Color.white); plot2.setRangeGridlinePaint(Color.white); CombinedDomainXYPlot cplot = new CombinedDomainXYPlot(domainAxis); cplot.add(plot1, 3); cplot.add(plot2, 2); cplot.setGap(8.0); cplot.setDomainGridlinePaint(Color.white); cplot.setDomainGridlinesVisible(true); // return a new chart containing the overlaid plot... JFreeChart chart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, cplot, false); LegendTitle legend = new LegendTitle(cplot); chart.addSubtitle(legend); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] createDailyLoginChart(int width, int height) { IntervalXYDataset dataset1 = getDailyLoginsDataSet(); IntervalXYDataset dataset2 = getDailySiteUserDataSet(); if ((dataset1 == null) || (dataset2 == null)) { return generateNoDataChart(width, height); } // create plot ... XYItemRenderer renderer1 = new XYLineAndShapeRenderer(true, false); renderer1.setSeriesPaint(0, Color.RED); renderer1.setSeriesPaint(1, Color.BLUE); renderer1.setSeriesPaint(2, Color.RED); renderer1.setSeriesPaint(3, Color.BLUE); renderer1.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer1.setSeriesStroke(1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); BasicStroke dashLineStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 0, new float[] { 4 }, 0); renderer1.setSeriesStroke(2, dashLineStroke); renderer1.setSeriesStroke(3, dashLineStroke); DateAxis domainAxis = new DateAxis(""); domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 7, new SimpleDateFormat("yyyy-MM-dd"))); domainAxis.setTickMarkPosition(DateTickMarkPosition.START); domainAxis.setVerticalTickLabels(true); domainAxis.setLowerMargin(0.01); domainAxis.setUpperMargin(0.01); NumberAxis rangeAxis = new NumberAxis("count"); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYPlot plot1 = new XYPlot(dataset1, null, rangeAxis, renderer1); plot1.setBackgroundPaint(Color.lightGray); plot1.setDomainGridlinePaint(Color.white); plot1.setRangeGridlinePaint(Color.white); // add a second dataset and renderer... XYItemRenderer renderer2 = new XYLineAndShapeRenderer(true, false); renderer2.setSeriesStroke(0, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesStroke(1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesStroke(2, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)); renderer2.setSeriesPaint(0, Color.GREEN); renderer2.setSeriesPaint(1, Color.BLACK); renderer2.setSeriesPaint(2, Color.CYAN); rangeAxis = new NumberAxis("count"); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); XYPlot plot2 = new XYPlot(dataset2, null, rangeAxis, renderer2); plot2.setBackgroundPaint(Color.lightGray); plot2.setDomainGridlinePaint(Color.white); plot2.setRangeGridlinePaint(Color.white); CombinedDomainXYPlot cplot = new CombinedDomainXYPlot(domainAxis); cplot.add(plot1, 3); cplot.add(plot2, 2); cplot.setGap(8.0); cplot.setDomainGridlinePaint(Color.white); cplot.setDomainGridlinesVisible(true); // return a new chart containing the overlaid plot... JFreeChart chart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, cplot, false); LegendTitle legend = new LegendTitle(cplot); chart.addSubtitle(legend); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateStackedAreaChart(CategoryDataset dataset, int width, int height) { JFreeChart chart = ChartFactory.createStackedAreaChart(null, // chart title null, // domain axis label null, // range axis label dataset, // data PlotOrientation.VERTICAL, // the plot orientation true, // legend true, // tooltips false // urls ); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); CategoryPlot plot = (CategoryPlot) chart.getPlot(); // set transparency plot.setForegroundAlpha(0.7f); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinesVisible(true); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinesVisible(true); plot.setRangeGridlinePaint(Color.white); // set colour of regular users using Karate belt colour: white, green, blue, brown, black/gold CategoryItemRenderer renderer = plot.getRenderer(); renderer.setSeriesPaint(0, new Color(205, 173, 0)); // gold users renderer.setSeriesPaint(1, new Color(139, 69, 19)); renderer.setSeriesPaint(2, Color.BLUE); renderer.setSeriesPaint(3, Color.GREEN); renderer.setSeriesPaint(4, Color.WHITE); // set the range axis to display integers only... NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); CategoryAxis domainAxis = (CategoryAxis) plot.getDomainAxis(); domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45); domainAxis.setLowerMargin(0.0); domainAxis.setUpperMargin(0.0); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateBoxAndWhiskerChart(BoxAndWhiskerCategoryDataset dataset, int width, int height) { JFreeChart chart = ChartFactory.createBoxAndWhiskerChart(null, null, null, dataset, false); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setDomainGridlinePaint(Color.white); plot.setDomainGridlinesVisible(true); plot.setRangeGridlinePaint(Color.white); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); CategoryAxis domainAxis = (CategoryAxis) plot.getDomainAxis(); domainAxis.setLowerMargin(0.0); domainAxis.setUpperMargin(0.0); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateLayeredBarChart(CategoryDataset dataset, int width, int height) { JFreeChart chart = ChartFactory.createBarChart(null, // chart title null, // domain axis label null, // range axis label dataset, // data PlotOrientation.VERTICAL, // the plot orientation true, // legend true, // tooltips false // urls ); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); CategoryPlot plot = (CategoryPlot) chart.getPlot(); // disable bar outlines... LayeredBarRenderer renderer = new LayeredBarRenderer(); renderer.setDrawBarOutline(false); renderer.setSeriesBarWidth(0, .6); renderer.setSeriesBarWidth(1, .8); renderer.setSeriesBarWidth(2, 1.0); plot.setRenderer(renderer); // for this renderer, we need to draw the first series last... plot.setRowRenderingOrder(SortOrder.DESCENDING); // set up gradient paints for series... GradientPaint gp0 = new GradientPaint(0.0f, 0.0f, Color.blue, 0.0f, 0.0f, new Color(0, 0, 64)); GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.green, 0.0f, 0.0f, new Color(0, 64, 0)); GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.red, 0.0f, 0.0f, new Color(64, 0, 0)); renderer.setSeriesPaint(0, gp0); renderer.setSeriesPaint(1, gp1); renderer.setSeriesPaint(2, gp2); CategoryAxis domainAxis = (CategoryAxis) plot.getDomainAxis(); domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45); domainAxis.setLowerMargin(0.0); domainAxis.setUpperMargin(0.0); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] createToolAnalysisChart(int width, int height) { CategoryDataset dataset = getToolAnalysisDataSet(); if (dataset == null) { return generateNoDataChart(width, height); } JFreeChart chart = ChartFactory.createBarChart(null, // chart title null, // domain axis label null, // range axis label dataset, // data PlotOrientation.HORIZONTAL, // the plot orientation false, // legend false, // tooltips false // urls ); // set background chart.setBackgroundPaint(parseColor(statsManager.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set anti alias chart.setAntiAlias(true); CategoryPlot plot = (CategoryPlot) chart.getPlot(); // set transparency plot.setForegroundAlpha(0.7f); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinesVisible(false); plot.setRangeGridlinesVisible(true); plot.setRangeGridlinePaint(Color.white); CategoryAxis domainAxis = plot.getDomainAxis(); domainAxis.setVisible(false); domainAxis.setUpperMargin(0); domainAxis.setLowerMargin(0); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setUpperMargin(0.20); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); BarRenderer renderer = (BarRenderer) plot.getRenderer(); CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator("{1}", NumberFormat.getInstance(new ResourceLoader().getLocale())); renderer.setBaseItemLabelGenerator(generator); renderer.setBaseItemLabelFont(new Font("SansSerif", Font.PLAIN, 9)); renderer.setBaseItemLabelsVisible(true); renderer.setItemMargin(0); renderer.setSeriesPaint(0, Color.BLUE); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateNoDataChart(int width, int height) { BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = img.createGraphics(); g2d.setBackground(parseColor(statsManager.getChartBackgroundColor())); g2d.clearRect(0, 0, width - 1, height - 1); g2d.setColor(parseColor("#cccccc")); g2d.drawRect(0, 0, width - 1, height - 1); Font f = new Font("SansSerif", Font.PLAIN, 12); g2d.setFont(f); FontMetrics fm = g2d.getFontMetrics(f); String noData = msgs.getString("no_data"); int noDataWidth = fm.stringWidth(noData); int noDataHeight = fm.getHeight(); g2d.setColor(parseColor("#555555")); g2d.drawString(noData, width / 2 - noDataWidth / 2, height / 2 - noDataHeight / 2 + 2); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { log.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } public static Color parseColor(String color) { if (color != null) { if (color.trim().startsWith("#")) { // HTML colors (#FFFFFF format) return new Color(Integer.parseInt(color.substring(1), 16)); } else if (color.trim().startsWith("rgb")) { // HTML colors (rgb(255, 255, 255) format) String values = color.substring(color.indexOf("(") + 1, color.indexOf(")")); String rgb[] = values.split(","); return new Color(Integer.parseInt(rgb[0].trim()), Integer.parseInt(rgb[1].trim()), Integer.parseInt(rgb[2].trim())); } else { // Colors by name if (color.equalsIgnoreCase("black")) return Color.black; if (color.equalsIgnoreCase("grey")) return Color.gray; if (color.equalsIgnoreCase("yellow")) return Color.yellow; if (color.equalsIgnoreCase("green")) return Color.green; if (color.equalsIgnoreCase("blue")) return Color.blue; if (color.equalsIgnoreCase("red")) return Color.red; if (color.equalsIgnoreCase("orange")) return Color.orange; if (color.equalsIgnoreCase("cyan")) return Color.cyan; if (color.equalsIgnoreCase("magenta")) return Color.magenta; if (color.equalsIgnoreCase("darkgray")) return Color.darkGray; if (color.equalsIgnoreCase("lightgray")) return Color.lightGray; if (color.equalsIgnoreCase("pink")) return Color.pink; if (color.equalsIgnoreCase("white")) return Color.white; } } log.info("Unable to parse body background-color (color:" + color + "). Assuming white."); return Color.white; } /** * Helper method to return the appropriate SQL for the DB vendor * Everything should be lowercase. * @return */ private String getSqlForVendor(String mysql, String oracle) { if (StringUtils.equals(dbVendor, "mysql")) { return mysql; } if (StringUtils.equals(dbVendor, "oracle")) { return oracle; } return null; } /** * Helper to get the externalDbName as a prefix to be used directly in queries, . is appended * If its not configured, then an empty string is returned so that whatever this returns can be used as-is * @return */ private String getExternalDbNameAsPrefix() { if (StringUtils.isNotBlank(externalDbName)) { return externalDbName + "."; } else { return ""; } } }