1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF)                              */
3 /* (C) Copyright IBM Corp. 2001                                              */
4 /*                                                                           */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0.    */
6 /*****************************************************************************/
7 
8 #ifndef STAF_Exception
9 #define STAF_Exception
10 
11 #ifdef __cplusplus
12 
13 #include <cstring>
14 #include <cstdio>
15 #include "STAF_iostream.h"
16 #include "STAFError.h"
17 
18 /* The THROW_STAF_EXCEPTION macro is used to throw a STAFException or */
19 /* one of its derivatives.  It also adds the location information to  */
20 /* the exception.                                                     */
21 
22 #define THROW_STAF_EXCEPTION(e)\
23 { e.setLocation(__FILE__, __LINE__); throw e; }
24 
25 class STAFException
26 {
27 public:
28 
29     STAFException(const char *text, unsigned int errorCode = 0,
30                   const char *name = "STAFException")
fErrorCode(errorCode)31         : fErrorCode(errorCode)
32     {
33         // Using strncpy to make sure don't exceed the size of fName
34         strncpy(fName, name, sizeof(fName) - 1);
35         fName[sizeof(fName) - 1] = 0;
36 
37         // Using strncpy to make sure don't exceed the size of fText
38         strncpy(fText, text, sizeof(fText) - 1);
39         fText[sizeof(fText) - 1] = 0;
40 
41         fLocation[0] = 0;
42     }
43 
setLocation(const char * filename,unsigned int lineNumber)44     void setLocation(const char *filename, unsigned int lineNumber)
45     {
46         // Make sure don't exceed the size of fLocation.
47         // Note: The 16 is based on the lineNumber length being at most 13,
48         //       plus 2 for the size of "(" and ")" plus 1.
49         sprintf(fLocation, "%.*s(%u)",
50                 static_cast<int>(sizeof(fLocation) - 16),
51                 filename, lineNumber);
52     }
53 
54     void trace(const char *caughtWhere = 0);
55     void trace(unsigned int tracePoint, const char *caughtWhere = 0);
56 
57     static void checkRC(STAFRC_t rc, const char *errorMessage,
58                         unsigned int osRC = 0);
59 
60     inline void write(const char *caughtWhere = 0, ostream &os = cout)
61     {
62         if (caughtWhere) os << "In " << caughtWhere << ":" << endl;
63 
64         os << "Caught STAFException" << endl
65            << "Name      : " << getName() << endl
66            << "Location  : " << getLocation() << endl
67            << "Text      : " << getText() << endl
68            << "Error code: " << getErrorCode() << endl;
69     }
70 
getName()71     const char *getName() { return fName; }
getText()72     const char *getText() { return fText; }
getLocation()73     const char *getLocation() { return fLocation; }
getErrorCode()74     unsigned int getErrorCode() { return fErrorCode; }
75 
~STAFException()76     ~STAFException() { /* Do Nothing */ }
77 
78 protected:
79 
80     static void checkStandardExceptions(char *buffer, STAFRC_t rc,
81                                         const char *errorMessage,
82                                         unsigned int osRC);
83 private:
84 
85     char fName[128];
86     /* Note: If change size of fText, must change size of buffer */
87     char fText[512];
88     char fLocation[384];
89     unsigned int fErrorCode;
90 };
91 
92 
93 /* The STAF_EXCEPTION_DEFINITION macro is used to create new types of */
94 /* STAF Exceptions.                                                 */
95 
96 #define STAF_EXCEPTION_DEFINITION(className, baseName)\
97 class className : public baseName\
98 {\
99 public:\
100     className(const char *text, unsigned int errorCode = 0,\
101               const char *name = #className)\
102         : baseName(text, errorCode, name)\
103     { /* Do Nothing */ }\
104 \
105     static void checkRC(STAFRC_t rc, const char *errorMessage, unsigned int osRC = 0)\
106     {\
107         if (rc != kSTAFOk)\
108         {\
109             /* Note the buffer size must be same as the fText size */\
110             char buffer[512] = { 0 };\
111             checkStandardExceptions(buffer, rc, errorMessage, osRC);\
112             sprintf(buffer, "%.*s",\
113                     static_cast<int>(sizeof(buffer) - 1), errorMessage);\
114             THROW_STAF_EXCEPTION(className(buffer, rc));\
115         }\
116     }\
117 \
118     ~className() { /* Do Nothing */ }\
119 };
120 
121 STAF_EXCEPTION_DEFINITION(STAFOutOfBoundsException,   STAFException);
122 STAF_EXCEPTION_DEFINITION(STAFInvalidObjectException, STAFException);
123 STAF_EXCEPTION_DEFINITION(STAFInvalidParmException,   STAFException);
124 STAF_EXCEPTION_DEFINITION(STAFBaseOSErrorException,   STAFException);
125 
checkRC(STAFRC_t rc,const char * errorMessage,unsigned int osRC)126 inline void STAFException::checkRC(STAFRC_t rc, const char *errorMessage,
127                                    unsigned int osRC)
128 {
129     if (rc != kSTAFOk)
130     {
131         // Note the buffer size must be same as the fText size
132         char buffer[512] = { 0 };
133         checkStandardExceptions(buffer, rc, errorMessage, osRC);
134         // Makes sure no buffer overflow occurs if errorMessage
135         // exceeds size of buffer
136         sprintf(buffer, "%.*s", static_cast<int>(sizeof(buffer) - 1),
137                 errorMessage);
138         THROW_STAF_EXCEPTION(STAFException(buffer, rc));
139     }
140 }
141 
checkStandardExceptions(char * buffer,STAFRC_t rc,const char * errorMessage,unsigned int osRC)142 inline void STAFException::checkStandardExceptions(char *buffer, STAFRC_t rc,
143                                                    const char *errorMessage,
144                                                    unsigned int osRC)
145 {
146     switch (rc)
147     {
148         case kSTAFBaseOSError:
149             // Makes sure no buffer overflow occurs
150             // Note: The 16 is based on the osRC length being at most 13,
151             //       plus 2 for the size of ": " plus 1.
152             sprintf(buffer, "%.*s: %u", static_cast<int>(sizeof(buffer) - 16),
153                     errorMessage, osRC);
154             THROW_STAF_EXCEPTION(STAFBaseOSErrorException(buffer, rc));
155 
156         case kSTAFInvalidObject:
157             // Makes sure no buffer overflow occurs if errorMessage
158             // exceeds size of buffer
159             sprintf(buffer, "%.*s", static_cast<int>(sizeof(buffer) - 1),
160                     errorMessage);
161             THROW_STAF_EXCEPTION(STAFInvalidObjectException(buffer, rc));
162 
163     case kSTAFInvalidParm:
164             // Makes sure no buffer overflow occurs if errorMessage
165             // exceeds size of buffer
166             sprintf(buffer, "%.*s", static_cast<int>(sizeof(buffer) - 1),
167                     errorMessage);
168             THROW_STAF_EXCEPTION(STAFInvalidParmException(buffer, rc));
169 
170         default:
171             break;
172     }
173 }
174 
175 #endif
176 
177 #endif
178