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 #include "BESDASResponse.h"
45 // #include "BESDMRResponse.h"
46 #include "BESDDSResponse.h"
47 #include "BESDataDDSResponse.h"
48 #include "BESContextManager.h"
49 #include "BESDapError.h"
50 #include "BESInternalFatalError.h"
51 #include "BESDebug.h"
52 
53 #include "BESDapResponseBuilder.h"
54 
56 // Local Helpers
57 
58 // File local helper superclass for common exception handling
59 // for transmitting DAP responses.
60 class Sender {
61 public:
62  virtual ~Sender()
63  {
64  }
65 
66  // The main call, non-virtual to force exception handling.
67  // Subclasses will override send_internal private virtual.
68  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
69  {
70  string response_string = get_request_type();
71  try {
72  send_internal(obj, dhi);
73  }
74  catch (InternalErr &e) {
75  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
76  throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
77  }
78  catch (Error &e) {
79  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
80  throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
81  }
82  catch (const BESError &e) {
83  throw; // rethrow as is
84  }
85  catch (const std::exception &e) {
86  string msg(
87  "std::exception caught transmitting " + response_string + ": " + e.what()
88  + " (caught in BESDapTransmit).");
89  throw BESInternalFatalError(msg, __FILE__, __LINE__);
90  }
91  catch (...) {
92  string s = "unknown error caught transmitting " + response_string + ": ";
93  BESInternalFatalError ex(s, __FILE__, __LINE__);
94  throw ex;
95  }
96  }
97 
98  // common code for subclasses
99  bool get_print_mime() const
100  {
101  bool found = false;
102  string protocol = BESContextManager::TheManager()->get_context("transmit_protocol", found);
103  bool print_mime = false;
104  if (found && protocol == "HTTP") {
105  print_mime = true;
106  }
107  return print_mime;
108  }
109 
110 private:
111 
112  // Name of the request being sent, for debug
113  virtual string get_request_type() const = 0;
114 
115  // Subclasses impl this for specialized behavior
116  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi) = 0;
117 };
118 
119 class SendDAS: public Sender {
120 private:
121  virtual string get_request_type() const
122  {
123  return "DAS";
124  }
125  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
126  {
127  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(obj);
128  if (!bdas) {
129  throw BESInternalError("cast error", __FILE__, __LINE__);
130  }
131 
132  DAS *das = bdas->get_das();
133  dhi.first_container();
134  bool print_mime = get_print_mime();
135 
138  rb.send_das(dhi.get_output_stream(), *das, print_mime);
139 
140  //rb.send_das(dhi.get_output_stream(), DDS &dds, ConstraintEvaluator &eval, bool constrained, bool with_mime_headers)
141  }
142 };
143 
144 class SendDDS: public Sender {
145 private:
146  virtual string get_request_type() const
147  {
148  return "DDS";
149  }
150  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
151  {
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  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
195  rb.send_data(dhi.get_output_stream(), *dds, ce, print_mime);
196  }
197 };
198 
199 class SendDDX: public Sender {
200 private:
201  virtual string get_request_type() const
202  {
203  return "DDX";
204  }
205  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
206  {
207  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
208  if (!bdds) {
209  throw BESInternalError("cast error", __FILE__, __LINE__);
210  }
211 
212  DDS *dds = bdds->get_dds();
213  ConstraintEvaluator & ce = bdds->get_ce();
214 
215  dhi.first_container();
216  bool print_mime = get_print_mime();
217 
220  rb.set_ce(dhi.data[POST_CONSTRAINT]);
221  rb.send_ddx(dhi.get_output_stream(), *dds, ce, print_mime);
222  }
223 };
224 #if 0
225 class SendDMR: public Sender {
226 private:
227  virtual string get_request_type() const
228  {
229  return "DMR";
230  }
231  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
232  {
233  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
234  if (!bdmr) {
235  throw BESInternalError("cast error", __FILE__, __LINE__);
236  }
237 
238  DMR *dmr = bdmr->get_dmr();
239  ConstraintEvaluator & ce = bdmr->get_ce();
240 
241  dhi.first_container();
242  bool print_mime = get_print_mime();
243 
246  BESDEBUG("dap", "SendDMR: dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
247  rb.set_ce(dhi.data[POST_CONSTRAINT]);
248  rb.send_dmr(dhi.get_output_stream(), *dmr, ce, print_mime);
249  }
250 };
251 
252 // FIXME
253 class SendDap4Data: public Sender {
254 private:
255  virtual string get_request_type() const
256  {
257  return "DAP4Data";
258  }
259  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
260  {
261  // In DAP2 we made a special object for data - a child of DDS. That turned to make
262  // some code harder to write, so this time I'll just use the DMR to hold data. jhrg
263  // 10/31/13
264  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
265  if (!bdmr) {
266  throw BESInternalError("cast error", __FILE__, __LINE__);
267  }
268  DMR *dmr = bdmr->get_dmr();
269  ConstraintEvaluator & ce = bdmr->get_ce();
270 
271  dhi.first_container();
272  bool print_mime = get_print_mime();
273 
275  rb.set_dataset_name(dmr->filename());
276  rb.set_ce(dhi.data[POST_CONSTRAINT]);
277  BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
278  rb.send_dap4_data(dhi.get_output_stream(), *dmr, ce, print_mime);
279  }
280 };
281 #endif
282 // Public Interface Impl
284 
287 {
292 #if 0
293  add_method(DMR_SERVICE, BESDapTransmit::send_basic_dmr);
294  add_method(DAP4DATA_SERVICE, BESDapTransmit::send_basic_dap4data);
295 #endif
296 }
297 
299 {
304 #if 0
305  remove_method(DMR_SERVICE);
306  remove_method(DAP4DATA_SERVICE);
307 #endif
308 }
309 
311 {
312  SendDAS sender;
313  sender.send(obj, dhi);
314 }
315 
317 {
318  SendDDS sender;
319  sender.send(obj, dhi);
320 }
321 
323 {
324  SendDDX sender;
325  sender.send(obj, dhi);
326 }
327 
329 {
330  SendDataDDS sender;
331  sender.send(obj, dhi);
332 }
333 #if 0
334 void BESDapTransmit::send_basic_dmr(BESResponseObject * obj, BESDataHandlerInterface & dhi)
335 {
336  SendDMR sender;
337  sender.send(obj, dhi);
338 }
339 
340 void BESDapTransmit::send_basic_dap4data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
341 {
342  SendDap4Data sender;
343  sender.send(obj, dhi);
344 }
345 #endif
#define DATA_SERVICE
Definition: BESDapNames.h:70
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:55
exception thrown if inernal error encountered
static void send_basic_dds(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)
virtual bool add_method(string method_name, p_transmitter trans_method)
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
virtual void send_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.
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
#define DDX_SERVICE
Definition: BESDapNames.h:65
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:141
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...
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
ConstraintEvaluator & get_ce()
Structure storing information used by the BES to handle the request.
#define DATADDX_STARTID
Definition: BESDapNames.h:93
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 constraint expression.
#define DDS_SERVICE
Definition: BESDapNames.h:60
virtual bool remove_method(string method_name)
Abstract base class representing a specific set of information in response to a request to the BES...
static void send_basic_das(BESResponseObject *obj, BESDataHandlerInterface &dhi)
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)
This function formats and prints an ASCII representation of a DDS on stdout.