bool DirectiveService::getDirectives( BtpAction* action, DynamicObject& in, DynamicObject& out) { bool rval = false; UserId userId; if(mNode->checkLogin(action, &userId)) { rval = true; // turn user ID into a key char key[22]; snprintf(key, 22, "%" PRIu64, userId); // return user's directive cache mCacheLock.lock(); { if(mDirectives->hasMember(key)) { out = mDirectives[key]; } else { out->setType(Map); } } mCacheLock.unlock(); } return rval; }
// FIXME: should this be using new JSON-LD frame stuff rather than this? bool JsonLd::filter( DynamicObject& context, DynamicObject& filter, DynamicObject& in, DynamicObject& out, bool simplify) { bool rval; DynamicObject normFilter; DynamicObject normIn; DynamicObject normOut; normOut->setType(Map); // remove contexts rval = removeContext(filter, normFilter) && removeContext(in, normIn); // filter to the output if(rval) { _filter(normFilter, normIn, normOut); // FIXME: fixup graph // Search normOut for unknown references that are in normIn and add them. // Futher optimize by checking reference count and embedding data as // needed. This will result in a graph that is as complete as the input // with regard to references. // flatten in the case of one result if(simplify && normOut->hasMember("@") && normOut["@"]->length() == 1) { normOut = normOut["@"][0]; } } // add context to output rval = rval && addContext(context, normOut, out); return rval; }
/** * Gets the field names and values for a particular X509_NAME. * * For instance, if the subject name is passed, then the "CN" (common name) * value, "C" (country) value, etc. will be added to the output. * * @param name the X509_name, i.e. X509_get_subject_name(mX509). * @param output the array to populate. */ static void _getX509NameValues(X509_NAME* name, DynamicObject& output) { output->setType(Array); unsigned char* value; X509_NAME_ENTRY* entry; int count = X509_NAME_entry_count(name); for(int i = 0; i < count; ++i) { entry = X509_NAME_get_entry(name, i); // get entry name (object) and value (data) ASN1_OBJECT* obj = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); // convert name and value to strings int nid = OBJ_obj2nid(obj); const char* sn = OBJ_nid2sn(nid); if(ASN1_STRING_to_UTF8(&value, str) != -1) { DynamicObject& item = output->append(); item["type"] = sn; item["value"] = value; OPENSSL_free(value); } } }
/** * Recursively applies context to the given input object. * * @param ctx the context to use. * @param usedCtx the used context values. * @param predicate the related predicate or NULL if none. * @param in the input object. * @param out the contextualized output object. */ static void _applyContext( DynamicObject& ctx, DynamicObject& usedCtx, const char* predicate, DynamicObject& in, DynamicObject& out) { if(in.isNull()) { out.setNull(); } else { // initialize output DynamicObjectType inType = in->getType(); out->setType(inType); if(inType == Map) { // add context to each property in the map char* tmp = NULL; DynamicObjectIterator i = in.getIterator(); while(i->hasNext()) { // compact predicate DynamicObject& next = i->next(); DynamicObject cp(NULL); const char* p; if(strcmp(i->getName(), "@") == 0) { p = "@"; } else { cp = _compactString(ctx, usedCtx, NULL, i->getName(), &tmp); p = cp; } // recurse _applyContext(ctx, usedCtx, p, next, out[p]); } free(tmp); } else if(inType == Array) { // apply context to each object in the array DynamicObjectIterator i = in.getIterator(); while(i->hasNext()) { DynamicObject& next = i->next(); _applyContext(ctx, usedCtx, predicate, next, out->append()); } } // only strings need context applied, numbers & booleans don't else if(inType == String) { // compact string char* tmp = NULL; out = _compactString(ctx, usedCtx, predicate, in->getString(), &tmp); free(tmp); } } }
DynamicObject DynamicObjectImpl::getStats() { DynamicObject rval; rval->setType(Map); #if defined(MO_DYNO_COUNTS) || defined(MO_DYNO_KEY_COUNTS) #define MAKESTAT(d, s) \ MO_STMT_START { \ d["counts"]["live"] = s.counts.live; \ d["counts"]["dead"] = s.counts.dead; \ d["counts"]["max"] = s.counts.max; \ d["bytes"]["live"] = s.bytes.live; \ d["bytes"]["dead"] = s.bytes.dead; \ d["bytes"]["max"] = s.bytes.max; \ } MO_STMT_END #endif // defined(MO_DYNO_COUNTS) || defined(MO_DYNO_KEY_COUNTS) #ifdef MO_DYNO_COUNTS #define GETSTAT(s, type) \ MO_STMT_START { \ DynamicObject& d = s[MO_STRINGIFY(type)]; \ MAKESTAT(d, _stats_counts[type]); \ } MO_STMT_END GETSTAT(rval, Object); GETSTAT(rval, String); GETSTAT(rval, Boolean); GETSTAT(rval, Int32); GETSTAT(rval, UInt32); GETSTAT(rval, Int64); GETSTAT(rval, UInt64); GETSTAT(rval, Double); GETSTAT(rval, Map); GETSTAT(rval, Array); GETSTAT(rval, Key); GETSTAT(rval, StringValue); #undef GETSTAT #endif // MO_DYNO_COUNTS #ifdef MO_DYNO_KEY_COUNTS { _stats_key_counts_lock.lock(); DynamicObject& d = rval["KeyCounts"]; d["count"] = _stats_key_counts.size(); d["keys"]->setType(Map); _StatsKeyMap::iterator i = _stats_key_counts.begin(); for(; i != _stats_key_counts.end(); ++i) { // create new stat entry DynamicObject& s = d["keys"][i->first]; MAKESTAT(s, _stats_key_counts[i->first]); } _stats_key_counts_lock.unlock(); } #endif // MO_DYNO_KEY_COUNTS return rval; }
DynamicObject& Exception::getDetails() { if(mDetails->isNull()) { DynamicObject details; details->setType(Map); *mDetails = details; } return *mDetails; }
/** * Recursively removes context from the given input object. * * @param ctx the context to use (changes during recursion as necessary). * @param in the input object. * @param out the normalized output object. * @param bnodeId the last blank node ID used. * * @return true on success, false on failure with exception set. */ static bool _removeContext( DynamicObject& ctx, DynamicObject& in, DynamicObject& out, int& bnodeId) { bool rval = true; if(in.isNull()) { out.setNull(); } else { // initialize output DynamicObjectType inType = in->getType(); out->setType(inType); // update context if(inType == Map && in->hasMember("#")) { ctx = in["#"]; } if(inType == Map) { rval = _normalize(ctx, in, NULL, &out, bnodeId); } else if(inType == Array) { // strip context from each object in the array DynamicObjectIterator i = in.getIterator(); while(i->hasNext()) { DynamicObject& next = i->next(); rval = _removeContext(ctx, next, out->append(), bnodeId); } } } return rval; }
static void runConfigManagerTest(TestRunner& tr) { tr.group("ConfigManager"); tr.test("init"); { DynamicObject expect; expect->setType(Map); ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]->setType(Map); assert(cm.addConfig(cfg)); assertDynoCmp(cm.getConfig("config", true), cfg); assertDynoCmp(cm.getConfig("config", false), expect); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("init & clear"); { DynamicObject expect; expect->setType(Map); ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]->setType(Map); assert(cm.addConfig(cfg)); cm.clear(); Config cfg2 = cm.getConfig("config"); assert(cfg2.isNull()); } tr.passIfException(); tr.test("1 config"); { DynamicObject expect; expect->setType(Map); expect["a"] = 0; ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]["a"] = 0; assert(cm.addConfig(cfg)); assertNoExceptionSet(); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("config change"); { ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]["a"] = 0; assert(cm.addConfig(cfg)); DynamicObject a; a["a"] = 0; assertDynoCmp(cm.getConfig("config"), a); Config change = cm.getConfig("config", true); change[ConfigManager::MERGE]["a"] = 1; assert(cm.setConfig(change)); DynamicObject expect; expect["a"] = 1; assert(cm.getConfig("config") != a); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("invalid set config"); { ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]["a"] = 0; assert(!cm.setConfig(cfg)); } tr.passIfException(); tr.test("double add config"); { ConfigManager cm; Config cfg; cfg[ConfigManager::ID] = "config"; cfg[ConfigManager::MERGE]["a"] = 0; assert(cm.addConfig(cfg)); cfg[ConfigManager::MERGE]["a"] = 1; assert(cm.addConfig(cfg)); DynamicObject expect; expect["a"] = 1; assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("add"); { DynamicObject expect; expect["a"] = 0; expect["b"] = 1; expect["c"] = 2; ConfigManager cm; Config a; a[ConfigManager::ID] = "config"; a[ConfigManager::MERGE]["a"] = 0; Config b; b[ConfigManager::ID] = "config"; b[ConfigManager::MERGE]["b"] = 1; Config c; c[ConfigManager::ID] = "config"; c[ConfigManager::MERGE]["c"] = 2; assert(cm.addConfig(a)); assertNoExceptionSet(); assert(cm.addConfig(b)); assertNoExceptionSet(); assert(cm.addConfig(c)); assertNoExceptionSet(); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("bad remove"); { ConfigManager cm; assert(!cm.removeConfig("error")); assertExceptionSet(); Exception::clear(); } tr.passIfNoException(); tr.test("remove"); { DynamicObject expect; expect["a"] = 0; expect["b"] = 1; expect["c"] = 2; ConfigManager cm; Config a; a[ConfigManager::ID] = "config a"; a[ConfigManager::GROUP] = "group"; a[ConfigManager::MERGE]["a"] = 0; Config b; b[ConfigManager::ID] = "config b"; b[ConfigManager::GROUP] = "group"; b[ConfigManager::MERGE]["b"] = 1; Config c; c[ConfigManager::ID] = "config c"; c[ConfigManager::GROUP] = "group"; c[ConfigManager::MERGE]["c"] = 2; assert(cm.addConfig(a)); assertNoExceptionSet(); assert(cm.addConfig(b)); assertNoExceptionSet(); assert(cm.addConfig(c)); assertNoExceptionSet(); assertDynoCmp(cm.getConfig("group"), expect); DynamicObject expect2; expect2["a"] = 0; expect2["c"] = 2; assert(cm.removeConfig("config b")); assertDynoCmp(cm.getConfig("group"), expect2); } tr.passIfNoException(); tr.test("default value"); { ConfigManager cm; Config a; a[ConfigManager::ID] = "config a"; a[ConfigManager::MERGE] = 1; assert(cm.addConfig(a)); assertNoExceptionSet(); Config b; b[ConfigManager::ID] = "config b"; b[ConfigManager::PARENT] = "config a"; b[ConfigManager::MERGE] = ConfigManager::DEFAULT_VALUE; assert(cm.addConfig(b)); assertNoExceptionSet(); DynamicObject expect; expect = 1; assertDynoCmp(cm.getConfig("config b"), expect); } tr.passIfNoException(); tr.test("default values"); { ConfigManager cm; Config cfga; cfga[ConfigManager::ID] = "config a"; Config& a = cfga[ConfigManager::MERGE]; a[0] = 10; a[1] = 11; a[2]["0"] = 120; a[2]["1"] = 121; assert(cm.addConfig(cfga)); assertNoExceptionSet(); Config cfgb; cfgb[ConfigManager::ID] = "config b"; cfgb[ConfigManager::PARENT] = "config a"; Config& b = cfgb[ConfigManager::MERGE]; b[0] = ConfigManager::DEFAULT_VALUE; b[1] = 21; b[2]["0"] = ConfigManager::DEFAULT_VALUE; b[2]["1"] = 221; assert(cm.addConfig(cfgb)); assertNoExceptionSet(); DynamicObject expect; expect[0] = 10; expect[1] = 21; expect[2]["0"] = 120; expect[2]["1"] = 221; assertDynoCmp(cm.getConfig("config b"), expect); } tr.passIfNoException(); tr.test("keyword substitution {RESOURCE_DIR}"); { DynamicObject expect; expect["dir"] = "/the/real/dir"; expect["dir-plus"] = "/the/real/dir/plus/more"; //expect["name"] = "Digital Bazaar, Inc."; ConfigManager cm; Config a; a[ConfigManager::ID] = "config"; a[ConfigManager::MERGE]["dir"] = "{RESOURCE_DIR}"; a[ConfigManager::MERGE]["dir-plus"] = "{RESOURCE_DIR}/plus/more"; // FIXME: only supports "{RESOURCE_DIR}" now //a[ConfigManager::MERGE]["other"] = "{DB}"; cm.setKeyword("RESOURCE_DIR", "/the/real/dir"); //cm.setKeyword("DB", "Digital Bazaar, Inc."); assert(cm.addConfig(a)); assertNoExceptionSet(); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("keyword substitution {CURRENT_DIR}"); { DynamicObject expect; string cwd; string cwdPlusMore; string absoluteDir; File configFile = File::createTempFile("test-config-file"); FileOutputStream fos(configFile); // create and populate the config file string configFileText = "{\n" "\"_id_\": \"config\",\n" "\"_merge_\": {\n" " \"dir\": \"{CURRENT_DIR}\",\n" " \"dir-plus\": \"{CURRENT_DIR}/plus/more\" }\n" "}\n"; fos.write(configFileText.c_str(), configFileText.length()); fos.close(); // modify the current working directory to the expected value absoluteDir = File::dirname(configFile->getAbsolutePath()); cwd = absoluteDir.c_str(); cwdPlusMore = cwd.c_str(); cwdPlusMore.append("/plus/more"); // set the expected values expect["dir"] = cwd.c_str(); expect["dir-plus"] = cwdPlusMore.c_str(); // create the configuration ConfigManager cm; assert(cm.addConfigFile(configFile->getAbsolutePath(), true, absoluteDir.c_str(), true, false)); assertNoExceptionSet(); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); #if 0 tr.test("user preferences"); { ConfigManager cm; // node // built in or loaded defaults DynamicObject nodec; nodec["node"]["host"] = "localhost"; nodec["node"]["port"] = 19100; nodec["node"]["modulePath"]->append("/usr/lib/bitmunk/modules"); nodec["node"]["userModulePath"] = "~/.bitmunk/modules"; assert(cm.addConfig(nodec)); assertNoExceptionSet(); // user // loaded defaults DynamicObject userc; userc["node"]["port"] = 19100; userc["node"]["comment"] = "My precious..."; assert(cm.addConfig(userc, ConfigManager::Custom)); assertNoExceptionSet(); // user makes changes during runtime DynamicObject c = cm.getConfig(); c["node"]["port"] = 19200; c["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev"; c["node"][ConfigManager::TMP]["not in changes"] = true; // get the changes from defaults to current config // serialize this to disk as needed DynamicObject changes; cm.getChanges(changes); // check it's correct DynamicObject expect; expect["node"]["port"] = 19200; expect["node"]["comment"] = "My precious..."; expect["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev"; // NOTE: will not have TMP var assertDynoCmp(changes, expect); } tr.passIfNoException(); #endif tr.test("versioning"); { ConfigManager cm; cm.getVersions()->clear(); Config c; c[ConfigManager::ID] = "config"; assert(cm.addConfig(c)); assertNoExceptionSet(); // config has no version - no check done - pass cm.addVersion("1"); assert(cm.addConfig(c)); assertNoExceptionSet(); // config has known version - pass c[ConfigManager::VERSION] = "1"; assert(cm.addConfig(c)); assertNoExceptionSet(); assert(cm.removeConfig("config")); // config has unknown version - fail c[ConfigManager::VERSION] = "2"; assert(!cm.addConfig(c)); assertExceptionSet(); Exception::clear(); } tr.passIfNoException(); tr.test("empty array & map"); { ConfigManager cm; DynamicObject a; a[ConfigManager::ID] = "config"; a[ConfigManager::MERGE][0]->setType(Array); a[ConfigManager::MERGE][1]->setType(Map); assert(cm.addConfig(a)); assertNoExceptionSet(); DynamicObject expect; expect[0]->setType(Array); expect[1]->setType(Map); assertDynoCmp(cm.getConfig("config"), expect); } tr.passIfNoException(); tr.test("empty group ids"); { ConfigManager cm; DynamicObject expect; expect->setType(Array); assertDynoCmp(cm.getIdsInGroup("Not-A-Group"), expect); } tr.passIfNoException(); tr.test("group ids"); { ConfigManager cm; DynamicObject c; c[ConfigManager::ID] = "c0"; c[ConfigManager::GROUP] = "c"; assert(cm.addConfig(c)); assertNoExceptionSet(); c[ConfigManager::ID] = "c1"; c[ConfigManager::GROUP] = "c"; assert(cm.addConfig(c)); assertNoExceptionSet(); DynamicObject expect; expect->setType(Array); expect[0] = "c0"; expect[1] = "c1"; assertDynoCmp(cm.getIdsInGroup("c"), expect); } tr.passIfNoException(); tr.test("replace keywords"); { ConfigManager cm; DynamicObject c; c[ConfigManager::ID] = "c"; c[ConfigManager::MERGE]["test"] = "{A}"; DynamicObject vars; vars["A"] = "a"; assertNoException(ConfigManager::replaceKeywords(c, vars)); DynamicObject expect; expect[ConfigManager::ID] = "c"; expect[ConfigManager::MERGE]["test"] = "a"; assertDynoCmp(c, expect); } tr.passIfNoException(); tr.test("replace keywords (invalid keyword)"); { ConfigManager cm; DynamicObject c; c[ConfigManager::ID] = "c"; c[ConfigManager::MERGE]["test"] = "{UNKNOWN}"; DynamicObject vars; vars["A"] = "a"; assertException(ConfigManager::replaceKeywords(c, vars)); } tr.passIfException(); tr.ungroup(); }
static void runNodeMonitorTest(TestRunner& tr) { tr.group("NodeMonitor"); tr.test("empty"); { NodeMonitor nm; DynamicObject expect; expect->setType(Map); DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("add1 init"); { bool r; NodeMonitor nm; DynamicObject si; si["init"] = "foo"; r = nm.addState("s", si); assert(r); DynamicObject expect; expect["s"] = "foo"; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("addN init"); { bool r; NodeMonitor nm; DynamicObject si; si["s"]["init"] = "foo"; si["u"]["init"] = (uint64_t)0; si["i"]["init"] = (int64_t)0; si["d"]["init"] = 0.; r = nm.addStates(si); assert(r); DynamicObject expect; expect["s"] = "foo"; expect["u"] = (uint64_t)0; expect["i"] = (int64_t)0; expect["d"] = 0.; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("remove"); { bool r; NodeMonitor nm; DynamicObject si; si["n"]["init"] = (uint64_t)0; si["rem"]["init"] = (uint64_t)0; r = nm.addStates(si); assert(r); DynamicObject s; s["rem"].setNull(); r = nm.removeStates(s); assert(r); DynamicObject expect; expect["n"] = (uint64_t)0; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("set"); { bool r; NodeMonitor nm; DynamicObject si; si["n"]["init"] = (uint64_t)0; r = nm.addStates(si); assert(r); DynamicObject s; s["n"] = (uint64_t)123; r = nm.setStates(s); assert(r); DynamicObject expect; expect["n"] = (uint64_t)123; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("adj"); { bool r; NodeMonitor nm; DynamicObject si; si["n"]["init"] = (uint64_t)0; r = nm.addStates(si); assert(r); DynamicObject s; s["n"] = (uint64_t)1; r = nm.adjustStates(s); assert(r); r = nm.adjustStates(s); assert(r); r = nm.adjustStates(s); assert(r); DynamicObject expect; expect["n"] = (uint64_t)3; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("reset"); { bool r; NodeMonitor nm; DynamicObject si; si["n"]["init"] = (uint64_t)100; r = nm.addStates(si); assert(r); DynamicObject s; s["n"] = (uint64_t)123; r = nm.setStates(s); assert(r); r = nm.resetStates(s); assert(r); DynamicObject expect; expect["n"] = (uint64_t)100; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("adj neg"); { bool r; NodeMonitor nm; DynamicObject si; si["n"]["init"] = (uint64_t)100; r = nm.addStates(si); assert(r); DynamicObject s; s["n"] = (int64_t)-1; r = nm.adjustStates(s); assert(r); DynamicObject expect; expect["n"] = (uint64_t)99; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("getN"); { bool r; NodeMonitor nm; DynamicObject si; si["a"]["init"] = "a"; si["b"]["init"] = "b"; si["c"]["init"] = "c"; r = nm.addStates(si); assert(r); DynamicObject s; s["b"].setNull(); s["c"].setNull(); r = nm.getStates(s); assert(r); DynamicObject expect; expect["b"] = "b"; expect["c"] = "c"; assertDynoCmp(expect, s); } tr.passIfNoException(); tr.test("add ex"); { NodeMonitor nm; DynamicObject si; si["bad"] = 0; assertException(nm.addStates(si)); Exception::clear(); } tr.passIfNoException(); tr.test("rem ex"); { NodeMonitor nm; DynamicObject s; s["a"] = 0; assertException(nm.removeStates(s)); Exception::clear(); } tr.passIfNoException(); // Not for use with async StateMonitor implementation. /* tr.test("set ex"); { bool r; NodeMonitor nm; DynamicObject s; s["a"] = 0; assertException(nm.setStates(s)); Exception::clear(); } tr.passIfNoException(); */ tr.test("get ex"); { NodeMonitor nm; DynamicObject s; s["a"] = 0; assertException(nm.getStates(s)); Exception::clear(); } tr.passIfNoException(); tr.test("adj ex"); { NodeMonitor nm; DynamicObject s; s["a"] = 1; assertException(nm.adjustStates(s)); Exception::clear(); } tr.passIfNoException(); tr.test("adj type ex"); { NodeMonitor nm; DynamicObject si; si["a"]["init"] = (uint64_t)0; assertNoException( nm.addStates(si)); // Not for use with async StateMonitor implementation. /* DynamicObject s; s["a"] = 0.; assertException(nm.adjustStates(s)); Exception::clear(); */ } tr.passIfNoException(); tr.test("txn adj ex"); { // check bad transaction doesn't change values NodeMonitor nm; DynamicObject si; si["a"]["init"] = (uint64_t)10; si["b"]["init"] = (uint64_t)10; assertNoException( nm.addStates(si)); // Not for use with async StateMonitor implementation. /* DynamicObject s; s["a"] = (int64_t)-1; s["b"] = -1.; assertException(nm.adjustStates(s)); Exception::clear(); */ DynamicObject expect; expect["a"] = (uint64_t)10; expect["b"] = (uint64_t)10; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.test("no ex"); { NodeMonitor nm; DynamicObject si; si["a"]["init"] = (uint64_t)10; assertNoException( nm.addStates(si)); DynamicObject s; s["bad"] = (int64_t)-1; assertException(nm.adjustStates(s)); Exception::clear(); DynamicObject expect; expect["a"] = (uint64_t)10; DynamicObject all = nm.getAll(); assertDynoCmp(expect, all); } tr.passIfNoException(); tr.ungroup(); }
bool WebServiceContainer::addService( WebServiceRef& service, WebService::SecurityType st, bool initialize, const char* domain) { bool rval = true; if(initialize) { rval = service->initialize(); } if(rval) { // build list of domains to add service to DynamicObject domains(NULL); DynamicObject added; added->setType(Array); if(domain != NULL) { domains = DynamicObject(); domains->append(domain); } else { domains = mDefaultDomains; } HttpRequestServicer* hrs = &(*service); const char* path = hrs->getPath(); // prevent other container access mContainerLock.lockExclusive(); DynamicObjectIterator di = domains.getIterator(); while(rval && di->hasNext()) { const char* dom = di->next()->getString(); rval = internalAddService(service, st, dom); if(rval) { added->append(dom); } } di = rval ? domains.getIterator() : added.getIterator(); while(di->hasNext()) { const char* dom = di->next()->getString(); // success, add domain to http servicer if(rval) { if(st == WebService::Secure || st == WebService::Both) { mHttpConnectionServicer.addRequestServicer(hrs, true, dom); MO_CAT_DEBUG(MO_WS_CAT, "Added secure web service: %s%s", dom, path); } if(st != WebService::Secure) { mHttpConnectionServicer.addRequestServicer(hrs, false, dom); MO_CAT_DEBUG(MO_WS_CAT, "Added non-secure web service: %s%s", dom, path); } } // could not add service to all domains, so remove it else { internalRemoveService(path, st, dom, NULL); } } // permit access again mContainerLock.unlockExclusive(); } // failed to add service if(!rval) { // service was initialized, so clean it up if(initialize) { service->cleanup(); } // set exception ExceptionRef e = new Exception( "Could not add web service.", "monarch.ws.AddWebServiceFailure"); Exception::push(e); } return rval; }
bool DomWriter::write(Element& e, OutputStream* os, int level) { DynamicObject nsPrefixMap; nsPrefixMap->setType(Map); return writeWithNamespaceSupport(e, os, level, nsPrefixMap); }
bool JsonLd::normalize(DynamicObject& in, DynamicObject& out) { bool rval = true; // initialize output out->setType(Map); out->clear(); // create map to store subjects DynamicObject subjects; subjects->setType(Map); // initialize context DynamicObject ctx(NULL); if(in->hasMember("#")) { ctx = in["#"]; } // put all subjects in an array for single code path DynamicObject input; input->setType(Array); if(in->hasMember("@") && in["@"]->getType() == Array) { input.merge(in["@"], true); } else { input->append(in); } // do normalization int bnodeId = 0; DynamicObjectIterator i = input.getIterator(); while(rval && i->hasNext()) { rval = _normalize(ctx, i->next(), &subjects, NULL, bnodeId); } // build output if(rval) { // single subject if(subjects->length() == 1) { DynamicObject subject = subjects.first(); out.merge(subject, false); // FIXME: will need to check predicates for blank nodes as well... // and fail if they aren't embeds? // strip blank node '@' if(_isBlankNode(out)) { out->removeMember("@"); } } // multiple subjects else { DynamicObject& array = out["@"]; array->setType(Array); i = subjects.getIterator(); while(i->hasNext()) { DynamicObject& next = i->next(); // FIXME: will need to check predicates for blank nodes as well... // and fail if they aren't embeds? // strip blank node '@' if(_isBlankNode(next)) { next->removeMember("@"); } array->append(next); } } } return rval; }
/** * Recursively normalizes the given input object. * * Input: A subject with predicates and possibly embedded other subjects. * Output: Either a map of normalized subjects OR a tree of normalized subjects. * * Normalization Algorithm: * * Replace the existing context if the input has '#'. * * For each key-value: * 1. Split the key on a colon and look for prefix in the context. If found, * expand the key to an IRI, else it is already an IRI, add <>, save the * new predicate to add to the output. * 2. If value is a Map, then it is a subject, set the predicate to the * subject's '@' IRI value and recurse into it. Else goto #3. * 3. Look up the key in the context to find type coercion info. If not found, * goto #4, else goto #5. * 4. Check the value for an integer, double, or boolean. If matched, set * type according to xsd types. If not matched, look for <>, if found, * do CURIE vs. IRI check like #1 and create appropriate value. * 5. If type coercion entry is a string, encode the value using the specific * type. If it is an array, check the type in order of preference. If an * unrecognized type (non-xsd, non-IRI) is provided, throw an exception. * * @param ctx the context to use (changes during recursion as necessary). * @param in the input object. * @param subjects a map of normalized subjects. * @param out a tree normalized objects. * @param bnodeId the last blank node ID used. * * @return true on success, false on failure with exception set. */ static bool _normalize( DynamicObject ctx, DynamicObject& in, DynamicObject* subjects, DynamicObject* out, int& bnodeId) { bool rval = true; // FIXME: validate context (check for non-xsd types in type coercion arrays) if(!in.isNull()) { // update context if(in->hasMember("#")) { ctx = in["#"]; } // vars for normalization state DynamicObject subject(NULL); if(subjects != NULL) { subject = DynamicObject(); subject->setType(Map); // assign blank node ID as needed if(!in->hasMember("@")) { string bnodeKey = _createBlankNodeId(++bnodeId); subject["@"] = bnodeKey.c_str(); } } string nKey; // iterate over key-values DynamicObjectIterator i = in.getIterator(); while(rval && i->hasNext()) { DynamicObject& value = i->next(); const char* key = i->getName(); // skip context keys if(key[0] == '#') { continue; } // get normalized key nKey = _normalizeValue(ctx, key, RDF_TYPE_IRI, NULL, NULL); // put values in an array for single code path DynamicObject values; values->setType(Array); if(value->getType() == Array) { values.merge(value, true); // preserve array structure when not using subjects map if(out != NULL) { (*out)[nKey.c_str()]->setType(Array); } } else { values->append(value); } // normalize all values DynamicObjectIterator vi = values.getIterator(); while(rval && vi->hasNext()) { DynamicObject v = vi->next(); if(v->getType() == Map) { if(subjects != NULL) { // get a normalized subject for the value string vSubject; if(v->hasMember("@")) { // normalize existing subject vSubject = _normalizeValue( ctx, v["@"], RDF_TYPE_IRI, NULL, NULL); } else { // generate the next blank node ID in order to preserve // the blank node embed in the code below vSubject = _createBlankNodeId(bnodeId + 1); } // determine if value is a blank node bool isBNode = _isBlankNode(v); // update non-blank node subject (use value's subject IRI) if(!isBNode) { _setPredicate(subject, nKey.c_str(), vSubject.c_str()); } // recurse rval = _normalize(ctx, v, subjects, out, bnodeId); // preserve embedded blank node if(rval && isBNode) { // remove embed from top-level subjects DynamicObject embed = (*subjects)[vSubject.c_str()]; (*subjects)->removeMember(vSubject.c_str()); embed->removeMember("@"); _setEmbed(subject, nKey.c_str(), embed); } } else { // update out and recurse DynamicObject next = (*out)[nKey.c_str()]; if(value->getType() == Array) { next = next->append(); } else { next->setType(Map); } rval = _normalize(ctx, v, subjects, &next, bnodeId); } } else { _setPredicate( (subjects != NULL) ? subject : *out, nKey.c_str(), _normalizeValue(ctx, v, RDF_TYPE_UNKNOWN, key, NULL).c_str()); } } } // add subject to map if(subjects != NULL) { (*subjects)[subject["@"]->getString()] = subject; } } return rval; }
void DatabaseClient::buildParams( SchemaObject& schema, DynamicObject& members, DynamicObject& params, const char* tableAlias) { // ensure params is an array params->setType(Array); // create shared table alias object DynamicObject taObj(NULL); if(tableAlias != NULL) { taObj = DynamicObject(); taObj = tableAlias; } // map the given members object into a list of parameters that can // be used to generate sql and set parameter values DynamicObjectIterator i = schema["columns"].getIterator(); while(i->hasNext()) { DynamicObject& column = i->next(); const char* memberName = column["memberName"]->getString(); // if the members map contains the given member name, create a param // for it and append it to the params array if(members->hasMember(memberName)) { /* Note: The member value is either a value, map, or an array. If it's * an array, then each entry in the array is either a value or a map. * * Create a single parameter for all values. Create an individual * parameter for every map entry. This algorithm will store all maps * in "p" and all values in "values". Then "values" will be added to * "p". Then a new parameter will be created for each entry in "p". */ DynamicObject& mv = members[memberName]; DynamicObject p(Array); DynamicObject values(Array); // group maps and values if(mv->getType() == Map) { p->append(mv); } else if(mv->getType() == Array) { DynamicObjectIterator mvi = mv.getIterator(); while(mvi->hasNext()) { DynamicObject& next = mvi->next(); if(next->getType() == Map) { p->append(next); } else { values->append(next); } } } else { values->append(mv); } // treat values as a single param if(values->length() > 0) { p->append(values); } // create params DynamicObjectIterator pi = p.getIterator(); while(pi->hasNext()) { DynamicObject& next = pi->next(); // add param DynamicObject& param = params->append(); param["name"] = column["name"]; param["type"] = column["columnType"]; param["op"] = "="; param["boolOp"] = "AND"; if(column->hasMember("encode")) { param["encode"] = column["encode"]; } if(tableAlias != NULL) { param["tableAlias"] = taObj; } // if next param is a map, get operator and value if(next->getType() == Map) { if(next->hasMember("op")) { param["op"] = next["op"].clone(); } if(next->hasMember("boolOp")) { param["boolOp"] = next["boolOp"].clone(); } param["value"] = next["value"].clone(); } else { param["value"] = next.clone(); } } } } }