commit b415e8d0cf55993d2c600b4dd51cfe6c4d1b0830 Author: Karsten Loesing karsten.loesing@gmx.net Date: Sat Oct 20 16:39:23 2012 -0400
Add graph download links for PDF and SVG.
Implements #7050. --- etc/web.xml | 87 ++++++++------------ .../torproject/ernie/web/GraphImageServlet.java | 16 ++-- src/org/torproject/ernie/web/RObjectGenerator.java | 15 +++- web/WEB-INF/fast-exits.jsp | 6 ++ web/WEB-INF/network.jsp | 30 +++++++ web/WEB-INF/performance.jsp | 9 ++ web/WEB-INF/users.jsp | 6 ++ 7 files changed, 108 insertions(+), 61 deletions(-)
diff --git a/etc/web.xml b/etc/web.xml index ccf6dd2..903f23d 100644 --- a/etc/web.xml +++ b/etc/web.xml @@ -158,74 +158,59 @@ <servlet-mapping> <servlet-name>GraphImage</servlet-name> <url-pattern>/networksize.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/networksize.pdf</url-pattern> + <url-pattern>/networksize.svg</url-pattern> <url-pattern>/cloudbridges.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/cloudbridges.pdf</url-pattern> + <url-pattern>/cloudbridges.svg</url-pattern> <url-pattern>/relaycountries.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/relaycountries.pdf</url-pattern> + <url-pattern>/relaycountries.svg</url-pattern> <url-pattern>/relayflags.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/relayflags.pdf</url-pattern> + <url-pattern>/relayflags.svg</url-pattern> <url-pattern>/relayflags-hour.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/relayflags-hour.pdf</url-pattern> + <url-pattern>/relayflags-hour.svg</url-pattern> <url-pattern>/versions.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/versions.pdf</url-pattern> + <url-pattern>/versions.svg</url-pattern> <url-pattern>/platforms.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/platforms.pdf</url-pattern> + <url-pattern>/platforms.svg</url-pattern> <url-pattern>/bandwidth.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/bandwidth.pdf</url-pattern> + <url-pattern>/bandwidth.svg</url-pattern> <url-pattern>/bwhist-flags.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/bwhist-flags.pdf</url-pattern> + <url-pattern>/bwhist-flags.svg</url-pattern> <url-pattern>/bandwidth-flags.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/bandwidth-flags.pdf</url-pattern> + <url-pattern>/bandwidth-flags.svg</url-pattern> <url-pattern>/dirbytes.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/dirbytes.pdf</url-pattern> + <url-pattern>/dirbytes.svg</url-pattern> <url-pattern>/direct-users.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/direct-users.pdf</url-pattern> + <url-pattern>/direct-users.svg</url-pattern> <url-pattern>/bridge-users.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/bridge-users.pdf</url-pattern> + <url-pattern>/bridge-users.svg</url-pattern> <url-pattern>/torperf.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/torperf.pdf</url-pattern> + <url-pattern>/torperf.svg</url-pattern> <url-pattern>/torperf-failures.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/torperf-failures.pdf</url-pattern> + <url-pattern>/torperf-failures.svg</url-pattern> <url-pattern>/connbidirect.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/connbidirect.pdf</url-pattern> + <url-pattern>/connbidirect.svg</url-pattern> <url-pattern>/fast-exits.png</url-pattern> - </servlet-mapping> - <servlet-mapping> - <servlet-name>GraphImage</servlet-name> + <url-pattern>/fast-exits.pdf</url-pattern> + <url-pattern>/fast-exits.svg</url-pattern> <url-pattern>/almost-fast-exits.png</url-pattern> + <url-pattern>/almost-fast-exits.pdf</url-pattern> + <url-pattern>/almost-fast-exits.svg</url-pattern> </servlet-mapping>
<servlet> diff --git a/src/org/torproject/ernie/web/GraphImageServlet.java b/src/org/torproject/ernie/web/GraphImageServlet.java index 5777172..ea24d44 100644 --- a/src/org/torproject/ernie/web/GraphImageServlet.java +++ b/src/org/torproject/ernie/web/GraphImageServlet.java @@ -34,11 +34,15 @@ public class GraphImageServlet extends HttpServlet { ServletException {
/* Find out which graph type was requested and make sure we know this - * graph type. */ + * graph type and file type. */ String requestedGraph = request.getRequestURI(); - if (requestedGraph.endsWith(".png")) { + String fileType = null; + if (requestedGraph.endsWith(".png") || + requestedGraph.endsWith(".pdf") || + requestedGraph.endsWith(".svg")) { + fileType = requestedGraph.substring(requestedGraph.length() - 3); requestedGraph = requestedGraph.substring(0, requestedGraph.length() - - ".png".length()); + - 4); } if (requestedGraph.contains("/")) { requestedGraph = requestedGraph.substring(requestedGraph. @@ -48,17 +52,17 @@ public class GraphImageServlet extends HttpServlet { /* Request graph from R object generator, which either returns it from * its cache or asks Rserve to generate it. */ RObject graph = rObjectGenerator.generateGraph(requestedGraph, - request.getParameterMap(), true); + fileType, request.getParameterMap(), true);
/* Make sure that we have a graph to return. */ - if (graph == null || graph.getBytes() == null) { + if (graph == null || graph.getBytes() == null || fileType == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; }
/* Write graph bytes to response. */ BufferedOutputStream output = null; - response.setContentType("image/png"); + response.setContentType("image/" + fileType); response.setHeader("Content-Length", String.valueOf(graph.getBytes().length)); response.setHeader("Content-Disposition", diff --git a/src/org/torproject/ernie/web/RObjectGenerator.java b/src/org/torproject/ernie/web/RObjectGenerator.java index b964958..c599807 100644 --- a/src/org/torproject/ernie/web/RObjectGenerator.java +++ b/src/org/torproject/ernie/web/RObjectGenerator.java @@ -13,8 +13,10 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet;
@@ -38,6 +40,7 @@ public class RObjectGenerator implements ServletContextListener { private SortedSet<String> availableCsvFiles; private Map<String, String> availableTables; private Map<String, String> availableGraphs; + private Set<String> availableGraphFileTypes;
public void contextInitialized(ServletContextEvent event) {
@@ -104,6 +107,8 @@ public class RObjectGenerator implements ServletContextListener { this.availableGraphs.put("fast-exits", "start,end,filename,dpi"); this.availableGraphs.put("almost-fast-exits", "start,end,filename,dpi"); + this.availableGraphFileTypes = new HashSet<String>(Arrays.asList( + "png,pdf,svg".split(","))); GraphParameterChecker.getInstance().setAvailableGraphs( availableGraphs);
@@ -129,7 +134,9 @@ public class RObjectGenerator implements ServletContextListener { generateTable(tableName, tableName, new HashMap(), false); } for (String graphName : availableGraphs.keySet()) { - generateGraph(graphName, new HashMap(), false); + for (String fileType : availableGraphFileTypes) { + generateGraph(graphName, fileType, new HashMap(), false); + } } lastUpdated = System.currentTimeMillis(); } @@ -141,8 +148,8 @@ public class RObjectGenerator implements ServletContextListener { /* Nothing to do. */ }
- public RObject generateGraph(String requestedGraph, Map parameterMap, - boolean checkCache) { + public RObject generateGraph(String requestedGraph, String fileType, + Map parameterMap, boolean checkCache) { Map<String, String[]> checkedParameters = GraphParameterChecker. getInstance().checkParameters(requestedGraph, parameterMap); if (checkedParameters == null) { @@ -172,7 +179,7 @@ public class RObjectGenerator implements ServletContextListener { parameterValues.length - 1] + "'), "); } } - imageFilenameBuilder.append(".png"); + imageFilenameBuilder.append("." + fileType); String imageFilename = imageFilenameBuilder.toString(); rQueryBuilder.append("path = '%s')"); String rQuery = rQueryBuilder.toString(); diff --git a/web/WEB-INF/fast-exits.jsp b/web/WEB-INF/fast-exits.jsp index c542a01..d97c8a4 100644 --- a/web/WEB-INF/fast-exits.jsp +++ b/web/WEB-INF/fast-exits.jsp @@ -47,6 +47,9 @@ requirements</a></h3> </p> </div> </form> +<p>Download graph as +<a href="fast-exits.pdf${fast_exits_url}">PDF</a> or +<a href="fast-exits.svg${fast_exits_url}">SVG</a>.</p> <br>
<a name="almostfastexits"></a> @@ -76,6 +79,9 @@ fast-exit requirements</a></h3> </p> </div> </form> +<p>Download graph as +<a href="almost-fast-exits.pdf${almost_fast_exits_url}">PDF</a> or +<a href="almost-fast-exits.svg${almost_fast_exits_url}">SVG</a>.</p> <br>
</div> diff --git a/web/WEB-INF/network.jsp b/web/WEB-INF/network.jsp index d73f672..53ed715 100644 --- a/web/WEB-INF/network.jsp +++ b/web/WEB-INF/network.jsp @@ -52,6 +52,9 @@ bridges in the network.</p> </p> </div> </form> +<p>Download graph as +<a href="networksize.pdf${networksize_url}">PDF</a> or +<a href="networksize.svg${networksize_url}">SVG</a>.</p> <p><a href="csv/networksize.csv">CSV</a> file containing all data.</p> <br>
@@ -90,6 +93,9 @@ country.</p> </p> </div> </form> +<p>Download graph as +<a href="relaycountries.pdf${relaycountries_url}">PDF</a> or +<a href="relaycountries.svg${relaycountries_url}">SVG</a>.</p> <p><a href="csv/relaycountries.csv">CSV</a> file containing all data.</p> <br>
@@ -134,6 +140,9 @@ average number of relays with these flags assigned.</p> </p> </div> </form> +<p>Download graph as +<a href="relayflags.pdf${relayflags_url}">PDF</a> or +<a href="relayflags.svg${relayflags_url}">SVG</a>.</p> <p><a href="csv/relayflags.csv">CSV</a> file containing all data.</p> <br>
@@ -170,6 +179,9 @@ The following graph shows the number of relays by version.</p> </p> </div> </form> +<p>Download graph as +<a href="versions.pdf${versions_url}">PDF</a> or +<a href="versions.svg${versions_url}">SVG</a>.</p> <p><a href="csv/versions.csv">CSV</a> file containing all data.</p> <br>
@@ -202,6 +214,9 @@ platform.</p> </p> </div> </form> +<p>Download graph as +<a href="platforms.pdf${platforms_url}">PDF</a> or +<a href="platforms.svg${platforms_url}">SVG</a>.</p> <p><a href="csv/platforms.csv">CSV</a> file containing all data.</p> <br>
@@ -234,6 +249,9 @@ network.</p> </p> </div> </form> +<p>Download graph as +<a href="cloudbridges.pdf${cloudbridges_url}">PDF</a> or +<a href="cloudbridges.svg${cloudbridges_url}">SVG</a>.</p> <p><a href="csv/cloudbridges.csv">CSV</a> file containing all data.</p> <br>
@@ -268,6 +286,9 @@ in the network.</p> </p> </div> </form> +<p>Download graph as +<a href="bandwidth.pdf${bandwidth_url}">PDF</a> or +<a href="bandwidth.svg${bandwidth_url}">SVG</a>.</p> <p><a href="csv/bandwidth.csv">CSV</a> file containing all data.</p> <br>
@@ -300,6 +321,9 @@ Exit and/or Guard flags assigned by the directory authorities.</p> </p> </div> </form> +<p>Download graph as +<a href="bwhist-flags.pdf${bwhist_flags_url}">PDF</a> or +<a href="bwhist-flags.svg${bwhist_flags_url}">SVG</a>.</p> <p><a href="csv/bwhist-flags.csv">CSV</a> file containing all data.</p> <br>
@@ -335,6 +359,9 @@ Guard flag.</p> </p> </div> </form> +<p>Download graph as +<a href="bandwidth-flags.pdf${bandwidth_flags_url}">PDF</a> or +<a href="bandwidth-flags.svg${bandwidth_flags_url}">SVG</a>.</p> <p><a href="csv/bandwidth-flags.csv">CSV</a> file containing all data.</p> <br>
@@ -370,6 +397,9 @@ the number of written and read dir bytes by all relays.</p> </p> </div> </form> +<p>Download graph as +<a href="dirbytes.pdf${dirbytes_url}">PDF</a> or +<a href="dirbytes.svg${dirbytes_url}">SVG</a>.</p> <p><a href="csv/dirbytes.csv">CSV</a> file containing all data.</p> <br> </div> diff --git a/web/WEB-INF/performance.jsp b/web/WEB-INF/performance.jsp index 5f25b8a..e6caf8e 100644 --- a/web/WEB-INF/performance.jsp +++ b/web/WEB-INF/performance.jsp @@ -59,6 +59,9 @@ graph.</p> </p> </div> </form> +<p>Download graph as +<a href="torperf.pdf${torperf_url}">PDF</a> or +<a href="torperf.svg${torperf_url}">SVG</a>.</p> <p><a href="csv/torperf.csv">CSV</a> file containing all data.</p>
<br> @@ -106,6 +109,9 @@ than 50 KiB (1 MiB, 5 MiB).</p> </p> </div> </form> +<p>Download graph as +<a href="torperf-failures.pdf${torperf_failures_url}">PDF</a> or +<a href="torperf-failures.svg${torperf_failures_url}">SVG</a>.</p> <p><a href="csv/torperf-failures.csv">CSV</a> file containing all data.</p>
<br> @@ -147,6 +153,9 @@ classifying connections, read and write counters are reset for the next </p> </div> </form> +<p>Download graph as +<a href="connbidirect.pdf${connbidirect_url}">PDF</a> or +<a href="connbidirect.svg${connbidirect_url}">SVG</a>.</p> <p><a href="csv/connbidirect.csv">CSV</a> file containing all data.</p> <br>
diff --git a/web/WEB-INF/users.jsp b/web/WEB-INF/users.jsp index f422123..3ef211b 100644 --- a/web/WEB-INF/users.jsp +++ b/web/WEB-INF/users.jsp @@ -64,6 +64,9 @@ based on the requests seen by a few dozen directory mirrors.</p> </p> </div> </form> +<p>Download graph as +<a href="direct-users.pdf${direct_users_url}">PDF</a> or +<a href="direct-users.svg${direct_users_url}">SVG</a>.</p> <hr> <a name="direct-users-table"></a> <p><b>Top-10 countries by directly connecting users:</b></p> @@ -175,6 +178,9 @@ by a few hundred bridges.</p> </p> </div> </form> +<p>Download graph as +<a href="bridge-users.pdf${bridge_users_url}">PDF</a> or +<a href="bridge-users.svg${bridge_users_url}">SVG</a>.</p> <hr> <p><a href="csv/bridge-users.csv">CSV</a> file containing all data.</p> <p><a href="csv/monthly-users-peak.csv">CSV</a> file containing peak daily