/* * HA-JDBC: High-Availability JDBC * Copyright (C) 2012 Paul Ferraro * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.hajdbc.cache.lazy; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.SequencePropertiesFactory; import net.sf.hajdbc.SequenceSupport; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.cache.AbstractDatabaseProperties; import net.sf.hajdbc.cache.DatabaseMetaDataProvider; import net.sf.hajdbc.dialect.Dialect; /** * @author Paul Ferraro * */ public class LazyDatabaseProperties extends AbstractDatabaseProperties { private final Dialect dialect; private final DatabaseMetaDataProvider provider; private final SequencePropertiesFactory sequenceFactory; private final AtomicReference<Map<QualifiedName, TableProperties>> tablesRef = new AtomicReference<>(); private final AtomicReference<Map<QualifiedName, SequenceProperties>> sequencesRef = new AtomicReference<>(); private final AtomicReference<List<String>> defaultSchemasRef = new AtomicReference<>(); private final AtomicReference<Map<Integer, Map.Entry<String, Integer>>> typesRef = new AtomicReference<>(); public LazyDatabaseProperties(DatabaseMetaDataProvider provider, Dialect dialect) throws SQLException { super(provider.getDatabaseMetaData(), dialect); this.provider = provider; this.dialect = dialect; SequenceSupport support = dialect.getSequenceSupport(); this.sequenceFactory = (support != null) ? support.createSequencePropertiesFactory(this.nameFactory) : null; } @Override protected Map<QualifiedName, TableProperties> tables() throws SQLException { Map<QualifiedName, TableProperties> tables = this.tablesRef.get(); if (tables == null) { tables = new HashMap<>(); for (QualifiedName table: this.dialect.getTables(this.provider.getDatabaseMetaData(), this.nameFactory)) { TableProperties properties = new LazyTableProperties(table, this.provider, this.dialect, this.nameFactory); tables.put(properties.getName(), properties); } if (!this.tablesRef.compareAndSet(null, tables)) { return this.tablesRef.get(); } } return tables; } @Override protected Map<QualifiedName, SequenceProperties> sequences() throws SQLException { Map<QualifiedName, SequenceProperties> sequences = this.sequencesRef.get(); if (sequences == null) { sequences = new HashMap<>(); if (this.sequenceFactory != null) { for (SequenceProperties sequence: this.dialect.getSequenceSupport().getSequences(this.provider.getDatabaseMetaData(), this.sequenceFactory)) { sequences.put(sequence.getName(), sequence); } } if (!this.sequencesRef.compareAndSet(null, sequences)) { return this.sequencesRef.get(); } } return sequences; } @Override protected List<String> defaultSchemas() throws SQLException { List<String> schemas = this.defaultSchemasRef.get(); if (schemas == null) { schemas = this.dialect.getDefaultSchemas(this.provider.getDatabaseMetaData()); if (!this.defaultSchemasRef.compareAndSet(null, schemas)) { return this.defaultSchemasRef.get(); } } return schemas; } @Override protected Map<Integer, Entry<String, Integer>> types() throws SQLException { Map<Integer, Map.Entry<String, Integer>> types = this.typesRef.get(); if (types == null) { types = this.dialect.getTypes(this.provider.getDatabaseMetaData()); if (!this.typesRef.compareAndSet(null, types)) { return this.typesRef.get(); } } return types; } }