From 86f6d1500a3659a3dacb55646079fa9de67ea51f Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 30 Mar 2017 13:46:58 +0900 Subject: [PATCH] Integrate the legacy context-common code and headers (1/2) This patch just imports the legacy code files. Change-Id: I6acd7303a4792faf864ef3e77e84bff35217fe64 Signed-off-by: Mu-Woong Lee --- common/client/CMakeLists.txt | 13 + common/client/DBusClient.cpp | 350 ++++++++++ common/client/IDBusClientListener.cpp | 23 + common/include/ContextProvider.h | 67 ++ common/include/CustomRegister.h | 48 ++ common/include/DBusClient.h | 69 ++ common/include/DBusSignalWatcher.h | 64 ++ common/include/DBusTypes.h | 53 ++ common/include/DatabaseManager.h | 92 +++ common/include/ErrorTypes.h | 44 ++ common/include/EventDrivenThread.h | 50 ++ common/include/IContextManager.h | 37 ++ common/include/ICustomRegister.h | 37 ++ common/include/IDBusClientListener.h | 37 ++ common/include/IDBusSignalListener.h | 42 ++ common/include/IDatabaseListener.h | 56 ++ common/include/ITimerListener.h | 39 ++ common/include/Json.h | 122 ++++ common/include/MyPlaceTypes.h | 85 +++ common/include/ProviderTypes.h | 184 +++++ common/include/ScopeMutex.h | 35 + common/include/SensorRecorderTypes.h | 55 ++ common/include/SharedVars.h | 50 ++ common/include/TimerManager.h | 105 +++ common/include/TriggerRuleTypes.h | 70 ++ common/include/TriggerTypes.h | 62 ++ common/include/Types.h | 72 ++ common/server/CMakeLists.txt | 13 + common/server/ContextProvider.cpp | 85 +++ common/server/CustomRegistser.cpp | 45 ++ common/server/DBusSignalWatcher.cpp | 111 ++++ common/server/DatabaseManager.cpp | 105 +++ common/server/DatabaseThread.cpp | 353 ++++++++++ common/server/DatabaseThread.h | 80 +++ common/server/EventDrivenThread.cpp | 136 ++++ common/server/IContextManager.cpp | 22 + common/server/IDBusSignalListener.cpp | 21 + common/server/IDatabaseListener.cpp | 21 + common/server/ITimerListener.cpp | 21 + common/server/SharedVars.cpp | 59 ++ common/server/TimerManager.cpp | 231 +++++++ common/shared/CMakeLists.txt | 12 + common/shared/Json.cpp | 925 ++++++++++++++++++++++++++ common/shared/MyPlaceTypes.cpp | 45 ++ common/shared/ScopeMutex.cpp | 29 + 45 files changed, 4275 insertions(+) create mode 100644 common/client/CMakeLists.txt create mode 100644 common/client/DBusClient.cpp create mode 100644 common/client/IDBusClientListener.cpp create mode 100644 common/include/ContextProvider.h create mode 100644 common/include/CustomRegister.h create mode 100644 common/include/DBusClient.h create mode 100644 common/include/DBusSignalWatcher.h create mode 100644 common/include/DBusTypes.h create mode 100644 common/include/DatabaseManager.h create mode 100644 common/include/ErrorTypes.h create mode 100644 common/include/EventDrivenThread.h create mode 100644 common/include/IContextManager.h create mode 100644 common/include/ICustomRegister.h create mode 100644 common/include/IDBusClientListener.h create mode 100644 common/include/IDBusSignalListener.h create mode 100644 common/include/IDatabaseListener.h create mode 100644 common/include/ITimerListener.h create mode 100644 common/include/Json.h create mode 100644 common/include/MyPlaceTypes.h create mode 100644 common/include/ProviderTypes.h create mode 100644 common/include/ScopeMutex.h create mode 100644 common/include/SensorRecorderTypes.h create mode 100644 common/include/SharedVars.h create mode 100644 common/include/TimerManager.h create mode 100644 common/include/TriggerRuleTypes.h create mode 100644 common/include/TriggerTypes.h create mode 100644 common/include/Types.h create mode 100644 common/server/CMakeLists.txt create mode 100644 common/server/ContextProvider.cpp create mode 100644 common/server/CustomRegistser.cpp create mode 100644 common/server/DBusSignalWatcher.cpp create mode 100644 common/server/DatabaseManager.cpp create mode 100644 common/server/DatabaseThread.cpp create mode 100644 common/server/DatabaseThread.h create mode 100644 common/server/EventDrivenThread.cpp create mode 100644 common/server/IContextManager.cpp create mode 100644 common/server/IDBusSignalListener.cpp create mode 100644 common/server/IDatabaseListener.cpp create mode 100644 common/server/ITimerListener.cpp create mode 100644 common/server/SharedVars.cpp create mode 100644 common/server/TimerManager.cpp create mode 100644 common/shared/CMakeLists.txt create mode 100644 common/shared/Json.cpp create mode 100644 common/shared/MyPlaceTypes.cpp create mode 100644 common/shared/ScopeMutex.cpp diff --git a/common/client/CMakeLists.txt b/common/client/CMakeLists.txt new file mode 100644 index 0000000..0b99d48 --- /dev/null +++ b/common/client/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-client") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +TARGET_LINK_LIBRARIES(${target} ctx-shared) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/client/DBusClient.cpp b/common/client/DBusClient.cpp new file mode 100644 index 0000000..85c9d75 --- /dev/null +++ b/common/client/DBusClient.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using namespace ctx; + +static const gchar __introspection[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +GDBusConnection *DBusClient::__connection = NULL; +GDBusNodeInfo *DBusClient::__nodeInfo = NULL; +std::atomic_int DBusClient::__instanceCount(0); +std::map DBusClient::__listenerMap; + +SO_EXPORT DBusClient::DBusClient() +{ + ++__instanceCount; +} + +SO_EXPORT DBusClient::~DBusClient() +{ + if (--__instanceCount == 0) + __release(); +} + +void DBusClient::__onMethodCalled(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer userData) +{ + IF_FAIL_VOID_TAG(STR_EQ(name, METHOD_RESPOND), _W, "Invalid method: %s", name); + + gint reqId = 0; + const gchar *subject = NULL; + gint error = 0; + const gchar *data = NULL; + + g_variant_get(param, "(i&si&s)", &reqId, &subject, &error, &data); + _D("[Response] ReqId: %d, Subject: %s, Error: %d", reqId, subject, error); + IF_FAIL_VOID_TAG(subject && data, _W, "Invalid parameter"); + + auto it = __listenerMap.find(subject); + it->second->onPublish(subject, reqId, error, data); + + g_dbus_method_invocation_return_value(invocation, NULL); +} + +bool DBusClient::__init() +{ + static GMutex mutex; + ScopeMutex sm(&mutex); + + if (__connection) + return true; + + GError *gerr = NULL; + gchar *addr = NULL; + GDBusInterfaceVTable vtable; + guint regId; + + __nodeInfo = g_dbus_node_info_new_for_xml(__introspection, NULL); + IF_FAIL_RETURN_TAG(__nodeInfo != NULL, false, _E, "Initialization failed"); + + addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(addr != NULL, _E, "Getting address failed"); + _SD("Address: %s", addr); + + __connection = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(__connection != NULL, _E, "Connection failed"); + + vtable.method_call = __onMethodCalled; + vtable.get_property = NULL; + vtable.set_property = NULL; + + regId = g_dbus_connection_register_object(__connection, DBUS_PATH, + __nodeInfo->interfaces[0], &vtable, NULL, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(regId > 0, _E, "Object registration failed"); + + _I("DBus connection established"); + _D("DBus name: %s", g_dbus_connection_get_unique_name(__connection)); + return true; + +CATCH: + __release(); + return false; +} + +void DBusClient::__release() +{ + if (__connection) { + g_dbus_connection_flush_sync(__connection, NULL, NULL); + g_dbus_connection_close_sync(__connection, NULL, NULL); + g_object_unref(__connection); + __connection = NULL; + } + + if (__nodeInfo) { + g_dbus_node_info_unref(__nodeInfo); + __nodeInfo = NULL; + } + + _I("DBus connection released"); +} + +int DBusClient::__request(int type, int reqId, const char *subject, const char *input, + std::string *result, std::string *outputData) +{ + _D("Requesting: %d, %d, %s", type, reqId, subject); + + if (input == NULL) + input = EMPTY_JSON_OBJECT; + + GVariant *param = g_variant_new("(isiss)", type, "", reqId, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + GVariant *response = g_dbus_connection_call_sync(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + HANDLE_GERROR(err); + IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed"); + + gint error = ERR_OPERATION_FAILED; + const gchar *resultStr = NULL; + const gchar *dataStr = NULL; + + g_variant_get(response, "(i&s&s)", &error, &resultStr, &dataStr); + + if (result && resultStr) + *result = resultStr; + + if (outputData && dataStr) + *outputData = dataStr; + + g_variant_unref(response); + + return error; +} + +int DBusClient::__request(int type, int reqId, const char* subject, const char* input) +{ + _D("Requesting: %d, %d, %s", type, reqId, subject); + + if (input == NULL) + input = EMPTY_JSON_OBJECT; + + GVariant *param = g_variant_new("(isiss)", type, "", reqId, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + g_dbus_connection_call(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err); + + if (err) { + HANDLE_GERROR(err); + return ERR_OPERATION_FAILED; + } + + return ERR_NONE; +} + +int DBusClient::__generateReqId() +{ + static GMutex mutex; + static int reqId = 0; + + ctx::ScopeMutex sm(&mutex); + + /* Overflow handling */ + if (++reqId < 0) + reqId = 1; + + return reqId; +} + +SO_EXPORT void DBusClient::addListener(std::string subject, IDBusClientListener *listener) +{ + _D("Registering the listener for '%s'", subject.c_str()); + + static GMutex mutex; + ctx::ScopeMutex sm(&mutex); + + __listenerMap[subject] = listener; +} + +SO_EXPORT int DBusClient::isSupported(std::string subject) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + return __request(REQ_SUPPORT, __generateReqId(), subject.c_str(), NULL, NULL, NULL); +} + +SO_EXPORT int DBusClient::subscribe(std::string subject, Json option, int *reqId, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + + *reqId = __generateReqId(); + + _I("[Subscribe] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string resultStr; + int error = __request(REQ_SUBSCRIBE, *reqId, subject.c_str(), option.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::unsubscribe(std::string subject, int reqId) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + _I("[Unsubscribe] ReqId: %d, Subject: %s", reqId, subject.c_str()); + + return __request(REQ_UNSUBSCRIBE, reqId, subject.c_str(), NULL, NULL, NULL); +} + +SO_EXPORT int DBusClient::read(std::string subject, Json option, int *reqId, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + + *reqId = __generateReqId(); + + _I("[Read] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string resultStr; + int error = __request(REQ_READ, *reqId, subject.c_str(), option.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::readSync(std::string subject, Json option, int *reqId, Json *outputData) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + ASSERT_NOT_NULL(outputData); + + *reqId = __generateReqId(); + + _I("[ReadSync] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string output; + int error = __request(REQ_READ_SYNC, *reqId, subject.c_str(), option.str().c_str(), NULL, &output); + + *outputData = output; + + _D("Error: %#x", error); + _SD("Data: %s", output.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::write(std::string subject, Json inputData) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + int reqId = __generateReqId(); + + _I("[Write] ReqId: %d, Subject: %s", reqId, subject.c_str()); + _SD("Data: %s", inputData.str().c_str()); + + int error = __request(REQ_WRITE, reqId, subject.c_str(), inputData.str().c_str()); + _D("Error: %#x", error); + + return error; +} + +SO_EXPORT int DBusClient::write(std::string subject, Json inputData, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + int reqId = __generateReqId(); + + _I("[Write with reply] ReqId: %d, Subject: %s", reqId, subject.c_str()); + _SD("Data: %s", inputData.str().c_str()); + + std::string resultStr; + int error = __request(REQ_WRITE, reqId, subject.c_str(), inputData.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::call(const char *method) +{ + int ret = ERR_NONE; + GError *err = NULL; + + GVariant *response = g_dbus_connection_call_sync(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + method, NULL, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + + if (response) { + g_variant_unref(response); + return ERR_NONE; + } + + ret = ERR_OPERATION_FAILED; + if (err->code == G_DBUS_ERROR_ACCESS_DENIED) + ret = ERR_PERMISSION_DENIED; + + HANDLE_GERROR(err); + return ret; +} diff --git a/common/client/IDBusClientListener.cpp b/common/client/IDBusClientListener.cpp new file mode 100644 index 0000000..0da37b2 --- /dev/null +++ b/common/client/IDBusClientListener.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +using namespace ctx; + +IDBusClientListener::~IDBusClientListener() +{ +} diff --git a/common/include/ContextProvider.h b/common/include/ContextProvider.h new file mode 100644 index 0000000..2d89262 --- /dev/null +++ b/common/include/ContextProvider.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_CONTEXT_PROVIDER_H_ +#define _CONTEXT_CONTEXT_PROVIDER_H_ + +#include +#include +#include + +#define OPS_SUBSCRIBE 1 +#define OPS_READ 2 +#define OPS_WRITE 4 + +namespace ctx { + + class IContextManager; + + class SO_EXPORT ContextProvider { + public: + virtual ~ContextProvider(); + + const char* getSubject(); + + virtual bool isSupported(); + virtual int subscribe(Json option, Json *requestResult); + virtual int unsubscribe(Json option); + virtual int read(Json option, Json *requestResult); + virtual int write(Json data, Json *requestResult); + + virtual void getPrivilege(std::vector &privilege); + + virtual bool unloadable(); + + bool publish(Json option, int error, Json dataUpdated); + bool replyToRead(Json option, int error, Json dataRead); + + protected: + ContextProvider(const char *subject); + + private: + static void __setContextManager(IContextManager *contextMgr); + + static IContextManager *__contextMgr; + + const char *__subject; + + friend class ContextManager; + + }; /* class ContextProvider */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_CONTEXT_PROVIDER_H_ */ diff --git a/common/include/CustomRegister.h b/common/include/CustomRegister.h new file mode 100644 index 0000000..5134613 --- /dev/null +++ b/common/include/CustomRegister.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_CUSTOM_REGISTER_H_ +#define _CONTEXT_CUSTOM_REGISTER_H_ + +#include +#include + +namespace ctx { + + class ICustomRegister; + + class SO_EXPORT CustomRegister { + public: + virtual ~CustomRegister(); + + bool registerCustomProvider(const char* subject, int operation, Json attribute, Json option, const char* owner = NULL); + bool unregisterCustomProvider(const char* subject); + + protected: + CustomRegister(); + + private: + static void __setCustomRegister(ICustomRegister *customRegister); + + static ICustomRegister *__customRegister; + + friend class ContextManager; + + }; /* class CustomRegister */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_CUSTOM_REGISTER_H_ */ diff --git a/common/include/DBusClient.h b/common/include/DBusClient.h new file mode 100644 index 0000000..c865e80 --- /dev/null +++ b/common/include/DBusClient.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_DBUS_CLIENT_H__ +#define __CONTEXT_DBUS_CLIENT_H__ + +#include +#include +#include +#include +#include +#include + +namespace ctx { + + class DBusClient { + public: + DBusClient(); + ~DBusClient(); + + void addListener(std::string subject, IDBusClientListener *listener); + + int isSupported(std::string subject); + + int subscribe(std::string subject, Json option, int *reqId, Json *result); + int unsubscribe(std::string subject, int reqId); + int read(std::string subject, Json option, int *reqId, Json *result); + int readSync(std::string subject, Json option, int *reqId, Json *outputData); + int write(std::string subject, Json inputData); + int write(std::string subject, Json inputData, Json *result); + + int call(const char *method); + + private: + static void __onMethodCalled(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer userData); + + bool __init(); + void __release(); + int __request(int type, int reqId, const char *subject, const char *input, + std::string *result, std::string *outputData); + int __request(int type, int reqId, const char *subject, const char *input); + int __generateReqId(); + + + static GDBusConnection *__connection; + static GDBusNodeInfo *__nodeInfo; + static std::atomic_int __instanceCount; + static std::map __listenerMap; + + }; /* class ctx::DBusClient */ + +} /* namespace ctx */ + +#endif // __CONTEXT_DBUS_CLIENT_H__ diff --git a/common/include/DBusSignalWatcher.h b/common/include/DBusSignalWatcher.h new file mode 100644 index 0000000..6b035ed --- /dev/null +++ b/common/include/DBusSignalWatcher.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DBUS_SIGNAL_WATCHER_H_ +#define _CONTEXT_DBUS_SIGNAL_WATCHER_H_ + +#include +#include +#include + +namespace ctx { + + enum class DBusType { + SYSTEM, + SESSION + }; + + class DBusSignalWatcher { + public: + DBusSignalWatcher(DBusType type); + ~DBusSignalWatcher(); + + /** + * @brief Subscribes to signals. + * @param[in] sender Sensor name to match on. NULL to listen from all senders. + * @param[in] path Object path to match on. NULL to match on all object paths. + * @param[in] iface D-Bus interface name to match on. NULL to match on all interfaces. + * @param[in] name D-Bus signal name to match on. NULL to match on all signals. + * @param[in] listener Listener object to receive matching signals. + * @return A subscription identifier that can be used with signal_unsubscribe(). + * If failed, a negative value. + */ + int64_t watch(const char *sender, const char *path, const char *iface, const char *name, IDBusSignalListener *listener); + void unwatch(int64_t signal_id); + + private: + void __openBus(GBusType type, GDBusConnection *&bus); + void __closeBus(GDBusConnection *&bus); + + static GMutex __mutex; + static unsigned int __systemBusCnt; + static unsigned int __sessionBusCnt; + static GDBusConnection *__systemBus; + static GDBusConnection *__sessionBus; + + DBusType __busType; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_DBUS_SIGNAL_WATCHER_H_ */ diff --git a/common/include/DBusTypes.h b/common/include/DBusTypes.h new file mode 100644 index 0000000..1921e30 --- /dev/null +++ b/common/include/DBusTypes.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DBUS_TYPES_H_ +#define _CONTEXT_DBUS_TYPES_H_ + +#define DBUS_DEST "org.tizen.context" +#define DBUS_PATH "/org/tizen/context" +#define DBUS_IFACE "org.tizen.context" +#define DBUS_TIMEOUT 3000 + +#define METHOD_REQUEST "Request" +#define METHOD_RESPOND "Respond" +#define SIGNAL_LAUNCHED "Launched" + +#define METHOD_CHK_PRIV "ChkPriv" +#define METHOD_CHK_PRIV_APPLAUNCH METHOD_CHK_PRIV "AppLaunch" +#define METHOD_CHK_PRIV_CALL METHOD_CHK_PRIV "Call" +#define METHOD_CHK_PRIV_NOTIFICATION METHOD_CHK_PRIV "Notification" + +#define ARG_REQTYPE "type" +#define ARG_COOKIE "cookie" +#define ARG_REQID "req_id" +#define ARG_SUBJECT "subject" +#define ARG_INPUT "input" + +#define ARG_RESULT_ERR "r_err" +#define ARG_RESULT_ADD "r_add" +#define ARG_OUTPUT "output" + +enum RequestType { + REQ_SUBSCRIBE = 1, + REQ_UNSUBSCRIBE, + REQ_READ, + REQ_READ_SYNC, + REQ_WRITE, + REQ_SUPPORT, +}; + +#endif /* _CONTEXT_DBUS_TYPES_H_ */ diff --git a/common/include/DatabaseManager.h b/common/include/DatabaseManager.h new file mode 100644 index 0000000..a0fe0ad --- /dev/null +++ b/common/include/DatabaseManager.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DATABASE_MANAGER_H_ +#define _CONTEXT_DATABASE_MANAGER_H_ + +#include + +namespace ctx { + + class DatabaseManager { + public: + DatabaseManager(); + ~DatabaseManager(); + + /** + * @brief Creates a table if not exists. Async. + * @details The column @c rowId is created by default, thus do not use the same column name. + * It is the primary of the auto-increment integer type. + * @param[in] queryId This number will be returned through IDatabaseListener::onTableCreated(). + * @param[in] tableName A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + * @param[in] listener A listener object to receive the result. Allows NULL. + */ + bool createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option = NULL, IDatabaseListener *listener = NULL); + + /** + * @brief Inserts a record to a table. Async. + * @param[in] queryId This number will be returned through IDatabaseListener::onInserted(). + * @param[in] tableName A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[in] listener A listener object to receive the result. Allows NULL. + */ + bool insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener = NULL); + + /** + * @brief Executes a SQL query. Async. + * @param[in] queryId This number will be returned through IDatabaseListener::onExecuted(). + * @param[in] query A query to be executed. + * @param[in] listener A listener object to receive the result. + */ + bool execute(unsigned int queryId, const char *query, IDatabaseListener *listener = NULL); + + /** + * @brief creates a table if not exists. Async. + * @param[in] tableName A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + */ + bool createTableSync(const char *tableName, const char *columns, const char *option = NULL); + + /** + * @brief Inserts a record to a table. Sync. + * @attention This blocks the current thread. + * @param[in] tableName A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[out] rowId The row id of the inserted record. If fails, a negative integer. + */ + bool insertSync(const char *tableName, Json record, int64_t *rowId); + + /** + * @brief Executes a SQL query. Sync. + * @attention This blocks the current thread. + * @param[in] query A query to be executed. + * @param[out] records Query result. + */ + bool executeSync(const char *query, std::vector *records); + + private: + static bool __init(); + static void __release(); + + friend class Server; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_DATABASE_MANAGER_H_ */ diff --git a/common/include/ErrorTypes.h b/common/include/ErrorTypes.h new file mode 100644 index 0000000..1e2e81c --- /dev/null +++ b/common/include/ErrorTypes.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_ERROR_TYPES_H_ +#define _CONTEXT_ERROR_TYPES_H_ + +#include + +/* Internal Error Codes + * Please define the necessary error codes here. + * Note that, these error codes must be aligned with the error enums defined in all API headers. + */ +#define ERR_NONE TIZEN_ERROR_NONE +#define ERR_INVALID_PARAMETER TIZEN_ERROR_INVALID_PARAMETER +#define ERR_INVALID_OPERATION TIZEN_ERROR_INVALID_OPERATION +#define ERR_OUT_OF_MEMORY TIZEN_ERROR_OUT_OF_MEMORY +#define ERR_PERMISSION_DENIED TIZEN_ERROR_PERMISSION_DENIED +#define ERR_NOT_SUPPORTED TIZEN_ERROR_NOT_SUPPORTED +#define ERR_NO_DATA TIZEN_ERROR_NO_DATA +#define ERR_ALREADY_STARTED (TIZEN_ERROR_CONTEXT | 0x01) +#define ERR_NOT_STARTED (TIZEN_ERROR_CONTEXT | 0x02) +#define ERR_OUT_OF_RANGE (TIZEN_ERROR_CONTEXT | 0x03) +#define ERR_OPERATION_FAILED (TIZEN_ERROR_CONTEXT | 0x04) +#define ERR_RULE_ENABLED (TIZEN_ERROR_CONTEXT | 0x05) +#define ERR_RULE_NOT_ENABLED (TIZEN_ERROR_CONTEXT | 0x06) +#define ERR_INVALID_RULE (TIZEN_ERROR_CONTEXT | 0x07) +#define ERR_RULE_NOT_EXIST (TIZEN_ERROR_CONTEXT | 0x08) +#define ERR_DATA_EXIST (TIZEN_ERROR_CONTEXT | 0X09) +#define ERR_INVALID_DATA (TIZEN_ERROR_CONTEXT | 0X0a) + +#endif /* _CONTEXT_ERROR_TYPES_H_ */ diff --git a/common/include/EventDrivenThread.h b/common/include/EventDrivenThread.h new file mode 100644 index 0000000..54b6efa --- /dev/null +++ b/common/include/EventDrivenThread.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EVENT_DRIVEN_THREAD_H_ +#define _EVENT_DRIVEN_THREAD_H_ + +#include +#include + +class SO_EXPORT EventDrivenThread { + + typedef struct thread_info_s* thread_info_t; + +public: + virtual ~EventDrivenThread(); + + bool start(); + bool stop(); + bool isRunning(); + +protected: + EventDrivenThread(); + + virtual void onEvent(int type, void* data) = 0; + + bool pushEvent(int type, void* data); + +private: + static gpointer __threadFunc(gpointer data); + + void __run(); + + thread_info_t __threadInfo; + +}; /* class EventDrivenThread */ + +#endif /* _EVENT_DRIVEN_THREAD_H_ */ diff --git a/common/include/IContextManager.h b/common/include/IContextManager.h new file mode 100644 index 0000000..4bb2561 --- /dev/null +++ b/common/include/IContextManager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_CONTEXT_MANAGER_H_ +#define _CONTEXT_I_CONTEXT_MANAGER_H_ + +#include +#include + +namespace ctx { + + class ContextProvider; + + class SO_EXPORT IContextManager { + public: + virtual ~IContextManager(); + + virtual bool publish(const char *subject, Json &option, int error, Json &dataUpdated) = 0; + virtual bool replyToRead(const char *subject, Json &option, int error, Json &dataRead) = 0; + }; /* class IContextManager */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_CONTEXT_MANAGER_H_ */ diff --git a/common/include/ICustomRegister.h b/common/include/ICustomRegister.h new file mode 100644 index 0000000..eca3596 --- /dev/null +++ b/common/include/ICustomRegister.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_CUSTOM_REGISTER_H_ +#define _CONTEXT_I_CUSTOM_REGISTER_H_ + +#include +#include + +namespace ctx { + + class CustomRegister; + + class SO_EXPORT ICustomRegister { + public: + virtual ~ICustomRegister(){}; + + virtual bool registerCustomProvider(const char *subject, int operation, Json &attribute, Json &option, const char* owner = NULL) = 0; + virtual bool unregisterCustomProvider(const char *subject) = 0; + }; /* class ICustomRegister */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_CUSTOM_REGISTER_H_ */ diff --git a/common/include/IDBusClientListener.h b/common/include/IDBusClientListener.h new file mode 100644 index 0000000..1463425 --- /dev/null +++ b/common/include/IDBusClientListener.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ +#define _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ + +#ifndef SO_EXPORT +#define SO_EXPORT __attribute__ ((visibility("default"))) +#endif + +#include +#include + +namespace ctx { + + class SO_EXPORT IDBusClientListener { + public: + virtual ~IDBusClientListener(); + virtual void onPublish(std::string subject, int reqId, int error, Json event) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ */ diff --git a/common/include/IDBusSignalListener.h b/common/include/IDBusSignalListener.h new file mode 100644 index 0000000..ed70efe --- /dev/null +++ b/common/include/IDBusSignalListener.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ +#define _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ + +#include +#include + +namespace ctx { + + class SO_EXPORT IDBusSignalListener { + public: + virtual ~IDBusSignalListener(); + + /** + * @brief Called when receiving a signal. + * @param[in] sender The unique bus name of the sender of the signal. + * @param[in] path The object path that the signal was emitted on. + * @param[in] iface The name of the interface. + * @param[in] name The name of the signal. + * @param[in] param A GVariant tuple with parameters of the signal. + */ + virtual void onSignal(const char *sender, const char *path, const char *iface, const char *name, GVariant *param) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ */ diff --git a/common/include/IDatabaseListener.h b/common/include/IDatabaseListener.h new file mode 100644 index 0000000..96205cb --- /dev/null +++ b/common/include/IDatabaseListener.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DATABASE_LISTENER_H_ +#define _CONTEXT_I_DATABASE_LISTENER_H_ + +#include +#include +#include + +namespace ctx { + + class SO_EXPORT IDatabaseListener { + public: + virtual ~IDatabaseListener(); + + /** + * @brief Called when a table creation is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::createTable(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + */ + virtual void onTableCreated(unsigned int queryId, int error) = 0; + + /** + * @brief Called when a record insertion is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::insert(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] rowId The row id of the inserted record. + */ + virtual void onInserted(unsigned int queryId, int error, int64_t rowId) = 0; + + /** + * @brief Called when a query execution is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::execute(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] records Data records retreived. + */ + virtual void onExecuted(unsigned int queryId, int error, std::vector& records) = 0; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_DATABASE_LISTENER_H_ */ diff --git a/common/include/ITimerListener.h b/common/include/ITimerListener.h new file mode 100644 index 0000000..a8bbe9f --- /dev/null +++ b/common/include/ITimerListener.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_TIMER_LISTENER_H_ +#define _CONTEXT_I_TIMER_LISTENER_H_ + +#include + +namespace ctx { + + class SO_EXPORT ITimerListener { + public: + virtual ~ITimerListener(); + + /** + * @brief Called when a timer is expired. + * @param[in] timer_id The expired timers' ID + * @return @c true, if the timer needs to be repeated.@n + * @c false, if the timer does not need to be repeated anymore. + */ + virtual bool onTimerExpired(int timerId) = 0; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_TIMER_LISTENER_H_ */ diff --git a/common/include/Json.h b/common/include/Json.h new file mode 100644 index 0000000..31a9d11 --- /dev/null +++ b/common/include/Json.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_JSON_H_ +#define _CONTEXT_JSON_H_ + +#include +#include +#include +#include + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while (0) + +#define EMPTY_JSON_OBJECT "{}" + +namespace ctx { + + class Json { + public: + Json(); + Json(const char *s); + Json(const std::string &s); + + /* This Json(const Json &j) only copies the reference to the underlying Json node. + * Therefore, changes applied to a Json object affect the other. + * If you need to create a 'real' copy of a Json, which can be manipulated separately, + * utilize the str() function, e.g., ctx::Json copy(original.str()); + */ + Json(const Json &j); + + ~Json(); + + Json& operator=(const char *s); + Json& operator=(const std::string &s); + + /* This operator=(const Json &j) only copies the reference to the underlying Json node. + * Therefore, changes applied to a Json object affect the other. + * If you need to create a 'real' copy of a Json, which can be manipulated separately, + * utilize the str() function, e.g., ctx::Json copy = original.str(); + */ + Json& operator=(const Json &j); + + bool operator==(const Json &rhs); + bool operator!=(const Json &rhs); + + std::string str(); + + bool getKeys(std::list *list); + bool valid(); + + bool set(const char *path, const char *key, Json &val); + bool set(const char *path, const char *key, int val); + bool set(const char *path, const char *key, int64_t val); + bool set(const char *path, const char *key, double val); + bool set(const char *path, const char *key, std::string val); + bool set(const char *path, const char *key, GVariant *val); + + bool get(const char *path, const char *key, Json *val); + bool get(const char *path, const char *key, int *val); + bool get(const char *path, const char *key, int64_t *val); + bool get(const char *path, const char *key, double *val); + bool get(const char *path, const char *key, std::string *val); + bool get(const char *path, const char *key, GVariant **val); + + bool remove(const char *path, const char *key); + + /* Array operations */ + int getSize(const char *path, const char *key); + + bool append(const char *path, const char *key, Json &val); + bool append(const char *path, const char *key, int val); + bool append(const char *path, const char *key, int64_t val); + bool append(const char *path, const char *key, double val); + bool append(const char *path, const char *key, std::string val); + + bool setAt(const char *path, const char *key, int index, Json &val); + bool setAt(const char *path, const char *key, int index, int val); + bool setAt(const char *path, const char *key, int index, int64_t val); + bool setAt(const char *path, const char *key, int index, double val); + bool setAt(const char *path, const char *key, int index, std::string val); + + bool getAt(const char *path, const char *key, int index, Json *val); + bool getAt(const char *path, const char *key, int index, int *val); + bool getAt(const char *path, const char *key, int index, int64_t *val); + bool getAt(const char *path, const char *key, int index, double *val); + bool getAt(const char *path, const char *key, int index, std::string *val); + + private: + typedef struct _JsonNode json_node_t; + json_node_t *__jsonNode; + + void __parse(const char *s); + void __release(); + char* __strDup(); + + /* For json vs json comparison */ + bool __getMembers(json_node_t *node, std::list &list); + bool __nodeEq(json_node_t *lhs, json_node_t *rhs); + bool __valueEq(json_node_t *lhs, json_node_t *rhs); + bool __objectEq(json_node_t *lhs, json_node_t *rhs); + bool __arrayEq(json_node_t *lhs, json_node_t *rhs); + }; + +} /* namespace ctx */ + +#endif // _CONTEXT_JSON_H_ diff --git a/common/include/MyPlaceTypes.h b/common/include/MyPlaceTypes.h new file mode 100644 index 0000000..2593649 --- /dev/null +++ b/common/include/MyPlaceTypes.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_MYPLACE_TYPES_H_ +#define _CONTEXT_MYPLACE_TYPES_H_ + +#include +#include +#include +#include + +#define PLACE_DETECTION_SUBJECT SUBJ_PLACE_DETECTION + +#define PLACE_DETECTION_REQUEST "Request" +#define PLACE_DETECTION_REQUEST_CONSENT "UserConsent" +#define PLACE_DETECTION_REQUEST_LIST "PlacesList" + +#define MYPLACE_SETTING_VALUE_TRUE "true" +#define MYPLACE_SETTING_VALUE_FALSE "false" + +#define PLACE_DATA_READ "PlacesList" +#define PLACE_CATEG_ID "CategId" +#define PLACE_CATEG_CONFIDENCE "CategConfidence" +#define PLACE_NAME "Name" +#define PLACE_LOCATION "Location" +#define PLACE_LOCATION_LATITUDE "Latitude" +#define PLACE_LOCATION_LONGITUDE "Longitude" +#define PLACE_LOCATION_ACCURACY "Accuracy" +#define PLACE_WIFI_APS "WifiAPs" +#define PLACE_WIFI_AP_MAC "Mac" +#define PLACE_WIFI_AP_NETWORK_NAME "Network" +#define PLACE_CREATE_DATE "CreateDate" + +namespace ctx { + + enum PlaceCategId { + PLACE_CATEG_ID_NONE = 0, + PLACE_CATEG_ID_HOME = 1, + PLACE_CATEG_ID_WORK = 2, + PLACE_CATEG_ID_OTHER = 3 + }; + + struct Location { + double latitude; + double longitude; + double accuracy; // [m] + + Location(double latitude_ = 0.0, double longitude_ = 0.0, double accuracy_ = -1.0) + : latitude(latitude_), longitude(longitude_), accuracy(accuracy_) {} + + }; /* struct Location */ + + typedef float confidence_t; + + class Place { + + public: + PlaceCategId categId; // category of a place (work/home/other) + confidence_t categConfidence; // confidence of the above category - between [0,1] + std::string name; // for now: "work"/"home"/"other" + bool locationValid; + Location location; // makes sense if locationValid == true; + std::map wifiAps; // WiFi APs MAC addresses to corresponding network name map + time_t createDate; // The last update time of this place + + }; /* class Place */ + + bool operator==(const Place &p1, const Place &p2); + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_MYPLACE_TYPES_H_ */ diff --git a/common/include/ProviderTypes.h b/common/include/ProviderTypes.h new file mode 100644 index 0000000..d720922 --- /dev/null +++ b/common/include/ProviderTypes.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_PROVIDER_TYPES_H_ +#define _CONTEXT_PROVIDER_TYPES_H_ + +/* Privileges */ +#define PRIV_ALARM "alarm.set" +#define PRIV_NETWORK "network.get" +#define PRIV_TELEPHONY "telephony" +#define PRIV_MESSAGE "message.read" +#define PRIV_CONTACT "contact.read" +#define PRIV_LOCATION "location" +#define PRIV_APP_HISTORY "apphistory.read" +#define PRIV_MEDIA_HISTORY "mediahistory.read" +#define PRIV_CALL_HISTORY "callhistory.read" + + +/* FW-wide Data Logger Parameters */ +#define LOG_RETENTION_PERIOD 7776000 /* 90 days in secs */ + + +/* FW-wide Default Values */ +#define DEFAULT_TIME_SPAN 30 +#define DEFAULT_LIMIT 10 + + +/* Subjects */ +/* TODO: Cleanup the below namings */ +#define SUBJ_STATE_BATTERY "system/battery" +#define SUBJ_STATE_CHARGER "system/charger" +#define SUBJ_STATE_HEADPHONE "system/headphone" +#define SUBJ_STATE_WIFI "system/wifi" +#define SUBJ_STATE_USB "system/usb" +#define SUBJ_STATE_GPS "system/gps" +#define SUBJ_STATE_PSMODE "system/psmode" +#define SUBJ_STATE_ALARM "device/alarm" +#define SUBJ_STATE_TIME "device/time" + +#define SUBJ_STATE_CALL "social/call" +#define SUBJ_STATE_EMAIL "social/email" +#define SUBJ_STATE_MESSAGE "social/message" +#define SUBJ_STATE_CONTACTS "social/contacts" + +#define SUBJ_ACTIVITY "activity/" +#define SUBJ_ACTIVITY_IN_VEHICLE SUBJ_ACTIVITY "in_vehicle" +#define SUBJ_ACTIVITY_RUNNING SUBJ_ACTIVITY "running" +#define SUBJ_ACTIVITY_STATIONARY SUBJ_ACTIVITY "stationary" +#define SUBJ_ACTIVITY_WALKING SUBJ_ACTIVITY "walking" + +#define SUBJ_APP_STATS "stats/app/" +#define SUBJ_APP_LOGGER SUBJ_APP_STATS "logger" +#define SUBJ_APP_RECENTLY_USED SUBJ_APP_STATS "recently" +#define SUBJ_APP_FREQUENTLY_USED SUBJ_APP_STATS "often" +#define SUBJ_APP_RARELY_USED SUBJ_APP_STATS "rarely" +#define SUBJ_APP_PEAK_TIME SUBJ_APP_STATS "peak_time" +#define SUBJ_APP_COMMON_SETTING SUBJ_APP_STATS "setting" +#define SUBJ_APP_FREQUENCY SUBJ_APP_STATS "frequency" + +#define SUBJ_BATTERY_STATS "stats/battery/" +#define SUBJ_BATTERY_LOGGER SUBJ_BATTERY_STATS "logger" +#define SUBJ_BATTERY_USAGE SUBJ_BATTERY_STATS "history" +#define SUBJ_BATTERY_RECENT_USAGE SUBJ_BATTERY_STATS "since_last_charge" + +#define SUBJ_MEDIA_LOGGER "stats/media/logger" +#define SUBJ_MUSIC_STATS "stats/music/" +#define SUBJ_MUSIC_PEAK_TIME SUBJ_MUSIC_STATS "peak_time" +#define SUBJ_MUSIC_COMMON_SETTING SUBJ_MUSIC_STATS "setting" +#define SUBJ_MUSIC_FREQUENCY SUBJ_MUSIC_STATS "frequency" +#define SUBJ_VIDEO_STATS "stats/video/" +#define SUBJ_VIDEO_PEAK_TIME SUBJ_VIDEO_STATS "peak_time" +#define SUBJ_VIDEO_COMMON_SETTING SUBJ_VIDEO_STATS "setting" +#define SUBJ_VIDEO_FREQUENCY SUBJ_VIDEO_STATS "frequency" + +#define SUBJ_SOCIAL_STATS "stats/contact/" +#define SUBJ_SOCIAL_FREQ_ADDRESS SUBJ_SOCIAL_STATS "often" +#define SUBJ_SOCIAL_FREQUENCY SUBJ_SOCIAL_STATS "frequency" + +#define SUBJ_PLACE_GEOFENCE "place/geofence" +#define SUBJ_PLACE_DETECTION "place/myplace" + +#define SUBJ_CUSTOM "custom" + +/* Data & Option Keys */ +#define KEY_CLIENT_PKG_ID "_ClientPkgId_" /* Special key for internal use */ +#define KEY_QUERY_RESULT "QueryResult" +#define KEY_RESULT_SIZE "ResultSize" +#define KEY_COL_ROW_ID "rowId" +#define KEY_TIME_SPAN "TimeSpan" +#define KEY_START_TIME "StartTime" +#define KEY_END_TIME "EndTime" +#define KEY_LAST_TIME "LastTime" +#define KEY_TOTAL_COUNT "TotalCount" +#define KEY_TOTAL_AMOUNT "TotalAmount" +#define KEY_AVERAGE_COUNT "AvgCount" +#define KEY_DURATION "Duration" +#define KEY_TOTAL_DURATION "TotalDuration" +#define KEY_DAY_OF_WEEK "DayOfWeek" +#define KEY_HOUR_OF_DAY "HourOfDay" +#define KEY_TIME_OF_DAY "TimeOfDay" +#define KEY_TOTAL_COUNT "TotalCount" +#define KEY_APP_ID "AppId" +#define KEY_PKG_ID "PkgId" +#define KEY_AUDIO_JACK "AudioJack" +#define KEY_SYSTEM_VOLUME "SystemVolume" +#define KEY_MEDIA_VOLUME "MediaVolume" +#define KEY_BSSID "BSSID" +#define KEY_UNIV_TIME "UTC" +#define KEY_LOCAL_TIME "LocalTime" +#define KEY_RANK "Rank" +#define KEY_COMMUNICATION_TYPE "CommunicationType" +#define KEY_USED_TIME "UsedTime" + +#define KEY_EVENT "Event" +#define KEY_STATE "State" +#define KEY_TYPE "Type" +#define KEY_LEVEL "Level" +#define KEY_ACCURACY "Accuracy" +#define KEY_BSSID "BSSID" +#define KEY_MEDIUM "Medium" +#define KEY_ADDRESS "Address" +#define KEY_IS_CONNECTED "IsConnected" +#define KEY_IS_ENABLED "IsEnabled" +#define KEY_IS_CHARGING "IsCharging" +#define KEY_DETECTED "Detected" +#define KEY_DAY_OF_MONTH "DayOfMonth" +#define KEY_PLACE_ID "PlaceId" + + +/* Data & Option Values */ +#define VAL_TRUE 1 +#define VAL_FALSE 0 +#define VAL_ENTER "Enter" +#define VAL_EXIT "Exit" +#define VAL_DISABLED "Disabled" +#define VAL_CONNECTED "Connected" +#define VAL_UNCONNECTED "Unconnected" +#define VAL_SEARCHING "Searching" +#define VAL_EMPTY "Empty" +#define VAL_CRITICAL "Critical" +#define VAL_LOW "Low" +#define VAL_NORMAL "Normal" +#define VAL_HIGH "High" +#define VAL_FULL "Full" +#define VAL_HEADSET "Headset" +#define VAL_BLUETOOTH "Bluetooth" +#define VAL_IDLE "Idle" +#define VAL_CONNECTING "Connecting" +#define VAL_CONNECTED "Connected" +#define VAL_HELD "Held" +#define VAL_DIALING "Dialing" +#define VAL_VOICE "Voice" +#define VAL_VIDEO "Video" +#define VAL_SENT "Sent" +#define VAL_RECEIVED "Received" +#define VAL_SMS "SMS" +#define VAL_MMS "MMS" +#define VAL_MY_PROFILE "MyProfile" +#define VAL_PERSON "Person" +#define VAL_CHANGED "Changed" +#define VAL_DETECTED "Detected" +#define VAL_UNCERTAIN "Uncertain" +#define VAL_IN "In" +#define VAL_OUT "Out" + +#define VAL_ACTIVE VAL_CONNECTED +#define VAL_ALERTING VAL_CONNECTING +#define VAL_INCOMING VAL_CONNECTING + + +#endif /* _CONTEXT_PROVIDER_TYPES_H_ */ diff --git a/common/include/ScopeMutex.h b/common/include/ScopeMutex.h new file mode 100644 index 0000000..a17bc2a --- /dev/null +++ b/common/include/ScopeMutex.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_SCOPE_MUTEX_H_ +#define _CONTEXT_SCOPE_MUTEX_H_ + +#include + +namespace ctx { + + class ScopeMutex { + private: + GMutex *__mutex; + + public: + ScopeMutex(GMutex *m); + ~ScopeMutex(); + }; + +} /* namespace ctx */ + +#endif // _CONTEXT_SCOPE_MUTEX_H_ diff --git a/common/include/SensorRecorderTypes.h b/common/include/SensorRecorderTypes.h new file mode 100644 index 0000000..7ad6d0c --- /dev/null +++ b/common/include/SensorRecorderTypes.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SENSOR_RECORDER_TYPES_H__ +#define __CONTEXT_SENSOR_RECORDER_TYPES_H__ + +#include + +/* Sensor Subjects */ +#define SUBJ_SENSOR "sensor/" +#define SUBJ_SENSOR_HEART_RATE SUBJ_SENSOR "heart_rate" +#define SUBJ_SENSOR_PEDOMETER SUBJ_SENSOR "pedometer" +#define SUBJ_SENSOR_SLEEP_MONITOR SUBJ_SENSOR "sleep_monitor" +#define SUBJ_SENSOR_PRESSURE SUBJ_SENSOR "pressure" +#define SUBJ_SENSOR_EXERCISE SUBJ_SENSOR "exercise" + +/* Keys */ +#define KEY_SUBJECT "Subject" +#define KEY_OPERATION "Operation" +#define KEY_OPTION "Option" + +#define KEY_RETENTION "Retention" +#define KEY_INTERVAL "Interval" +#define KEY_ANCHOR "Anchor" + +#define KEY_STEPS "Steps" +#define KEY_WALK_STEPS "WalkSteps" +#define KEY_RUN_STEPS "RunSteps" +#define KEY_DISTANCE "Dist" +#define KEY_CALORIES "Cal" +#define KEY_PRESSURE "Pressure" +#define KEY_AVG_PRESSURE "AvgPressure" +#define KEY_MIN_PRESSURE "MinPressure" +#define KEY_MAX_PRESSURE "MaxPressure" +#define KEY_SLEEP_STATE KEY_STATE +#define KEY_HEART_RATE "HeartRate" + +/* Values */ +#define VAL_START "Start" +#define VAL_STOP "Stop" + +#endif /* __CONTEXT_SENSOR_RECORDER_TYPES_H__ */ diff --git a/common/include/SharedVars.h b/common/include/SharedVars.h new file mode 100644 index 0000000..4171e1a --- /dev/null +++ b/common/include/SharedVars.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_SHARED_VARS_H_ +#define _CONTEXT_SHARED_VARS_H_ + +#include +#include +#include + +namespace ctx { + + /* + * TODO: Maybe later, it would be possible to extend this to support a sort of + * 'update observation' feature, i.e., getting notifications when a variable is updated. + */ + class SharedVars { + public: + enum VarId { + WIFI_BSSID, + }; + + SharedVars(); + ~SharedVars(); + + const std::string& set(VarId id, std::string value) const; + std::string get(VarId id); + void clear(VarId id); + + private: + static GMutex __mutex; + static std::map __varsMap; + }; + +} + +#endif diff --git a/common/include/TimerManager.h b/common/include/TimerManager.h new file mode 100644 index 0000000..d8338f2 --- /dev/null +++ b/common/include/TimerManager.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TIMER_H_ +#define _CONTEXT_TIMER_H_ + +#include +#include +#include +#include +#include + +#define DAYS_PER_WEEK 7 +#define DOW_MON "Mon" +#define DOW_TUE "Tue" +#define DOW_WED "Wed" +#define DOW_THU "Thu" +#define DOW_FRI "Fri" +#define DOW_SAT "Sat" +#define DOW_SUN "Sun" +#define DOW_WEEKDAY "Weekday" +#define DOW_WEEKEND "Weekend" +#define DOW_EVERYDAY "Everyday" + +namespace ctx { + + enum class DayOfWeek { + SUN = 0x01, + MON = 0x02, + TUE = 0x04, + WED = 0x08, + THU = 0x10, + FRI = 0x20, + SAT = 0x40, + WEEKDAY = MON | TUE | WED | THU | FRI, + WEEKEND = SAT | SUN, + EVERYDAY = SUN | MON | TUE | WED | THU | FRI | SAT + }; + + class TimerManager { + public: + TimerManager(); + ~TimerManager(); + + static std::string dowToStr(int dow); + static int dowToInt(std::string dow); + + /** + * @brief Sets a repeated timer for a given interval of time (s). + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] interval Timer interval. The first timer will be expired after @c interval minutes, + * and will be repeated until the listener returns @c false. + * @param[in] listener A listner object to be notified. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int setFor(int interval, ITimerListener *listener); + + /** + * @brief Sets a timer that will be expired at a specific time, at designated days of week. + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] hour Hour + * @param[in] min Minute + * @param[in] dow The timer will expire at hour:min:00, at every day(s) of week designated here. + * @param[in] listener Listener object. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int setAt(int hour, int min, DayOfWeek dow, ITimerListener *listener); + + /** + * @brief Removes the timer specified by @c timerId. + */ + void remove(int timerId); + + private: + static int __onAlarmExpired(int alarmId, void *userdata); + + bool __init(); + void __release(); + void __remove(int timerId); + + static unsigned int __instanceCnt; + static GMutex __mutex; + static std::map> __listenerMap; + + std::set __alarms; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_TIMER_H_ */ diff --git a/common/include/TriggerRuleTypes.h b/common/include/TriggerRuleTypes.h new file mode 100644 index 0000000..886d119 --- /dev/null +++ b/common/include/TriggerRuleTypes.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TRIGGER_RULE_TYPES_H_ +#define _CONTEXT_TRIGGER_RULE_TYPES_H_ + +#include + +#define TRIG_RULE_REF_KEY_PREFIX "?" + +/* Rule Key */ +#define TRIG_RULE_KEY_DESCRIPTION "description" +#define TRIG_RULE_KEY_EVENT "event" +#define TRIG_RULE_KEY_CONDITION "condition" +#define TRIG_RULE_KEY_ACTION "action" +#define TRIG_RULE_KEY_OPTION "option" +#define TRIG_RULE_KEY_COMPARISON "comparison" +#define TRIG_RULE_KEY_OPERATOR "operator" +#define TRIG_RULE_KEY_VALUE "value" +#define TRIG_RULE_KEY_APP_LAUNCH "appLaunch" +#define TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL "appControl" +#define TRIG_RULE_KEY_NOTIFICATION "notification" +#define TRIG_RULE_KEY_NOTI_TITLE "title" +#define TRIG_RULE_KEY_NOTI_CONTENT "content" +#define TRIG_RULE_KEY_NOTI_ICON_PATH "iconPath" +#define TRIG_RULE_KEY_NOTI_APP_CONTROL "appControl" +#define TRIG_RULE_KEY_DBUS_CALL "dbusCall" +#define TRIG_RULE_KEY_DBUS_NAME "name" +#define TRIG_RULE_KEY_DBUS_OBJECT "object" +#define TRIG_RULE_KEY_DBUS_INTERFACE "interafce" +#define TRIG_RULE_KEY_DBUS_METHOD "method" +#define TRIG_RULE_KEY_DBUS_PARAMETER "parameter" + +/* Internal Rule Key */ +#define _TRIG_RULE_KEY_EXTRA "_extra" +#define _TRIG_RULE_KEY_RULE_LOGICAL_OP "_ruleOp" +#define _TRIG_RULE_KEY_EVENT_LOGICAL_OP "_eventOp" +#define _TRIG_RULE_KEY_CONDITION_LOGICAL_OP "_condOp" + +/* Comparison Operator */ +#define TRIG_RULE_OP_EQUAL_TO "==" +#define TRIG_RULE_OP_NOT_EQUAL_TO "!=" +#define TRIG_RULE_OP_GREATER_THAN ">" +#define TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO ">=" +#define TRIG_RULE_OP_LESS_THAN "<" +#define TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO "<=" +#define TRIG_RULE_OP_ONE_OF "oneOf" +#define TRIG_RULE_OP_NONE_OF "noneOf" +#define TRIG_RULE_OP_IN "in" +#define TRIG_RULE_OP_NOT_IN "notIn" +//#define TRIG_RULE_OP_CONTAIN "contain" + +/* Old Rule Keys */ +#define TRIG_RULE_LOGICAL_CONJUNCTION "and" +#define TRIG_RULE_LOGICAL_DISJUNCTION "or" + +#endif /* _CONTEXT_TRIGGER_RULE_TYPES_H_ */ diff --git a/common/include/TriggerTypes.h b/common/include/TriggerTypes.h new file mode 100644 index 0000000..85f688b --- /dev/null +++ b/common/include/TriggerTypes.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TRIGGER_TYPES_H_ +#define _CONTEXT_TRIGGER_TYPES_H_ + +/* Request Subject */ +#define SUBJ_TRIGGER_ADD "trigger/add" +#define SUBJ_TRIGGER_REMOVE "trigger/remove" +#define SUBJ_TRIGGER_ENABLE "trigger/enable" +#define SUBJ_TRIGGER_DISABLE "trigger/disable" +#define SUBJ_TRIGGER_GET "trigger/get" +#define SUBJ_TRIGGER_GET_RULE_IDS "trigger/getRuleIds" +#define SUBJ_TRIGGER_GET_TEMPLATE "trigger/tepmlate/get" +#define SUBJ_TRIGGER_CUSTOM "custom" + +/* Response Types */ +#define TRIG_KEY_RULE_ID "id" +#define TRIG_KEY_ENABLED_IDS "enabledRuleIds" +#define TRIG_KEY_DISABLED_IDS "disabledRuleIds" + +/* Template Types */ +#define TRIG_TMPL_KEY_SUBJECT "subject" +#define TRIG_TMPL_KEY_OWNER "owner" +#define TRIG_TMPL_KEY_OPTION "options" +#define TRIG_TMPL_KEY_ATTRIBUTE "attributes" +#define TRIG_TMPL_KEY_MIN "minimum" +#define TRIG_TMPL_KEY_MAX "maximum" +#define TRIG_TMPL_KEY_TYPE "type" +#define TRIG_TMPL_TYPE_INTEGER "integer" +#define TRIG_TMPL_TYPE_STRING "string" +#define TRIG_TMPL_TYPE_ENUM "enum" +#define TRIG_TMPL_TYPE_DOUBLE "double" + +/* Custom Request Types */ +#define TRIG_CUSTOM_PREFIX SUBJ_TRIGGER_CUSTOM +#define TRIG_CUSTOM_KEY_REQ "req" +#define TRIG_CUSTOM_REQ_ADD "add" +#define TRIG_CUSTOM_REQ_REMOVE "remove" +#define TRIG_CUSTOM_REQ_PUBLISH "publish" + +/* Custom Fact Types */ +#define TRIG_CUSTOM_KEY_NAME "name" +#define TRIG_CUSTOM_KEY_FACT "fact" + +/* Etc */ +#define TRIG_SUBJECT_SEPERATOR "/" + +#endif /* _CONTEXT_TRIGGER_TYPES_H_ */ diff --git a/common/include/Types.h b/common/include/Types.h new file mode 100644 index 0000000..aaadd57 --- /dev/null +++ b/common/include/Types.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TYPES_H_ +#define _CONTEXT_TYPES_H_ + +#include +#include + +#define SO_EXPORT __attribute__ ((visibility("default"))) + +/* Logging and Error Handling */ +#define _I SLOGI +#define _D SLOGD +#define _W SLOGW +#define _E SLOGE +#define _SI SECURE_SLOGI +#define _SD SECURE_SLOGD +#define _SW SECURE_LOGW +#define _SE SECURE_SLOGE + +/* Color code for dlog */ +#define RED(X) "\033[0;31m" X "\033[0m" +#define GREEN(X) "\033[0;32m" X "\033[0m" +#define YELLOW(X) "\033[0;33m" X "\033[0m" +#define BLUE(X) "\033[0;34m" X "\033[0m" +#define PURPLE(X) "\033[0;35m" X "\033[0m" +#define CYAN(X) "\033[0;36m" X "\033[0m" + +#define REPLACE_NULL(X) ((X) ? (X) : "") +#define STR_EQ(X, Y) (g_strcmp0((X), (Y)) == 0) + +#define IF_FAIL_RETURN_TAG(cond, ret, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return ret; } } while (0) + +#define IF_FAIL_RETURN(cond, ret) \ + do { if (!(cond)) { return ret; } } while (0) + +#define IF_FAIL_VOID_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return; } } while (0) + +#define IF_FAIL_VOID(cond) \ + do { if (!(cond)) { return; } } while (0) + +#define IF_FAIL_CATCH_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); goto CATCH; } } while (0) + +#define IF_FAIL_CATCH(cond) \ + do { if (!(cond)) { goto CATCH; } } while (0) + +#define IS_FAILED(X) ((X) != ERR_NONE) + +#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed") +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, ERR_INVALID_PARAMETER, _E, "Parameter null") + +#define HANDLE_GERROR(Err) \ + do { if ((Err)) { _E("GError: %s", Err->message); g_error_free(Err); Err = NULL; } } while (0) + +#endif /* _CONTEXT_TYPES_H_ */ diff --git a/common/server/CMakeLists.txt b/common/server/CMakeLists.txt new file mode 100644 index 0000000..31c854b --- /dev/null +++ b/common/server/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-server") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +TARGET_LINK_LIBRARIES(${target} ctx-shared) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/server/ContextProvider.cpp b/common/server/ContextProvider.cpp new file mode 100644 index 0000000..ac2758c --- /dev/null +++ b/common/server/ContextProvider.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace ctx; + +IContextManager *ContextProvider::__contextMgr = NULL; + +ContextProvider::ContextProvider(const char *subject) : + __subject(subject) +{ +} + +ContextProvider::~ContextProvider() +{ +} + +const char* ContextProvider::getSubject() +{ + return __subject; +} + +bool ContextProvider::isSupported() +{ + return true; +} + +int ContextProvider::subscribe(Json option, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::unsubscribe(Json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::read(Json option, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::write(Json data, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +void ContextProvider::getPrivilege(std::vector &privilege) +{ +} + +bool ContextProvider::unloadable() +{ + return true; +} + +bool ContextProvider::publish(Json option, int error, Json dataUpdated) +{ + return __contextMgr->publish(__subject, option, error, dataUpdated); +} + +bool ContextProvider::replyToRead(Json option, int error, Json dataRead) +{ + return __contextMgr->replyToRead(__subject, option, error, dataRead); +} + +void ContextProvider::__setContextManager(IContextManager *contextMgr) +{ + __contextMgr = contextMgr; +} diff --git a/common/server/CustomRegistser.cpp b/common/server/CustomRegistser.cpp new file mode 100644 index 0000000..313d685 --- /dev/null +++ b/common/server/CustomRegistser.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace ctx; + +ICustomRegister *CustomRegister::__customRegister = NULL; + +CustomRegister::CustomRegister() +{ +} + +CustomRegister::~CustomRegister() +{ +} + +bool CustomRegister::registerCustomProvider(const char* subject, int operation, Json attribute, Json option, const char* owner) +{ + return __customRegister->registerCustomProvider(subject, operation, attribute, option, owner); +} + +bool CustomRegister::unregisterCustomProvider(const char* subject) +{ + return __customRegister->unregisterCustomProvider(subject); +} + +void CustomRegister::__setCustomRegister(ICustomRegister *customRegister) +{ + __customRegister = customRegister; +} diff --git a/common/server/DBusSignalWatcher.cpp b/common/server/DBusSignalWatcher.cpp new file mode 100644 index 0000000..c03c781 --- /dev/null +++ b/common/server/DBusSignalWatcher.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using namespace ctx; + +GMutex DBusSignalWatcher::__mutex; +unsigned int DBusSignalWatcher::__systemBusCnt = 0; +unsigned int DBusSignalWatcher::__sessionBusCnt = 0; +GDBusConnection *DBusSignalWatcher::__systemBus = NULL; +GDBusConnection *DBusSignalWatcher::__sessionBus = NULL; + +static void __signal_cb(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, gpointer userdata) +{ + IF_FAIL_VOID_TAG(userdata, _W, "user_data cannot be null"); + IDBusSignalListener *listener = static_cast(userdata); + listener->onSignal(sender, path, iface, name, param); +} + +SO_EXPORT DBusSignalWatcher::DBusSignalWatcher(DBusType type) : + __busType(type) +{ + ScopeMutex sm(&__mutex); + + if (__busType == DBusType::SYSTEM) { + if (__systemBusCnt++ == 0) + __openBus(G_BUS_TYPE_SYSTEM, __systemBus); + } else { + if (__sessionBusCnt++ == 0) + __openBus(G_BUS_TYPE_SESSION, __sessionBus); + } +} + +SO_EXPORT DBusSignalWatcher::~DBusSignalWatcher() +{ + ScopeMutex sm(&__mutex); + + if (__busType == DBusType::SYSTEM) { + if (--__systemBusCnt == 0) + __closeBus(__systemBus); + } else { + if (--__sessionBusCnt == 0) + __closeBus(__sessionBus); + } +} + +SO_EXPORT int64_t DBusSignalWatcher::watch(const char *sender, const char *path, const char *iface, const char *name, IDBusSignalListener *listener) +{ + GDBusConnection *bus = (__busType == DBusType::SYSTEM ? __systemBus : __sessionBus); + IF_FAIL_RETURN_TAG(bus, -1, _E, "Dbus not connected"); + + guint sid = g_dbus_connection_signal_subscribe(bus, + sender, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, + __signal_cb, listener, NULL); + + return static_cast(sid); +} + +SO_EXPORT void DBusSignalWatcher::unwatch(int64_t signal_id) +{ + IF_FAIL_VOID_TAG(signal_id >= 0, _W, "Invalid parameter"); + GDBusConnection *bus = (__busType == DBusType::SYSTEM ? __systemBus : __sessionBus); + g_dbus_connection_signal_unsubscribe(bus, static_cast(signal_id)); +} + +void DBusSignalWatcher::__openBus(GBusType type, GDBusConnection *&bus) +{ + GError *gerr = NULL; + gchar *addr = g_dbus_address_get_for_bus_sync(type, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_VOID(addr); + + bus = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_VOID(bus); + + _D("%s Bus Connected", type == G_BUS_TYPE_SYSTEM ? "SYSTEM" : "SESSION"); +} + +void DBusSignalWatcher::__closeBus(GDBusConnection *&bus) +{ + IF_FAIL_VOID(bus); + + g_dbus_connection_close_sync(bus, NULL, NULL); + g_object_unref(bus); + bus = NULL; + + _D("%s Bus Closed", __busType == DBusType::SYSTEM ? "SYSTEM" : "SESSION"); +} diff --git a/common/server/DatabaseManager.cpp b/common/server/DatabaseManager.cpp new file mode 100644 index 0000000..008c450 --- /dev/null +++ b/common/server/DatabaseManager.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "DatabaseThread.h" + +#define CONTEXT_DB_PATH tzplatform_mkpath(TZ_USER_DB, ".context-service.db") + +using namespace ctx; + +static unsigned int __refCount = 0; +static GMutex __mutex; +static DatabaseThread *__databaseThread = NULL; + +SO_EXPORT DatabaseManager::DatabaseManager() +{ + ScopeMutex sm(&__mutex); + + if (++__refCount > 1) + return; + + if (!__databaseThread->start()) + _E("Failed to start Database thread"); +} + +SO_EXPORT DatabaseManager::~DatabaseManager() +{ + ScopeMutex sm(&__mutex); + + if (--__refCount > 0) + return; + + __databaseThread->stop(); +} + +SO_EXPORT bool DatabaseManager::__init() +{ + __databaseThread = new(std::nothrow) DatabaseThread(); + IF_FAIL_RETURN_TAG(__databaseThread, false, _E, "Memory allocation failed"); + + if (__databaseThread->open(CONTEXT_DB_PATH)) + return true; + + _E("Database initialization failed"); + delete __databaseThread; + __databaseThread = NULL; + return false; +} + +SO_EXPORT void DatabaseManager::__release() +{ + if (!__databaseThread) + return; + + __databaseThread->stop(); + __databaseThread->close(); + + delete __databaseThread; + __databaseThread = NULL; +} + +SO_EXPORT bool DatabaseManager::createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option, IDatabaseListener *listener) +{ + return __databaseThread->createTable(queryId, tableName, columns, option, listener); +} + +SO_EXPORT bool DatabaseManager::insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener) +{ + return __databaseThread->insert(queryId, tableName, record, listener); +} + +SO_EXPORT bool DatabaseManager::execute(unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + return __databaseThread->execute(queryId, query, listener); +} + +SO_EXPORT bool DatabaseManager::createTableSync(const char *tableName, const char *columns, const char *option) +{ + return __databaseThread->createTableSync(tableName, columns, option); +} + +SO_EXPORT bool DatabaseManager::insertSync(const char *tableName, Json record, int64_t *rowId) +{ + return __databaseThread->insertSync(tableName, record, rowId); +} + +SO_EXPORT bool DatabaseManager::executeSync(const char *query, std::vector *records) +{ + return __databaseThread->executeSync(query, records); +} diff --git a/common/server/DatabaseThread.cpp b/common/server/DatabaseThread.cpp new file mode 100644 index 0000000..66e622e --- /dev/null +++ b/common/server/DatabaseThread.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "DatabaseThread.h" + +using namespace ctx; + +DatabaseThread::DatabaseThread() : + __databaseHandle(NULL) +{ + g_mutex_init(&__execMutex); +} + +DatabaseThread::~DatabaseThread() +{ + g_mutex_clear(&__execMutex); +} + +bool DatabaseThread::open(const char *dbPath) +{ + sqlite3 *db = NULL; + char *err = NULL; + int ret; + + ret = sqlite3_open(dbPath, &db); + IF_FAIL_RETURN_TAG(ret == SQLITE_OK, false, _E, "Path: %s / Error: %s", dbPath, sqlite3_errmsg(db)); + + ret = sqlite3_exec(db, "PRAGMA journal_mode = WAL", NULL, NULL, &err); + if (ret != SQLITE_OK) { + _E("Setting journal mode failed: %s", err); + sqlite3_free(err); + sqlite3_close(db); + return false; + } + + __databaseHandle = db; + return true; +} + +void DatabaseThread::close() +{ + sqlite3_close(__databaseHandle); +} + +bool DatabaseThread::createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option, IDatabaseListener *listener) +{ + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->query = __composeCreate(tableName, columns, option); + info->id = queryId; + info->listener = listener; + + if (!pushEvent(QUERY_CREATE_TABLE, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener) +{ + std::string query = __composeInsert(tableName, record); + IF_FAIL_RETURN(!query.empty(), false); + + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->query = query; + info->id = queryId; + info->listener = listener; + + if (!pushEvent(QUERY_INSERT, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::execute(unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + IF_FAIL_RETURN(query, false); + + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->id = queryId; + info->query = query; + info->listener = listener; + + if (!pushEvent(QUERY_EXECUTE, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::createTableSync(const char *tableName, const char *columns, const char *option) +{ + std::string query = __composeCreate(tableName, columns, option); + IF_FAIL_RETURN(!query.empty(), false); + _SD("SQL: %s", query.c_str()); + + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query.c_str(), NULL, NULL, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + return true; +} + +bool DatabaseThread::insertSync(const char *tableName, Json record, int64_t *rowId) +{ + IF_FAIL_RETURN(tableName && rowId, false); + + std::string query = __composeInsert(tableName, record); + IF_FAIL_RETURN(!query.empty(), false); + _SD("SQL: %s", query.c_str()); + + std::vector queryResult; + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query.c_str(), __executionCb, &queryResult, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + IF_FAIL_RETURN_TAG(!queryResult.empty(), false, _E, "No row id"); + + *rowId = -1; + queryResult.at(0).get(NULL, "seq", rowId); + _D("RowId: %lld", *rowId); + + return true; +} + +bool DatabaseThread::executeSync(const char *query, std::vector *records) +{ + IF_FAIL_RETURN(query, false); + + _SD("SQL: %s", query); + + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query, __executionCb, records, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + return true; +} + +void DatabaseThread::onEvent(int type, void* data) +{ + IF_FAIL_VOID(data); + QueryInfo *info = static_cast(data); + + __execute(static_cast(type), info->id, info->query.c_str(), info->listener); + + deleteEvent(type, data); +} + +void DatabaseThread::deleteEvent(int type, void* data) +{ + IF_FAIL_VOID(data); + QueryInfo *info = static_cast(data); + delete info; +} + +std::string DatabaseThread::__composeCreate(const char *tableName, const char *columns, const char *option) +{ + std::string query; + query = "CREATE TABLE IF NOT EXISTS "; + query = query + tableName + " (rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + columns + ")"; + if (option) { + query = query + " " + option; + } + query += ";"; + return query; +} + +std::string DatabaseThread::__composeInsert(const char *tableName, Json record) +{ + std::string cols; + std::string vals; + std::list keys; + + IF_FAIL_RETURN_TAG(record.getKeys(&keys), "", _E, "Invalid record"); + + for (auto it = keys.begin(); it != keys.end(); ++it) { + std::string s; + int64_t i; + if (record.get(NULL, (*it).c_str(), &s)) { + cols = cols + *it + ","; + + char* buf = sqlite3_mprintf("%Q", s.c_str()); + IF_FAIL_RETURN_TAG(buf, "", _E, "Memory allocation failed"); + + vals = vals + buf + ","; + sqlite3_free(buf); + + } else if (record.get(NULL, (*it).c_str(), &i)) { + cols = cols + *it + ","; + vals = vals + std::to_string(i) + ","; + } + } + + IF_FAIL_RETURN_TAG(!cols.empty(), "", _E, "Invalid record"); + + cols.erase(cols.size() - 1); + vals.erase(vals.size() - 1); + + std::string query = "INSERT INTO "; + query = query + tableName + " (" + cols + ") VALUES (" + vals + ");"; + query = query + "SELECT seq FROM sqlite_sequence WHERE name='" + tableName + "';"; + + return query; +} + +void DatabaseThread::__execute(QueryType type, unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + _SD("SQL(%d): %s", queryId, query); + + std::vector *queryResult = new(std::nothrow) std::vector; + IF_FAIL_VOID_TAG(queryResult, _E, "Memory allocation failed"); + + char *err = NULL; + int ret; + + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query, __executionCb, queryResult, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + __dispatchResult(type, queryId, listener, ERR_OPERATION_FAILED, queryResult); + return; + } + + __dispatchResult(type, queryId, listener, ERR_NONE, queryResult); + return; +} + +void DatabaseThread::__dispatchResult(QueryType type, unsigned int queryId, IDatabaseListener *listener, int error, std::vector *result) +{ + QueryResult *qr = new(std::nothrow) QueryResult(); + IF_FAIL_VOID_TAG(qr, _E, "Memory allocation failed"); + + qr->type = type; + qr->id = queryId; + qr->listener = listener; + qr->error = error; + qr->result = result; + + g_idle_add(__dispatcher, qr); +} + +int DatabaseThread::__executionCb(void *userData, int dim, char **value, char **column) +{ + IF_FAIL_RETURN(userData, 0); + + std::vector *records = static_cast*>(userData); + Json row; + bool columnNull = false; + + for (int i = 0; i < dim; ++i) { + if (!value[i]) { + columnNull = true; + _W(RED("Null columns exist")); + break; + } + + row.set(NULL, column[i], value[i]); + } + + if (!columnNull) { + records->push_back(row); + } + + return 0; +} + +gboolean DatabaseThread::__dispatcher(gpointer data) +{ + QueryResult *qr = static_cast(data); + + if (qr->listener) { + switch (qr->type) { + case QUERY_CREATE_TABLE: + qr->listener->onTableCreated(qr->id, qr->error); + break; + case QUERY_INSERT: + { + int64_t rowId = -1; + if (qr->error == ERR_NONE && qr->result && !qr->result->empty()) { + qr->result->at(0).get(NULL, "seq", &rowId); + _D("RowId: %d", rowId); + } + qr->listener->onInserted(qr->id, qr->error, rowId); + } + break; + case QUERY_EXECUTE: + qr->listener->onExecuted(qr->id, qr->error, *(qr->result)); + break; + default: + _W("Unknown query type: %d", qr->type); + } + } + + delete qr->result; + delete qr; + return FALSE; +} diff --git a/common/server/DatabaseThread.h b/common/server/DatabaseThread.h new file mode 100644 index 0000000..4e3b608 --- /dev/null +++ b/common/server/DatabaseThread.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DATABASE_THREAD_H_ +#define _CONTEXT_DATABASE_THREAD_H_ + +#include +#include +#include + +namespace ctx { + + class DatabaseThread : public EventDrivenThread { + public: + DatabaseThread(); + ~DatabaseThread(); + + bool open(const char *dbPath); + void close(); + + bool createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option = NULL, IDatabaseListener *listener = NULL); + bool insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener = NULL); + bool execute(unsigned int queryId, const char *query, IDatabaseListener *listener = NULL); + bool createTableSync(const char *tableName, const char *columns, const char *option = NULL); + bool insertSync(const char *tableName, Json record, int64_t *rowId); + bool executeSync(const char *query, std::vector *records); + + private: + enum QueryType { + QUERY_CREATE_TABLE = 1, + QUERY_INSERT, + QUERY_EXECUTE, + }; + + struct QueryInfo { + unsigned int id; + IDatabaseListener *listener; + std::string query; + }; + + struct QueryResult { + int type; + unsigned int id; + int error; + IDatabaseListener *listener; + std::vector *result; + }; + + void onEvent(int type, void* data); + void deleteEvent(int type, void* data); + + std::string __composeCreate(const char *tableName, const char *columns, const char *option); + std::string __composeInsert(const char *tableName, Json record); + + void __execute(QueryType type, unsigned int queryId, const char *query, IDatabaseListener *listener); + void __dispatchResult(QueryType type, unsigned int queryId, IDatabaseListener *listener, int error, std::vector *result); + + static int __executionCb(void *userData, int dim, char **value, char **column); + static gboolean __dispatcher(gpointer data); + + sqlite3 *__databaseHandle; + GMutex __execMutex; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_DATABASE_THREAD_H_ */ diff --git a/common/server/EventDrivenThread.cpp b/common/server/EventDrivenThread.cpp new file mode 100644 index 0000000..6718ecc --- /dev/null +++ b/common/server/EventDrivenThread.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +struct thread_info_s { + GThread *thread; + std::atomic_bool isRunning; + GAsyncQueue *eventQueue; + thread_info_s() : thread(NULL), isRunning(false), eventQueue(NULL) {} +}; + +struct event_message_s { + int type; + void* data; + bool term; + event_message_s() : type(-1), data(NULL), term(false) {} +}; + +EventDrivenThread::EventDrivenThread() : + __threadInfo(NULL) +{ +} + +EventDrivenThread::~EventDrivenThread() +{ + if (__threadInfo) { + stop(); + delete __threadInfo; + } +} + +bool EventDrivenThread::start() +{ + if (!__threadInfo) { + __threadInfo = new(std::nothrow) thread_info_s; + } + + IF_FAIL_RETURN_TAG(__threadInfo, false, _E, "Memory allocation failed"); + + if (!isRunning()) { + + __threadInfo->eventQueue = g_async_queue_new(); + + if (__threadInfo->eventQueue == NULL) { + _E("Memory allocation failed"); + return false; + } + + __threadInfo->isRunning = true; + + __threadInfo->thread = g_thread_new(NULL, __threadFunc, static_cast(this)); + + if (__threadInfo->thread == NULL) { + _E(RED("Thread creation failed")); + __threadInfo->isRunning = false; + g_async_queue_unref(__threadInfo->eventQueue); + return false; + } + + _I(PURPLE("A thread initiated")); + } + + return true; +} + +bool EventDrivenThread::stop() +{ + if (!isRunning()) + return true; + + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->term = true; + g_async_queue_push(__threadInfo->eventQueue, event); + g_thread_join(__threadInfo->thread); + g_async_queue_unref(__threadInfo->eventQueue); + return true; +} + +bool EventDrivenThread::isRunning() +{ + return __threadInfo->isRunning.load(); +} + +bool EventDrivenThread::pushEvent(int type, void* data) +{ + if (!isRunning()) + return false; + + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->type = type; + event->data = data; + g_async_queue_push(__threadInfo->eventQueue, event); + return true; +} + +gpointer EventDrivenThread::__threadFunc(gpointer data) +{ + static_cast(data)->__run(); + return NULL; +} + +void EventDrivenThread::__run() +{ + event_message_s *event = NULL; + + while (isRunning()) { + event = static_cast(g_async_queue_pop(__threadInfo->eventQueue)); + if (event->term) { + __threadInfo->isRunning = false; + } else { + onEvent(event->type, event->data); + } + delete event; + } +} diff --git a/common/server/IContextManager.cpp b/common/server/IContextManager.cpp new file mode 100644 index 0000000..1a02a57 --- /dev/null +++ b/common/server/IContextManager.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +ctx::IContextManager::~IContextManager() +{ +} diff --git a/common/server/IDBusSignalListener.cpp b/common/server/IDBusSignalListener.cpp new file mode 100644 index 0000000..7296733 --- /dev/null +++ b/common/server/IDBusSignalListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::IDBusSignalListener::~IDBusSignalListener() +{ +} diff --git a/common/server/IDatabaseListener.cpp b/common/server/IDatabaseListener.cpp new file mode 100644 index 0000000..9eea63e --- /dev/null +++ b/common/server/IDatabaseListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::IDatabaseListener::~IDatabaseListener() +{ +} diff --git a/common/server/ITimerListener.cpp b/common/server/ITimerListener.cpp new file mode 100644 index 0000000..03f7e79 --- /dev/null +++ b/common/server/ITimerListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::ITimerListener::~ITimerListener() +{ +} diff --git a/common/server/SharedVars.cpp b/common/server/SharedVars.cpp new file mode 100644 index 0000000..dbcc36d --- /dev/null +++ b/common/server/SharedVars.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#define EMPTY_STRING "" + +using namespace ctx; + +GMutex SharedVars::__mutex; +std::map SharedVars::__varsMap; + +SO_EXPORT SharedVars::SharedVars() +{ +} + +SO_EXPORT SharedVars::~SharedVars() +{ +} + +SO_EXPORT const std::string& SharedVars::set(SharedVars::VarId id, std::string value) const +{ + ScopeMutex sm(&__mutex); + _D("var[%d] = %s", id, value.c_str()); + __varsMap[id] = value; + return __varsMap[id]; +} + +SO_EXPORT std::string SharedVars::get(SharedVars::VarId id) +{ + ScopeMutex sm(&__mutex); + auto it = __varsMap.find(id); + if (it != __varsMap.end()) + return it->second; + else + return EMPTY_STRING; +} + +SO_EXPORT void SharedVars::clear(SharedVars::VarId id) +{ + ScopeMutex sm(&__mutex); + _D("Remove var[%d]", id); + __varsMap.erase(id); +} diff --git a/common/server/TimerManager.cpp b/common/server/TimerManager.cpp new file mode 100644 index 0000000..46d2179 --- /dev/null +++ b/common/server/TimerManager.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#define IDENTIFIER "contextd" +#define EMPTY_STRING "" + +using namespace ctx; + +unsigned int TimerManager::__instanceCnt = 0; +GMutex TimerManager::__mutex; +std::map> TimerManager::__listenerMap; + +SO_EXPORT TimerManager::TimerManager() +{ + ScopeMutex sm(&__mutex); + + if (__instanceCnt++ == 0) + __init(); +} + +SO_EXPORT TimerManager::~TimerManager() +{ + ScopeMutex sm(&__mutex); + + for (int i : __alarms) { + __remove(i); + } + + if (--__instanceCnt == 0) + __release(); +} + +SO_EXPORT std::string TimerManager::dowToStr(int dow) +{ + static const char *dowStr[] = { + DOW_SUN, DOW_MON, DOW_TUE, DOW_WED, DOW_THU, DOW_FRI, DOW_SAT + }; + + if (static_cast(dow) == DayOfWeek::WEEKDAY) + return DOW_WEEKDAY; + + if (static_cast(dow) == DayOfWeek::WEEKEND) + return DOW_WEEKEND; + + if (static_cast(dow) == DayOfWeek::EVERYDAY) + return DOW_EVERYDAY; + + int d = log2(static_cast(dow)); + if (d >= 0 && d < DAYS_PER_WEEK) + return dowStr[d]; + + return EMPTY_STRING; +} + +SO_EXPORT int TimerManager::dowToInt(std::string dow) +{ + if (dow == DOW_SUN) return static_cast(DayOfWeek::SUN); + if (dow == DOW_MON) return static_cast(DayOfWeek::MON); + if (dow == DOW_TUE) return static_cast(DayOfWeek::TUE); + if (dow == DOW_WED) return static_cast(DayOfWeek::WED); + if (dow == DOW_THU) return static_cast(DayOfWeek::THU); + if (dow == DOW_FRI) return static_cast(DayOfWeek::FRI); + if (dow == DOW_SAT) return static_cast(DayOfWeek::SAT); + if (dow == DOW_WEEKDAY) return static_cast(DayOfWeek::WEEKDAY); + if (dow == DOW_WEEKEND) return static_cast(DayOfWeek::WEEKEND); + if (dow == DOW_EVERYDAY) return static_cast(DayOfWeek::EVERYDAY); + return 0; +} + +SO_EXPORT int TimerManager::setFor(int interval, ITimerListener *listener) +{ + IF_FAIL_RETURN_TAG(interval > 0 && listener, -1, _E, "Invalid parameter"); + + int alarmId; + int result; + + result = alarmmgr_add_periodic_alarm_withcb(interval, QUANTUMIZE, __onAlarmExpired, NULL, &alarmId); + IF_FAIL_RETURN_TAG(result == ALARMMGR_RESULT_SUCCESS, -1, _E, "Alarm setting failed"); + + ScopeMutex sm(&__mutex); + __listenerMap[alarmId] = std::make_pair(listener, this); + __alarms.insert(alarmId); + + _D("Timer %d was set for %dm interval", alarmId, interval); + return alarmId; +} + +SO_EXPORT int TimerManager::setAt(int hour, int min, DayOfWeek dow, ITimerListener *listener) +{ + IF_FAIL_RETURN_TAG( + hour < 24 && hour >= 0 && + min < 60 && min >= 0 && + static_cast(dow) > 0 && + static_cast(dow) <= static_cast(DayOfWeek::EVERYDAY) && + listener, -1, _E, "Invalid parameter"); + + int repeat = 0; + if (static_cast(dow) & static_cast(DayOfWeek::SUN)) + repeat |= ALARM_WDAY_SUNDAY; + if (static_cast(dow) & static_cast(DayOfWeek::MON)) + repeat |= ALARM_WDAY_MONDAY; + if (static_cast(dow) & static_cast(DayOfWeek::TUE)) + repeat |= ALARM_WDAY_TUESDAY; + if (static_cast(dow) & static_cast(DayOfWeek::WED)) + repeat |= ALARM_WDAY_WEDNESDAY; + if (static_cast(dow) & static_cast(DayOfWeek::THU)) + repeat |= ALARM_WDAY_THURSDAY; + if (static_cast(dow) & static_cast(DayOfWeek::FRI)) + repeat |= ALARM_WDAY_FRIDAY; + if (static_cast(dow) & static_cast(DayOfWeek::SAT)) + repeat |= ALARM_WDAY_SATURDAY; + + alarm_entry_t *alarmInfo = alarmmgr_create_alarm(); + IF_FAIL_RETURN_TAG(alarmInfo, -1, _E, "Memory allocation failed"); + + time_t currentTime; + struct tm currentTm; + time(¤tTime); + tzset(); + localtime_r(¤tTime, ¤tTm); + + alarm_date_t alarmTime; + alarmTime.year = currentTm.tm_year + 1900; + alarmTime.month = currentTm.tm_mon + 1; + alarmTime.day = currentTm.tm_mday; + alarmTime.hour = hour; + alarmTime.min = min; + alarmTime.sec = 0; + + alarmmgr_set_time(alarmInfo, alarmTime); + alarmmgr_set_repeat_mode(alarmInfo, ALARM_REPEAT_MODE_WEEKLY, repeat); + alarmmgr_set_type(alarmInfo, ALARM_TYPE_VOLATILE); + + int alarmId; + int ret = alarmmgr_add_alarm_with_localtime(alarmInfo, NULL, &alarmId); + alarmmgr_free_alarm(alarmInfo); + + IF_FAIL_RETURN_TAG(ret == ALARMMGR_RESULT_SUCCESS, -1, _E, "Alarm setting failed"); + + ScopeMutex sm(&__mutex); + __listenerMap[alarmId] = std::make_pair(listener, this); + __alarms.insert(alarmId); + + _D("Timer %d was set at %02d:%02d:00 (day of week: %#x)", alarmId, hour, min, dow); + return alarmId; +} + +SO_EXPORT void TimerManager::remove(int timerId) +{ + ScopeMutex sm(&__mutex); + __remove(timerId); + __alarms.erase(timerId); +} + +void TimerManager::__remove(int timerId) +{ + auto it = __listenerMap.find(timerId); + if (it != __listenerMap.end()) { + __listenerMap.erase(it); + alarmmgr_remove_alarm(timerId); + _D("Timer %d was removed", timerId); + } +} + +bool TimerManager::__init() +{ + int result = alarmmgr_init(IDENTIFIER); + IF_FAIL_RETURN_TAG(result == ALARMMGR_RESULT_SUCCESS, false, _E, "Alarm manager initialization failed"); + + result = alarmmgr_set_cb(__onAlarmExpired, NULL); + if (result != ALARMMGR_RESULT_SUCCESS) { + alarmmgr_fini(); + _E("Alarm callback registration failed"); + return false; + } + + alarmmgr_remove_all(); + _D("Timer initialized"); + return true; +} + +void TimerManager::__release() +{ + alarmmgr_remove_all(); + alarmmgr_fini(); + __listenerMap.clear(); + _D("Timer released"); +} + +int TimerManager::__onAlarmExpired(int alarmId, void *userdata) +{ + ITimerListener *listener = NULL; + TimerManager *timer = NULL; + + { + ScopeMutex sm(&__mutex); + auto it = __listenerMap.find(alarmId); + IF_FAIL_RETURN_TAG(it != __listenerMap.end(), 0, _W, "Unknown Alarm %d", alarmId); + listener = it->second.first; + timer = it->second.second; + } + + _D("Timer %d expired", alarmId); + + if (listener->onTimerExpired(alarmId)) + return 0; + + _D("Stop repeating TimerManager %d", alarmId); + timer->remove(alarmId); + return 0; +} diff --git a/common/shared/CMakeLists.txt b/common/shared/CMakeLists.txt new file mode 100644 index 0000000..9e52d5b --- /dev/null +++ b/common/shared/CMakeLists.txt @@ -0,0 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-shared") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/shared/Json.cpp b/common/shared/Json.cpp new file mode 100644 index 0000000..2f8a1b8 --- /dev/null +++ b/common/shared/Json.cpp @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PATH_DELIM '.' +#define MAX_PRECISION 15 +#define GVAR_VALUES "values" +#define GVAR_TYPES "types" + +using namespace ctx; + +static std::string __double_to_string(double in) +{ + /* Locale-independent double-to-string conversion */ + int prec = MAX_PRECISION; + std::string out; + std::ostringstream ostr; + + ostr.imbue(std::locale("C")); + ostr << std::setprecision(prec) << in; + out = ostr.str(); + + if (out.find('e') == std::string::npos) + return out; + + /* If 'out' is in scientific notation */ + ostr.clear(); + ostr.str(std::string()); + ostr.imbue(std::locale("C")); + + /* Get the number of fraction digits to precisely print the number */ + double number = in * 10; + while (static_cast(number) == 0) { + number *= 10; + ++prec; + } + + ostr << std::fixed << std::setprecision(prec) << in; + out = ostr.str(); + + /* Remove trailing '0' */ + std::size_t found = out.find_last_not_of("0"); + if (found != std::string::npos) + out.erase(found + 1); + + /* If 'out' ends with '.' */ + if (out.back() == '.') + out.erase(out.end() - 1); + + return out; +} + +static double __string_to_double(const char* in) +{ + IF_FAIL_RETURN_TAG(in, 0, _E, "Parameter NULL"); + + double out; + + /* Locale-independent string-to-double conversion */ + std::istringstream istr(in); + istr.imbue(std::locale("C")); + istr >> out; + + return out; +} + +SO_EXPORT Json::Json() : + __jsonNode(NULL) +{ + JsonObject *obj = json_object_new(); + IF_FAIL_VOID_TAG(obj, _E, "Json object construction failed"); + + __jsonNode = json_node_new(JSON_NODE_OBJECT); + if (!__jsonNode) { + json_object_unref(obj); + _E("Json object construction failed"); + } + + json_node_set_object(__jsonNode, obj); + json_object_unref(obj); +} + +SO_EXPORT Json::Json(const Json &j) + : __jsonNode(NULL) +{ + __jsonNode = json_node_copy(j.__jsonNode); + IF_FAIL_VOID_TAG(__jsonNode, _E, "Json object construction failed"); +} + +SO_EXPORT Json::Json(const char *s) + : __jsonNode(NULL) +{ + if (s) { + __parse(s); + } else { + __parse(EMPTY_JSON_OBJECT); + } +} + +SO_EXPORT Json::Json(const std::string &s) + : __jsonNode(NULL) +{ + if (s.empty()) { + __parse(EMPTY_JSON_OBJECT); + } else { + __parse(s.c_str()); + } +} + +SO_EXPORT Json::~Json() +{ + __release(); +} + +void Json::__parse(const char *s) +{ + gboolean result; + JsonParser *parser = NULL; + JsonNode *root = NULL; + + parser = json_parser_new(); + IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed"); + + result = json_parser_load_from_data(parser, s, -1, NULL); + IF_FAIL_CATCH_TAG(result, _E, "Parsing failed"); + + root = json_parser_get_root(parser); + IF_FAIL_CATCH_TAG(root, _E, "Getting root failed"); + + __jsonNode = json_node_copy(root); + IF_FAIL_CATCH_TAG(__jsonNode, _E, "Copying failed"); + +CATCH: + if (parser) + g_object_unref(parser); +} + +void Json::__release() +{ + if (__jsonNode) { + json_node_free(__jsonNode); + __jsonNode = NULL; + } +} + +SO_EXPORT bool Json::valid() +{ + return (__jsonNode != NULL); +} + +SO_EXPORT Json& Json::operator=(const Json &j) +{ + __release(); + __jsonNode = json_node_copy(j.__jsonNode); + if (!__jsonNode) { + _E("Json object copy failed"); + } + return *this; +} + +SO_EXPORT Json& Json::operator=(const char *s) +{ + __release(); + if (s) { + __parse(s); + } else { + __parse(EMPTY_JSON_OBJECT); + } + return *this; +} + +SO_EXPORT Json& Json::operator=(const std::string &s) +{ + __release(); + if (s.empty()) { + __parse(EMPTY_JSON_OBJECT); + } else { + __parse(s.c_str()); + } + return *this; +} + +SO_EXPORT bool Json::operator==(const Json &rhs) +{ + return __nodeEq(__jsonNode, rhs.__jsonNode); +} + +SO_EXPORT bool Json::operator!=(const Json &rhs) +{ + return !operator==(rhs); +} + +char* Json::__strDup() +{ + IF_FAIL_RETURN_TAG(__jsonNode, NULL, _E, "Json object not initialized"); + + JsonGenerator *jgen = NULL; + char *output = NULL; + + jgen = json_generator_new(); + IF_FAIL_CATCH(jgen); + + json_generator_set_root(jgen, __jsonNode); + output = json_generator_to_data(jgen, NULL); + IF_FAIL_CATCH(output); + + g_object_unref(jgen); + return output; + +CATCH: + if (jgen) { + g_object_unref(jgen); + } + + _E("Memory allocation failed"); + return NULL; +} + +SO_EXPORT std::string Json::str() +{ + std::string output; + char *_s = __strDup(); + IF_FAIL_RETURN(_s, output = EMPTY_JSON_OBJECT); + + output = _s; + g_free(_s); + + return output; +} + +static std::vector __tokenize_path(std::string path) +{ + std::vector tokens; + std::size_t begin = 0; + std::size_t end = path.find(PATH_DELIM, 0); + + while (end != std::string::npos) { + tokens.push_back(path.substr(begin, end - begin)); + begin = end + 1; + end = path.find(PATH_DELIM, begin); + } + + tokens.push_back(path.substr(begin)); + return tokens; +} + +static JsonObject* __traverse(JsonNode *jnode, const char *path, bool force) +{ + IF_FAIL_RETURN_TAG(jnode, NULL, _E, "Invalid parameter"); + + unsigned int depth = 0; + std::vector pathToken; + JsonObject *jobj = NULL; + JsonObject *childObj = NULL; + JsonNode *childNode = NULL; + + jobj = json_node_get_object(jnode); + IF_FAIL_RETURN(jobj, NULL); + + if (path) + pathToken = __tokenize_path(path); + + for (depth = 0; depth < pathToken.size(); depth++) { + if (!json_object_has_member(jobj, pathToken[depth].c_str())) { + if (!force) { + return NULL; + } + childObj = json_object_new(); + IF_FAIL_RETURN_TAG(childObj, NULL, _E, "Memory allocation failed"); + json_object_set_object_member(jobj, pathToken[depth].c_str(), childObj); + } + childNode = json_object_get_member(jobj, pathToken[depth].c_str()); + IF_FAIL_RETURN(childNode && json_node_get_node_type(childNode) == JSON_NODE_OBJECT, NULL); + + jobj = json_node_get_object(childNode); + IF_FAIL_RETURN(jobj, NULL); + } + + return jobj; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_member(jobj, key, val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, int val) +{ + return set(path, key, static_cast(val)); +} + +SO_EXPORT bool Json::set(const char *path, const char *key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_int_member(jobj, key, val); + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, double val) +{ + return set(path, key, __double_to_string(val)); +} + +SO_EXPORT bool Json::set(const char *path, const char *key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) { + json_object_remove_member(jobj, key); + } + + json_object_set_string_member(jobj, key, val.c_str()); + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, GVariant *val) +{ +#if JSON_CHECK_VERSION(0, 14, 0) + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + const gchar *typeStr = g_variant_get_type_string(val); + IF_FAIL_RETURN_TAG(typeStr, false, _E, "GVariant manipulation failed"); + + json_node_t *node = json_gvariant_serialize(val); + IF_FAIL_RETURN_TAG(node, false, _E, "GVariant manipulation failed"); + + Json gvarJson; + gvarJson.set(NULL, GVAR_TYPES, std::string(typeStr)); + json_object_set_member(json_node_get_object(gvarJson.__jsonNode), GVAR_VALUES, node); + + return set(path, key, gvarJson); +#else + _E("Insufficient version of json-glib(" JSON_VERSION_S ")"); + return false; +#endif +} + +SO_EXPORT bool Json::get(const char *path, const char *key, Json *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonObject *jobj = NULL; + JsonNode *node = NULL; + + jobj = __traverse(__jsonNode, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), false); + + node = json_object_dup_member(jobj, key); + IF_FAIL_RETURN_TAG(node, false, _E, "Memory allocation failed"); + + if (val->__jsonNode) { + json_node_free(val->__jsonNode); + } + val->__jsonNode = node; + + return true; +} + +static JsonNode* __get_value_node(JsonNode *jnode, const char *path, const char *key) +{ + JsonNode *node = NULL; + JsonObject *jobj = NULL; + JsonNodeType ntype; + + jobj = __traverse(jnode, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), NULL); + + node = json_object_get_member(jobj, key); + ntype = json_node_get_node_type(node); + IF_FAIL_RETURN(ntype == JSON_NODE_VALUE, NULL); + + return node; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, int *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + int64_t v; + + if (get(path, key, &v)) { + *val = v; + return true; + } + + return false; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, int64_t *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + //TODO: if the string is not a number? + *val = static_cast(__string_to_double(json_node_get_string(node))); + } else { + return false; + } + + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, double *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = __string_to_double(json_node_get_string(node)); + } else { + return false; + } + + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, std::string *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN(vtype == G_TYPE_STRING, false); + + const char *str_val = json_node_get_string(node); + IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed"); + + *val = str_val; + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, GVariant **val) +{ +#if JSON_CHECK_VERSION(0, 14, 0) + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + bool ret; + Json gvarJson; + ret = get(path, key, &gvarJson); + IF_FAIL_RETURN(ret, false); + + std::string gvarTypes; + ret = gvarJson.get(NULL, GVAR_TYPES, &gvarTypes); + IF_FAIL_RETURN(ret, false); + + Json gvarValues; + ret = gvarJson.get(NULL, GVAR_VALUES, &gvarValues); + IF_FAIL_RETURN(ret, false); + + GError *gerr = NULL; + *val = json_gvariant_deserialize(gvarValues.__jsonNode, gvarTypes.c_str(), &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN(*val, false); + + return true; +#else + _E("Insufficient version of json-glib(" JSON_VERSION_S ")"); + *val = NULL; + return false; +#endif +} + +SO_EXPORT bool Json::remove(const char *path, const char *key) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + return true; +} + +static JsonArray* __get_array(JsonNode *jnode, const char *path, const char *key, bool force) +{ + JsonNode *node = NULL; + JsonArray *arr = NULL; + JsonObject *jobj = NULL; + + jobj = __traverse(jnode, path, force); + IF_FAIL_RETURN(jobj, NULL); + + if (!json_object_has_member(jobj, key)) { + if (force) { + arr = json_array_new(); + IF_FAIL_RETURN_TAG(arr, NULL, _E, "Memory allocation failed"); + json_object_set_array_member(jobj, key, arr); + } else { + return NULL; + } + } + node = json_object_get_member(jobj, key); + IF_FAIL_RETURN_TAG(node && json_node_get_node_type(node) == JSON_NODE_ARRAY, + NULL, _W, "Type mismatched: %s", key); + + return json_node_get_array(node); +} + +SO_EXPORT int Json::getSize(const char *path, const char *key) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, -1, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, -1, _E, "Invalid parameter"); + + JsonArray *jarr = __get_array(__jsonNode, path, key, false); + IF_FAIL_RETURN_TAG(jarr, -1, _D, "Mismatched data type"); + + return json_array_get_length(jarr); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_element(arr, val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::append(const char *path, const char *key, int val) +{ + return append(path, key, static_cast(val)); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_int_element(arr, val); + return true; +} + +SO_EXPORT bool Json::append(const char *path, const char *key, double val) +{ + return append(path, key, __double_to_string(val)); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_string_element(arr, val.c_str()); + return true; +} + +static JsonNode* __get_array_elem(JsonNode *jnode, const char *path, const char *key, int index) +{ + JsonArray *jarr = __get_array(jnode, path, key, false); + IF_FAIL_RETURN_TAG(jarr, NULL, _W, "Mismatched data type"); + + int size = json_array_get_length(jarr); + IF_FAIL_RETURN(size > index, NULL); + + JsonNode *node = json_array_get_element(jarr, index); + IF_FAIL_RETURN_TAG(node, NULL, _E, "Failed to get an array element"); + + return node; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(val.__jsonNode && key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + + JsonObject *obj = json_node_get_object(val.__jsonNode); + IF_FAIL_RETURN_TAG(obj, false, _E, "Getting object failed"); + + json_node_set_object(node, obj); + json_node_free(val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, int val) +{ + return setAt(path, key, index, static_cast(val)); +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_int(node, val); + return true; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, double val) +{ + return setAt(path, key, index, __double_to_string(val)); +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, val.c_str()); + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, Json *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNode *nodeCopy = json_node_copy(node); + IF_FAIL_RETURN_TAG(nodeCopy, false, _E, "Memory allocation failed"); + + if (val->__jsonNode) { + json_node_free(val->__jsonNode); + } + val->__jsonNode = nodeCopy; + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, int *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + int64_t v; + if (getAt(path, key, index, &v)) { + *val = v; + return true; + } + + return false; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, int64_t *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = static_cast(__string_to_double(json_node_get_string(node))); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, double *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = __string_to_double(json_node_get_string(node)); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, std::string *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN_TAG(vtype == G_TYPE_STRING, false, _E, "Type mismatched: %s", key); + + const char *str_val = json_node_get_string(node); + IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed"); + + *val = str_val; + return true; +} + +bool Json::__getMembers(json_node_t *node, std::list &list) +{ + IF_FAIL_RETURN(node, false); + list.clear(); + + JsonObject *jobj = json_node_get_object(node); + IF_FAIL_RETURN_TAG(jobj, false, _E, "Getting Json object failed"); + + GList *members = json_object_get_members(jobj); + IF_FAIL_RETURN(members, true); + + for (GList *it = g_list_first(members); it; it = g_list_next(it)) { + const char *key = static_cast(it->data); + if (!key) { + list.clear(); + g_list_free(members); + _E("Member list extraction failed"); + return false; + } + + list.push_back(key); + } + + g_list_free(members); + return true; +} + +SO_EXPORT bool Json::getKeys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return __getMembers(__jsonNode, *list); +} + +bool Json::__nodeEq(json_node_t *lhs, json_node_t *rhs) +{ + IF_FAIL_RETURN(lhs && rhs, false); + + JsonNodeType ltype = json_node_get_node_type(lhs); + JsonNodeType rtype = json_node_get_node_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case JSON_NODE_VALUE: + IF_FAIL_RETURN(__valueEq(lhs, rhs), false); + break; + case JSON_NODE_OBJECT: + IF_FAIL_RETURN(__objectEq(lhs, rhs), false); + break; + case JSON_NODE_ARRAY: + IF_FAIL_RETURN(__arrayEq(lhs, rhs), false); + break; + default: + _W("Unsupported type"); + return false; + } + + return true; +} + +bool Json::__valueEq(json_node_t *lhs, json_node_t *rhs) +{ + GType ltype = json_node_get_value_type(lhs); + GType rtype = json_node_get_value_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case G_TYPE_INT64: + return json_node_get_int(lhs) == json_node_get_int(rhs); + case G_TYPE_DOUBLE: + return json_node_get_double(lhs) == json_node_get_double(rhs); + case G_TYPE_STRING: + return STR_EQ(json_node_get_string(lhs), json_node_get_string(rhs)); + default: + _W("Unsupported type"); + return false; + } +} + +bool Json::__objectEq(json_node_t *lhs, json_node_t *rhs) +{ + std::list lm, rm; + IF_FAIL_RETURN(__getMembers(lhs, lm), false); + IF_FAIL_RETURN(__getMembers(rhs, rm), false); + IF_FAIL_RETURN(lm.size() == rm.size(), false); + + lm.sort(); + rm.sort(); + + std::list::iterator lit, rit; + lit = lm.begin(); + rit = rm.begin(); + + while (lit != lm.end()) { + IF_FAIL_RETURN(*lit == *rit, false); + + json_node_t *lhsChild = json_object_get_member(json_node_get_object(lhs), (*lit).c_str()); + json_node_t *rhsChild = json_object_get_member(json_node_get_object(rhs), (*rit).c_str()); + IF_FAIL_RETURN(__nodeEq(lhsChild, rhsChild), false); + + ++lit; + ++rit; + } + + return true; +} + +bool Json::__arrayEq(json_node_t *lhs, json_node_t *rhs) +{ + JsonArray *larr = json_node_get_array(lhs); + JsonArray *rarr = json_node_get_array(rhs); + + int size = json_array_get_length(larr); + IF_FAIL_RETURN(size == static_cast(json_array_get_length(rarr)), false); + + for (int i = 0; i < size; ++i) { + json_node_t *lhsChild = json_array_get_element(larr, i); + json_node_t *rhsChild = json_array_get_element(rarr, i); + IF_FAIL_RETURN(__nodeEq(lhsChild, rhsChild), false); + } + + return true; +} diff --git a/common/shared/MyPlaceTypes.cpp b/common/shared/MyPlaceTypes.cpp new file mode 100644 index 0000000..c5c2600 --- /dev/null +++ b/common/shared/MyPlaceTypes.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +SO_EXPORT bool ctx::operator==(const ctx::Place &p1, const ctx::Place &p2) +{ + bool ret = p1.categId == p2.categId + && p1.categConfidence == p2.categConfidence + && p1.name == p2.name + && p1.createDate == p2.createDate + && p1.locationValid == p2.locationValid; + if (ret && p1.locationValid) { + // Check location only if it is valid / filled + if (p1.location.latitude != p2.location.latitude + || p1.location.longitude != p2.location.longitude + || p1.location.accuracy != p2.location.accuracy) { + ret = false; + } + } + if (ret) { + for (std::pair ap : p1.wifiAps) { + // Check only MAC addresses because network names are only addition. + if (p2.wifiAps.find(ap.first) == p2.wifiAps.end()) { + ret = false; + break; + } + } + } + return ret; +} diff --git a/common/shared/ScopeMutex.cpp b/common/shared/ScopeMutex.cpp new file mode 100644 index 0000000..8bc0b51 --- /dev/null +++ b/common/shared/ScopeMutex.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +SO_EXPORT ctx::ScopeMutex::ScopeMutex(GMutex *m) : + __mutex(m) +{ + g_mutex_lock(__mutex); +} + +SO_EXPORT ctx::ScopeMutex::~ScopeMutex() +{ + g_mutex_unlock(__mutex); +} -- 2.34.1