KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > junit > viewer > server > ReportImageServer


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.junit.viewer.server;
17
18 import com.google.gwt.junit.viewer.client.Benchmark;
19 import com.google.gwt.junit.viewer.client.BrowserInfo;
20 import com.google.gwt.junit.viewer.client.Category;
21 import com.google.gwt.junit.viewer.client.Report;
22 import com.google.gwt.junit.viewer.client.Result;
23 import com.google.gwt.junit.viewer.client.Trial;
24
25 import org.jfree.chart.ChartFactory;
26 import org.jfree.chart.JFreeChart;
27 import org.jfree.chart.encoders.EncoderUtil;
28 import org.jfree.chart.encoders.ImageFormat;
29 import org.jfree.chart.plot.PlotOrientation;
30 import org.jfree.data.category.DefaultCategoryDataset;
31 import org.jfree.data.xy.XYSeries;
32 import org.jfree.data.xy.XYSeriesCollection;
33
34 import java.awt.Font JavaDoc;
35 import java.awt.image.BufferedImage JavaDoc;
36 import java.io.ByteArrayInputStream JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.InputStream JavaDoc;
39 import java.io.OutputStream JavaDoc;
40 import java.net.URLDecoder JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.Iterator JavaDoc;
44 import java.util.List JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.Set JavaDoc;
47 import java.util.TreeMap JavaDoc;
48 import java.util.TreeSet JavaDoc;
49
50 import javax.servlet.ServletException JavaDoc;
51 import javax.servlet.http.HttpServlet JavaDoc;
52 import javax.servlet.http.HttpServletRequest JavaDoc;
53 import javax.servlet.http.HttpServletResponse JavaDoc;
54
55 /**
56  * Serves up report images for the ReportViewer application. Generates the
57  * charts/graphs which contain the benchmarking data for a report.
58  *
59  * <p>
60  * This servlet requires the name of the report file, the category, the
61  * benchmark class, the test method, and the browser agent.
62  * <p>
63  *
64  * <p>
65  * An Example URI:
66  *
67  * <pre>
68  * /com.google.gwt.junit.viewer.ReportViewer/test_images/
69  * report-12345.xml/
70  * RemoveCategory/
71  * com.google.gwt.junit.client.ArrayListAndVectorBenchmark/
72  * testArrayListRemoves/
73  * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050920/
74  * </pre>
75  *
76  * </p>
77  */

78 public class ReportImageServer extends HttpServlet JavaDoc {
79
80   private static final String JavaDoc charset = "UTF-8";
81
82   private static void copy(InputStream JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc {
83     byte[] buf = new byte[512];
84
85     while (true) {
86       int bytesRead = in.read(buf);
87       if (bytesRead == -1) {
88         break;
89       }
90       out.write(buf, 0, bytesRead);
91     }
92   }
93
94   private JFreeChart createChart(String JavaDoc testName, Result result, String JavaDoc title) {
95
96     // Display the trial data - we might need meta information from the result
97
// that tells us how many total variables there are, what types they are of,
98
// etc....
99
List JavaDoc trials = result.getTrials();
100     Trial firstTrial = (Trial) trials.get(0);
101
102     // Pick the domain and series variables for our graph.
103
// Right now we only handle up to two "user" variables.
104
// We set the domain variable to the be the one containing the most unique
105
// values.
106
int numVariables = firstTrial.getVariables().size();
107
108     String JavaDoc domainVariable = null;
109     String JavaDoc seriesVariable = null;
110
111     Map JavaDoc/* <String,Set<String>> */variableValues = null;
112
113     if (numVariables == 1) {
114       domainVariable = (String JavaDoc) firstTrial.getVariables().keySet().iterator().next();
115     } else {
116       // TODO(tobyr): Do something smarter, like allow the user to specify which
117
// variables
118
// are domain and series, along with the variables which are held
119
// constant.
120

121       variableValues = new HashMap JavaDoc();
122
123       for (int i = 0; i < trials.size(); ++i) {
124         Trial trial = (Trial) trials.get(i);
125         Map JavaDoc variables = trial.getVariables();
126
127         for (Iterator JavaDoc it = variables.entrySet().iterator(); it.hasNext();) {
128           Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
129           String JavaDoc variable = (String JavaDoc) entry.getKey();
130           String JavaDoc value = (String JavaDoc) entry.getValue();
131           Set JavaDoc set = (Set JavaDoc) variableValues.get(variable);
132           if (set == null) {
133             set = new TreeSet JavaDoc();
134             variableValues.put(variable, set);
135           }
136           set.add(value);
137         }
138       }
139
140       TreeMap JavaDoc numValuesMap = new TreeMap JavaDoc();
141
142       for (Iterator JavaDoc it = variableValues.entrySet().iterator(); it.hasNext();) {
143         Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
144         String JavaDoc variable = (String JavaDoc) entry.getKey();
145         Set JavaDoc values = (Set JavaDoc) entry.getValue();
146         Integer JavaDoc numValues = new Integer JavaDoc(values.size());
147         List JavaDoc variables = (List JavaDoc) numValuesMap.get(numValues);
148         if (variables == null) {
149           variables = new ArrayList JavaDoc();
150           numValuesMap.put(numValues, variables);
151         }
152         variables.add(variable);
153       }
154
155       if (numValuesMap.values().size() > 0) {
156         domainVariable = (String JavaDoc) ((List JavaDoc) numValuesMap.get(numValuesMap.lastKey())).get(0);
157         seriesVariable = (String JavaDoc) ((List JavaDoc) numValuesMap.get(numValuesMap.firstKey())).get(0);
158       }
159     }
160
161     String JavaDoc valueTitle = "time (ms)"; // This axis is time across all charts.
162

163     if (numVariables == 0) {
164       // Show a bar graph, with a single centered simple bar
165
// 0 variables means there is only 1 trial
166
Trial trial = (Trial) trials.iterator().next();
167
168       DefaultCategoryDataset data = new DefaultCategoryDataset();
169       data.addValue(trial.getRunTimeMillis(), "result", "result");
170
171       return ChartFactory.createBarChart(title, testName, valueTitle, data,
172           PlotOrientation.VERTICAL, false, false, false);
173     } else if (numVariables == 1) {
174
175       // Show a line graph with only 1 series
176
// Or.... choose between a line graph and a bar graph depending upon
177
// whether the
178
// type of the domain is numeric.
179

180       XYSeriesCollection data = new XYSeriesCollection();
181
182       XYSeries series = new XYSeries(domainVariable);
183
184       for (Iterator JavaDoc it = trials.iterator(); it.hasNext();) {
185         Trial trial = (Trial) it.next();
186         if (trial.getException() != null) {
187           continue;
188         }
189         double time = trial.getRunTimeMillis();
190         String JavaDoc domainValue = (String JavaDoc) trial.getVariables().get(domainVariable);
191         series.add(Double.parseDouble(domainValue), time);
192       }
193
194       data.addSeries(series);
195
196       return ChartFactory.createXYLineChart(title, domainVariable, valueTitle,
197           data, PlotOrientation.VERTICAL, false, false, false);
198     } else if (numVariables == 2) {
199       // Show a line graph with multiple series
200
XYSeriesCollection data = new XYSeriesCollection();
201
202       Set JavaDoc seriesValues = (Set JavaDoc) variableValues.get(seriesVariable);
203
204       for (Iterator JavaDoc it = seriesValues.iterator(); it.hasNext();) {
205         String JavaDoc seriesValue = (String JavaDoc) it.next();
206         XYSeries series = new XYSeries(seriesValue);
207
208         for (Iterator JavaDoc trialsIt = trials.iterator(); trialsIt.hasNext();) {
209           Trial trial = (Trial) trialsIt.next();
210           if (trial.getException() != null) {
211             continue;
212           }
213           Map JavaDoc variables = trial.getVariables();
214           if (variables.get(seriesVariable).equals(seriesValue)) {
215             double time = trial.getRunTimeMillis();
216             String JavaDoc domainValue = (String JavaDoc) trial.getVariables().get(
217                 domainVariable);
218             series.add(Double.parseDouble(domainValue), time);
219           }
220         }
221         data.addSeries(series);
222       }
223
224       return ChartFactory.createXYLineChart(title, domainVariable, valueTitle,
225           data, PlotOrientation.VERTICAL, true, true, false);
226     }
227
228     return null;
229
230     // Sample JFreeChart code for creating certain charts:
231
// Leaving this around until we can handle multivariate charts in dimensions
232
// greater than two.
233

234     // Code for creating a category data set - probably better with a bar chart
235
// instead of line chart
236
/*
237      * DefaultCategoryDataset data = new DefaultCategoryDataset(); String series =
238      * domainVariable;
239      *
240      * for ( Iterator it = trials.iterator(); it.hasNext(); ) { Trial trial =
241      * (Trial) it.next(); double time = trial.getRunTimeMillis(); String
242      * domainValue = (String) trial.getVariables().get( domainVariable );
243      * data.addValue( time, series, domainValue ); }
244      *
245      * String title = ""; String categoryTitle = domainVariable; PlotOrientation
246      * orientation = PlotOrientation.VERTICAL;
247      *
248      * chart = ChartFactory.createLineChart( title, categoryTitle, valueTitle,
249      * data, orientation, true, true, false );
250      */

251
252     /*
253      * DefaultCategoryDataset data = new DefaultCategoryDataset(); String
254      * series1 = "firefox"; String series2 = "ie";
255      *
256      * data.addValue( 1.0, series1, "1024"); data.addValue( 2.0, series1,
257      * "2048"); data.addValue( 4.0, series1, "4096"); data.addValue( 8.0,
258      * series1, "8192");
259      *
260      * data.addValue( 2.0, series2, "1024"); data.addValue( 4.0, series2,
261      * "2048"); data.addValue( 8.0, series2, "4096"); data.addValue( 16.0,
262      * series2,"8192");
263      *
264      * String title = ""; String categoryTitle = "size"; PlotOrientation
265      * orientation = PlotOrientation.VERTICAL;
266      *
267      * chart = ChartFactory.createLineChart( title, categoryTitle, valueTitle,
268      * data, orientation, true, true, false );
269      */

270   }
271
272   public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
273       throws ServletException JavaDoc, IOException JavaDoc {
274     handleRequest(request, response);
275   }
276
277   public void doPost(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
278       throws ServletException JavaDoc, IOException JavaDoc {
279     handleRequest(request, response);
280   }
281
282   private Benchmark getBenchmarkByName(List JavaDoc benchmarks, String JavaDoc name) {
283     for (Iterator JavaDoc it = benchmarks.iterator(); it.hasNext();) {
284       Benchmark benchmark = (Benchmark) it.next();
285       if (benchmark.getName().equals(name)) {
286         return benchmark;
287       }
288     }
289     return null;
290   }
291
292   private Category getCategoryByName(List JavaDoc categories, String JavaDoc categoryName) {
293     for (Iterator JavaDoc catIt = categories.iterator(); catIt.hasNext();) {
294       Category category = (Category) catIt.next();
295       if (category.getName().equals(categoryName)) {
296         return category;
297       }
298     }
299     return null;
300   }
301
302   private Result getResultsByAgent(List JavaDoc results, String JavaDoc agent) {
303     for (Iterator JavaDoc it = results.iterator(); it.hasNext();) {
304       Result result = (Result) it.next();
305       if (result.getAgent().equals(agent)) {
306         return result;
307       }
308     }
309     return null;
310   }
311
312   private void handleRequest(HttpServletRequest JavaDoc request,
313       HttpServletResponse JavaDoc response) throws IOException JavaDoc, ServletException JavaDoc {
314
315     String JavaDoc uri = request.getRequestURI();
316     String JavaDoc requestString = uri.split("test_images/")[1];
317     String JavaDoc[] requestParams = requestString.split("/");
318
319     String JavaDoc reportName = URLDecoder.decode(requestParams[0], charset);
320     String JavaDoc categoryName = URLDecoder.decode(requestParams[1], charset);
321     String JavaDoc className = URLDecoder.decode(requestParams[2], charset);
322     String JavaDoc testName = URLDecoder.decode(requestParams[3], charset);
323     String JavaDoc agent = URLDecoder.decode(requestParams[4], charset);
324
325     ReportDatabase db = ReportDatabase.getInstance();
326     Report report = db.getReport(reportName);
327     List JavaDoc categories = report.getCategories();
328     Category category = getCategoryByName(categories, categoryName);
329     List JavaDoc benchmarks = category.getBenchmarks();
330     Benchmark benchmark = getBenchmarkByName(benchmarks, testName);
331     List JavaDoc results = benchmark.getResults();
332     Result result = getResultsByAgent(results, agent);
333
334     String JavaDoc title = BrowserInfo.getBrowser(agent);
335     JFreeChart chart = null;
336
337     try {
338       chart = createChart(testName, result, title);
339
340       if (chart == null) {
341         super.doGet(request, response);
342         return;
343       }
344     } catch (Exception JavaDoc e) {
345       e.printStackTrace();
346     }
347
348     chart.getTitle().setFont(Font.decode("Arial"));
349
350     // Try to fit all the graphs into a 1024 window, with a min of 240 and a max
351
// of 480
352
final int graphWidth = Math.max(240, Math.min(480,
353         (1024 - 10 * results.size()) / results.size()));
354     BufferedImage JavaDoc img = chart.createBufferedImage(graphWidth, 240);
355     byte[] image = EncoderUtil.encode(img, ImageFormat.PNG);
356
357     response.setContentType("image/png");
358
359     OutputStream JavaDoc output = response.getOutputStream();
360     copy(new ByteArrayInputStream JavaDoc(image), output);
361   }
362 }
363
Popular Tags