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 //#define USE_DODSFILTER 1
38 #undef DODSFILTER
39 
40 #include "BESDapTransmit.h"
41 #ifdef USE_DODSFILTER
42 #include "DODSFilter.h"
43 #endif
44 #include "ResponseBuilder.h"
45 #include "BESContainer.h"
46 #include "BESDapNames.h"
47 #include "BESDataNames.h"
48 #include "BESResponseNames.h"
49 #ifdef USE_DODSFILTER
50 #include "mime_util.h"
51 #endif
52 #include "BESDASResponse.h"
53 #include "BESDDSResponse.h"
54 #include "BESDataDDSResponse.h"
55 #include "BESContextManager.h"
56 #include "BESDapError.h"
57 #include "BESInternalFatalError.h"
58 #include "BESDebug.h"
59 #include "Error.h"
60 
62 // Local Helpers
63 
64 // File local helper superclass for common exception handling
65 // for transmitting DAP responses.
66 class Sender
67 {
68 public:
69  virtual ~Sender() {}
70 
71  // The main call, non-virtual to force exception handling.
72  // Subclasses will override send_internal private virtual.
73  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
74  {
75  string response_string = get_request_type();
76  try
77  {
78  send_internal(obj, dhi);
79  }
80  catch( InternalErr &e )
81  {
82  string err = "libdap error transmitting " +
83  response_string + ": " +
84  e.get_error_message() ;
85  throw BESDapError( err, true, e.get_error_code(), __FILE__, __LINE__ ) ;
86  }
87  catch( Error &e )
88  {
89  string err = "libdap error transmitting " +
90  response_string + ": " +
91  e.get_error_message() ;
92  throw BESDapError( err, false, e.get_error_code(), __FILE__, __LINE__ );
93  }
94  catch( const BESError &e )
95  {
96  throw; // rethrow as is
97  }
98  catch( const std::exception &e )
99  {
100  string msg("std::exception caught transmitting " +
101  response_string + ": " +
102  e.what() );
103  throw BESInternalFatalError(msg, __FILE__, __LINE__);
104  }
105  catch(...)
106  {
107  string s = "unknown error caught transmitting " +
108  response_string + ": ";
109  BESInternalFatalError ex( s, __FILE__, __LINE__ ) ;
110  throw ex;
111  }
112  }
113 
114  // common code for subclasses
115  bool get_print_mime() const
116  {
117  bool found = false ;
118  string context = "transmit_protocol" ;
119  string protocol = BESContextManager::TheManager()->get_context( context,
120  found ) ;
121  bool print_mime = false ;
122  if( protocol == "HTTP" ) {
123  print_mime = true;
124  }
125  return print_mime;
126  }
127 
128 private:
129 
130  // Name of the request being sent, for debug
131  virtual string get_request_type() const = 0;
132 
133  // Subclasses impl this for specialized behavior
134  virtual void send_internal(
135  BESResponseObject * obj,
136  BESDataHandlerInterface & dhi) = 0;
137 };
138 
139 class SendDAS : public Sender
140 {
141 private:
142  virtual string get_request_type() const { return "DAS"; }
143  virtual void send_internal(
144  BESResponseObject * obj,
146  {
147  BESDASResponse *bdas = dynamic_cast < BESDASResponse * >(obj);
148  if( !bdas ) {
149  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
150  }
151  DAS *das = bdas->get_das();
152  dhi.first_container();
153  bool print_mime = get_print_mime();
154 #ifdef USE_DODSFILTER
155  DODSFilter df ;
156  df.set_dataset_name( dhi.container->get_real_name() ) ;
157  df.send_das( dhi.get_output_stream(), *das, "", print_mime ) ;
158 #else
159  ResponseBuilder rb ;
160  rb.set_dataset_name( dhi.container->get_real_name() ) ;
161  rb.send_das( dhi.get_output_stream(), *das, print_mime ) ;
162 #endif
163  }
164 };
165 
166 class SendDDS : public Sender
167 {
168 private:
169  virtual string get_request_type() const { return "DDS"; }
170  virtual void send_internal(
171  BESResponseObject * obj,
173  {
174  BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
175  if( !bdds ) {
176  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
177  }
178  DDS *dds = bdds->get_dds();
179  ConstraintEvaluator & ce = bdds->get_ce();
180  dhi.first_container();
181  bool print_mime = get_print_mime();
182 
183 #ifdef USE_DODSFILTER
184  DODSFilter df;
185  df.set_dataset_name(dhi.container->get_real_name());
186  df.set_ce(dhi.data[POST_CONSTRAINT]);
187  df.send_dds(dhi.get_output_stream(), *dds, ce, true, "", print_mime);
188 #else
189  ResponseBuilder rb;
190  rb.set_dataset_name(dhi.container->get_real_name());
191  rb.set_ce(dhi.data[POST_CONSTRAINT]);
192  rb.send_dds(dhi.get_output_stream(), *dds, ce, true, print_mime);
193 #endif
194  }
195 };
196 
197 class SendDataDDS : public Sender
198 {
199 private:
200  virtual string get_request_type() const { return "DataDDS"; }
201  virtual void send_internal(
202  BESResponseObject * obj,
204  {
205  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
206  if( !bdds ) {
207  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
208  }
209  DataDDS *dds = bdds->get_dds();
210  ConstraintEvaluator & ce = bdds->get_ce();
211  dhi.first_container();
212  bool print_mime = get_print_mime();
213 
214 #ifdef USE_DODSFILTER
215  DODSFilter df;
216  df.set_dataset_name(dds->filename());
217  df.set_ce(dhi.data[POST_CONSTRAINT]);
218  df.send_data(*dds, ce, dhi.get_output_stream(), "", print_mime);
219 #else
220  ResponseBuilder rb;
221  rb.set_dataset_name(dds->filename());
222  rb.set_ce(dhi.data[POST_CONSTRAINT]);
223  rb.send_data(dhi.get_output_stream(), *dds, ce, print_mime);
224 #endif
225  }
226 };
227 
228 class SendDDX : public Sender
229 {
230 private:
231  virtual string get_request_type() const { return "DDX"; }
232  virtual void send_internal(
233  BESResponseObject * obj,
235  {
236  BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
237  if( !bdds ) {
238  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
239  }
240  DDS *dds = bdds->get_dds();
241  ConstraintEvaluator & ce = bdds->get_ce();
242  dhi.first_container();
243  bool print_mime = get_print_mime();
244 
245 #ifdef USE_DODSFILTER
246  DODSFilter df;
247  df.set_dataset_name(dhi.container->get_real_name());
248  df.set_ce(dhi.data[POST_CONSTRAINT]);
249  df.send_ddx(*dds, ce, dhi.get_output_stream(), print_mime);
250 #else
251  ResponseBuilder rb;
252  rb.set_dataset_name(dhi.container->get_real_name());
253  rb.set_ce(dhi.data[POST_CONSTRAINT]);
254  rb.send_ddx(dhi.get_output_stream(), *dds, ce, print_mime);
255 #endif
256  }
257 };
258 
259 class SendDataDDX : public Sender
260 {
261 private:
262  virtual string get_request_type() const { return "DataDDX"; }
263  virtual void send_internal(
264  BESResponseObject * obj,
266  {
267  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
268  if( !bdds ) {
269  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
270  }
271  DataDDS *dds = bdds->get_dds();
272  ConstraintEvaluator & ce = bdds->get_ce();
273  dhi.first_container();
274  bool print_mime = get_print_mime();
275 
276 #ifdef USE_DODSFILTER
277  DODSFilter df;
278  df.set_dataset_name(dds->filename());
279  df.set_ce(dhi.data[POST_CONSTRAINT]);
280  BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
281  df.send_data_ddx(*dds, ce, dhi.get_output_stream(),
283  "", print_mime);
284 #else
285  ResponseBuilder rb;
286  rb.set_dataset_name(dds->filename());
287  rb.set_ce(dhi.data[POST_CONSTRAINT]);
288  BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
289  rb.send_data_ddx(dhi.get_output_stream(), *dds, ce,
290  dhi.data[DATADDX_STARTID], dhi.data[DATADDX_BOUNDARY], print_mime);
291 #endif
292  }
293 };
294 
296 // Public Interface Impl
297 
300 {
306 }
307 
308 void
311 {
312  SendDAS sender;
313  sender.send(obj, dhi);
314 }
315 
316 void
319 {
320  SendDDS sender;
321  sender.send(obj, dhi);
322 }
323 
324 void
327 {
328  SendDDX sender;
329  sender.send(obj, dhi);
330 }
331 
332 void
335 {
336  SendDataDDS sender;
337  sender.send(obj, dhi);
338 }
339 
340 void
343 {
344  SendDataDDX sender;
345  sender.send(obj, dhi);
346 }