1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 1996, 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.lib;
  28 
  29 import java.util.Iterator;
  30 import java.util.Set;
  31 import java.util.Vector;
  32 import java.io.IOException;
  33 import java.io.PrintWriter;
  34 
  35 import com.sun.javatest.Script;
  36 import com.sun.javatest.Status;
  37 import com.sun.javatest.TestResult;
  38 import com.sun.javatest.TestDescription;
  39 import com.sun.javatest.TestEnvironment;
  40 import com.sun.javatest.util.StringArray;
  41 
  42 /**
  43  * Default script, which delegates to one of a number of scripts defined in
  44  * environment entries, according to the keywords on the test description.
  45  */
  46 public class KeywordScript extends Script
  47 {
  48     /**
  49      * Run the script, using the parameters set up by the standard initialization
  50      * methods.
  51      */
  52     public void run() {
  53 
  54         PrintWriter trOut = getTestResult().getTestCommentWriter();
  55         TestDescription td = getTestDescription();
  56 
  57         for (int i = 0; i < scriptArgs.length; i++) {
  58             if (scriptArgs[i].equals("-debug"))
  59                 debug = true;
  60             else {
  61                 setStatus(Status.error("bad args for script: " + scriptArgs[i]));
  62                 return;
  63             }   // else
  64         }   // for
  65 
  66         String prefix = "script.";
  67         Set<String> testKeys = td.getKeywordTable();
  68         Vector<String> choices = new Vector<>(); // the set of choices
  69         Vector<String> matches = new Vector<>(); // the set of matches
  70         int wordsMatchingInMatches = 0;// the number of words matching
  71 
  72     findMatch:
  73         for (Iterator<String> iter = env.keys().iterator(); iter.hasNext(); ) {
  74             String key = (iter.next());
  75 
  76             // if the key does not begin with the `script.' prefix, ignore key
  77             if (!key.startsWith(prefix))
  78                 continue;
  79 
  80             if (debug)
  81                 trOut.println("CHECKING " + key);
  82 
  83             String keyList = key.substring(prefix.length()).replace('_', ' ').toLowerCase();
  84             String[] keys = StringArray.split(keyList);
  85 
  86             choices.addElement(keyList);
  87 
  88             if (debug)
  89                 trOut.println("keys: " + StringArray.join(keys));
  90 
  91             // if there are no words after the `script.' prefix,
  92             // or if it has fewer words than the best match so far, ignore key
  93             if (keys == null || keys.length < wordsMatchingInMatches)
  94                 continue;
  95 
  96             for (int i = 0; i < keys.length; i++) {
  97                 // if key has a word that is not for the test, ignore key
  98                 if (!testKeys.contains(keys[i])) {
  99 
 100                     if (debug)
 101                         trOut.println("discarding, because of " + keys[i]);
 102 
 103                     continue findMatch;
 104                 }
 105             }
 106 
 107             // see if key is better than best so far
 108             if (keys.length > wordsMatchingInMatches) {
 109                 // update best so far
 110 
 111                 if (debug)
 112                     trOut.println("new best match, " + keys.length + " keys");
 113 
 114                 matches = new Vector<>();
 115                 wordsMatchingInMatches = keys.length;
 116             }
 117 
 118             // this key deserves note
 119             matches.addElement(key);
 120         }   // for
 121 
 122         // check we have a unique script selected
 123         String name = env.getName();
 124         String envName = (name.length() == 0 ?
 125                           "The anonymous environment" :
 126                           "Environment `" + env.getName() + "'");
 127         if (matches.size() == 0) {
 128             if (choices.size() == 0) {
 129                 String s = envName + " has no `script' entries";
 130                 trOut.println(s);
 131                 setStatus(Status.error(s));
 132                 return;
 133             }
 134             else {
 135                 String s = envName + " has no suitable `script' entry";
 136                 trOut.println(s);
 137                 trOut.println("The keyword combinations for scripts in this environment are: ");
 138                 for (int i = 0; i < choices.size(); i++) {
 139                     trOut.println(choices.elementAt(i));
 140                 }   // for
 141 
 142                 setStatus(Status.error(s));
 143                 return;
 144             }   // inner else
 145         } else if (matches.size() > 1) {
 146             String s = envName + " has ambiguous `script' entries";
 147             trOut.println(s);
 148             for (int i = 0; i < matches.size(); i++) {
 149                 trOut.println(i + ": " + matches.elementAt(i));
 150             }   // for
 151 
 152             setStatus(Status.error(s));
 153             return;
 154         }   // else if
 155 
 156         String bestScript = matches.elementAt(0);
 157         //trOut.report.println("BEST " + bestScript);
 158 
 159         try {
 160             String[] command = env.lookup(bestScript);
 161             if (command.length == 0) {
 162                 String s = "INTERNAL ERROR: failed to lookup key: " + bestScript;
 163                 trOut.println(s);
 164                 setStatus(Status.error(s));
 165                 return;
 166             }
 167 
 168             trOut.println("test: " + td.getRootRelativeURL());
 169             trOut.println("script: " + this.getClass().getName() + " " +
 170                           StringArray.join(scriptArgs));
 171 
 172             String[] msgs = {
 173                 "Based on these keywords:    " +
 174                 bestScript.substring(prefix.length()).replace('_', ' ').toLowerCase(),
 175                 "this script has now been selected: " + "   " +
 176                 StringArray.join(command) };
 177             printStrArr(trOut, msgs);
 178 
 179             try {
 180                 Class<?> c = Class.forName(command[0]);
 181 
 182                 Script script = (Script)c.newInstance();
 183                 String[] scriptArgs = new String[command.length - 1];
 184                 System.arraycopy(command, 1, scriptArgs, 0, scriptArgs.length);
 185                 initDelegate(script, scriptArgs);
 186 
 187                 script.run();
 188             }
 189             catch (ClassNotFoundException ex) {
 190                 setStatus(Status.error("Can't find class `" +
 191                                      command[0] + "' for `" + env.getName() + "'"));
 192             }
 193             catch (IllegalAccessException ex) {
 194                 setStatus(Status.error("Illegal access to class `" +
 195                                      command[0] + "' for `" + env.getName() + "'"));
 196             }
 197             catch (InstantiationException ex) {
 198                 setStatus(Status.error("Can't instantiate class`" +
 199                                      command[0] + "' for `" + env.getName() + "'"));
 200             }
 201         }
 202         catch (TestEnvironment.Fault ex) {
 203             setStatus(Status.error("environment `" +
 204                                       env.getName() +
 205                                       "' has bad `script' entry for `" +
 206                                       bestScript +"'"));
 207         }
 208     }
 209 
 210     public Status run(String[] args, TestDescription td, TestEnvironment env) {
 211         throw new Error("Method not applicable.");
 212     }
 213 
 214     private static void printStrArr(PrintWriter pw, String[] data) {
 215         if(data == null) return;
 216 
 217         for(int i = 0; i < data.length; i++) {
 218             pw.println(data[i]);
 219         }
 220     }
 221 
 222     private void setStatus(Status s) {
 223         TestResult tr = getTestResult();
 224         tr.setEnvironment(env);
 225         tr.setStatus(s);
 226         try {
 227             tr.writeResults(workDir, backupPolicy);
 228         }
 229         catch (IOException e) {
 230             e.printStackTrace();
 231         }
 232     }
 233 
 234     private boolean debug = false;
 235 }