001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (C) 2012  Paul Ferraro
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package net.sf.hajdbc.cache.lazy;
019
020import java.lang.ref.Reference;
021import java.sql.Connection;
022import java.sql.DatabaseMetaData;
023import java.sql.SQLException;
024import java.util.AbstractMap;
025import java.util.Map;
026import java.util.TreeMap;
027
028import net.sf.hajdbc.Database;
029import net.sf.hajdbc.DatabaseCluster;
030import net.sf.hajdbc.DatabaseProperties;
031import net.sf.hajdbc.cache.DatabaseMetaDataCache;
032import net.sf.hajdbc.dialect.Dialect;
033import net.sf.hajdbc.util.ref.ReferenceMap;
034import net.sf.hajdbc.util.ref.SoftReferenceFactory;
035
036/**
037 * Per-database {@link DatabaseMetaDataCache} implementation that populates itself lazily.
038 * @author Paul Ferraro
039 */
040public class LazyDatabaseMetaDataCache<Z, D extends Database<Z>> implements DatabaseMetaDataCache<Z, D>
041{
042        private final Map<D, Map.Entry<DatabaseProperties, LazyDatabaseMetaDataProvider>> map = new ReferenceMap<D, Map.Entry<DatabaseProperties, LazyDatabaseMetaDataProvider>>(new TreeMap<D, Reference<Map.Entry<DatabaseProperties, LazyDatabaseMetaDataProvider>>>(), SoftReferenceFactory.getInstance());
043        private final DatabaseCluster<Z, D> cluster;
044
045        public LazyDatabaseMetaDataCache(DatabaseCluster<Z, D> cluster)
046        {
047                this.cluster = cluster;
048        }
049        
050        /**
051         * {@inheritDoc}
052         * @see net.sf.hajdbc.cache.DatabaseMetaDataCache#flush()
053         */
054        @Override
055        public void flush()
056        {
057                synchronized (this.map)
058                {
059                        this.map.clear();
060                }
061        }
062
063        /**
064         * {@inheritDoc}
065         * @see net.sf.hajdbc.cache.DatabaseMetaDataCache#getDatabaseProperties(net.sf.hajdbc.Database, java.sql.Connection)
066         */
067        @Override
068        public DatabaseProperties getDatabaseProperties(D database, Connection connection) throws SQLException
069        {
070                synchronized (this.map)
071                {
072                        Map.Entry<DatabaseProperties, LazyDatabaseMetaDataProvider> entry = this.map.get(database);
073                        
074                        if (entry == null)
075                        {
076                                DatabaseMetaData metaData = connection.getMetaData();
077                                Dialect dialect = this.cluster.getDialect();
078                                LazyDatabaseMetaDataProvider provider = new LazyDatabaseMetaDataProvider(metaData);
079                                DatabaseProperties properties = new LazyDatabaseProperties(provider, dialect);
080                                
081                                entry = new AbstractMap.SimpleImmutableEntry<DatabaseProperties, LazyDatabaseMetaDataProvider>(properties, provider);
082
083                                this.map.put(database, entry);
084                        }
085                        else
086                        {
087                                entry.getValue().setConnection(connection);
088                        }
089                        
090                        return entry.getKey();
091                }
092        }
093}