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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <sstream>
34 
35 using std::ostringstream;
36 
37 #include "BESDapTransmit.h"
38 #include "DODSFilter.h"
39 #include "BESContainer.h"
40 #include "BESDapNames.h"
41 #include "BESDataNames.h"
42 #include "BESResponseNames.h"
43 #include "mime_util.h"
44 #include "BESDASResponse.h"
45 #include "BESDDSResponse.h"
46 #include "BESDataDDSResponse.h"
47 #include "BESContextManager.h"
48 #include "BESDapError.h"
49 #include "BESInternalFatalError.h"
50 #include "BESDebug.h"
51 #include "Error.h"
52 
54 // Local Helpers
55 
56 // File local helper superclass for common exception handling
57 // for transmitting DAP responses.
58 class Sender
59 {
60 public:
61  virtual ~Sender() {}
62 
63  // The main call, non-virtual to force exception handling.
64  // Subclasses will override send_internal private virtual.
65  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
66  {
67  string response_string = get_request_type();
68  try
69  {
70  send_internal(obj, dhi);
71  }
72  catch( InternalErr &e )
73  {
74  string err = "libdap error transmitting " +
75  response_string + ": " +
76  e.get_error_message() ;
77  throw BESDapError( err, true, e.get_error_code(), __FILE__, __LINE__ ) ;
78  }
79  catch( Error &e )
80  {
81  string err = "libdap error transmitting " +
82  response_string + ": " +
83  e.get_error_message() ;
84  throw BESDapError( err, false, e.get_error_code(), __FILE__, __LINE__ );
85  }
86  catch( const BESError &e )
87  {
88  throw; // rethrow as is
89  }
90  catch( const std::exception &e )
91  {
92  string msg("std::exception caught transmitting " +
93  response_string + ": " +
94  e.what() );
95  throw BESInternalFatalError(msg, __FILE__, __LINE__);
96  }
97  catch(...)
98  {
99  string s = "unknown error caught transmitting " +
100  response_string + ": ";
101  BESInternalFatalError ex( s, __FILE__, __LINE__ ) ;
102  throw ex;
103  }
104  }
105 
106  // common code for subclasses
107  bool get_print_mime() const
108  {
109  bool found = false ;
110  string context = "transmit_protocol" ;
111  string protocol = BESContextManager::TheManager()->get_context( context,
112  found ) ;
113  bool print_mime = false ;
114  if( protocol == "HTTP" ) {
115  print_mime = true;
116  }
117  return print_mime;
118  }
119 
120 private:
121 
122  // Name of the request being sent, for debug
123  virtual string get_request_type() const = 0;
124 
125  // Subclasses impl this for specialized behavior
126  virtual void send_internal(
127  BESResponseObject * obj,
128  BESDataHandlerInterface & dhi) = 0;
129 };
130 
131 class SendDAS : public Sender
132 {
133 private:
134  virtual string get_request_type() const { return "DAS"; }
135  virtual void send_internal(
136  BESResponseObject * obj,
138  {
139  BESDASResponse *bdas = dynamic_cast < BESDASResponse * >(obj);
140  if( !bdas ) {
141  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
142  }
143  DAS *das = bdas->get_das();
144  dhi.first_container();
145  bool print_mime = get_print_mime();
146 
147  DODSFilter df ;
148  df.set_dataset_name( dhi.container->get_real_name() ) ;
149  df.send_das( dhi.get_output_stream(), *das, "", print_mime ) ;
150  }
151 };
152 
153 class SendDDS : public Sender
154 {
155 private:
156  virtual string get_request_type() const { return "DDS"; }
157  virtual void send_internal(
158  BESResponseObject * obj,
160  {
161  BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
162  if( !bdds ) {
163  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
164  }
165  DDS *dds = bdds->get_dds();
166  ConstraintEvaluator & ce = bdds->get_ce();
167  dhi.first_container();
168  bool print_mime = get_print_mime();
169 
170  DODSFilter df;
171  df.set_dataset_name(dhi.container->get_real_name());
172  df.set_ce(dhi.data[POST_CONSTRAINT]);
173  df.send_dds(dhi.get_output_stream(), *dds, ce, true, "", print_mime);
174  }
175 };
176 
177 class SendDataDDS : public Sender
178 {
179 private:
180  virtual string get_request_type() const { return "DataDDS"; }
181  virtual void send_internal(
182  BESResponseObject * obj,
184  {
185  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
186  if( !bdds ) {
187  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
188  }
189  DataDDS *dds = bdds->get_dds();
190  ConstraintEvaluator & ce = bdds->get_ce();
191  dhi.first_container();
192  bool print_mime = get_print_mime();
193 
194  DODSFilter df;
195  df.set_dataset_name(dds->filename());
196  df.set_ce(dhi.data[POST_CONSTRAINT]);
197  df.send_data(*dds, ce, dhi.get_output_stream(), "", print_mime);
198  }
199 };
200 
201 class SendDDX : public Sender
202 {
203 private:
204  virtual string get_request_type() const { return "DDX"; }
205  virtual void send_internal(
206  BESResponseObject * obj,
208  {
209  BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
210  if( !bdds ) {
211  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
212  }
213  DDS *dds = bdds->get_dds();
214  ConstraintEvaluator & ce = bdds->get_ce();
215  dhi.first_container();
216  bool print_mime = get_print_mime();
217 
218  DODSFilter df;
219  df.set_dataset_name(dhi.container->get_real_name());
220  df.set_ce(dhi.data[POST_CONSTRAINT]);
221  df.send_ddx(*dds, ce, dhi.get_output_stream(), print_mime);
222  }
223 };
224 
225 class SendDataDDX : public Sender
226 {
227 private:
228  virtual string get_request_type() const { return "DataDDX"; }
229  virtual void send_internal(
230  BESResponseObject * obj,
232  {
233  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
234  if( !bdds ) {
235  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
236  }
237  DataDDS *dds = bdds->get_dds();
238  ConstraintEvaluator & ce = bdds->get_ce();
239  dhi.first_container();
240  bool print_mime = get_print_mime();
241 
242  DODSFilter df;
243  df.set_dataset_name(dds->filename());
244  df.set_ce(dhi.data[POST_CONSTRAINT]);
245  BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
246  df.send_data_ddx(*dds, ce, dhi.get_output_stream(),
248  "", print_mime);
249  }
250 };
251 
253 // Public Interface Impl
254 
257 {
263 }
264 
265 void
268 {
269  SendDAS sender;
270  sender.send(obj, dhi);
271 }
272 
273 void
276 {
277  SendDDS sender;
278  sender.send(obj, dhi);
279 }
280 
281 void
284 {
285  SendDDX sender;
286  sender.send(obj, dhi);
287 }
288 
289 void
292 {
293  SendDataDDS sender;
294  sender.send(obj, dhi);
295 }
296 
297 void
300 {
301  SendDataDDX sender;
302  sender.send(obj, dhi);
303 }
#define DATA_SERVICE
Definition: BESDapNames.h:67
#define DATADDX_BOUNDARY
Definition: BESDapNames.h:84
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 string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
static void send_basic_dataddx(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
#define DDX_SERVICE
Definition: BESDapNames.h:63
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:51
#define DATADDX_SERVICE
Definition: BESDapNames.h:71
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
static BESContextManager * TheManager()
#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:83
map< string, string > data
the map of string data that will be required for the current request.
string get_real_name() const
retreive the real name for this container, such as a file name.
Definition: BESContainer.h:141
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
#define DDS_SERVICE
Definition: BESDapNames.h:59
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