Spring cleaning
[platform/core/test/security-tests.git] / src / framework / include / dpl / exception.h
1 /*
2  * Copyright (c) 2011-2020 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 DPL_EXCEPTION_H
23 #define DPL_EXCEPTION_H
24
25 #include <string>
26 #include <cstring>
27 #include <cstdio>
28 #include <exception>
29 #include <cstdlib>
30 #include <sstream>
31
32 namespace DPL {
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 DPL {
41 class Exception
42 {
43   private:
44     static unsigned int m_exceptionCount;
45     static Exception* m_lastException;
46     static void (*m_terminateHandler)();
47
48     static void AddRef(Exception* exception)
49     {
50         if (!m_exceptionCount) {
51             m_terminateHandler = std::set_terminate(&TerminateHandler);
52         }
53
54         ++m_exceptionCount;
55         m_lastException = exception;
56     }
57
58     static void UnRef(Exception* e)
59     {
60         if (m_lastException == e) {
61             m_lastException = nullptr;
62         }
63
64         --m_exceptionCount;
65
66         if (!m_exceptionCount) {
67             std::set_terminate(m_terminateHandler);
68             m_terminateHandler = nullptr;
69         }
70     }
71
72     static void TerminateHandler()
73     {
74         if (m_lastException != nullptr) {
75             DisplayKnownException(*m_lastException);
76             abort();
77         } else {
78             DisplayUnknownException();
79             abort();
80         }
81     }
82
83     Exception *m_reason;
84     std::string m_path;
85     std::string m_function;
86     int m_line;
87
88   protected:
89     std::string m_message;
90     std::string m_className;
91
92   public:
93     static std::string KnownExceptionToString(const Exception &e)
94     {
95         std::ostringstream message;
96         message <<
97         "\033[1;5;31m\n=== Unhandled DPL exception occurred ===\033[m\n\n";
98         message << "\033[1;33mException trace:\033[m\n\n";
99         message << e.DumpToString();
100         message << "\033[1;31m\n=== Will now abort ===\033[m\n";
101
102         return message.str();
103     }
104
105     static std::string UnknownExceptionToString()
106     {
107         std::ostringstream message;
108         message <<
109         "\033[1;5;31m\n=== Unhandled non-DPL exception occurred ===\033[m\n\n";
110         message << "\033[1;31m\n=== Will now abort ===\033[m\n";
111
112         return message.str();
113     }
114
115     static void DisplayKnownException(const Exception& e)
116     {
117         LogUnhandledException(KnownExceptionToString(e));
118     }
119
120     static void DisplayUnknownException()
121     {
122         LogUnhandledException(UnknownExceptionToString());
123     }
124
125     Exception(const Exception &other)
126     {
127         // Deep copy
128         if (other.m_reason != nullptr) {
129             m_reason = new Exception(*other.m_reason);
130         } else {
131             m_reason = nullptr;
132         }
133
134         m_message = other.m_message;
135         m_path = other.m_path;
136         m_function = other.m_function;
137         m_line = other.m_line;
138
139         m_className = other.m_className;
140
141         AddRef(this);
142     }
143
144     const Exception &operator =(const Exception &other)
145     {
146         if (this == &other) {
147             return *this;
148         }
149
150         // Deep copy
151         if (other.m_reason != nullptr) {
152             m_reason = new Exception(*other.m_reason);
153         } else {
154             m_reason = nullptr;
155         }
156
157         m_message = other.m_message;
158         m_path = other.m_path;
159         m_function = other.m_function;
160         m_line = other.m_line;
161
162         m_className = other.m_className;
163
164         AddRef(this);
165
166         return *this;
167     }
168
169     Exception(const char *path,
170               const char *function,
171               int line,
172               const std::string &message) :
173         m_reason(nullptr),
174         m_path(path),
175         m_function(function),
176         m_line(line),
177         m_message(message)
178     {
179         AddRef(this);
180     }
181
182     Exception(const char *path,
183               const char *function,
184               int line,
185               const Exception &reason,
186               const std::string &message) :
187         m_reason(new Exception(reason)),
188         m_path(path),
189         m_function(function),
190         m_line(line),
191         m_message(message)
192     {
193         AddRef(this);
194     }
195
196     virtual ~Exception() throw()
197     {
198         if (m_reason != nullptr) {
199             delete m_reason;
200             m_reason = nullptr;
201         }
202
203         UnRef(this);
204     }
205
206     void Dump() const
207     {
208         // Show reason first
209         if (m_reason != nullptr) {
210             m_reason->Dump();
211         }
212
213         // Afterward, dump exception
214         const char *file = strchr(m_path.c_str(), '/');
215
216         if (file == nullptr) {
217             file = m_path.c_str();
218         } else {
219             ++file;
220         }
221
222         printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
223                file, m_line,
224                m_function.c_str(),
225                m_className.c_str(),
226                m_message.empty() ? "<EMPTY>" : m_message.c_str());
227     }
228
229     std::string DumpToString() const
230     {
231         std::string ret;
232         if (m_reason != nullptr) {
233             ret = m_reason->DumpToString();
234         }
235
236         const char *file = strchr(m_path.c_str(), '/');
237
238         if (file == nullptr) {
239             file = m_path.c_str();
240         } else {
241             ++file;
242         }
243
244         char buf[1024];
245         snprintf(buf,
246                  sizeof(buf),
247                  "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
248                  file,
249                  m_line,
250                  m_function.c_str(),
251                  m_className.c_str(),
252                  m_message.empty() ? "<EMPTY>" : m_message.c_str());
253
254         buf[sizeof(buf) - 1] = '\n';
255         ret += buf;
256
257         return ret;
258     }
259
260     Exception *GetReason() const
261     {
262         return m_reason;
263     }
264
265     std::string GetPath() const
266     {
267         return m_path;
268     }
269
270     std::string GetFunction() const
271     {
272         return m_function;
273     }
274
275     int GetLine() const
276     {
277         return m_line;
278     }
279
280     std::string GetMessage() const
281     {
282         return m_message;
283     }
284
285     std::string GetClassName() const
286     {
287         return m_className;
288     }
289 };
290 } // namespace DPL
291
292 #define Try try
293
294 #define Throw(ClassName) \
295     throw ClassName(__FILE__, __FUNCTION__, __LINE__)
296
297 #define ThrowMsg(ClassName, Message)                                                 \
298     do                                                                               \
299     {                                                                                \
300         std::ostringstream dplLoggingStream;                                         \
301         dplLoggingStream << Message;                                                 \
302         throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str());   \
303     } while (0)
304
305 #define ReThrow(ClassName) \
306     throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception)
307
308 #define ReThrowMsg(ClassName, Message) \
309     throw ClassName(__FILE__, \
310                     __FUNCTION__, \
311                     __LINE__, \
312                     _rethrown_exception, \
313                     Message)
314
315 #define Catch(ClassName) \
316     catch (const ClassName &_rethrown_exception)
317
318 #define DECLARE_EXCEPTION_TYPE(BaseClass, Class)                                                                                          \
319     class Class :                                                                                                                                 \
320         public BaseClass                                                                                                                \
321     {                                                                                                                                     \
322       public:                                                                                                                               \
323         Class(const char *path, \
324               const char *function, \
325               int line, \
326               const std::string & message = std::string()) :                                                                                                                             \
327             BaseClass(path, function, line, message)                                                                                    \
328         {                                                                                                                                 \
329             BaseClass::m_className = #Class;                                                                                              \
330         }                                                                                                                                 \
331                                                                                                                                           \
332         Class(const char *path, \
333               const char *function, \
334               int line, \
335               const DPL::Exception & reason, \
336               const std::string & message = std::string()) :                                                                                                                             \
337             BaseClass(path, function, line, reason, message)                                                                            \
338         {                                                                                                                                 \
339             BaseClass::m_className = #Class;                                                                                              \
340         }                                                                                                                                 \
341     };
342
343 #define UNHANDLED_EXCEPTION_HANDLER_BEGIN try
344
345 #define UNHANDLED_EXCEPTION_HANDLER_END                                                                   \
346     catch (const DPL::Exception &exception)                                                               \
347     {                                                                                                     \
348         std::ostringstream msg;                                                                           \
349         msg << DPL::Exception::KnownExceptionToString(exception);                                         \
350         DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__);                          \
351         abort();                                                                                          \
352     }                                                                                                     \
353     catch (std::exception& e)                                                                             \
354     {                                                                                                     \
355         std::ostringstream msg;                                                                           \
356         msg << e.what();                                                                                  \
357         msg << "\n";                                                                                      \
358         msg << DPL::Exception::UnknownExceptionToString();                                                \
359         DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__);                          \
360         abort();                                                                                          \
361     }                                                                                                     \
362     catch (...)                                                                                           \
363     {                                                                                                     \
364         std::ostringstream msg;                                                                           \
365         msg << DPL::Exception::UnknownExceptionToString();                                                \
366         DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__);                          \
367         abort();                                                                                          \
368     }
369
370 namespace DPL {
371 namespace CommonException {
372 /**
373  * Internal exception definitions
374  *
375  * These should normally not happen.
376  * Usually, exception trace with internal error includes
377  * important messages.
378  */
379 DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from
380                                                  // underlying libraries or
381                                                  // kernel
382 }
383 }
384
385 #endif // DPL_EXCEPTION_H