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