package net.raymanoz.config;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Set;
import net.raymanoz.io.FileImpl;
import net.raymanoz.io.File;
import net.raymanoz.ui.GUIInteractionStrategy;
import net.raymanoz.ui.NoUserInputStrategy;
import net.raymanoz.ui.UserInteractionStrategy;
import net.raymanoz.util.DirType;
import net.raymanoz.util.FileUtil;
import net.raymanoz.util.Properties;
import static net.raymanoz.config.UMigrateProperty.*;
public class ConfigurationImpl implements Configuration {
private static final int DEFAULT_NUMBER_OF_DIGITS = 1;
private static final int DEFAULT_DB_VERSION = 1;
private FileUtil fileUtil;
private static Connection connection;
private final ApplicationProperties properties;
private DatabaseType databaseType = null;
private Properties uMigrateproperties;
public ConfigurationImpl(ApplicationProperties properties, FileUtil fileUtil, Properties uMigrateproperties) {
this.properties = properties;
this.fileUtil = fileUtil;
this.uMigrateproperties = uMigrateproperties;
}
public File getScriptDirectory(long dbVersion) {
if (dbVersion < 0) {
throw new IllegalStateException(String.format("asked for a negative DB Version (%d) script dir", dbVersion));
}
final String dirfmt = properties.getString(SCRIPTS_DIRECTORY.getKey());
final String dirName = String.format(dirfmt, Math.max(dbVersion, 0));
if ((dbVersion > 1) && (dirfmt.compareTo(dirName) ==0)) {
throw new IllegalStateException(String.format("Scipt Directory doesn't seem to have version tag - " +
"suggest adding '_%%03d' to script.dir in config (currently it is '%s'",
dirfmt));
}
return createExistingDirectory(dirName, DirType.SCRIPT, dbVersion);
}
public File getExecuteDirectory() {
String dirName = properties.getString(EXECUTION_DIRECTORY.getKey());
return createExistingDirectory(dirName, DirType.EXECUTED_SCRIPTS, null);
}
private File createExistingDirectory(String dirName, DirType dirType, Long dbversion) {
File dir = fileUtil.newFile(dirName, dirType, dbversion);
if (!dir.exists(true)) {
throw new IllegalStateException(String.format("%s directory '%s' does not exist", dirType.Desc(dbversion), dir));
}
return dir;
}
public File getTemplateFile() {
String filename = properties.getString(TEMPLATE_FILENAME.getKey());
return new FileImpl(filename, null, DirType.TEMPLATE);
}
public String getExecutionCommand() {
return properties.getString(EXECUTION_COMMAND.getKey());
}
public int getNumberOfDigits() {
String numberOfDigits = properties.getString(NUMBER_OF_DIGITS.getKey());
if(numberOfDigits==null) {
return DEFAULT_NUMBER_OF_DIGITS;
}
return new Integer(numberOfDigits);
}
public UserInteractionStrategy getUserInteractionStrategy() {
String message = properties.getString(CONFIRMATION_MESSAGE.getKey());
if (message == null) {
return new NoUserInputStrategy();
} else {
return new GUIInteractionStrategy(this, message);
}
}
private boolean databaseclassChecked = false;
private void checkDatabaseClass(){
if (databaseclassChecked) return;
try {
Class.forName(properties.getString(JDBC_DRIVER.getKey()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
databaseclassChecked = true;
}
private Connection createConnection(String account, String password){
checkDatabaseClass();
String url = properties.getString(JDBC_URL.getKey());
try {
return DriverManager.getConnection(url, account, password);
} catch (SQLException e) {
final String msgFmt = "Error trying to connect to '%s' using url '%s'";
throw new RuntimeException(String.format(msgFmt, account, url), e);
}
}
public Connection getConnection(String account, String password){
if (account == null || account.length() == 0){
account = properties.getString(JDBC_USERNAME.getKey());
password = properties.getString(JDBC_PASSWORD.getKey());
}
else if (!checkUserExists(account)) {
return null;
}
return createConnection(account, password);
};
@Override
public Set<String> getConnectionVariablesRequiringDialog() {
return properties.findVariablesRequiringDialog(JDBC_USERNAME.getKey(), JDBC_PASSWORD.getKey(), JDBC_URL.getKey());
}
public Connection getConnection() {
if(connection == null) {
String username = properties.getString(JDBC_USERNAME.getKey());
String password = properties.getString(JDBC_PASSWORD.getKey());
connection = createConnection(username, password);
}
return connection;
}
public String getSchemaVersionTable() {
return properties.getString(SCHEMA_VERSION_TABLE.getKey());
}
public String getScriptHistoryTable() {
return properties.getString(SCRIPT_HISTORY_TABLE.getKey());
}
public DatabaseType getDatabaseType(){
if (databaseType == null){
databaseType = DatabaseType.find(properties.getString(JDBC_URL.getKey()));
}
return databaseType;
}
public long getLatestDBVersion() {
String dbVerStr = properties.getString(LATEST_SCRIPT_DBVERSION.getKey());
if(dbVerStr==null) {
return DEFAULT_DB_VERSION;
}
return new Long(dbVerStr);
}
public File getLatestScriptDirectory() {
return getScriptDirectory(getLatestDBVersion());
}
@Override
public Properties uMigrateProperties() {
return uMigrateproperties;
}
@Override
public String getMigrationMessage() {
return properties.getString(MIGRATION_MESSAGE.getKey());
}
@Override
public boolean checkUserExists(String account){
if (!getDatabaseType().supportsCheckusr()) return true;
boolean result = false;
try {
PreparedStatement statement = getConnection().prepareStatement(getDatabaseType().getmetaDataChkUserSQL());
try{
statement.setString(1, account);
ResultSet resultSet = statement.executeQuery();
try {
if (resultSet.next()) {
result = resultSet.getLong(1) > 0;
}
} finally {
resultSet.close();
}
} finally {
statement.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return result;
}
@Override
public java.io.File getSchemaRepositryRootDir() {
String dir = properties.getString(SCHEMA_REPOSITORY_ROOT_DIR.getKey());
if (dir == null) return null;
return new java.io.File(dir);
}
}