Source Code Cross Referenced for ReportViewer.java in  » Ajax » GWT » com » google » gwt » junit » viewer » client » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » GWT » com.google.gwt.junit.viewer.client 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2007 Google Inc.
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005:         * use this file except in compliance with the License. You may obtain a copy of
006:         * the License at
007:         * 
008:         * http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013:         * License for the specific language governing permissions and limitations under
014:         * the License.
015:         */
016:        package com.google.gwt.junit.viewer.client;
017:
018:        import com.google.gwt.core.client.EntryPoint;
019:        import com.google.gwt.core.client.GWT;
020:        import com.google.gwt.http.client.URL;
021:        import com.google.gwt.user.client.DOM;
022:        import com.google.gwt.user.client.Element;
023:        import com.google.gwt.user.client.rpc.AsyncCallback;
024:        import com.google.gwt.user.client.rpc.ServiceDefTarget;
025:        import com.google.gwt.user.client.ui.Button;
026:        import com.google.gwt.user.client.ui.CellPanel;
027:        import com.google.gwt.user.client.ui.ClickListener;
028:        import com.google.gwt.user.client.ui.FlexTable;
029:        import com.google.gwt.user.client.ui.HTML;
030:        import com.google.gwt.user.client.ui.HasHorizontalAlignment;
031:        import com.google.gwt.user.client.ui.HasVerticalAlignment;
032:        import com.google.gwt.user.client.ui.HorizontalPanel;
033:        import com.google.gwt.user.client.ui.Image;
034:        import com.google.gwt.user.client.ui.Label;
035:        import com.google.gwt.user.client.ui.RootPanel;
036:        import com.google.gwt.user.client.ui.VerticalPanel;
037:        import com.google.gwt.user.client.ui.Widget;
038:        import com.google.gwt.user.client.ui.TableListener;
039:        import com.google.gwt.user.client.ui.SourcesTableEvents;
040:
041:        import java.util.ArrayList;
042:        import java.util.Collections;
043:        import java.util.Comparator;
044:        import java.util.List;
045:        import java.util.Map;
046:
047:        /**
048:         * The application for viewing benchmark reports. In order for the ReportViewer
049:         * to operate correctly, you must have both the {@link ReportServer} RPC and
050:         * {@link com.google.gwt.junit.viewer.server.ReportImageServer} servlets up and
051:         * running within a servlet container.
052:         * 
053:         * <code>ReportViewer's</code> GWT XML module is configured to start these
054:         * servlets by default. Just start <code>ReportViewer</code> in hosted mode,
055:         * and GWT will run them within its own embedded servlet engine. For example,
056:         * 
057:         * <pre>java -cp &lt;classpath&gt; com.google.gwt.dev.GWTShell -out
058:         * ReportViewerShell/www
059:         * com.google.gwt.junit.viewer.ReportViewer/ReportViewer.html</pre>
060:         * 
061:         * You can configure the location where ReportServer reads the benchmark reports
062:         * from by setting the system property named in
063:         * {@link com.google.gwt.junit.client.Benchmark#REPORT_PATH}.
064:         */
065:        public class ReportViewer implements  EntryPoint {
066:
067:            private static class MutableBool {
068:
069:                boolean value;
070:
071:                MutableBool(boolean value) {
072:                    this .value = value;
073:                }
074:            }
075:
076:            private class SummariesTableListener implements  TableListener {
077:
078:                private FlexTable summariesTable;
079:
080:                SummariesTableListener(FlexTable summariesTable) {
081:                    this .summariesTable = summariesTable;
082:                }
083:
084:                public void onCellClicked(SourcesTableEvents sender, int row,
085:                        int col) {
086:                    if (currentSelectedRow != -1) {
087:                        summariesTable.getRowFormatter().removeStyleName(
088:                                currentSelectedRow, "viewer-SelectedRow");
089:                    }
090:                    currentSelectedRow = row;
091:                    summariesTable.getRowFormatter().addStyleName(row,
092:                            "viewer-SelectedRow");
093:                    ReportSummary summary = (ReportSummary) summaries
094:                            .get(row - 1);
095:                    getReportDetails(summary.getId());
096:                }
097:            }
098:
099:            private static final String baseUrl = GWT.getModuleBaseURL();
100:
101:            private static final String imageServer = baseUrl + "test_images/";
102:
103:            HTML detailsLabel;
104:
105:            Report report;
106:
107:            VerticalPanel reportPanel;
108:
109:            ReportServerAsync reportServer;
110:
111:            FlexTable reportTable;
112:
113:            HTML statusLabel;
114:
115:            List/* <ReportSummary> */summaries;
116:
117:            VerticalPanel summariesPanel;
118:
119:            FlexTable summariesTable;
120:
121:            CellPanel topPanel;
122:
123:            private int currentSelectedRow = -1;
124:
125:            public void onModuleLoad() {
126:
127:                init();
128:
129:                // Asynchronously load the summaries
130:                ServiceDefTarget target = (ServiceDefTarget) GWT
131:                        .create(ReportServer.class);
132:                target.setServiceEntryPoint(GWT.getModuleBaseURL()
133:                        + "test_reports");
134:                reportServer = (ReportServerAsync) target;
135:
136:                reportServer.getReportSummaries(new AsyncCallback() {
137:                    public void onFailure(Throwable caught) {
138:                        String msg = "<p>" + caught.toString() + "</p>"
139:                                + "<p>Is your path to the reports correct?</p>";
140:                        statusLabel.setHTML(msg);
141:                    }
142:
143:                    public void onSuccess(Object result) {
144:                        summaries = (List/* <ReportSummary> */) result;
145:                        if (summaries != null) {
146:                            if (summaries.size() == 0) {
147:                                statusLabel
148:                                        .setText("There are no benchmark reports available in this folder.");
149:                            }
150:                            Collections.sort(summaries, new Comparator() {
151:                                public int compare(Object o1, Object o2) {
152:                                    ReportSummary r1 = (ReportSummary) o1;
153:                                    ReportSummary r2 = (ReportSummary) o2;
154:                                    return r2.getDate().compareTo(r1.getDate()); // most recent first
155:                                }
156:                            });
157:                            displaySummaries();
158:                        }
159:                    }
160:                });
161:            }
162:
163:            private FlexTable createReportTable() {
164:
165:                FlexTable topTable = new FlexTable();
166:
167:                FlexTable tempReportTable = new FlexTable();
168:                tempReportTable.setBorderWidth(1);
169:                tempReportTable.setCellPadding(5);
170:                tempReportTable.setWidget(0, 0, new Label("Date Created"));
171:                tempReportTable.setWidget(0, 1, new Label("GWT Version"));
172:
173:                if (report == null) {
174:                    tempReportTable.setWidget(1, 0, new Label(
175:                            "No currently selected report."));
176:                    tempReportTable.getFlexCellFormatter().setColSpan(1, 0, 3);
177:                    return tempReportTable;
178:                }
179:
180:                detailsLabel
181:                        .setHTML("<h3>" + report.getId() + " details </h3>");
182:                tempReportTable.setWidget(1, 0, new Label(report
183:                        .getDateString()));
184:                tempReportTable.setWidget(1, 1, new Label(report
185:                        .getGwtVersion()));
186:
187:                // topTable.setWidget( 0, 0, tempReportTable );
188:                int currentRow = 1;
189:
190:                Collections.sort(report.getCategories(), new Comparator() {
191:                    public int compare(Object o1, Object o2) {
192:                        Category c1 = (Category) o1;
193:                        Category c2 = (Category) o2;
194:                        return c1.getName().compareTo(c2.getName());
195:                    }
196:                }); // Should be done once in the RPC
197:
198:                for (int i = 0; i < report.getCategories().size(); ++i) {
199:                    Category c = (Category) report.getCategories().get(i);
200:
201:                    if (!c.getName().equals("")) {
202:                        FlexTable categoryTable = new FlexTable();
203:                        categoryTable.setBorderWidth(0);
204:                        categoryTable.setCellPadding(5);
205:                        categoryTable.setText(0, 0, c.getName());
206:                        categoryTable.getFlexCellFormatter().setStyleName(0, 0,
207:                                "benchmark-category");
208:
209:                        categoryTable.setWidget(0, 1, new Label("Description"));
210:                        categoryTable.setWidget(1, 0, new Label(c.getName()));
211:                        categoryTable.setWidget(1, 1, new Label(c
212:                                .getDescription()));
213:
214:                        topTable.setWidget(currentRow++, 0, categoryTable);
215:                    }
216:
217:                    Collections.sort(c.getBenchmarks(), new Comparator() {
218:                        public int compare(Object o1, Object o2) {
219:                            Benchmark b1 = (Benchmark) o1;
220:                            Benchmark b2 = (Benchmark) o2;
221:                            return b1.getName().compareTo(b2.getName());
222:                        }
223:                    }); // Should be done once in the RPC
224:
225:                    for (int j = 0; j < c.getBenchmarks().size(); ++j) {
226:                        Benchmark benchmark = (Benchmark) c.getBenchmarks()
227:                                .get(j);
228:
229:                        FlexTable benchmarkTable = new FlexTable();
230:                        benchmarkTable.setBorderWidth(0);
231:                        benchmarkTable.setCellPadding(5);
232:                        benchmarkTable.setText(0, 0, benchmark.getName());
233:                        // benchmarkTable.setText(0, 1, benchmark.getDescription());
234:                        String codeHtml;
235:                        String sourceText = benchmark.getSourceCode();
236:                        if (sourceText != null) {
237:                            Element tempElem = DOM.createDiv();
238:                            DOM.setInnerText(tempElem, sourceText);
239:                            String escapedCodeHtml = DOM.getInnerHTML(tempElem);
240:                            codeHtml = "<pre>" + escapedCodeHtml + "</pre>";
241:                        } else {
242:                            codeHtml = "<i>(source not available)</i>";
243:                        }
244:                        benchmarkTable.setWidget(1, 0, new HTML(codeHtml));
245:                        benchmarkTable.getFlexCellFormatter().setStyleName(0,
246:                                0, "benchmark-name");
247:                        // benchmarkTable.getFlexCellFormatter().setStyleName( 0, 1,
248:                        // "benchmark-description" );
249:                        benchmarkTable.getFlexCellFormatter().setStyleName(1,
250:                                0, "benchmark-code");
251:
252:                        // TODO(tobyr) Provide detailed benchmark information.
253:                        // Following bits of commented code are steps in that direction.
254:                        /*
255:                         * benchmarkTable.setWidget( 0, 1, new Label( "Description"));
256:                         * benchmarkTable.setWidget( 0, 2, new Label( "Class Name"));
257:                         * benchmarkTable.setWidget( 0, 3, new Label( "Source Code"));
258:                         * benchmarkTable.setWidget( 1, 0, new Label( benchmark.getName()));
259:                         * benchmarkTable.setWidget( 1, 1, new Label(
260:                         * benchmark.getDescription())); benchmarkTable.setWidget( 1, 2, new
261:                         * Label( benchmark.getClassName())); benchmarkTable.setWidget( 1, 3,
262:                         * new HTML( "<pre>" + benchmark.getSourceCode() + "</pre>"));
263:                         */
264:                        topTable.setWidget(currentRow++, 0, benchmarkTable);
265:
266:                        FlexTable resultsTable = new FlexTable();
267:                        resultsTable.setBorderWidth(0);
268:                        resultsTable.setCellPadding(5);
269:                        FlexTable.FlexCellFormatter resultsFormatter = resultsTable
270:                                .getFlexCellFormatter();
271:                        topTable.setWidget(currentRow++, 0, resultsTable);
272:
273:                        Collections.sort(benchmark.getResults(),
274:                                new Comparator() {
275:                                    public int compare(Object o1, Object o2) {
276:                                        Result r1 = (Result) o1;
277:                                        Result r2 = (Result) o2;
278:                                        return r1.getAgent().compareTo(
279:                                                r2.getAgent());
280:                                    }
281:                                }); // Should be done once in the RPC
282:
283:                        final List trialsTables = new ArrayList();
284:
285:                        Result sampleResult = (Result) benchmark.getResults()
286:                                .get(0);
287:                        Trial sampleTrial = (Trial) sampleResult.getTrials()
288:                                .get(0);
289:                        int numVariables = sampleTrial.getVariables().size();
290:                        final MutableBool isVisible = new MutableBool(
291:                                numVariables > 2);
292:                        String buttonName = isVisible.value ? "Hide Data"
293:                                : "Show Data";
294:
295:                        Button visibilityButton = new Button(buttonName,
296:                                new ClickListener() {
297:                                    public void onClick(Widget sender) {
298:                                        isVisible.value = !isVisible.value;
299:                                        for (int i = 0; i < trialsTables.size(); ++i) {
300:                                            Widget w = (Widget) trialsTables
301:                                                    .get(i);
302:                                            w.setVisible(isVisible.value);
303:                                        }
304:                                        String name = isVisible.value ? "Hide Data"
305:                                                : "Show Data";
306:                                        ((Button) sender).setText(name);
307:                                    }
308:                                });
309:
310:                        for (int k = 0; k < benchmark.getResults().size(); ++k) {
311:                            Result result = (Result) benchmark.getResults()
312:                                    .get(k);
313:                            List trials = result.getTrials();
314:
315:                            // Currently only support graphs for results of 2 variables or less
316:                            if (numVariables <= 2) {
317:                                resultsTable.setWidget(0, k, new Image(
318:                                        getImageUrl(report.getId(),
319:                                                c.getName(), benchmark
320:                                                        .getClassName(),
321:                                                benchmark.getName(), result
322:                                                        .getAgent())));
323:                            } else {
324:                                if (k == 0) {
325:                                    resultsTable
326:                                            .setHTML(
327:                                                    0,
328:                                                    k,
329:                                                    "<b>"
330:                                                            + BrowserInfo
331:                                                                    .getBrowser(result
332:                                                                            .getAgent())
333:                                                            + "</b><br><font size=\"-1\">(Graphs are not yet available "
334:                                                            + "for benchmarks with more than two parameters)</font>");
335:                                }
336:                            }
337:
338:                            /*
339:                             * FlexTable allTrialsTable = new FlexTable();
340:                             * allTrialsTable.setBorderWidth(1); allTrialsTable.setCellPadding(5);
341:                             * FlexTable.CellFormatter allTrialsFormatter = allTrialsTable
342:                             * .getFlexCellFormatter(); topTable.setWidget(currentRow++, 0,
343:                             * allTrialsTable); allTrialsTable.setWidget(0, k, trialsTable);
344:                             * allTrialsFormatter .setAlignment(0, k,
345:                             * HasHorizontalAlignment.ALIGN_CENTER,
346:                             * HasVerticalAlignment.ALIGN_TOP);
347:                             */
348:
349:                            resultsFormatter.setAlignment(2, k,
350:                                    HasHorizontalAlignment.ALIGN_LEFT,
351:                                    HasVerticalAlignment.ALIGN_TOP);
352:
353:                            // A table of straight data for all trials for an agent
354:                            FlexTable trialsTable = new FlexTable();
355:                            trialsTable.setVisible(isVisible.value);
356:                            trialsTables.add(trialsTable);
357:                            trialsTable.setBorderWidth(1);
358:                            trialsTable.setCellPadding(5);
359:
360:                            if (k == 0) {
361:                                resultsTable.setWidget(1, k, visibilityButton);
362:                                resultsFormatter.setColSpan(1, k, benchmark
363:                                        .getResults().size());
364:                                resultsFormatter.setAlignment(1, k,
365:                                        HasHorizontalAlignment.ALIGN_LEFT,
366:                                        HasVerticalAlignment.ALIGN_MIDDLE);
367:                            }
368:
369:                            resultsTable.setWidget(2, k, trialsTable);
370:
371:                            int numTrials = trials.size();
372:
373:                            Map variables = sampleTrial.getVariables();
374:                            List variableNames = new ArrayList(variables
375:                                    .keySet());
376:                            Collections.sort(variableNames);
377:
378:                            // Write out the variable column headers
379:                            for (int varIndex = 0; varIndex < numVariables; ++varIndex) {
380:                                String varName = (String) variableNames
381:                                        .get(varIndex);
382:                                trialsTable.setHTML(0, varIndex, varName);
383:                            }
384:
385:                            // Timing header
386:                            trialsTable.setHTML(0, numVariables, "Timing (ms)");
387:
388:                            // Write out all the trial data
389:                            for (int l = 0; l < numTrials; ++l) {
390:                                Trial trial = (Trial) trials.get(l);
391:
392:                                // Write the variable values
393:                                for (int varIndex = 0; varIndex < numVariables; ++varIndex) {
394:                                    String varName = (String) variableNames
395:                                            .get(varIndex);
396:                                    String varValue = (String) trial
397:                                            .getVariables().get(varName);
398:                                    trialsTable.setHTML(l + 1, varIndex,
399:                                            varValue);
400:                                }
401:
402:                                // Write out the timing data
403:                                String data = null;
404:                                if (trial.getException() != null) {
405:                                    data = trial.getException();
406:                                } else {
407:                                    data = trial.getRunTimeMillis() + "";
408:                                }
409:                                trialsTable.setHTML(l + 1, numVariables, data);
410:                            }
411:                        }
412:                    }
413:                }
414:
415:                return topTable;
416:            }
417:
418:            private FlexTable createSummariesTable() {
419:
420:                FlexTable tempSummariesTable = new FlexTable();
421:                tempSummariesTable.addStyleName("viewer-List");
422:                tempSummariesTable.setCellPadding(5);
423:                tempSummariesTable.setBorderWidth(1);
424:                tempSummariesTable.setCellSpacing(0);
425:                tempSummariesTable.setWidget(0, 0, new Label("Report"));
426:                tempSummariesTable.setWidget(0, 1, new Label("Date Created"));
427:                tempSummariesTable.setWidget(0, 2, new Label("Tests"));
428:                tempSummariesTable.getRowFormatter().addStyleName(0,
429:                        "viewer-ListHeader");
430:
431:                if (summaries == null) {
432:                    tempSummariesTable.setWidget(1, 0, new Label(
433:                            "Fetching reports..."));
434:                    tempSummariesTable.getFlexCellFormatter().setColSpan(1, 0,
435:                            4);
436:                    return tempSummariesTable;
437:                }
438:
439:                for (int i = 0; i < summaries.size(); ++i) {
440:                    ReportSummary summary = (ReportSummary) summaries.get(i);
441:                    int index = i + 1;
442:                    tempSummariesTable.setHTML(index, 0,
443:                            "<a href=\"javascript:void(0)\">" + summary.getId()
444:                                    + "</a>");
445:                    tempSummariesTable.setWidget(index, 1, new Label(summary
446:                            .getDateString()));
447:                    tempSummariesTable.setWidget(index, 2, new Label(String
448:                            .valueOf(summary.getNumTests())));
449:                }
450:
451:                tempSummariesTable.addTableListener(new SummariesTableListener(
452:                        tempSummariesTable));
453:
454:                return tempSummariesTable;
455:            }
456:
457:            private void displayReport() {
458:                FlexTable table = createReportTable();
459:                reportPanel.remove(reportTable);
460:                reportTable = table;
461:                reportPanel.insert(reportTable, 1);
462:            }
463:
464:            private void displaySummaries() {
465:                FlexTable table = createSummariesTable();
466:                summariesPanel.remove(summariesTable);
467:                summariesTable = table;
468:                summariesPanel.insert(summariesTable, 1);
469:            }
470:
471:            private String encode(String str) {
472:                if (str.equals("")) {
473:                    return str;
474:                }
475:                return URL.encodeComponent(str);
476:            }
477:
478:            private String getImageUrl(String report, String category,
479:                    String testClass, String testMethod, String agent) {
480:                return imageServer + encode(report) + "/" + encode(category)
481:                        + "/" + encode(testClass) + "/" + encode(testMethod)
482:                        + "/" + encode(agent);
483:            }
484:
485:            /**
486:             * Loads report details asynchronously for a given report.
487:             * 
488:             * @param id the non-null id of the report
489:             */
490:            private void getReportDetails(String id) {
491:                statusLabel.setText("Retrieving the report...");
492:                reportServer.getReport(id, new AsyncCallback() {
493:                    public void onFailure(Throwable caught) {
494:                        statusLabel.setText(caught.toString());
495:                    }
496:
497:                    public void onSuccess(Object result) {
498:                        report = (Report) result;
499:                        statusLabel
500:                                .setText("Finished fetching report details.");
501:                        displayReport();
502:                    }
503:                });
504:            }
505:
506:            private void init() {
507:                topPanel = new VerticalPanel();
508:
509:                summariesPanel = new VerticalPanel();
510:                summariesPanel.add(new HTML("<h3>Benchmark Reports</h3>"));
511:                summariesTable = createSummariesTable();
512:                summariesPanel.add(summariesTable);
513:
514:                reportPanel = new VerticalPanel();
515:                detailsLabel = new HTML("<h3>Report Details</h3>");
516:                reportPanel.add(detailsLabel);
517:                reportTable = createReportTable();
518:                // reportPanel.add( reportTable );
519:
520:                topPanel.add(summariesPanel);
521:                CellPanel spacerPanel = new HorizontalPanel();
522:                spacerPanel.setSpacing(10);
523:                spacerPanel.add(new Label());
524:                topPanel.add(spacerPanel);
525:                topPanel.add(reportPanel);
526:                final RootPanel root = RootPanel.get();
527:
528:                root.add(topPanel);
529:
530:                statusLabel = new HTML("Select a report.");
531:                root.add(statusLabel);
532:            }
533:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.