bes  Updated for version 3.17.0
BESDapTransmit.cc
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 {
65 public:
66  virtual ~Sender()
67  {
68  }
69 
70  // The main call, non-virtual to force exception handling.
71  // Subclasses will override send_internal private virtual.
72  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
73  {
74  string response_string = get_request_type();
75  try {
76  send_internal(obj, dhi);
77  }
78  catch (InternalErr &e) {
79  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
80  throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
81  }
82  catch (Error &e) {
83  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
84  throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
85  }
86  catch (const BESError &e) {
87  throw; // rethrow as is
88  }
89  catch (const std::exception &e) {
90  string msg = "std::exception caught transmitting " + response_string + ": " + e.what()
91  + " (caught in BESDapTransmit).";
92  throw BESInternalFatalError(msg, __FILE__, __LINE__);
93  }
94  catch (...) {
95  string s = "unknown error caught transmitting " + response_string + ": ";
96  BESInternalFatalError ex(s, __FILE__, __LINE__);
97  throw ex;
98  }
99  }
100 
101  // common code for subclasses
102  bool get_print_mime() const
103  {
104  bool found = false;
105  string protocol = BESContextManager::TheManager()->get_context("transmit_protocol", found);
106  bool print_mime = false;
107  if (found && protocol == "HTTP") {
108  print_mime = true;
109  }
110  return print_mime;
111  }
112 
113 private:
114 
115  // Name of the request being sent, for debug
116  virtual string get_request_type() const = 0;
117 
118  // Subclasses impl this for specialized behavior
119  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi) = 0;
120 };
121 
122 class SendDAS: public Sender
123 {
124 private:
125  virtual string get_request_type() const
126  {
127  return "DAS";
128  }
129  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
130  {
131  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(obj);
132  if (!bdas) {
133  throw BESInternalError("cast error", __FILE__, __LINE__);
134  }
135 
136  DAS *das = bdas->get_das();
137  dhi.first_container();
138  bool print_mime = get_print_mime();
139 
142  rb.send_das(dhi.get_output_stream(), *das, print_mime);
143 
144  //rb.send_das(dhi.get_output_stream(), DDS &dds, ConstraintEvaluator &eval, bool constrained, bool with_mime_headers)
145  }
146 };
147 
148 class SendDDS: public Sender
149 {
150 private:
151  virtual string get_request_type() const
152  {
153  return "DDS";
154  }
155  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
156  {
157  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
158  if (!bdds) {
159  throw BESInternalError("cast error", __FILE__, __LINE__);
160  }
161 
162  DDS *dds = bdds->get_dds();
163  ConstraintEvaluator & ce = bdds->get_ce();
164 
165  dhi.first_container();
166  bool print_mime = get_print_mime();
167 
170  rb.set_ce(dhi.data[POST_CONSTRAINT]);
171  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
172  rb.send_dds(dhi.get_output_stream(), *dds, ce, true, print_mime);
173  }
174 };
175 
176 class SendDataDDS: public Sender
177 {
178 private:
179  virtual string get_request_type() const
180  {
181  return "DataDDS";
182  }
183  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
184  {
185  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
186  if (!bdds) {
187  throw BESInternalError("cast error", __FILE__, __LINE__);
188  }
189 
190  DataDDS *dds = bdds->get_dds();
191  ConstraintEvaluator & ce = bdds->get_ce();
192 
193  dhi.first_container();
194  bool print_mime = get_print_mime();
195 
197  rb.set_dataset_name(dds->filename());
198  rb.set_ce(dhi.data[POST_CONSTRAINT]);
199 
200  rb.set_async_accepted(dhi.data[ASYNC]);
201  rb.set_store_result(dhi.data[STORE_RESULT]);
202 
203  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
204  rb.send_dap2_data(dhi.get_output_stream(), *dds, ce, print_mime);
205  }
206 };
207 
208 class SendDDX: public Sender
209 {
210 private:
211  virtual string get_request_type() const
212  {
213  return "DDX";
214  }
215  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
216  {
217  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
218  if (!bdds) {
219  throw BESInternalError("cast error", __FILE__, __LINE__);
220  }
221 
222  DDS *dds = bdds->get_dds();
223  ConstraintEvaluator & ce = bdds->get_ce();
224 
225  dhi.first_container();
226  bool print_mime = get_print_mime();
227 
230  rb.set_ce(dhi.data[POST_CONSTRAINT]);
231  rb.send_ddx(dhi.get_output_stream(), *dds, ce, print_mime);
232  }
233 };
234 
235 class SendDMR: public Sender
236 {
237 private:
238  virtual string get_request_type() const
239  {
240  return "DMR";
241  }
242 
243  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
244  {
245  BESDEBUG("dap", "Entering SendDMR::send_internal ..." << endl);
246 
247  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
248  if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
249 
250  DMR *dmr = bdmr->get_dmr();
251 
252  dhi.first_container();
253 
256 
257  rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
258  rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
259 
260  rb.set_async_accepted(dhi.data[ASYNC]);
261  rb.set_store_result(dhi.data[STORE_RESULT]);
262 
263  rb.send_dmr(dhi.get_output_stream(), *dmr, get_print_mime());
264  }
265 };
266 
267 class SendDap4Data: public Sender
268 {
269 private:
270  virtual string get_request_type() const
271  {
272  return "DAP4Data";
273  }
274  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
275  {
276  // In DAP2 we made a special object for data - a child of DDS. That turned to make
277  // some code harder to write, so this time I'll just use the DMR to hold data. jhrg
278  // 10/31/13
279  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
280  if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
281 
282  DMR *dmr = bdmr->get_dmr();
283 
284  dhi.first_container();
285 
287  rb.set_dataset_name(dmr->filename());
288 
289  rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
290  rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
291 
292  rb.set_async_accepted(dhi.data[ASYNC]);
293  rb.set_store_result(dhi.data[STORE_RESULT]);
294 
295  rb.send_dap4_data(dhi.get_output_stream(), *dmr, get_print_mime());
296  }
297 };
298 
300 // Public Interface Impl
301 
302 BESDapTransmit::BESDapTransmit() :
304 {
305  add_method(DAS_SERVICE, BESDapTransmit::send_basic_das);
306  add_method(DDS_SERVICE, BESDapTransmit::send_basic_dds);
307  add_method(DDX_SERVICE, BESDapTransmit::send_basic_ddx);
308  add_method(DATA_SERVICE, BESDapTransmit::send_basic_data);
309 
310  add_method(DMR_SERVICE, BESDapTransmit::send_basic_dmr);
311  add_method(DAP4DATA_SERVICE, BESDapTransmit::send_basic_dap4data);
312 }
313 
314 BESDapTransmit::~BESDapTransmit()
315 {
316  remove_method(DAS_SERVICE);
317  remove_method(DDS_SERVICE);
318  remove_method(DDX_SERVICE);
319  remove_method(DATA_SERVICE);
320 
321  remove_method(DMR_SERVICE);
322  remove_method(DAP4DATA_SERVICE);
323 }
324 
325 void BESDapTransmit::send_basic_das(BESResponseObject * obj, BESDataHandlerInterface & dhi)
326 {
327  SendDAS sender;
328  sender.send(obj, dhi);
329 }
330 
331 void BESDapTransmit::send_basic_dds(BESResponseObject * obj, BESDataHandlerInterface & dhi)
332 {
333  SendDDS sender;
334  sender.send(obj, dhi);
335 }
336 
337 void BESDapTransmit::send_basic_ddx(BESResponseObject * obj, BESDataHandlerInterface & dhi)
338 {
339  SendDDX sender;
340  sender.send(obj, dhi);
341 }
342 
343 void BESDapTransmit::send_basic_data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
344 {
345  SendDataDDS sender;
346  sender.send(obj, dhi);
347 }
348 
349 void BESDapTransmit::send_basic_dmr(BESResponseObject * obj, BESDataHandlerInterface & dhi)
350 {
351  SendDMR sender;
352  sender.send(obj, dhi);
353 }
354 
355 void BESDapTransmit::send_basic_dap4data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
356 {
357  SendDap4Data sender;
358  sender.send(obj, dhi);
359 }
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
Represents an OPeNDAP DDS DAP2 data object within the BES.
virtual void send_dap2_data(std::ostream &data_stream, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Transmit data.
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:56
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:51
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:161
virtual void set_dataset_name(const std::string _dataset)
Set the dataset pathname.
virtual void set_dap4function(std::string _func)
virtual void send_ddx(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Structure storing information used by the BES to handle the request.
map< string, string > data
the map of string data that will be required for the current request.
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
virtual void set_ce(std::string _ce)
Abstract base class representing a specific set of information in response to a request to the BES...
virtual void set_dap4ce(std::string _ce)
BESContainer * container
pointer to current container in this interface
virtual void send_dds(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.