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.finder;
  28 
  29 import java.io.BufferedOutputStream;
  30 import java.io.File;
  31 import java.io.FileOutputStream;
  32 import java.io.IOException;
  33 import java.io.PrintStream;
  34 import java.nio.charset.StandardCharsets;
  35 import java.util.Iterator;
  36 
  37 import com.sun.javatest.TestDescription;
  38 import com.sun.javatest.TestFinder;
  39 
  40 /**
  41  * ShowTests is a utility program to show the tests that are read by
  42  * a test finder.
  43  */
  44 public class ShowTests
  45 {
  46     /**
  47      * This exception is used to report bad command line arguments.
  48      */
  49     public class BadArgs extends Exception {
  50         /**
  51          * Create a BadArgs exception.
  52          * @param msg A detail message about an error that has been found.
  53          */
  54         BadArgs(String msg) {
  55             super(msg);
  56         }
  57     }
  58 
  59     /**
  60      * This exception is used to report problems that occur while running.
  61      */
  62 
  63     public class Fault extends Exception {
  64         /**
  65          * Create a Fault exception.
  66          * @param msg A detail message about a fault that has occurred.
  67          */
  68         Fault(String msg) {
  69             super(msg);
  70         }
  71     }
  72 
  73     //------------------------------------------------------------------------------------------
  74 
  75     /**
  76      * Standard program entry point.
  77      * @param args      An array of strings, typically provided via the command line.
  78      * The arguments should be of the form:<br>
  79      * <em>[options]</em> <em>testsuite</em>
  80      * <table><tr><th colspan=2>Options</th></tr>
  81      * <tr><td>-finder <em>finderClass</em> <em>finderArgs</em> <em>...</em> -end
  82      *          <td>The name of a test finder class and any arguments it might take.
  83      *          The results of reading this test finder will be stored in the
  84      *          output file.
  85      * <tr><td>-initial <em>initial-file</em>
  86      *          <td>An initial file within the test suite at which to start reading tests.
  87      * <tr><td>-o <em>output-file</em>
  88      *          <td>The output file in which to write the results. If omitted,
  89      *          The results will be written to the standard console output stream.
  90      * <tr><td>-nodes
  91      *          <td>By default, only the names of the tests are output.
  92      *          If you specify this option, the names of the parent directories
  93      *          will be displayed as well.
  94      * <tr><td>-full]tests
  95      *          <td>By default, only the names of the tests are output.
  96      *          If you specify this option, the contents of the test descriptions
  97      *          will be displayed as well.
  98      * </table>
  99      */
 100     public static void main(String[] args) {
 101         try {
 102             if (args.length == 0)
 103                 usage(System.out);
 104             else {
 105                 ShowTests m = new ShowTests();
 106                 m.run(args);
 107             }
 108         }
 109         catch (BadArgs e) {
 110             System.err.println("Bad Arguments: " + e.getMessage());
 111             usage(System.err);
 112             System.exit(1);
 113         }
 114         catch (Fault f) {
 115             System.err.println("Error: " + f.getMessage());
 116             System.exit(2);
 117         }
 118         catch (IOException e) {
 119             System.err.println("Error: " + e);
 120             System.exit(3);
 121         }
 122     }
 123 
 124     /**
 125      * Print out command-line help.
 126      */
 127     private static void usage(PrintStream out) {
 128         String prog = System.getProperty("program", "java " + ShowTests.class.getName());
 129         out.println("Usage:");
 130         out.println("  " + prog + " [options]  test-suite");
 131         out.println("Options:");
 132         out.println("  -finder finderClass finderArgs... -end");
 133         out.println("                          specify the test finder to be used");
 134         out.println("  -initial initial-file   specify a starting point (optional)");
 135         out.println("  -o output-file          output file (default is standard output)");
 136         out.println("  -nodes                  show nodes in the tree");
 137         out.println("  -fulltests              show contents of tests");
 138     }
 139 
 140     //------------------------------------------------------------------------------------------
 141 
 142     /**
 143      * Main work method.
 144      * Reads all the arguments on the command line, makes sure a valid
 145      * testFinder is available, and then calls methods to create the tree of tests
 146      * and then write the binary file.
 147      *
 148      * @param args      An array of strings, typically provided via the command line
 149      * @throws ShowTests.BadArgs
 150      *                  if a problem is found in the arguments provided
 151      * @throws ShowTests.Fault
 152      *                  if a fault is found while running
 153      * @throws IOException
 154      *                  if a problem is found while trying to read a file
 155      * @see #main
 156      */
 157     public void run(String[] args) throws BadArgs, Fault, IOException {
 158         File testSuite = null;
 159         String finder = null;
 160         String[] finderArgs = null;
 161         File outFile = null;
 162         File initialFile = null;
 163 
 164         for (int i = 0; i < args.length; i++) {
 165             if (args[i].equalsIgnoreCase("-finder") && (i + 1 < args.length)) {
 166                 finder = args[++i];
 167                 int j = ++i;
 168                 while ((i < args.length - 1) && !(args[i].equalsIgnoreCase("-end")))
 169                     ++i;
 170                 finderArgs = new String[i - j];
 171                 System.arraycopy(args, j, finderArgs, 0, finderArgs.length);
 172             }
 173             else if (args[i].equalsIgnoreCase("-initial") && (i + 1 < args.length)) {
 174                 initialFile = new File(args[++i]);
 175             }
 176             else if (args[i].equalsIgnoreCase("-o") && (i + 1 < args.length)) {
 177                 outFile = new File(args[++i]);
 178             }
 179             else if (args[i].equalsIgnoreCase("-nodes")) {
 180                 nodes = true;
 181             }
 182             else if (args[i].equalsIgnoreCase("-fulltests")) {
 183                 fullTests = true;
 184             }
 185             else if (args[i].startsWith("-") ) {
 186                 throw new BadArgs(args[i]);
 187             }
 188             else
 189                 testSuite = new File(args[i]);
 190         }
 191 
 192         if (finder == null)
 193             throw new BadArgs("no test finder specified");
 194 
 195         if (testSuite == null)
 196             throw new BadArgs("testsuite.html file not specified");
 197 
 198         testFinder = initializeTestFinder(finder, finderArgs, testSuite);
 199 
 200         if (initialFile == null)
 201             initialFile = testFinder.getRoot(); // equals testSuite, adjusted by finder as necessary .. e.g. for dirWalk, webWalk etc
 202 
 203         if (outFile == null)
 204             out = System.out;
 205         else
 206             out = new PrintStream(new BufferedOutputStream(new FileOutputStream(outFile)), true, StandardCharsets.UTF_8.name());
 207 
 208         // read the tests and write them to output
 209         list(initialFile);
 210     }
 211 
 212     //------------------------------------------------------------------------------------------
 213 
 214     /**
 215      * Creates and initializes an instance of a test finder
 216      *
 217      * @param finder The class name of the required test finder
 218      * @param args any args to pass to the TestFinder's init method.
 219      * @param ts The testsuite root file
 220      * @return The newly created TestFinder.
 221      */
 222     private TestFinder initializeTestFinder(String finder, String[] args, File ts) throws Fault {
 223         TestFinder testFinder;
 224 
 225         try {
 226             Class<?> c = Class.forName(finder);
 227             testFinder = (TestFinder) (c.newInstance());
 228             testFinder.init(args, ts, null);
 229         }
 230         catch (ClassNotFoundException e) {
 231             throw new Fault("Error: Can't find class for TestFinder specified");
 232         }
 233         catch (InstantiationException e) {
 234             throw new Fault("Error: Can't create new instance of TestFinder");
 235         }
 236         catch (IllegalAccessException e) {
 237             throw new Fault("Error: Illegal Access Exception");
 238         }
 239         catch (TestFinder.Fault e) {
 240             throw new Fault("Error: Can't initialize test-finder: " + e.getMessage());
 241         }
 242 
 243         return testFinder;
 244     }
 245 
 246     //------------------------------------------------------------------------------------------
 247 
 248     private void list(File file) {
 249         if (nodes)
 250             out.println(file);
 251 
 252         testFinder.read(file);
 253         TestDescription[] tests = testFinder.getTests();
 254         File[] files = testFinder.getFiles();
 255 
 256         if (tests != null) {
 257             for (int i = 0; i < tests.length; i++) {
 258                 TestDescription td = tests[i];
 259                 out.println("    " + td.getRootRelativeURL());
 260                 if (fullTests) {
 261                     for (Iterator<String> iter = td.getParameterKeys(); iter.hasNext(); ) {
 262                         String key = (iter.next());
 263                         String value = td.getParameter(key);
 264                         out.print("        ");
 265                         out.print(key);
 266                         pad(key, 15);
 267                         out.print(value);
 268                         out.println();
 269                     }
 270                 }
 271             }
 272         }
 273 
 274         if (files != null) {
 275             for (int i = 0; i < files.length; i++)
 276                 list(files[i]);
 277         }
 278     }
 279 
 280     void pad(String s, int length) {
 281         for (int i = s.length(); i < length; i++)
 282             out.write(' ');
 283         out.write(' ');
 284     }
 285 
 286     //------------------------------------------------------------------------------------------
 287 
 288     private TestFinder testFinder;
 289     private PrintStream out;
 290     private boolean nodes;
 291     private boolean fullTests;
 292 }