bes Updated for version 3.20.10
BESXDTransmit.cc
1// BESXDTransmit.cc
2
3// This file is part of bes, A C++ back-end server implementation framework
4// for the OPeNDAP Data Access Protocol.
5
6// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
7// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact University Corporation for Atmospheric Research at
24// 3080 Center Green Drive, Boulder, CO 80301
25
26// Authors:
27// pwest Patrick West <pwest@ucar.edu>
28// jgarcia Jose Garcia <jgarcia@ucar.edu>
29
30#include <libdap/BaseType.h>
31#include <libdap/Sequence.h>
32#include <libdap/ConstraintEvaluator.h>
33#include <libdap/DataDDS.h>
34
35#include <libdap/escaping.h>
36#include <libdap/InternalErr.h>
37#include <libdap/util.h>
38#include <libdap/mime_util.h>
39#include <libdap/XMLWriter.h>
40
41#include <BESUtil.h>
42#include <BESDapTransmit.h>
43#include <BESContainer.h>
44#include <BESDataNames.h>
45#include <BESDataDDSResponse.h>
46#include <BESDapError.h>
47#include <BESInternalFatalError.h>
48#include <BESDebug.h>
49#include <DapFunctionUtils.h>
50
51#include "BESXDTransmit.h"
52#include "get_xml_data.h"
53
54using namespace xml_data;
55using namespace libdap;
56
57void BESXDTransmit::send_basic_ascii(BESResponseObject * obj, BESDataHandlerInterface & dhi)
58{
59 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() - BEGIN" << endl);
60 BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
61 if (!bdds)
62 throw BESInternalFatalError("Expected a BESDataDDSResponse instance.", __FILE__, __LINE__);
63
64 DDS *dds = bdds->get_dds();
65 ConstraintEvaluator & ce = bdds->get_ce();
66
67 dhi.first_container();
68
69 string constraint = www2id(dhi.data[POST_CONSTRAINT], "%", "%20%26");
70
71 try {
72 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() - " "parsing constraint: " << constraint << endl);
73 ce.parse_constraint(constraint, *dds);
74 }
75 catch (InternalErr &e) {
76 string err = "Failed to parse the constraint expression: " + e.get_error_message();
77 throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
78 }
79 catch (Error &e) {
80 string err = "Failed to parse the constraint expression: " + e.get_error_message();
81 throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
82 }
83 catch (...) {
84 string err = (string) "Failed to parse the constraint expression: " + "Unknown exception caught";
85 throw BESInternalFatalError(err, __FILE__, __LINE__);
86 }
87
88 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() - " "tagging sequences" << endl);
89 dds->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
90
91 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() - " "accessing container" << endl);
92 string dataset_name = dhi.container->access();
93
94 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() - dataset_name = " << dataset_name << endl);
95
96 bool functional_constraint = false;
97 try {
98 // Handle *functional* constraint expressions specially
99 if (ce.function_clauses()) {
100 BESDEBUG("xd", "BESXDTransmit::send_base_ascii() Processing functional constraint clause(s)." << endl);
101 DDS *tmp_dds = ce.eval_function_clauses(*dds);
102 delete dds;
103 dds = tmp_dds;
104 bdds->set_dds(dds);
105 // This next step utilizes a well known function, promote_function_output_structures()
106 // to look for one or more top level Structures whose name indicates (by way of ending
107 // with "_uwrap") that their contents should be promoted (aka moved) to the top level.
108 // This is in support of a hack around the current API where server side functions
109 // may only return a single DAP object and not a collection of objects. The name suffix
110 // "_unwrap" is used as a signal from the function to the the various response
111 // builders and transmitters that the representation needs to be altered before
112 // transmission, and that in fact is what happens in our friend
113 // promote_function_output_structures()
114 promote_function_output_structures(dds);
115 }
116 else {
117 // Iterate through the variables in the DataDDS and read
118 // in the data if the variable has the send flag set.
119 for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
120 if ((*i)->send_p()) {
121 (*i)->intern_data(ce, *dds);
122 }
123 }
124 }
125 }
126 catch (InternalErr &e) {
127 if (functional_constraint)
128 delete dds;
129 string err = "Failed to read data: " + e.get_error_message();
130 throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
131 }
132 catch (Error & e) {
133 if (functional_constraint)
134 delete dds;
135 string err = "Failed to read data: " + e.get_error_message();
136 throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
137 }
138 catch (BESError &e) {
139 throw;
140 }
141 catch (...) {
142 if (functional_constraint)
143 delete dds;
144 string err = "Failed to read data: Unknown exception caught";
145 throw BESInternalFatalError(err, __FILE__, __LINE__);
146 }
147
148 try {
149 // Now that we have constrained the DataDDS and read in the data,
150 // send it as ascii
151 BESDEBUG("xd", "converting to xd datadds" << endl);
152 DDS *xd_dds = dds_to_xd_dds(dds);
153
154 // Now that we are ready to start building the response data we
155 // cancel any pending timeout alarm according to the configuration.
157
158 BESDEBUG("xd", "getting xd values" << endl);
159 XMLWriter writer;
160 get_data_values_as_xml(xd_dds, &writer);
161 dhi.get_output_stream() << writer.get_doc();
162
163 BESDEBUG("xd", "got the ascii values" << endl);
164 dhi.get_output_stream() << flush;
165 delete xd_dds;
166
167 BESDEBUG("xd", "done transmitting ascii" << endl);
168 }
169 catch (InternalErr &e) {
170 if (functional_constraint)
171 delete dds;
172 string err = "Failed to get values as ascii: " + e.get_error_message();
173 throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
174 }
175 catch (Error &e) {
176 if (functional_constraint)
177 delete dds;
178 string err = "Failed to get values as ascii: " + e.get_error_message();
179 throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
180 }
181 catch (BESError &e) {
182 throw;
183 }
184 catch (...) {
185 if (functional_constraint)
186 delete dds;
187 string err = "Failed to get values as ascii: Unknown exception caught";
188 throw BESInternalFatalError(err, __FILE__, __LINE__);
189 }
190
191 if (functional_constraint)
192 delete dds;
193}
194
195
virtual std::string access()=0
returns the true name of this container
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void set_dds(libdap::DDS *ddsIn)
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.
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
exception thrown if an internal error is found and is fatal to the BES
Abstract base class representing a specific set of information in response to a request to the BES.
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
Definition: BESUtil.cc:992