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 that 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 = createMockDataSource();
037 driver = createMockDriver();
038 connection = createMockConnection();
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 * Creates the {@link com.mockrunner.mock.jdbc.MockConnection} using <code>new</code>.
145 * This method can be overridden to return a subclass of {@link com.mockrunner.mock.jdbc.MockConnection}.
146 * @return the {@link com.mockrunner.mock.jdbc.MockConnection}
147 */
148 public MockConnection createMockConnection()
149 {
150 return new MockConnection();
151 }
152
153 /**
154 * Creates the {@link com.mockrunner.mock.jdbc.MockDriver} using <code>new</code>.
155 * This method can be overridden to return a subclass of {@link com.mockrunner.mock.jdbc.MockDriver}.
156 * @return the {@link com.mockrunner.mock.jdbc.MockDriver}
157 */
158 public MockDriver createMockDriver()
159 {
160 return new MockDriver();
161 }
162
163 /**
164 * Creates the {@link com.mockrunner.mock.jdbc.MockDataSource} using <code>new</code>.
165 * This method can be overridden to return a subclass of {@link com.mockrunner.mock.jdbc.MockDataSource}.
166 * @return the {@link com.mockrunner.mock.jdbc.MockDataSource}
167 */
168 public MockDataSource createMockDataSource()
169 {
170 return new MockDataSource();
171 }
172
173 /**
174 * Returns the {@link com.mockrunner.mock.jdbc.MockDataSource}.
175 * @return the {@link com.mockrunner.mock.jdbc.MockDataSource}
176 */
177 public MockDataSource getMockDataSource()
178 {
179 return dataSource;
180 }
181
182 /**
183 * Returns the {@link com.mockrunner.mock.jdbc.MockDriver}.
184 * @return the {@link com.mockrunner.mock.jdbc.MockDriver}
185 */
186 public MockDriver getMockDriver()
187 {
188 return driver;
189 }
190
191 /**
192 * Returns the {@link com.mockrunner.mock.jdbc.MockConnection}.
193 * @return the {@link com.mockrunner.mock.jdbc.MockConnection}
194 */
195 public MockConnection getMockConnection()
196 {
197 return connection;
198 }
199 }