All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jk.data.datasource.JKDataSourceFactory Maven / Gradle / Ivy

/*
 * Copyright 2002-2022 Dr. Jalal Kiswani. 
 * Email: [email protected]
 * Check out https://smart-api.com for more details
 * 
 * All the opensource projects of Dr. Jalal Kiswani are free for personal and academic use only, 
 * for commercial usage and support, please contact the author.
 *
 * 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.jk.data.datasource;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.jk.core.config.JKConfig;
import com.jk.core.config.JKConfigEvent;
import com.jk.core.config.JKConfigListener;
import com.jk.core.config.JKConstants;
import com.jk.core.logging.JKLogger;
import com.jk.core.logging.JKLoggerFactory;
import com.jk.core.util.JK;
import com.jk.data.datasource.impl.JKHibernateDataSource;
import com.jk.data.datasource.impl.JKPlainDataSource;

// TODO: Auto-generated Javadoc
/**
 * A factory for creating JKDataSource objects.
 */
public class JKDataSourceFactory {

	/** The Constant DEFAULT_PREFIX. */
	private static final String DEFAULT_PREFIX = "default";

	/** The logger. */
	static JKLogger logger = JKLoggerFactory.getLogger(JKDataSourceFactory.class);

	/** The datasources. */
	static Map datasources = new HashMap<>();
	static {
		JKConfig.addListner(new JKConfigListener() {

			@Override
			public void reloadConfig(JKConfigEvent event) {
				close();
			}

			@Override
			public void closeConfig(JKConfigEvent event) {
				close();
			}
		});
	}

	/**
	 * Creates a new JKDataSource object.
	 *
	 * @return the JK data source
	 */
	public static JKDataSource getDefaultDataSource() {
		return getDataSource(DEFAULT_PREFIX);
	}

	/**
	 * Creates a new JKDataSource object.
	 *
	 * @param prefix the prefix
	 * @return the JK data source
	 */
	public static synchronized JKDataSource getDataSource(String prefix) {
		logger.debug("getDataSource for prefix({})", prefix);
		JKDataSource datasource = datasources.get(prefix);
		if (datasource == null) {
			logger.info("datasource ({}) not found, create new one", prefix);
			Properties properties = JKConfig.get().toProperties();
			if (!prefix.equals(DEFAULT_PREFIX)) {
				Set keys = properties.keySet();

				Properties databaseProperties = new Properties();
				for (Object key : keys) {
					if (key.toString().startsWith(prefix + ".")) {
						logger.debug("key found ({})", key);
						String newKey = key.toString().replaceFirst(prefix + ".", "");
						String value = properties.getProperty(key.toString());
						databaseProperties.setProperty(newKey, value);
					}
				}
				logger.info("create new datasource for prefix ({}) with the properties ({})", prefix,
						databaseProperties);
				if (databaseProperties.size() == 0) {
					logger.error("no config found for prefix " + prefix);
					JK.exception("no config found for prefix " + prefix);
				}
				properties = databaseProperties;
			}
			datasource = createDataSource(prefix, properties);
			datasources.put(prefix, datasource);
		}
		return datasource;
	}

	/**
	 * Creates a new JKDataSource object.
	 *
	 * @param driver         the driver
	 * @param url            the url
	 * @param userName       the user name
	 * @param password       the password
	 * @param dialect        the dialect
	 * @param datasourceName the datasource name
	 * @return the JK data source
	 */
	/////////////////////////////////////////////////////////////////////////
	public static JKDataSource createDataSource(String driver, String url, String userName, String password,
			Class dialect, String datasourceName) {
		JKConfig prop = new JKConfig();
		prop.setString(JKConstants.Hibernate.HIBERNATE_JDBC_DRIVER_NAME, driver);
		prop.setString(JKConstants.Hibernate.JDBC_URL, url);
		prop.setString(JKConstants.Hibernate.JDBC_USERNAME, userName);
		prop.setPassword(JKConstants.Hibernate.JDBC_PASSWORD, password);
		if (dialect != null) {
			prop.setString(JKConstants.Hibernate.HIBERNATE_JDBC_DIALICT, dialect.getName());
		} else {
			JK.fixMe("check the correct dialict automtically");
		}
		return createDataSource(datasourceName, prop.toProperties());
	}

	/**
	 * Creates a new JKDataSource object.
	 *
	 * @param name the name
	 * @param prop the prop
	 * @return the JK data source
	 */
	/////////////////////////////////////////////////////////////////////////
	public static JKDataSource createDataSource(String name, final Properties prop) {
		String defaultDataSourceType = JKConfig.get().getProperty(JKConstants.Database.DEFAULT_DATASOURCE_TYPE,
				"hibernate");
		JKDataSource datasource = null;
		switch (defaultDataSourceType) {
		case "plain":
			datasource = new JKPlainDataSource(name, prop);
			break;
		default:
			// make the plain is the default??
			datasource = new JKHibernateDataSource(name, prop);
		}
		datasource.init();

//		Runtime.getRuntime().addShutdownHook(new Thread() {
//			@Override
//			public void run() {
//				try {
//					datasource.close();
//				} catch (Exception e) {
//				}
//			}
//		});
		return datasource;
	}

	/**
	 * Close.
	 */
	public static void close() {
		logger.info("close");
		Collection values = datasources.values();
		for (JKDataSource ds : values) {
			try {
				logger.info("closing datasource at url ({}) ", ds.getDatabaseUrl());
				ds.close();
			} catch (Exception e) {
				logger.info("unable to close datasource at url ({}) ", ds.getDatabaseUrl());
			}
		}
		closeDrivers();
		values.clear();
	}
	
	/**
	 * Close drivers.
	 */
	public static void closeDrivers() {
		Enumeration drivers = DriverManager.getDrivers();
		while (drivers.hasMoreElements()) {
			Driver driver = drivers.nextElement();
			try {
				DriverManager.deregisterDriver(driver);
				logger.info("deregistering jdbc driver: {}", driver);
			} catch (SQLException e) {
				logger.info("Error deregistering driver {}", driver);
			}
		}
	}


}