1 22 23 package org.xquark.mapper; 24 25 import java.io.PrintWriter ; 26 import java.sql.SQLException ; 27 import java.util.HashMap ; 28 29 import javax.sql.DataSource ; 30 31 import org.xquark.mapper.dbms.AbstractConnection; 32 import org.xquark.mapper.dbms.AbstractConnectionFactory; 33 import org.xquark.mapper.dbms.RepositoryConnectionImpl; 34 import org.xquark.mapper.metadata.Repository; 35 import org.xquark.mapper.util.CounterMap; 36 import org.xquark.mapper.util.DestructionToken; 37 import org.xquark.xml.xdbc.XMLConnection; 38 import org.xquark.xml.xdbc.XMLDBCException; 39 import org.xquark.xml.xdbc.XMLDataSource; 40 41 44 public final class RepositoryDataSource implements XMLDataSource 45 { 46 private static final String RCSRevision = "$Revision: 1.1 $"; 47 private static final String RCSName = "$Name: $"; 48 49 private static final String ORACLE_URL_PREFIX = "jdbc:oracle"; 50 private static final String TIMESTEN_URL_PREFIX = "jdbc:timesten"; 51 private static final String SYBASE_URL_PREFIX = "jdbc:sybase"; 52 private static final String SQLSERVER_URL_PREFIX = "jdbc:microsoft:sqlserver"; 53 54 private static final String ORACLE_DRIVER_CLASS = "oracle.jdbc.driver.OracleDriver"; 55 private static final String TIMESTEN_DRIVER_CLASS = "com.timesten.jdbc.TimesTenDriver"; 56 private static final String SYBASE_DRIVER_CLASS = "com.sybase.jdbc2.jdbc.SybDriver"; 57 private static final String SQLSERVER_DRIVER_CLASS = "com.microsoft.jdbc.sqlserver.SQLServerDriver"; 58 59 private static final String DATA_SOURCE_FAKE_NAME = "DS"; 60 61 private CounterMap repositories = new CounterMap(); 62 private HashMap standByRepositories = new HashMap (); 63 64 private AbstractConnectionFactory connectionFactory; 65 private DataSource JDBCDs; 66 67 private PrintWriter logger; 68 private int logTimeout; 69 70 75 public RepositoryDataSource(String url) 76 throws XMLDBCException 77 { 78 acceptsJDBCURL(url); 79 connectionFactory = new AbstractConnectionFactory(url); 80 } 81 82 87 public RepositoryDataSource(DataSource ds) 88 { 89 JDBCDs = ds; 90 } 91 92 private boolean acceptsJDBCURL(String url) throws XMLDBCException 93 { 94 try { 95 if (url.startsWith(ORACLE_URL_PREFIX)) 97 Class.forName(ORACLE_DRIVER_CLASS); 98 else if (url.startsWith(TIMESTEN_URL_PREFIX)) 99 Class.forName(TIMESTEN_DRIVER_CLASS); 100 else if (url.startsWith(SYBASE_URL_PREFIX)) 101 Class.forName(SYBASE_DRIVER_CLASS); 102 else if (url.startsWith(SQLSERVER_URL_PREFIX)) 103 Class.forName(SQLSERVER_DRIVER_CLASS); 104 } 106 catch (Exception e) 107 { 108 throw new XMLDBCException("JDBC driver could not be found. Check your classpath or load it yourself if it is not supported."); 109 } 110 111 return true; 112 } 113 114 117 public java.io.PrintWriter getLogWriter() 118 { 119 return logger; 120 } 121 122 125 public void setLogWriter(PrintWriter writer) 126 { 127 logger = writer; 128 } 129 130 133 public void setLoginTimeout(int seconds) 134 { 135 logTimeout = seconds; 136 } 137 138 141 public int getLoginTimeout() 142 { 143 return logTimeout; 144 } 145 146 154 public XMLConnection getConnection(String user, String password) throws XMLDBCException 155 { 156 return getRepositoryConnection(user, password); 157 } 158 159 168 public RepositoryConnection getRepositoryConnection(String user, String password) 169 throws XMLDBCException 170 { 171 String key = user.toUpperCase(); 172 173 Repository rep = (Repository)repositories.checkOut(key); 174 175 try { 176 if (rep == null) 177 { 178 rep = (Repository)standByRepositories.get(key); 180 if (rep == null) 181 rep = new Repository(getAbstractConnection(user, password)); 182 else 183 rep.restoreConnection(getAbstractConnection(user, password)); 184 repositories.put(key, rep); 185 } 186 187 return new RepositoryConnectionImpl( 188 rep, 189 getAbstractConnection(user, password), 190 new ConnectionDestructor() 191 ); 192 } 193 catch (SQLException e) { 194 throw new RepositoryException(RepositoryException.DB_ERROR, 195 "JDBC error while creating a RepositoryConnection.", e); 196 } 197 198 } 199 200 206 public XMLConnection getConnection() throws XMLDBCException 207 { 208 return getRepositoryConnection(); 209 } 210 211 217 public RepositoryConnection getRepositoryConnection() throws XMLDBCException 218 { 219 Repository rep = (Repository)repositories.checkOut(DATA_SOURCE_FAKE_NAME); 220 221 try 222 { 223 if (rep == null) 224 { 225 rep = (Repository)standByRepositories.get(DATA_SOURCE_FAKE_NAME); 227 if (rep == null) 228 rep = new Repository(getAbstractConnection()); 229 else 230 rep.restoreConnection(getAbstractConnection()); 231 repositories.put(DATA_SOURCE_FAKE_NAME, rep); 232 } 233 234 return new RepositoryConnectionImpl( 235 rep, 236 getAbstractConnection(), 237 new DSConnectionDestructor() 238 ); 239 } 240 catch (SQLException e) 241 { 242 throw new RepositoryException(RepositoryException.DB_ERROR, 243 "JDBC error while creating a RepositoryConnection.", e); 244 } 245 } 246 247 private AbstractConnection getAbstractConnection() throws SQLException 251 { 252 if (JDBCDs == null) 253 return connectionFactory.getAbstractConnection(); 254 else 255 return AbstractConnectionFactory.newConnection(JDBCDs.getConnection()); 256 } 257 258 private AbstractConnection getAbstractConnection(String user, String password) 259 throws SQLException 260 { 261 if (JDBCDs == null) 262 return connectionFactory.getAbstractConnection(user, password); 263 else 264 return AbstractConnectionFactory.newConnection( 265 JDBCDs.getConnection(user, password) 266 ); 267 } 268 269 private void releaseConnection(String user) 270 { 271 Repository rep = (Repository)repositories.remove(user); 272 273 try 274 { 275 if (rep != null) 276 { 277 if (rep.isAlive()) { 279 rep.withdrawConnection(); standByRepositories.put(user, rep); 281 } 282 else 283 rep.close(); 284 } 285 } 286 catch (XMLDBCException e) 287 { 288 } 290 } 291 292 private class ConnectionDestructor implements DestructionToken 293 { 294 public void destruct(Object o) 295 { 296 try 297 { 298 releaseConnection(((RepositoryConnection)o).getUserName()); 299 } 300 catch (XMLDBCException e) 301 { 302 } 304 } 305 } 306 307 private class DSConnectionDestructor implements DestructionToken 308 { 309 public void destruct(Object o) 310 { 311 releaseConnection(DATA_SOURCE_FAKE_NAME); 312 } 313 } 314 } 315 | Popular Tags |