1 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 ; 30 31 import com.mchange.v2.c3p0.*; 32 import com.mchange.v2.cfg.MultiPropertiesConfig; 33 34 import java.io.ByteArrayInputStream ; 35 import java.io.ByteArrayOutputStream ; 36 import java.io.DataInputStream ; 37 import java.io.DataOutputStream ; 38 import java.io.IOException ; 39 import java.security.SecureRandom ; 40 import java.sql.Connection ; 41 import java.sql.SQLException ; 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 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 [] NOARGS = new Object [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 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 VMID_PROPKEY = "com.mchange.v2.c3p0.VMID"; 92 private final static String VMID_PFX; 93 94 static 95 { 96 String 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 static String connectionTesterClassName = null; 107 static ConnectionTester cachedTester = null; 108 109 private static String generateVmId() 110 { 111 DataOutputStream dos = null; 112 DataInputStream dis = null; 113 try 114 { 115 SecureRandom srand = new SecureRandom (); 116 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 117 dos = new DataOutputStream ( baos ); 118 try 119 { 120 dos.write( InetAddress.getLocalHost().getAddress() ); 121 } 122 catch (Exception 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 (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 sb = new StringBuffer (32); 141 byte[] vmid_bytes = baos.toByteArray(); 142 dis = new DataInputStream (new ByteArrayInputStream ( 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 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 try { if (dos != null) dos.close(); } 166 catch ( IOException 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 e ) 170 { logger.log(MLevel.WARNING, "Huh? Exception close()ing a byte-array bound IntputStream.", e); } 171 } 172 } 173 174 178 public static String allocateIdentityToken(Object o) 179 { 180 if (o == null) 181 return null; 182 else 183 { 184 String shortIdToken = Integer.toString( System.identityHashCode( o ), 16 ); 185 186 188 String out; 189 long count; 190 StringBuffer sb = new StringBuffer (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 o) 208 throws SQLException 209 { 210 if ( o == null ) 211 return NULL_AUTH; 212 213 String user = null; 214 String password = null; 215 216 String overrideDefaultUser = null; 217 String 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 propCl = pd.getPropertyType(); 227 String propName = pd.getName(); 228 if (propCl == String .class) 229 { 230 234 Method readMethod = pd.getReadMethod(); 235 if (readMethod != null) 236 { 237 Object propVal = readMethod.invoke( o, NOARGS ); 238 String value = (String ) 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 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 pCon, 266 boolean forceIgnoreUnresolvedTransactions, 267 boolean autoCommitOnClose, 268 boolean txnKnownResolved ) throws SQLException 269 { 270 if ( !forceIgnoreUnresolvedTransactions && !pCon.getAutoCommit() ) 271 { 272 if (! autoCommitOnClose && ! txnKnownResolved) 273 { 274 pCon.rollback(); 276 } 277 pCon.setAutoCommit( true ); } 279 } 280 281 public synchronized static ConnectionTester defaultConnectionTester() 282 { 283 String 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 e ) 294 { 295 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 target, String mname, Class [] argTypes) 308 { 309 try {return (target.getClass().getMethod( mname, argTypes ) != null); } 310 catch ( NoSuchMethodException e ) 311 { return false; } 312 catch (SecurityException 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 HASM_HEADER = "HexAsciiSerializedMap"; 324 325 public static String createUserOverridesAsString( Map userOverrides ) throws IOException 326 { 327 StringBuffer sb = new StringBuffer (); 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 userOverridesAsString ) throws IOException , ClassNotFoundException 336 { 337 if (userOverridesAsString != null) 338 { 339 String 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 368 382 | Popular Tags |