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 }