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