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

com.jk.data.datasource.impl.JKAbstractDataSource 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.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import com.jk.core.annotations.AnnotationDetector;
import com.jk.core.config.JKConfig;
import com.jk.core.config.JKConstants;
import com.jk.core.context.JKContext;
import com.jk.core.context.JKContextFactory;
import com.jk.core.exceptions.JKDataAccessException;
import com.jk.core.logging.JKLogger;
import com.jk.core.logging.JKLoggerFactory;
import com.jk.core.security.JKSecurityUtil;
import com.jk.core.util.JK;
import com.jk.core.util.JKIOUtil;
import com.jk.data.datasource.JKDataSource;
import com.jk.data.datasource.JKDatabase;

import jakarta.persistence.Entity;
import jakarta.persistence.EntityManagerFactory;

// TODO: Auto-generated Javadoc
/**
 * The Class JKAbstractDataSource.
 */
public abstract class JKAbstractDataSource implements JKDataSource {
	/** The logger. */
	protected JKLogger logger = JKLoggerFactory.getLogger(getClass());

	/** The fix map. */
//	Map fixMap = new LinkedHashMap();
//	{
//		fixMap.put("hibernate.c3p0.min_size", JKConstants.Hibernate.HIBERNATE_MIN_SIZE);
//		fixMap.put("hibernate.c3p0.max_size", JKConstants.Hibernate.HIBERNATE_MAX_SIZE);
//	}

	/** The entities. */
	private List entities;

	/** The name. */
	private String name;

	/** The properties. */
	private JKConfig config;

	/** The emf. */
	private EntityManagerFactory emf;

	/**
	 * Instantiates a new JK abstract data source.
	 */
	public JKAbstractDataSource() {
	}

	/**
	 * Instantiates a new JK abstract data source.
	 *
	 * @param name the name
	 * @param properties the properties
	 */
	public JKAbstractDataSource(String name, Properties properties) {
		this.name = name;
		initProperties(properties);
	}

	/**
	 * Inits the properties.
	 *
	 * @param properties the properties
	 */
	protected void initProperties(Properties properties) {
		logger.info("Load Pool config default properties from ({})", JKConstants.Config.DEFAULT_CONFIG_FILE);
		config = new JKConfig(JKIOUtil.readPropertiesFile(JKConstants.Config.DEFAULT_CONFIG_FILE));
		// set useful session info
		config.setString("hibernate.connection.v$session.program", JK.getAppName());
		config.addProperties(properties);
		fixProperties();
	}

	/**
	 * Override config from properties.
	 */
	/////////////////////////////////////////////////////////////////////////////
	protected void fixProperties() {
		// we should put them first to insure
		Properties properties = getProperties();
		Set keySet = properties.keySet();
		{ // load config from my proetries file
			for (Object keyObject : keySet) {
				String key = keyObject.toString().trim();
				String value = properties.getProperty(key);
				processProperty(properties, key, value);
			}
		}
	}

	/**
	 * Process property.
	 *
	 * @param properties the properties
	 * @param key the key
	 * @param value the value
	 */
	protected void processProperty(Properties properties, String key, String value) {
//		logger.trace("Processing key ({}) with value({})", key, properties.getProperty(key));
//				key = fixKey(key);

//		logger.trace("Key after ,Processing key ({}) with value({})", key, properties.getProperty(key));
		if (key.startsWith("hibernate.")) {
			logger.debug("Processing Hibernate key ({}) with value({})", key, properties.getProperty(key));
			if (key.toLowerCase().contains("password")) {
				logger.trace("Hibernate: Set ({}) password property )", key);
				if (value.startsWith("___")) {
					value = new String(JKSecurityUtil.decrypt(value.substring(3)));
				}
			} else {
				logger.trace("Hibernate: Set ({}) property with value ({})", key, value);
			}
			config.setProperty(key, value);
		}
	}

	/**
	 * Inits the.
	 */
	public abstract void init();

	/**
	 * Gets the name.
	 *
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 *
	 * @param name the new name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Gets the entities.
	 *
	 * @return the entities
	 */
	public List getEntities() {
		return entities;
	}

	/**
	 * Gets the entities.
	 *
	 * @param initIfNull the init if null
	 * @return the entities
	 */
	public List getEntities(boolean initIfNull) {
		if (entities == null) {
			scanJpaEntities();
		}
		return entities;
	}

//	public Map getFixMap() {
//		return fixMap;
//	}

	/**
 * Gets the properties.
 *
 * @return the properties
 */
@Override
	public Properties getProperties() {
		return config.toProperties();
	}

	/**
	 * Fix key.
	 *
	 * @return the string
	 */
//	/////////////////////////////////////////////////////////////////////////////
//	protected String fixKey(String key) {
//		if (fixMap.get(key) != null) {
//			return fixMap.get(key);
//		}
//		return key;
//	}

	/**
	 * Clean specific database resources.
	 */
	protected void cleanSpecificDatabaseResources() {
		logger.debug("cleanSpecificDatabaseResources ({})", getDatabaseType());
		if (getDatabaseType() == JKDatabase.H2) {
			try {
				Statement stat = getConnection().createStatement();
				stat.execute("SHUTDOWN");
			} catch (Exception e) {
				// logger.error(e);
			}
		}
	}

	/**
	 * Close.
	 *
	 * @param con the con
	 */
	@Override
	public void close(Connection con) {
		logger.debug("Closing connection");
		try {
			// add support for query connection
			if (con == null || con.isClosed()) {
				return;
			}
			con.close();
		} catch (final SQLException e) {
			logger.error(e);
		} finally {
		}
		logger.debug("/Closing connection");
	}

	/**
	 * Close.
	 *
	 * @param connection the connection
	 * @param commit     the commit
	 */
	@Override
	public void close(Connection connection, boolean commit) {
		logger.debug("closeConnection(commit={})", commit);
		try {
			if (connection.getAutoCommit()) {
				logger.trace("Auto commit is already enabled");
			} else {
				if (commit) {
					this.logger.trace("commit transaction");
					connection.commit();
				} else {
					this.logger.trace("rollback transaction");
					connection.rollback();
				}
			}
		} catch (final SQLException e) {
			throw new JKDataAccessException(e);
		} finally {
			close(connection);
			logger.debug("/closeConnection(commit={})", commit);
		}
	}

	/**
	 * Gets the connection.
	 *
	 * @return the connection
	 * @throws JKDataAccessException the JK data access exception
	 */
	@Override
	public Connection getConnection() throws JKDataAccessException {
		logger.debug("getConnection()");
		Connection connection = null;
//		boolean success = false;
		try {
			connection = createConnection();
//			success = true;
			if (config.getPropertyAsBoolean(JKConstants.Database.SET_CLIENT_INFO, false)) {
				connection.setClientInfo(getClientInfoProperties());
			}
			return connection;
		} catch (SQLException | JKDataAccessException e) {
			JK.throww(e);
			return null;
		} finally {
			logger.debug("/getConnection()");
//			synchronized (this) {
//				if (success) {
//					totalConnectionsOpened++;
//				} else {
//					totalConnectionsFailed++;
//				}
//			}
		}
	}

	/**
	 * Gets the client info properties.
	 *
	 * @return the client info properties
	 */
	public Properties getClientInfoProperties() {
		Properties prop = new Properties();
		JKContext ctx = JKContextFactory.getCurrentContext();
		if (getDatabaseType() == JKDatabase.ORACLE) {
			prop.setProperty("OCSID.CLIENTID", ctx.getClientId() == null ? "JK-Client-id" : ctx.getClientId());
			prop.setProperty("OCSID.MODULE", ctx.getModule() == null ? "JK-Module-Name" : ctx.getModule());
			prop.setProperty("OCSID.ACTION", ctx.getAction() == null ? "JK-Action-Name" : ctx.getAction());
		}
		return prop;
	}

	/**
	 * Gets the emf.
	 *
	 * @return the emf
	 */
	public EntityManagerFactory getEmf() {
		return emf;
	}

	/**
	 * Sets the emf.
	 *
	 * @param emf the new emf
	 */
	protected void setEmf(EntityManagerFactory emf) {
		this.emf = emf;
	}

	/**
	 * Adds the J pa entities.
	 */
	/////////////////////////////////////////////////////////////////////////////
	protected void scanJpaEntities() {
		logger.debug("scanJpaEntities()");
		String entitiesPackages = config.getProperty(JKConstants.Database.PROPERTY_DB_ENTITY_PACKAGES, "com.app");

		List entityClassNames = AnnotationDetector.scanAsList(Entity.class, entitiesPackages.split(","));
		entities = new ArrayList<>();
		for (String entityClassName : entityClassNames) {
			logger.info("Adding Entity ({})", entityClassName);
			entities.add(entityClassName);
		}
		logger.debug("/scanJpaEntities()");
	}

	/**
	 * Gets the max allowed connections.
	 *
	 * @return the max allowed connections
	 */
	public int getMaxAllowedConnections() {
		return JK.toInt(getProperties().getProperty(JKConstants.Hibernate.HIBERNATE_MAX_SIZE, "-1"));
	}

	/**
	 * Sets the property.
	 *
	 * @param key the key
	 * @param value the value
	 */
	public void setProperty(String key, String value) {
		config.setProperty(key, value);
	}

	/**
	 * Checks if is entity available.
	 *
	 * @param clas the clas
	 * @return true, if is entity available
	 */
	@Override
	public boolean isEntityAvailable(Class clas) {
		return getEntities(true).indexOf(clas.getName()) != -1;
	}

	/**
	 * Gets the database type.
	 *
	 * @return the database type
	 */
	@Override
	public JKDatabase getDatabaseType() {
		return JKDatabase.getDatabaseByUrl(config.getProperty(JKConstants.Hibernate.JDBC_URL));
	}

	/**
	 * Gets the config.
	 *
	 * @return the config
	 */
	public JKConfig getConfig() {
		return config;
	}

	/////////////////////////////////////////////////////////////////////////////
	/**
	 * Sets the property if null.
	 *
	 * @param property the property
	 * @param value    the value
	 */
	//
	protected void setPropertyIfNull(String property, String value) {
		if (config.getProperty(property) == null) {
			config.setProperty(property, value);
		}
	}

	/**
	 * Close.
	 */
	@Override
	public void close() {
		logger.info("close ({})", getName());
		if (emf != null) {
			try {
				logger.debug("close EMF");
				emf.close();
			} catch (Exception e) {
				logger.error(e);
			}
			emf = null;
		}
	}

	/**
	 * Gets the query connection.
	 *
	 * @return the query connection
	 * @throws JKDataAccessException the JK data access exception
	 */
	@Override
	public Connection getQueryConnection() throws JKDataAccessException {
		logger.debug("getQueryConnection()");
		return getConnection();
	}

}