001package org.itsallcode.jdbc;
002
003import java.sql.Connection;
004import java.sql.SQLException;
005
006import javax.sql.DataSource;
007
008import org.itsallcode.jdbc.dialect.DbDialect;
009
010/**
011 * This class connects to a database using a {@link DataSource} and returns new
012 * {@link SimpleConnection}s.
013 * <p>
014 * Create a new instance using {@link #create(String, DataSource)} or
015 * {@link #create(DbDialect, DataSource)}.
016 */
017public final class DataSourceConnectionFactory {
018    private final Context context;
019    private final DbDialect dialect;
020    private final DataSource dataSource;
021
022    private DataSourceConnectionFactory(final Context context, final DbDialect dialect, final DataSource dataSource) {
023        this.context = context;
024        this.dialect = dialect;
025        this.dataSource = dataSource;
026    }
027
028    /**
029     * Create a new {@link DataSourceConnectionFactory} using the given JDBC URL and
030     * data source.
031     * <p>
032     * Note: The data source will not be closed automatically. It is the caller's
033     * responsibility to close the data source.
034     * 
035     * @param jdbcUrl    JDBC URL used to determine the database dialect
036     * @param dataSource data source
037     * @return new connection factory
038     */
039    public static DataSourceConnectionFactory create(final String jdbcUrl, final DataSource dataSource) {
040        final DbDialect dialect = new DbDialectFactory().createDialect(jdbcUrl);
041        return create(dialect, dataSource);
042    }
043
044    /**
045     * Create a new {@link DataSourceConnectionFactory} using the given dialect and
046     * data source.
047     * <p>
048     * Note: The data source will not be closed automatically. It is the caller's
049     * responsibility to close the data source.
050     * 
051     * @param dialect    database dialect
052     * @param dataSource data source
053     * @return new connection factory
054     */
055    public static DataSourceConnectionFactory create(final DbDialect dialect, final DataSource dataSource) {
056        return new DataSourceConnectionFactory(Context.builder().build(), dialect, dataSource);
057    }
058
059    /**
060     * Get a new {@link SimpleConnection} from the {@link DataSource}.
061     * 
062     * @return new connection
063     */
064    public SimpleConnection getConnection() {
065        return new SimpleConnection(createConnection(), context, dialect);
066    }
067
068    private Connection createConnection() {
069        try {
070            return dataSource.getConnection();
071        } catch (final SQLException e) {
072            throw new UncheckedSQLException("Error getting connection from data source", e);
073        }
074    }
075}