bes  Updated for version 3.20.6
BESAsciiTransmit.cc
1 // BESAsciiTransmit.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 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <memory>
34 
35 #include <BaseType.h>
36 #include <Sequence.h>
37 #include <ConstraintEvaluator.h>
38 #include <D4Group.h>
39 #include <DMR.h>
40 #include <D4ConstraintEvaluator.h>
41 #include <crc.h>
42 #include <InternalErr.h>
43 #include <util.h>
44 #include <escaping.h>
45 #include <mime_util.h>
46 
47 #include <BESUtil.h>
48 #include <BESDapNames.h>
49 #include <BESDataNames.h>
50 #include <BESDapTransmit.h>
51 #include <BESContainer.h>
52 #include <BESDataDDSResponse.h>
53 #include <BESDMRResponse.h>
54 #include <BESDapResponseBuilder.h>
55 
56 #include <BESError.h>
57 #include <BESDapError.h>
58 #include <BESForbiddenError.h>
59 #include <BESInternalFatalError.h>
60 #include <DapFunctionUtils.h>
61 
62 #include <BESDebug.h>
63 
64 #include "BESAsciiTransmit.h"
65 #include "get_ascii.h"
66 #include "get_ascii_dap4.h"
67 
68 using namespace dap_asciival;
69 
70 BESAsciiTransmit::BESAsciiTransmit() :
72 {
73  add_method(DATA_SERVICE, BESAsciiTransmit::send_basic_ascii);
75 }
76 
77 void BESAsciiTransmit::send_basic_ascii(BESResponseObject *obj, BESDataHandlerInterface &dhi)
78 {
79  BESDEBUG("ascii", "BESAsciiTransmit::send_basic_ascii() - BEGIN" << endl);
80 
81  try { // Expanded try block so all DAP errors are caught. ndp 12/23/2015
82  BESDapResponseBuilder responseBuilder;
83 
84  // Now that we are ready to start reading the response data we
85  // cancel any pending timeout alarm according to the configuration.
87 
88  // Use the DDS from the ResponseObject along with the parameters
89  // from the DataHandlerInterface to load the DDS with values.
90  // Note that the BESResponseObject will manage the loaded_dds object's
91  // memory. Make this a shared_ptr<>. jhrg 9/6/16
92  DDS *loaded_dds = responseBuilder.intern_dap2_data(obj, dhi);
93 
94  // Send data values as CSV/ASCII
95  auto_ptr<DDS> ascii_dds(datadds_to_ascii_datadds(loaded_dds)); // unique_ptr<> jhrg 9/6/16
96 
97  get_data_values_as_ascii(ascii_dds.get(), dhi.get_output_stream());
98  dhi.get_output_stream() << flush;
99  }
100  catch (Error &e) {
101  throw BESDapError("Failed to get values as ascii: " + e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
102  }
103  catch (BESError &e) {
104  throw;
105  }
106  catch (std::exception &e) {
107  throw BESInternalError("Failed to read data: STL Error: " + string(e.what()), __FILE__, __LINE__);
108  }
109  catch (...) {
110  throw BESInternalError("Failed to get values as ascii: Unknown exception caught", __FILE__, __LINE__);
111  }
112 
113  BESDEBUG("ascii", "Done BESAsciiTransmit::send_basic_ascii()" << endl);
114 }
115 
120 {
121  BESDEBUG("ascii", "BESAsciiTransmit::send_dap4_csv" << endl);
122 
123  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
124  if (!bdmr) throw BESInternalFatalError("Expected a BESDMRResponse instance.", __FILE__, __LINE__);
125 
126  DMR *dmr = bdmr->get_dmr();
127 
128  string dap4Constraint = www2id(dhi.data[DAP4_CONSTRAINT], "%", "%20%26");
129  string dap4Function = www2id(dhi.data[DAP4_FUNCTION], "%", "%20%26");
130 
131  // Not sure we need this...
132  dhi.first_container();
133 
134  try {
135  // @TODO Handle *functional* constraint expressions specially
136  // Use the D4FunctionDriver class and evaluate the functions, building
137  // a new DMR, then evaluate the D4CE in the context of that DMR.
138  // This might be coded as "if (there's a function) do this else process the CE".
139  // Or it might be coded as "if (there's a function) build the new DMR, then fall
140  // through and process the CE but on the new DMR". jhrg 9/3/14
141 
142  if (!dap4Constraint.empty()) {
143  D4ConstraintEvaluator d4ce(dmr);
144  bool parse_ok = d4ce.parse(dap4Constraint);
145  if (!parse_ok) throw Error(malformed_expr, "Constraint Expression (" + dap4Constraint + ") failed to parse.");
146  }
147  else {
148  dmr->root()->set_send_p(true);
149  }
150 
151  if (dmr->response_limit() != 0 && (dmr->request_size(true) > dmr->response_limit())) {
152  string msg = "The Request for " + long_to_string(dmr->request_size(true))
153  + "KB is too large; requests for this server are limited to " + long_to_string(dmr->response_limit())
154  + "KB.";
155  throw Error(msg);
156  }
157 
158  // Now that we are ready to start building the response data we
159  // cancel any pending timeout alarm according to the configuration.
161 
162  print_values_as_ascii(dmr, dhi.get_output_stream());
163  dhi.get_output_stream() << flush;
164  }
165  catch (Error &e) {
166  throw BESDapError("Failed to return values as ascii: " + e.get_error_message(), false, e.get_error_code(),__FILE__, __LINE__);
167  }
168  catch (BESError &e){
169  throw;
170  }
171  catch (...) {
172  throw BESInternalError("Failed to return values as ascii: Unknown exception caught", __FILE__, __LINE__);
173  }
174 
175  BESDEBUG("ascii", "Done BESAsciiTransmit::send_dap4_csv" << endl);
176 }
177 
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESUtil::conditional_timeout_cancel
static void conditional_timeout_cancel()
Definition: BESUtil.cc:967
BESRequestHandler::add_method
virtual bool add_method(const std::string &name, p_request_handler_method method)
add a handler method to the request handler that knows how to fill in a specific response object
Definition: BESRequestHandler.cc:58
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
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
BESTransmitter
Definition: BESTransmitter.h:47
BESDapResponseBuilder::intern_dap2_data
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Definition: BESDapResponseBuilder.cc:980
BESDapResponseBuilder
Definition: BESDapResponseBuilder.h:53
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
BESAsciiTransmit::send_dap4_csv
static void send_dap4_csv(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Definition: BESAsciiTransmit.cc:119
BESResponseObject
Abstract base class representing a specific set of information in response to a request to the BES.
Definition: BESResponseObject.h:45
BESDMRResponse
Represents an OPeNDAP DMR DAP4 data object within the BES.
Definition: BESDMRResponse.h:39