KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > c3p0 > impl > C3P0ImplUtils


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

22
23
24 package com.mchange.v2.c3p0.impl;
25
26 import java.beans.*;
27 import java.util.*;
28 import java.lang.reflect.*;
29 import java.net.InetAddress JavaDoc;
30
31 import com.mchange.v2.c3p0.*;
32 import com.mchange.v2.cfg.MultiPropertiesConfig;
33
34 import java.io.ByteArrayInputStream JavaDoc;
35 import java.io.ByteArrayOutputStream JavaDoc;
36 import java.io.DataInputStream JavaDoc;
37 import java.io.DataOutputStream JavaDoc;
38 import java.io.IOException JavaDoc;
39 import java.security.SecureRandom JavaDoc;
40 import java.sql.Connection JavaDoc;
41 import java.sql.SQLException JavaDoc;
42 import com.mchange.lang.ByteUtils;
43 import com.mchange.v2.encounter.EncounterCounter;
44 import com.mchange.v2.encounter.EqualityEncounterCounter;
45 import com.mchange.v2.lang.VersionUtils;
46 import com.mchange.v2.log.MLevel;
47 import com.mchange.v2.log.MLog;
48 import com.mchange.v2.log.MLogger;
49 import com.mchange.v2.ser.SerializableUtils;
50 import com.mchange.v2.sql.SqlUtils;
51
52 public final class C3P0ImplUtils
53 {
54     // turning this on would only test to generate long tokens
55
// on 64 bit machines, but since identityHashCode() is not
56
// GUARANTEED unique under 32-bit JVMs, even if in practice
57
// always is, we always test to be sure we're not reusing
58
// an identity token.
59
private final static boolean CONDITIONAL_LONG_TOKENS = false;
60
61     final static MLogger logger = MLog.getLogger( C3P0ImplUtils.class );
62
63     public final static DbAuth NULL_AUTH = new DbAuth(null,null);
64
65     public final static Object JavaDoc[] NOARGS = new Object JavaDoc[0];
66
67     private final static EncounterCounter ID_TOKEN_COUNTER;
68
69     static
70     {
71     if (CONDITIONAL_LONG_TOKENS)
72         {
73         boolean long_tokens;
74         Integer JavaDoc jnb = VersionUtils.jvmNumberOfBits();
75         if (jnb == null)
76             long_tokens = true;
77         else if (jnb.intValue() > 32)
78             long_tokens = true;
79         else
80             long_tokens = false;
81         
82         if (long_tokens)
83             ID_TOKEN_COUNTER = new EqualityEncounterCounter();
84         else
85             ID_TOKEN_COUNTER = null;
86         }
87     else
88         ID_TOKEN_COUNTER = new EqualityEncounterCounter();
89      }
90     
91     public static String JavaDoc VMID_PROPKEY = "com.mchange.v2.c3p0.VMID";
92     private final static String JavaDoc VMID_PFX;
93     
94     static
95     {
96         String JavaDoc vmid = MultiPropertiesConfig.readVmConfig().getProperty(VMID_PROPKEY);
97         if (vmid == null || (vmid = vmid.trim()).equals("") || vmid.equals("AUTO"))
98             VMID_PFX = generateVmId() + '|';
99         else if (vmid.equals("NONE"))
100             VMID_PFX = "";
101         else
102             VMID_PFX = vmid + "|";
103     }
104
105     //MT: protected by class' lock
106
static String JavaDoc connectionTesterClassName = null;
107     static ConnectionTester cachedTester = null;
108     
109     private static String JavaDoc generateVmId()
110     {
111         DataOutputStream JavaDoc dos = null;
112         DataInputStream JavaDoc dis = null;
113         try
114         {
115             SecureRandom JavaDoc srand = new SecureRandom JavaDoc();
116             ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
117             dos = new DataOutputStream JavaDoc( baos );
118             try
119             {
120                 dos.write( InetAddress.getLocalHost().getAddress() );
121             }
122             catch (Exception JavaDoc e)
123             {
124                 if (logger.isLoggable(MLevel.INFO))
125                     logger.log(MLevel.INFO, "Failed to get local InetAddress for VMID. This is unlikely to matter. At all. We'll add some extra randomness", e);
126                 dos.write( srand.nextInt() );
127             }
128             dos.writeLong(System.currentTimeMillis());
129             dos.write( srand.nextInt() );
130             
131             int remainder = baos.size() % 4; //if it wasn't a 4 byte inet address
132
if (remainder > 0)
133             {
134                 int pad = 4 - remainder;
135                 byte[] pad_bytes = new byte[pad];
136                 srand.nextBytes(pad_bytes);
137                 dos.write(pad_bytes);
138             }
139             
140             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(32);
141             byte[] vmid_bytes = baos.toByteArray();
142             dis = new DataInputStream JavaDoc(new ByteArrayInputStream JavaDoc( vmid_bytes ) );
143             for (int i = 0, num_ints = vmid_bytes.length / 4; i < num_ints; ++i)
144             {
145                 int signed = dis.readInt();
146                 long unsigned = ((long) signed) & 0x00000000FFFFFFFFL;
147                 sb.append(Long.toString(unsigned, Character.MAX_RADIX));
148             }
149             return sb.toString();
150         }
151         catch (IOException JavaDoc e)
152         {
153             if (logger.isLoggable(MLevel.WARNING))
154                 logger.log(MLevel.WARNING,
155                            "Bizarro! IOException while reading/writing from ByteArray-based streams? " +
156                            "We're skipping the VMID thing. It almost certainly doesn't matter, " +
157                            "but please report the error.",
158                            e);
159             return "";
160         }
161         finally
162         {
163             // this is like total overkill for byte-array based streams,
164
// but it's a good habit
165
try { if (dos != null) dos.close(); }
166             catch ( IOException JavaDoc e )
167             { logger.log(MLevel.WARNING, "Huh? Exception close()ing a byte-array bound OutputStream.", e); }
168             try { if (dis != null) dis.close(); }
169             catch ( IOException JavaDoc e )
170             { logger.log(MLevel.WARNING, "Huh? Exception close()ing a byte-array bound IntputStream.", e); }
171         }
172     }
173
174     // identityHashCode() is not a sufficient unique token, because they are
175
// not guaranteed unique, and in practice are occasionally not unique,
176
// particularly on 64-bit systems.
177

178     public static String JavaDoc allocateIdentityToken(Object JavaDoc o)
179     {
180     if (o == null)
181         return null;
182     else
183         {
184         String JavaDoc shortIdToken = Integer.toString( System.identityHashCode( o ), 16 );
185
186         //new Exception( "DEBUG_STACK_TRACE: " + o.getClass().getName() + " " + shortIdToken ).printStackTrace();
187

188         String JavaDoc out;
189         long count;
190         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(128);
191         sb.append(VMID_PFX);
192         if (ID_TOKEN_COUNTER != null && ((count = ID_TOKEN_COUNTER.encounter( shortIdToken )) > 0))
193             {
194             sb.append( shortIdToken );
195             sb.append('#');
196             sb.append( count );
197             }
198         else
199             sb.append(shortIdToken);
200
201         out = sb.toString().intern();
202
203         return out;
204         }
205     }
206
207     public static DbAuth findAuth(Object JavaDoc o)
208     throws SQLException JavaDoc
209     {
210     if ( o == null )
211         return NULL_AUTH;
212
213     String JavaDoc user = null;
214     String JavaDoc password = null;
215
216     String JavaDoc overrideDefaultUser = null;
217     String JavaDoc overrideDefaultPassword = null;
218
219     try
220         {
221         BeanInfo bi = Introspector.getBeanInfo( o.getClass() );
222         PropertyDescriptor[] pds = bi.getPropertyDescriptors();
223         for (int i = 0, len = pds.length; i < len; ++i)
224             {
225             PropertyDescriptor pd = pds[i];
226             Class JavaDoc propCl = pd.getPropertyType();
227             String JavaDoc propName = pd.getName();
228             if (propCl == String JavaDoc.class)
229                 {
230 // System.err.println( "---> " + propName );
231
// System.err.println( o.getClass() );
232
// System.err.println( pd.getReadMethod() );
233

234                 Method readMethod = pd.getReadMethod();
235                 if (readMethod != null)
236                     {
237                     Object JavaDoc propVal = readMethod.invoke( o, NOARGS );
238                     String JavaDoc value = (String JavaDoc) propVal;
239                     if ("user".equals(propName))
240                         user = value;
241                     else if ("password".equals(propName))
242                         password = value;
243                     else if ("overrideDefaultUser".equals(propName))
244                         overrideDefaultUser = value;
245                     else if ("overrideDefaultPassword".equals(propName))
246                         overrideDefaultPassword = value;
247                     }
248                 }
249             }
250         if (overrideDefaultUser != null)
251             return new DbAuth( overrideDefaultUser, overrideDefaultPassword );
252         else if (user != null)
253             return new DbAuth( user, password );
254         else
255             return NULL_AUTH;
256         }
257     catch (Exception JavaDoc e)
258         {
259         if (Debug.DEBUG && logger.isLoggable( MLevel.FINE ))
260             logger.log( MLevel.FINE, "An exception occurred while trying to extract the default authentification info from a bean.", e );
261         throw SqlUtils.toSQLException(e);
262         }
263     }
264
265     static void resetTxnState( Connection JavaDoc pCon,
266                    boolean forceIgnoreUnresolvedTransactions,
267                    boolean autoCommitOnClose,
268                    boolean txnKnownResolved ) throws SQLException JavaDoc
269     {
270     if ( !forceIgnoreUnresolvedTransactions && !pCon.getAutoCommit() )
271         {
272         if (! autoCommitOnClose && ! txnKnownResolved)
273             {
274             //System.err.println("Rolling back potentially unresolved txn...");
275
pCon.rollback();
276             }
277         pCon.setAutoCommit( true ); //implies commit if not already rolled back.
278
}
279     }
280
281     public synchronized static ConnectionTester defaultConnectionTester()
282     {
283     String JavaDoc dfltCxnTesterClassName = PoolConfig.defaultConnectionTesterClassName();
284     if ( connectionTesterClassName != null && connectionTesterClassName.equals(dfltCxnTesterClassName) )
285         return cachedTester;
286     else
287         {
288         try
289             {
290             cachedTester = (ConnectionTester) Class.forName( dfltCxnTesterClassName ).newInstance();
291             connectionTesterClassName = cachedTester.getClass().getName();
292             }
293         catch ( Exception JavaDoc e )
294             {
295             //e.printStackTrace();
296
if ( logger.isLoggable( MLevel.WARNING ) )
297                 logger.log(MLevel.WARNING,
298                        "Could not load ConnectionTester " + dfltCxnTesterClassName + ", using built in default.",
299                        e);
300             cachedTester = C3P0Defaults.connectionTester();
301             connectionTesterClassName = cachedTester.getClass().getName();
302             }
303         return cachedTester;
304         }
305     }
306
307     public static boolean supportsMethod(Object JavaDoc target, String JavaDoc mname, Class JavaDoc[] argTypes)
308     {
309     try {return (target.getClass().getMethod( mname, argTypes ) != null); }
310     catch ( NoSuchMethodException JavaDoc e )
311         { return false; }
312     catch (SecurityException JavaDoc e)
313         {
314         if ( logger.isLoggable( MLevel.FINE ) )
315             logger.log(MLevel.FINE,
316                    "We were denied access in a check of whether " + target + " supports method " + mname +
317                    ". Prob means external clients have no access, returning false.",
318                    e);
319         return false;
320         }
321     }
322
323     private final static String JavaDoc HASM_HEADER = "HexAsciiSerializedMap";
324
325     public static String JavaDoc createUserOverridesAsString( Map userOverrides ) throws IOException JavaDoc
326     {
327     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
328     sb.append(HASM_HEADER);
329     sb.append('[');
330     sb.append( ByteUtils.toHexAscii( SerializableUtils.toByteArray( userOverrides ) ) );
331     sb.append(']');
332     return sb.toString();
333     }
334
335     public static Map parseUserOverridesAsString( String JavaDoc userOverridesAsString ) throws IOException JavaDoc, ClassNotFoundException JavaDoc
336     {
337     if (userOverridesAsString != null)
338         {
339         String JavaDoc hexAscii = userOverridesAsString.substring(HASM_HEADER.length() + 1, userOverridesAsString.length() - 1);
340         byte[] serBytes = ByteUtils.fromHexAscii( hexAscii );
341         return Collections.unmodifiableMap( (Map) SerializableUtils.fromByteArray( serBytes ) );
342         }
343     else
344         return Collections.EMPTY_MAP;
345     }
346
347     private C3P0ImplUtils()
348     {}
349 }
350
351
352
353 // Class methodClass = readMethod.getDeclaringClass();
354
// Package methodPkg = methodClass.getPackage();
355
// System.err.println( methodPkg.getName() + '\t' + C3P0ImplUtils.class.getPackage().getName() );
356
// if (! methodPkg.getName().equals(
357
// C3P0ImplUtils.class.getPackage().getName() ) )
358
// {
359
// System.err.println("public check: " + (methodClass.getModifiers() & Modifier.PUBLIC));
360
// if ((methodClass.getModifiers() & Modifier.PUBLIC) == 0)
361
// {
362
// System.err.println("SKIPPED -- Can't Access!");
363
// continue;
364
// }
365
// }
366
// System.err.println( o );
367

368     /*
369     private final static ThreadLocal threadLocalConnectionCustomizer = new ThreadLocal();
370
371     // used so that C3P0PooledConnectionPool can pass a ConnectionCustomizer
372     // to WrapperConnectionPoolDataSource without altering that class' public API
373     public static void setThreadConnectionCustomizer(ConnectionCustomizer cc)
374     { threadLocalConnectionCustomizer.set( cc ); }
375
376     public static ConnectionCustomizer getThreadConnectionCustomizer()
377     { return threadLocalConnectionCustomizer.get(); }
378
379     public static void unsetThreadConnectionCustomizer()
380     { setThreadConnectionCustomizer( null ); }
381     */

382
Popular Tags