001 /* 002 * file StpException.java 003 * 004 * Licensed Materials - Property of IBM 005 * Restricted Materials of IBM 006 * 007 * com.ibm.rational.wvcm.stp.StpException 008 * 009 * (C) Copyright IBM Corporation 2006, 2010. All Rights Reserved. 010 * Note to U.S. Government Users Restricted Rights: Use, duplication or 011 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 012 */ 013 014 package com.ibm.rational.wvcm.stp; 015 016 import java.lang.reflect.InvocationTargetException; 017 import java.lang.reflect.Method; 018 import java.util.HashMap; 019 import java.util.Locale; 020 021 import javax.wvcm.Feedback; 022 import javax.wvcm.Resource; 023 import javax.wvcm.WvcmException; 024 import javax.wvcm.WvcmException.ReasonCode; 025 026 import com.ibm.rational.wvcm.stpex.StpExEnumeration; 027 import com.ibm.rational.wvcm.stpex.StpExEnumerationBase; 028 029 /** 030 * An extension of {@link javax.wvcm.WvcmException javax.wvcm.WvcmException} 031 * used throughout this API. Although API methods are declared to throw 032 * WvcmException, the exception actually thrown is StpException or one of its 033 * subclasses. 034 * <p> 035 * This class extends the WvcmException class, adding a <i>sub-reason code</i> 036 * field that encodes conditions specific to this API more finely than the 037 * {@link javax.wvcm.WvcmException.ReasonCode} 038 * <p> 039 * This class (unlike the WvcmException class) leverages the Java 1.4 chained 040 * exception mechanism. By default, if an StpException is constructed from one 041 * or more nested Throwables, the first nested Throwable in the list is also set 042 * as the StpException's {@link java.lang.Throwable#initCause cause}. In 043 * certain special cases, the cause may be set to something other than the first 044 * nested Throwable. 045 * 046 * Exception classes that extend StpException because they convey additional 047 * information, are as follows: 048 * <ul> 049 * <li>{@link StpPropertyException} - adds name of property responsible for the 050 * exception 051 * <p> 052 * <li>{@link StpPartialResultsException} - holds a ResourceList of child 053 * resources successfully received, a nested list of Exceptions for child 054 * resources that could not be retrieved, and an indicator of whether the two 055 * lists completely identify all resources that were supposed to be retrieved. 056 * <p> 057 * </ul> 058 */ 059 public abstract class StpException extends WvcmException 060 { 061 /** 062 * The specification for the data implementation object associated with this 063 * exception. 064 */ 065 public interface Data { 066 public String getMessage(); 067 public StpReasonCode getStpReasonCode(); 068 public String toString(); 069 } 070 071 /** 072 * An encoding of exception conditions specific to this API. Each 073 * StpReasonCode maps to one WvcmException.ReasonCode, but, because the 074 * granularity of the StpReasonCode enumeration is finer than that of the 075 * ReasonCode, the mapping may be many-to-one. 076 * <p> 077 * 078 * When the correspondence between an StpReasonCode and a ReasonCode is not 079 * obvious, the StpReasonCode is mapped to either ReasonCode.CONFLICT or 080 * ReasonCode.FORBIDDEN 081 * using the following rationale: 082 * <p> 083 * <ul> 084 * <li>{@link javax.wvcm.WvcmException.ReasonCode#CONFLICT CONFLICT} - the exception 085 * relates to an issue where the client may be able to retry the method 086 * after changing the state on some object. 087 * 088 * <li>{@link javax.wvcm.WvcmException.ReasonCode#FORBIDDEN FORBIDDEN} - the 089 * exception relates to an issue where the client cannot do anything to 090 * retry the method. 091 * </ul> 092 * 093 * For conditions where there is not enough information to decide whether or 094 * not there is anything the client could do to retry the method, the 095 * StpReasonCode is classified as CONFLICT. 096 * <p> 097 */ 098 099 public static enum StpReasonCode implements StpExEnumeration 100 { 101 /** 102 * The request timed out waiting for a resource to become free. 103 */ 104 REQUEST_TIMED_OUT(ReasonCode.ABORTED), 105 106 /** 107 * <code>Precondition:</code> Cannot create this resource at the 108 * specified location. 109 */ 110 CANNOT_CREATE_AT_THIS_LOCATION, 111 112 /** 113 * <code>Precondition:</code> Operation failed because it attempted to 114 * set a protected property. 115 */ 116 CANNOT_MODIFY_PROTECTED_PROPERTY, 117 118 /** Cannot overwrite existing binding. */ 119 CANNOT_OVERWRITE, 120 121 /** 122 * The operation cannot be performed because of a conflict with resource 123 * state. 124 */ 125 CONFLICT, 126 127 /** 128 * A checkout was attempted with no explicit activity and no current 129 * activity in the workspace. 130 */ 131 ACTIVITY_NEEDED(ReasonCode.CONFLICT), 132 133 /** 134 * The specified record is already being edited (by the same user). 135 */ 136 ALREADY_BEING_EDITED(ReasonCode.CONFLICT), 137 138 /** 139 * Authentication information is required but client didn't provide any. 140 */ 141 AUTHENTICATION_INFO_REQUIRED(ReasonCode.CONFLICT), 142 143 /** 144 * The requested action is inappropriate for the current state of the 145 * query (precondition failure) 146 */ 147 BAD_SOURCE_STATE(ReasonCode.CONFLICT), 148 149 /** 150 * The checkin operation failed because the resource is not checked out. 151 */ 152 CANNOT_CHECKIN_MUST_BE_CHECKED_OUT(ReasonCode.CONFLICT), 153 154 /** 155 * Used when a string is not supported by the server's operating system. 156 */ 157 CANNOT_ENCODE_STRING(ReasonCode.CONFLICT), 158 159 /** 160 * The uncheckout operation failed because the resource is not checked 161 * out. 162 */ 163 CANNOT_UNCHECKOUT_MUST_BE_CHECKED_OUT(ReasonCode.CONFLICT), 164 165 /** 166 * Checkout failed because the branch was not mastered locally. 167 */ 168 CHECKOUT_BRANCH_NOT_MASTERED(ReasonCode.CONFLICT), 169 170 /** 171 * Checkout failed because the branch type was not mastered locally. 172 */ 173 CHECKOUT_BRTYPE_NOT_MASTERED(ReasonCode.CONFLICT), 174 175 /** Version being checked out is not the latest **/ 176 CHECKOUT_NOT_LATEST(ReasonCode.CONFLICT), 177 178 /** The client location is not within a file area */ 179 CLIENT_LOCATION_NOT_IN_FILE_AREA(ReasonCode.CONFLICT), 180 181 /** A communication precondition failed */ 182 CONDITIONAL_EXECUTION(ReasonCode.CONFLICT), 183 184 /** 185 * An operation failed because the connection to the remote server could 186 * not be established or terminated prematurely after being established. 187 */ 188 CONNECTION_FAILED(ReasonCode.CONFLICT), 189 190 /** 191 * An attempt to deliver a resource from the change context to the 192 * database failed. 193 */ 194 DELIVERY_ERROR(ReasonCode.CONFLICT), 195 196 /** Version discordance detected **/ 197 DISCORDANCE_VERSION(ReasonCode.CONFLICT), 198 199 /** Duplicate activity name **/ 200 DUPLICATE_ACTIVITY_NAME(ReasonCode.CONFLICT), 201 202 /** Duplicate stream name **/ 203 DUPLICATE_STREAM_NAME(ReasonCode.CONFLICT), 204 205 /** 206 * This code indicates that an external lock couldn't be acquired 207 * because the lock already exists. 208 */ 209 EXTERNAL_LOCK_ALREADY_PRESENT(ReasonCode.CONFLICT), 210 211 /** 212 * Some dependency required by the communication channel failed. 213 */ 214 FAILED_DEPENDENCY(ReasonCode.CONFLICT), 215 216 /** 217 * A field did not pass validation during an attempted delivery. 218 */ 219 FIELD_VALIDATION(ReasonCode.CONFLICT), 220 221 /** 222 * The client resource resides in a file area whose version is not 223 * compatible with the currently running software. The file area needs 224 * to be upgraded in order to work with this software. 225 */ 226 FILE_AREA_NEEDS_UPGRADE(ReasonCode.CONFLICT), 227 228 /** A file error was encountered */ 229 FILE_ERROR(ReasonCode.CONFLICT), 230 231 /** 232 * While firing a named ClearQuest hook, the hook returned a message, 233 * which generally represents an error or need for additional 234 * information 235 */ 236 HOOK_RETURNED_MESSAGE(ReasonCode.CONFLICT), 237 238 /** 239 * An in-line query definition during query execution 240 */ 241 ILLEGAL_QUERY(ReasonCode.CONFLICT), 242 243 /** 244 * The client resource resides in a file area whose version is not 245 * compatible with the currently running software. The software needs to 246 * be upgraded to handle this file area. 247 */ 248 INCOMPATIBLE_FILE_AREA_VERSION(ReasonCode.CONFLICT), 249 250 /** Insufficient permission for the requested operation */ 251 INSUFFICIENT_PERMISSION(ReasonCode.CONFLICT), 252 253 /** An interaction request has occurred */ 254 INTERACTION_REQUEST(ReasonCode.CONFLICT), 255 256 /** An internal error has occurred */ 257 INTERNAL_ERROR(ReasonCode.CONFLICT), 258 259 /** 260 * The provider's server encountered an unexpected internal error 261 * condition which prevented it from fulfilling the request. This 262 * loosely corresponds to an HTTP 500 Internal Server Error response 263 * from the server. 264 * 265 * @see #SERVER_ERROR 266 */ 267 INTERNAL_SERVER_ERROR(ReasonCode.CONFLICT), 268 269 /** 270 * A required field is missing from or malformed in an StpLocation 271 * specification. 272 */ 273 INVALID_OBJECT_SELECTOR(ReasonCode.CONFLICT), 274 275 /** An invalid response was received */ 276 INVALID_RESPONSE(ReasonCode.CONFLICT), 277 278 /** 279 * Completion of operation was prevented because one or more properties 280 * have invalid values 281 */ 282 INVALID_VALUES(ReasonCode.CONFLICT), 283 284 /** License error occurred **/ 285 LICENSE_ERROR(ReasonCode.CONFLICT), 286 287 /** The database to be affected is currently locked */ 288 LOCKED_DATABASE(ReasonCode.CONFLICT), 289 290 /** The name supplied for a new resource is invalid */ 291 NAME_MUST_BE_VALID(ReasonCode.CONFLICT), 292 293 /** Resource needs to be merged from latest version **/ 294 NEEDS_MERGE_FROM_LATEST(ReasonCode.CONFLICT), 295 296 /** For use when StpException is just a wrapper for a WvcmException */ 297 NONE(ReasonCode.CONFLICT), 298 299 /** 300 * A duplicate record is specified but the action is not a duplicate 301 * action. 302 */ 303 NOT_DUPLICATE_ACTION(ReasonCode.CONFLICT), 304 305 /** A parameter mismatch was detected in a response */ 306 PARAMETER_MISMATCH(ReasonCode.CONFLICT), 307 308 /** The parent of a targeted resource needs to exist, but doesn't */ 309 PARENT_MUST_EXIST(ReasonCode.CONFLICT), 310 311 /** 312 * This exception is reporting failure in an operation that was applied 313 * independently to multiple resources and failed on some of them. 314 * 315 * @see StpPartialResultsException 316 */ 317 PARTIAL_RESULTS(ReasonCode.CONFLICT), 318 319 /** Used when delivering change contexts */ 320 PRIOR_COMMIT_FAILURE(ReasonCode.CONFLICT), 321 322 /** 323 * Some other property error such as 324 * <ul> 325 * <li>Can't update value because it is inappropriate for property. 326 * <li>Can't update value because of server-specific restriction such 327 * as length of string or list. 328 * <li> 329 * </ul> 330 */ 331 PROPERTY_ERROR(ReasonCode.CONFLICT), 332 333 /** 334 * An exception with this StpReasonCode is thrown by the execution of 335 * any property "getter" method when the targeted property could not be 336 * retrieved from the server. Exceptions of this type wrap the exception 337 * generated by the server, which is accessible via the getCause() or 338 * {@link javax.wvcm.WvcmException#getNestedExceptions()} methods of 339 * this wrapping exception. 340 * <p> 341 * The traceback for the outer, PROPERTY_RETRIEVAL_FAILED exception will 342 * identify the context in which the attempt was made to get the 343 * property value from the proxy, while the traceback for the cause of 344 * that exception will identify the context in which the attempt was 345 * made to read the value into the proxy. 346 */ 347 PROPERTY_RETRIEVAL_FAILED(ReasonCode.CONFLICT), 348 349 /** 350 * Thrown by CreateRecord when an attempt is made to create a record with 351 * the same name as one that already exists on the server. 352 */ 353 RECORD_WITH_SAME_DISPLAYNAME_EXISTS(ReasonCode.CONFLICT), 354 355 /** Request failed error **/ 356 REQUEST_FAILED_ERROR(ReasonCode.CONFLICT), 357 358 /** 359 * The provider has detected something inappropriate with a server's 360 * response. It could be the result of a bug in the server's response or 361 * a bug in the provider's processing of the response. 362 * 363 * @see #INTERNAL_SERVER_ERROR 364 */ 365 SERVER_ERROR(ReasonCode.CONFLICT), 366 367 /** View update cancel failed **/ 368 SYNC_CANCEL_FAILED(ReasonCode.CONFLICT), 369 370 /** 371 * View's config spec is not synchronized with stream's configuration. 372 * An update view operation is required. 373 */ 374 VIEW_OUT_OF_SYNC_WITH_STREAM(ReasonCode.CONFLICT), 375 376 /** 377 * The provider was unable to complete the operation for an unspecified 378 * reason. 379 */ 380 FORBIDDEN, 381 382 /** Request not understood or contextually incorrect for the provider. */ 383 BAD_REQUEST(ReasonCode.FORBIDDEN), 384 385 /** Used by REVERT method */ 386 CHILD_ORIGINAL_SOURCE_DIRECTORY_NO_LONGER_EXISTS(ReasonCode.FORBIDDEN), 387 388 /** Used by REVERT method */ 389 CHILDREN_OF_FOLDER_MUST_BE_REVERTED_FIRST(ReasonCode.FORBIDDEN), 390 391 /** 392 * Used when an operation is forbidden due to operating in disconnected 393 * mode 394 */ 395 DISCONNECTED(ReasonCode.FORBIDDEN), 396 397 /** Used when trying to delete query folders */ 398 FOLDER_HAS_CHILDREN(ReasonCode.FORBIDDEN), 399 400 /** An illegal argument was specified */ 401 ILLEGAL_ARG(ReasonCode.FORBIDDEN), 402 403 /** The request or operation in not valid */ 404 INVALID(ReasonCode.FORBIDDEN), 405 406 /** 407 * Thrown by OpenRecord when a duplicate record is not specified with a 408 * duplicate action. 409 */ 410 NO_DUPLICATE_RECORD(ReasonCode.FORBIDDEN), 411 412 /** Request not allowed by the provider. */ 413 NOT_ALLOWED(ReasonCode.FORBIDDEN), 414 415 /** The request or operation is not supported */ 416 NOT_SUPPORTED(ReasonCode.FORBIDDEN), 417 418 /** The submit request is not allowed */ 419 SUBMIT_NOT_ALLOWED(ReasonCode.FORBIDDEN), 420 421 /** 422 * Thrown by OpenRecord when the specified action is not defined for the 423 * record type. 424 */ 425 UNKNOWN_ACTION(ReasonCode.FORBIDDEN), 426 427 /** 428 * Thrown when a report has been requested on resource that does not 429 * support that report type. 430 */ 431 UNSUPPORTED_REPORT(ReasonCode.FORBIDDEN), 432 433 /** Illegal syntax for location string value. */ 434 ILLEGAL_LOCATION_SYNTAX, 435 436 /** 437 * <code>Precondition:</code> Report failed since the resource does 438 * not support the specified report. 439 */ 440 BAD_REPORT(ReasonCode.METHOD_NOT_SUPPORTED), 441 442 /** The resource has no content. */ 443 NO_CONTENT(ReasonCode.METHOD_NOT_SUPPORTED), 444 445 /** 446 * The corresponding remote resource no longer exists or was never 447 * created. 448 */ 449 NOT_FOUND, 450 451 /** 452 * <code>Precondition:</code> Failed to retrieve a property that 453 * should be supported. A potentially recoverable condition prevented 454 * the server from retrieving the property value. 455 */ 456 PROPERTY_NOT_CURRENTLY_AVAILABLE, 457 458 /** 459 * The requested property value is unavailable because it is not valid 460 * for the targeted resource--the property name used is not defined in 461 * the targeted resource's interface nor is it included in the 462 * PropertyRequest returned by 463 * {@link javax.wvcm.Resource#doGetPropertyNameList(Feedback)} for the 464 * resource. 465 */ 466 PROPERTY_NOT_DEFINED_FOR_RESOURCE, 467 468 /** 469 * The property value is maintained only on the server and so is not 470 * available locally 471 */ 472 PROPERTY_NOT_AVAILABLE_LOCALLY(ReasonCode.PROPERTY_NOT_DEFINED_FOR_RESOURCE), 473 474 /** 475 * The property value is unavailable because it was not in the property 476 * name list when the proxy was created nor has it subsequently been 477 * added via {@link Resource#setProperty} or one of the other property 478 * setters. 479 */ 480 PROPERTY_NOT_REQUESTED, 481 482 /** 483 * Even though this API says the property is valid for the targeted 484 * resource, the server does not support it. For properties the server 485 * intends to support in the release under development, the exception 486 * message should say “NOT YET IMPLEMENTED”. 487 */ 488 PROPERTY_NOT_SUPPORTED_BY_SERVER, 489 490 /** The property value update would overwrite an earlier change. */ 491 PROPERTY_OVERWRITE_FORBIDDEN, 492 493 /** The provider suffered an I/O failure, the operation may be retried. */ 494 READ_FAILED, 495 496 /** 497 * <code>Precondition:</code> Creating a resource failed because a 498 * resource already exists at the specified location. 499 */ 500 RESOURCE_ALREADY_EXISTS_AT_LOCATION, 501 502 /** View update was canceled **/ 503 SYNC_CANCELLED (ReasonCode.CONFLICT), 504 505 /** The user is not authorized to execute the attempted operation. */ 506 UNAUTHORIZED, 507 508 /** Login on server failed**/ 509 LOGIN_FAILED(ReasonCode.UNAUTHORIZED), 510 511 /** The provider suffered an I/O failure, the operation may be retried. */ 512 WRITE_FAILED, 513 514 /** 515 * Session does not exist or the session has expired. 516 */ 517 SESSION_EXPIRED_OR_DOES_NOT_EXIST(ReasonCode.UNAUTHORIZED), 518 519 /** 520 * Used if an operation requires credentials but none were provided 521 */ 522 CREDENTIALS_REQUIRED(ReasonCode.UNAUTHORIZED), 523 524 /** 525 * Used when the server capacity has been reached. 526 */ 527 SERVER_BUSY(ReasonCode.CONFLICT), 528 529 /** 530 * Used when the client is not compatible with the server. (This may 531 * be caused by a client that is too old, or too new.) 532 */ 533 INCOMPATIBLE_SERVER(ReasonCode.VERSION_NOT_SUPPORTED), 534 535 RPC_UNEXPECTEDLY_EXITED(ReasonCode.CONFLICT), 536 537 ; 538 /* end of enum StpReasonCode */; 539 540 // ==================================================================== 541 542 /** 543 * Returns the WVCM base reason code associated with this STP reason 544 * code. 545 * 546 * @return The WVCM reason code associated with this STP reason code. 547 */ 548 public ReasonCode getWvcmReasonCode() 549 { 550 return m_wvcmReasonCode; 551 } 552 553 /* 554 * A string representation of this reason code. 555 */ 556 public String toString() 557 { 558 return name().toLowerCase().replaceAll("_", "-"); 559 } 560 561 /** 562 * Constructs an StpReasonCode that is semantically equivalent to the 563 * WVCM ReasonCode of the same name. 564 */ 565 private StpReasonCode() 566 { 567 m_wvcmReasonCode = ReasonCode.valueOf(ReasonCode.class, name()); 568 } 569 570 /** 571 * Constructs an StpReasonCode as a refinement of a WVCM base 572 * ReasonCode. 573 * 574 * @param wvcmBaseCode The WVCM reason code that this StpReasonCode 575 * refines. Cannot be <code>null</code>. 576 */ 577 private StpReasonCode(ReasonCode wvcmBaseCode) 578 { 579 m_wvcmReasonCode = wvcmBaseCode; 580 } 581 582 /** 583 * The WVCM reason code classification for this SubReasonCode. 584 */ 585 private final ReasonCode m_wvcmReasonCode; 586 } 587 588 /** 589 * Casts an Object to a Type, avoiding a type safety warning. Use sparingly. 590 * May throw ClassCastException at runtime. Some Java compilers can deduce 591 * U from context, such as in an assignment or a return statement; however, 592 * others may not. It is suggested, therefore, that all uses of this method 593 * should include the target type explicitly. 594 * <pre> 595 * StpException.<desired-type>unchecked_cast(x) 596 * </pre> 597 * The ugliness of this construct matches the sledge hammer that is being 598 * used to make the code compile without warnings. 599 * 600 * @param <U> The Type to which the object should be cast 601 * @param obj The Object to be cast 602 * @return The argument Object cast to Type U. 603 */ 604 @SuppressWarnings("unchecked") 605 public static <U> U unchecked_cast(Object obj) 606 { 607 return (U)obj; 608 } 609 610 /** 611 * @return Returns an implementation object that stores the fields of this 612 * exception not defined by WvcmException and implements the other 613 * methods of this exception. Will never be <b>null</b>. 614 */ 615 public abstract Data data(); 616 617 /** 618 * Localizes the message contained within this exception and returns it. 619 */ 620 public String getMessage() { return data().getMessage(); } 621 622 /** 623 * @return The StpReasonCode assigned to this exception. 624 */ 625 public StpReasonCode getStpReasonCode() 626 { return data().getStpReasonCode(); } 627 628 /** 629 * @return A String image of this StpException and any nested Exceptions 630 */ 631 public String toString() { return data().toString(); } 632 633 /** 634 * Constructs this exception object for its subclasses. 635 * 636 * @param resource The Resource argument to WvcmException 637 * @param reasonCode The ReasonCode argument to WvcmException 638 * @param nestedExceptions The Throwable[] argument to WvcmException 639 * 640 * @see javax.wvcm.WvcmException 641 */ 642 protected StpException(Resource resource, 643 ReasonCode reasonCode, 644 Throwable... nestedExceptions) 645 { 646 super(null, resource, reasonCode, nestedExceptions); 647 } 648 }