/**
* 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.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* Create and initialize connections to Oracle RDBMS.
*/
public class OracleConnectionFactory {
protected OracleConnectionFactory() {
}
protected static final OraOopLog LOG = OraOopLogFactory
.getLog(OracleConnectionFactory.class.getName());
public static Connection createOracleJdbcConnection(
String jdbcDriverClassName, String jdbcUrl, String username,
String password) throws SQLException {
Properties props = null;
return createOracleJdbcConnection(jdbcDriverClassName, jdbcUrl, username,
password, props);
}
public static Connection createOracleJdbcConnection(
String jdbcDriverClassName, String jdbcUrl, String username,
String password, Properties additionalProps) throws SQLException {
loadJdbcDriver(jdbcDriverClassName);
Connection connection =
createConnection(jdbcUrl, username, password, additionalProps);
// Only OraOopDBRecordReader will call initializeOracleConnection(), as
// we only need to initialize the session(s) prior to the mapper starting
// it's job.
// i.e. We don't need to initialize the sessions in order to get the
// table's data-files etc.
// initializeOracleConnection(connection, conf);
return connection;
}
private static void loadJdbcDriver(String jdbcDriverClassName) {
try {
Class.forName(jdbcDriverClassName);
} catch (ClassNotFoundException ex) {
String errorMsg =
"Unable to load the jdbc driver class : " + jdbcDriverClassName;
LOG.error(errorMsg);
throw new RuntimeException(errorMsg);
}
}
private static Connection createConnection(String jdbcUrl, String username,
String password, Properties additionalProps) throws SQLException {
Properties props = new Properties();
if (username != null) {
props.put("user", username);
}
if (password != null) {
props.put("password", password);
}
if (additionalProps != null && additionalProps.size() > 0) {
props.putAll(additionalProps);
}
try {
Connection result = DriverManager.getConnection(jdbcUrl, props);
result.setAutoCommit(false);
return result;
} catch (SQLException ex) {
String errorMsg = String.format(
"Unable to obtain a JDBC connection to the URL \"%s\" as user \"%s\": ",
jdbcUrl, (username != null) ? username : "[null]");
LOG.error(errorMsg, ex);
throw ex;
}
}
public static void initializeOracleConnection(Connection connection,
org.apache.hadoop.conf.Configuration conf) throws SQLException {
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
connection.setAutoCommit(false);
OraOopOracleQueries.setConnectionTimeZone(connection, conf);
setSessionClientInfo(connection, conf);
OraOopOracleQueries.setJdbcFetchSize(connection, conf);
executeOraOopSessionInitializationStatements(connection, conf);
}
protected static void setSessionClientInfo(Connection connection,
org.apache.hadoop.conf.Configuration conf) {
String sql = "";
try {
sql =
"begin \n"
+ " dbms_application_info.set_module(module_name => "
+ "'%s', action_name => '%s'); \n"
+ "end;";
String oracleSessionActionName =
conf.get(OraOopConstants.ORACLE_SESSION_ACTION_NAME);
sql =
String.format(sql, OraOopConstants.ORACLE_SESSION_MODULE_NAME,
oracleSessionActionName);
Statement statement = connection.createStatement();
statement.execute(sql);
LOG.info("Initializing Oracle session with SQL :\n" + sql);
} catch (Exception ex) {
LOG.error(String.format("An error occurred while attempting to execute "
+ "the following Oracle session-initialization statement:" + "\n%s"
+ "\nError:" + "\n%s", sql, ex.getMessage()));
}
}
protected static void executeOraOopSessionInitializationStatements(
Connection connection, org.apache.hadoop.conf.Configuration conf) {
List<String> statements = parseOraOopSessionInitializationStatements(conf);
if (statements.size() == 0) {
LOG.warn(String
.format(
"No Oracle 'session initialization' statements were found to "
+ "execute.\nCheck that your %s and/or %s files are correctly "
+ "installed in the ${SQOOP_HOME}/conf directory.",
OraOopConstants.ORAOOP_SITE_TEMPLATE_FILENAME,
OraOopConstants.ORAOOP_SITE_FILENAME));
} else {
for (String statement : statements) {
try {
connection.createStatement().execute(statement);
LOG.info("Initializing Oracle session with SQL : " + statement);
} catch (Exception ex) {
LOG.error(String.format(
"An error occurred while attempting to execute "
+ "the following Oracle session-initialization statement:"
+ "\n%s" + "\nError:" + "\n%s", statement, ex.getMessage()));
}
}
}
}
protected static List<String> parseOraOopSessionInitializationStatements(
org.apache.hadoop.conf.Configuration conf) {
ArrayList<String> result = new ArrayList<String>();
if (conf == null) {
throw new IllegalArgumentException(
"No configuration argument must be specified.");
}
String sessionInitializationStatements =
conf.get(OraOopConstants.ORAOOP_SESSION_INITIALIZATION_STATEMENTS);
if (sessionInitializationStatements != null
&& !sessionInitializationStatements.isEmpty()) {
String[] initializationStatements =
sessionInitializationStatements.split(";");
for (String initializationStatement : initializationStatements) {
initializationStatement = initializationStatement.trim();
if (initializationStatement != null
&& !initializationStatement.isEmpty()
&& !initializationStatement
.startsWith(OraOopConstants.Oracle.
ORACLE_SQL_STATEMENT_COMMENT_TOKEN)) {
LOG.debug(String
.format(
"initializationStatement (quoted & pre-expression "
+ "evaluation) = \"%s\"",
initializationStatement));
initializationStatement =
OraOopUtilities.replaceConfigurationExpression(
initializationStatement, conf);
result.add(initializationStatement);
}
}
}
return result;
}
}