001: /*
002: * Distributed as part of c3p0 v.0.9.1.2
003: *
004: * Copyright (C) 2005 Machinery For Change, Inc.
005: *
006: * Author: Steve Waldman <swaldman@mchange.com>
007: *
008: * This library is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU Lesser General Public License version 2.1, as
010: * published by the Free Software Foundation.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public License
018: * along with this software; see the file LICENSE. If not, write to the
019: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: */
022:
023: package com.mchange.v2.c3p0.stmt;
024:
025: import java.sql.Connection;
026: import java.sql.ResultSet;
027: import java.lang.reflect.Method;
028: import com.mchange.v2.coalesce.*;
029:
030: import java.sql.Connection;
031: import java.sql.ResultSet;
032: import java.lang.reflect.Method;
033: import com.mchange.v2.coalesce.*;
034:
035: final class ValueIdentityStatementCacheKey extends StatementCacheKey {
036: //MT: not thread-safe, but protected within the find() method
037: // by StatementCacheKey.class lock
038: final static Coalescer keyCoalescer;
039:
040: //MT: modified only within StatementCacheKey.class-locked find() method
041: static ValueIdentityStatementCacheKey spare = new ValueIdentityStatementCacheKey();
042:
043: static {
044: CoalesceChecker cc = new CoalesceChecker() {
045: public boolean checkCoalesce(Object a, Object b) {
046: return StatementCacheKey.equals((StatementCacheKey) a,
047: b);
048: }
049:
050: public int coalesceHash(Object a) {
051: return ((ValueIdentityStatementCacheKey) a).cached_hash;
052: }
053: };
054:
055: //make weak, unsync'ed coalescer
056: keyCoalescer = CoalescerFactory
057: .createCoalescer(cc, true, false);
058: }
059:
060: static StatementCacheKey _find(Connection pcon,
061: Method stmtProducingMethod, Object[] args) {
062: ///BEGIN FIND LOGIC///
063: String stmtText = (String) args[0];
064: boolean is_callable = stmtProducingMethod.getName().equals(
065: "prepareCall");
066: int result_set_type;
067: int result_set_concurrency;
068:
069: int[] columnIndexes;
070: String[] columnNames;
071: Integer autogeneratedKeys;
072: Integer resultSetHoldability;
073:
074: if (args.length == 1) {
075: result_set_type = ResultSet.TYPE_FORWARD_ONLY;
076: result_set_concurrency = ResultSet.CONCUR_READ_ONLY;
077: columnIndexes = null;
078: columnNames = null;
079: autogeneratedKeys = null;
080: resultSetHoldability = null;
081: } else if (args.length == 2) {
082: Class[] argTypes = stmtProducingMethod.getParameterTypes();
083: if (argTypes[1].isArray()) {
084: Class baseType = argTypes[1].getComponentType();
085: if (baseType == int.class) //second arg is columnIndexes
086: {
087: result_set_type = ResultSet.TYPE_FORWARD_ONLY;
088: result_set_concurrency = ResultSet.CONCUR_READ_ONLY;
089: columnIndexes = (int[]) args[1];
090: columnNames = null;
091: autogeneratedKeys = null;
092: resultSetHoldability = null;
093: } else if (baseType == String.class) {
094: result_set_type = ResultSet.TYPE_FORWARD_ONLY;
095: result_set_concurrency = ResultSet.CONCUR_READ_ONLY;
096: columnIndexes = null;
097: columnNames = (String[]) args[1];
098: autogeneratedKeys = null;
099: resultSetHoldability = null;
100: } else
101: throw new IllegalArgumentException(
102: "c3p0 probably needs to be updated for some new "
103: + "JDBC spec! As of JDBC3, we expect two arg statement "
104: + "producing methods where the second arg is either "
105: + "an int, int array, or String array.");
106: } else //it should be a boxed int, autogeneratedKeys
107: {
108: result_set_type = ResultSet.TYPE_FORWARD_ONLY;
109: result_set_concurrency = ResultSet.CONCUR_READ_ONLY;
110: columnIndexes = null;
111: columnNames = null;
112: autogeneratedKeys = (Integer) args[1];
113: resultSetHoldability = null;
114: }
115: } else if (args.length == 3) {
116: result_set_type = ((Integer) args[1]).intValue();
117: result_set_concurrency = ((Integer) args[2]).intValue();
118: columnIndexes = null;
119: columnNames = null;
120: autogeneratedKeys = null;
121: resultSetHoldability = null;
122: } else if (args.length == 4) {
123: result_set_type = ((Integer) args[1]).intValue();
124: result_set_concurrency = ((Integer) args[2]).intValue();
125: columnIndexes = null;
126: columnNames = null;
127: autogeneratedKeys = null;
128: resultSetHoldability = (Integer) args[3];
129: } else
130: throw new IllegalArgumentException(
131: "Unexpected number of args to "
132: + stmtProducingMethod.getName());
133: ///END FIND LOGIC///
134:
135: // we keep around a "spare" and initialize it over and over again
136: // rather than allocating, because usually we'll find the statement we're
137: // looking for is already in the coalescer, and we can avoid the
138: // allocation altogether.
139: spare.init(pcon, stmtText, is_callable, result_set_type,
140: result_set_concurrency, columnIndexes, columnNames,
141: autogeneratedKeys, resultSetHoldability);
142:
143: StatementCacheKey out = (StatementCacheKey) keyCoalescer
144: .coalesce(spare);
145:
146: // System.err.println( "StatementCacheKey -> " + out );
147: // System.err.println( "Key is coalesced already? " + (out != spare) );
148: // System.err.println( "Keys in coalescer: " + keyCoalescer.countCoalesced() );
149:
150: if (out == spare)
151: spare = new ValueIdentityStatementCacheKey();
152: return out;
153: }
154:
155: void init(Connection physicalConnection, String stmtText,
156: boolean is_callable, int result_set_type,
157: int result_set_concurrency, int[] columnIndexes,
158: String[] columnNames, Integer autogeneratedKeys,
159: Integer resultSetHoldability) {
160: super .init(physicalConnection, stmtText, is_callable,
161: result_set_type, result_set_concurrency, columnIndexes,
162: columnNames, autogeneratedKeys, resultSetHoldability);
163: this .cached_hash = StatementCacheKey.hashCode(this );
164: }
165:
166: // extra instance varieable
167: int cached_hash;
168:
169: // Note that we DON'T override equals() or hashCode() here -- each instance let the coalescer guarantee a
170: // single instance exists that would equals() it (that is, itself), and we rely on Object's default equals() and
171: // hashCode methods do their thangs.
172: }
|