001    package com.mockrunner.mock.jdbc;
002    
003    import java.sql.Driver;
004    import java.sql.DriverManager;
005    import java.sql.SQLException;
006    import java.util.Enumeration;
007    import java.util.HashSet;
008    import java.util.Iterator;
009    import java.util.Set;
010    
011    import com.mockrunner.base.NestedApplicationException;
012    
013    /**
014     * Used to create all types of JDBC mock objects. 
015     * Maintains the necessary dependencies between the mock objects.
016     * If you use the mock objects returned by this
017     * factory in your tests you can be sure, they are all
018     * up to date.
019     * Please note, that this class removes all drivers
020     * from the JDBC <code>DriverManager</code> and registers
021     * the {@link MockDriver}. All drivers are preserved and
022     * can be restored with {@link #restoreDrivers}.
023     */
024    public class JDBCMockObjectFactory
025    {
026        private MockDataSource dataSource;
027        private MockDriver driver;
028        private MockConnection connection;
029        private Set preservedDrivers;
030        
031        /**
032         * Creates a new set of mock objects.
033         */
034        public JDBCMockObjectFactory()
035        {
036            dataSource = new MockDataSource();
037            driver = new MockDriver();
038            connection = new MockConnection();
039            preservedDrivers = new HashSet();
040            setUpDependencies();
041        }
042        
043        private void setUpDependencies()
044        {
045            dataSource.setupConnection(connection);
046            driver.setupConnection(connection);
047            registerMockDriver();
048        }
049    
050        private void deregisterDrivers()
051        {
052            try
053            {
054                Enumeration drivers = DriverManager.getDrivers();
055                while(drivers.hasMoreElements())
056                {
057                    DriverManager.deregisterDriver((Driver)drivers.nextElement());
058                }
059            }
060            catch(SQLException exc)
061            {
062                throw new NestedApplicationException(exc);
063            }
064        }
065        
066        private void deregisterMockDrivers()
067        {
068            try
069            {
070                Enumeration drivers = DriverManager.getDrivers();
071                while(drivers.hasMoreElements())
072                {
073                    Driver currentDriver = (Driver)drivers.nextElement();
074                    if(currentDriver instanceof MockDriver)
075                    {
076                        DriverManager.deregisterDriver(currentDriver);
077                    }
078                }
079            }
080            catch(SQLException exc)
081            {
082                throw new NestedApplicationException(exc);
083            }
084        }
085        
086        private void preserveDrivers()
087        {
088            Enumeration drivers = DriverManager.getDrivers();
089            while(drivers.hasMoreElements())
090            {
091                Driver currentDriver = (Driver)drivers.nextElement();
092                if(!(currentDriver instanceof MockDriver))
093                {
094                    preservedDrivers.add(currentDriver);
095                }
096            }
097        }
098        
099        /**
100         * Removes all JDBC drivers from the <code>DriveManager</code> and
101         * registers the mock driver. The removed drivers are preserved and
102         * can be restored with {@link #restoreDrivers}.
103         */
104        public void registerMockDriver()
105        {
106            try
107            {
108                preserveDrivers();
109                deregisterDrivers();
110                DriverManager.registerDriver(driver);
111            }
112            catch(SQLException exc)
113            {
114                throw new NestedApplicationException(exc);
115            }
116        }
117        
118        /**
119         * Since <code>JDBCMockObjectFactory</code> removes all the
120         * drivers from the <code>DriveManager</code> (so the
121         * {@link MockDriver} is guaranteed to be the only one)
122         * you can use this method to restore the original drivers.
123         * Automatically called by {@link com.mockrunner.base.BaseTestCase#tearDown}.
124         */
125        public void restoreDrivers()
126        {
127            deregisterMockDrivers();
128            try
129            {
130                Iterator drivers = preservedDrivers.iterator();
131                while(drivers.hasNext())
132                {
133                    DriverManager.registerDriver((Driver)drivers.next());
134                }
135            }
136            catch(SQLException exc)
137            {
138                throw new NestedApplicationException(exc);
139            }
140            preservedDrivers.clear();
141        }
142    
143        /**
144         * Returns the {@link com.mockrunner.mock.jdbc.MockDataSource}.
145         * @return the {@link com.mockrunner.mock.jdbc.MockDataSource}
146         */
147        public MockDataSource getMockDataSource()
148        {
149            return dataSource;
150        }
151        
152        /**
153         * Returns the {@link com.mockrunner.mock.jdbc.MockDriver}.
154         * @return the {@link com.mockrunner.mock.jdbc.MockDriver}
155         */
156        public MockDriver getMockDriver()
157        {
158            return driver;
159        }
160    
161        /**
162         * Returns the {@link com.mockrunner.mock.jdbc.MockConnection}.
163         * @return the {@link com.mockrunner.mock.jdbc.MockConnection}
164         */
165        public MockConnection getMockConnection()
166        {
167            return connection;
168        }
169    }