/**
 * 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
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.sqoop.manager.oracle;

import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.hadoop.conf.Configuration;

import com.cloudera.sqoop.SqoopOptions;
import com.cloudera.sqoop.SqoopOptions.IncrementalMode;
import com.cloudera.sqoop.manager.ConnManager;
import com.cloudera.sqoop.manager.ManagerFactory;
import com.cloudera.sqoop.metastore.JobData;

import org.apache.sqoop.manager.OracleManager;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatUpdate.UpdateMode;
import org.apache.sqoop.manager.oracle.OraOopUtilities.
           JdbcOracleThinConnectionParsingError;

import static org.apache.sqoop.mapreduce.JobBase.HADOOP_MAP_TASK_MAX_ATTEMTPS;

/**
 * OraOop manager - if OraOop cannot be used it should fall back to the default
 * OracleManager.
 *
 * To increase the amount of heap memory available to the mappers:
 *                                     -Dmapred.child.java.opts=-Xmx4000M
 * To prevent failed mapper tasks from being reattempted:
 *                                     -Dmapred.map.max.attempts=1
 */
public class OraOopManagerFactory extends ManagerFactory {

  @SuppressWarnings("unused")
  private static final OraOopLog ORAOOP_LOG = OraOopLogFactory
      .getLog("org.apache.sqoop.manager.oracle");
  private static final OraOopLog LOG = OraOopLogFactory
      .getLog(OraOopManagerFactory.class.getName());

  static {
    Configuration
        .addDefaultResource(OraOopConstants.ORAOOP_SITE_TEMPLATE_FILENAME);
    Configuration.addDefaultResource(OraOopConstants.ORAOOP_SITE_FILENAME);
  }

  @Override
  public ConnManager accept(JobData jobData) {

    OraOopUtilities.enableDebugLoggingIfRequired(jobData.getSqoopOptions()
        .getConf());

    LOG.debug(String.format("%s can be called by Sqoop!",
        OraOopConstants.ORAOOP_PRODUCT_NAME));

    ConnManager result = null;

    if (jobData != null) {

      SqoopOptions sqoopOptions = jobData.getSqoopOptions();

      String connectString = sqoopOptions.getConnectString();
      if (connectString != null
          && connectString.toLowerCase().trim().startsWith("jdbc:oracle")) {

        if (!isOraOopEnabled(sqoopOptions)) {
          return result;
        }

        OraOopConnManager oraOopConnManager = null;

        OraOopConstants.Sqoop.Tool jobType = getSqoopJobType(jobData);
        OraOopUtilities.rememberSqoopJobType(jobType, jobData.getSqoopOptions()
            .getConf());

        List<OraOopLogMessage> messagesToDisplayAfterWelcome =
            new ArrayList<OraOopLogMessage>();

        switch (jobType) {

          case IMPORT:
            if (isNumberOfImportMappersOkay(sqoopOptions)
                && !isSqoopImportIncremental(jobData)
                && isSqoopImportJobTableBased(sqoopOptions)) {

              // At this stage, the Sqoop import job appears to be one we're
              // interested in accepting. We now need to connect to
              // the Oracle database to perform more tests...

              oraOopConnManager = new OraOopConnManager(sqoopOptions);

              try {
                Connection connection = oraOopConnManager.getConnection();

                if (isSqoopTableAnOracleTable(connection, sqoopOptions
                    .getUsername(),
                    oraOopConnManager.getOracleTableContext())) {

                  // OraOop will not accept responsibility for an Index
                  // Organized Table (IOT)...
                  if (!isSqoopTableAnIndexOrganizedTable(connection,
                      oraOopConnManager.getOracleTableContext())) {
                    result = oraOopConnManager; // <- OraOop accepts
                                                // responsibility for this Sqoop
                                                // job!
                  } else {
                    OraOopConstants.OraOopOracleDataChunkMethod method =
                        OraOopUtilities.getOraOopOracleDataChunkMethod(
                            sqoopOptions.getConf());
                    if (method == OraOopConstants.
                                      OraOopOracleDataChunkMethod.PARTITION) {
                      result = oraOopConnManager;
                    } else {
                      LOG.info(String.format("%s will not process this Sqoop"
                         + " connection, as the Oracle table %s is an"
                         + " index-organized table. If the table is"
                         + " partitioned, set "
                         + OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD
                         + " to "
                         + OraOopConstants.OraOopOracleDataChunkMethod.PARTITION
                         + ".",
                         OraOopConstants.ORAOOP_PRODUCT_NAME,
                         oraOopConnManager.getOracleTableContext().toString()));
                    }
                  }
                }
              } catch (SQLException ex) {
                throw new RuntimeException(String.format(
                    "Unable to connect to the Oracle database at %s\n"
                        + "Error:%s", sqoopOptions.getConnectString(), ex
                        .getMessage()), ex);
              }
            }
            break;

          case EXPORT:
            if (isNumberOfExportMappersOkay(sqoopOptions)) {

              // At this stage, the Sqoop export job appears to be one we're
              // interested in accepting. We now need to connect to
              // the Oracle database to perform more tests...

              oraOopConnManager = new OraOopConnManager(sqoopOptions);

              Connection connection = null;
              try {
                connection = oraOopConnManager.getConnection();
              } catch (SQLException ex) {
                throw new RuntimeException(String.format(
                    "Unable to connect to the Oracle database at %s\n"
                        + "Error:%s", sqoopOptions.getConnectString(), ex
                        .getMessage()), ex);
              }

              try {

                createAnyRequiredOracleObjects(sqoopOptions, connection,
                    oraOopConnManager, messagesToDisplayAfterWelcome);

                if (isSqoopTableAnOracleTable(connection, sqoopOptions
                    .getUsername(),
                    oraOopConnManager.getOracleTableContext())) {

                  result = oraOopConnManager; // <- OraOop accepts
                                              // responsibility for this Sqoop
                                              // job!
                }

              } catch (SQLException ex) {
                LOG.error(OraOopUtilities.getFullExceptionMessage(ex));
              }
            }

            break;
          default:
            // OraOop doesn't know how to handle other types of jobs - so won't
            // accept them.
            break;
        }

        // If OraOop has accepted this Sqoop job...
        if (result != null) {

          showUserTheOraOopWelcomeMessage();

          for (OraOopLogMessage message : messagesToDisplayAfterWelcome) {
            message.log(LOG);
          }

          // By the time we get into getSplits(), the number of mappers
          // stored in the config can be either 4 or 1 - so it seems
          // a bit unreliable. We'll use our own property name to ensure
          // getSplits() gets the correct value...
          sqoopOptions.getConf().setInt(
              OraOopConstants.ORAOOP_DESIRED_NUMBER_OF_MAPPERS,
              sqoopOptions.getNumMappers());

          // Generate the "action" name that we'll assign to our Oracle sessions
          // so that the user knows which Oracle sessions belong to OraOop...
          sqoopOptions.getConf().set(
              OraOopConstants.ORACLE_SESSION_ACTION_NAME,
              getOracleSessionActionName(jobData));

          OraOopUtilities.appendJavaSecurityEgd(sqoopOptions.getConf());

          // Get the Oracle database version...
          try {
            OracleVersion oracleVersion =
                OraOopOracleQueries.getOracleVersion(result.getConnection());
            LOG.info(String.format("Oracle Database version: %s",
                oracleVersion.getBanner()));
            sqoopOptions.getConf().setInt(
                OraOopConstants.ORAOOP_ORACLE_DATABASE_VERSION_MAJOR,
                oracleVersion.getMajor());
            sqoopOptions.getConf().setInt(
                OraOopConstants.ORAOOP_ORACLE_DATABASE_VERSION_MINOR,
                oracleVersion.getMinor());
          } catch (SQLException ex) {
            LOG.error("Unable to obtain the Oracle database version.", ex);
          }

          try {
            if (sqoopOptions.getConf().getBoolean(
                OraOopConstants.ORAOOP_IMPORT_CONSISTENT_READ, false)) {
              long scn =
                  sqoopOptions.getConf().getLong(
                      OraOopConstants.ORAOOP_IMPORT_CONSISTENT_READ_SCN, 0);
              if (scn == 0) {
                scn = OraOopOracleQueries.getCurrentScn(result.getConnection());
              }
              sqoopOptions.getConf().setLong(
                  OraOopConstants.ORAOOP_IMPORT_CONSISTENT_READ_SCN, scn);
              LOG.info("Performing a consistent read using SCN: " + scn);
            }
          } catch (SQLException ex) {
            throw new RuntimeException("Unable to determine SCN of database.",
                ex);
          }

          // Generate the JDBC URLs to be used by each mapper...
          setMapperConnectionDetails(oraOopConnManager, jobData);

          // Show the user the Oracle command that can be used to kill this
          // OraOop
          // job via Oracle...
          showUserTheOracleCommandToKillOraOop(sqoopOptions);
        }

      }
    }

    return result;
  }

  private void setMapperConnectionDetails(OraOopConnManager oraOopConnManager,
      JobData jobData) {

    // Ensure we have a connection to the database...
    Connection connection = null;
    try {
      connection = oraOopConnManager.getConnection();
    } catch (SQLException ex) {
      throw new RuntimeException(String.format(
          "Unable to connect to the Oracle database at %s\n" + "Error:%s",
          jobData.getSqoopOptions().getConnectString(), ex.getMessage()));
    }

    // Query v$active_instances to get a list of all instances in the Oracle RAC
    // (assuming this *could* be a RAC)...
    List<OracleActiveInstance> activeInstances = null;
    try {
      activeInstances =
          OraOopOracleQueries.getOracleActiveInstances(connection);
    } catch (SQLException ex) {
      throw new RuntimeException(
          "An error was encountered when attempting to determine the "
        + "configuration of the Oracle RAC.",
        ex);
    }

    if (activeInstances == null) {
      LOG.info("This Oracle database is not a RAC.");
    } else {
      LOG.info("This Oracle database is a RAC.");
    }

    // Is dynamic JDBC URL generation disabled?...
    if (OraOopUtilities.oracleJdbcUrlGenerationDisabled(jobData
        .getSqoopOptions().getConf())) {
      LOG.info(String
          .format(
              "%s will not use dynamically generated JDBC URLs - this feature "
            + "has been disabled.",
            OraOopConstants.ORAOOP_PRODUCT_NAME));
      return;
    }

    boolean generateRacBasedJdbcUrls = false;

    // Decide whether this is a multi-instance RAC, and whether we need to do
    // anything more...
    if (activeInstances != null) {
      generateRacBasedJdbcUrls = true;

      if (activeInstances.size() < OraOopUtilities
          .getMinNumberOfOracleRacActiveInstancesForDynamicJdbcUrlUse(jobData
              .getSqoopOptions().getConf())) {
        LOG.info(String.format(
            "There are only %d active instances in the Oracle RAC. "
          + "%s will not bother utilizing dynamically generated JDBC URLs.",
          activeInstances.size(), OraOopConstants.ORAOOP_PRODUCT_NAME));
        generateRacBasedJdbcUrls = false;
      }
    }

    // E.g. jdbc:oracle:thin:@localhost.localdomain:1521:orcl
    String jdbcConnectStr = jobData.getSqoopOptions().getConnectString();

    // Parse the JDBC URL to obtain the port number for the TNS listener...
    String jdbcHost = "";
    int jdbcPort = 0;
    String jdbcSid = "";
    String jdbcService = "";
    String jdbcTnsName = "";
    try {

      OraOopJdbcUrl oraOopJdbcUrl = new OraOopJdbcUrl(jdbcConnectStr);
      OraOopUtilities.JdbcOracleThinConnection jdbcConnection =
          oraOopJdbcUrl.parseJdbcOracleThinConnectionString();
      jdbcHost = jdbcConnection.getHost();
      jdbcPort = jdbcConnection.getPort();
      jdbcSid = jdbcConnection.getSid();
      jdbcService = jdbcConnection.getService();
      jdbcTnsName = jdbcConnection.getTnsName();
    } catch (JdbcOracleThinConnectionParsingError ex) {
      LOG.info(String.format(
          "Unable to parse the JDBC connection URL \"%s\" as a connection "
        + "that uses the Oracle 'thin' JDBC driver.\n"
        + "This problem prevents %s from being able to dynamically generate "
        + "JDBC URLs that specify 'dedicated server connections' or spread "
        + "mapper sessions across multiple Oracle instances.\n"
        + "If the JDBC driver-type is 'OCI' (instead of 'thin'), then "
        + "load-balancing should be appropriately managed automatically.",
              jdbcConnectStr, OraOopConstants.ORAOOP_PRODUCT_NAME, ex));
      return;
    }

    if (generateRacBasedJdbcUrls) {

      // Retrieve the Oracle service name to use when connecting to the RAC...
      String oracleServiceName =
          OraOopUtilities.getOracleServiceName(jobData.getSqoopOptions()
              .getConf());

      // Generate JDBC URLs for each of the mappers...
      if (!oracleServiceName.isEmpty()) {
        if (!generateRacJdbcConnectionUrlsByServiceName(jdbcHost, jdbcPort,
            oracleServiceName, jobData)) {
          throw new RuntimeException(String.format(
              "Unable to connect to the Oracle database at %s "
                  + "via the service name \"%s\".", jobData.getSqoopOptions()
                  .getConnectString(), oracleServiceName));
        }
      } else {
        generateJdbcConnectionUrlsByActiveInstance(activeInstances, jdbcPort,
            jobData);
      }
    } else {
      generateJdbcConnectionUrlsByTnsnameSidOrService(jdbcHost, jdbcPort,
        jdbcSid, jdbcService, jdbcTnsName, jobData);
    }

  }

  private void generateJdbcConnectionUrlsByTnsnameSidOrService(String hostName,
    int port, String sid, String serviceName, String tnsName, JobData jobData) {

    String jdbcUrl = null;
    if (tnsName != null && !tnsName.isEmpty()) {
      jdbcUrl = OraOopUtilities.generateOracleTnsNameJdbcUrl(tnsName);
    } else if (sid != null && !sid.isEmpty()) {
      jdbcUrl = OraOopUtilities.generateOracleSidJdbcUrl(hostName, port, sid);
    } else {
      jdbcUrl =
          OraOopUtilities.generateOracleServiceNameJdbcUrl(hostName, port,
              serviceName);
    }

    // Now store these connection strings in such a way that each mapper knows
    // which one to use...
    for (int idxMapper = 0; idxMapper < jobData.getSqoopOptions()
        .getNumMappers(); idxMapper++) {
      storeJdbcUrlForMapper(idxMapper, jdbcUrl, jobData);
    }
  }

  private boolean generateRacJdbcConnectionUrlsByServiceName(String hostName,
      int port, String serviceName, JobData jobData) {

    boolean result = false;
    String jdbcUrl =
        OraOopUtilities.generateOracleServiceNameJdbcUrl(hostName, port,
            serviceName);

    if (testDynamicallyGeneratedOracleRacInstanceConnection(jdbcUrl, jobData
        .getSqoopOptions().getUsername(), jobData.getSqoopOptions()
        .getPassword(), jobData.getSqoopOptions().getConnectionParams()
        , false // <- ShowInstanceSysTimestamp
        , "" // <- instanceDescription
    )) {

      LOG.info(String.format(
          "%s will load-balance sessions across the Oracle RAC instances "
              + "by connecting each mapper to the Oracle Service \"%s\".",
          OraOopConstants.ORAOOP_PRODUCT_NAME, serviceName));

      // Now store these connection strings in such a way that each mapper knows
      // which one to use...
      for (int idxMapper = 0; idxMapper < jobData.getSqoopOptions()
          .getNumMappers(); idxMapper++) {
        storeJdbcUrlForMapper(idxMapper, jdbcUrl, jobData);
      }
      result = true;
    }
    return result;
  }

  private void
      generateJdbcConnectionUrlsByActiveInstance(
          List<OracleActiveInstance> activeInstances, int jdbcPort,
          JobData jobData) {

    // Generate JDBC URLs for each of the instances in the RAC...
    ArrayList<OraOopUtilities.JdbcOracleThinConnection>
        jdbcOracleActiveThinConnections =
            new ArrayList<OraOopUtilities.JdbcOracleThinConnection>(
                activeInstances.size());

    for (OracleActiveInstance activeInstance : activeInstances) {

      OraOopUtilities.JdbcOracleThinConnection
          jdbcActiveInstanceThinConnection =
              new OraOopUtilities.JdbcOracleThinConnection(
                  activeInstance.getHostName(),
                  jdbcPort, activeInstance.getInstanceName(), "", "");

      if (testDynamicallyGeneratedOracleRacInstanceConnection(
          jdbcActiveInstanceThinConnection.toString(), jobData
              .getSqoopOptions().getUsername(), jobData.getSqoopOptions()
              .getPassword(), jobData.getSqoopOptions().getConnectionParams(),
          true, activeInstance.getInstanceName())) {
        jdbcOracleActiveThinConnections.add(jdbcActiveInstanceThinConnection);
      }
    }

    // If there are multiple JDBC URLs that work okay for the RAC, then we'll
    // make use of them...
    if (jdbcOracleActiveThinConnections.size() < OraOopUtilities
        .getMinNumberOfOracleRacActiveInstancesForDynamicJdbcUrlUse(jobData
            .getSqoopOptions().getConf())) {
      LOG.info(String
          .format(
              "%s will not attempt to load-balance sessions across instances "
            + "of an Oracle RAC - as multiple JDBC URLs to the "
            + "Oracle RAC could not be dynamically generated.",
              OraOopConstants.ORAOOP_PRODUCT_NAME));
      return;
    } else {
      StringBuilder msg = new StringBuilder();
      msg.append(String
          .format(
              "%s will load-balance sessions across the following instances of"
            + "the Oracle RAC:\n",
              OraOopConstants.ORAOOP_PRODUCT_NAME));

      for (OraOopUtilities.JdbcOracleThinConnection thinConnection
               : jdbcOracleActiveThinConnections) {
        msg.append(String.format("\tInstance: %s \t URL: %s\n",
            thinConnection.getSid(), thinConnection.toString()));
      }
      LOG.info(msg.toString());
    }

    // Now store these connection strings in such a way that each mapper knows
    // which one to use...
    int racInstanceIdx = 0;
    OraOopUtilities.JdbcOracleThinConnection thinUrl;
    for (int idxMapper = 0; idxMapper < jobData.getSqoopOptions()
        .getNumMappers(); idxMapper++) {
      if (racInstanceIdx > jdbcOracleActiveThinConnections.size() - 1) {
        racInstanceIdx = 0;
      }
      thinUrl = jdbcOracleActiveThinConnections.get(racInstanceIdx);
      racInstanceIdx++;
      storeJdbcUrlForMapper(idxMapper, thinUrl.toString(), jobData);
    }
  }

  private boolean testDynamicallyGeneratedOracleRacInstanceConnection(
      String url, String userName, String password, Properties additionalProps,
      boolean showInstanceSysTimestamp, String instanceDescription) {

    boolean result = false;

    // Test the connection...
    try {
      Connection testConnection =
          OracleConnectionFactory.createOracleJdbcConnection(
              OraOopConstants.ORACLE_JDBC_DRIVER_CLASS, url, userName,
              password, additionalProps);

      // Show the system time on each instance...
      if (showInstanceSysTimestamp) {
        LOG.info(String.format("\tDatabase time on %s is %s",
            instanceDescription, OraOopOracleQueries
                .getSysTimeStamp(testConnection)));
      }

      testConnection.close();
      result = true;
    } catch (SQLException ex) {
      LOG.warn(
          String
              .format(
                  "The dynamically generated JDBC URL \"%s\" was unable to "
                  + "connect to an instance in the Oracle RAC.",
                  url), ex);
    }

    return result;
  }

  private void storeJdbcUrlForMapper(int mapperIdx, String jdbcUrl,
      JobData jobData) {

    // Now store these connection strings in such a way that each mapper knows
    // which one to use...
    Configuration conf = jobData.getSqoopOptions().getConf();
    String mapperJdbcUrlPropertyName =
        OraOopUtilities.getMapperJdbcUrlPropertyName(mapperIdx, conf);
    LOG.debug("Setting mapper url " + mapperJdbcUrlPropertyName + " = "
      + jdbcUrl);
    conf.set(mapperJdbcUrlPropertyName, jdbcUrl);
  }

  private boolean isOraOopEnabled(SqoopOptions sqoopOptions) {

    String oraOopDisabled =
        sqoopOptions.getConf().get(OraOopConstants.ORAOOP_DISABLED, "false")
            .toLowerCase();
    boolean oraOopIsDisabled =
        oraOopDisabled.equalsIgnoreCase("true")
            || oraOopDisabled.equalsIgnoreCase("yes")
            || oraOopDisabled.equalsIgnoreCase("y")
            || oraOopDisabled.equalsIgnoreCase("1");

    oraOopIsDisabled = oraOopIsDisabled || !sqoopOptions.isDirect();

    if (oraOopIsDisabled) {
      LOG.info(String.format("%s is disabled.",
          OraOopConstants.ORAOOP_PRODUCT_NAME));
    }

    return !oraOopIsDisabled;
  }

  private OraOopConstants.Sqoop.Tool getSqoopJobType(JobData jobData) {

    OraOopConstants.Sqoop.Tool result = OraOopConstants.Sqoop.Tool.UNKNOWN;

    String sqoopToolName = getSqoopToolName(jobData).toUpperCase().trim();
    try {
      result = OraOopConstants.Sqoop.Tool.valueOf(sqoopToolName);
    } catch (IllegalArgumentException ex) {
      LOG.debug(String.format(
          "The Sqoop tool name \"%s\" is not supported by OraOop",
          sqoopToolName), ex);
    }
    return result;
  }

  private boolean isNumberOfImportMappersOkay(SqoopOptions sqoopOptions) {

    // Check whether there are enough mappers for OraOop to be of benefit...
    boolean result =
      (sqoopOptions.getNumMappers() >= OraOopUtilities
          .getMinNumberOfImportMappersAcceptedByOraOop(sqoopOptions.getConf()));

    if (!result) {
      LOG.info(String.format(
        "%s will not process this sqoop connection, as an insufficient number "
            + "of mappers are being used.",
        OraOopConstants.ORAOOP_PRODUCT_NAME));
    }

    return result;
  }

  private boolean isNumberOfExportMappersOkay(SqoopOptions sqoopOptions) {

    // Check whether there are enough mappers for OraOop to be of benefit...
    boolean result =
        (sqoopOptions.getNumMappers() >= OraOopUtilities
          .getMinNumberOfExportMappersAcceptedByOraOop(sqoopOptions.getConf()));

    if (!result) {
      LOG.info(String.format(
        "%s will not process this sqoop connection, as an insufficient number "
            + "of mappers are being used.",
        OraOopConstants.ORAOOP_PRODUCT_NAME));
    }

    return result;
  }

  private boolean isSqoopImportJobTableBased(SqoopOptions sqoopOptions) {

    String tableName = sqoopOptions.getTableName();
    return (tableName != null && !tableName.isEmpty());
  }

  private boolean isSqoopTableAnOracleTable(Connection connection,
      String connectionUserName, OracleTable tableContext) {

    String oracleObjectType;

    try {

      // Find the table via dba_tables...
      OracleTable oracleTable =
          OraOopOracleQueries.getTable(connection, tableContext.getSchema(),
              tableContext.getName());
      if (oracleTable != null) {
        return true;
      }

      // If we could not find the table via dba_tables, then try and determine
      // what type of database object the
      // user was referring to. Perhaps they've specified the name of a view?...
      oracleObjectType =
          OraOopOracleQueries.getOracleObjectType(connection, tableContext);

      if (oracleObjectType == null) {
        LOG.info(String.format(
            "%1$s will not process this Sqoop connection, "
          + "as the Oracle user %2$s does not own a table named %3$s.\n"
          + "\tPlease prefix the table name with the owner.\n "
          + "\tNote: You may need to double-quote the owner and/or table name."
          + "\n\tE.g. sqoop ... --username %4$s --table %2$s.%3$s\n",
          OraOopConstants.ORAOOP_PRODUCT_NAME, tableContext.getSchema(),
          tableContext.getName(), connectionUserName));
        return false;
      }

    } catch (SQLException ex) {
      LOG.warn(String.format(
        "Unable to determine the Oracle-type of the object named %s owned by "
            + "%s.\nError:\n" + "%s", tableContext.getName(), tableContext
            .getSchema(), ex.getMessage()));

      // In the absence of conflicting information, let's assume the object is
      // actually a table...
      return true;
    }

    boolean result =
        oracleObjectType
            .equalsIgnoreCase(OraOopConstants.Oracle.OBJECT_TYPE_TABLE);

    if (!result) {
      LOG.info(String.format("%s will not process this sqoop connection, "
          + "as %s is not an Oracle table, it's a %s.",
          OraOopConstants.ORAOOP_PRODUCT_NAME, tableContext.toString(),
          oracleObjectType));
    }

    return result;
  }

  private boolean isSqoopTableAnIndexOrganizedTable(Connection connection,
      OracleTable tableContext) {

    boolean result = false;
    try {
      result =
          OraOopOracleQueries.isTableAnIndexOrganizedTable(connection,
              tableContext);
      return result;
    } catch (SQLException ex) {
      LOG.warn(String.format(
         "Unable to determine whether the Oracle table %s is an index-organized"
       + " table.\nError:\n" + "%s", tableContext.toString(), ex.getMessage()));
    }
    return result;
  }

  private String getSqoopToolName(JobData jobData) {

    return jobData.getSqoopTool().getToolName();
  }

  private String getOracleSessionActionName(JobData jobData) {

    // This method has been written assuming that:
    // (1) OraOop only processes Sqoop "import" and "export" jobs; and
    // (2) a table will be used during the import/export (not a query).

    if (getSqoopJobType(jobData) != OraOopConstants.Sqoop.Tool.IMPORT
        && getSqoopJobType(jobData) != OraOopConstants.Sqoop.Tool.EXPORT) {
      throw new UnsupportedOperationException(String.format(
          "%s needs to be updated to cope " + "with Sqoop jobs of type %s.",
          OraOopUtilities.getCurrentMethodName(), getSqoopToolName(jobData)));
    }

    String timeStr =
        (new SimpleDateFormat("yyyyMMddHHmmsszzz")).format(new Date());

    String result = String.format("%s %s", getSqoopToolName(jobData), timeStr);

    // NOTE: The "action" column of v$session is only a 32 character column.
    // Therefore we need to ensure that the string returned by this
    // method does not exceed 32 characters...
    if (result.length() > 32) {
      result = result.substring(0, 32).trim();
    }

    return result;
  }

  private boolean isSqoopImportIncremental(JobData jobData) {

    boolean result =
        jobData.getSqoopOptions().getIncrementalMode() != IncrementalMode.None;

    if (result) {
      LOG.info(String.format("%1$s will not process this sqoop connection, "
          + "as incremental mode is not supported by %1$s.",
          OraOopConstants.ORAOOP_PRODUCT_NAME));
    }

    return result;
  }

  private void showUserTheOraOopWelcomeMessage() {

    String msg1 =
        String.format("Using %s", OraOopConstants.ORAOOP_PRODUCT_NAME);

    int longestMessage = msg1.length();

    msg1 = OraOopUtilities.padRight(msg1, longestMessage);

    char[] asterisks = new char[longestMessage + 8];
    Arrays.fill(asterisks, '*');

    String msg =
        String.format("\n" + "%1$s\n" + "*** %2$s ***\n" + "%1$s", new String(
            asterisks), msg1);
    LOG.info(msg);
  }

  private void showUserTheOracleCommandToKillOraOop(SqoopOptions sqoopOptions) {

    int taskAttempts =
        sqoopOptions.getConf().getInt(HADOOP_MAP_TASK_MAX_ATTEMTPS, -1);

    // If killing the Oracle session if futile - because the job will be
    // reattempted, then don't
    // bother telling the user about this feature...
    if (taskAttempts != 1) {
      return;
    }

    String moduleName = OraOopConstants.ORACLE_SESSION_MODULE_NAME;
    String actionName =
        sqoopOptions.getConf().get(OraOopConstants.ORACLE_SESSION_ACTION_NAME);

    String msg = String.format(
        "\nNote: This %s job can be killed via Oracle by executing the "
      + "following statement:\n\tbegin\n"
      + "\t\tfor row in (select sid,serial# from v$session where module='%s' "
      + "and action='%s') loop\n"
      + "\t\t\texecute immediate 'alter system kill session ''' || row.sid || "
      + "',' || row.serial# || '''';\n"
      + "\t\tend loop;\n" + "\tend;",
      OraOopConstants.ORAOOP_PRODUCT_NAME, moduleName, actionName);
    LOG.info(msg);
  }

  private void createAnyRequiredOracleObjects(SqoopOptions sqoopOptions,
    Connection connection, OraOopConnManager oraOopConnManager,
    List<OraOopLogMessage> messagesToDisplayAfterWelcome) throws SQLException {

    Configuration conf = sqoopOptions.getConf();

    // The SYSDATE on the Oracle database will be used as the partition value
    // for this export job...
    Object sysDateTime = OraOopOracleQueries.getSysDate(connection);
    String sysDateStr =
      OraOopOracleQueries.oraDATEToString(sysDateTime, "yyyy-mm-dd hh24:mi:ss");
    OraOopUtilities.rememberOracleDateTime(conf,
        OraOopConstants.ORAOOP_JOB_SYSDATE, sysDateStr);

    checkForOldOraOopTemporaryOracleTables(connection, sysDateTime,
        OraOopOracleQueries.getCurrentSchema(connection),
        messagesToDisplayAfterWelcome);

    // Store the actual partition value, so the N mappers know what value to
    // insert...
    String partitionValue =
        OraOopOracleQueries.oraDATEToString(sysDateTime,
            OraOopConstants.ORAOOP_EXPORT_PARTITION_DATE_FORMAT);
    conf.set(OraOopConstants.ORAOOP_EXPORT_PARTITION_DATE_VALUE,
             partitionValue);

    // Generate the (22 character) partition name...
    String partitionName =
        OraOopUtilities
            .createExportTablePartitionNameFromOracleTimestamp(sysDateTime);

    int numMappers = sqoopOptions.getNumMappers();

    String exportTableTemplate =
        conf.get(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_TEMPLATE, "");

    String user = sqoopOptions.getUsername();
    if (user == null) {
      user = OracleManager.getSessionUser(connection);
    }

    OracleTable templateTableContext =
        OraOopUtilities.decodeOracleTableName(user, exportTableTemplate);

    boolean noLoggingOnNewTable =
        conf.getBoolean(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_NO_LOGGING,
            false);

    String updateKeyCol = sqoopOptions.getUpdateKeyCol();

    /* =========================== */
    /* VALIDATION OF INPUTS */
    /* =========================== */

    if (updateKeyCol == null || updateKeyCol.isEmpty()) {
      // We're performing an "insert" export, not an "update" export.

      // Check that the "oraoop.export.merge" property has not been specified,
      // as this would be
      // an invalid scenario...
      if (OraOopUtilities.getExportUpdateMode(conf) == UpdateMode.Merge) {
        throw new RuntimeException(String.format(
            "\n\nThe option \"%s\" can only be used if \"%s\" is "
                + "also used.\n", OraOopConstants.ORAOOP_EXPORT_MERGE,
            "--update-key"));
      }
    }

    if (OraOopUtilities
        .userWantsToCreatePartitionedExportTableFromTemplate(conf)
        || OraOopUtilities
            .userWantsToCreateNonPartitionedExportTableFromTemplate(conf)) {

      // OraOop will create the export table.

      if (oraOopConnManager.getOracleTableContext().getName().length()
              > OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH) {
        String msg =
            String.format(
                "The Oracle table name \"%s\" is longer than %d characters.\n"
              + "Oracle will not allow a table with this name to be created.",
            oraOopConnManager.getOracleTableContext().getName(),
            OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH);
        throw new RuntimeException(msg);
      }

      if (updateKeyCol != null && !updateKeyCol.isEmpty()) {

        // We're performing an "update" export, not an "insert" export.

        // Check whether the user is attempting an "update" (i.e. a non-merge).
        // If so, they're
        // asking to only UPDATE rows in a (about to be created) (empty) table
        // that contains no rows.
        // This will be a waste of time, as we'd be attempting to perform UPDATE
        // operations against a
        // table with no rows in it...
        UpdateMode updateMode = OraOopUtilities.getExportUpdateMode(conf);
        if (updateMode == UpdateMode.Update) {
          throw new RuntimeException(String.format(
              "\n\nCombining the option \"%s\" with the option \"%s=false\" is "
            + "nonsensical, as this would create an "
            + "empty table and then perform "
            + "a lot of work that results in a table containing no rows.\n",
              OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_TEMPLATE,
              OraOopConstants.ORAOOP_EXPORT_MERGE));
        }
      }

      // Check that the specified template table actually exists and is a
      // table...
      String templateTableObjectType =
          OraOopOracleQueries.getOracleObjectType(connection,
              templateTableContext);
      if (templateTableObjectType == null) {
        throw new RuntimeException(String.format(
            "The specified Oracle template table \"%s\" does not exist.",
            templateTableContext.toString()));
      }

      if (!templateTableObjectType
          .equalsIgnoreCase(OraOopConstants.Oracle.OBJECT_TYPE_TABLE)) {
        throw new RuntimeException(
          String.format(
              "The specified Oracle template table \"%s\" is not an "
            + "Oracle table, it's a %s.",
              templateTableContext.toString(), templateTableObjectType));
      }

      if (conf.getBoolean(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_DROP,
          false)) {
        OraOopOracleQueries.dropTable(connection, oraOopConnManager
            .getOracleTableContext());
      }

      // Check that there is no existing database object with the same name of
      // the table to be created...
      String newTableObjectType =
          OraOopOracleQueries.getOracleObjectType(connection, oraOopConnManager
              .getOracleTableContext());
      if (newTableObjectType != null) {
        throw new RuntimeException(
          String.format(
              "%s cannot create a new Oracle table named %s as a \"%s\" "
            + "with this name already exists.",
            OraOopConstants.ORAOOP_PRODUCT_NAME, oraOopConnManager
                .getOracleTableContext().toString(), newTableObjectType));
      }
    } else {
      // The export table already exists.

      if (updateKeyCol != null && !updateKeyCol.isEmpty()) {

        // We're performing an "update" export, not an "insert" export.

        // Check that there exists an index on the export table on the
        // update-key column(s).
        // Without such an index, this export may perform like a real dog...
        String[] updateKeyColumns =
            OraOopUtilities.getExportUpdateKeyColumnNames(sqoopOptions);
        if (!OraOopOracleQueries.doesIndexOnColumnsExist(connection,
            oraOopConnManager.getOracleTableContext(), updateKeyColumns)) {
          String msg = String.format(
              "\n**************************************************************"
            + "***************************************************************"
            + "\n\tThe table %1$s does not have a valid index on "
            + "the column(s) %2$s.\n"
            + "\tAs a consequence, this export may take a long time to "
            + "complete.\n"
            + "\tIf performance is unacceptable, consider reattempting this "
            + "job after creating an index "
            + "on this table via the SQL...\n"
            + "\t\tcreate index <index_name> on %1$s(%2$s);\n"
            + "****************************************************************"
            + "*************************************************************",
                      oraOopConnManager.getOracleTableContext().toString(),
                      OraOopUtilities.stringArrayToCSV(updateKeyColumns));
          messagesToDisplayAfterWelcome.add(new OraOopLogMessage(
              OraOopConstants.Logging.Level.WARN, msg));
        }
      }
    }

    /* ================================= */
    /* CREATE A PARTITIONED TABLE */
    /* ================================= */
    if (OraOopUtilities
        .userWantsToCreatePartitionedExportTableFromTemplate(conf)) {

      // Create a new Oracle table using the specified template...

      String[] subPartitionNames =
          OraOopUtilities.generateExportTableSubPartitionNames(numMappers,
              sysDateTime, conf);
      // Create the export table from a template table...
      String tableStorageClause =
          OraOopUtilities.getExportTableStorageClause(conf);

      OraOopOracleQueries.createExportTableFromTemplateWithPartitioning(
          connection, oraOopConnManager.getOracleTableContext(),
          tableStorageClause, templateTableContext, noLoggingOnNewTable,
          partitionName, sysDateTime, sqoopOptions.getNumMappers(),
          subPartitionNames);
      return;
    }

    /* ===================================== */
    /* CREATE A NON-PARTITIONED TABLE */
    /* ===================================== */
    if (OraOopUtilities
        .userWantsToCreateNonPartitionedExportTableFromTemplate(conf)) {

      String tableStorageClause =
          OraOopUtilities.getExportTableStorageClause(conf);

      OraOopOracleQueries.createExportTableFromTemplate(connection,
          oraOopConnManager.getOracleTableContext(), tableStorageClause,
          templateTableContext, noLoggingOnNewTable);
      return;
    }

    /* ===================================================== */
    /* ADD ADDITIONAL PARTITIONS TO AN EXISTING TABLE */
    /* ===================================================== */

    // If the export table is partitioned, and the partitions were created by
    // OraOop, then we need
    // create additional partitions...

    OracleTablePartitions tablePartitions =
        OraOopOracleQueries.getPartitions(connection, oraOopConnManager
            .getOracleTableContext());
    // Find any partition name starting with "ORAOOP_"...
    OracleTablePartition oraOopPartition =
        tablePartitions.findPartitionByRegEx("^"
            + OraOopConstants.EXPORT_TABLE_PARTITION_NAME_PREFIX);

    if (tablePartitions.size() > 0 && oraOopPartition == null) {

      for (int idx = 0; idx < tablePartitions.size(); idx++) {
        messagesToDisplayAfterWelcome.add(new OraOopLogMessage(
            OraOopConstants.Logging.Level.INFO, String.format(
                "The Oracle table %s has a partition named \"%s\".",
                oraOopConnManager.getOracleTableContext().toString(),
                tablePartitions.get(idx).getName())));
      }

      messagesToDisplayAfterWelcome.add(new OraOopLogMessage(
          OraOopConstants.Logging.Level.WARN, String.format(
              "The Oracle table %s is partitioned.\n"
                  + "These partitions were not created by %s.",
              oraOopConnManager.getOracleTableContext().toString(),
              OraOopConstants.ORAOOP_PRODUCT_NAME)));
    }

    if (oraOopPartition != null) {

      // Indicate in the configuration what's happening...
      conf.setBoolean(OraOopConstants.EXPORT_TABLE_HAS_ORAOOP_PARTITIONS, true);

      messagesToDisplayAfterWelcome
          .add(new OraOopLogMessage(
              OraOopConstants.Logging.Level.INFO,
              String
                  .format(
                      "The Oracle table %s is partitioned.\n"
                          + "These partitions were created by %s, so "
                          + "additional partitions will now be created.\n"
                          + "The name of the new partition will be \"%s\".",
                      oraOopConnManager.getOracleTableContext().toString(),
                      OraOopConstants.ORAOOP_PRODUCT_NAME, partitionName)));

      String[] subPartitionNames =
          OraOopUtilities.generateExportTableSubPartitionNames(numMappers,
              sysDateTime, conf);

      // Add another partition (and N subpartitions) to this existing,
      // partitioned export table...
      OraOopOracleQueries.createMoreExportTablePartitions(connection,
          oraOopConnManager.getOracleTableContext(), partitionName,
          sysDateTime, subPartitionNames);

      return;
    }
  }

  private void checkForOldOraOopTemporaryOracleTables(Connection connection,
      Object sysDateTime, String schema,
      List<OraOopLogMessage> messagesToDisplayAfterWelcome) {

    try {

      StringBuilder message = new StringBuilder();
      message
        .append(String.format(
          "The following tables appear to be old temporary tables created by "
        + "%s that have not been deleted.\n"
        + "They are probably left over from jobs that encountered an error and "
        + "could not clean up after themselves.\n"
        + "You might want to drop these Oracle tables in order to reclaim "
        + "Oracle storage space:\n", OraOopConstants.ORAOOP_PRODUCT_NAME));
      boolean showMessage = false;

      String generatedTableName =
          OraOopUtilities.generateExportTableMapperTableName(0, sysDateTime,
              schema).getName();
      generatedTableName = generatedTableName.replaceAll("[0-9]", "%");
      generatedTableName =
          OraOopUtilities.replaceAll(generatedTableName, "%%", "%");
      Date sysDate = OraOopOracleQueries.oraDATEToDate(sysDateTime);

      List<OracleTable> tables =
          OraOopOracleQueries.getTablesWithTableNameLike(connection, schema,
              generatedTableName);

      for (OracleTable oracleTable : tables) {
        OraOopUtilities.DecodedExportMapperTableName tableName =
            OraOopUtilities.decodeExportTableMapperTableName(oracleTable);
        if (tableName != null) {
          Date tableDate =
              OraOopOracleQueries.oraDATEToDate(tableName.getTableDateTime());
          double daysApart =
              (sysDate.getTime() - tableDate.getTime()) / (1000 * 60 * 60 * 24);
          if (daysApart > 1.0) {
            showMessage = true;
            message.append(String.format("\t%s\n", oracleTable.toString()));
          }
        }
      }

      if (showMessage) {
        messagesToDisplayAfterWelcome.add(new OraOopLogMessage(
            OraOopConstants.Logging.Level.INFO, message.toString()));
      }
    } catch (Exception ex) {
      messagesToDisplayAfterWelcome.add(new OraOopLogMessage(
          OraOopConstants.Logging.Level.WARN, String.format(
              "%s was unable to check for the existance of old "
                  + "temporary Oracle tables.\n" + "Error:\n%s",
              OraOopConstants.ORAOOP_PRODUCT_NAME, ex.toString())));
    }
  }
}
