1 22 package org.jboss.resource.adapter.jdbc; 23 24 import java.io.PrintWriter ; 25 import java.io.Serializable ; 26 import java.security.AccessController ; 27 import java.security.PrivilegedAction ; 28 import java.sql.Connection ; 29 import java.sql.SQLException ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.Properties ; 33 import java.util.Set ; 34 35 import javax.resource.ResourceException ; 36 import javax.resource.spi.ConnectionManager ; 37 import javax.resource.spi.ConnectionRequestInfo ; 38 import javax.resource.spi.ManagedConnectionFactory ; 39 import javax.resource.spi.ValidatingManagedConnectionFactory ; 40 import javax.resource.spi.security.PasswordCredential ; 41 import javax.security.auth.Subject ; 42 43 import org.jboss.logging.Logger; 44 import org.jboss.resource.JBossResourceException; 45 46 55 56 public abstract class BaseWrapperManagedConnectionFactory implements ManagedConnectionFactory , ValidatingManagedConnectionFactory , Serializable 57 { 58 59 static final long serialVersionUID = -84923705377702088L; 60 61 public static final int TRACK_STATEMENTS_FALSE_INT = 0; 62 public static final int TRACK_STATEMENTS_TRUE_INT = 1; 63 public static final int TRACK_STATEMENTS_NOWARN_INT = 2; 64 65 public static final String TRACK_STATEMENTS_FALSE = "false"; 66 public static final String TRACK_STATEMENTS_TRUE = "true"; 67 public static final String TRACK_STATEMENTS_NOWARN = "nowarn"; 68 69 protected final Logger log = Logger.getLogger(getClass()); 70 71 protected String userName; 72 protected String password; 73 74 protected final Properties connectionProps = new Properties (); 78 79 protected int transactionIsolation = -1; 80 81 protected int preparedStatementCacheSize = 0; 82 83 protected boolean doQueryTimeout = false; 84 85 90 protected String newConnectionSQL; 91 92 99 protected String checkValidConnectionSQL; 100 101 104 protected String validConnectionCheckerClassName; 105 106 109 protected ValidConnectionChecker connectionChecker; 110 111 112 protected StaleConnectionChecker staleConnectionChecker; 113 114 115 private String staleConnectionCheckerClassName; 116 117 private String exceptionSorterClassName; 118 119 private ExceptionSorter exceptionSorter; 120 121 protected int trackStatements = TRACK_STATEMENTS_NOWARN_INT; 122 123 124 protected boolean sharePS = false; 125 126 protected boolean isTransactionQueryTimeout = false; 127 128 protected int queryTimeout = 0; 129 130 private boolean validateOnMatch = true; 131 132 public BaseWrapperManagedConnectionFactory () 133 { 134 135 } 136 137 public PrintWriter getLogWriter() throws ResourceException 138 { 139 return null; 140 } 141 142 public void setLogWriter(PrintWriter param1) throws ResourceException 143 { 144 } 145 146 public Object createConnectionFactory(ConnectionManager cm) throws ResourceException 147 { 148 return new WrapperDataSource(this, cm); 149 } 150 151 public Object createConnectionFactory() throws ResourceException 152 { 153 throw new JBossResourceException("Resource Adapter does not currently support running in a non-managed environment."); 154 } 155 156 public String getUserName() 157 { 158 return userName; 159 } 160 161 public void setUserName(final String userName) 162 { 163 this.userName = userName; 164 } 165 166 public String getPassword() 167 { 168 return password; 169 } 170 171 public void setPassword(final String password) 172 { 173 this.password = password; 174 } 175 176 public int getPreparedStatementCacheSize() 177 { 178 return preparedStatementCacheSize; 179 } 180 181 public void setPreparedStatementCacheSize(int size) 182 { 183 preparedStatementCacheSize = size; 184 } 185 186 public boolean getSharePreparedStatements() 187 { 188 return sharePS; 189 } 190 191 public void setSharePreparedStatements(boolean sharePS) 192 { 193 this.sharePS = sharePS; 194 } 195 196 public String getTransactionIsolation() 197 { 198 switch (this.transactionIsolation) 199 { 200 case Connection.TRANSACTION_NONE: 201 return "TRANSACTION_NONE"; 202 case Connection.TRANSACTION_READ_COMMITTED: 203 return "TRANSACTION_READ_COMMITTED"; 204 case Connection.TRANSACTION_READ_UNCOMMITTED: 205 return "TRANSACTION_READ_UNCOMMITTED"; 206 case Connection.TRANSACTION_REPEATABLE_READ: 207 return "TRANSACTION_REPEATABLE_READ"; 208 case Connection.TRANSACTION_SERIALIZABLE: 209 return "TRANSACTION_SERIALIZABLE"; 210 case -1: 211 return "DEFAULT"; 212 default: 213 return Integer.toString(transactionIsolation); 214 } 215 } 216 217 public void setTransactionIsolation(String transactionIsolation) 218 { 219 if (transactionIsolation.equals("TRANSACTION_NONE")) 220 this.transactionIsolation = Connection.TRANSACTION_NONE; 221 else if (transactionIsolation.equals("TRANSACTION_READ_COMMITTED")) 222 this.transactionIsolation = Connection.TRANSACTION_READ_COMMITTED; 223 else if (transactionIsolation.equals("TRANSACTION_READ_UNCOMMITTED")) 224 this.transactionIsolation = Connection.TRANSACTION_READ_UNCOMMITTED; 225 else if (transactionIsolation.equals("TRANSACTION_REPEATABLE_READ")) 226 this.transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ; 227 else if (transactionIsolation.equals("TRANSACTION_SERIALIZABLE")) 228 this.transactionIsolation = Connection.TRANSACTION_SERIALIZABLE; 229 else 230 { 231 try 232 { 233 this.transactionIsolation = Integer.parseInt(transactionIsolation); 234 } 235 catch (NumberFormatException nfe) 236 { 237 throw new IllegalArgumentException ("Setting Isolation level to unknown state: " + transactionIsolation); 238 } 239 } 240 } 241 242 public String getNewConnectionSQL() 243 { 244 return newConnectionSQL; 245 } 246 247 public void setNewConnectionSQL(String newConnectionSQL) 248 { 249 this.newConnectionSQL = newConnectionSQL; 250 } 251 252 public String getCheckValidConnectionSQL() 253 { 254 return checkValidConnectionSQL; 255 } 256 257 public void setCheckValidConnectionSQL(String checkValidConnectionSQL) 258 { 259 this.checkValidConnectionSQL = checkValidConnectionSQL; 260 } 261 262 public void setStaleConnectionCheckerClassName(String value) 263 { 264 staleConnectionCheckerClassName = value; 265 266 } 267 268 public String getStaleConnectionCheckerClassName() 269 { 270 return staleConnectionCheckerClassName; 271 272 } 273 274 public String getTrackStatements() 275 { 276 if (trackStatements == TRACK_STATEMENTS_FALSE_INT) 277 return TRACK_STATEMENTS_FALSE; 278 else if (trackStatements == TRACK_STATEMENTS_TRUE_INT) 279 return TRACK_STATEMENTS_TRUE; 280 return TRACK_STATEMENTS_NOWARN; 281 } 282 283 public boolean getValidateOnMatch() 284 { 285 return this.validateOnMatch; 286 } 287 288 public void setValidateOnMatch(boolean validateOnMatch) 289 { 290 this.validateOnMatch = validateOnMatch; 291 } 292 293 public void setTrackStatements(String value) 294 { 295 if (value == null) 296 throw new IllegalArgumentException ("Null value for trackStatements"); 297 String trimmed = value.trim(); 298 if (trimmed.equalsIgnoreCase(TRACK_STATEMENTS_FALSE)) 299 trackStatements = TRACK_STATEMENTS_FALSE_INT; 300 else if (trimmed.equalsIgnoreCase(TRACK_STATEMENTS_TRUE)) 301 trackStatements = TRACK_STATEMENTS_TRUE_INT; 302 else 303 trackStatements = TRACK_STATEMENTS_NOWARN_INT; 304 } 305 306 public String getExceptionSorterClassName() 307 { 308 return exceptionSorterClassName; 309 } 310 311 public void setExceptionSorterClassName(String exceptionSorterClassName) 312 { 313 this.exceptionSorterClassName = exceptionSorterClassName; 314 } 315 316 public String getValidConnectionCheckerClassName() 317 { 318 return validConnectionCheckerClassName; 319 } 320 321 public void setValidConnectionCheckerClassName(String value) 322 { 323 validConnectionCheckerClassName = value; 324 } 325 326 public boolean isTransactionQueryTimeout() 327 { 328 return isTransactionQueryTimeout; 329 } 330 331 public void setTransactionQueryTimeout(boolean value) 332 { 333 isTransactionQueryTimeout = value; 334 } 335 336 public int getQueryTimeout() 337 { 338 return queryTimeout; 339 } 340 341 public void setQueryTimeout(int timeout) 342 { 343 queryTimeout = timeout; 344 } 345 346 public Set getInvalidConnections(final Set connectionSet) throws ResourceException 347 { 348 final Set invalid = new HashSet (); 349 350 for (Iterator iter = connectionSet.iterator(); iter.hasNext();) 351 { 352 final Object anonymous = iter.next(); 353 354 if (anonymous instanceof BaseWrapperManagedConnection) 355 { 356 BaseWrapperManagedConnection mc = (BaseWrapperManagedConnection) anonymous; 357 358 if (!mc.checkValid()) 359 { 360 invalid.add(mc); 361 362 } 363 364 } 365 366 } 367 368 return invalid; 369 } 370 371 372 382 protected Properties getConnectionProperties(Subject subject, ConnectionRequestInfo cri) 383 throws ResourceException 384 { 385 if (cri != null && cri.getClass() != WrappedConnectionRequestInfo.class) 386 throw new JBossResourceException("Wrong kind of ConnectionRequestInfo: " + cri.getClass()); 387 388 Properties props = new Properties (); 389 props.putAll(connectionProps); 390 if (subject != null) 391 { 392 if (SubjectActions.addMatchingProperties(subject, props, this) == true) 393 return props; 394 throw new JBossResourceException("No matching credentials in Subject!"); 395 } 396 WrappedConnectionRequestInfo lcri = (WrappedConnectionRequestInfo)cri; 397 if (lcri != null) 398 { 399 props.setProperty("user", (lcri.getUserName() == null)? "": lcri.getUserName()); 400 props.setProperty("password", (lcri.getPassword() == null)? "": lcri.getPassword()); 401 return props; 402 } 403 if (userName != null) 404 { 405 props.setProperty("user", userName); 406 props.setProperty("password", (password == null) ? "" : password); 407 } 408 return props; 409 } 410 411 boolean isExceptionFatal(SQLException e) 412 { 413 try 414 { 415 if (exceptionSorter != null) 416 return exceptionSorter.isExceptionFatal(e); 417 418 if (exceptionSorterClassName != null) 419 { 420 try 421 { 422 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 423 Class clazz = cl.loadClass(exceptionSorterClassName); 424 exceptionSorter = (ExceptionSorter)clazz.newInstance(); 425 return exceptionSorter.isExceptionFatal(e); 426 } 427 catch (Exception e2) 428 { 429 log.warn("exception trying to create exception sorter (disabling):", e2); 430 exceptionSorter = new NullExceptionSorter(); 431 } 432 } 433 } 434 catch (Throwable t) 435 { 436 log.warn("Error checking exception fatality: ", t); 437 } 438 return false; 439 } 440 441 444 SQLException isValidConnection(Connection c) 445 { 446 if (connectionChecker != null) 448 return connectionChecker.isValidConnection(c); 449 450 if (validConnectionCheckerClassName != null) 452 { 453 try 454 { 455 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 456 Class clazz = cl.loadClass(validConnectionCheckerClassName); 457 connectionChecker = (ValidConnectionChecker) clazz.newInstance(); 458 return connectionChecker.isValidConnection(c); 459 } 460 catch (Exception e) 461 { 462 log.warn("Exception trying to create connection checker (disabling):", e); 463 connectionChecker = new NullValidConnectionChecker(); 464 } 465 } 466 467 if (checkValidConnectionSQL != null) 469 { 470 connectionChecker = new CheckValidConnectionSQL(checkValidConnectionSQL); 471 return connectionChecker.isValidConnection(c); 472 } 473 474 return null; 476 } 477 478 boolean isStaleConnection(SQLException e) 479 { 480 boolean isStale = false; 481 482 if(staleConnectionChecker != null) 483 { 484 485 isStale = staleConnectionChecker.isStaleConnection(e); 486 487 } 488 489 if(staleConnectionCheckerClassName != null) 490 { 491 492 try 493 { 494 495 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 496 Class clazz = cl.loadClass(staleConnectionCheckerClassName); 497 staleConnectionChecker = (StaleConnectionChecker)clazz.newInstance(); 498 isStale = staleConnectionChecker.isStaleConnection(e); 499 500 }catch (Exception ex2) 501 { 502 log.warn("exception trying to create stale connection checker (disabling)" + staleConnectionCheckerClassName, ex2); 503 staleConnectionChecker = new NullStaleConnectionChecker(); 504 505 } 506 507 } 508 509 return isStale; 510 } 511 512 513 514 static class SubjectActions implements PrivilegedAction 515 { 516 Subject subject; 517 518 Properties props; 519 520 ManagedConnectionFactory mcf; 521 522 SubjectActions(Subject subject, Properties props, ManagedConnectionFactory mcf) 523 { 524 this.subject = subject; 525 this.props = props; 526 this.mcf = mcf; 527 } 528 529 public Object run() 530 { 531 Iterator i = subject.getPrivateCredentials().iterator(); 532 while (i.hasNext()) 533 { 534 Object o = i.next(); 535 if (o instanceof PasswordCredential ) 536 { 537 PasswordCredential cred = (PasswordCredential ) o; 538 if (cred.getManagedConnectionFactory().equals(mcf)) 539 { 540 props.setProperty("user", (cred.getUserName() == null) ? "" : cred.getUserName()); 541 if( cred.getPassword() != null ) 542 props.setProperty("password", new String (cred.getPassword())); 543 return Boolean.TRUE; 544 } 545 } 546 } 547 return Boolean.FALSE; 548 } 549 550 static boolean addMatchingProperties(Subject subject, Properties props, ManagedConnectionFactory mcf) 551 { 552 SubjectActions action = new SubjectActions(subject, props, mcf); 553 Boolean matched = (Boolean ) AccessController.doPrivileged(action); 554 return matched.booleanValue(); 555 } 556 } 557 } 558 | Popular Tags |