OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
BESDapTransmit.cc
Go to the documentation of this file.
00001 // BESDapTransmit.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025 
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <sstream>
00034 
00035 using std::ostringstream;
00036 
00037 #include "BESDapTransmit.h"
00038 #include "DODSFilter.h"
00039 #include "BESContainer.h"
00040 #include "BESDapNames.h"
00041 #include "BESDataNames.h"
00042 #include "BESResponseNames.h"
00043 #include "mime_util.h"
00044 #include "BESDASResponse.h"
00045 #include "BESDDSResponse.h"
00046 #include "BESDataDDSResponse.h"
00047 #include "BESContextManager.h"
00048 #include "BESDapError.h"
00049 #include "BESInternalFatalError.h"
00050 #include "BESDebug.h"
00051 #include "Error.h"
00052 
00054 // Local Helpers
00055 
00056 // File local helper superclass for common exception handling
00057 // for transmitting DAP responses.
00058 class Sender
00059 {
00060 public:
00061   virtual ~Sender() {}
00062 
00063   // The main call, non-virtual to force exception handling.
00064   // Subclasses will override send_internal private virtual.
00065   void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
00066   {
00067     string response_string = get_request_type();
00068     try
00069     {
00070       send_internal(obj, dhi);
00071     }
00072     catch( InternalErr &e )
00073     {
00074       string err = "libdap error transmitting " +
00075           response_string + ": " +
00076           e.get_error_message() ;
00077          throw BESDapError( err, true, e.get_error_code(), __FILE__, __LINE__ ) ;
00078     }
00079     catch( Error &e )
00080     {
00081       string err = "libdap error transmitting " +
00082           response_string + ": " +
00083           e.get_error_message() ;
00084       throw BESDapError( err, false, e.get_error_code(), __FILE__, __LINE__ );
00085     }
00086     catch( const BESError &e )
00087     {
00088       throw; // rethrow as is
00089     }
00090     catch( const std::exception &e )
00091     {
00092       string msg("std::exception caught transmitting " +
00093           response_string + ": " +
00094           e.what() );
00095       throw BESInternalFatalError(msg, __FILE__, __LINE__);
00096     }
00097     catch(...)
00098     {
00099       string s = "unknown error caught transmitting " +
00100           response_string + ": ";
00101       BESInternalFatalError ex( s, __FILE__, __LINE__ ) ;
00102       throw ex;
00103     }
00104   }
00105 
00106   // common code for subclasses
00107   bool get_print_mime() const
00108   {
00109     bool found = false ;
00110     string context = "transmit_protocol" ;
00111     string protocol = BESContextManager::TheManager()->get_context( context,
00112                                                                     found ) ;
00113     bool print_mime = false ;
00114     if( protocol == "HTTP" ) {
00115       print_mime = true;
00116     }
00117     return print_mime;
00118   }
00119 
00120 private:
00121 
00122   // Name of the request being sent, for debug
00123   virtual string get_request_type() const = 0;
00124 
00125   // Subclasses impl this for specialized behavior
00126   virtual void send_internal(
00127       BESResponseObject * obj,
00128       BESDataHandlerInterface & dhi) = 0;
00129 };
00130 
00131 class SendDAS : public Sender
00132 {
00133 private:
00134   virtual string get_request_type() const { return "DAS"; }
00135   virtual void  send_internal(
00136       BESResponseObject * obj,
00137       BESDataHandlerInterface & dhi)
00138   {
00139     BESDASResponse *bdas = dynamic_cast < BESDASResponse * >(obj);
00140     if( !bdas ) {
00141       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00142     }
00143     DAS *das = bdas->get_das();
00144     dhi.first_container();
00145     bool print_mime = get_print_mime();
00146 
00147     DODSFilter df ;
00148     df.set_dataset_name( dhi.container->get_real_name() ) ;
00149     df.send_das( dhi.get_output_stream(), *das, "", print_mime ) ;
00150   }
00151 };
00152 
00153 class SendDDS : public Sender
00154 {
00155 private:
00156   virtual string get_request_type() const { return "DDS"; }
00157   virtual void  send_internal(
00158       BESResponseObject * obj,
00159       BESDataHandlerInterface & dhi)
00160   {
00161     BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
00162     if( !bdds ) {
00163       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00164     }
00165     DDS *dds = bdds->get_dds();
00166     ConstraintEvaluator & ce = bdds->get_ce();
00167     dhi.first_container();
00168     bool print_mime = get_print_mime();
00169 
00170     DODSFilter df;
00171     df.set_dataset_name(dhi.container->get_real_name());
00172     df.set_ce(dhi.data[POST_CONSTRAINT]);
00173     df.send_dds(dhi.get_output_stream(), *dds, ce, true, "", print_mime);
00174   }
00175 };
00176 
00177 class SendDataDDS : public Sender
00178 {
00179 private:
00180   virtual string get_request_type() const { return "DataDDS"; }
00181   virtual void  send_internal(
00182       BESResponseObject * obj,
00183       BESDataHandlerInterface & dhi)
00184   {
00185     BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
00186      if( !bdds ) {
00187          throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00188      }
00189      DataDDS *dds = bdds->get_dds();
00190      ConstraintEvaluator & ce = bdds->get_ce();
00191      dhi.first_container();
00192      bool print_mime = get_print_mime();
00193 
00194      DODSFilter df;
00195      df.set_dataset_name(dds->filename());
00196      df.set_ce(dhi.data[POST_CONSTRAINT]);
00197      df.send_data(*dds, ce, dhi.get_output_stream(), "", print_mime);
00198   }
00199 };
00200 
00201 class SendDDX : public Sender
00202 {
00203 private:
00204   virtual string get_request_type() const { return "DDX"; }
00205   virtual void  send_internal(
00206       BESResponseObject * obj,
00207       BESDataHandlerInterface & dhi)
00208   {
00209     BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
00210     if( !bdds ) {
00211       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00212     }
00213     DDS *dds = bdds->get_dds();
00214     ConstraintEvaluator & ce = bdds->get_ce();
00215     dhi.first_container();
00216     bool print_mime = get_print_mime();
00217 
00218     DODSFilter df;
00219     df.set_dataset_name(dhi.container->get_real_name());
00220     df.set_ce(dhi.data[POST_CONSTRAINT]);
00221     df.send_ddx(*dds, ce, dhi.get_output_stream(), print_mime);
00222   }
00223 };
00224 
00225 class SendDataDDX : public Sender
00226 {
00227 private:
00228   virtual string get_request_type() const { return "DataDDX"; }
00229   virtual void  send_internal(
00230       BESResponseObject * obj,
00231       BESDataHandlerInterface & dhi)
00232   {
00233     BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
00234     if( !bdds ) {
00235       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00236     }
00237     DataDDS *dds = bdds->get_dds();
00238     ConstraintEvaluator & ce = bdds->get_ce();
00239     dhi.first_container();
00240     bool print_mime = get_print_mime();
00241 
00242     DODSFilter df;
00243     df.set_dataset_name(dds->filename());
00244     df.set_ce(dhi.data[POST_CONSTRAINT]);
00245     BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
00246     df.send_data_ddx(*dds, ce, dhi.get_output_stream(),
00247         dhi.data[DATADDX_STARTID], dhi.data[DATADDX_BOUNDARY],
00248         "", print_mime);
00249   }
00250 };
00251 
00253 // Public Interface Impl
00254 
00255 BESDapTransmit::BESDapTransmit()
00256     : BESBasicTransmitter()
00257 {
00258     add_method( DAS_SERVICE, BESDapTransmit::send_basic_das ) ;
00259     add_method( DDS_SERVICE, BESDapTransmit::send_basic_dds ) ;
00260     add_method( DDX_SERVICE, BESDapTransmit::send_basic_ddx ) ;
00261     add_method( DATA_SERVICE, BESDapTransmit::send_basic_data ) ;
00262     add_method( DATADDX_SERVICE, BESDapTransmit::send_basic_dataddx ) ;
00263 }
00264 
00265 void
00266 BESDapTransmit::send_basic_das(BESResponseObject * obj,
00267                                BESDataHandlerInterface & dhi)
00268 {
00269   SendDAS sender;
00270   sender.send(obj, dhi);
00271 }
00272 
00273 void
00274 BESDapTransmit::send_basic_dds(BESResponseObject * obj,
00275                                BESDataHandlerInterface & dhi)
00276 {
00277   SendDDS sender;
00278   sender.send(obj, dhi);
00279 }
00280 
00281 void
00282 BESDapTransmit::send_basic_ddx(BESResponseObject * obj,
00283                                BESDataHandlerInterface & dhi)
00284 {
00285   SendDDX sender;
00286   sender.send(obj, dhi);
00287 }
00288 
00289 void
00290 BESDapTransmit::send_basic_data(BESResponseObject * obj,
00291                                 BESDataHandlerInterface & dhi)
00292 {
00293   SendDataDDS sender;
00294   sender.send(obj, dhi);
00295 }
00296 
00297 void
00298 BESDapTransmit::send_basic_dataddx(BESResponseObject * obj,
00299                                    BESDataHandlerInterface & dhi)
00300 {
00301   SendDataDDX sender;
00302   sender.send(obj, dhi);
00303 }