1 /* 2 * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.sql; 27 28 import java.io.IOException; 29 import java.io.InvalidObjectException; 30 import java.io.ObjectInputStream; 31 import java.io.ObjectOutputStream; 32 import java.util.Arrays; 33 34 /** 35 * The subclass of {@link SQLException} thrown when an error 36 * occurs during a batch update operation. In addition to the 37 * information provided by {@link SQLException}, a 38 * {@code BatchUpdateException} provides the update 39 * counts for all commands that were executed successfully during the 40 * batch update, that is, all commands that were executed before the error 41 * occurred. The order of elements in an array of update counts 42 * corresponds to the order in which commands were added to the batch. 43 * <P> 44 * After a command in a batch update fails to execute properly 45 * and a {@code BatchUpdateException} is thrown, the driver 46 * may or may not continue to process the remaining commands in 47 * the batch. If the driver continues processing after a failure, 48 * the array returned by the method 49 * {@code BatchUpdateException.getUpdateCounts} will have 50 * an element for every command in the batch rather than only 51 * elements for the commands that executed successfully before 52 * the error. In the case where the driver continues processing 53 * commands, the array element for any command 54 * that failed is {@code Statement.EXECUTE_FAILED}. 55 * <P> 56 * A JDBC driver implementation should use 57 * the constructor {@code BatchUpdateException(String reason, String SQLState, 58 * int vendorCode, long []updateCounts,Throwable cause) } instead of 59 * constructors that take {@code int[]} for the update counts to avoid the 60 * possibility of overflow. 61 * <p> 62 * If {@code Statement.executeLargeBatch} method is invoked it is recommended that 63 * {@code getLargeUpdateCounts} be called instead of {@code getUpdateCounts} 64 * in order to avoid a possible overflow of the integer update count. 65 * @since 1.2 66 */ 67 68 public class BatchUpdateException extends SQLException { 69 70 /** 71 * Constructs a {@code BatchUpdateException} object initialized with a given 72 * {@code reason}, {@code SQLState}, {@code vendorCode} and 73 * {@code updateCounts}. 74 * The {@code cause} is not initialized, and may subsequently be 75 * initialized by a call to the 76 * {@link Throwable#initCause(java.lang.Throwable)} method. 77 * <p> 78 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 79 * overflow and because of this it is recommended that you use the constructor 80 * {@code BatchUpdateException(String reason, String SQLState, 81 * int vendorCode, long []updateCounts,Throwable cause) }. 82 * </p> 83 * @param reason a description of the error 84 * @param SQLState an XOPEN or SQL:2003 code identifying the exception 85 * @param vendorCode an exception code used by a particular 86 * database vendor 87 * @param updateCounts an array of {@code int}, with each element 88 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 89 * {@code Statement.EXECUTE_FAILED} for each SQL command in 90 * the batch for JDBC drivers that continue processing 91 * after a command failure; an update count or 92 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 93 * prior to the failure for JDBC drivers that stop processing after a command 94 * failure 95 * @since 1.2 96 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 97 * java.lang.Throwable) 98 */ BatchUpdateException( String reason, String SQLState, int vendorCode, int[] updateCounts )99 public BatchUpdateException( String reason, String SQLState, int vendorCode, 100 int[] updateCounts ) { 101 super(reason, SQLState, vendorCode); 102 this.updateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length); 103 this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts); 104 } 105 106 /** 107 * Constructs a {@code BatchUpdateException} object initialized with a given 108 * {@code reason}, {@code SQLState} and 109 * {@code updateCounts}. 110 * The {@code cause} is not initialized, and may subsequently be 111 * initialized by a call to the 112 * {@link Throwable#initCause(java.lang.Throwable)} method. The vendor code 113 * is initialized to 0. 114 * <p> 115 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 116 * overflow and because of this it is recommended that you use the constructor 117 * {@code BatchUpdateException(String reason, String SQLState, 118 * int vendorCode, long []updateCounts,Throwable cause) }. 119 * </p> 120 * @param reason a description of the exception 121 * @param SQLState an XOPEN or SQL:2003 code identifying the exception 122 * @param updateCounts an array of {@code int}, with each element 123 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 124 * {@code Statement.EXECUTE_FAILED} for each SQL command in 125 * the batch for JDBC drivers that continue processing 126 * after a command failure; an update count or 127 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 128 * prior to the failure for JDBC drivers that stop processing after a command 129 * failure 130 * @since 1.2 131 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 132 * java.lang.Throwable) 133 */ BatchUpdateException(String reason, String SQLState, int[] updateCounts)134 public BatchUpdateException(String reason, String SQLState, 135 int[] updateCounts) { 136 this(reason, SQLState, 0, updateCounts); 137 } 138 139 /** 140 * Constructs a {@code BatchUpdateException} object initialized with a given 141 * {@code reason} and {@code updateCounts}. 142 * The {@code cause} is not initialized, and may subsequently be 143 * initialized by a call to the 144 * {@link Throwable#initCause(java.lang.Throwable)} method. The 145 * {@code SQLState} is initialized to {@code null} 146 * and the vendor code is initialized to 0. 147 * <p> 148 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 149 * overflow and because of this it is recommended that you use the constructor 150 * {@code BatchUpdateException(String reason, String SQLState, 151 * int vendorCode, long []updateCounts,Throwable cause) }. 152 * </p> 153 * @param reason a description of the exception 154 * @param updateCounts an array of {@code int}, with each element 155 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 156 * {@code Statement.EXECUTE_FAILED} for each SQL command in 157 * the batch for JDBC drivers that continue processing 158 * after a command failure; an update count or 159 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 160 * prior to the failure for JDBC drivers that stop processing after a command 161 * failure 162 * @since 1.2 163 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 164 * java.lang.Throwable) 165 */ BatchUpdateException(String reason, int[] updateCounts)166 public BatchUpdateException(String reason, int[] updateCounts) { 167 this(reason, null, 0, updateCounts); 168 } 169 170 /** 171 * Constructs a {@code BatchUpdateException} object initialized with a given 172 * {@code updateCounts}. 173 * initialized by a call to the 174 * {@link Throwable#initCause(java.lang.Throwable)} method. The {@code reason} 175 * and {@code SQLState} are initialized to null and the vendor code 176 * is initialized to 0. 177 * <p> 178 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 179 * overflow and because of this it is recommended that you use the constructor 180 * {@code BatchUpdateException(String reason, String SQLState, 181 * int vendorCode, long []updateCounts,Throwable cause) }. 182 * </p> 183 * @param updateCounts an array of {@code int}, with each element 184 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 185 * {@code Statement.EXECUTE_FAILED} for each SQL command in 186 * the batch for JDBC drivers that continue processing 187 * after a command failure; an update count or 188 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 189 * prior to the failure for JDBC drivers that stop processing after a command 190 * failure 191 * @since 1.2 192 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 193 * java.lang.Throwable) 194 */ BatchUpdateException(int[] updateCounts)195 public BatchUpdateException(int[] updateCounts) { 196 this(null, null, 0, updateCounts); 197 } 198 199 /** 200 * Constructs a {@code BatchUpdateException} object. 201 * The {@code reason}, {@code SQLState} and {@code updateCounts} 202 * are initialized to {@code null} and the vendor code is initialized to 0. 203 * The {@code cause} is not initialized, and may subsequently be 204 * initialized by a call to the 205 * {@link Throwable#initCause(java.lang.Throwable)} method. 206 * 207 * @since 1.2 208 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 209 * java.lang.Throwable) 210 */ BatchUpdateException()211 public BatchUpdateException() { 212 this(null, null, 0, null); 213 } 214 215 /** 216 * Constructs a {@code BatchUpdateException} object initialized with 217 * a given {@code cause}. 218 * The {@code SQLState} and {@code updateCounts} 219 * are initialized 220 * to {@code null} and the vendor code is initialized to 0. 221 * The {@code reason} is initialized to {@code null} if 222 * {@code cause==null} or to {@code cause.toString()} if 223 * {@code cause!=null}. 224 * @param cause the underlying reason for this {@code SQLException} 225 * (which is saved for later retrieval by the {@code getCause()} method); 226 * may be null indicating the cause is non-existent or unknown. 227 * @since 1.6 228 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 229 * java.lang.Throwable) 230 */ BatchUpdateException(Throwable cause)231 public BatchUpdateException(Throwable cause) { 232 this((cause == null ? null : cause.toString()), null, 0, (int[])null, cause); 233 } 234 235 /** 236 * Constructs a {@code BatchUpdateException} object initialized with a 237 * given {@code cause} and {@code updateCounts}. 238 * The {@code SQLState} is initialized 239 * to {@code null} and the vendor code is initialized to 0. 240 * The {@code reason} is initialized to {@code null} if 241 * {@code cause==null} or to {@code cause.toString()} if 242 * {@code cause!=null}. 243 * <p> 244 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 245 * overflow and because of this it is recommended that you use the constructor 246 * {@code BatchUpdateException(String reason, String SQLState, 247 * int vendorCode, long []updateCounts,Throwable cause) }. 248 * </p> 249 * @param updateCounts an array of {@code int}, with each element 250 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 251 * {@code Statement.EXECUTE_FAILED} for each SQL command in 252 * the batch for JDBC drivers that continue processing 253 * after a command failure; an update count or 254 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 255 * prior to the failure for JDBC drivers that stop processing after a command 256 * failure 257 * @param cause the underlying reason for this {@code SQLException} 258 * (which is saved for later retrieval by the {@code getCause()} method); may be null indicating 259 * the cause is non-existent or unknown. 260 * @since 1.6 261 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 262 * java.lang.Throwable) 263 */ BatchUpdateException(int []updateCounts , Throwable cause)264 public BatchUpdateException(int []updateCounts , Throwable cause) { 265 this((cause == null ? null : cause.toString()), null, 0, updateCounts, cause); 266 } 267 268 /** 269 * Constructs a {@code BatchUpdateException} object initialized with 270 * a given {@code reason}, {@code cause} 271 * and {@code updateCounts}. The {@code SQLState} is initialized 272 * to {@code null} and the vendor code is initialized to 0. 273 * <p> 274 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 275 * overflow and because of this it is recommended that you use the constructor 276 * {@code BatchUpdateException(String reason, String SQLState, 277 * int vendorCode, long []updateCounts,Throwable cause) }. 278 * </p> 279 * @param reason a description of the exception 280 * @param updateCounts an array of {@code int}, with each element 281 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 282 * {@code Statement.EXECUTE_FAILED} for each SQL command in 283 * the batch for JDBC drivers that continue processing 284 * after a command failure; an update count or 285 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 286 * prior to the failure for JDBC drivers that stop processing after a command 287 * failure 288 * @param cause the underlying reason for this {@code SQLException} (which is saved for later retrieval by the {@code getCause()} method); 289 * may be null indicating 290 * the cause is non-existent or unknown. 291 * @since 1.6 292 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 293 * java.lang.Throwable) 294 */ BatchUpdateException(String reason, int []updateCounts, Throwable cause)295 public BatchUpdateException(String reason, int []updateCounts, Throwable cause) { 296 this(reason, null, 0, updateCounts, cause); 297 } 298 299 /** 300 * Constructs a {@code BatchUpdateException} object initialized with 301 * a given {@code reason}, {@code SQLState},{@code cause}, and 302 * {@code updateCounts}. The vendor code is initialized to 0. 303 * 304 * @param reason a description of the exception 305 * @param SQLState an XOPEN or SQL:2003 code identifying the exception 306 * @param updateCounts an array of {@code int}, with each element 307 * indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 308 * {@code Statement.EXECUTE_FAILED} for each SQL command in 309 * the batch for JDBC drivers that continue processing 310 * after a command failure; an update count or 311 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 312 * prior to the failure for JDBC drivers that stop processing after a command 313 * failure 314 * <p> 315 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 316 * overflow and because of this it is recommended that you use the constructor 317 * {@code BatchUpdateException(String reason, String SQLState, 318 * int vendorCode, long []updateCounts,Throwable cause) }. 319 * </p> 320 * @param cause the underlying reason for this {@code SQLException} 321 * (which is saved for later retrieval by the {@code getCause()} method); 322 * may be null indicating 323 * the cause is non-existent or unknown. 324 * @since 1.6 325 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 326 * java.lang.Throwable) 327 */ BatchUpdateException(String reason, String SQLState, int []updateCounts, Throwable cause)328 public BatchUpdateException(String reason, String SQLState, 329 int []updateCounts, Throwable cause) { 330 this(reason, SQLState, 0, updateCounts, cause); 331 } 332 333 /** 334 * Constructs a {@code BatchUpdateException} object initialized with 335 * a given {@code reason}, {@code SQLState}, {@code vendorCode} 336 * {@code cause} and {@code updateCounts}. 337 * 338 * @param reason a description of the error 339 * @param SQLState an XOPEN or SQL:2003 code identifying the exception 340 * @param vendorCode an exception code used by a particular 341 * database vendor 342 * @param updateCounts an array of {@code int}, with each element 343 *indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 344 * {@code Statement.EXECUTE_FAILED} for each SQL command in 345 * the batch for JDBC drivers that continue processing 346 * after a command failure; an update count or 347 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 348 * prior to the failure for JDBC drivers that stop processing after a command 349 * failure 350 * <p> 351 * <strong>Note:</strong> There is no validation of {@code updateCounts} for 352 * overflow and because of this it is recommended that you use the constructor 353 * {@code BatchUpdateException(String reason, String SQLState, 354 * int vendorCode, long []updateCounts,Throwable cause) }. 355 * </p> 356 * @param cause the underlying reason for this {@code SQLException} (which is saved for later retrieval by the {@code getCause()} method); 357 * may be null indicating 358 * the cause is non-existent or unknown. 359 * @since 1.6 360 * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[], 361 * java.lang.Throwable) 362 */ BatchUpdateException(String reason, String SQLState, int vendorCode, int []updateCounts,Throwable cause)363 public BatchUpdateException(String reason, String SQLState, int vendorCode, 364 int []updateCounts,Throwable cause) { 365 super(reason, SQLState, vendorCode, cause); 366 this.updateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length); 367 this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts); 368 } 369 370 /** 371 * Retrieves the update count for each update statement in the batch 372 * update that executed successfully before this exception occurred. 373 * A driver that implements batch updates may or may not continue to 374 * process the remaining commands in a batch when one of the commands 375 * fails to execute properly. If the driver continues processing commands, 376 * the array returned by this method will have as many elements as 377 * there are commands in the batch; otherwise, it will contain an 378 * update count for each command that executed successfully before 379 * the {@code BatchUpdateException} was thrown. 380 * <P> 381 * The possible return values for this method were modified for 382 * the Java 2 SDK, Standard Edition, version 1.3. This was done to 383 * accommodate the new option of continuing to process commands 384 * in a batch update after a {@code BatchUpdateException} object 385 * has been thrown. 386 * 387 * @return an array of {@code int} containing the update counts 388 * for the updates that were executed successfully before this error 389 * occurred. Or, if the driver continues to process commands after an 390 * error, one of the following for every command in the batch: 391 * <OL> 392 * <LI>an update count 393 * <LI>{@code Statement.SUCCESS_NO_INFO} to indicate that the command 394 * executed successfully but the number of rows affected is unknown 395 * <LI>{@code Statement.EXECUTE_FAILED} to indicate that the command 396 * failed to execute successfully 397 * </OL> 398 * @since 1.3 399 * @see #getLargeUpdateCounts() 400 */ getUpdateCounts()401 public int[] getUpdateCounts() { 402 return (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length); 403 } 404 405 /** 406 * Constructs a {@code BatchUpdateException} object initialized with 407 * a given {@code reason}, {@code SQLState}, {@code vendorCode} 408 * {@code cause} and {@code updateCounts}. 409 * <p> 410 * This constructor should be used when the returned update count may exceed 411 * {@link Integer#MAX_VALUE}. 412 * 413 * @param reason a description of the error 414 * @param SQLState an XOPEN or SQL:2003 code identifying the exception 415 * @param vendorCode an exception code used by a particular 416 * database vendor 417 * @param updateCounts an array of {@code long}, with each element 418 *indicating the update count, {@code Statement.SUCCESS_NO_INFO} or 419 * {@code Statement.EXECUTE_FAILED} for each SQL command in 420 * the batch for JDBC drivers that continue processing 421 * after a command failure; an update count or 422 * {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch 423 * prior to the failure for JDBC drivers that stop processing after a command 424 * failure 425 * @param cause the underlying reason for this {@code SQLException} 426 * (which is saved for later retrieval by the {@code getCause()} method); 427 * may be null indicating the cause is non-existent or unknown. 428 * @since 1.8 429 */ BatchUpdateException(String reason, String SQLState, int vendorCode, long []updateCounts,Throwable cause)430 public BatchUpdateException(String reason, String SQLState, int vendorCode, 431 long []updateCounts,Throwable cause) { 432 super(reason, SQLState, vendorCode, cause); 433 this.longUpdateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length); 434 this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts); 435 } 436 437 /** 438 * Retrieves the update count for each update statement in the batch 439 * update that executed successfully before this exception occurred. 440 * A driver that implements batch updates may or may not continue to 441 * process the remaining commands in a batch when one of the commands 442 * fails to execute properly. If the driver continues processing commands, 443 * the array returned by this method will have as many elements as 444 * there are commands in the batch; otherwise, it will contain an 445 * update count for each command that executed successfully before 446 * the {@code BatchUpdateException} was thrown. 447 * <p> 448 * This method should be used when {@code Statement.executeLargeBatch} is 449 * invoked and the returned update count may exceed {@link Integer#MAX_VALUE}. 450 * 451 * @return an array of {@code long} containing the update counts 452 * for the updates that were executed successfully before this error 453 * occurred. Or, if the driver continues to process commands after an 454 * error, one of the following for every command in the batch: 455 * <OL> 456 * <LI>an update count 457 * <LI>{@code Statement.SUCCESS_NO_INFO} to indicate that the command 458 * executed successfully but the number of rows affected is unknown 459 * <LI>{@code Statement.EXECUTE_FAILED} to indicate that the command 460 * failed to execute successfully 461 * </OL> 462 * @since 1.8 463 */ getLargeUpdateCounts()464 public long[] getLargeUpdateCounts() { 465 return (longUpdateCounts == null) ? null : 466 Arrays.copyOf(longUpdateCounts, longUpdateCounts.length); 467 } 468 469 /** 470 * The array that describes the outcome of a batch execution. 471 * @serial 472 * @since 1.2 473 */ 474 private int[] updateCounts; 475 476 /* 477 * Starting with Java SE 8, JDBC has added support for returning an update 478 * count > Integer.MAX_VALUE. Because of this the following changes were made 479 * to BatchUpdateException: 480 * <ul> 481 * <li>Add field longUpdateCounts</li> 482 * <li>Add Constructor which takes long[] for update counts</li> 483 * <li>Add getLargeUpdateCounts method</li> 484 * </ul> 485 * When any of the constructors are called, the int[] and long[] updateCount 486 * fields are populated by copying the one array to each other. 487 * 488 * As the JDBC driver passes in the updateCounts, there has always been the 489 * possibility for overflow and BatchUpdateException does not need to account 490 * for that, it simply copies the arrays. 491 * 492 * JDBC drivers should always use the constructor that specifies long[] and 493 * JDBC application developers should call getLargeUpdateCounts. 494 */ 495 496 /** 497 * The array that describes the outcome of a batch execution. 498 * @serial 499 * @since 1.8 500 */ 501 private long[] longUpdateCounts; 502 503 private static final long serialVersionUID = 5977529877145521757L; 504 505 /* 506 * Utility method to copy int[] updateCount to long[] updateCount 507 */ copyUpdateCount(int[] uc)508 private static long[] copyUpdateCount(int[] uc) { 509 long[] copy = new long[uc.length]; 510 for(int i= 0; i< uc.length; i++) { 511 copy[i] = uc[i]; 512 } 513 return copy; 514 } 515 516 /* 517 * Utility method to copy long[] updateCount to int[] updateCount. 518 * No checks for overflow will be done as it is expected a user will call 519 * getLargeUpdateCounts. 520 */ copyUpdateCount(long[] uc)521 private static int[] copyUpdateCount(long[] uc) { 522 int[] copy = new int[uc.length]; 523 for(int i= 0; i< uc.length; i++) { 524 copy[i] = (int) uc[i]; 525 } 526 return copy; 527 } 528 /** 529 * readObject is called to restore the state of the 530 * {@code BatchUpdateException} from a stream. 531 * @param s the {@code ObjectInputStream} to read from. 532 * 533 * @throws ClassNotFoundException if the class of a serialized object 534 * could not be found. 535 * @throws IOException if an I/O error occurs. 536 */ readObject(ObjectInputStream s)537 private void readObject(ObjectInputStream s) 538 throws IOException, ClassNotFoundException { 539 540 ObjectInputStream.GetField fields = s.readFields(); 541 int[] tmp = (int[])fields.get("updateCounts", null); 542 long[] tmp2 = (long[])fields.get("longUpdateCounts", null); 543 if(tmp != null && tmp2 != null && tmp.length != tmp2.length) 544 throw new InvalidObjectException("update counts are not the expected size"); 545 if (tmp != null) 546 updateCounts = tmp.clone(); 547 if (tmp2 != null) 548 longUpdateCounts = tmp2.clone(); 549 if(updateCounts == null && longUpdateCounts != null) 550 updateCounts = copyUpdateCount(longUpdateCounts); 551 if(longUpdateCounts == null && updateCounts != null) 552 longUpdateCounts = copyUpdateCount(updateCounts); 553 554 } 555 556 /** 557 * writeObject is called to save the state of the {@code BatchUpdateException} 558 * to a stream. 559 * @param s the {@code ObjectOutputStream} to write to. 560 * @throws IOException if an I/O error occurs. 561 */ writeObject(ObjectOutputStream s)562 private void writeObject(ObjectOutputStream s) 563 throws IOException { 564 565 ObjectOutputStream.PutField fields = s.putFields(); 566 fields.put("updateCounts", updateCounts); 567 fields.put("longUpdateCounts", longUpdateCounts); 568 s.writeFields(); 569 } 570 } 571