001: package org.apache.ojb.broker.platforms;
002:
003: /* Copyright 2003-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
019: import org.apache.ojb.broker.metadata.ConnectionPoolDescriptor;
020: import org.apache.ojb.broker.util.ClassHelper;
021: import org.apache.ojb.broker.util.logging.Logger;
022: import org.apache.ojb.broker.util.logging.LoggerFactory;
023:
024: import java.io.ByteArrayInputStream;
025: import java.lang.reflect.Method;
026: import java.sql.Connection;
027: import java.sql.PreparedStatement;
028: import java.sql.SQLException;
029: import java.sql.Statement;
030: import java.sql.Types;
031: import java.util.Collections;
032: import java.util.Map;
033: import java.util.WeakHashMap;
034:
035: /**
036: * This class is a concrete implementation of <code>Platform</code>. Provides
037: * an implementation that works around some issues with Oracle in general and
038: * Oracle 9i's Thin driver in particular.
039: *
040: * NOTE: When using BEA WebLogic and BLOB/CLOB datatypes, the physical connection will be
041: * used causing WebLogic to mark it as "infected" and discard it when
042: * the logicical connection is closed. You can change this behavior by setting the
043: * RemoveInfectedConnectionsEnabled attribute on a connection pool.
044: * see <a href="http://e-docs.bea.com/wls/docs81/jdbc/thirdparty.html#1043646">WebLogic docs</a>.
045: *
046: * Optimization: Oracle Batching (not standard JDBC batching)
047: * see http://technet.oracle.com/products/oracle9i/daily/jun07.html
048: *
049: * Optimization: Oracle Prefetching
050: * see http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/RowPrefetchSample/Readme.html
051: *
052: * Optimization: Oracle Statement Caching
053: * see http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/jdbc30/StmtCacheSample/Readme.html
054: *
055: * TODO: Optimization: use ROWNUM to minimize the effects of not having server side cursors
056: * see http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:127412348064
057: *
058: * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
059: * @author <a href="mailto:mkalen@apache.org">Martin Kalén</a>
060: * @author Contributions from: Erik Forkalsrud, Danilo Tommasina, Thierry Hanot, Don Lyon
061: * @version CVS $Id: PlatformOracle9iImpl.java,v 1.13.2.9 2005/04/26 03:41:36 mkalen Exp $
062: * @see Platform
063: * @see PlatformDefaultImpl
064: * @see PlatformOracleImpl
065: */
066: public class PlatformOracle9iImpl extends PlatformOracleImpl {
067: private Logger logger = LoggerFactory
068: .getLogger(PlatformOracle9iImpl.class);
069:
070: /**
071: * Number of cached statements per connection,
072: * when using implicit caching with OracleConnections.
073: * Set in {@link #initializeJdbcConnection}.
074: * @see <a href="http://www.apache.org/~mkalen/ojb/broker-tests.html">Profiling page</a>
075: * for a discussion re sizing
076: */
077: protected static final int STATEMENT_CACHE_SIZE = 10;
078: /**
079: * Number of rows pre-fetched by the JDBC-driver for each executed query,
080: * when using Oracle row pre-fetching with OracleConnections.
081: * Set in {@link #initializeJdbcConnection}.
082: * <p>
083: * <em>Note</em>: this setting can be overridden by specifying a
084: * connection-pool attribute with name="jdbc.defaultRowPrefetch".
085: * Oracle JDBC-driver default value=10.
086: */
087: protected static final int ROW_PREFETCH_SIZE = 20;
088:
089: // From Oracle9i JDBC Developer's Guide and Reference:
090: // "Batch values between 5 and 30 tend to be the most effective."
091: protected static final int STATEMENTS_PER_BATCH = 20;
092: protected static Map m_batchStatementsInProgress = Collections
093: .synchronizedMap(new WeakHashMap(STATEMENTS_PER_BATCH));
094:
095: protected static final Class[] PARAM_TYPE_EMPTY = {};
096: protected static final Class[] PARAM_TYPE_INTEGER = { Integer.TYPE };
097: protected static final Class[] PARAM_TYPE_BOOLEAN = { Boolean.TYPE };
098: protected static final Class[] PARAM_TYPE_STRING = { String.class };
099:
100: protected static final Object[] PARAM_EMPTY = new Object[] {};
101: protected static final Object[] PARAM_STATEMENT_CACHE_SIZE = new Object[] { new Integer(
102: STATEMENT_CACHE_SIZE) };
103: protected static final Object[] PARAM_ROW_PREFETCH_SIZE = new Object[] { new Integer(
104: ROW_PREFETCH_SIZE) };
105: protected static final Object[] PARAM_STATEMENT_BATCH_SIZE = new Object[] { new Integer(
106: STATEMENTS_PER_BATCH) };
107: protected static final Object[] PARAM_BOOLEAN_TRUE = new Object[] { Boolean.TRUE };
108:
109: protected static final String JBOSS_CONN_NAME = "org.jboss.resource.adapter.jdbc.WrappedConnection";
110: protected static Class JBOSS_CONN_CLASS = null;
111:
112: protected static Class ORA_CONN_CLASS;
113: protected static Class ORA_PS_CLASS;
114: protected static Class ORA_CLOB_CLASS;
115: protected static Class ORA_BLOB_CLASS;
116: protected static Class[] PARAM_TYPE_INT_ORACLOB;
117: protected static Class[] PARAM_TYPE_INT_ORABLOB;
118: protected static Method METHOD_SET_STATEMENT_CACHE_SIZE;
119: protected static Method METHOD_SET_IMPLICIT_CACHING_ENABLED;
120: protected static Method METHOD_SET_ROW_PREFETCH;
121: protected static Method METHOD_SET_BLOB = null;
122: protected static Method METHOD_SET_CLOB = null;
123: protected static boolean ORA_STATEMENT_CACHING_AVAILABLE;
124: protected static boolean ORA_ROW_PREFETCH_AVAILABLE;
125: protected static boolean ORA_CLOB_HANDLING_AVAILABLE;
126: protected static boolean ORA_BLOB_HANDLING_AVAILABLE;
127:
128: /** Method names used by {@link #unwrapConnection}. */
129: protected static final String UNWRAP_CONN_METHOD_NAMES[] = {
130: "unwrapCompletely" /* Oracle 10g */,
131: "getInnermostDelegate" /* Commons DBCP */,
132: "getUnderlyingConnection" /* JBoss */,
133: "getVendorConnection" /* BEA WebLogic */, "getJDBC" /* P6Spy */
134: };
135: /**
136: * Method parameter signature used by {@link #unwrapConnection} for corresponding
137: * {@link #UNWRAP_CONN_METHOD_NAMES}-index.
138: * If signature is not {@link #PARAM_TYPE_EMPTY}, the actual connection object
139: * will be passed at runtime. (NB: Requires special handling of param type in constructor.)
140: */
141: protected static final Class[][] UNWRAP_CONN_PARAM_TYPES = {
142: null /* Index 0 reserved for Oracle 10g - initialized in constructor */,
143: PARAM_TYPE_EMPTY /* Commons DBCP */,
144: PARAM_TYPE_EMPTY /* JBoss */,
145: PARAM_TYPE_EMPTY /* BEA WebLogic */, PARAM_TYPE_EMPTY /* P6Spy */
146: };
147: /** Method names used by {@link #unwrapStatement}. */
148: protected static final String UNWRAP_PS_METHOD_NAMES[] = {
149: "getInnermostDelegate" /* Commons DBCP */,
150: "getUnderlyingStatement" /* JBoss */, "getJDBC" /* P6Spy */
151: };
152: /**
153: * Method parameter signature used by {@link #unwrapStatement} for corresponding
154: * {@link #UNWRAP_PS_METHOD_NAMES}-index.
155: * If signature is not {@link #PARAM_TYPE_EMPTY}, the actual Statement object
156: * will be passed at runtime. (NB: Requires special handling of param type in constructor.)
157: */
158: protected static final Class[][] UNWRAP_PS_PARAM_TYPES = {
159: PARAM_TYPE_EMPTY /* Commons DBCP */,
160: PARAM_TYPE_EMPTY /* JBoss */, PARAM_TYPE_EMPTY /* P6Spy */
161: };
162:
163: /**
164: * Default constructor.
165: */
166: public PlatformOracle9iImpl() {
167: super ();
168: }
169:
170: /**
171: * Enables Oracle statement caching and row prefetching if supported by the JDBC-driver.
172: * @param jcd the OJB <code>JdbcConnectionDescriptor</code> (metadata) for the connection to be initialized
173: * @param conn the <code>Connection</code>-object (physical) to be initialized
174: * @see PlatformDefaultImpl#initializeJdbcConnection
175: * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/jdbc30/StmtCacheSample/Readme.html">
176: * Oracle TechNet Statement Caching Sample</a>
177: * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/RowPrefetchSample/Readme.html">
178: * Oracle TechNet Row Pre-fetch Sample<a>
179: */
180: public void initializeJdbcConnection(
181: final JdbcConnectionDescriptor jcd, final Connection conn)
182: throws PlatformException {
183: // Do all the generic initialization in PlatformDefaultImpl first
184: super .initializeJdbcConnection(jcd, conn);
185:
186: // Check for managed environments known to reject Oracle extension at this level
187: // (saves us from trying to unwrap just to catch exceptions next)
188: final Class connClass = conn.getClass();
189: if (JBOSS_CONN_CLASS != null
190: && JBOSS_CONN_CLASS.isAssignableFrom(connClass)) {
191: if (logger.isDebugEnabled()) {
192: logger
193: .debug("JBoss detected, Oracle Connection tuning left to J2EE container.");
194: }
195: return;
196: }
197:
198: // Check if this is a wrapped connection and if so unwrap it
199: final Connection oraConn = unwrapConnection(conn);
200: if (oraConn == null) {
201: return;
202: }
203:
204: // At this point we know that we have an OracleConnection instance and can thus
205: // try to invoke methods via reflection (if available)
206: if (ORA_STATEMENT_CACHING_AVAILABLE) {
207: try {
208: // Set number of cached statements and enable implicit caching
209: METHOD_SET_STATEMENT_CACHE_SIZE.invoke(oraConn,
210: PARAM_STATEMENT_CACHE_SIZE);
211: METHOD_SET_IMPLICIT_CACHING_ENABLED.invoke(oraConn,
212: PARAM_BOOLEAN_TRUE);
213: } catch (Exception e) {
214: if (logger.isDebugEnabled()) {
215: logger
216: .debug("PlatformOracle9iImpl could not enable Oracle statement caching."
217: + " Original/unwrapped connection classes="
218: + connClass.getName()
219: + "/"
220: + oraConn.getClass().getName());
221: }
222: }
223: }
224:
225: /*
226: mkalen: Note from the Oracle documentation:
227: Do not mix the JDBC 2.0 fetch size API and the Oracle row prefetching API
228: in your application. You can use one or the other, but not both.
229: */
230: final ConnectionPoolDescriptor cpd = jcd
231: .getConnectionPoolDescriptor();
232: final int cpdFetchSizeHint = cpd.getFetchSize();
233: if (cpdFetchSizeHint == 0 && ORA_ROW_PREFETCH_AVAILABLE) {
234: try {
235: final String prefetchFromJcd;
236: prefetchFromJcd = cpd.getJdbcProperties().getProperty(
237: "defaultRowPrefetch");
238: if (prefetchFromJcd == null) {
239: METHOD_SET_ROW_PREFETCH.invoke(oraConn,
240: PARAM_ROW_PREFETCH_SIZE);
241: }
242: // Else, number of prefetched rows were set via Properties on Connection
243: } catch (Exception e) {
244: if (logger.isDebugEnabled()) {
245: logger
246: .debug("PlatformOracle9iImpl could not enable Oracle row pre-fetching."
247: + "Original/unwrapped connection classes="
248: + connClass.getName()
249: + "/"
250: + oraConn.getClass().getName());
251: }
252: }
253: }
254: }
255:
256: /**
257: * Performs platform-specific operations on each statement.
258: * @param stmt the statement just created
259: */
260: public void afterStatementCreate(Statement stmt) {
261: // mkalen: do NOT call super#afterStatementCreate since escape processing for SQL92
262: // syntax is enabled by default for Oracle9i and higher, and explicit calls
263: // to setEscapeProcessing for PreparedStatements will make Oracle 10g JDBC-
264: // driver throw exceptions (and is functionally useless).
265: }
266:
267: /**
268: * Try Oracle update batching and call setExecuteBatch or revert to
269: * JDBC update batching. See 12-2 Update Batching in the Oracle9i
270: * JDBC Developer's Guide and Reference.
271: * @param stmt the prepared statement to be used for batching
272: * @throws PlatformException upon JDBC failure
273: */
274: public void beforeBatch(PreparedStatement stmt)
275: throws PlatformException {
276: // Check for Oracle batching support
277: final Method methodSetExecuteBatch;
278: final Method methodSendBatch;
279: methodSetExecuteBatch = ClassHelper.getMethod(stmt,
280: "setExecuteBatch", PARAM_TYPE_INTEGER);
281: methodSendBatch = ClassHelper
282: .getMethod(stmt, "sendBatch", null);
283:
284: final boolean statementBatchingSupported = methodSetExecuteBatch != null
285: && methodSendBatch != null;
286: if (statementBatchingSupported) {
287: try {
288: // Set number of statements per batch
289: methodSetExecuteBatch.invoke(stmt,
290: PARAM_STATEMENT_BATCH_SIZE);
291: m_batchStatementsInProgress.put(stmt, methodSendBatch);
292: } catch (Exception e) {
293: throw new PlatformException(e.getLocalizedMessage(), e);
294: }
295: } else {
296: super .beforeBatch(stmt);
297: }
298: }
299:
300: /**
301: * Try Oracle update batching and call executeUpdate or revert to
302: * JDBC update batching.
303: * @param stmt the statement beeing added to the batch
304: * @throws PlatformException upon JDBC failure
305: */
306: public void addBatch(PreparedStatement stmt)
307: throws PlatformException {
308: // Check for Oracle batching support
309: final boolean statementBatchingSupported = m_batchStatementsInProgress
310: .containsKey(stmt);
311: if (statementBatchingSupported) {
312: try {
313: stmt.executeUpdate();
314: } catch (SQLException e) {
315: throw new PlatformException(e.getLocalizedMessage(), e);
316: }
317: } else {
318: super .addBatch(stmt);
319: }
320: }
321:
322: /**
323: * Try Oracle update batching and call sendBatch or revert to
324: * JDBC update batching.
325: * @param stmt the batched prepared statement about to be executed
326: * @return always <code>null</code> if Oracle update batching is used,
327: * since it is impossible to dissolve total row count into distinct
328: * statement counts. If JDBC update batching is used, an int array is
329: * returned containing number of updated rows for each batched statement.
330: * @throws PlatformException upon JDBC failure
331: */
332: public int[] executeBatch(PreparedStatement stmt)
333: throws PlatformException {
334: // Check for Oracle batching support
335: final Method methodSendBatch = (Method) m_batchStatementsInProgress
336: .remove(stmt);
337: final boolean statementBatchingSupported = methodSendBatch != null;
338:
339: int[] retval = null;
340: if (statementBatchingSupported) {
341: try {
342: // sendBatch() returns total row count as an Integer
343: methodSendBatch.invoke(stmt, null);
344: } catch (Exception e) {
345: throw new PlatformException(e.getLocalizedMessage(), e);
346: }
347: } else {
348: retval = super .executeBatch(stmt);
349: }
350: return retval;
351: }
352:
353: /** @see Platform#setObjectForStatement */
354: public void setObjectForStatement(PreparedStatement ps, int index,
355: Object value, int sqlType) throws SQLException {
356: // Check for Oracle JDBC-driver LOB-support
357: final Statement oraStmt;
358: final Connection oraConn;
359: final boolean oraLargeLobSupportAvailable;
360: if (sqlType == Types.CLOB || sqlType == Types.BLOB) {
361: oraStmt = unwrapStatement(ps);
362: oraConn = unwrapConnection(ps.getConnection());
363: oraLargeLobSupportAvailable = oraStmt != null
364: && oraConn != null
365: && (sqlType == Types.CLOB ? ORA_CLOB_HANDLING_AVAILABLE
366: : ORA_BLOB_HANDLING_AVAILABLE);
367: } else {
368: oraStmt = null;
369: oraConn = null;
370: oraLargeLobSupportAvailable = false;
371: }
372:
373: // Type-specific Oracle conversions
374: if (((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY))
375: && (value instanceof byte[])) {
376: byte buf[] = (byte[]) value;
377: ByteArrayInputStream inputStream = new ByteArrayInputStream(
378: buf);
379: super .changePreparedStatementResultSetType(ps);
380: ps.setBinaryStream(index, inputStream, buf.length);
381: } else if (value instanceof Double) {
382: // workaround for the bug in Oracle thin driver
383: ps.setDouble(index, ((Double) value).doubleValue());
384: } else if (sqlType == Types.BIGINT && value instanceof Integer) {
385: // workaround: Oracle thin driver problem when expecting long
386: ps.setLong(index, ((Integer) value).intValue());
387: } else if (sqlType == Types.INTEGER && value instanceof Long) {
388: ps.setLong(index, ((Long) value).longValue());
389: } else if (sqlType == Types.CLOB && oraLargeLobSupportAvailable
390: && value instanceof String) {
391: // TODO: If using Oracle update batching with the thin driver, throw exception on 4k limit
392: try {
393: Object clob = Oracle9iLobHandler.createCLOBFromString(
394: oraConn, (String) value);
395: METHOD_SET_CLOB.invoke(oraStmt, new Object[] {
396: new Integer(index), clob });
397: } catch (Exception e) {
398: throw new SQLException(e.getLocalizedMessage());
399: }
400: } else if (sqlType == Types.BLOB && oraLargeLobSupportAvailable
401: && value instanceof byte[]) {
402: // TODO: If using Oracle update batching with the thin driver, throw exception on 2k limit
403: try {
404: Object blob = Oracle9iLobHandler
405: .createBLOBFromByteArray(oraConn,
406: (byte[]) value);
407: METHOD_SET_BLOB.invoke(oraStmt, new Object[] {
408: new Integer(index), blob });
409: } catch (Exception e) {
410: throw new SQLException(e.getLocalizedMessage());
411: }
412: } else {
413: // Fall-through to superclass
414: super .setObjectForStatement(ps, index, value, sqlType);
415: }
416: }
417:
418: /**
419: * Get join syntax type for this RDBMS.
420: *
421: * @return SQL92_NOPAREN_JOIN_SYNTAX
422: */
423: public byte getJoinSyntaxType() {
424: return SQL92_NOPAREN_JOIN_SYNTAX;
425: }
426:
427: /**
428: * Return an OracleConnection after trying to unwrap from known Connection wrappers.
429: * @param conn the connection to unwrap (if needed)
430: * @return OracleConnection or null if not able to unwrap
431: */
432: protected Connection unwrapConnection(Connection conn) {
433: final Object unwrapped;
434: unwrapped = genericUnwrap(ORA_CONN_CLASS, conn,
435: UNWRAP_CONN_METHOD_NAMES, UNWRAP_CONN_PARAM_TYPES);
436: if (unwrapped == null) {
437: // mkalen: only log this as debug since it will be logged for every connection
438: // (ie only useful during development).
439: if (logger.isDebugEnabled()) {
440: logger.debug("PlatformOracle9iImpl could not unwrap "
441: + conn.getClass().getName()
442: + ", Oracle-extensions disabled.");
443: }
444: }
445: return (Connection) unwrapped;
446: }
447:
448: /**
449: * Return an OraclePreparedStatement after trying to unwrap from known Statement wrappers.
450: * @param ps the PreparedStatement to unwrap (if needed)
451: * @return OraclePreparedStatement or null if not able to unwrap
452: */
453: protected Statement unwrapStatement(Statement ps) {
454: final Object unwrapped;
455: unwrapped = genericUnwrap(ORA_PS_CLASS, ps,
456: UNWRAP_PS_METHOD_NAMES, UNWRAP_PS_PARAM_TYPES);
457: if (unwrapped == null) {
458: // mkalen: only log this as debug since it will be logged for every connection
459: // (ie only useful during development).
460: if (logger.isDebugEnabled()) {
461: logger.debug("PlatformOracle9iImpl could not unwrap "
462: + ps.getClass().getName()
463: + ", large CLOB/BLOB support disabled.");
464: }
465: }
466: return (Statement) unwrapped;
467: }
468:
469: protected Object genericUnwrap(Class classToMatch, Object toUnwrap,
470: String[] methodNameCandidates,
471: Class[][] methodTypeCandidates) {
472: if (classToMatch == null) {
473: return null;
474: }
475:
476: Object unwrapped;
477: final Class psClass = toUnwrap.getClass();
478: if (classToMatch.isAssignableFrom(psClass)) {
479: return toUnwrap;
480: }
481: try {
482: String methodName;
483: Class[] paramTypes;
484: Object[] args;
485: for (int i = 0; i < methodNameCandidates.length; i++) {
486: methodName = methodNameCandidates[i];
487: paramTypes = methodTypeCandidates[i];
488: final Method method = ClassHelper.getMethod(toUnwrap,
489: methodName, paramTypes);
490: if (method != null) {
491: args = paramTypes == PARAM_TYPE_EMPTY ? PARAM_EMPTY
492: : new Object[] { toUnwrap };
493: unwrapped = method.invoke(toUnwrap, args);
494: if (unwrapped != null) {
495: if (classToMatch.isAssignableFrom(unwrapped
496: .getClass())) {
497: return unwrapped;
498: }
499: // When using eg both DBCP and P6Spy we have to recursively unwrap
500: return genericUnwrap(classToMatch, unwrapped,
501: methodNameCandidates,
502: methodTypeCandidates);
503: }
504: }
505: }
506: } catch (Exception e) {
507: // ignore
508: if (logger.isDebugEnabled()) {
509: logger.debug("genericUnwrap failed", e);
510: }
511: }
512: return null;
513: }
514:
515: /**
516: * Initializes static variables needed for Oracle-extensions and large BLOB/CLOB support.
517: */
518: protected void initOracleReflectedVars() {
519: super .initOracleReflectedVars();
520: try {
521: /*
522: Check for Oracle-specific classes, OracleConnection-specific
523: statement caching/row pre-fetch methods and Oracle BLOB/CLOB access methods.
524: We can do this in constructor in spite of possible mixing of instance being
525: able vs unable passed at runtime (since withouth these classes and methods
526: it's impossible to enable ORA-extensions at all even if instances are capable).
527: */
528: ORA_CONN_CLASS = ClassHelper.getClass(
529: "oracle.jdbc.OracleConnection", false);
530: ORA_PS_CLASS = ClassHelper.getClass(
531: "oracle.jdbc.OraclePreparedStatement", false);
532: ORA_CLOB_CLASS = ClassHelper.getClass("oracle.sql.CLOB",
533: false);
534: ORA_BLOB_CLASS = ClassHelper.getClass("oracle.sql.BLOB",
535: false);
536: PARAM_TYPE_INT_ORACLOB = new Class[] { Integer.TYPE,
537: ORA_CLOB_CLASS };
538: PARAM_TYPE_INT_ORABLOB = new Class[] { Integer.TYPE,
539: ORA_BLOB_CLASS };
540:
541: // Index 0 reserved for Oracle 10g
542: UNWRAP_CONN_PARAM_TYPES[0] = new Class[] { ORA_CONN_CLASS };
543:
544: METHOD_SET_STATEMENT_CACHE_SIZE = ClassHelper.getMethod(
545: ORA_CONN_CLASS, "setStatementCacheSize",
546: PARAM_TYPE_INTEGER);
547: METHOD_SET_IMPLICIT_CACHING_ENABLED = ClassHelper
548: .getMethod(ORA_CONN_CLASS,
549: "setImplicitCachingEnabled",
550: PARAM_TYPE_BOOLEAN);
551: METHOD_SET_ROW_PREFETCH = ClassHelper.getMethod(
552: ORA_CONN_CLASS, "setDefaultRowPrefetch",
553: PARAM_TYPE_INTEGER);
554: METHOD_SET_CLOB = ClassHelper.getMethod(ORA_PS_CLASS,
555: "setCLOB", PARAM_TYPE_INT_ORACLOB);
556: METHOD_SET_BLOB = ClassHelper.getMethod(ORA_PS_CLASS,
557: "setBLOB", PARAM_TYPE_INT_ORABLOB);
558:
559: ORA_STATEMENT_CACHING_AVAILABLE = METHOD_SET_STATEMENT_CACHE_SIZE != null
560: && METHOD_SET_IMPLICIT_CACHING_ENABLED != null;
561: ORA_ROW_PREFETCH_AVAILABLE = METHOD_SET_ROW_PREFETCH != null;
562: ORA_CLOB_HANDLING_AVAILABLE = METHOD_SET_CLOB != null;
563: ORA_BLOB_HANDLING_AVAILABLE = METHOD_SET_BLOB != null;
564: } catch (ClassNotFoundException e) {
565: // ignore (we tried...)
566: }
567: // Isolated checks for other connection classes (OK when not found)
568: try {
569: JBOSS_CONN_CLASS = ClassHelper.getClass(JBOSS_CONN_NAME,
570: false);
571: } catch (ClassNotFoundException e) {
572: // ignore (no problem)
573: }
574: }
575:
576: }
|