content: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   * <p/>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p/>
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.bigtop.itest;
  
  import java.lang.reflect.Field;
  
  import static org.junit.Assert.assertNotNull;
  
  /**
   * Class containing utility methods for test classes to use (in a static
   * setup method) for obtaining the values of parameters passed in via
   * environment variables or system properties. The parameters are obtained
   * by introspecting the {@link org.apache.bigtop.itest.Contract Contract}
   * annotation of the test class.
   */
  public class ParameterSetter {
  
    /**
     * Sets the values of parameters passed in via environment variables, using
     * convention.
     * Assumes the presence in the target class of static fields (the parameters)
     * with the same names as the environment variables.
     * (Unix/Linux environment variable names shall consist solely of uppercase
     * letters, digits, and the '_' (underscore) character, and shall not begin
     * with a digit.)
     * If an environment variable is required and it is not set, an
     * AssertionError is thrown.
     *
     * @param target the test class
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static void setEnv(Class target)
        throws NoSuchFieldException, IllegalAccessException {
      Contract contract = (Contract) target.getAnnotation(Contract.class);
      Variable[] vars = contract.env();
      for (int i = 0; i < vars.length; i++) {
        Variable var = vars[i];
        String name = var.name();
        Field field = target.getDeclaredField(name);
        String value = System.getenv(name);
        if (value == null && var.required()) {
          assertNotNull(name + " is not set", value);
        }
        field.setAccessible(true);
        field.set(target, value);
      }
    }
  
    /**
     * Sets the values of parameters passed in via environment variables.
     * Assumes the presence in the target class of static fields with the given
     * names.
     * If an environment variable is required and it is not set, an
     * AssertionError is thrown.
     *
     * @param target     the test class
     * @param fieldNames the names of the static fields corresponding to the
     *                   environment variables; the number of names must match the number of
     *                   environment variables
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static void setEnv(Class target, String[] fieldNames)
        throws NoSuchFieldException, IllegalAccessException {
      Contract contract = (Contract) target.getAnnotation(Contract.class);
      Variable[] vars = contract.env();
      assert vars.length == fieldNames.length;
      for (int i = 0; i < vars.length; i++) {
        Variable var = vars[i];
        String name = var.name();
        Field field = target.getDeclaredField(fieldNames[i]);
        String value = System.getenv(name);
        if (value == null && var.required()) {
          assertNotNull(name + " is not set", value);
        }
        field.setAccessible(true);
        field.set(target, value);
      }
    }
  
    /**
     * Sets the values of parameters passed in via system properties, using
     * convention.
     * Assumes the presence in the target class of static fields (the parameters)
     * with the same names as the system properties, except with '.' replaced by
     * '_'. (The names of the system properties shall be chosen so that the
     * corresponding field names are valid Java identifiers.)
     * If a system property is not set, the parameter is set to a default value.
     * Therefore usable default values must be provided in the annotation or else
     * test logic must be written to handle the lack thereof.
     *
     * @param target the test class
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static void setProperties(Class target)
        throws NoSuchFieldException, IllegalAccessException {
      Contract contract = (Contract) target.getAnnotation(Contract.class);
      Property[] props = contract.properties();
      for (int i = 0; i < props.length; i++) {
        Property prop = props[i];
        String name = prop.name();
        Field field = target.getDeclaredField(name.replace('.', '_'));
        Object value = null;
        switch (prop.type()) {
          case STRING:
            value = System.getProperty(name, prop.defaultValue());
            break;
          case INT:
            value = Integer.getInteger(name, prop.intValue());
            break;
          case LONG:
            value = Long.getLong(name, prop.longValue());
            break;
          case BOOLEAN:
            value = Boolean.getBoolean(name);
        }
        field.setAccessible(true);
        field.set(target, value);
      }
    }
  
    /**
     * Sets the values of parameters passed in via system properties.
     * Assumes the presence in the target class of static fields with the given
     * names.
     * If a system property is not set, the parameter is set to a default value.
     * Therefore usable default values must be provided in the annotation or else
     * test logic must be written to handle the lack thereof.
     *
     * @param target     the test class
     * @param fieldNames the names of the static fields corresponding to the
     *                   system properties; the number of names must match the number of
     *                   system properties
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static void setProperties(Class target, String[] fieldNames)
        throws NoSuchFieldException, IllegalAccessException {
      Contract contract = (Contract) target.getAnnotation(Contract.class);
      Property[] props = contract.properties();
      assert props.length == fieldNames.length;
      for (int i = 0; i < props.length; i++) {
        Property prop = props[i];
        String name = prop.name();
        Field field = target.getDeclaredField(fieldNames[i]);
        Object value = null;
        switch (prop.type()) {
          case STRING:
            value = System.getProperty(name, prop.defaultValue());
            break;
          case INT:
            value = Integer.getInteger(name, prop.intValue());
            break;
          case LONG:
            value = Long.getLong(name, prop.longValue());
            break;
          case BOOLEAN:
            value = Boolean.getBoolean(name);
        }
        field.setAccessible(true);
        field.set(target, value);
      }
    }
  }
  