dae719ea4e25911550813860a378e666d1092afd
[platform/core/security/cert-svc.git] / vcore / src / vcore / exception.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    exception.h
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version 1.0
20  * @brief   Header file for base exception
21  */
22 #ifndef ValidationCore_EXCEPTION_H
23 #define ValidationCore_EXCEPTION_H
24
25 #include <string>
26 #include <cstring>
27 #include <cstdio>
28 #include <exception>
29 #include <cstdlib>
30 #include <sstream>
31
32 namespace ValidationCore {
33 void LogUnhandledException(const std::string &str);
34 void LogUnhandledException(const std::string &str,
35                            const char *filename,
36                            int line,
37                            const char *function);
38 }
39
40 namespace ValidationCore {
41 class Exception {
42 private:
43     static unsigned int m_exceptionCount;
44     static Exception* m_lastException;
45     static void (*m_terminateHandler)();
46
47     static void AddRef(Exception* exception)
48     {
49         if (!m_exceptionCount) {
50             m_terminateHandler = std::set_terminate(&TerminateHandler);
51         }
52
53         ++m_exceptionCount;
54         m_lastException = exception;
55     }
56
57     static void UnRef(Exception* e)
58     {
59         if (m_lastException == e) {
60             m_lastException = NULL;
61         }
62
63         --m_exceptionCount;
64
65         if (!m_exceptionCount) {
66             std::set_terminate(m_terminateHandler);
67             m_terminateHandler = NULL;
68         }
69     }
70
71     static void TerminateHandler()
72     {
73         if (m_lastException != NULL) {
74             DisplayKnownException(*m_lastException);
75             abort();
76         } else {
77             DisplayUnknownException();
78             abort();
79         }
80     }
81
82     Exception *m_reason;
83     std::string m_path;
84     std::string m_function;
85     int m_line;
86
87 protected:
88     std::string m_message;
89     std::string m_className;
90
91 public:
92     static std::string KnownExceptionToString(const Exception &e)
93     {
94         std::ostringstream message;
95         message <<
96         "\033[1;5;31m\n=== Unhandled DPL exception occurred ===\033[m\n\n";
97         message << "\033[1;33mException trace:\033[m\n\n";
98         message << e.DumpToString();
99         message << "\033[1;31m\n=== Will now abort ===\033[m\n";
100
101         return message.str();
102     }
103
104     static std::string UnknownExceptionToString()
105     {
106         std::ostringstream message;
107         message <<
108         "\033[1;5;31m\n=== Unhandled non-DPL exception occurred ===\033[m\n\n";
109         message << "\033[1;31m\n=== Will now abort ===\033[m\n";
110
111         return message.str();
112     }
113
114     static void DisplayKnownException(const Exception& e)
115     {
116         LogUnhandledException(KnownExceptionToString(e).c_str());
117     }
118
119     static void DisplayUnknownException()
120     {
121         LogUnhandledException(UnknownExceptionToString().c_str());
122     }
123
124     Exception(const Exception &other)
125     {
126         // Deep copy
127         if (other.m_reason != NULL) {
128             m_reason = new Exception(*other.m_reason);
129         } else {
130             m_reason = NULL;
131         }
132
133         m_message = other.m_message;
134         m_path = other.m_path;
135         m_function = other.m_function;
136         m_line = other.m_line;
137
138         m_className = other.m_className;
139
140         AddRef(this);
141     }
142
143     const Exception &operator =(const Exception &other)
144     {
145         if (this == &other) {
146             return *this;
147         }
148
149         // Deep copy
150         if (other.m_reason != NULL) {
151             m_reason = new Exception(*other.m_reason);
152         } else {
153             m_reason = NULL;
154         }
155
156         m_message = other.m_message;
157         m_path = other.m_path;
158         m_function = other.m_function;
159         m_line = other.m_line;
160
161         m_className = other.m_className;
162
163         AddRef(this);
164
165         return *this;
166     }
167
168     Exception(const char *path,
169               const char *function,
170               int line,
171               const std::string &message) :
172         m_reason(NULL),
173         m_path(path),
174         m_function(function),
175         m_line(line),
176         m_message(message)
177     {
178         AddRef(this);
179     }
180
181     Exception(const char *path,
182               const char *function,
183               int line,
184               const Exception &reason,
185               const std::string &message) :
186         m_reason(new Exception(reason)),
187         m_path(path),
188         m_function(function),
189         m_line(line),
190         m_message(message)
191     {
192         AddRef(this);
193     }
194
195     virtual ~Exception() throw()
196     {
197         if (m_reason != NULL) {
198             delete m_reason;
199             m_reason = NULL;
200         }
201
202         UnRef(this);
203     }
204
205     void Dump() const
206     {
207         // Show reason first
208         if (m_reason != NULL) {
209             m_reason->Dump();
210         }
211
212         // Afterward, dump exception
213         const char *file = strchr(m_path.c_str(), '/');
214
215         if (file == NULL) {
216             file = m_path.c_str();
217         } else {
218             ++file;
219         }
220
221         printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
222                file, m_line,
223                m_function.c_str(),
224                m_className.c_str(),
225                m_message.empty() ? "<EMPTY>" : m_message.c_str());
226     }
227
228     std::string DumpToString() const
229     {
230         std::string ret;
231         if (m_reason != NULL) {
232             ret = m_reason->DumpToString();
233         }
234
235         const char *file = strchr(m_path.c_str(), '/');
236
237         if (file == NULL) {
238             file = m_path.c_str();
239         } else {
240             ++file;
241         }
242
243         char buf[1024];
244         snprintf(buf,
245                  sizeof(buf),
246                  "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
247                  file,
248                  m_line,
249                  m_function.c_str(),
250                  m_className.c_str(),
251                  m_message.empty() ? "<EMPTY>" : m_message.c_str());
252
253         buf[sizeof(buf) - 1] = '\n';
254         ret += buf;
255
256         return ret;
257     }
258
259     Exception *GetReason() const
260     {
261         return m_reason;
262     }
263
264     std::string GetPath() const
265     {
266         return m_path;
267     }
268
269     std::string GetFunction() const
270     {
271         return m_function;
272     }
273
274     int GetLine() const
275     {
276         return m_line;
277     }
278
279     std::string GetMessage() const
280     {
281         return m_message;
282     }
283
284     std::string GetClassName() const
285     {
286         return m_className;
287     }
288 };
289 } // namespace ValidationCore
290
291 #define VcoreTry try
292
293 #define VcoreThrow(ClassName) \
294     throw ClassName(__FILE__, __FUNCTION__, __LINE__)
295
296 #define VcoreThrowMsg(ClassName, Message)                                            \
297     do                                                                               \
298     {                                                                                \
299         std::ostringstream dplLoggingStream;                                         \
300         dplLoggingStream << Message;                                                 \
301         throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str());   \
302     } while (0)
303
304 #define VcoreReThrow(ClassName) \
305     throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception)
306
307 #define VcoreReThrowMsg(ClassName, Message)                                          \
308     throw ClassName(__FILE__,                                                        \
309                     __FUNCTION__,                                                    \
310                     __LINE__,                                                        \
311                     _rethrown_exception,                                             \
312                     Message)
313
314 #define VcoreCatch(ClassName)                                                        \
315     catch (const ClassName &_rethrown_exception)
316
317 #define VCORE_DECLARE_EXCEPTION_TYPE(BaseClass, Class)                               \
318     class Class : public BaseClass {                                                 \
319     public:                                                                          \
320         Class(const char *path,                                                      \
321               const char *function,                                                  \
322               int line,                                                              \
323               const std::string & message = std::string())                           \
324           : BaseClass(path, function, line, message) {                               \
325                                                                                      \
326             BaseClass::m_className = #Class;                                         \
327         }                                                                            \
328                                                                                      \
329         Class(const char *path,                                                      \
330               const char *function,                                                  \
331               int line,                                                              \
332               const ValidationCore::Exception & reason,                              \
333               const std::string & message = std::string())                           \
334           : BaseClass(path, function, line, reason, message) {                       \
335             BaseClass::m_className = #Class;                                         \
336         }                                                                            \
337     };
338
339 #define VCORE_UNHANDLED_EXCEPTION_HANDLER_BEGIN try
340
341 #define VCORE_UNHANDLED_EXCEPTION_HANDLER_END                                        \
342     catch (const ValidationCore::Exception &exception)                               \
343     {                                                                                \
344         std::ostringstream msg;                                                      \
345         msg << ValidationCore::Exception::KnownExceptionToString(exception);         \
346         ValidationCore::LogUnhandledException(msg.str(),                             \
347                                         __FILE__,                                    \
348                                         __LINE__,                                    \
349                                        __FUNCTION__);                                \
350         abort();                                                                     \
351     }                                                                                \
352     catch (std::exception& e)                                                        \
353     {                                                                                \
354         std::ostringstream msg;                                                      \
355         msg << e.what();                                                             \
356         msg << "\n";                                                                 \
357         msg << ValidationCore::Exception::UnknownExceptionToString();                \
358         ValidationCore::LogUnhandledException(msg.str(),                             \
359                                         __FILE__,                                    \
360                                         __LINE__,                                    \
361                                         __FUNCTION__);                               \
362         abort();                                                                     \
363     }                                                                                \
364     catch (...)                                                                      \
365     {                                                                                \
366         std::ostringstream msg;                                                      \
367         msg << ValidationCore::Exception::UnknownExceptionToString();                \
368         ValidationCore::LogUnhandledException(msg.str(),                             \
369                                         __FILE__,                                    \
370                                         __LINE__,                                    \
371                                         __FUNCTION__);                               \
372         abort();                                                                     \
373     }
374
375 namespace ValidationCore {
376 namespace CommonException {
377 /**
378  * Internal exception definitions
379  *
380  * These should normally not happen.
381  * Usually, exception trace with internal error includes
382  * important messages.
383  */
384 VCORE_DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from
385                                                           // underlying libraries or
386                                                           // kernel
387 }
388 }
389
390 #endif // ValidationCore_EXCEPTION_H