#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
namespace common {
return get<T>(node, std::move(path));
}
+ void set(std::vector<std::string> path, const std::string& value) {
+ rapidjson::Value* curr = &doc_;
+ for (auto it = path.begin(); it != path.end(); ++it) {
+ if (!curr->IsObject()) {
+ throw std::runtime_error("Expected object while traversing to set key");
+ }
+
+ auto memberIt = curr->FindMember(it->c_str());
+ if (memberIt == curr->MemberEnd()) {
+ rapidjson::Value key(it->c_str(), doc_.GetAllocator());
+ rapidjson::Value newObj(rapidjson::kObjectType);
+ curr->AddMember(key, newObj, doc_.GetAllocator());
+ memberIt = curr->FindMember(it->c_str());
+ }
+ if (std::next(it) == path.end()) {
+ memberIt->value.SetString(value.c_str(), doc_.GetAllocator());
+ } else {
+ curr = &memberIt->value;
+ }
+ }
+ }
+
+ void set(const std::string& dotPath, const std::string& value) {
+ std::vector<std::string> path = split(dotPath, '.');
+ set(std::move(path), value);
+ }
+
+ std::string stringify() const {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ doc_.Accept(writer);
+ return buffer.GetString();
+ }
+
private:
rapidjson::Document doc_;
)
TARGET_LINK_LIBRARIES(${TARGET_TIZEN_ACTION_PLUGIN_DAEMON} PRIVATE ${TARGET_TIZEN_ACTION} ${TARGET_TIZEN_ACTION_COMMON})
+TARGET_INCLUDE_DIRECTORIES(${TARGET_TIZEN_ACTION_PLUGIN_DAEMON} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
INSTALL(TARGETS ${TARGET_TIZEN_ACTION_PLUGIN_DAEMON} DESTINATION bin)
#include <cstdio>
#include <utility>
+#include "action/sqlite_db.hh"
+#include "common/action_schema.h"
#include "common/utils/logging.hh"
+#include "common/utils/safe_json.hpp"
+#include "plugin.hh"
#include "plugin_manager_stub.h"
+namespace {
+
+const char kActionFrameworkServiceAppId[] =
+ "org.tizen.action-framework.service";
+
+} // namespace
+
class PluginService
: public rpc_port::plugin_manager_stub::stub::PluginManager::ServiceBase {
public:
std::string instance = GetInstance();
LOG(INFO) << "PluginService execute. sender: " << sender
<< ", instance: " << instance;
- PrintAction(action);
- // TODO: find executable path;
- if (true) {
- LOG(ERROR) << "Executable parameter not found";
- result_cb->Invoke("Fail");
+ if (sender != kActionFrameworkServiceAppId) {
+ LOG(ERROR) << "Invalid sender";
+ common::SafeJson result("{}");
+ result.set("error", "Permission denied");
+ result_cb->Invoke(result.stringify());
return;
}
- // TODO: implement action execution
-
- result_cb->Invoke("Success");
+ PrintAction(action);
+ std::string action_name = action.Getaction_id();
+ auto db = std::make_unique<action::SqliteDb>();
+ std::string schema_json = db->GetAction(action_name);
+ try {
+ common::ActionSchema schema(schema_json);
+ std::string plugin_path = schema.GetPluginPath();
+ LOG(INFO) << "Plugin path: " + plugin_path;
+ auto plugin = std::make_unique<Plugin>(plugin_path);
+ std::string result_json = plugin->Execute(action.Getjson());
+ common::SafeJson result("{}");
+ result.set("data", result_json);
+ result_cb->Invoke(result.stringify());
+ } catch (const std::runtime_error& e) {
+ LOG(ERROR) << "Exception occurred: " << e.what();
+ common::SafeJson result("{}");
+ result.set("error", e.what());
+ result_cb->Invoke(result.stringify());
+ }
}
private:
--- /dev/null
+#include "plugin.hh"
+
+#include <dlfcn.h>
+
+#include <stdexcept>
+#include <utility>
+
+#include "common/utils/logging.hh"
+
+Plugin::Plugin(std::string plugin_path) : plugin_path_(std::move(plugin_path)) {
+ handle_ = dlopen(plugin_path_.c_str(), RTLD_LAZY);
+ if (handle_ == nullptr) {
+ LOG(ERROR) << "Failed to open plugin: " << dlerror();
+ throw std::runtime_error("Invalid plugin");;
+ }
+
+ execute_function_ = reinterpret_cast<const char* (*)(const char*)>(
+ dlsym(handle_, "PLUGIN_EXECUTE"));
+ if (execute_function_ == nullptr) {
+ LOG(ERROR) << "Failed to find symbol: " << dlerror();
+ dlclose(handle_);
+ throw std::runtime_error("Invalid plugin");
+ }
+
+ LOG(INFO) << "Plugin loaded successfully";
+}
+
+Plugin::~Plugin() {
+ if (handle_)
+ dlclose(handle_);
+}
+
+std::string Plugin::Execute(std::string action_model_json) {
+ return execute_function_(action_model_json.c_str());
+}
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd 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.
+ */
+
+#ifndef PLUGIN_DAEMON_PLUGIN_HH_
+#define PLUGIN_DAEMON_PLUGIN_HH_
+
+#include <string>
+
+class Plugin {
+ public:
+ using PluginExecuteFunction = const char* (*)(const char*);
+ explicit Plugin(std::string plugin_path);
+ ~Plugin();
+ std::string Execute(std::string action_model_json);
+
+ private:
+ std::string plugin_path_;
+ void* handle_ = nullptr;
+ PluginExecuteFunction execute_function_;
+};
+
+#endif // PLUGIN_DAEMON_PLUGIN_HH_