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.&lt;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    }