001    
002    /*
003     * Copyright (C) 2011 Archie L. Cobbs. All rights reserved.
004     *
005     * $Id: UpdatingDataSource.java 268 2012-02-01 20:24:34Z archie.cobbs $
006     */
007    
008    package org.dellroad.stuff.schema;
009    
010    import java.sql.Connection;
011    import java.sql.SQLException;
012    
013    import javax.sql.DataSource;
014    
015    /**
016     * A {@link DataSource} that wraps an inner {@link DataSource} and automatically applies a configured
017     * {@link SQLCommandList} on first access.
018     *
019     * @see SQLCommandList
020     */
021    public class UpdatingDataSource extends AbstractUpdatingDataSource {
022    
023        private SQLCommandList action;
024        private boolean transactional = true;
025    
026        /**
027         * Configure the {@link SQLCommandList} to be applied to the database on first access. Required property.
028         */
029        public void setSQLCommandList(SQLCommandList action) {
030            this.action = action;
031        }
032    
033        /**
034         * Configure whether the {@link SQLCommandList} is applied transactionally or not.
035         * Default is {@code true}.
036         */
037        public void setTransactional(boolean transactional) {
038            this.transactional = transactional;
039        }
040    
041        @Override
042        protected void updateDataSource(DataSource dataSource) throws SQLException {
043    
044            // Sanity check
045            if (this.action == null)
046                throw new IllegalArgumentException("no SQLCommandList configured");
047    
048            // Get connection
049            Connection c = dataSource.getConnection();
050            boolean tx = this.transactional;
051            try {
052                try {
053    
054                    // Open transaction if so configured
055                    if (tx) {
056                        c.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
057                        c.setAutoCommit(false);
058                    }
059    
060                    // Apply SQL command(s)
061                    this.action.apply(c);
062    
063                    // Commit transaction
064                    if (tx)
065                        c.commit();
066                    tx = false;
067                } finally {
068                    if (tx)
069                        c.rollback();
070                }
071            } finally {
072                c.close();
073            }
074        }
075    }
076