1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest;
  28 
  29 import java.io.File;
  30 import java.io.IOException;
  31 import java.io.PrintWriter;
  32 import java.util.Iterator;
  33 
  34 import com.sun.interview.WizPrint;
  35 import com.sun.javatest.httpd.JThttpProvider;
  36 import com.sun.javatest.httpd.PageGenerator;
  37 import com.sun.javatest.httpd.RootRegistry;
  38 import com.sun.javatest.httpd.httpURL;
  39 import com.sun.javatest.util.I18NResourceBundle;
  40 import com.sun.javatest.util.PropertyArray;
  41 import com.sun.javatest.util.StringArray;
  42 
  43 class HarnessHttpHandler extends JThttpProvider
  44     implements Harness.Observer
  45 {
  46     HarnessHttpHandler(Harness harness) {
  47         this.harness = harness;
  48         harness.addObserver(this);
  49     }
  50 
  51     public void serviceRequest(httpURL requestURL, PrintWriter out) {
  52         String nf = requestURL.getNextFile();
  53         if (nf == null) {                           // request for root
  54             beginGood(out);
  55             printHtml(out);
  56         }
  57         else if (nf.equals("env")) {                // environment dump
  58             beginGood(out);
  59             printEnv(out);
  60         }
  61         else if (nf.equals("interview")) {          // interview dump
  62             beginGood(out);
  63             printInterview(out);
  64         }
  65         else if (nf.equals("text"))                 // get text only data
  66             printText(requestURL, out);
  67         else if (nf.equals("stop")) {       // stop the harness
  68             if (!harness.isRunning()) {
  69                 println(out, i18n.getString("harnessHttp.noStop"));
  70             }
  71             else {
  72                 // generate the token if it hasn't already been
  73                 beginGood(out);
  74                 if (magicToken == null) {
  75                     long num = Math.round(Math.floor(Math.random() * 30000.0 ));
  76                     magicToken = Integer.toString((int)num);
  77                 }
  78 
  79                 PageGenerator.writeHeader(out, i18n.getString("harnessHttp.stop.hdr"));
  80                 PageGenerator.startBody(out);
  81 
  82                 String token = requestURL.getValue("token");
  83                 if (token == null)
  84                     printStopConfirm(out);
  85                 else if (token.equals(magicToken)) {
  86                     harness.stop();
  87                     println(out, i18n.getString("harnessHttp.stopped"));
  88                 }
  89                 else {
  90                     printStopErr(out);
  91                 }
  92 
  93                 out.println("<hr>");
  94                 PageGenerator.writeFooter(out);
  95                 PageGenerator.endBody(out);
  96                 PageGenerator.writeEndDoc(out);
  97             }
  98         }
  99         else {                              // bad url
 100             if (debug)
 101                 System.out.println("TRT.HH-remainder of URL unknown (" + nf + ")");
 102 
 103             beginBad(out);
 104             printHtml(out);
 105         }
 106 
 107         out.close();
 108     }
 109 
 110     private void beginGood(PrintWriter out) {
 111         PageGenerator.generateOkHttp(out);
 112         PageGenerator.generateDocType(out, PageGenerator.HTML32);
 113     }
 114 
 115     private void beginBad(PrintWriter out) {
 116         PageGenerator.generateBadHttp(out);
 117         PageGenerator.generateDocType(out, PageGenerator.HTML32);
 118     }
 119 
 120     /**
 121      * Print the basic HTML page for Harness.
 122      */
 123     private void printHtml(PrintWriter out) {
 124         PageGenerator.writeBeginDoc(out);
 125 
 126         printIndex(out);
 127 
 128         out.println("<hr>");
 129         PageGenerator.writeFooter(out);
 130         PageGenerator.endBody(out);
 131         PageGenerator.writeEndDoc(out);
 132     }
 133 
 134     /**
 135      * Print the environment settings in formatted HTML.
 136      */
 137     private void printEnv(PrintWriter out) {
 138         PageGenerator.writeBeginDoc(out);
 139         PageGenerator.writeHeader(out, i18n.getString("harnessHttp.env.title"));
 140 
 141         out.print("<h3>");
 142         print(out, i18n.getString("harnessHttp.env.hdr"));
 143         out.println("</h3>");
 144 
 145         Parameters params = harness.getParameters();
 146         if (params != null)
 147             printEnv(out, params.getEnv());
 148         else
 149             out.println(i18n.getString("harnessHttp.env.none"));
 150 
 151         out.println("<hr>");
 152         PageGenerator.writeFooter(out);
 153         PageGenerator.endBody(out);
 154         PageGenerator.writeEndDoc(out);
 155     }
 156 
 157     /**
 158      * Print the interview settings in formatted HTML.
 159      */
 160     private void printInterview(PrintWriter out) {
 161         PageGenerator.writeBeginDoc(out);
 162         PageGenerator.writeHeader(out, i18n.getString("harnessHttp.interview.title"));
 163 
 164         out.print("<h3>");
 165         print(out, i18n.getString("harnessHttp.interview.hdr"));
 166         out.println("</h3>");
 167 
 168         try {
 169             Parameters params = harness.getParameters();
 170             if (params == null ||
 171                 !(harness.getParameters() instanceof InterviewParameters)) {
 172                 println(out, i18n.getString("harnessHttp.interview.none"));
 173             }
 174             else {
 175                 InterviewParameters interview = (InterviewParameters)(harness.getParameters());
 176                 WizPrint wp = new WizPrint(interview);
 177                 wp.setShowResponses(true);
 178                 wp.setShowResponseTypes(true);
 179                 wp.setShowTags(true);
 180                 wp.write(out);
 181             }   // else
 182 
 183             out.println("<hr>");
 184             PageGenerator.writeFooter(out);
 185             PageGenerator.endBody(out);
 186             PageGenerator.writeEndDoc(out);
 187         }   // try
 188         catch (IOException e) {
 189             println(out, i18n.getString("harnessHttp.ioProblem"));
 190         }   // catch
 191     }
 192 
 193     /**
 194      * Access to raw text output pages.
 195      * We choose to not including the standard HTTP response header when
 196      * returning plain text.  This makes it easier to process on the client side.
 197      */
 198     private void printText(httpURL requestURL, PrintWriter out) {
 199         // write directly to out in this method, we are not
 200         // transmitting HTML encoded data
 201         Parameters params = harness.getParameters();
 202         String nf = requestURL.getNextFile();
 203         if (nf == null) {
 204             beginGood(out);
 205             printIndex(out);
 206         }
 207         else if (nf.equals("env")) {
 208             // special case for incomplete interview?
 209 
 210             TestEnvironment env = params.getEnv();
 211 
 212             if (env == null) {
 213                 print(out, i18n.getString("harnessHttp.env.none"));
 214                 return;
 215             }
 216 
 217             /* does not fit in the properties style output
 218             out.print(i18n.getString("harnessHttp.env.name"));
 219             out.println(env.getName());
 220             */
 221 
 222             String[] pa = new String[0];
 223 
 224             for (Iterator<TestEnvironment.Element> i = env.elements().iterator(); i.hasNext(); ) {
 225                 TestEnvironment.Element elem = i.next();
 226                 // this is stunningly inefficient and should be fixed
 227                 pa = PropertyArray.put(pa, elem.getKey(), elem.getValue());
 228             }
 229 
 230             try {
 231                 PropertyArray.save(pa, out);
 232             }
 233             catch (IOException e) {
 234                 // this is probably useless since problems with out
 235                 // probably caused this
 236                 out.println(i18n.getString("harnessHttp.ioProblem"));
 237             }
 238         }
 239         else if (nf.equals("config")) {
 240             if (params == null) {
 241                 out.print(i18n.getString("harnessHttp.text.unavail"));
 242                 return;
 243             }
 244 
 245             // test suite info
 246             TestSuite ts = params.getTestSuite();
 247             out.print(i18n.getString("harnessHttp.text.ts.path"));
 248             out.print("=");
 249             if (ts != null) {
 250                 out.println(ts.getPath());
 251             }
 252             else
 253                 out.println(i18n.getString("harnessHttp.text.empty"));
 254 
 255             out.print(i18n.getString("harnessHttp.text.ts.name"));
 256             out.print("=");
 257             if (ts != null) {
 258                 out.println(ts.getName());
 259             }
 260             else
 261                 out.println(i18n.getString("harnessHttp.text.empty"));
 262 
 263             out.print(i18n.getString("harnessHttp.text.wd.val"));
 264             out.print("=");
 265             WorkDirectory wd = params.getWorkDirectory();
 266             if (wd != null)
 267                 out.println(wd.getPath());
 268             else
 269                 out.println(i18n.getString("harnessHttp.text.empty"));
 270         }
 271         else if (nf.equals("tests")) {
 272             if (params == null) {
 273                 out.print(i18n.getString("harnessHttp.text.unavail"));
 274                 return;
 275             }
 276 
 277             String[] tests = params.getTests();
 278             if (tests != null && tests.length != 0) {
 279                 for (int i = 0; i < tests.length; i++) {
 280                     out.print("url");
 281                     out.print(Integer.toString(i));
 282                     out.print("=");
 283                     out.println(tests[i]);
 284                 }   // for
 285             }
 286         }
 287         else if (nf.equals("stats")) {
 288             if (!harness.isRunning()) {
 289                 out.println("");
 290                 return;
 291             }
 292 
 293             stats[Status.NOT_RUN] = harness.getTestsFoundCount() - stats[Status.PASSED] -
 294                                 stats[Status.FAILED] - stats[Status.ERROR];
 295 
 296             for (int i = 0; i < Status.NUM_STATES; i++) {
 297                 out.print((Status.typeToString(i)).replace(' ', '_'));
 298                 out.print("=");
 299                 out.println(stats[i]);
 300             }   // for
 301         }
 302         else if (nf.equals("state")) {
 303             // provide information about the Harness' state
 304             print(out, i18n.getString("harnessHttp.state.run.val"));
 305             out.println(harness.isRunning());
 306         }
 307         else if (nf.equals("results")) {
 308             // test dump
 309             TestResultTable trt = harness.getResultTable();
 310             TestFilter[] filters = params.getFilters();
 311             String[] tests = params.getTests();
 312 
 313             Iterator<TestResult> it = null;
 314             if (tests == null || tests.length == 0)
 315                 it = trt.getIterator(filters);
 316             else
 317                 it = trt.getIterator(params.getTests(), filters);
 318 
 319             while (it.hasNext()) {
 320                 TestResult tr = it.next();
 321                 out.println(tr.getTestName());
 322                 out.println(tr.getStatus().toString());
 323             }   // while
 324         }
 325         else {
 326             if (debug)
 327                 System.out.println("TRT.HH-remainder of URL unknown (" + nf + ")");
 328 
 329             println(out, i18n.getString("harnessHttp.badRequest", requestURL.getFullPath()));
 330         }
 331     }
 332 
 333     private void printStopConfirm(PrintWriter out) {
 334         out.print("<h2>");
 335         print(out, i18n.getString("harnessHttp.stopConfirm.hdr"));
 336         out.println("</h2>");
 337         out.print("<h4>");
 338         print(out, i18n.getString("harnessHttp.stopConfirm.txt"));
 339         out.println("</h4>");
 340         out.print("<Form method=get enctype=application/x-www-form-urlencoded>");
 341 
 342         out.print("<p><Input align=center type=submit value=");
 343         out.print(i18n.getString("harnessHttp.stopConfirm.btn"));
 344         out.println(">");
 345         out.print("<Input type=hidden name=token value=");
 346         out.print(magicToken);
 347         out.println("></Form>");
 348     }
 349 
 350     private void printStopErr(PrintWriter out) {
 351         out.println("<h2>");
 352         println(out, i18n.getString("harnessHttp.stopErr.hdr"));
 353         out.println("</h2>");
 354         out.println("<b>");
 355         println(out, i18n.getString("harnessHttp.stopErr.text1"));
 356         println(out, i18n.getString("harnessHttp.stopErr.text2"));
 357         out.println("</b>");
 358         out.println("<p>");
 359         println(out, i18n.getString("harnessHttp.stopErr.text3"));
 360         out.println("<a href=\"/harness/stop\">");
 361         println(out, i18n.getString("harnessHttp.stopErr.text4"));
 362         out.println("</a>");
 363         println(out, i18n.getString("harnessHttp.stopErr.text5"));
 364     }
 365 
 366     private void printIndex(PrintWriter out) {
 367         PageGenerator.writeHeader(out, i18n.getString("harnessHttp.index.title"));
 368         PageGenerator.startBody(out);
 369         out.println("<h2>");
 370         out.print("JT Harness ™ ");
 371         println(out, i18n.getString("harnessHttp.index.hdr"));
 372         out.println("</h2>");
 373 
 374         Parameters params = harness.getParameters();
 375         if (params == null) {
 376             out.println(i18n.getString("harnessHttp.parameters.noParams"));
 377             return;
 378         }
 379 
 380         // print test suite
 381         print(out, i18n.getString("harnessHttp.parameters.tsName"));
 382         String name = params.getTestSuite().getName();
 383         println(out, (name == null ?
 384                       i18n.getString("harnessHttp.parameters.noTs") :
 385                       name));
 386 
 387         out.println("<br>");
 388         print(out, i18n.getString("harnessHttp.parameters.tsPath"));
 389         File tsr = params.getTestSuite().getRoot();
 390         println(out, (tsr == null ?
 391                       i18n.getString("harnessHttp.parameters.noTs") :
 392                       tsr.getPath()));
 393 
 394         out.println("<br>");
 395 
 396         // print workdir
 397         print(out, i18n.getString("harnessHttp.parameters.wd"));
 398 
 399         WorkDirectory wd = params.getWorkDirectory();
 400         if (wd != null)
 401             println(out, wd.getPath());
 402         else
 403             print(out, i18n.getString("harnessHttp.parameters.noWd"));
 404 
 405         out.println("<p>");
 406 
 407         // print parameters
 408         printParameters(out, params);
 409 
 410         // print results link
 411         TestResultTable currentResults = harness.getResultTable();
 412         out.println("<h3>");
 413         println(out, i18n.getString("harnessHttp.results.hdr"));
 414         out.println("</h3>");
 415         if (currentResults != null) {
 416             JThttpProvider trtProv = RootRegistry.getObjectHandler(currentResults);
 417             if (trtProv != null && trtProv.getRootURL() != null) {
 418                 out.print("<a href=\"");
 419                 out.print(trtProv.getRootURL());
 420                 out.print("\">");
 421                 print(out, i18n.getString("harnessHttp.trt.link"));
 422                 out.println("</a>");
 423             }
 424         }
 425         else {
 426             out.print(i18n.getString("harnessHttp.trt.none"));
 427         }
 428     }
 429 
 430     private void printParameters(PrintWriter out, Parameters params) {
 431         out.println("<h3>");
 432         println(out, i18n.getString("harnessHttp.parameters.hdr"));
 433         out.println("</h3>");
 434 
 435         print(out, i18n.getString("harnessHttp.parameters.env"));
 436         TestEnvironment tev = params.getEnv();
 437         if (tev != null) {
 438             out.print("<a href=\"");
 439             out.print(getRootURL());
 440             out.print("/env\">");
 441 
 442             print(out, tev.getName());
 443             out.println("</a>");
 444         }
 445         else {
 446             println(out, i18n.getString("harnessHttp.parameters.noEnv"));
 447         }
 448 
 449         out.println("<br>");
 450 
 451         print(out, i18n.getString("harnessHttp.parameters.interview"));
 452         if (params instanceof InterviewParameters) {
 453             InterviewParameters ip = (InterviewParameters)params;
 454             File ipf = ip.getFile();
 455 
 456             out.print("<a href=\"");
 457             out.print(getRootURL());
 458             out.print("/interview\">");
 459             print(out, (ipf == null ?
 460                        i18n.getString("harnessHttp.parameters.noInterviewFile") :
 461                        ipf.getPath()));
 462             out.println("</a>");
 463         }
 464         else {
 465             println(out, i18n.getString("harnessHttp.parameters.noInterview"));
 466         }
 467 
 468         out.println("<p>");
 469 
 470         // initial files info
 471         out.println("<ul>");
 472         out.print("<li>");
 473         print(out, i18n.getString("harnessHttp.parameters.urls"));
 474         printTests(out);
 475 
 476         // jtx info
 477         out.print("<li>");
 478         print(out, i18n.getString("harnessHttp.parameters.jtx"));
 479         Parameters.ExcludeListParameters exclParams = params.getExcludeListParameters();
 480 
 481         if (exclParams instanceof Parameters.MutableExcludeListParameters) {
 482             Parameters.MutableExcludeListParameters e =
 483                 (Parameters.MutableExcludeListParameters) (exclParams);
 484             File[] jtx = e.getExcludeFiles();
 485             if (jtx == null || jtx.length == 0)
 486                 println(out, i18n.getString("harnessHttp.parameters.emptyJtx"));
 487             else {
 488                 out.println("<ul>");
 489                 for (int i = 0; i < jtx.length; i++)
 490                     out.println("<li>" + jtx[i].getPath());
 491 
 492                 out.println("</ul>");
 493             }
 494         }
 495         else {
 496             println(out, i18n.getString("harnessHttp.parameters.noJtx"));
 497         }
 498 
 499         // keyword info
 500         /* removed until output can be improved
 501         out.print("<li>");
 502         print(out, i18n.getString("harnessHttp.parameters.keyw"));
 503         out.println(params.getKeywords());
 504         */
 505 
 506         out.println("</ul>");
 507 
 508         // status
 509     }
 510 
 511     private void printTests(PrintWriter out) {
 512         String[] tests = harness.getParameters().getTests();
 513         if (tests == null || tests.length == 0) {
 514             print(out, i18n.getString("harnessHttp.parameters.noTests"));
 515         }
 516         else {
 517             out.println("<ul>");
 518 
 519             for (int i = 0; i < tests.length; i++) {
 520                 out.println("<li>");
 521                 println(out, tests[i]);
 522             }
 523 
 524             out.println("</ul>");
 525         }
 526     }   // printTests()
 527 
 528     private void printEnv(PrintWriter out, TestEnvironment env) {
 529         out.print(i18n.getString("harnessHttp.env.name"));
 530         println(out, env.getName());
 531 
 532         String keyHeader = "Key";
 533         String valHeader = "Value";
 534 
 535         out.println("<Table Border>");
 536 
 537         StringBuffer buf = new StringBuffer(50);
 538 
 539         // write the table header
 540         buf.append("<tr><th>");
 541         buf.append(filterTags(keyHeader));
 542         buf.append("<th>");
 543         buf.append(filterTags(valHeader));
 544         buf.append("</tr>");
 545         out.println(buf.toString());
 546 
 547         for (Iterator<String> keys = env.keys().iterator(); keys.hasNext(); ) {
 548             String key = keys.next();
 549             out.println("<tr>");
 550             buf.setLength(0);
 551             buf.append("<td>");
 552             buf.append(key.toString());
 553             buf.append("<td>");
 554             try {
 555                 buf.append(filterTags(StringArray.join((env.lookup(key)))));
 556             }
 557             catch (TestEnvironment.Fault f) {
 558                 buf.append(i18n.getString("harnessHttp.env.error"));
 559             }
 560 
 561             out.println(buf.toString());
 562             out.println("</tr>");
 563         }   // while
 564 
 565         out.println("</Table>");
 566     }
 567 
 568     // ------------ instance vars ------------
 569     private Harness harness;
 570     private boolean debug = false;
 571     private String magicToken;
 572     private int[] stats = new int[Status.NUM_STATES];
 573     private TestFinderQueue tfq;
 574     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(HarnessHttpHandler.class);
 575 
 576     // ------------ Harness.Observer ------------
 577     public void startingTestRun(Parameters params) { }
 578 
 579     public void startingTest(TestResult tr) { }
 580 
 581     public void finishedTest(TestResult tr) {
 582         stats[tr.getStatus().getType()]++;
 583     }
 584 
 585     public void stoppingTestRun() { }
 586     public void finishedTesting() { }
 587     public void finishedTestRun(boolean allOK) { }
 588 
 589     public void error(String msg) { }
 590 }