/*
* Copyright 2016 TWO SIGMA OPEN SOURCE, LLC
*
* 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 com.twosigma.beaker.sql;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import java.nio.charset.StandardCharsets;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
public class ConnectionStringHolder {
public static final String USER_CONNECTION_KEY = "user";
public static final String PASSWORD_CONNECTION_KEY = "password";
public static final String KEY_FOR_DISPLAY_INPUT_DIALOG = "<prompt>";
public static final char EQUAL_SIGN = '=';
public static final char [] SEPARATORS = new char[]{'?', '&', ';' , '/' , '\\'};
private JDBCClient jdbcClient;
private String connectionString;
private String user;
private String password;
private boolean showDialog;
public ConnectionStringHolder(String connectionString, JDBCClient jdbcClient) {
this.jdbcClient = jdbcClient;
setConnectionString(connectionString);
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isShowDialog() {
return showDialog;
}
public void setShowDialog(boolean showDialog) {
this.showDialog = showDialog;
}
public String getConnectionString() {
return connectionString;
}
public String getActualConnectionString() {
return removeParameter(connectionString, USER_CONNECTION_KEY, PASSWORD_CONNECTION_KEY);
}
public void setConnectionString(String connectionString) {
this.connectionString = connectionString;
if(connectionString != null && !connectionString.isEmpty()){
BasicDataSource ds = null;
String user = null;
try {
ds = jdbcClient.getDataSource(connectionString);
} catch (SQLException e) {}
if(ds!= null){
user = getProperty(USER_CONNECTION_KEY, connectionString, ds.getDriver());
}if(user == null){
user = getProperty(USER_CONNECTION_KEY, connectionString);
}
if (user != null) {
if (KEY_FOR_DISPLAY_INPUT_DIALOG.equals(user)) {
showDialog = true;
} else {
this.user = user;
}
String password = getProperty(PASSWORD_CONNECTION_KEY, connectionString);
if (password != null) {
if (KEY_FOR_DISPLAY_INPUT_DIALOG.equals(password)) {
showDialog = true;
} else {
this.password = password;
}
} else {
showDialog = true;
}
}
}
}
protected static String getProperty(String property, String connectionString, Driver dbDriver){
String ret = null;
if(property != null && !property.isEmpty() && dbDriver != null && connectionString != null && !connectionString.isEmpty()){
try {
for (DriverPropertyInfo dpi : dbDriver.getPropertyInfo(connectionString, null)) {
if(property.equalsIgnoreCase(dpi.name.trim())){
ret = dpi.value;
break;
}
}
} catch (SQLException e) {}
}
return ret;
}
/**
* MSSQL driver do not return password, so we need to parse it manually
* @param property
* @param connectionString
* @return
*/
protected static String getProperty(String property, String connectionString) {
String ret = null;
if (property != null && !property.isEmpty() && connectionString != null && !connectionString.isEmpty()) {
for (NameValuePair param : URLEncodedUtils.parse(connectionString, StandardCharsets.UTF_8, SEPARATORS)) {
if(property.equals(param.getName())){
ret = param.getValue();
break;
}
}
}
return ret;
}
protected static String removeParameter(String connectionString, String ... parameters) {
String ret = connectionString;
for (String parameter : parameters) {
int index = ret.indexOf(parameter + EQUAL_SIGN);
if(index > -1){
int parameterEnd = ret.length();
for (char c : SEPARATORS) {
int temp = ret.indexOf(c, index);
if(temp > -1){
parameterEnd = Math.min(temp, parameterEnd);
}
}
String toRet = ret.substring(0, index);
toRet += ret.substring(parameterEnd, ret.length());
ret = toRet;
}
}
return ret;
}
}