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

org.pojava.persistence.sql.DatabaseCache Maven / Gradle / Ivy

Go to download

POJava Persistence is a small library of tools used in the persistence and retrieval of data to and from storage, such as to a database or XML document. It contains an ORM (Object Relational Mapping) tool that supports use of existing beans and POJO's rather than requiring POJO's to be instrumented to support a tool.

The newest version!
package org.pojava.persistence.sql;

import org.pojava.persistence.util.SqlTool;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.security.InvalidParameterException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * This singleton caches object properties that facilitate interchange between Java and external
 * data stores.
 * 
 * @author John Pile
 */
public class DatabaseCache {

    /**
     * Holds DataSourceMetadata objects by DataSource name.
     */
    private static Map dataSourceMetadataCache = new HashMap();

    /**
     * Holds DataSource objects by DataSource name.
     */
    private static Map dataSourceCache = new HashMap();

    /**
     * Holds TableMap objects by Java class + table name.
     */
    private static Map> tableMapCache = new HashMap>();

    /**
     * Holds the names of DataSource objects used for locks.
     */
    private static Map dataSourceLocks = new HashMap();

    /**
     * Return the metadata for the named DataSource
     * 
     * @param dsName
     *            Name of DataSource
     * @return Metadata gathered from a connection from this dataSource
     */
    public static DataSourceMetadata getDataSourceMetadata(String dsName) throws SQLException {
        // Try the fastest option first
        if (dataSourceMetadataCache.containsKey(dsName)) {
            return (DataSourceMetadata) dataSourceMetadataCache.get(dsName);
        }
        DataSourceMetadata metadata;
        Object lock;
        // Acquire a lock unique to the dsName
        synchronized (dataSourceLocks) {
            lock = dataSourceLocks.get(dsName);
            if (lock == null) {
                lock = new Object();
                dataSourceLocks.put(dsName, lock);
            }
        }
        // The lock allows one thread per DataSource name
        synchronized (lock) {
            metadata = (DataSourceMetadata) dataSourceMetadataCache.get(dsName);
            if (metadata == null) {
                DataSource dataSource = getDataSource(dsName);
                Connection conn = dataSource.getConnection();
                metadata = new DataSourceMetadata(conn);
                dataSourceMetadataCache.put(dsName, metadata);
            }
        }
        return metadata;
    }

    /**
     * Fetch a DataSource from the registry.
     * 
     * @param dsName named datasource
     * @return DataSource retrieved from cache or JNDI registry.
     */
    public static DataSource getDataSource(String dsName) {
        // Try the fastest option first
        if (dataSourceCache.containsKey(dsName)) {
            return dataSourceCache.get(dsName);
        }
        // Retrieve from JNDI Registry
        Context ctx;
        DataSource ds;
        try {
            ctx = new InitialContext();
        } catch (NamingException ex) {
            throw new IllegalStateException(
                    ex.getMessage()
                            + "  See org.pojava.persistence.jndi.JNDIRegistry if you need to create an InitialContext for unit testing.");
        }
        try {
            ds = (DataSource) ctx.lookup("java:comp/env/jdbc/" + dsName.trim());
        } catch (NamingException ex) {
            throw new InvalidParameterException(dsName.trim() + " triggered NamingException "
                    + ex.getMessage());
        }
        if (ds == null) {
            throw new IllegalStateException("Could not find java:comp/env/jdbc/"
                    + dsName.trim() + " in registry.");
        } else {
            dataSourceCache.put(dsName, ds);
        }
        return ds;
    }

    /**
     * Build a key combining a java class with a table name.
     * 
     * @param javaClass Class of java file
     * @param tableName Table name
     * @param dataSourceName Data Source name
     * @return String combining name, table, dataSource for use as a key
     */
    private static String tableMapKey(Class javaClass, String tableName,
            String dataSourceName) {
        return javaClass.getName() + ":" + tableName + ":" + dataSourceName;
    }

    /**
     * Register a tableMap
     * 
     * @param tableMap Mapped fields
     */
    public static void registerTableMap(TableMap tableMap) {
        tableMapCache.put(tableMapKey(tableMap.getClass(), tableMap.getTableName(), tableMap
                .getDataSourceName()), tableMap);
    }

    /**
     * Register a DataSource.
     * 
     * @param dataSourceName datasource name
     * @param dataSource JDBC data source
     */
    public static void registerDataSource(String dataSourceName, DataSource dataSource) {
        dataSourceCache.put(dataSourceName, dataSource);
    }

    /**
     * Retrieve a tableMap
     * 
     * @param javaClass Java Class
     * @param tableName Table Name
     * @param dataSourceName Data Source Name
     * @return TableMap or null if not found.
     */
    @SuppressWarnings("unchecked")
    public static  TableMap getTableMap(Class javaClass, String tableName,
            String dataSourceName) {
        String key = tableMapKey(javaClass, tableName, dataSourceName);
        // Use cached version if it exists
        if (tableMapCache.containsKey(key)) {
            return (TableMap) tableMapCache.get(key);
        }
        Object lock;
        // Acquire a lock unique to the key
        synchronized (dataSourceLocks) {
            lock = dataSourceLocks.get(key);
            if (lock == null) {
                lock = new Object();
                dataSourceLocks.put(key, lock);
            }
        }
        // The lock allows one thread per unique key
        TableMap tableMap;
        synchronized (lock) {
            tableMap = (TableMap) tableMapCache.get(key);
            if (tableMap == null) {
                tableMap = (TableMap) SqlTool.autoGenerateTableMap(javaClass, tableName,
                        dataSourceName);
                tableMapCache.put(key, tableMap);
            }
        }
        return tableMap;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy