[766] | 1 | /* |
---|
| 2 | Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. |
---|
| 3 | |
---|
| 4 | |
---|
| 5 | The MySQL Connector/J is licensed under the terms of the GPLv2 |
---|
| 6 | <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors. |
---|
| 7 | There are special exceptions to the terms and conditions of the GPLv2 as it is applied to |
---|
| 8 | this software, see the FLOSS License Exception |
---|
| 9 | <http://www.mysql.com/about/legal/licensing/foss-exception.html>. |
---|
| 10 | |
---|
| 11 | This program is free software; you can redistribute it and/or modify it under the terms |
---|
| 12 | of the GNU General Public License as published by the Free Software Foundation; version 2 |
---|
| 13 | of the License. |
---|
| 14 | |
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
---|
| 16 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
| 17 | See the GNU General Public License for more details. |
---|
| 18 | |
---|
| 19 | You should have received a copy of the GNU General Public License along with this |
---|
| 20 | program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth |
---|
| 21 | Floor, Boston, MA 02110-1301 USA |
---|
| 22 | |
---|
| 23 | |
---|
| 24 | |
---|
| 25 | */ |
---|
| 26 | package com.mysql.jdbc; |
---|
| 27 | |
---|
| 28 | import java.io.ObjectInputStream; |
---|
| 29 | import java.io.PrintWriter; |
---|
| 30 | import java.io.StringWriter; |
---|
| 31 | import java.lang.reflect.Constructor; |
---|
| 32 | import java.lang.reflect.InvocationTargetException; |
---|
| 33 | import java.lang.reflect.Method; |
---|
| 34 | import java.math.BigDecimal; |
---|
| 35 | import java.math.BigInteger; |
---|
| 36 | import java.sql.SQLException; |
---|
| 37 | import java.util.HashMap; |
---|
| 38 | import java.util.Iterator; |
---|
| 39 | import java.util.LinkedList; |
---|
| 40 | import java.util.List; |
---|
| 41 | import java.util.Map; |
---|
| 42 | import java.util.Properties; |
---|
| 43 | import java.util.TimeZone; |
---|
| 44 | |
---|
| 45 | /** |
---|
| 46 | * Various utility methods for the driver. |
---|
| 47 | * |
---|
| 48 | * @author Mark Matthews |
---|
| 49 | */ |
---|
| 50 | public class Util { |
---|
| 51 | protected final static Method systemNanoTimeMethod; |
---|
| 52 | |
---|
| 53 | static { |
---|
| 54 | Method aMethod; |
---|
| 55 | |
---|
| 56 | try { |
---|
| 57 | aMethod = System.class.getMethod("nanoTime", (Class[])null); |
---|
| 58 | } catch (SecurityException e) { |
---|
| 59 | aMethod = null; |
---|
| 60 | } catch (NoSuchMethodException e) { |
---|
| 61 | aMethod = null; |
---|
| 62 | } |
---|
| 63 | |
---|
| 64 | systemNanoTimeMethod = aMethod; |
---|
| 65 | } |
---|
| 66 | |
---|
| 67 | public static boolean nanoTimeAvailable() { |
---|
| 68 | return systemNanoTimeMethod != null; |
---|
| 69 | } |
---|
| 70 | |
---|
| 71 | private static Method CAST_METHOD; |
---|
| 72 | |
---|
| 73 | // cache this ourselves, as the method call is statically-synchronized in |
---|
| 74 | // all but JDK6! |
---|
| 75 | |
---|
| 76 | private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault(); |
---|
| 77 | |
---|
| 78 | static final TimeZone getDefaultTimeZone() { |
---|
| 79 | return (TimeZone) DEFAULT_TIMEZONE.clone(); |
---|
| 80 | } |
---|
| 81 | |
---|
| 82 | class RandStructcture { |
---|
| 83 | long maxValue; |
---|
| 84 | |
---|
| 85 | double maxValueDbl; |
---|
| 86 | |
---|
| 87 | long seed1; |
---|
| 88 | |
---|
| 89 | long seed2; |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | private static Util enclosingInstance = new Util(); |
---|
| 93 | |
---|
| 94 | private static boolean isJdbc4 = false; |
---|
| 95 | |
---|
| 96 | private static boolean isColdFusion = false; |
---|
| 97 | |
---|
| 98 | static { |
---|
| 99 | try { |
---|
| 100 | CAST_METHOD = Class.class.getMethod("cast", |
---|
| 101 | new Class[] { Object.class }); |
---|
| 102 | } catch (Throwable t) { |
---|
| 103 | // ignore - not available in this VM |
---|
| 104 | } |
---|
| 105 | |
---|
| 106 | try { |
---|
| 107 | Class.forName("java.sql.NClob"); |
---|
| 108 | isJdbc4 = true; |
---|
| 109 | } catch (Throwable t) { |
---|
| 110 | isJdbc4 = false; |
---|
| 111 | } |
---|
| 112 | |
---|
| 113 | // |
---|
| 114 | // Detect the ColdFusion MX environment |
---|
| 115 | // |
---|
| 116 | // Unfortunately, no easy-to-discern classes are available |
---|
| 117 | // to our classloader to check... |
---|
| 118 | // |
---|
| 119 | |
---|
| 120 | String loadedFrom = stackTraceToString(new Throwable()); |
---|
| 121 | |
---|
| 122 | if (loadedFrom != null) { |
---|
| 123 | isColdFusion = loadedFrom.indexOf("coldfusion") != -1; |
---|
| 124 | } else { |
---|
| 125 | isColdFusion = false; |
---|
| 126 | } |
---|
| 127 | } |
---|
| 128 | |
---|
| 129 | // ~ Methods |
---|
| 130 | // ---------------------------------------------------------------- |
---|
| 131 | |
---|
| 132 | public static boolean isJdbc4() { |
---|
| 133 | return isJdbc4; |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | public static boolean isColdFusion() { |
---|
| 137 | return isColdFusion; |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | // Right from Monty's code |
---|
| 141 | public static String newCrypt(String password, String seed) { |
---|
| 142 | byte b; |
---|
| 143 | double d; |
---|
| 144 | |
---|
| 145 | if ((password == null) || (password.length() == 0)) { |
---|
| 146 | return password; |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | long[] pw = newHash(seed); |
---|
| 150 | long[] msg = newHash(password); |
---|
| 151 | long max = 0x3fffffffL; |
---|
| 152 | long seed1 = (pw[0] ^ msg[0]) % max; |
---|
| 153 | long seed2 = (pw[1] ^ msg[1]) % max; |
---|
| 154 | char[] chars = new char[seed.length()]; |
---|
| 155 | |
---|
| 156 | for (int i = 0; i < seed.length(); i++) { |
---|
| 157 | seed1 = ((seed1 * 3) + seed2) % max; |
---|
| 158 | seed2 = (seed1 + seed2 + 33) % max; |
---|
| 159 | d = (double) seed1 / (double) max; |
---|
| 160 | b = (byte) java.lang.Math.floor((d * 31) + 64); |
---|
| 161 | chars[i] = (char) b; |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | seed1 = ((seed1 * 3) + seed2) % max; |
---|
| 165 | seed2 = (seed1 + seed2 + 33) % max; |
---|
| 166 | d = (double) seed1 / (double) max; |
---|
| 167 | b = (byte) java.lang.Math.floor(d * 31); |
---|
| 168 | |
---|
| 169 | for (int i = 0; i < seed.length(); i++) { |
---|
| 170 | chars[i] ^= (char) b; |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | return new String(chars); |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | static long[] newHash(String password) { |
---|
| 177 | long nr = 1345345333L; |
---|
| 178 | long add = 7; |
---|
| 179 | long nr2 = 0x12345671L; |
---|
| 180 | long tmp; |
---|
| 181 | |
---|
| 182 | for (int i = 0; i < password.length(); ++i) { |
---|
| 183 | if ((password.charAt(i) == ' ') || (password.charAt(i) == '\t')) { |
---|
| 184 | continue; // skip spaces |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | tmp = (0xff & password.charAt(i)); |
---|
| 188 | nr ^= ((((nr & 63) + add) * tmp) + (nr << 8)); |
---|
| 189 | nr2 += ((nr2 << 8) ^ nr); |
---|
| 190 | add += tmp; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | long[] result = new long[2]; |
---|
| 194 | result[0] = nr & 0x7fffffffL; |
---|
| 195 | result[1] = nr2 & 0x7fffffffL; |
---|
| 196 | |
---|
| 197 | return result; |
---|
| 198 | } |
---|
| 199 | |
---|
| 200 | public static String oldCrypt(String password, String seed) { |
---|
| 201 | long hp; |
---|
| 202 | long hm; |
---|
| 203 | long s1; |
---|
| 204 | long s2; |
---|
| 205 | long max = 0x01FFFFFF; |
---|
| 206 | double d; |
---|
| 207 | byte b; |
---|
| 208 | |
---|
| 209 | if ((password == null) || (password.length() == 0)) { |
---|
| 210 | return password; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | hp = oldHash(seed); |
---|
| 214 | hm = oldHash(password); |
---|
| 215 | |
---|
| 216 | long nr = hp ^ hm; |
---|
| 217 | nr %= max; |
---|
| 218 | s1 = nr; |
---|
| 219 | s2 = nr / 2; |
---|
| 220 | |
---|
| 221 | char[] chars = new char[seed.length()]; |
---|
| 222 | |
---|
| 223 | for (int i = 0; i < seed.length(); i++) { |
---|
| 224 | s1 = ((s1 * 3) + s2) % max; |
---|
| 225 | s2 = (s1 + s2 + 33) % max; |
---|
| 226 | d = (double) s1 / max; |
---|
| 227 | b = (byte) java.lang.Math.floor((d * 31) + 64); |
---|
| 228 | chars[i] = (char) b; |
---|
| 229 | } |
---|
| 230 | |
---|
| 231 | return new String(chars); |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | static long oldHash(String password) { |
---|
| 235 | long nr = 1345345333; |
---|
| 236 | long nr2 = 7; |
---|
| 237 | long tmp; |
---|
| 238 | |
---|
| 239 | for (int i = 0; i < password.length(); i++) { |
---|
| 240 | if ((password.charAt(i) == ' ') || (password.charAt(i) == '\t')) { |
---|
| 241 | continue; |
---|
| 242 | } |
---|
| 243 | |
---|
| 244 | tmp = password.charAt(i); |
---|
| 245 | nr ^= ((((nr & 63) + nr2) * tmp) + (nr << 8)); |
---|
| 246 | nr2 += tmp; |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | return nr & ((1L << 31) - 1L); |
---|
| 250 | } |
---|
| 251 | |
---|
| 252 | private static RandStructcture randomInit(long seed1, long seed2) { |
---|
| 253 | RandStructcture randStruct = enclosingInstance.new RandStructcture(); |
---|
| 254 | |
---|
| 255 | randStruct.maxValue = 0x3FFFFFFFL; |
---|
| 256 | randStruct.maxValueDbl = randStruct.maxValue; |
---|
| 257 | randStruct.seed1 = seed1 % randStruct.maxValue; |
---|
| 258 | randStruct.seed2 = seed2 % randStruct.maxValue; |
---|
| 259 | |
---|
| 260 | return randStruct; |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | /** |
---|
| 264 | * Given a ResultSet and an index into the columns of that ResultSet, read |
---|
| 265 | * binary data from the column which represents a serialized object, and |
---|
| 266 | * re-create the object. |
---|
| 267 | * |
---|
| 268 | * @param resultSet |
---|
| 269 | * the ResultSet to use. |
---|
| 270 | * @param index |
---|
| 271 | * an index into the ResultSet. |
---|
| 272 | * @return the object if it can be de-serialized |
---|
| 273 | * @throws Exception |
---|
| 274 | * if an error occurs |
---|
| 275 | */ |
---|
| 276 | public static Object readObject(java.sql.ResultSet resultSet, int index) |
---|
| 277 | throws Exception { |
---|
| 278 | ObjectInputStream objIn = new ObjectInputStream(resultSet |
---|
| 279 | .getBinaryStream(index)); |
---|
| 280 | Object obj = objIn.readObject(); |
---|
| 281 | objIn.close(); |
---|
| 282 | |
---|
| 283 | return obj; |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | private static double rnd(RandStructcture randStruct) { |
---|
| 287 | randStruct.seed1 = ((randStruct.seed1 * 3) + randStruct.seed2) |
---|
| 288 | % randStruct.maxValue; |
---|
| 289 | randStruct.seed2 = (randStruct.seed1 + randStruct.seed2 + 33) |
---|
| 290 | % randStruct.maxValue; |
---|
| 291 | |
---|
| 292 | return ((randStruct.seed1) / randStruct.maxValueDbl); |
---|
| 293 | } |
---|
| 294 | |
---|
| 295 | /** |
---|
| 296 | * DOCUMENT ME! |
---|
| 297 | * |
---|
| 298 | * @param message |
---|
| 299 | * DOCUMENT ME! |
---|
| 300 | * @param password |
---|
| 301 | * DOCUMENT ME! |
---|
| 302 | * |
---|
| 303 | * @return DOCUMENT ME! |
---|
| 304 | */ |
---|
| 305 | public static String scramble(String message, String password) { |
---|
| 306 | long[] hashPass; |
---|
| 307 | long[] hashMessage; |
---|
| 308 | byte[] to = new byte[8]; |
---|
| 309 | String val = ""; //$NON-NLS-1$ |
---|
| 310 | |
---|
| 311 | message = message.substring(0, 8); |
---|
| 312 | |
---|
| 313 | if ((password != null) && (password.length() > 0)) { |
---|
| 314 | hashPass = newHash(password); |
---|
| 315 | hashMessage = newHash(message); |
---|
| 316 | |
---|
| 317 | RandStructcture randStruct = randomInit(hashPass[0] |
---|
| 318 | ^ hashMessage[0], hashPass[1] ^ hashMessage[1]); |
---|
| 319 | |
---|
| 320 | int msgPos = 0; |
---|
| 321 | int msgLength = message.length(); |
---|
| 322 | int toPos = 0; |
---|
| 323 | |
---|
| 324 | while (msgPos++ < msgLength) { |
---|
| 325 | to[toPos++] = (byte) (Math.floor(rnd(randStruct) * 31) + 64); |
---|
| 326 | } |
---|
| 327 | |
---|
| 328 | /* Make it harder to break */ |
---|
| 329 | byte extra = (byte) (Math.floor(rnd(randStruct) * 31)); |
---|
| 330 | |
---|
| 331 | for (int i = 0; i < to.length; i++) { |
---|
| 332 | to[i] ^= extra; |
---|
| 333 | } |
---|
| 334 | |
---|
| 335 | val = StringUtils.toString(to); |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | return val; |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | // ~ Inner Classes |
---|
| 342 | // ---------------------------------------------------------- |
---|
| 343 | |
---|
| 344 | /** |
---|
| 345 | * Converts a nested exception into a nicer message |
---|
| 346 | * |
---|
| 347 | * @param ex |
---|
| 348 | * the exception to expand into a message. |
---|
| 349 | * |
---|
| 350 | * @return a message containing the exception, the message (if any), and a |
---|
| 351 | * stacktrace. |
---|
| 352 | */ |
---|
| 353 | public static String stackTraceToString(Throwable ex) { |
---|
| 354 | StringBuffer traceBuf = new StringBuffer(); |
---|
| 355 | traceBuf.append(Messages.getString("Util.1")); //$NON-NLS-1$ |
---|
| 356 | |
---|
| 357 | if (ex != null) { |
---|
| 358 | traceBuf.append(ex.getClass().getName()); |
---|
| 359 | |
---|
| 360 | String message = ex.getMessage(); |
---|
| 361 | |
---|
| 362 | if (message != null) { |
---|
| 363 | traceBuf.append(Messages.getString("Util.2")); //$NON-NLS-1$ |
---|
| 364 | traceBuf.append(message); |
---|
| 365 | } |
---|
| 366 | |
---|
| 367 | StringWriter out = new StringWriter(); |
---|
| 368 | |
---|
| 369 | PrintWriter printOut = new PrintWriter(out); |
---|
| 370 | |
---|
| 371 | ex.printStackTrace(printOut); |
---|
| 372 | |
---|
| 373 | traceBuf.append(Messages.getString("Util.3")); //$NON-NLS-1$ |
---|
| 374 | traceBuf.append(out.toString()); |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | traceBuf.append(Messages.getString("Util.4")); //$NON-NLS-1$ |
---|
| 378 | |
---|
| 379 | return traceBuf.toString(); |
---|
| 380 | } |
---|
| 381 | |
---|
| 382 | public static Object getInstance(String className, Class<?>[] argTypes, |
---|
| 383 | Object[] args, ExceptionInterceptor exceptionInterceptor) throws SQLException { |
---|
| 384 | |
---|
| 385 | try { |
---|
| 386 | return handleNewInstance(Class.forName(className).getConstructor( |
---|
| 387 | argTypes), args, exceptionInterceptor); |
---|
| 388 | } catch (SecurityException e) { |
---|
| 389 | throw SQLError.createSQLException( |
---|
| 390 | "Can't instantiate required class", |
---|
| 391 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 392 | } catch (NoSuchMethodException e) { |
---|
| 393 | throw SQLError.createSQLException( |
---|
| 394 | "Can't instantiate required class", |
---|
| 395 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 396 | } catch (ClassNotFoundException e) { |
---|
| 397 | throw SQLError.createSQLException( |
---|
| 398 | "Can't instantiate required class", |
---|
| 399 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 400 | } |
---|
| 401 | } |
---|
| 402 | |
---|
| 403 | /** |
---|
| 404 | * Handles constructing new instance with the given constructor and wrapping |
---|
| 405 | * (or not, as required) the exceptions that could possibly be generated |
---|
| 406 | */ |
---|
| 407 | public static final Object handleNewInstance(Constructor<?> ctor, Object[] args, ExceptionInterceptor exceptionInterceptor) |
---|
| 408 | throws SQLException { |
---|
| 409 | try { |
---|
| 410 | |
---|
| 411 | return ctor.newInstance(args); |
---|
| 412 | } catch (IllegalArgumentException e) { |
---|
| 413 | throw SQLError.createSQLException( |
---|
| 414 | "Can't instantiate required class", |
---|
| 415 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 416 | } catch (InstantiationException e) { |
---|
| 417 | throw SQLError.createSQLException( |
---|
| 418 | "Can't instantiate required class", |
---|
| 419 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 420 | } catch (IllegalAccessException e) { |
---|
| 421 | throw SQLError.createSQLException( |
---|
| 422 | "Can't instantiate required class", |
---|
| 423 | SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); |
---|
| 424 | } catch (InvocationTargetException e) { |
---|
| 425 | Throwable target = e.getTargetException(); |
---|
| 426 | |
---|
| 427 | if (target instanceof SQLException) { |
---|
| 428 | throw (SQLException) target; |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | if (target instanceof ExceptionInInitializerError) { |
---|
| 432 | target = ((ExceptionInInitializerError) target).getException(); |
---|
| 433 | } |
---|
| 434 | |
---|
| 435 | throw SQLError.createSQLException(target.toString(), |
---|
| 436 | SQLError.SQL_STATE_GENERAL_ERROR, exceptionInterceptor); |
---|
| 437 | } |
---|
| 438 | } |
---|
| 439 | |
---|
| 440 | /** |
---|
| 441 | * Does a network interface exist locally with the given hostname? |
---|
| 442 | * |
---|
| 443 | * @param hostname |
---|
| 444 | * the hostname (or IP address in string form) to check |
---|
| 445 | * @return true if it exists, false if no, or unable to determine due to VM |
---|
| 446 | * version support of java.net.NetworkInterface |
---|
| 447 | */ |
---|
| 448 | public static boolean interfaceExists(String hostname) { |
---|
| 449 | try { |
---|
| 450 | Class<?> networkInterfaceClass = Class |
---|
| 451 | .forName("java.net.NetworkInterface"); |
---|
| 452 | return networkInterfaceClass.getMethod("getByName", (Class[])null).invoke( |
---|
| 453 | networkInterfaceClass, new Object[] { hostname }) != null; |
---|
| 454 | } catch (Throwable t) { |
---|
| 455 | return false; |
---|
| 456 | } |
---|
| 457 | } |
---|
| 458 | |
---|
| 459 | /** |
---|
| 460 | * Reflexive access on JDK-1.5's Class.cast() method so we don't have to |
---|
| 461 | * move that out into separate classes built for JDBC-4.0. |
---|
| 462 | * |
---|
| 463 | * @param invokeOn |
---|
| 464 | * @param toCast |
---|
| 465 | * @return |
---|
| 466 | */ |
---|
| 467 | public static Object cast(Object invokeOn, Object toCast) { |
---|
| 468 | if (CAST_METHOD != null) { |
---|
| 469 | try { |
---|
| 470 | return CAST_METHOD.invoke(invokeOn, new Object[] { toCast }); |
---|
| 471 | } catch (Throwable t) { |
---|
| 472 | return null; |
---|
| 473 | } |
---|
| 474 | } |
---|
| 475 | |
---|
| 476 | return null; |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | public static long getCurrentTimeNanosOrMillis() { |
---|
| 480 | if (systemNanoTimeMethod != null) { |
---|
| 481 | try { |
---|
| 482 | return ((Long) systemNanoTimeMethod.invoke(null, (Object[])null)) |
---|
| 483 | .longValue(); |
---|
| 484 | } catch (IllegalArgumentException e) { |
---|
| 485 | // ignore - fall through to currentTimeMillis() |
---|
| 486 | } catch (IllegalAccessException e) { |
---|
| 487 | // ignore - fall through to currentTimeMillis() |
---|
| 488 | } catch (InvocationTargetException e) { |
---|
| 489 | // ignore - fall through to currentTimeMillis() |
---|
| 490 | } |
---|
| 491 | } |
---|
| 492 | |
---|
| 493 | return System.currentTimeMillis(); |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
---|
| 497 | public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs) |
---|
| 498 | throws SQLException { |
---|
| 499 | while (rs.next()) { |
---|
| 500 | mappedValues.put(rs.getObject(1), rs.getObject(2)); |
---|
| 501 | } |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
---|
| 505 | public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs, int key, int value) |
---|
| 506 | throws SQLException { |
---|
| 507 | while (rs.next()) { |
---|
| 508 | mappedValues.put(rs.getObject(key), rs.getObject(value)); |
---|
| 509 | } |
---|
| 510 | } |
---|
| 511 | |
---|
| 512 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
---|
| 513 | public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs, String key, String value) |
---|
| 514 | throws SQLException { |
---|
| 515 | while (rs.next()) { |
---|
| 516 | mappedValues.put(rs.getObject(key), rs.getObject(value)); |
---|
| 517 | } |
---|
| 518 | } |
---|
| 519 | |
---|
| 520 | public static Map<Object, Object> calculateDifferences(Map<?,?> map1, Map<?,?> map2) { |
---|
| 521 | Map<Object, Object> diffMap = new HashMap<Object, Object>(); |
---|
| 522 | |
---|
| 523 | for (Map.Entry<?,?> entry : map1.entrySet()) { |
---|
| 524 | Object key = entry.getKey(); |
---|
| 525 | |
---|
| 526 | Number value1 = null; |
---|
| 527 | Number value2 = null; |
---|
| 528 | |
---|
| 529 | if (entry.getValue() instanceof Number) { |
---|
| 530 | |
---|
| 531 | value1 = (Number) entry.getValue(); |
---|
| 532 | value2 = (Number) map2.get(key); |
---|
| 533 | } else { |
---|
| 534 | try { |
---|
| 535 | value1 = new Double(entry.getValue().toString()); |
---|
| 536 | value2 = new Double(map2.get(key).toString()); |
---|
| 537 | } catch (NumberFormatException nfe) { |
---|
| 538 | continue; |
---|
| 539 | } |
---|
| 540 | } |
---|
| 541 | |
---|
| 542 | if (value1.equals(value2)) { |
---|
| 543 | continue; |
---|
| 544 | } |
---|
| 545 | |
---|
| 546 | if (value1 instanceof Byte) { |
---|
| 547 | diffMap.put(key, Byte.valueOf( |
---|
| 548 | (byte) (((Byte) value2).byteValue() - ((Byte) value1) |
---|
| 549 | .byteValue()))); |
---|
| 550 | } else if (value1 instanceof Short) { |
---|
| 551 | diffMap.put(key, Short.valueOf((short) (((Short) value2) |
---|
| 552 | .shortValue() - ((Short) value1).shortValue()))); |
---|
| 553 | } else if (value1 instanceof Integer) { |
---|
| 554 | diffMap.put(key, Integer.valueOf( |
---|
| 555 | (((Integer) value2).intValue() - ((Integer) value1) |
---|
| 556 | .intValue()))); |
---|
| 557 | } else if (value1 instanceof Long) { |
---|
| 558 | diffMap.put(key, Long.valueOf( |
---|
| 559 | (((Long) value2).longValue() - ((Long) value1) |
---|
| 560 | .longValue()))); |
---|
| 561 | } else if (value1 instanceof Float) { |
---|
| 562 | diffMap.put(key, Float.valueOf(((Float) value2).floatValue() |
---|
| 563 | - ((Float) value1).floatValue())); |
---|
| 564 | } else if (value1 instanceof Double) { |
---|
| 565 | diffMap.put(key, Double.valueOf( |
---|
| 566 | (((Double) value2).shortValue() - ((Double) value1) |
---|
| 567 | .shortValue()))); |
---|
| 568 | } else if (value1 instanceof BigDecimal) { |
---|
| 569 | diffMap.put(key, ((BigDecimal) value2) |
---|
| 570 | .subtract((BigDecimal) value1)); |
---|
| 571 | } else if (value1 instanceof BigInteger) { |
---|
| 572 | diffMap.put(key, ((BigInteger) value2) |
---|
| 573 | .subtract((BigInteger) value1)); |
---|
| 574 | } |
---|
| 575 | } |
---|
| 576 | |
---|
| 577 | return diffMap; |
---|
| 578 | } |
---|
| 579 | |
---|
| 580 | public static List<Extension> loadExtensions(Connection conn, |
---|
| 581 | Properties props, String extensionClassNames, |
---|
| 582 | String errorMessageKey, ExceptionInterceptor exceptionInterceptor) throws SQLException { |
---|
| 583 | List<Extension> extensionList = new LinkedList<Extension>(); |
---|
| 584 | |
---|
| 585 | List<String> interceptorsToCreate = StringUtils.split(extensionClassNames, ",", |
---|
| 586 | true); |
---|
| 587 | |
---|
| 588 | Iterator<String> iter = interceptorsToCreate.iterator(); |
---|
| 589 | |
---|
| 590 | String className = null; |
---|
| 591 | |
---|
| 592 | try { |
---|
| 593 | while (iter.hasNext()) { |
---|
| 594 | className = iter.next().toString(); |
---|
| 595 | Extension extensionInstance = (Extension) Class.forName( |
---|
| 596 | className).newInstance(); |
---|
| 597 | extensionInstance.init(conn, props); |
---|
| 598 | |
---|
| 599 | extensionList.add(extensionInstance); |
---|
| 600 | } |
---|
| 601 | } catch (Throwable t) { |
---|
| 602 | SQLException sqlEx = SQLError.createSQLException(Messages |
---|
| 603 | .getString(errorMessageKey, new Object[] { className }), exceptionInterceptor); |
---|
| 604 | sqlEx.initCause(t); |
---|
| 605 | |
---|
| 606 | throw sqlEx; |
---|
| 607 | } |
---|
| 608 | |
---|
| 609 | return extensionList; |
---|
| 610 | } |
---|
| 611 | |
---|
| 612 | } |
---|