/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed 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.pentaho.hadoop.shim.hdi35.invocationhandler;
/**
* User: Dzmitry Stsiapanau Date: 01/17/2017 Time: 15:14
*/
import org.pentaho.hadoop.shim.common.HiveSQLUtils;
import org.pentaho.hadoop.shim.common.invocationhandler.ConnectionInvocationHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* DriverInvocationHandler is a proxy handler class for java.sql.Driver. However the code in this file is specifically
* for handling Hive JDBC calls, and therefore should not be used to proxy any other JDBC objects besides those provided
* by Hive.
*/
public class HDIDriverInvocationHandler implements InvocationHandler {
/**
* The driver.
*/
Driver driver;
/**
* Instantiates a new Driver proxy handler.
*
* @param obj the Driver to proxy
*/
public HDIDriverInvocationHandler( Driver obj ) {
driver = obj;
}
/**
* Intercepts methods called on the Driver to possibly perform alternate processing.
*
* @param proxy the proxy object
* @param method the method being invoked
* @param args the arguments to the method
* @return the object returned by whatever processing takes place
* @throws Throwable if an error occurs during processing
*/
@Override
public Object invoke( final Object proxy, Method method, Object[] args ) throws Throwable {
try {
if ( "connect".equals( method.getName() ) || "acceptsURL".equals( method.getName() ) || "getPropertyInfo"
.equals( method.getName() ) ) {
String sql = (String) args[ 0 ];
if ( !sql.contains( "transportMode" ) ) {
args[ 0 ] = sql + ";httpPath=cliservice;transportMode=http";
}
if ( !"acceptsURL".equals( method.getName() ) ) {
Properties info = (Properties) args[ 1 ];
info.setProperty( "httpPath", "cliservice" );
info.setProperty( "transportMode", "http" );
}
}
Object o = method.invoke( driver, args );
if ( o instanceof Connection ) {
// Intercept the Connection object so we can proxy that too
Connection proxiedConnection = (Connection) Proxy.newProxyInstance( o.getClass().getClassLoader(),
new Class[] { Connection.class }, new ConnectionInvocationHandler( (Connection) o ) );
String dbName = HiveSQLUtils.getDatabaseNameFromURL( (String) args[ 0 ] );
useSchema( dbName, proxiedConnection.createStatement() );
return proxiedConnection;
} else {
return o;
}
} catch ( Throwable t ) {
throw ( t instanceof InvocationTargetException ) ? t.getCause() : t;
}
}
protected static void useSchema( String dbName, Statement statement ) throws SQLException {
if ( dbName.trim().length() > 0 ) {
String queries = String.format( "use %s", dbName );
statement.execute( queries );
}
}
}