package org.joget.commons.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
public class DynamicDataSourceManager {
public static final String DATASOURCE_FILE = "app_datasource.properties";
public static final String FILE_PREFIX = "app_datasource-";
public static final String FILE_EXTENSION = ".properties";
public static final String FILE_PATH = SetupManager.getBaseSharedDirectory();
public static final String CURRENT_PROFILE_KEY = "currentProfile";
public static final String DEFAULT_PROFILE = "default";
public static final String SECURE_VALUE = "****SECURE VALUE****";
public static final String SECURE_FIELD = "workflowPassword";
private static DatasourceProfilePropertyManager profilePropertyManager;
/**
* The property manager is initialized via spring injection.
*/
public DynamicDataSourceManager(DatasourceProfilePropertyManager propertyManager) {
DynamicDataSourceManager.profilePropertyManager = propertyManager;
}
public static boolean testConnection(String driver, String url, String user, String password) {
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
return true;
} catch (Exception e) {
return false;
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
}
public static Properties getProperties() {
Properties properties = profilePropertyManager.newInstance();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(determineFilePath(getCurrentProfile())));
properties.load(fis);
} catch (FileNotFoundException e) {
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
return properties;
}
public static String getProperty(String key) {
Properties properties = profilePropertyManager.newInstance();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(determineFilePath(getCurrentProfile())));
properties.load(fis);
return properties.getProperty(key);
} catch (FileNotFoundException e) {
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
return null;
}
public static List<String> getProfileList() {
try {
File[] fileList = new File(FILE_PATH).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
if (name.startsWith(FILE_PREFIX) && name.endsWith(FILE_EXTENSION) && name.length() > (FILE_PREFIX.length() + FILE_EXTENSION.length())) {
return true;
} else {
return false;
}
}
});
List<String> profileList = new ArrayList<String>();
for (File file : fileList) {
String fileName = file.getName();
String profileName = fileName.replace(FILE_PREFIX, "").replace(FILE_EXTENSION, "");
profileList.add(profileName);
}
return profileList;
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
return null;
}
public static Properties getProfileProperties() {
Properties properties = profilePropertyManager.newInstance();
FileInputStream fis = null;
String defaultDataSourceFilename = determineDefaultDataSourceFilename();
try {
fis = new FileInputStream(new File(defaultDataSourceFilename));
properties.load(fis);
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
return properties;
}
public static String getCurrentProfile() {
Properties properties = new Properties();
FileInputStream fis = null;
String defaultDataSourceFilename = determineDefaultDataSourceFilename();
try {
// look for profile or hostname set by HostManager in thread
String currentProfile = HostManager.getCurrentProfile();
if (currentProfile == null || currentProfile.trim().length() == 0) {
// load from properties file
fis = new FileInputStream(new File(defaultDataSourceFilename));
properties.load(fis);
String hostname = HostManager.getCurrentHost();
if (hostname != null && hostname.trim().length() > 0) {
currentProfile = properties.getProperty(hostname);
}
if (currentProfile == null || currentProfile.trim().length() == 0) {
// look for matching context path
String contextPath = HostManager.getContextPath();
if (contextPath != null && contextPath.trim().length() > 0) {
currentProfile = properties.getProperty(contextPath);
}
}
}
if (currentProfile == null || currentProfile.trim().length() == 0) {
// default profile
currentProfile = properties.getProperty(CURRENT_PROFILE_KEY);
}
// set profile in thread
HostManager.setCurrentProfile(currentProfile);
return currentProfile;
} catch (FileNotFoundException e) {
if (!(e.getMessage() != null && e.getMessage().contains("Too many open files"))) {
// As of v5, don't automatically create default profile, to allow setup on first startup
// createDefaultProfile();
LogUtil.debug(DynamicDataSourceManager.class.getName(), defaultDataSourceFilename + " not found, using default datasource");
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
return null;
}
public static void changeProfile(String profileName) {
Properties properties = new Properties();
FileInputStream fis = null;
FileOutputStream fos = null;
String defaultDataSourceFilename = determineDefaultDataSourceFilename();
try {
profileName = SecurityUtil.validateStringInput(profileName);
File datasourceFile = new File(defaultDataSourceFilename);
if (!datasourceFile.exists()) {
new File(FILE_PATH).mkdirs();
datasourceFile.createNewFile();
}
fis = new FileInputStream(datasourceFile);
properties.load(fis);
properties.setProperty(CURRENT_PROFILE_KEY, profileName);
fos = new FileOutputStream(datasourceFile);
properties.store(fos, "");
HostManager.setCurrentProfile(profileName);
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
try {
if (fos != null) {
fos.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
}
public static boolean createProfile(String profileName) {
try {
profileName = SecurityUtil.validateStringInput(profileName);
File file = new File(determineFilePath(profileName));
if (file.exists()) {
return false;
}
file.createNewFile();
return true;
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
return false;
}
public static boolean deleteProfile(String profileName) {
try {
profileName = SecurityUtil.validateStringInput(profileName);
File file = new File(determineFilePath(profileName));
file.delete();
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
return false;
}
public static void writeProperty(String key, String value) {
Properties properties = profilePropertyManager.newInstance();
FileInputStream fis = null;
FileOutputStream fos = null;
try {
String currentProfile = getCurrentProfile();
fis = new FileInputStream(new File(determineFilePath(currentProfile)));
properties.load(fis);
properties.setProperty(key, value);
fos = new FileOutputStream(new File(determineFilePath(currentProfile)));
properties.store(fos, "");
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
try {
if (fos != null) {
fos.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
}
public static Set getPropertyKeySet() {
Properties properties = profilePropertyManager.newInstance();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(determineFilePath(getCurrentProfile())));
properties.load(fis);
return properties.keySet();
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
return null;
}
protected static String determineFilePath(String currentProfile) {
if (!FILE_PATH.endsWith(File.separator)) {
return FILE_PATH + File.separator + FILE_PREFIX + currentProfile + FILE_EXTENSION;
} else {
return FILE_PATH + FILE_PREFIX + currentProfile + FILE_EXTENSION;
}
}
protected static String determineDefaultDataSourceFilename() {
if (!FILE_PATH.endsWith(File.separator)) {
return FILE_PATH + File.separator + DATASOURCE_FILE;
} else {
return FILE_PATH + DATASOURCE_FILE;
}
}
protected static void createDefaultProfile() {
Properties properties = new Properties();
FileOutputStream fos = null;
String defaultDataSourceFilename = determineDefaultDataSourceFilename();
try {
//create datasource properties file
File file = new File(defaultDataSourceFilename);
new File(FILE_PATH).mkdirs();
file.createNewFile();
fos = new FileOutputStream(file);
properties.setProperty(CURRENT_PROFILE_KEY, DEFAULT_PROFILE);
properties.store(fos, "");
//create default datasource properties file
createProfile(DEFAULT_PROFILE);
changeProfile(DEFAULT_PROFILE);
writeProperty("workflowUser", "root");
writeProperty("workflowPassword", "");
writeProperty("workflowDriver", "com.mysql.jdbc.Driver");
writeProperty("workflowUrl", "jdbc:mysql://localhost:3306/jwdb?characterEncoding=UTF-8");
writeProperty("profileName", "");
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "Error creating default profile");
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (Exception e) {
LogUtil.error(DynamicDataSourceManager.class.getName(), e, "");
}
}
}
}