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("() - ")
61 BESXMLInterface::BESXMLInterface(
const string &xml_doc, ostream *strm) :
66 d_dhi_ptr = &d_xml_interface_dhi;
69 BESXMLInterface::~BESXMLInterface()
78 BESDEBUG(
"bes", prolog <<
"BEGIN" << endl);
79 BESDEBUG(
"bes", prolog <<
"Building request plan for xml document: " << endl << d_xml_document << endl);
89 xmlNode *root_element = NULL;
90 xmlNode *current_node = NULL;
94 vector<string> parseerrors;
98 doc = xmlReadMemory(d_xml_document.c_str(), d_xml_document.size(),
"" ,
99 NULL , XML_PARSE_NONET );
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 d_xml_cmd_list.push_back(current_cmd);
181 if (has_response && cmd_has_response)
182 throw BESSyntaxUserError(
"Commands with multiple responses not supported.", __FILE__, __LINE__);
184 has_response = cmd_has_response;
196 string return_as = current_dhi.
data[RETURN_CMD];
197 if (!return_as.empty() && !BESReturnManager::TheManager()->find_transmitter(return_as))
198 throw BESSyntaxUserError(
string(
"Unable to find transmitter ").append(return_as), __FILE__,
202 current_node = current_node->next;
225 BESDEBUG(
"bes",
"Done building request plan" << endl);
232 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
233 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
234 for (; i != e; i++) {
235 (*i)->prep_request();
246 #ifdef LOG_ONLY_GET_COMMANDS
251 string log_delim=
"|&|";
253 string new_log_info =
"";
257 string olfs_log_line = BESContextManager::TheManager()->
get_context(
"olfsLog", found);
259 new_log_info.append(
"OLFS").append(log_delim).append(olfs_log_line).append(log_delim);
260 new_log_info.append(
"BES").append(log_delim);
267 new_log_info.append(log_delim).append(
d_dhi_ptr->
data[RETURN_CMD]);
284 REQUEST_LOG(new_log_info << endl);
287 ERROR_LOG(
"The previous command had multiple containers defined, but only the was logged.");
290 if (!BESLog::TheLog()->is_verbose()) {
341 INFO_LOG(
"Transmitting error content: " << strm.str() << endl);
352 if (!return_as.empty()) {
353 d_transmitter = BESReturnManager::TheManager()->find_transmitter(return_as);
355 throw BESSyntaxUserError(
string(
"Unable to find transmitter ") + return_as, __FILE__, __LINE__);
372 if (BESLog::TheLog()->is_verbose()) {
373 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
374 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
375 for (; i != e; i++) {
391 vector<BESXMLCommand *>::iterator i = d_xml_cmd_list.begin();
392 vector<BESXMLCommand *>::iterator e = d_xml_cmd_list.end();
393 for (; i != e; i++) {
406 d_xml_cmd_list.clear();
417 strm << BESIndent::LMarg <<
"BESXMLInterface::dump - (" << (
void *)
this <<
")" << endl;
420 vector<BESXMLCommand *>::const_iterator i = d_xml_cmd_list.begin();
421 vector<BESXMLCommand *>::const_iterator e = d_xml_cmd_list.end();
422 for (; i != e; i++) {
426 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.
virtual void dump(std::ostream &strm) const
dumps information about this object
BESDataHandlerInterface * d_dhi_ptr
Allocated by the child class.
BESTransmitter * d_transmitter
The Transmitter to use for the result.
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 BESDataHandlerInterface & get_xmlcmd_dhi()
Return the current BESDataHandlerInterface.
virtual bool has_response()=0
Does this command return a response to the client?
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.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void transmit_data()
Transmit the response object.
virtual void clean()
Clean up after the request is completed.
virtual void build_data_request_plan()
Build the data request plan using the BESCmdParser.
virtual void log_status()
Log the status of the request to the BESLog file.
virtual void execute_data_request_plan()
Execute the data request plan.
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.