bes  Updated for version 3.20.6
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 <BaseType.h>
31 #include <Sequence.h>
32 #include <ConstraintEvaluator.h>
33 #include <DataDDS.h>
34 
35 #include <escaping.h>
36 #include <InternalErr.h>
37 #include <util.h>
38 #include <mime_util.h>
39 #include <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 
54 using namespace xml_data;
55 using namespace libdap;
56 
57 void 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 
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESDataDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDataDDSResponse.h:73
BESUtil::conditional_timeout_cancel
static void conditional_timeout_cancel()
Definition: BESUtil.cc:967
libdap
Definition: BESDapFunctionResponseCache.h:35
BESContainer::access
virtual std::string access()=0
returns the true name of this container
BESDataHandlerInterface::data
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Definition: BESDataHandlerInterface.h:90
BESDataDDSResponse
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Definition: BESDataDDSResponse.h:46
Error
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESDapError
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
BESResponseObject
Abstract base class representing a specific set of information in response to a request to the BES.
Definition: BESResponseObject.h:45