// Path: kettle-plugins/common/job/src/main/java/org/pentaho/big/data/kettle/plugins/job/JobEntryUtils.java
// public class JobEntryUtils {
// 
//     /**
//      * @return {@code true} if {@link Boolean#parseBoolean(String)} returns {@code true} for
//      *         {@link #isBlockingExecution()}
//      */
//     /**
//      * Determine if the string equates to {@link Boolean#TRUE} after performing a variable substitution.
//      *
//      * @param s
//      *          String-encoded boolean value or variable expression
//      * @param variableSpace
//      *          Context for variables so we can substitute {@code s}
//      * @return the value returned by {@link Boolean#parseBoolean(String) Boolean.parseBoolean(s)} after substitution
//      */
//     public static boolean asBoolean( String s, VariableSpace variableSpace ) {
//         String value = variableSpace.environmentSubstitute( s );
//         return Boolean.parseBoolean( value );
//     }
// 
//     /**
//      * Parse the string as a {@link Long} after variable substitution.
//      *
//      * @param s
//      *          String-encoded {@link Long} value or variable expression that should resolve to a {@link Long} value
//      * @param variableSpace
//      *          Context for variables so we can substitute {@code s}
//      * @return the value returned by {@link Long#parseLong(String, int) Long.parseLong(s, 10)} after substitution
//      */
//     public static Long asLong( String s, VariableSpace variableSpace ) {
//         String value = variableSpace.environmentSubstitute( s );
//         return value == null ? null : Long.valueOf( value, 10 );
//     }
// }


import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Filter;
import org.pentaho.big.data.kettle.plugins.job.AbstractJobEntry;
import org.pentaho.big.data.kettle.plugins.job.JobEntryMode;
import org.pentaho.big.data.kettle.plugins.job.JobEntryUtils;
import org.pentaho.big.data.kettle.plugins.job.PropertyEntry;
import org.pentaho.di.cluster.SlaveServer;
import org.pentaho.di.core.Result;
import org.pentaho.di.core.database.DatabaseInterface;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.encryption.Encr;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.logging.log4j.KettleLogChannelAppender;
import org.pentaho.di.core.logging.log4j.Log4jKettleLayout;
import org.pentaho.di.core.util.StringUtil;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.job.entry.JobEntryInterface;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.hadoop.shim.api.HadoopClientServices;
import org.pentaho.hadoop.shim.api.cluster.NamedCluster;
import org.pentaho.hadoop.shim.api.cluster.NamedClusterService;
import org.pentaho.hadoop.shim.api.cluster.NamedClusterServiceLocator;
import org.pentaho.hadoop.shim.api.core.ShimIdentifierInterface;
import org.pentaho.metastore.api.IMetaStore;
import org.pentaho.platform.api.util.LogUtil;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.runtime.test.RuntimeTester;
import org.pentaho.runtime.test.action.RuntimeTestActionService;
import org.w3c.dom.Node;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
        Logger sqoopLogger = LogManager.getLogger( LOGS_TO_MONITOR[0] );
        LogUtil.removeAppender( sqoopToKettleAppender, sqoopLogger );
        sqoopToKettleAppender = null;
      }
      if ( stdErrProxy != null ) {
        System.setErr( stdErrProxy.getWrappedStream() );
        stdErrProxy = null;
      }
    } catch ( Exception ex ) {
      logError( getString( "ErrorDetachingLogging" ) );
      logDebug( Throwables.getStackTraceAsString( ex ) );
    }
  }

  /**
   * Validate any configuration option we use directly that could be invalid at runtime.
   *
   * @param config
   *          Configuration to validate
   * @return List of warning messages for any invalid configuration options we use directly in this job entry.
   */
  @Override
  public List<String> getValidationWarnings( SqoopConfig config ) {
    List<String> warnings = new ArrayList<String>();

    if ( StringUtil.isEmpty( config.getConnect() ) ) {
      warnings.add( getString( "ValidationError.Connect.Message", config.getConnect() ) );
    }

    try {
// Path: kettle-plugins/common/job/src/main/java/org/pentaho/big/data/kettle/plugins/job/JobEntryUtils.java
// public class JobEntryUtils {
// 
//     /**
//      * @return {@code true} if {@link Boolean#parseBoolean(String)} returns {@code true} for
//      *         {@link #isBlockingExecution()}
//      */
//     /**
//      * Determine if the string equates to {@link Boolean#TRUE} after performing a variable substitution.
//      *
//      * @param s
//      *          String-encoded boolean value or variable expression
//      * @param variableSpace
//      *          Context for variables so we can substitute {@code s}
//      * @return the value returned by {@link Boolean#parseBoolean(String) Boolean.parseBoolean(s)} after substitution
//      */
//     public static boolean asBoolean( String s, VariableSpace variableSpace ) {
//         String value = variableSpace.environmentSubstitute( s );
//         return Boolean.parseBoolean( value );
//     }
// 
//     /**
//      * Parse the string as a {@link Long} after variable substitution.
//      *
//      * @param s
//      *          String-encoded {@link Long} value or variable expression that should resolve to a {@link Long} value
//      * @param variableSpace
//      *          Context for variables so we can substitute {@code s}
//      * @return the value returned by {@link Long#parseLong(String, int) Long.parseLong(s, 10)} after substitution
//      */
//     public static Long asLong( String s, VariableSpace variableSpace ) {
//         String value = variableSpace.environmentSubstitute( s );
//         return value == null ? null : Long.valueOf( value, 10 );
//     }
// }


// Path: kettle-plugins/sqoop/src/main/java/org/pentaho/big/data/kettle/plugins/sqoop/AbstractSqoopJobEntry.java
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Filter;
import org.pentaho.big.data.kettle.plugins.job.AbstractJobEntry;
import org.pentaho.big.data.kettle.plugins.job.JobEntryMode;
import org.pentaho.big.data.kettle.plugins.job.JobEntryUtils;
import org.pentaho.big.data.kettle.plugins.job.PropertyEntry;
import org.pentaho.di.cluster.SlaveServer;
import org.pentaho.di.core.Result;
import org.pentaho.di.core.database.DatabaseInterface;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.encryption.Encr;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.logging.log4j.KettleLogChannelAppender;
import org.pentaho.di.core.logging.log4j.Log4jKettleLayout;
import org.pentaho.di.core.util.StringUtil;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.job.entry.JobEntryInterface;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.hadoop.shim.api.HadoopClientServices;
import org.pentaho.hadoop.shim.api.cluster.NamedCluster;
import org.pentaho.hadoop.shim.api.cluster.NamedClusterService;
import org.pentaho.hadoop.shim.api.cluster.NamedClusterServiceLocator;
import org.pentaho.hadoop.shim.api.core.ShimIdentifierInterface;
import org.pentaho.metastore.api.IMetaStore;
import org.pentaho.platform.api.util.LogUtil;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.runtime.test.RuntimeTester;
import org.pentaho.runtime.test.action.RuntimeTestActionService;
import org.w3c.dom.Node;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

        Logger sqoopLogger = LogManager.getLogger( LOGS_TO_MONITOR[0] );
        LogUtil.removeAppender( sqoopToKettleAppender, sqoopLogger );
        sqoopToKettleAppender = null;
      }
      if ( stdErrProxy != null ) {
        System.setErr( stdErrProxy.getWrappedStream() );
        stdErrProxy = null;
      }
    } catch ( Exception ex ) {
      logError( getString( "ErrorDetachingLogging" ) );
      logDebug( Throwables.getStackTraceAsString( ex ) );
    }
  }

  /**
   * Validate any configuration option we use directly that could be invalid at runtime.
   *
   * @param config
   *          Configuration to validate
   * @return List of warning messages for any invalid configuration options we use directly in this job entry.
   */
  @Override
  public List<String> getValidationWarnings( SqoopConfig config ) {
    List<String> warnings = new ArrayList<String>();

    if ( StringUtil.isEmpty( config.getConnect() ) ) {
      warnings.add( getString( "ValidationError.Connect.Message", config.getConnect() ) );
    }

    try {
      JobEntryUtils.asLong( config.getBlockingPollingInterval(), variables );