OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESDapTransmit.cc
Go to the documentation of this file.
1 // BESDapTransmit.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-2009 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 <DDS.h>
34 #include <DAS.h>
35 #include <ConstraintEvaluator.h>
36 // #include <DMR.h>
37 #include <Error.h>
38 
39 #include "BESDapTransmit.h"
40 #include "BESContainer.h"
41 #include "BESDapNames.h"
42 #include "BESDataNames.h"
43 #include "BESResponseNames.h"
44 
45 #include "BESDASResponse.h"
46 #include "BESDDSResponse.h"
47 #include "BESDataDDSResponse.h"
48 
49 #include "BESDMRResponse.h"
50 
51 #include "BESContextManager.h"
52 #include "BESDapError.h"
53 #include "BESInternalFatalError.h"
54 #include "BESDebug.h"
55 
56 #include "BESDapResponseBuilder.h"
57 
59 // Local Helpers
60 
61 // File local helper superclass for common exception handling
62 // for transmitting DAP responses.
63 class Sender {
64 public:
65  virtual ~Sender()
66  {
67  }
68 
69  // The main call, non-virtual to force exception handling.
70  // Subclasses will override send_internal private virtual.
71  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
72  {
73  string response_string = get_request_type();
74  try {
75  send_internal(obj, dhi);
76  }
77  catch (InternalErr &e) {
78  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
79  throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
80  }
81  catch (Error &e) {
82  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
83  throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
84  }
85  catch (const BESError &e) {
86  throw; // rethrow as is
87  }
88  catch (const std::exception &e) {
89  string msg = "std::exception caught transmitting " + response_string + ": " + e.what() + " (caught in BESDapTransmit).";
90  throw BESInternalFatalError(msg, __FILE__, __LINE__);
91  }
92  catch (...) {
93  string s = "unknown error caught transmitting " + response_string + ": ";
94  BESInternalFatalError ex(s, __FILE__, __LINE__);
95  throw ex;
96  }
97  }
98 
99  // common code for subclasses
100  bool get_print_mime() const
101  {
102  bool found = false;
103  string protocol = BESContextManager::TheManager()->get_context("transmit_protocol", found);
104  bool print_mime = false;
105  if (found && protocol == "HTTP") {
106  print_mime = true;
107  }
108  return print_mime;
109  }
110 
111 private:
112 
113  // Name of the request being sent, for debug
114  virtual string get_request_type() const = 0;
115 
116  // Subclasses impl this for specialized behavior
117  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi) = 0;
118 };
119 
120 class SendDAS: public Sender {
121 private:
122  virtual string get_request_type() const
123  {
124  return "DAS";
125  }
126  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
127  {
128  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(obj);
129  if (!bdas) {
130  throw BESInternalError("cast error", __FILE__, __LINE__);
131  }
132 
133  DAS *das = bdas->get_das();
134  dhi.first_container();
135  bool print_mime = get_print_mime();
136 
139  rb.send_das(dhi.get_output_stream(), *das, print_mime);
140 
141  //rb.send_das(dhi.get_output_stream(), DDS &dds, ConstraintEvaluator &eval, bool constrained, bool with_mime_headers)
142  }
143 };
144 
145 class SendDDS: public Sender {
146 private:
147  virtual string get_request_type() const
148  {
149  return "DDS";
150  }
151  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
152  {
153  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
154  if (!bdds) {
155  throw BESInternalError("cast error", __FILE__, __LINE__);
156  }
157 
158  DDS *dds = bdds->get_dds();
159  ConstraintEvaluator & ce = bdds->get_ce();
160 
161  dhi.first_container();
162  bool print_mime = get_print_mime();
163 
166  rb.set_ce(dhi.data[POST_CONSTRAINT]);
167  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
168  rb.send_dds(dhi.get_output_stream(), *dds, ce, true, print_mime);
169  }
170 };
171 
172 class SendDataDDS: public Sender {
173 private:
174  virtual string get_request_type() const
175  {
176  return "DataDDS";
177  }
178  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
179  {
180  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
181  if (!bdds) {
182  throw BESInternalError("cast error", __FILE__, __LINE__);
183  }
184 
185  DataDDS *dds = bdds->get_dds();
186  ConstraintEvaluator & ce = bdds->get_ce();
187 
188  dhi.first_container();
189  bool print_mime = get_print_mime();
190 
192  rb.set_dataset_name(dds->filename());
193  rb.set_ce(dhi.data[POST_CONSTRAINT]);
194 
195  rb.set_async_accepted(dhi.data[ASYNC]);
197 
198  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
199  rb.send_dap2_data(dhi.get_output_stream(), *dds, ce, print_mime);
200  }
201 };
202 
203 class SendDDX: public Sender {
204 private:
205  virtual string get_request_type() const
206  {
207  return "DDX";
208  }
209  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
210  {
211  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
212  if (!bdds) {
213  throw BESInternalError("cast error", __FILE__, __LINE__);
214  }
215 
216  DDS *dds = bdds->get_dds();
217  ConstraintEvaluator & ce = bdds->get_ce();
218 
219  dhi.first_container();
220  bool print_mime = get_print_mime();
221 
224  rb.set_ce(dhi.data[POST_CONSTRAINT]);
225  rb.send_ddx(dhi.get_output_stream(), *dds, ce, print_mime);
226  }
227 };
228 
229 class SendDMR: public Sender {
230 private:
231  virtual string get_request_type() const
232  {
233  return "DMR";
234  }
235 
236  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
237  {
238  BESDEBUG("dap", "Entering SendDMR::send_internal ..." << endl);
239 
240  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
241  if (!bdmr)
242  throw BESInternalError("cast error", __FILE__, __LINE__);
243 
244  DMR *dmr = bdmr->get_dmr();
245 
246  dhi.first_container();
247 
250 
253 
254  rb.set_async_accepted(dhi.data[ASYNC]);
256 
257  rb.send_dmr(dhi.get_output_stream(), *dmr, get_print_mime());
258  }
259 };
260 
261 class SendDap4Data: public Sender {
262 private:
263  virtual string get_request_type() const
264  {
265  return "DAP4Data";
266  }
267  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
268  {
269  // In DAP2 we made a special object for data - a child of DDS. That turned to make
270  // some code harder to write, so this time I'll just use the DMR to hold data. jhrg
271  // 10/31/13
272  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
273  if (!bdmr)
274  throw BESInternalError("cast error", __FILE__, __LINE__);
275 
276  DMR *dmr = bdmr->get_dmr();
277 
278  dhi.first_container();
279 
281  rb.set_dataset_name(dmr->filename());
282 
285 
286  rb.set_async_accepted(dhi.data[ASYNC]);
288 
289  rb.send_dap4_data(dhi.get_output_stream(), *dmr, get_print_mime());
290  }
291 };
292 
294 // Public Interface Impl
295 
298 {
303 
306 }
307 
309 {
314 
317 }
318 
320 {
321  SendDAS sender;
322  sender.send(obj, dhi);
323 }
324 
326 {
327  SendDDS sender;
328  sender.send(obj, dhi);
329 }
330 
332 {
333  SendDDX sender;
334  sender.send(obj, dhi);
335 }
336 
338 {
339  SendDataDDS sender;
340  sender.send(obj, dhi);
341 }
342 
344 {
345  SendDMR sender;
346  sender.send(obj, dhi);
347 }
348 
350 {
351  SendDap4Data sender;
352  sender.send(obj, dhi);
353 }
virtual void send_dmr(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
#define DATA_SERVICE
Definition: BESDapNames.h:71
exception thrown if an internal error is found and is fatal to the BES
static void send_basic_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
#define DAS_SERVICE
Definition: BESDapNames.h:56
exception thrown if inernal error encountered
static void send_basic_dds(BESResponseObject *obj, BESDataHandlerInterface &dhi)
static void send_basic_dmr(BESResponseObject *obj, BESDataHandlerInterface &dhi)
ConstraintEvaluator & get_ce()
Represents an OPeNDAP DDS DAP2 data object within the BES.
static void send_basic_ddx(BESResponseObject *obj, BESDataHandlerInterface &dhi)
#define DMR_SERVICE
Definition: BESDapNames.h:82
virtual bool add_method(string method_name, p_transmitter trans_method)
virtual void send_dap2_data(std::ostream &data_stream, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Send the data in the DDS object back to the client program.
virtual void send_das(std::ostream &out, libdap::DAS &das, bool with_mime_headers=true) const
virtual string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
#define DAP4_CONSTRAINT
Definition: BESDataNames.h:47
#define DAP4_FUNCTION
Definition: BESDataNames.h:46
Represents an OPeNDAP DMR DAP4 data object within the BES.
#define DDX_SERVICE
Definition: BESDapNames.h:66
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:51
#define STORE_RESULT
Definition: BESDataNames.h:50
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
virtual void set_async_accepted(std::string _aa)
string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:161
#define ASYNC
Definition: BESDataNames.h:49
virtual void set_dataset_name(const std::string _dataset)
Set the dataset name, which is a string used to access the dataset on the machine running the server...
virtual void set_dap4function(std::string _func)
Set the DAP4 Server Side Fucntion expression.
static BESContextManager * TheManager()
virtual void send_ddx(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Send the DDX response.
#define POST_CONSTRAINT
Definition: BESDataNames.h:43
virtual void send_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
ConstraintEvaluator & get_ce()
Structure storing information used by the BES to handle the request.
static void send_basic_dap4data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
map< string, string > data
the map of string data that will be required for the current request.
virtual ~BESDapTransmit()
This class is used to build responses for/by the BES.
Represents an OPeNDAP DAS DAP2 data object within the BES.
void first_container()
set the container pointer to the first container in the containers list
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
virtual void set_ce(std::string _ce)
Set the DAP2 constraint expression.
#define DAP4DATA_SERVICE
Definition: BESDapNames.h:87
#define DDS_SERVICE
Definition: BESDapNames.h:61
virtual bool remove_method(string method_name)
Abstract base class representing a specific set of information in response to a request to the BES...
virtual void set_dap4ce(std::string _ce)
Set the DAP4 constraint expression.
static void send_basic_das(BESResponseObject *obj, BESDataHandlerInterface &dhi)
BESContainer * container
pointer to current container in this interface
virtual void set_store_result(std::string _sr)
virtual void send_dds(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
This function formats and prints an ASCII representation of a DDS on stdout.