/********************************************************************\
Name: mjsonrpc_user.cxx
Created by: Konstantin Olchanski
Contents: handler of user-provided and experimental JSON-RPC requests
\********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <map>
#include "mjson.h"
#include "midas.h"
#include "msystem.h"
#include "mjsonrpc.h"
#include <mutex> // std::mutex
//
// example 1: extract request parameters, return up to 3 results
//
static MJsonNode* user_example1(const MJsonNode* params)
{
if (!params) {
MJSO* doc = MJSO::I();
doc->D("example of user defined RPC method that returns up to 3 results");
doc->P("arg", MJSON_STRING, "example string argment");
doc->P("optional_arg?", MJSON_INT, "optional example integer argument");
doc->R("string", MJSON_STRING, "returns the value of \"arg\" parameter");
doc->R("integer", MJSON_INT, "returns the value of \"optional_arg\" parameter");
return doc;
}
MJsonNode* error = NULL;
std::string arg = mjsonrpc_get_param(params, "arg", &error)->GetString(); if (error) return error;
int optional_arg = mjsonrpc_get_param(params, "optional_arg", NULL)->GetInt();
if (mjsonrpc_debug)
printf("user_example1(%s,%d)\n", arg.c_str(), optional_arg);
return mjsonrpc_make_result("string", MJsonNode::MakeString(arg.c_str()), "integer", MJsonNode::MakeInt(optional_arg));
}
//
// example 2: extract request parameters, return more than 3 results
//
static MJsonNode* user_example2(const MJsonNode* params)
{
if (!params) {
MJSO* doc = MJSO::I();
doc->D("example of user defined RPC method that returns more than 3 results");
doc->P("arg", MJSON_STRING, "example string argment");
doc->P("optional_arg?", MJSON_INT, "optional example integer argument");
doc->R("string1", MJSON_STRING, "returns the value of \"arg\" parameter");
doc->R("string2", MJSON_STRING, "returns \"hello\"");
doc->R("string3", MJSON_STRING, "returns \"world!\"");
doc->R("value1", MJSON_INT, "returns the value of \"optional_arg\" parameter");
doc->R("value2", MJSON_NUMBER, "returns 3.14");
return doc;
}
MJsonNode* error = NULL;
std::string arg = mjsonrpc_get_param(params, "arg", &error)->GetString(); if (error) return error;
int optional_arg = mjsonrpc_get_param(params, "optional_arg", NULL)->GetInt();
if (mjsonrpc_debug)
printf("user_example2(%s,%d)\n", arg.c_str(), optional_arg);
MJsonNode* result = MJsonNode::MakeObject();
result->AddToObject("string1", MJsonNode::MakeString(arg.c_str()));
result->AddToObject("string2", MJsonNode::MakeString("hello"));
result->AddToObject("string3", MJsonNode::MakeString("world!"));
result->AddToObject("value1", MJsonNode::MakeInt(optional_arg));
result->AddToObject("value2", MJsonNode::MakeNumber(3.14));
return mjsonrpc_make_result(result);
}
//
// example 3: return an error
//
static MJsonNode* user_example3(const MJsonNode* params)
{
if (!params) {
MJSO* doc = MJSO::I();
doc->D("example of user defined RPC method that returns an error");
doc->P("arg", MJSON_INT, "integer value, if zero, throws a JSON-RPC error");
doc->R("status", MJSON_INT, "returns the value of \"arg\" parameter");
return doc;
}
MJsonNode* error = NULL;
int arg = mjsonrpc_get_param(params, "arg", &error)->GetInt(); if (error) return error;
if (mjsonrpc_debug)
printf("user_example3(%d)\n", arg);
if (arg)
return mjsonrpc_make_result("status", MJsonNode::MakeInt(arg));
else
return mjsonrpc_make_error(15, "example error message", "example error data");
}
static MJsonNode* js_any_list_files(const MJsonNode* params)
{
if (!params) {
MJSO* doc = MJSO::I();
doc->D("js_any_list_files");
doc->P("subdir", MJSON_STRING, "List files in /Seq/State/Path/subdir");
doc->R("status", MJSON_INT, "return status of midas library calls");
doc->R("path", MJSON_STRING, "Search path");
doc->R("fileext", MJSON_STRING, "Filename extension");
doc->R("subdirs[]", MJSON_STRING, "list of subdirectories");
doc->R("files[].filename", MJSON_STRING, "script filename");
doc->R("files[].description", MJSON_STRING, "script description");
return doc;
}
MJsonNode* error = NULL;
std::string subdir = mjsonrpc_get_param(params, "subdir", &error)->GetString(); if (error) return error;
std::string fileext = mjsonrpc_get_param(params, "fileext", &error)->GetString(); if (error) return error;
std::string path = mjsonrpc_get_param(params, "path", NULL)->GetString();
if (subdir.find("..") != std::string::npos) {
return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM));
}
int status;
HNDLE hDB;
status = cm_get_experiment_database(&hDB, NULL);
if (status != DB_SUCCESS) {
return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
}
// std::string path;
// If path is not provided get from ODB
if (path == "") {
status = db_get_value_string(hDB, 0, "/Sequencer/State/Path", 0, &path, FALSE);
}
if (status != DB_SUCCESS) {
return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
}
path = cm_expand_env(path.c_str());
if (subdir.length() > 0) {
if (path[path.length()-1] != DIR_SEPARATOR) {
path += DIR_SEPARATOR_STR;
}
path += subdir;
}
char* flist = NULL;
//printf("path: [%s]\n", path.c_str());
MJsonNode* s = MJsonNode::MakeArray();
/*---- go over subdirectories ----*/
int n = ss_dir_find(path.c_str(), "*", &flist);
for (int i=0 ; i<n ; i++) {
if (flist[i*MAX_STRING_LENGTH] != '.') {
//printf("subdir %d: [%s]\n", i, flist+i*MAX_STRING_LENGTH);
ss_repair_utf8(flist+i*MAX_STRING_LENGTH);
s->AddToArray(MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH));
}
}
MJsonNode* f = MJsonNode::MakeArray();
/*---- go over files in path ----*/
n = ss_file_find(path.c_str(), fileext.c_str(), &flist);
for (int i=0 ; i<n ; i++) {
//printf("file %d: [%s]\n", i, flist+i*MAX_STRING_LENGTH);
MJsonNode* o = MJsonNode::MakeObject();
ss_repair_utf8(flist+i*MAX_STRING_LENGTH);
o->AddToObject("filename", MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH));
o->AddToObject("description", MJsonNode::MakeString("description"));
f->AddToArray(o);
#if 0
char comment[512];
comment[0] = 0;
strlcpy(str, path, sizeof(str));
if (strlen(str)>1 && str[strlen(str)-1] != DIR_SEPARATOR)
strlcat(str, DIR_SEPARATOR_STR, sizeof(str));
strlcat(str, flist+i*MAX_STRING_LENGTH, sizeof(str));
if (msl_parse(str, error, sizeof(error), &error_line)) {
if (strchr(str, '.')) {
*strchr(str, '.') = 0;
strlcat(str, ".xml", sizeof(str));
}
comment[0] = 0;
if (pnseq) {
mxml_free_tree(pnseq);
pnseq = NULL;
}
pnseq = mxml_parse_file(str, error, sizeof(error), &error_line);
if (error[0]) {
strlcpy(comment, error, sizeof(comment));
} else {
if (pnseq) {
pn = mxml_find_node(pnseq, "RunSequence/Comment");
if (pn)
strlcpy(comment, mxml_get_value(pn), sizeof(comment));
else
strcpy(comment, "<No description in XML file>");
}
}
if (pnseq) {
mxml_free_tree(pnseq);
pnseq = NULL;
}
} else {
sprintf(comment, "Error in MSL: %s", error);
}
strsubst(comment, sizeof(comment), "\"", "\\\'");
r->rsprintf("<option onClick=\"document.getElementById('cmnt').innerHTML='%s'\"", comment);
r->rsprintf(" onDblClick=\"load();\">%s</option>\n", flist+i*MAX_STRING_LENGTH);
#endif
}
free(flist);
flist = NULL;
MJsonNode* r = MJsonNode::MakeObject();
r->AddToObject("status", MJsonNode::MakeInt(SUCCESS));
ss_repair_utf8(path);
r->AddToObject("path", MJsonNode::MakeString(path.c_str()));
r->AddToObject("subdirs", s);
r->AddToObject("files", f);
return mjsonrpc_make_result(r);
}
//
// to create your own rpc method handler, copy one of the examples here, register it in user_init below
//
//
// user_init function is called at startup time to register user rpc method handlers
//
void mjsonrpc_user_init()
{
if (mjsonrpc_debug) {
printf("mjsonrpc_user_init!\n");
}
// add user functions to the rpc list
mjsonrpc_add_handler("user_example1", user_example1);
mjsonrpc_add_handler("user_example2", user_example2);
mjsonrpc_add_handler("user_example3", user_example3);
mjsonrpc_add_handler("any_list_files", js_any_list_files, true);
}
/* emacs
* Local Variables:
* tab-width: 8
* c-basic-offset: 3
* indent-tabs-mode: nil
* End:
*/
|