1 package org.apache.ojb.broker.platforms; 2 3 17 18 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor; 19 import org.apache.ojb.broker.metadata.ConnectionPoolDescriptor; 20 import org.apache.ojb.broker.util.ClassHelper; 21 import org.apache.ojb.broker.util.logging.Logger; 22 import org.apache.ojb.broker.util.logging.LoggerFactory; 23 24 import java.io.ByteArrayInputStream ; 25 import java.lang.reflect.Method ; 26 import java.sql.Connection ; 27 import java.sql.PreparedStatement ; 28 import java.sql.SQLException ; 29 import java.sql.Statement ; 30 import java.sql.Types ; 31 import java.util.Collections ; 32 import java.util.Map ; 33 import java.util.WeakHashMap ; 34 35 66 public class PlatformOracle9iImpl extends PlatformOracleImpl 67 { 68 private Logger logger = LoggerFactory.getLogger(PlatformOracle9iImpl.class); 69 70 77 protected static final int STATEMENT_CACHE_SIZE = 10; 78 87 protected static final int ROW_PREFETCH_SIZE = 20; 88 89 protected static final int STATEMENTS_PER_BATCH = 20; 92 protected static Map m_batchStatementsInProgress = Collections.synchronizedMap(new WeakHashMap (STATEMENTS_PER_BATCH)); 93 94 protected static final Class [] PARAM_TYPE_EMPTY = {}; 95 protected static final Class [] PARAM_TYPE_INTEGER = {Integer.TYPE}; 96 protected static final Class [] PARAM_TYPE_BOOLEAN = {Boolean.TYPE}; 97 protected static final Class [] PARAM_TYPE_STRING = {String .class}; 98 99 protected static final Object [] PARAM_EMPTY = new Object []{}; 100 protected static final Object [] PARAM_STATEMENT_CACHE_SIZE = new Object []{new Integer (STATEMENT_CACHE_SIZE)}; 101 protected static final Object [] PARAM_ROW_PREFETCH_SIZE = new Object []{new Integer (ROW_PREFETCH_SIZE)}; 102 protected static final Object [] PARAM_STATEMENT_BATCH_SIZE = new Object []{new Integer (STATEMENTS_PER_BATCH)}; 103 protected static final Object [] PARAM_BOOLEAN_TRUE = new Object []{Boolean.TRUE}; 104 105 protected static final String JBOSS_CONN_NAME = 106 "org.jboss.resource.adapter.jdbc.WrappedConnection"; 107 protected static Class JBOSS_CONN_CLASS = null; 108 109 protected static Class ORA_CONN_CLASS; 110 protected static Class ORA_PS_CLASS; 111 protected static Class ORA_CLOB_CLASS; 112 protected static Class ORA_BLOB_CLASS; 113 protected static Class [] PARAM_TYPE_INT_ORACLOB; 114 protected static Class [] PARAM_TYPE_INT_ORABLOB; 115 protected static Method METHOD_SET_STATEMENT_CACHE_SIZE; 116 protected static Method METHOD_SET_IMPLICIT_CACHING_ENABLED; 117 protected static Method METHOD_SET_ROW_PREFETCH; 118 protected static Method METHOD_SET_BLOB = null; 119 protected static Method METHOD_SET_CLOB = null; 120 protected static boolean ORA_STATEMENT_CACHING_AVAILABLE; 121 protected static boolean ORA_ROW_PREFETCH_AVAILABLE; 122 protected static boolean ORA_CLOB_HANDLING_AVAILABLE; 123 protected static boolean ORA_BLOB_HANDLING_AVAILABLE; 124 125 126 protected static final String UNWRAP_CONN_METHOD_NAMES[] = 127 { 128 "unwrapCompletely" , 129 "getInnermostDelegate" , 130 "getUnderlyingConnection" , 131 "getVendorConnection" , 132 "getJDBC" 133 }; 134 140 protected static final Class [][] UNWRAP_CONN_PARAM_TYPES = 141 { 142 null , 143 PARAM_TYPE_EMPTY , 144 PARAM_TYPE_EMPTY , 145 PARAM_TYPE_EMPTY , 146 PARAM_TYPE_EMPTY 147 }; 148 149 protected static final String UNWRAP_PS_METHOD_NAMES[] = 150 { 151 "getInnermostDelegate" , 152 "getUnderlyingStatement" , 153 "getJDBC" 154 }; 155 161 protected static final Class [][] UNWRAP_PS_PARAM_TYPES = 162 { 163 PARAM_TYPE_EMPTY , 164 PARAM_TYPE_EMPTY , 165 PARAM_TYPE_EMPTY 166 }; 167 168 169 172 public PlatformOracle9iImpl() 173 { 174 super(); 175 } 176 177 187 public void initializeJdbcConnection(final JdbcConnectionDescriptor jcd, 188 final Connection conn) 189 throws PlatformException 190 { 191 super.initializeJdbcConnection(jcd, conn); 193 194 final Class connClass = conn.getClass(); 197 if (JBOSS_CONN_CLASS != null && JBOSS_CONN_CLASS.isAssignableFrom(connClass)) 198 { 199 if (logger.isDebugEnabled()) 200 { 201 logger.debug("JBoss detected, Oracle Connection tuning left to J2EE container."); 202 } 203 return; 204 } 205 206 final Connection oraConn = unwrapConnection(conn); 208 if (oraConn == null) 209 { 210 return; 211 } 212 213 if (ORA_STATEMENT_CACHING_AVAILABLE) 216 { 217 try 218 { 219 METHOD_SET_STATEMENT_CACHE_SIZE.invoke(oraConn, PARAM_STATEMENT_CACHE_SIZE); 221 METHOD_SET_IMPLICIT_CACHING_ENABLED.invoke(oraConn, PARAM_BOOLEAN_TRUE); 222 } 223 catch (Exception e) 224 { 225 if (logger.isDebugEnabled()) 226 { 227 logger.debug("PlatformOracle9iImpl could not enable Oracle statement caching." 228 + " Original/unwrapped connection classes=" 229 + connClass.getName() + "/" + oraConn.getClass().getName()); 230 } 231 } 232 } 233 234 239 final ConnectionPoolDescriptor cpd = jcd.getConnectionPoolDescriptor(); 240 final int cpdFetchSizeHint = cpd.getFetchSize(); 241 if (cpdFetchSizeHint == 0 && ORA_ROW_PREFETCH_AVAILABLE) 242 { 243 try 244 { 245 final String prefetchFromJcd; 246 prefetchFromJcd = cpd.getJdbcProperties().getProperty("defaultRowPrefetch"); 247 if (prefetchFromJcd == null) 248 { 249 METHOD_SET_ROW_PREFETCH.invoke(oraConn, PARAM_ROW_PREFETCH_SIZE); 250 } 251 } 253 catch (Exception e) 254 { 255 if (logger.isDebugEnabled()) 256 { 257 logger.debug("PlatformOracle9iImpl could not enable Oracle row pre-fetching." 258 + "Original/unwrapped connection classes=" 259 + connClass.getName() + "/" + oraConn.getClass().getName()); 260 } 261 } 262 } 263 } 264 265 269 public void afterStatementCreate(Statement stmt) 270 { 271 } 276 277 284 public void beforeBatch(PreparedStatement stmt) throws PlatformException 285 { 286 final Method methodSetExecuteBatch; 288 final Method methodSendBatch; 289 methodSetExecuteBatch = ClassHelper.getMethod(stmt, "setExecuteBatch", PARAM_TYPE_INTEGER); 290 methodSendBatch = ClassHelper.getMethod(stmt, "sendBatch", null); 291 292 final boolean statementBatchingSupported = methodSetExecuteBatch != null && methodSendBatch != null; 293 if (statementBatchingSupported) 294 { 295 try 296 { 297 methodSetExecuteBatch.invoke(stmt, PARAM_STATEMENT_BATCH_SIZE); 299 m_batchStatementsInProgress.put(stmt, methodSendBatch); 300 } 301 catch (Exception e) 302 { 303 throw new PlatformException(e.getLocalizedMessage(), e); 304 } 305 } 306 else 307 { 308 super.beforeBatch(stmt); 309 } 310 } 311 312 318 public void addBatch(PreparedStatement stmt) throws PlatformException 319 { 320 final boolean statementBatchingSupported = m_batchStatementsInProgress.containsKey(stmt); 322 if (statementBatchingSupported) 323 { 324 try 325 { 326 stmt.executeUpdate(); 327 } 328 catch (SQLException e) 329 { 330 throw new PlatformException(e.getLocalizedMessage(), e); 331 } 332 } 333 else 334 { 335 super.addBatch(stmt); 336 } 337 } 338 339 349 public int[] executeBatch(PreparedStatement stmt) throws PlatformException 350 { 351 final Method methodSendBatch = (Method ) m_batchStatementsInProgress.remove(stmt); 353 final boolean statementBatchingSupported = methodSendBatch != null; 354 355 int[] retval = null; 356 if (statementBatchingSupported) 357 { 358 try 359 { 360 methodSendBatch.invoke(stmt, null); 362 } 363 catch (Exception e) 364 { 365 throw new PlatformException(e.getLocalizedMessage(), e); 366 } 367 } 368 else 369 { 370 retval = super.executeBatch(stmt); 371 } 372 return retval; 373 } 374 375 376 public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType) throws SQLException 377 { 378 final Statement oraStmt; 380 final Connection oraConn; 381 final boolean oraLargeLobSupportAvailable; 382 if (sqlType == Types.CLOB || sqlType == Types.BLOB) 383 { 384 oraStmt = unwrapStatement(ps); 385 oraConn = unwrapConnection(ps.getConnection()); 386 oraLargeLobSupportAvailable = 387 oraStmt != null && oraConn != null && 388 (sqlType == Types.CLOB ? ORA_CLOB_HANDLING_AVAILABLE : ORA_BLOB_HANDLING_AVAILABLE); 389 } 390 else 391 { 392 oraStmt = null; 393 oraConn = null; 394 oraLargeLobSupportAvailable = false; 395 } 396 397 if (((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY)) && (value instanceof byte[])) 399 { 400 byte buf[] = (byte[]) value; 401 ByteArrayInputStream inputStream = new ByteArrayInputStream (buf); 402 super.changePreparedStatementResultSetType(ps); 403 ps.setBinaryStream(index, inputStream, buf.length); 404 } 405 else if (value instanceof Double ) 406 { 407 ps.setDouble(index, ((Double ) value).doubleValue()); 409 } 410 else if (sqlType == Types.BIGINT && value instanceof Integer ) 411 { 412 ps.setLong(index, ((Integer ) value).intValue()); 414 } 415 else if (sqlType == Types.INTEGER && value instanceof Long ) 416 { 417 ps.setLong(index, ((Long ) value).longValue()); 418 } 419 else if (sqlType == Types.CLOB && oraLargeLobSupportAvailable && value instanceof String ) 420 { 421 try 423 { 424 Object clob = Oracle9iLobHandler.createCLOBFromString(oraConn, (String ) value); 425 METHOD_SET_CLOB.invoke(oraStmt, new Object []{new Integer (index), clob}); 426 } 427 catch (Exception e) 428 { 429 throw new SQLException (e.getLocalizedMessage()); 430 } 431 } 432 else if (sqlType == Types.BLOB && oraLargeLobSupportAvailable && value instanceof byte[]) 433 { 434 try 436 { 437 Object blob = Oracle9iLobHandler.createBLOBFromByteArray(oraConn, (byte[]) value); 438 METHOD_SET_BLOB.invoke(oraStmt, new Object []{new Integer (index), blob}); 439 } 440 catch (Exception e) 441 { 442 throw new SQLException (e.getLocalizedMessage()); 443 } 444 } 445 else 446 { 447 super.setObjectForStatement(ps, index, value, sqlType); 449 } 450 } 451 452 457 public byte getJoinSyntaxType() 458 { 459 return SQL92_NOPAREN_JOIN_SYNTAX; 460 } 461 462 467 protected Connection unwrapConnection(Connection conn) 468 { 469 final Object unwrapped; 470 unwrapped = genericUnwrap(ORA_CONN_CLASS, conn, UNWRAP_CONN_METHOD_NAMES, UNWRAP_CONN_PARAM_TYPES); 471 if (unwrapped == null) 472 { 473 if (logger.isDebugEnabled()) 476 { 477 logger.debug("PlatformOracle9iImpl could not unwrap " + conn.getClass().getName() + 478 ", Oracle-extensions disabled."); 479 } 480 } 481 return (Connection ) unwrapped; 482 } 483 484 489 protected Statement unwrapStatement(Statement ps) 490 { 491 final Object unwrapped; 492 unwrapped = genericUnwrap(ORA_PS_CLASS, ps, UNWRAP_PS_METHOD_NAMES, UNWRAP_PS_PARAM_TYPES); 493 if (unwrapped == null) 494 { 495 if (logger.isDebugEnabled()) 498 { 499 logger.debug("PlatformOracle9iImpl could not unwrap " + ps.getClass().getName() + 500 ", large CLOB/BLOB support disabled."); 501 } 502 } 503 return (Statement ) unwrapped; 504 } 505 506 protected Object genericUnwrap(Class classToMatch, Object toUnwrap, 507 String [] methodNameCandidates, 508 Class [][] methodTypeCandidates) 509 { 510 if (classToMatch == null) 511 { 512 return null; 513 } 514 515 Object unwrapped; 516 final Class psClass = toUnwrap.getClass(); 517 if (classToMatch.isAssignableFrom(psClass)) 518 { 519 return toUnwrap; 520 } 521 try 522 { 523 String methodName; 524 Class [] paramTypes; 525 Object [] args; 526 for (int i = 0; i < methodNameCandidates.length; i++) 527 { 528 methodName = methodNameCandidates[i]; 529 paramTypes = methodTypeCandidates[i]; 530 final Method method = ClassHelper.getMethod(toUnwrap, methodName, paramTypes); 531 if (method != null) 532 { 533 args = paramTypes == PARAM_TYPE_EMPTY ? PARAM_EMPTY : new Object []{ toUnwrap }; 534 unwrapped = method.invoke(toUnwrap, args); 535 if (unwrapped != null) 536 { 537 if (classToMatch.isAssignableFrom(unwrapped.getClass())) 538 { 539 return unwrapped; 540 } 541 return genericUnwrap(classToMatch, unwrapped, 543 methodNameCandidates, methodTypeCandidates); 544 } 545 } 546 } 547 } 548 catch (Exception e) 549 { 550 if (logger.isDebugEnabled()) 552 { 553 logger.debug("genericUnwrap failed", e); 554 } 555 } 556 return null; 557 } 558 559 562 protected void initOracleReflectedVars() 563 { 564 super.initOracleReflectedVars(); 565 try 566 { 567 574 ORA_CONN_CLASS = ClassHelper.getClass("oracle.jdbc.OracleConnection", false); 575 ORA_PS_CLASS = ClassHelper.getClass("oracle.jdbc.OraclePreparedStatement", false); 576 ORA_CLOB_CLASS = ClassHelper.getClass("oracle.sql.CLOB", false); 577 ORA_BLOB_CLASS = ClassHelper.getClass("oracle.sql.BLOB", false); 578 PARAM_TYPE_INT_ORACLOB = new Class []{ Integer.TYPE, ORA_CLOB_CLASS }; 579 PARAM_TYPE_INT_ORABLOB = new Class []{ Integer.TYPE, ORA_BLOB_CLASS }; 580 581 UNWRAP_CONN_PARAM_TYPES[0] = new Class []{ ORA_CONN_CLASS }; 583 584 METHOD_SET_STATEMENT_CACHE_SIZE = 585 ClassHelper.getMethod(ORA_CONN_CLASS, "setStatementCacheSize", PARAM_TYPE_INTEGER); 586 METHOD_SET_IMPLICIT_CACHING_ENABLED = 587 ClassHelper.getMethod(ORA_CONN_CLASS, "setImplicitCachingEnabled", PARAM_TYPE_BOOLEAN); 588 METHOD_SET_ROW_PREFETCH = ClassHelper.getMethod(ORA_CONN_CLASS, "setDefaultRowPrefetch", PARAM_TYPE_INTEGER); 589 METHOD_SET_CLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setCLOB", PARAM_TYPE_INT_ORACLOB); 590 METHOD_SET_BLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setBLOB", PARAM_TYPE_INT_ORABLOB); 591 592 ORA_STATEMENT_CACHING_AVAILABLE = 593 METHOD_SET_STATEMENT_CACHE_SIZE != null && METHOD_SET_IMPLICIT_CACHING_ENABLED != null; 594 ORA_ROW_PREFETCH_AVAILABLE = METHOD_SET_ROW_PREFETCH != null; 595 ORA_CLOB_HANDLING_AVAILABLE = METHOD_SET_CLOB != null; 596 ORA_BLOB_HANDLING_AVAILABLE = METHOD_SET_BLOB != null; 597 } 598 catch (ClassNotFoundException e) 599 { 600 } 602 try 604 { 605 JBOSS_CONN_CLASS = ClassHelper.getClass(JBOSS_CONN_NAME, false); 606 } 607 catch (ClassNotFoundException e) 608 { 609 } 611 } 612 613 } 614 | Popular Tags |