40#include "BESXMLInterface.h"
41#include "BESXMLCommand.h"
42#include "BESXMLUtils.h"
43#include "BESDataNames.h"
44#include "BESResponseNames.h"
45#include "BESContextManager.h"
47#include "BESResponseHandler.h"
48#include "BESReturnManager.h"
50#include "BESStopWatch.h"
51#include "TheBESKeys.h"
55#include "BESSyntaxUserError.h"
57#define LOG_ONLY_GET_COMMANDS
59#define prolog std::string("BESXMLInterface::").append(__func__).append("() - ")
61BESXMLInterface::BESXMLInterface(
const string &xml_doc, ostream *strm) :
66 d_dhi_ptr = &d_xml_interface_dhi;
69BESXMLInterface::~BESXMLInterface()
78 BESDEBUG(
"bes", prolog <<
"BEGIN" << endl);
79 BESDEBUG(
"bes", prolog <<
"Building request plan for xml document: " << endl << d_xml_document << endl);
88 xmlDoc *doc =
nullptr;
89 xmlNode *root_element =
nullptr;
90 xmlNode *current_node =
nullptr;
94 vector<string> parseerrors;
98 doc = xmlReadMemory(d_xml_document.c_str(), (
int)d_xml_document.size(),
"" ,
99 nullptr , XML_PARSE_NONET );
101 if (doc ==
nullptr) {
102 string err =
"Problem parsing the request xml document:\n";
104 vector<string>::const_iterator i = parseerrors.begin();
105 vector<string>::const_iterator e = parseerrors.end();
106 for (; i != e; i++) {
107 if (!isfirst && (*i).compare(0, 6,
"Entity") == 0) {
117 root_element = xmlDocGetRootElement(doc);
118 if (!root_element)
throw BESSyntaxUserError(
"There is no root element in the xml document", __FILE__, __LINE__);
122 map<string, string> attributes;
124 if (root_name !=
"request")
126 string(
"The root element should be a request element, name is ").append((
char *) root_element->name),
129 if (!root_val.empty())
130 throw BESSyntaxUserError(
string(
"The request element must not contain a value, ").append(root_val),
134 string &reqId = attributes[REQUEST_ID];
135 if (reqId.empty())
throw BESSyntaxUserError(
"The request id value empty", __FILE__, __LINE__);
139 BESDEBUG(
"besxml",
"request id = " <<
d_dhi_ptr->
data[REQUEST_ID] << endl);
143 bool has_response =
false;
144 current_node = root_element->children;
146 while (current_node) {
147 if (current_node->type == XML_ELEMENT_NODE) {
150 string node_name = (
char *) current_node->name;
152 if (node_name == SETCONTAINER_STR) {
155 map<string, string> props;
157 BESDEBUG(MODULE, prolog <<
"In " << SETCONTAINER_STR <<
" element. Value: " << value << endl);
168 throw BESSyntaxUserError(
string(
"Unable to find command for ").append(node_name), __FILE__,
173 throw BESInternalError(
string(
"Failed to build command object for ").append(node_name), __FILE__,
177 if (node_name == SET_CONTEXT_STR) {
190 setContext_xml_dhi.response_handler->
execute(setContext_xml_dhi);
198 d_xml_cmd_list.push_back(current_cmd);
202 if (has_response && cmd_has_response)
203 throw BESSyntaxUserError(
"Commands with multiple responses not supported.", __FILE__, __LINE__);
205 has_response = cmd_has_response;
217 string return_as = current_dhi.
data[RETURN_CMD];
218 if (!return_as.empty() && !BESReturnManager::TheManager()->find_transmitter(return_as))
219 throw BESSyntaxUserError(
string(
"Unable to find transmitter ").append(return_as), __FILE__,
224 current_node = current_node->next;
247 BESDEBUG(
"bes",
"Done building request plan" << endl);
262#ifdef LOG_ONLY_GET_COMMANDS
267 string log_delim=
"|&|";
273 string olfs_log_line = BESContextManager::TheManager()->
get_context(
"olfsLog", found);
275 new_log_info.append(
"OLFS").append(log_delim).append(olfs_log_line).append(log_delim);
276 new_log_info.append(
"BES").append(log_delim);
282 new_log_info.append(log_delim).append(
d_dhi_ptr->
data[RETURN_CMD]);
299 REQUEST_LOG(new_log_info << endl);
302 ERROR_LOG(
"The previous command had multiple containers defined, but only the first was logged.");
305 if (!BESLog::TheLog()->is_verbose()) {
318 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
319 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
320 for (; i != e; i++) {
321 (*i)->prep_request();
366 INFO_LOG(
"Transmitting error content: " << strm.str() << endl);
377 if (!return_as.empty()) {
378 d_transmitter = BESReturnManager::TheManager()->find_transmitter(return_as);
380 throw BESSyntaxUserError(
string(
"Unable to find transmitter ") + return_as, __FILE__, __LINE__);
397 if (BESLog::TheLog()->is_verbose()) {
398 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
399 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
400 for (; i != e; i++) {
416 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
417 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
418 for (; i != e; i++) {
431 d_xml_cmd_list.clear();
442 strm << BESIndent::LMarg <<
"BESXMLInterface::dump - (" << (
void *)
this <<
")" << endl;
445 vector<BESXMLCommand *>::const_iterator i = d_xml_cmd_list.begin();
446 vector<BESXMLCommand *>::const_iterator e = d_xml_cmd_list.end();
447 for (; i != e; i++) {
451 BESIndent::UnIndent();
A container is something that holds data. E.G., a netcdf file or a database entry.
std::string get_dap4_constraint() const
retrieve the constraint expression for this container
std::string get_dap4_function() const
retrieve the constraint expression for this container
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
std::string get_constraint() const
retrieve the constraint expression for this container
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
std::string action
the response object requested, e.g. das, dds
void clean()
clean up any information created within this data handler interface
BESInfo * error_info
error information object
static bool IsSet(const std::string &flagName)
see if the debug context flagName is set to true
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)=0
transmit the informational object
virtual void print(std::ostream &strm)
print the information from this informational object to the specified stream
Entry point into BES, building responses to given requests.
BESDataHandlerInterface * d_dhi_ptr
Allocated by the child class.
BESTransmitter * d_transmitter
The Transmitter to use for the result.
void dump(std::ostream &strm) const override
dumps information about this object
exception thrown if internal error encountered
virtual void execute(BESDataHandlerInterface &dhi)=0
knows how to build a requested response object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)=0
transmit the response object built by the execute command using the specified transmitter object
virtual bool start(std::string name)
error thrown if there is a user syntax error in the request or any other user error
Base class for the BES's commands.
virtual bool has_response()=0
Does this command return a response to the client?
virtual BESDataHandlerInterface & get_xmlcmd_dhi()
Return the current BESDataHandlerInterface.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void parse_request(xmlNode *node)=0
Parse the XML request document beginning at the given node.
static p_xmlcmd_builder find_command(const std::string &cmd_str)
Find the BESXMLCommand creation function with the given name.
void transmit_data() override
Transmit the response object.
void execute_data_request_plan() override
Execute the data request plan.
void clean() override
Clean up after the request is completed.
void log_the_command()
Log information about the command.
void log_status() override
Log the status of the request to the BESLog file.
void build_data_request_plan() override
Build the data request plan using the BESCmdParser.
void dump(std::ostream &strm) const override
dumps information about this object
static void GetNodeInfo(xmlNode *node, std::string &name, std::string &value, std::map< std::string, std::string > &props)
get the name, value if any, and any properties for the specified node
static void XMLErrorFunc(void *context, const char *msg,...)
error function used by libxml2 to report errors
static TheBESKeys * TheKeys()
void load_dynamic_config(std::string name)
Loads the the applicable dynamic configuration or nothing if no configuration is applicable.