1 /*
   2  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 package j2dbench;
  42 
  43 import java.io.PrintWriter;
  44 import java.io.FileReader;
  45 import java.io.FileWriter;
  46 import java.io.LineNumberReader;
  47 import java.io.FileNotFoundException;
  48 import java.io.IOException;
  49 import java.io.File;
  50 import java.awt.Frame;
  51 import java.awt.Dimension;
  52 import java.awt.BorderLayout;
  53 import java.awt.event.ActionListener;
  54 import java.awt.event.ActionEvent;
  55 import java.awt.event.WindowAdapter;
  56 import java.awt.event.WindowEvent;
  57 import javax.swing.JFrame;
  58 import javax.swing.JButton;
  59 import javax.swing.JPanel;
  60 import javax.swing.BoxLayout;
  61 import javax.swing.JFileChooser;
  62 import javax.swing.JOptionPane;
  63 import javax.swing.SwingUtilities;
  64 import javax.swing.WindowConstants;
  65 
  66 import java.text.SimpleDateFormat;
  67 import java.util.Date;
  68 
  69 import j2dbench.tests.GraphicsTests;
  70 import j2dbench.tests.ImageTests;
  71 import j2dbench.tests.MiscTests;
  72 import j2dbench.tests.RenderTests;
  73 import j2dbench.tests.PixelTests;
  74 import j2dbench.tests.iio.IIOTests;
  75 import j2dbench.tests.cmm.CMMTests;
  76 import j2dbench.tests.text.TextConstructionTests;
  77 import j2dbench.tests.text.TextMeasureTests;
  78 import j2dbench.tests.text.TextRenderTests;
  79 import j2dbench.tests.text.TextTests;
  80 
  81 public class J2DBench {
  82     static Group progoptroot;
  83 
  84     static Option.Enable verbose;
  85     static Option.Enable printresults;
  86 
  87     static boolean looping = false;
  88 
  89     static JFrame guiFrame;
  90 
  91     static final SimpleDateFormat sdf =
  92         new SimpleDateFormat("MM.dd.yyyy 'at' HH:mm aaa z");
  93 
  94     public static void init() {
  95         progoptroot = new Group("prog", "Program Options");
  96         progoptroot.setHidden();
  97 
  98         verbose =
  99             new Option.Enable(progoptroot,
 100                               "verbose", "Verbose print statements",
 101                               false);
 102         printresults =
 103             new Option.Enable(progoptroot,
 104                               "printresults", "Print results after each run",
 105                               true);
 106     }
 107 
 108     public static void usage(int exitcode) {
 109         System.out.println("usage: java -jar J2DBench.jar "+
 110                            "[<optionname>=<value>]");
 111         System.out.println("    "+
 112                            "[-list] "+
 113                            "[-gui | -interactive] "+
 114                            "[-batch] "+
 115                            "[-noshow] "+
 116                            "[-nosave] "+
 117                            "[-report:[NMKAUOsmuna/]] "+
 118                            "[-usage | -help] "+
 119                            "\n    "+
 120                            "\n    "+
 121                            "[-loadopts | -loadoptions] <optfile> "+
 122                            "[-saveopts | -saveoptions] <optfile> "+
 123                            "\n    "+
 124                            "[-saveres | -saveresults] <resfile> "+
 125                            "[-appres | -appendresults] <resfile> "+
 126                            "\n    "+
 127                            "[-title] <title> "+
 128                            "[-desc | -description] <description> "+
 129                            "\n    "+
 130                            "[-loop] <duration> [-loopdef | -loopdefault] "+
 131                            "");
 132         System.out.println("        -list      "+
 133                            "List the option settings on stdout");
 134         System.out.println("        -gui       "+
 135                            "Run the program in interactive mode (launch GUI)");
 136         System.out.println("        -batch     "+
 137                            "Run the program in batch mode (do not launch GUI)");
 138         System.out.println("        -noshow    "+
 139                            "Do not show output on the screen (batch mode)");
 140         System.out.println("        -nosave    "+
 141                            "Do not show save results to a file (batch mode)");
 142         System.out.println("        -report    "+
 143                            "Rate format to report 'X per Y' (default u/s)");
 144         System.out.println("                   "+
 145                            "  N = report in single units or ops");
 146         System.out.println("                   "+
 147                            "  M = report in millions of units or ops");
 148         System.out.println("                   "+
 149                            "  K = report in thousands of units or ops");
 150         System.out.println("                   "+
 151                            "  A = (auto) M or K as needed");
 152         System.out.println("                   "+
 153                            "  U = units as defined by the operation");
 154         System.out.println("                   "+
 155                            "  O = operations");
 156         System.out.println("                   "+
 157                            "  s = report by whole seconds");
 158         System.out.println("                   "+
 159                            "  m = report by milliseconds");
 160         System.out.println("                   "+
 161                            "  u = report by microseconds");
 162         System.out.println("                   "+
 163                            "  n = report by nanoseconds");
 164         System.out.println("                   "+
 165                            "  a = (auto) milli/micro/nanoseconds as needed");
 166         System.out.println("                   "+
 167                            "  / = invert (N/sec or secs/N)");
 168         System.out.println("        -usage     "+
 169                            "Print out this usage message");
 170         System.out.println("        -saveres   "+
 171                            "Save the results to the indicated file");
 172         System.out.println("        -appres    "+
 173                            "Append the results to the indicated file");
 174         System.out.println("        -title     "+
 175                            "Use the title for the saved results");
 176         System.out.println("        -desc      "+
 177                            "Use the description for the saved results");
 178         System.out.println("        -loop      "+
 179                            "Loop for the specified duration"+
 180                            "\n                   "+
 181                            "Duration specified as :"+
 182                            "\n                     "+
 183                            "<days>d / <hours>h / <minutes>m / dd:hh:mm");
 184         System.out.println("        -loopdef   "+
 185                            "Loop for a default duration of 72 hours");
 186 
 187         System.exit(exitcode);
 188     }
 189 
 190     public static void main(String[] argv) {
 191         init();
 192         TestEnvironment.init();
 193         Result.init();
 194 
 195         Destinations.init();
 196         GraphicsTests.init();
 197         RenderTests.init();
 198         PixelTests.init();
 199         ImageTests.init();
 200         MiscTests.init();
 201         TextTests.init();
 202         TextRenderTests.init();
 203         TextMeasureTests.init();
 204         TextConstructionTests.init();
 205         IIOTests.init();
 206         CMMTests.init();
 207 
 208         boolean gui = true;
 209         boolean showresults = true;
 210         boolean saveresults = true;
 211         String resfilename = null;
 212         String title = null;
 213         String desc = null;
 214         boolean appendres = false;
 215         long requiredLoopTime = 259200000; // 72 hrs * 60 * 60 * 1000
 216         for (int i = 0; i < argv.length; i++) {
 217             String arg = argv[i];
 218             if (arg.equalsIgnoreCase("-list")) {
 219                 PrintWriter pw = new PrintWriter(System.out);
 220                 Node.Iterator iter = Group.root.getRecursiveChildIterator();
 221                 while (iter.hasNext()) {
 222                     Node n = iter.next();
 223                     n.write(pw);
 224                 }
 225                 pw.flush();
 226             } else if (arg.equalsIgnoreCase("-gui") ||
 227                        arg.equalsIgnoreCase("-interactive"))
 228             {
 229                 gui = true;
 230             } else if (arg.equalsIgnoreCase("-batch")) {
 231                 gui = false;
 232             } else if (arg.equalsIgnoreCase("-noshow")) {
 233                 showresults = false;
 234             } else if (arg.equalsIgnoreCase("-nosave")) {
 235                 saveresults = false;
 236             } else if (arg.equalsIgnoreCase("-usage") ||
 237                        arg.equalsIgnoreCase("-help"))
 238             {
 239                 usage(0);
 240             } else if (arg.equalsIgnoreCase("-loadoptions") ||
 241                        arg.equalsIgnoreCase("-loadopts"))
 242             {
 243                 if (++i < argv.length) {
 244                     String file = argv[i];
 245                     String reason = loadOptions(file);
 246                     if (reason != null) {
 247                         System.err.println(reason);
 248                         System.exit(1);
 249                     }
 250                 } else {
 251                     usage(1);
 252                 }
 253             } else if (arg.equalsIgnoreCase("-saveoptions") ||
 254                        arg.equalsIgnoreCase("-saveopts"))
 255             {
 256                 if (++i < argv.length) {
 257                     String file = argv[i];
 258                     String reason = saveOptions(file);
 259                     if (reason != null) {
 260                         System.err.println(reason);
 261                         System.exit(1);
 262                     }
 263                 } else {
 264                     usage(1);
 265                 }
 266             } else if (arg.equalsIgnoreCase("-saveresults") ||
 267                        arg.equalsIgnoreCase("-saveres") ||
 268                        arg.equalsIgnoreCase("-appendresults") ||
 269                        arg.equalsIgnoreCase("-appres"))
 270             {
 271                 if (++i < argv.length) {
 272                     resfilename = argv[i];
 273                     appendres = arg.substring(0, 4).equalsIgnoreCase("-app");
 274                 } else {
 275                     usage(1);
 276                 }
 277             } else if (arg.equalsIgnoreCase("-title")) {
 278                 if (++i < argv.length) {
 279                     title = argv[i];
 280                 } else {
 281                     usage(1);
 282                 }
 283             } else if (arg.equalsIgnoreCase("-desc") ||
 284                        arg.equalsIgnoreCase("-description"))
 285             {
 286                 if (++i < argv.length) {
 287                     desc = argv[i];
 288                 } else {
 289                     usage(1);
 290                 }
 291             } else if (arg.equalsIgnoreCase("-loopdef") ||
 292                        arg.equalsIgnoreCase("-loopdefault"))
 293             {
 294                 requiredLoopTime = 259200000; // 72 hrs * 60 * 60 * 1000
 295                 J2DBench.looping = true;
 296             } else if (arg.equalsIgnoreCase("-loop")) {
 297 
 298                 if (++i >= argv.length) {
 299                     usage(1);
 300                 }
 301 
 302                 J2DBench.looping = true;
 303 
 304                 /*
 305                  * d or D    ->  Days
 306                  * h or H    ->  Hours
 307                  * m or M    ->  Minutes
 308                  * dd:hh:mm  ->  Days:Hours:Minutes
 309                  */
 310 
 311                 if (argv[i].indexOf(":") >= 0) {
 312 
 313                     String[] values = argv[i].split(":");
 314                     int[] intVals = new int[3];
 315 
 316                     for(int j=0; j<values.length; j++) {
 317                         try {
 318                             intVals[j] = Integer.parseInt(values[j]);
 319                         } catch(Exception e) {}
 320                     }
 321 
 322                     System.out.println("\nLoop for " + intVals[0] +
 323                                        " days " + intVals[1] +
 324                                        " hours and " + intVals[2] + " minutes.\n");
 325 
 326                     requiredLoopTime = ((intVals[0] * 24 * 60 * 60) +
 327                                         (intVals[1] * 60 * 60) +
 328                                         (intVals[2] * 60)) * 1000;
 329 
 330                 } else {
 331 
 332                     String type = argv[i].substring(argv[i].length() - 1);
 333 
 334                     int multiplyWith = 1;
 335 
 336                     if (type.equalsIgnoreCase("d")) {
 337                         multiplyWith = 24 * 60 * 60;
 338                     } else if (type.equalsIgnoreCase("h")) {
 339                         multiplyWith = 60 * 60;
 340                     } else if (type.equalsIgnoreCase("m")) {
 341                         multiplyWith = 60;
 342                     } else {
 343                         System.err.println("Invalid \"-loop\" option specified.");
 344                         usage(1);
 345                     }
 346 
 347                     int val = 1;
 348                     try {
 349                         val = Integer.parseInt(argv[i].substring(0, argv[i].length() - 1));
 350                     } catch(Exception e) {
 351                         System.err.println("Invalid \"-loop\" option specified.");
 352                         usage(1);
 353                     }
 354 
 355                     requiredLoopTime = val * multiplyWith * 1000;
 356                 }
 357 
 358            } else if (arg.length() > 8 &&
 359                         arg.substring(0, 8).equalsIgnoreCase("-report:"))
 360            {
 361                 String error = Result.parseRateOpt(arg.substring(8));
 362                 if (error != null) {
 363                      System.err.println("Invalid rate: "+error);
 364                      usage(1);
 365                 }
 366             } else {
 367                 String reason = Group.root.setOption(arg);
 368                 if (reason != null) {
 369                     System.err.println("Option "+arg+" ignored: "+reason);
 370                 }
 371             }
 372         }
 373         if (verbose.isEnabled()) {
 374             Group.root.traverse(new Node.Visitor() {
 375                 public void visit(Node node) {
 376                     System.out.println(node);
 377                 }
 378             });
 379         }
 380 
 381         if (gui) {
 382             SwingUtilities.invokeLater(new Runnable() {
 383                 public void run() {
 384                     startGUI();
 385                 }
 386             });
 387         } else {
 388 
 389             long start = System.currentTimeMillis();
 390 
 391             int nLoopCount = 1;
 392 
 393             if (saveresults) {
 394                 if (title == null) {
 395                     title = inputUserStr("title");
 396                 }
 397                 if (desc == null) {
 398                     desc = inputUserStr("description");
 399                 }
 400             }
 401 
 402             PrintWriter writer = null;
 403 
 404             if (J2DBench.looping) {
 405 
 406                 System.out.println("\nAbout to run tests for : " +
 407                                    (requiredLoopTime/1000) + " seconds.\n");
 408 
 409                 if(resfilename != null) {
 410 
 411                     try {
 412                         String loopReportFileName =
 413                             resfilename.substring(0, resfilename.lastIndexOf(".xml"));
 414                         writer = new PrintWriter(
 415                             new FileWriter(loopReportFileName + "_Loop.html"));
 416                         writer.println("<html><head><title>" + title + "</title></head>");
 417                         writer.println("<body bgcolor=\"#ffffff\"><hr size=\"1\">");
 418                         writer.println("<center><h2>" + title + "</h2>");
 419                         writer.println("</center><hr size=\"1\"><br>");
 420                         writer.flush();
 421                     } catch(IOException ioe) {
 422                         ioe.printStackTrace();
 423                         System.err.println("\nERROR : Could not create Loop-Report. Exit");
 424                         System.exit(1);
 425                     }
 426                 }
 427             }
 428 
 429             do {
 430 
 431                 Date loopStart = new Date();
 432                 if (J2DBench.looping) {
 433                     writer.println("<b>Loop # " + nLoopCount + "</b><br>");
 434                     writer.println("<b>Start : </b>" + sdf.format(loopStart) + "<br>");
 435                     writer.flush();
 436                 }
 437 
 438                 runTests(showresults);
 439                 if (saveresults) {
 440                     if (resfilename != null) {
 441                         lastResults.setTitle(title);
 442                         lastResults.setDescription(desc);
 443                         String reason = saveResults(resfilename, appendres);
 444                         if (reason != null) {
 445                             System.err.println(reason);
 446                         }
 447                     } else {
 448                         saveResults(title, desc);
 449                     }
 450                 }
 451 
 452                 if (J2DBench.looping) {
 453 
 454                     Date loopEnd = new Date();
 455 
 456                     System.out.println("\n================================================================");
 457                     System.out.println("-- Completed Loop " + nLoopCount + " at " + sdf.format(loopEnd) + " --");
 458                     System.out.println("================================================================\n");
 459 
 460                     writer.println("<b>End : </b>" + sdf.format(loopEnd) + "<br>");
 461                     writer.println("<b>Duration </b>: " + (loopEnd.getTime() - loopStart.getTime())/1000 + " Seconds<br>");
 462                     writer.println("<b>Total : " + (loopEnd.getTime() - start)/1000 + " Seconds</b><br>");
 463                     writer.println("</center><hr size=\"1\">");
 464                     writer.flush();
 465 
 466                     if ((loopEnd.getTime() - start) > requiredLoopTime) {
 467                         break;
 468                     }
 469 
 470                     //Append results for looping - mode
 471                     appendres = true;
 472 
 473                     nLoopCount++;
 474                 }
 475 
 476             } while(J2DBench.looping);
 477 
 478             if (J2DBench.looping) {
 479                 writer.println("</html>");
 480                 writer.flush();
 481                 writer.close();
 482             }
 483         }
 484     }
 485 
 486     public static String loadOptions(String filename) {
 487         FileReader fr;
 488         try {
 489             fr = new FileReader(filename);
 490         } catch (FileNotFoundException e) {
 491             return "file "+filename+" not found";
 492         }
 493         return loadOptions(fr, filename);
 494     }
 495 
 496     public static String loadOptions(File file) {
 497         FileReader fr;
 498         try {
 499             fr = new FileReader(file);
 500         } catch (FileNotFoundException e) {
 501             return "file "+file.getPath()+" not found";
 502         }
 503         return loadOptions(fr, file.getPath());
 504     }
 505 
 506     public static String loadOptions(FileReader fr, String filename) {
 507         LineNumberReader lnr = new LineNumberReader(fr);
 508         Group.restoreAllDefaults();
 509         String line;
 510         try {
 511             while ((line = lnr.readLine()) != null) {
 512                 String reason = Group.root.setOption(line);
 513                 if (reason != null) {
 514                     System.err.println("Option "+line+
 515                                        " at line "+lnr.getLineNumber()+
 516                                        " ignored: "+reason);
 517                 }
 518             }
 519         } catch (IOException e) {
 520             Group.restoreAllDefaults();
 521             return ("IO Error reading "+filename+
 522                     " at line "+lnr.getLineNumber());
 523         }
 524         return null;
 525     }
 526 
 527     public static String saveOptions(String filename) {
 528         return saveOptions(new File(filename));
 529     }
 530 
 531     public static String saveOptions(File file) {
 532         if (file.exists()) {
 533             if (!file.isFile()) {
 534                 return "Cannot save options to a directory!";
 535             }
 536             int ret = JOptionPane.showOptionDialog
 537                 (guiFrame,
 538                  new String[] {
 539                      "The file '"+file.getName()+"' already exists!",
 540                      "",
 541                      "Do you wish to overwrite this file?",
 542                  },
 543                  "File exists!",
 544                  JOptionPane.DEFAULT_OPTION,
 545                  JOptionPane.WARNING_MESSAGE,
 546                  null, new String[] {
 547                      "Overwrite",
 548                      "Cancel",
 549                  }, "Cancel");
 550             if (ret == 1) {
 551                 return null;
 552             }
 553         }
 554         FileWriter fw;
 555         try {
 556             fw = new FileWriter(file);
 557         } catch (IOException e) {
 558             return "Error opening option file "+file.getPath();
 559         }
 560         return saveOptions(fw, file.getPath());
 561     }
 562 
 563     public static String saveOptions(FileWriter fw, String filename) {
 564         PrintWriter pw = new PrintWriter(fw);
 565         Group.writeAll(pw);
 566         return null;
 567     }
 568 
 569     public static JFileChooser theFC;
 570     public static JFileChooser getFileChooser() {
 571         if (theFC == null) {
 572             theFC = new JFileChooser(System.getProperty("user.dir"));
 573         }
 574         theFC.rescanCurrentDirectory();
 575         return theFC;
 576     }
 577 
 578     public static ResultSet lastResults;
 579     public static boolean saveOrDiscardLastResults() {
 580         if (lastResults != null) {
 581             int ret = JOptionPane.showConfirmDialog
 582                 (guiFrame,
 583                  "The results of the last test will be "+
 584                  "discarded if you continue!  Do you want "+
 585                  "to save them?",
 586                  "Discard last results?",
 587                  JOptionPane.YES_NO_CANCEL_OPTION);
 588             if (ret == JOptionPane.CANCEL_OPTION) {
 589                 return false;
 590             } else if (ret == JOptionPane.YES_OPTION) {
 591                 if (saveResults()) {
 592                     lastResults = null;
 593                 } else {
 594                     return false;
 595                 }
 596             }
 597         }
 598         return true;
 599     }
 600 
 601     public static String inputUserStr(String type) {
 602         return JOptionPane.showInputDialog("Enter a "+
 603                                            type+
 604                                            " for this result set:");
 605     }
 606 
 607     public static boolean saveResults() {
 608         return saveResults(inputUserStr("title"), inputUserStr("description"));
 609     }
 610 
 611     public static boolean saveResults(String title, String desc) {
 612         lastResults.setTitle(title);
 613         lastResults.setDescription(desc);
 614         JFileChooser fc = getFileChooser();
 615         int ret = fc.showSaveDialog(guiFrame);
 616         if (ret == JFileChooser.APPROVE_OPTION) {
 617             File file = fc.getSelectedFile();
 618             boolean append = false;
 619             if (file.exists()) {
 620                 if (!file.isFile()) {
 621                     System.err.println("Cannot save results to a directory!");
 622                     return false;
 623                 }
 624                 ret = JOptionPane.showOptionDialog
 625                     (guiFrame,
 626                      new String[] {
 627                          "The file '"+file.getName()+"' already exists!",
 628                          "",
 629                          "Do you wish to overwrite or append to this file?",
 630                      },
 631                      "File exists!",
 632                      JOptionPane.DEFAULT_OPTION,
 633                      JOptionPane.WARNING_MESSAGE,
 634                      null, new String[] {
 635                          "Overwrite",
 636                          "Append",
 637                          "Cancel",
 638                      }, "Cancel");
 639                 if (ret == 0) {
 640                     append = false;
 641                 } else if (ret == 1) {
 642                     append = true;
 643                 } else {
 644                     return false;
 645                 }
 646             }
 647             String reason = saveResults(file, append);
 648             if (reason == null) {
 649                 return true;
 650             } else {
 651                 System.err.println(reason);
 652             }
 653         }
 654         return false;
 655     }
 656 
 657     public static String saveResults(String filename, boolean append) {
 658         FileWriter fw;
 659         try {
 660             fw = new FileWriter(filename, append);
 661         } catch (IOException e) {
 662             return "Error opening results file "+filename;
 663         }
 664         return saveResults(fw, filename, append);
 665     }
 666 
 667     public static String saveResults(File file, boolean append) {
 668         FileWriter fw;
 669         try {
 670             fw = new FileWriter(file, append);
 671         } catch (IOException e) {
 672             return "Error opening results file "+file.getName();
 673         }
 674         return saveResults(fw, file.getName(), append);
 675     }
 676 
 677     public static String saveResults(FileWriter fw, String filename,
 678                                      boolean append)
 679     {
 680         PrintWriter pw = new PrintWriter(fw);
 681         if (!append) {
 682             pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
 683             pw.println("<!--For Entertainment Purposes Only-->");
 684         }
 685         pw.println();
 686         lastResults.write(pw);
 687         pw.flush();
 688         pw.close();
 689         return null;
 690     }
 691 
 692     public static void startGUI() {
 693         final JFrame f = new JFrame("J2DBench") {
 694             public Dimension getPreferredSize() {
 695                 Dimension pref = super.getPreferredSize();
 696                 pref.width = Math.max(pref.width, 800);
 697                 pref.height = Math.max(pref.height, 600);
 698                 return pref;
 699             }
 700         };
 701         guiFrame = f;
 702         f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 703         f.getContentPane().setLayout(new BorderLayout());
 704         f.getContentPane().add(Group.root.getJComponent(), BorderLayout.CENTER);
 705         JPanel p = new JPanel();
 706         p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
 707         JButton b = new JButton("Run Tests...");
 708         b.addActionListener(new ActionListener() {
 709             public void actionPerformed(ActionEvent e) {
 710                 if (!saveOrDiscardLastResults()) {
 711                     return;
 712                 }
 713                 if (verbose.isEnabled()) {
 714                     System.out.println(e);
 715                     System.out.println("running tests...");
 716                 }
 717                 new Thread(new Runnable() {
 718                     public void run() {
 719                         runTests(true);
 720                     }
 721                 }).start();
 722                 if (verbose.isEnabled()) {
 723                     System.out.println("done");
 724                 }
 725             }
 726         });
 727         p.add(b);
 728 
 729         b = new JButton("Load Options");
 730         b.addActionListener(new ActionListener() {
 731             public void actionPerformed(ActionEvent e) {
 732                 JFileChooser fc = getFileChooser();
 733                 int ret = fc.showOpenDialog(f);
 734                 if (ret == JFileChooser.APPROVE_OPTION) {
 735                     String reason = loadOptions(fc.getSelectedFile());
 736                     if (reason != null) {
 737                         System.err.println(reason);
 738                     }
 739                 }
 740             }
 741         });
 742         p.add(b);
 743 
 744         b = new JButton("Save Options");
 745         b.addActionListener(new ActionListener() {
 746             public void actionPerformed(ActionEvent e) {
 747                 JFileChooser fc = getFileChooser();
 748                 int ret = fc.showSaveDialog(f);
 749                 if (ret == JFileChooser.APPROVE_OPTION) {
 750                     String reason = saveOptions(fc.getSelectedFile());
 751                     if (reason != null) {
 752                         System.err.println(reason);
 753                     }
 754                 }
 755             }
 756         });
 757         p.add(b);
 758 
 759         b = new JButton("Save Results");
 760         b.addActionListener(new ActionListener() {
 761             public void actionPerformed(ActionEvent e) {
 762                 if (saveResults()) {
 763                     lastResults = null;
 764                 }
 765             }
 766         });
 767         p.add(b);
 768 
 769         b = new JButton("Quit");
 770         b.addActionListener(new ActionListener() {
 771             public void actionPerformed(ActionEvent e) {
 772                 if (!saveOrDiscardLastResults()) {
 773                     return;
 774                 }
 775                 System.exit(0);
 776             }
 777         });
 778         p.add(b);
 779 
 780         f.getContentPane().add(p, BorderLayout.SOUTH);
 781         f.pack();
 782         f.setLocationRelativeTo(null);
 783         f.show();
 784     }
 785 
 786     public static void runTests(boolean showresults) {
 787         final TestEnvironment env = new TestEnvironment();
 788         Frame f = null;
 789         if (showresults) {
 790             f = new Frame("J2DBench test run");
 791             f.addWindowListener(new WindowAdapter() {
 792                 public void windowClosing(WindowEvent e) {
 793                     env.stop();
 794                 }
 795             });
 796             f.add(env.getCanvas());
 797             f.pack();
 798             f.show();
 799         }
 800         for (int i = 0; i < 5; i++) {
 801             env.idle();
 802         }
 803         env.runAllTests();
 804         if (showresults) {
 805             f.hide();
 806             f.dispose();
 807         }
 808         lastResults = env.results;
 809         if (J2DBench.printresults.isEnabled()) {
 810             System.out.println();
 811         }
 812         System.out.println("All test results:");
 813         env.summarize();
 814         System.out.println();
 815     }
 816 }