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;
  28 
  29 import java.io.*;
  30 //import java.util.Hashtable;
  31 import java.nio.charset.StandardCharsets;
  32 import java.util.Iterator;
  33 import java.util.Map;
  34 import java.util.Vector;
  35 
  36 import com.sun.javatest.util.I18NResourceBundle;
  37 import com.sun.javatest.util.Properties;
  38 import com.sun.javatest.util.DynamicArray;
  39 //import com.sun.interview.Interview;
  40 
  41 /**
  42  * A table representing the collection of environments found in a set of environment files.
  43  */
  44 public class TestEnvContext
  45 {
  46     /**
  47      * This exception is to report problems using {@link TestEnvContext} objects.
  48      */
  49     public static class Fault extends Exception
  50     {
  51         Fault(I18NResourceBundle i18n, String s) {
  52             super(i18n.getString(s));
  53         }
  54 
  55         Fault(I18NResourceBundle i18n, String s, Object o) {
  56             super(i18n.getString(s, o));
  57         }
  58 
  59         Fault(I18NResourceBundle i18n, String s, Object[] o) {
  60             super(i18n.getString(s, o));
  61         }
  62     }
  63 
  64     /**
  65      * Create a context from a set of environment (.jte) files.
  66      * @param files The environment files to read
  67      * @throws TestEnvContext.Fault if an error is found while reading the files
  68      */
  69     public TestEnvContext(File[] files) throws Fault {
  70         Vector<String> n = new Vector<>();
  71         Vector<Map<String, String>> p = new Vector<>();
  72         try {
  73             if (files != null) {
  74                 for (int i = 0; i < files.length; i++) {
  75                     File f = files[i];
  76                     add(p, n, load(f), f.getPath());
  77                 }
  78             }
  79         }
  80         finally {
  81             propTables = new Map[p.size()];
  82             p.copyInto(propTables);
  83             propTableNames = new String[n.size()];
  84             n.copyInto(propTableNames);
  85             updateEnvTable();
  86         }
  87     }
  88 
  89     /**
  90      * Create a context from a specified set of named tables.
  91      * @param tables An array of tables giving the properties to be read
  92      * @param tableNames An array of names, one for each table in the tables array,
  93      *  that will be used to identify the source of the properties in any
  94      *  environments that are created
  95      */
  96     public TestEnvContext(Map[] tables, String[] tableNames) {
  97         Vector<String> n = new Vector<>();
  98         Vector<Map<String, String>> p = new Vector<>();
  99         for (int i = 0; i < tables.length; i++) {
 100             add(p, n, tables[i], tableNames[i]);
 101         }
 102         propTables = new Map[p.size()];
 103         p.copyInto(propTables);
 104         propTableNames = new String[n.size()];
 105         n.copyInto(propTableNames);
 106         updateEnvTable();
 107     }
 108 
 109     /**
 110      * Create a context from a named table.
 111      * @param table A table giving the properties to be read
 112      * @param tableName The name that will be used to identify the source
 113      *   of the properties in any environments that are created.
 114      */
 115     public TestEnvContext(Map table, String tableName) {
 116         Vector<String> n = new Vector<>();
 117         Vector<Map<String, String>> p = new Vector<>();
 118         add(p, n, table, tableName);
 119         propTables = new Map[p.size()];
 120         p.copyInto(propTables);
 121         propTableNames = new String[n.size()];
 122         n.copyInto(propTableNames);
 123         updateEnvTable();
 124     }
 125 
 126     /**
 127      * Get a environment from this set of environments.
 128      * @param name the name of the desired environment
 129      * @return the specified environment, or null if not found
 130      * @throws TestEnvironment.Fault if there is a problem creating
 131      *          the specified environment
 132      */
 133     public TestEnvironment getEnv(String name) throws TestEnvironment.Fault {
 134         if (isValidEnv(name))
 135             return new TestEnvironment(name, propTables, propTableNames);
 136         else
 137             return null;
 138     }
 139 
 140     /**
 141      * Check if a name matches the name of one of the environments in this
 142      * set of environments.
 143      * @param name the name to check
 144      * @return true if and only if the name matches the name of one of the
 145      * environments in trhis set of environments
 146      */
 147     public boolean isValidEnv(String name) {
 148         // empty name is always valid (null is not)
 149         if (name.length() == 0)
 150             return true;
 151 
 152         for (int i = 0; i < envNames.length; i++)
 153             if (envNames[i].equals(name))
 154                 return true;
 155 
 156         return false;
 157     }
 158 
 159     /**
 160      * Get an array containing all the names of environments in this set of
 161      * environments.
 162      * @return an array containing the names of all the environments in this set
 163      */
 164     public String[] getEnvNames() {
 165         // does not include null string (for now)
 166         return envNames;
 167     }
 168 
 169     /**
 170      * Get an array containing all the names of environments that should
 171      * appear in a menu of valid environment names. This is all environment
 172      * names, excluding those environments that define an entry "menu=false".
 173      * @return an array containing the names of all the environments in this set
 174      * that should appear in a menu of valid environment names
 175      */
 176     public String[] getEnvMenuNames() {
 177         return envMenuNames;
 178     }
 179 
 180     private Map<String, String> load(File f) throws Fault {
 181         if (f == null)
 182             return null;
 183 
 184         try {
 185             InputStream in = new BufferedInputStream(new FileInputStream(f));
 186             Map<String, String> p = Properties.load(in);
 187             in.close();
 188 
 189             /*
 190             if (f.getName().endsWith(".jti" )) {  //BETTER TO GET THIS FROM SOMEWHERE
 191                 String interviewClassName = (String)p.get("INTERVIEW");
 192                 if (interviewClassName == null)
 193                     throw new Fault(i18n, "tec.noInterview", f);
 194                 Class c = Class.forName(interviewClassName);
 195                 Interview i = (Interview)(c.newInstance());
 196                 Map d = new Hashtable();
 197                 i.export(d);
 198                 return d;
 199             }
 200             else*/
 201                 return p;
 202         }
 203         catch (FileNotFoundException e) {
 204             throw new Fault(i18n, "tec.cantFindFile", f);
 205         }
 206         catch (IOException e) {
 207             throw new Fault(i18n, "tec.ioError", new Object[] {f, e});
 208         }
 209         /*
 210         catch (ClassNotFoundException e) {
 211             throw new Fault(i18n, "tec.interviewClassNotFound",
 212                             new Object[] {f, e.getMessage()});
 213         }
 214         */
 215         /*
 216         catch (IllegalAccessException e) {
 217             throw new Fault(i18n, "tec.interviewClassAccess",
 218                             new Object[] {f, e.getMessage()});
 219         }
 220         */
 221         /*
 222         catch (InstantiationException e) {
 223             throw new Fault(i18n, "tec.interviewClassInstantiation",
 224                             new Object[] {f, e.getMessage()});
 225         }
 226         */
 227     }
 228 
 229     private void add(Vector<Map<String, String>> pv, Vector<String> nv, Map<String, String> p, String n) {
 230         if (p != null) {
 231             pv.addElement(p);
 232             nv.addElement(n);
 233         }
 234     }
 235 
 236     private void updateEnvTable() {
 237         // the tables given to the constructor ...
 238         Map[] tables = propTables;
 239         String[] tableNames = propTableNames;
 240 
 241         // defaults given to TestEnvironment
 242         Map[] defaultTables = TestEnvironment.defaultPropTables;
 243         String[] defaultTableNames = TestEnvironment.defaultPropTableNames;
 244 
 245         // if there are defaults, merge them with the TestEnvContext tables
 246         // for the purposes of determining the EnvTable
 247         if (defaultTables != null && defaultTables.length > 0) {
 248             tables = DynamicArray.join(defaultTables, tables);
 249             tableNames = DynamicArray.join(defaultTableNames, tableNames);
 250         }
 251 
 252         Vector<String> allVec = new Vector<>();
 253         Vector<String> menuExcludeVec = new Vector<>();
 254 
 255         // scan all the property tables, looking for entries
 256         final String ENV_DOT = "env.";
 257         final String DOT_DESCRIPTION = ".description";
 258         final String DOT_FINDER = ".finder";
 259         final String DOT_SCRIPT = ".script";
 260         final String DOT_SCRIPT_DOT = ".script.";
 261         final String DOT_INHERITS = ".inherits";
 262         final String DOT_MENU = ".menu";
 263         final String DOT_TESTSUITE = ".testsuite";
 264 
 265         if (debug)
 266             System.err.println(getClass().getName() + ": trace");
 267 
 268         for (int i = 0; i < tables.length; i++) {
 269             if (debug)
 270                 System.err.println("Checking " + tableNames[i] + " for environments...");
 271 
 272             Map table = tables[i];
 273             for (Iterator ii = table.keySet().iterator(); ii.hasNext(); ) {
 274                 String prop = (String) (ii.next());
 275                 String name = null;
 276 
 277                 if (debug)
 278                     System.err.println("Checking property " + prop);
 279 
 280                 if (!prop.startsWith(ENV_DOT))
 281                     continue;
 282 
 283                 if (prop.endsWith(DOT_INHERITS)) {
 284                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_INHERITS.length());
 285                 }
 286                 else if (prop.endsWith(DOT_MENU)) {
 287                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_MENU.length());
 288                     String value = (String) (table.get(prop));
 289                     if ("false".equals(value))
 290                         sortedInsert(menuExcludeVec, name);
 291                 }
 292                 else if (prop.endsWith(DOT_DESCRIPTION)) {
 293                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_DESCRIPTION.length());
 294                 }
 295                 else if (prop.endsWith(DOT_FINDER)) {
 296                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_FINDER.length());
 297                 }
 298                 else if (prop.endsWith(DOT_SCRIPT)) {
 299                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_SCRIPT.length());
 300                 }
 301                 else if (prop.endsWith(DOT_TESTSUITE)) {
 302                     name = prop.substring(ENV_DOT.length(), prop.length() - DOT_TESTSUITE.length());
 303                 }
 304                 else {
 305                     int lastDot = prop.lastIndexOf('.');
 306                     int scriptStartIndex = lastDot - DOT_SCRIPT_DOT.length() + 1;
 307                     if (scriptStartIndex > 0 &&
 308                         prop.regionMatches(scriptStartIndex, DOT_SCRIPT_DOT, 0, DOT_SCRIPT_DOT.length())) {
 309                         name = prop.substring(ENV_DOT.length(), scriptStartIndex);
 310                     }
 311                     else
 312                         continue;
 313                 }
 314 
 315                 if (debug)
 316                     System.err.println("found environment name: " + name);
 317 
 318                 sortedInsert(allVec, name);
 319             }
 320         }
 321 
 322         envNames = new String[allVec.size()];
 323         allVec.copyInto(envNames);
 324         Vector<String> menuVec = new Vector<String>(allVec);
 325         for (int i = 0; i < menuExcludeVec.size(); i++)
 326             menuVec.removeElement(menuExcludeVec.elementAt(i));
 327         envMenuNames = new String[menuVec.size()];
 328         menuVec.copyInto(envMenuNames);
 329     }
 330 
 331     private void sortedInsert(Vector<String> v, String s) {
 332         for (int i = 0; i < v.size(); i++) {
 333             int c = s.compareTo(v.elementAt(i));
 334             if (c > 0) {
 335                 v.insertElementAt(s, i);
 336                 return;
 337             }
 338             else if (c == 0)
 339                 return;
 340         }
 341         v.addElement(s);
 342     }
 343 
 344     private Map[] propTables;
 345     private String[] propTableNames;
 346     private String[] envNames;
 347     private String[] envMenuNames;
 348 
 349     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(TestEnvContext.class);
 350     private static boolean debug = Boolean.getBoolean("debug." + TestEnvContext.class.getName());
 351 }