From: Harish Kumara Marappa Date: Thu, 6 Aug 2015 08:40:14 +0000 (+0530) Subject: Implementation of Logger interface between Application and X-Git-Tag: 1.2.0+RC1~764^2~46 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=834881cc63d0ac291aa51cb77aa1f1f94fe2b401;p=platform%2Fupstream%2Fiotivity.git Implementation of Logger interface between Application and simulator C++ modules. Change-Id: I572a52907f16e06b9f0877e7dc150056d0aa7532 Signed-off-by: Harish Kumara Marappa Reviewed-on: https://gerrit.iotivity.org/gerrit/1870 Tested-by: jenkins-iotivity Reviewed-by: Madan Lanka --- diff --git a/service/simulator/examples/server/service_provider.cpp b/service/simulator/examples/server/service_provider.cpp index e9e3ed6..8f634ca 100644 --- a/service/simulator/examples/server/service_provider.cpp +++ b/service/simulator/examples/server/service_provider.cpp @@ -20,6 +20,16 @@ #include "simulator_manager.h" +class AppLogger : public ILogger +{ + public: + void write(std::string time, ILogger::Level level, std::string message) + { + std::cout << "[APPLogger] " << time << " " << ILogger::getString(level) << " " << message; + } +}; +std::shared_ptr gAppLogger(new AppLogger()); + class SimLightResource { public: @@ -72,6 +82,12 @@ class SimLightResource int selectResource() { + if (0 == m_resources.size()) + { + std::cout << "No resouces!" << std::endl; + return -1; + } + int index = 1; for (auto & resource : m_resources) { @@ -99,7 +115,8 @@ class SimLightResource std::cout << "#### Modified attributes are ####" << std::endl; for (auto & attribute : resModel.getAttributes()) { - std::cout << attribute.second.getName() << " : " << attribute.second.valueToString().c_str() << std::endl; + std::cout << attribute.second.getName() << " : " << attribute.second.valueToString().c_str() << + std::endl; } std::cout << "########################" << std::endl; } @@ -287,7 +304,7 @@ class SimLightResource int choice = -1; std::cout << "Select the attribute which you want to automate for updation: " << std::endl; std::cin >> choice; - if (choice == -1 || choice > size) + if (choice < 0 || choice > size) { std::cout << "Invalid selection!" << std::endl; return; @@ -335,11 +352,45 @@ void printMainMenu() { std::cout << "############### MAIN MENU###############" << std::endl; std::cout << "1. Test simulation of light resource" << std::endl; - std::cout << "2. Help" << std::endl; + std::cout << "2. Set Logger" << std::endl; + std::cout << "3. Help" << std::endl; std::cout << "0. Exit" << std::endl; std::cout << "######################################" << std::endl; } +void setLogger() +{ + std::cout << "1. Default console logger" << std::endl; + std::cout << "2. Default file logger" << std::endl; + std::cout << "3. custom logger" << std::endl; + + int choice = -1; + std::cin >> choice; + if (choice <= 0 || choice > 3) + { + std::cout << "Invalid selection !" << std::endl; + return; + } + + switch (choice) + { + case 1: + { + if (false == SimulatorManager::getInstance()->setDefaultConsoleLogger()) + std::cout << "Failed to set the default console logger" << std::endl; + } break; + case 2: + { + std::string filePath; + std::cout << "Enter the file path (without file name) : "; + std::cin >> filePath; + if (false == SimulatorManager::getInstance()->setDefaultFileLogger(filePath)) + std::cout << "Failed to set default file logger" << std::endl; + } break; + case 3: SimulatorManager::getInstance()->setLogger(gAppLogger); + } +} + int main(void) { SimLightResource lightResource; @@ -351,7 +402,7 @@ int main(void) int choice = -1; std::cout << "Enter your choice: "; std::cin >> choice; - if (choice < 0 || choice > 2) + if (choice < 0 || choice > 3) { std::cout << "Invaild choice !" << std::endl; continue; } @@ -361,7 +412,8 @@ int main(void) case 1: lightResource.startTest(); std::cout << "Welcome back to main menu !" << std::endl; break; - case 2: printMainMenu(); break; + case 2: setLogger(); break; + case 3: printMainMenu(); break; case 0: cont = false; } } diff --git a/service/simulator/inc/simulator_manager.h b/service/simulator/inc/simulator_manager.h index 2d83c7e..424791c 100644 --- a/service/simulator/inc/simulator_manager.h +++ b/service/simulator/inc/simulator_manager.h @@ -31,6 +31,7 @@ #include #include "simulator_error_codes.h" #include "simulator_resource.h" +#include "simulator_logger.h" /** * @class SimulatorManager @@ -96,6 +97,34 @@ class SimulatorManager */ SimulatorResult deleteResources(const std::string &resourceType = ""); + /** + * API for setting logger target for receiving the log messages. + * + * @param logger - ILogger interface for handling the log messages. + * + */ + void setLogger(std::shared_ptr logger); + + /** + * API for setting console as logger target. + * + * @return true if console set as logger target, + * otherwise false. + * + */ + bool setDefaultConsoleLogger(); + + /** + * API for setting file as logger target. + * + * @param path - File to which log messages to be saved. + * + * @return true if console set as logger target, + * otherwise false. + * + */ + bool setDefaultFileLogger(std::string &path); + private: SimulatorManager(); }; diff --git a/service/simulator/java/jni/simulator_common_jni.h b/service/simulator/java/jni/simulator_common_jni.h index 1e49152..10e7c9d 100644 --- a/service/simulator/java/jni/simulator_common_jni.h +++ b/service/simulator/java/jni/simulator_common_jni.h @@ -23,41 +23,25 @@ #include -static jfieldID GetHandleField(JNIEnv *env, jobject jobj) -{ - jclass cls = env->GetObjectClass(jobj); - return env->GetFieldID(cls, "nativeHandle", "J"); -} - -template -static T *GetHandle(JNIEnv *env, jobject jobj) -{ - jlong handle = env->GetLongField(jobj, GetHandleField(env, jobj)); - return reinterpret_cast(handle); -} - -template -static void SetHandle(JNIEnv *env, jobject jobj, T *type) -{ - jlong handle = reinterpret_cast(type); - - env->SetLongField(jobj, GetHandleField(env, jobj), handle); -} - typedef struct { jclass classInteger; jclass classDouble; jclass classString; jclass classHashMap; + jclass classVector; jclass classSimulatorResource; jclass classSimulatorResourceModel; jclass classSimulatorResourceAttribute; + jclass classSimulatorRemoteResource; + jclass classSimulatorCallback; jmethodID classIntegerCtor; jmethodID classDoubleCtor; jmethodID classHashMapCtor; jmethodID classHashMapPut; + jmethodID classVectorCtor; + jmethodID classVectorAddElement; jmethodID classSimulatorResourceCtor; jmethodID classSimulatorResourceSetURI; jmethodID classSimulatorResourceSetResourceType; @@ -67,4 +51,28 @@ typedef struct jmethodID classSimulatorResourceAttributeCtor; } SimulatorClassRefs; +static jfieldID GetHandleField(JNIEnv *env, jobject jobj) +{ + jclass cls = env->GetObjectClass(jobj); + return env->GetFieldID(cls, "nativeHandle", "J"); +} + +template +static T *GetHandle(JNIEnv *env, jobject jobj) +{ + jlong handle = env->GetLongField(jobj, GetHandleField(env, jobj)); + return reinterpret_cast(handle); +} + +template +static void SetHandle(JNIEnv *env, jobject jobj, T *type) +{ + jlong handle = reinterpret_cast(type); + + env->SetLongField(jobj, GetHandleField(env, jobj), handle); +} + +JNIEnv *getEnv(); +void releaseEnv(); + #endif diff --git a/service/simulator/java/jni/simulator_manager_jni.cpp b/service/simulator/java/jni/simulator_manager_jni.cpp index d0958bc..406dcfa 100644 --- a/service/simulator/java/jni/simulator_manager_jni.cpp +++ b/service/simulator/java/jni/simulator_manager_jni.cpp @@ -23,16 +23,86 @@ #include "simulator_common_jni.h" #include "simulator_manager.h" -#define SIMULATOR_RESOURCE_PATH "org/iotivity/simulator/SimulatorResourceServer" -#define SIMULATOR_RESOURCE_TYPE "Lorg/iotivity/simulator/SimulatorResourceServer;" +SimulatorClassRefs gSimulatorClassRefs; +std::mutex gEnvMutex; +JavaVM *gvm; -#define SIMULATOR_RESOURCE_MODEL_PATH "org/iotivity/simulator/SimulatorResourceModel" -#define SIMULATOR_RESOURCE_MODEL_TYPE "Lorg/iotivity/simulator/SimulatorResourceModel;" +JNIEnv *getEnv() +{ + std::unique_lock lock(gEnvMutex); + if (nullptr == gvm) + return NULL; -#define SIMULATOR_RESOURCE_ATTRIBUTE_PATH "org/iotivity/simulator/SimulatorResourceAttribute" -#define SIMULATOR_RESOURCE_ATTRIBUTE_TYPE "Lorg/iotivity/simulator/SimulatorResourceAttribute;" + JNIEnv *env = NULL; + jint ret = gvm->GetEnv((void **)&env, JNI_VERSION_1_6); + switch (ret) + { + case JNI_OK: + return env; + case JNI_EDETACHED: + if (0 == gvm->AttachCurrentThread((void **)&env, NULL)) + return env; + } + + return NULL; +} + +void releaseEnv() +{ + std::unique_lock lock(gEnvMutex); + if (nullptr == gvm) + return; + gvm->DetachCurrentThread(); +} + +class JNILogger : public ILogger +{ + public: + void setJavaLogger(JNIEnv *env, jobject logger) + { + m_logger = env->NewWeakGlobalRef(logger); + } + + void write(std::string time, ILogger::Level level, std::string message) + { + JNIEnv *env = getEnv(); + if (nullptr == env) + return; + + jobject logger = env->NewLocalRef(m_logger); + if (!logger) + { + releaseEnv(); + return; + } + + jclass loggerCls = env->GetObjectClass(logger); + if (!loggerCls) + { + releaseEnv(); + return; + } + + jmethodID writeMId = env->GetMethodID(loggerCls, "write", + "(Ljava/lang/String;ILjava/lang/String;)V"); + if (!writeMId) + { + releaseEnv(); + return; + } + + jstring msg = env->NewStringUTF(message.c_str()); + jstring timeStr = env->NewStringUTF(time.c_str()); + env->CallVoidMethod(logger, writeMId, timeStr, static_cast(level), msg); + env->DeleteLocalRef(msg); + env->DeleteLocalRef(timeStr); + releaseEnv(); + } + + private: + jweak m_logger; +}; -SimulatorClassRefs gSimulatorClassRefs; JNIEXPORT jobject JNICALL Java_org_iotivity_simulator_SimulatorManagerNativeInterface_createResource @@ -114,6 +184,15 @@ Java_org_iotivity_simulator_SimulatorManagerNativeInterface_deleteResources } +JNIEXPORT void JNICALL +Java_org_iotivity_simulator_SimulatorManagerNativeInterface_setLogger +(JNIEnv *env, jclass object, jobject logger) +{ + static std::shared_ptr target(new JNILogger()); + dynamic_cast(target.get())->setJavaLogger(env, logger); + SimulatorManager::getInstance()->setLogger(target); +} + static bool getClassRef(JNIEnv *env, const char *className, jclass &classRef) { jclass localClassRef = nullptr; @@ -142,7 +221,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) return JNI_ERR; } - // Get the class references and constructor methods + // Get the class references if (false == getClassRef(env, "java/lang/Integer", gSimulatorClassRefs.classInteger)) { return JNI_ERR; @@ -163,24 +242,37 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) return JNI_ERR; } - if (false == getClassRef(env, SIMULATOR_RESOURCE_PATH, gSimulatorClassRefs.classSimulatorResource)) + if (false == getClassRef(env, "java/util/Vector", gSimulatorClassRefs.classVector)) + { + return JNI_ERR; + } + + if (false == getClassRef(env, "org/oic/simulator/serviceprovider/SimulatorResourceServer", + gSimulatorClassRefs.classSimulatorResource)) { return JNI_ERR; } - if (false == getClassRef(env, SIMULATOR_RESOURCE_MODEL_PATH, + if (false == getClassRef(env, "org/oic/simulator/serviceprovider/SimulatorResourceModel", gSimulatorClassRefs.classSimulatorResourceModel)) { return JNI_ERR; } - if (false == getClassRef(env, SIMULATOR_RESOURCE_ATTRIBUTE_PATH, + if (false == getClassRef(env, "org/oic/simulator/SimulatorResourceAttribute", gSimulatorClassRefs.classSimulatorResourceAttribute)) { return JNI_ERR; } - // Get the constructor methods + if (false == getClassRef(env, "org/oic/simulator/clientcontroller/SimulatorRemoteResource", + gSimulatorClassRefs.classSimulatorRemoteResource)) + { + return JNI_ERR; + } + + + // Get the reference to methods gSimulatorClassRefs.classIntegerCtor = env->GetMethodID(gSimulatorClassRefs.classInteger, "", "(I)V"); if (!gSimulatorClassRefs.classIntegerCtor) @@ -201,6 +293,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) if (!gSimulatorClassRefs.classHashMapPut) return JNI_ERR; + gSimulatorClassRefs.classVectorCtor = env->GetMethodID(gSimulatorClassRefs.classVector, "", + "()V"); + if (!gSimulatorClassRefs.classVectorCtor) + return JNI_ERR; + + gSimulatorClassRefs.classVectorAddElement = env->GetMethodID(gSimulatorClassRefs.classVector, + "addElement", + "(Ljava/lang/Object;)V"); + if (!gSimulatorClassRefs.classVectorAddElement) + return JNI_ERR; + gSimulatorClassRefs.classSimulatorResourceCtor = env->GetMethodID( gSimulatorClassRefs.classSimulatorResource, "", "(J)V"); if (!gSimulatorClassRefs.classSimulatorResourceCtor) @@ -236,16 +339,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) if (!gSimulatorClassRefs.classSimulatorResourceAttributeCtor) return JNI_ERR; + gvm = vm; return JNI_VERSION_1_6; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { - JNIEnv *env = NULL; - if (JNI_OK != vm->GetEnv((void **)&env, JNI_VERSION_1_6)) - { - return; - } } #ifdef __cplusplus diff --git a/service/simulator/java/jni/simulator_manager_jni.h b/service/simulator/java/jni/simulator_manager_jni.h index 28a9cbb..a18d062 100644 --- a/service/simulator/java/jni/simulator_manager_jni.h +++ b/service/simulator/java/jni/simulator_manager_jni.h @@ -55,6 +55,10 @@ JNIEXPORT void JNICALL Java_org_iotivity_simulator_SimulatorManagerNativeInterface_deleteResources (JNIEnv *env, jclass object, jstring resourceType); +JNIEXPORT void JNICALL +Java_org_iotivity_simulator_SimulatorManagerNativeInterface_setLogger +(JNIEnv *env, jclass object, jobject logger); + #ifdef __cplusplus } #endif diff --git a/service/simulator/src/simulator_logger.cpp b/service/simulator/src/simulator_logger.cpp new file mode 100644 index 0000000..e8ed2ea --- /dev/null +++ b/service/simulator/src/simulator_logger.cpp @@ -0,0 +1,117 @@ +/****************************************************************** + * + * Copyright 2015 Samsung Electronics All Rights Reserved. + * + * + * + * 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 "simulator_logger.h" +#include +#include +#include + +class ConsoleLogger : public ILogger +{ + public: + void write(std::string time, ILogger::Level level, std::string message) + { + std::ostringstream out; + out << time << " " << ILogger::getString(level) << " " << message; + std::cout << out.str() << std::endl; + } +}; + +class FileLogger : public ILogger +{ + public: + FileLogger(std::string filePath) : m_filePath(filePath) {} + + bool open() + { + m_out.open(m_filePath, std::ofstream::out); + return m_out.is_open(); + } + + void close() + { + if (m_out.is_open()) + m_out.close(); + } + + void write(std::string time, ILogger::Level level, std::string message) + { + m_out << time << " " << ILogger::getString(level) << " " << message; + } + + private: + std::ofstream m_out; + std::string m_filePath; +}; + +bool Logger::setDefaultConsoleTarget() +{ + if (nullptr != m_target) + return false; + + m_target = std::make_shared(); + return true; +} + +bool Logger::setDefaultFileTarget(std::string &path) +{ + if (nullptr != m_target || path.empty()) + return false; + + time_t timeInfo = time(NULL); + struct tm *localTime = localtime(&timeInfo); + std::ostringstream newFileName; + newFileName << path << "/Simulator_"; + newFileName << localTime->tm_year << localTime->tm_mon << localTime->tm_mday << localTime->tm_hour + << localTime->tm_min << localTime->tm_sec; + newFileName << ".log"; + + std::shared_ptr fileLogger(new FileLogger(newFileName.str())); + if (fileLogger->open()) + { + m_target = fileLogger; + return true; + } + + return false; +} + +void Logger::setCustomTarget(std::shared_ptr target) +{ + m_target = target; +} + +void Logger::write(ILogger::Level level, std::ostringstream &str) +{ + if (nullptr != m_target) + { + time_t timeInfo = time(NULL); + struct tm *localTime = localtime(&timeInfo); + std::ostringstream timeStr; + timeStr << localTime->tm_hour << "." << localTime->tm_min << "." << localTime->tm_sec; + m_target->write(timeStr.str(), level, str.str()); + } +} + +auto simLogger() -> Logger & +{ + static Logger logger; + return logger; +} \ No newline at end of file diff --git a/service/simulator/src/simulator_logger.h b/service/simulator/src/simulator_logger.h new file mode 100644 index 0000000..9c7e407 --- /dev/null +++ b/service/simulator/src/simulator_logger.h @@ -0,0 +1,79 @@ +/****************************************************************** + * + * Copyright 2015 Samsung Electronics All Rights Reserved. + * + * + * + * 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. + * + ******************************************************************/ + +/** + * @file simulator_logger.h + * + * @brief This file provides the interface for logging messages to different targets (console/file). + */ + +#ifndef SIMULATOR_LOGGER_H_ +#define SIMULATOR_LOGGER_H_ + +#include +#include + +class ILogger +{ + public: + enum Level + { + INFO = 0, + DEBUG, + WARNING, + ERROR + }; + + static const char *getString(Level level) + { + switch (level) + { + case Level::INFO: return "INFO"; + case Level::DEBUG: return "DEBUG"; + case Level::WARNING: return "WARNING"; + case Level::ERROR: return "ERROR"; + default: return "UNKNOWN"; + } + } + + virtual void write(std::string, Level, std::string) = 0; +}; + +class Logger +{ + public: + bool setDefaultConsoleTarget(); + bool setDefaultFileTarget(std::string &path); + void setCustomTarget(std::shared_ptr target); + void write(ILogger::Level level, std::ostringstream &str); + + private: + std::shared_ptr m_target; +}; + +auto simLogger() -> Logger &; + +#ifndef SIM_LOG +#define SIM_LOG(LEVEL, MSG) { \ + simLogger().write(LEVEL, static_cast(std::ostringstream()<deleteResources(resourceType); +} + +void SimulatorManager::setLogger(std::shared_ptr logger) +{ + simLogger().setCustomTarget(logger); +} + +bool SimulatorManager::setDefaultConsoleLogger() +{ + return simLogger().setDefaultConsoleTarget(); +} + +bool SimulatorManager::setDefaultFileLogger(std::string &path) +{ + return simLogger().setDefaultFileTarget(path); } \ No newline at end of file