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 //#define USE_DODSFILTER 1
00038 #undef DODSFILTER
00039 
00040 #include "BESDapTransmit.h"
00041 #ifdef USE_DODSFILTER
00042 #include "DODSFilter.h"
00043 #endif
00044 #include "ResponseBuilder.h"
00045 #include "BESContainer.h"
00046 #include "BESDapNames.h"
00047 #include "BESDataNames.h"
00048 #include "BESResponseNames.h"
00049 #ifdef USE_DODSFILTER
00050 #include "mime_util.h"
00051 #endif
00052 #include "BESDASResponse.h"
00053 #include "BESDDSResponse.h"
00054 #include "BESDataDDSResponse.h"
00055 #include "BESContextManager.h"
00056 #include "BESDapError.h"
00057 #include "BESInternalFatalError.h"
00058 #include "BESDebug.h"
00059 #include "Error.h"
00060 
00062 // Local Helpers
00063 
00064 // File local helper superclass for common exception handling
00065 // for transmitting DAP responses.
00066 class Sender
00067 {
00068 public:
00069   virtual ~Sender() {}
00070 
00071   // The main call, non-virtual to force exception handling.
00072   // Subclasses will override send_internal private virtual.
00073   void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
00074   {
00075     string response_string = get_request_type();
00076     try
00077     {
00078       send_internal(obj, dhi);
00079     }
00080     catch( InternalErr &e )
00081     {
00082       string err = "libdap error transmitting " +
00083           response_string + ": " +
00084           e.get_error_message() ;
00085          throw BESDapError( err, true, e.get_error_code(), __FILE__, __LINE__ ) ;
00086     }
00087     catch( Error &e )
00088     {
00089       string err = "libdap error transmitting " +
00090           response_string + ": " +
00091           e.get_error_message() ;
00092       throw BESDapError( err, false, e.get_error_code(), __FILE__, __LINE__ );
00093     }
00094     catch( const BESError &e )
00095     {
00096       throw; // rethrow as is
00097     }
00098     catch( const std::exception &e )
00099     {
00100       string msg("std::exception caught transmitting " +
00101           response_string + ": " +
00102           e.what() );
00103       throw BESInternalFatalError(msg, __FILE__, __LINE__);
00104     }
00105     catch(...)
00106     {
00107       string s = "unknown error caught transmitting " +
00108           response_string + ": ";
00109       BESInternalFatalError ex( s, __FILE__, __LINE__ ) ;
00110       throw ex;
00111     }
00112   }
00113 
00114   // common code for subclasses
00115   bool get_print_mime() const
00116   {
00117     bool found = false ;
00118     string context = "transmit_protocol" ;
00119     string protocol = BESContextManager::TheManager()->get_context( context,
00120                                                                     found ) ;
00121     bool print_mime = false ;
00122     if( protocol == "HTTP" ) {
00123       print_mime = true;
00124     }
00125     return print_mime;
00126   }
00127 
00128 private:
00129 
00130   // Name of the request being sent, for debug
00131   virtual string get_request_type() const = 0;
00132 
00133   // Subclasses impl this for specialized behavior
00134   virtual void send_internal(
00135       BESResponseObject * obj,
00136       BESDataHandlerInterface & dhi) = 0;
00137 };
00138 
00139 class SendDAS : public Sender
00140 {
00141 private:
00142   virtual string get_request_type() const { return "DAS"; }
00143   virtual void  send_internal(
00144       BESResponseObject * obj,
00145       BESDataHandlerInterface & dhi)
00146   {
00147     BESDASResponse *bdas = dynamic_cast < BESDASResponse * >(obj);
00148     if( !bdas ) {
00149       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00150     }
00151     DAS *das = bdas->get_das();
00152     dhi.first_container();
00153     bool print_mime = get_print_mime();
00154 #ifdef USE_DODSFILTER
00155     DODSFilter df ;
00156     df.set_dataset_name( dhi.container->get_real_name() ) ;
00157     df.send_das( dhi.get_output_stream(), *das, "", print_mime ) ;
00158 #else
00159     ResponseBuilder rb ;
00160     rb.set_dataset_name( dhi.container->get_real_name() ) ;
00161     rb.send_das( dhi.get_output_stream(), *das, print_mime ) ;
00162 #endif
00163     }
00164 };
00165 
00166 class SendDDS : public Sender
00167 {
00168 private:
00169   virtual string get_request_type() const { return "DDS"; }
00170   virtual void  send_internal(
00171       BESResponseObject * obj,
00172       BESDataHandlerInterface & dhi)
00173   {
00174     BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
00175     if( !bdds ) {
00176       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00177     }
00178     DDS *dds = bdds->get_dds();
00179     ConstraintEvaluator & ce = bdds->get_ce();
00180     dhi.first_container();
00181     bool print_mime = get_print_mime();
00182 
00183 #ifdef USE_DODSFILTER
00184     DODSFilter df;
00185     df.set_dataset_name(dhi.container->get_real_name());
00186     df.set_ce(dhi.data[POST_CONSTRAINT]);
00187     df.send_dds(dhi.get_output_stream(), *dds, ce, true, "", print_mime);
00188 #else
00189     ResponseBuilder rb;
00190     rb.set_dataset_name(dhi.container->get_real_name());
00191     rb.set_ce(dhi.data[POST_CONSTRAINT]);
00192     rb.send_dds(dhi.get_output_stream(), *dds, ce, true, print_mime);
00193 #endif
00194   }
00195 };
00196 
00197 class SendDataDDS : public Sender
00198 {
00199 private:
00200   virtual string get_request_type() const { return "DataDDS"; }
00201   virtual void  send_internal(
00202       BESResponseObject * obj,
00203       BESDataHandlerInterface & dhi)
00204   {
00205     BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
00206      if( !bdds ) {
00207          throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00208      }
00209      DataDDS *dds = bdds->get_dds();
00210      ConstraintEvaluator & ce = bdds->get_ce();
00211      dhi.first_container();
00212      bool print_mime = get_print_mime();
00213 
00214 #ifdef USE_DODSFILTER
00215      DODSFilter df;
00216      df.set_dataset_name(dds->filename());
00217      df.set_ce(dhi.data[POST_CONSTRAINT]);
00218      df.send_data(*dds, ce, dhi.get_output_stream(), "", print_mime);
00219 #else
00220      ResponseBuilder rb;
00221      rb.set_dataset_name(dds->filename());
00222      rb.set_ce(dhi.data[POST_CONSTRAINT]);
00223      rb.send_data(dhi.get_output_stream(), *dds, ce, print_mime);
00224 #endif
00225   }
00226 };
00227 
00228 class SendDDX : public Sender
00229 {
00230 private:
00231   virtual string get_request_type() const { return "DDX"; }
00232   virtual void  send_internal(
00233       BESResponseObject * obj,
00234       BESDataHandlerInterface & dhi)
00235   {
00236     BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(obj);
00237     if( !bdds ) {
00238       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00239     }
00240     DDS *dds = bdds->get_dds();
00241     ConstraintEvaluator & ce = bdds->get_ce();
00242     dhi.first_container();
00243     bool print_mime = get_print_mime();
00244 
00245 #ifdef USE_DODSFILTER
00246     DODSFilter df;
00247     df.set_dataset_name(dhi.container->get_real_name());
00248     df.set_ce(dhi.data[POST_CONSTRAINT]);
00249     df.send_ddx(*dds, ce, dhi.get_output_stream(), print_mime);
00250 #else
00251     ResponseBuilder rb;
00252     rb.set_dataset_name(dhi.container->get_real_name());
00253     rb.set_ce(dhi.data[POST_CONSTRAINT]);
00254     rb.send_ddx(dhi.get_output_stream(), *dds, ce, print_mime);
00255 #endif
00256   }
00257 };
00258 
00259 class SendDataDDX : public Sender
00260 {
00261 private:
00262   virtual string get_request_type() const { return "DataDDX"; }
00263   virtual void  send_internal(
00264       BESResponseObject * obj,
00265       BESDataHandlerInterface & dhi)
00266   {
00267     BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(obj);
00268     if( !bdds ) {
00269       throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
00270     }
00271     DataDDS *dds = bdds->get_dds();
00272     ConstraintEvaluator & ce = bdds->get_ce();
00273     dhi.first_container();
00274     bool print_mime = get_print_mime();
00275 
00276 #ifdef USE_DODSFILTER
00277     DODSFilter df;
00278     df.set_dataset_name(dds->filename());
00279     df.set_ce(dhi.data[POST_CONSTRAINT]);
00280     BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
00281     df.send_data_ddx(*dds, ce, dhi.get_output_stream(),
00282         dhi.data[DATADDX_STARTID], dhi.data[DATADDX_BOUNDARY],
00283         "", print_mime);
00284 #else
00285     ResponseBuilder rb;
00286     rb.set_dataset_name(dds->filename());
00287     rb.set_ce(dhi.data[POST_CONSTRAINT]);
00288     BESDEBUG("dap", "dhi.data[DATADDX_STARTID]: " << dhi.data[DATADDX_STARTID] << endl);
00289     rb.send_data_ddx(dhi.get_output_stream(), *dds, ce,
00290         dhi.data[DATADDX_STARTID], dhi.data[DATADDX_BOUNDARY], print_mime);
00291 #endif
00292   }
00293 };
00294 
00296 // Public Interface Impl
00297 
00298 BESDapTransmit::BESDapTransmit()
00299     : BESBasicTransmitter()
00300 {
00301     add_method( DAS_SERVICE, BESDapTransmit::send_basic_das ) ;
00302     add_method( DDS_SERVICE, BESDapTransmit::send_basic_dds ) ;
00303     add_method( DDX_SERVICE, BESDapTransmit::send_basic_ddx ) ;
00304     add_method( DATA_SERVICE, BESDapTransmit::send_basic_data ) ;
00305     add_method( DATADDX_SERVICE, BESDapTransmit::send_basic_dataddx ) ;
00306 }
00307 
00308 void
00309 BESDapTransmit::send_basic_das(BESResponseObject * obj,
00310                                BESDataHandlerInterface & dhi)
00311 {
00312   SendDAS sender;
00313   sender.send(obj, dhi);
00314 }
00315 
00316 void
00317 BESDapTransmit::send_basic_dds(BESResponseObject * obj,
00318                                BESDataHandlerInterface & dhi)
00319 {
00320   SendDDS sender;
00321   sender.send(obj, dhi);
00322 }
00323 
00324 void
00325 BESDapTransmit::send_basic_ddx(BESResponseObject * obj,
00326                                BESDataHandlerInterface & dhi)
00327 {
00328   SendDDX sender;
00329   sender.send(obj, dhi);
00330 }
00331 
00332 void
00333 BESDapTransmit::send_basic_data(BESResponseObject * obj,
00334                                 BESDataHandlerInterface & dhi)
00335 {
00336   SendDataDDS sender;
00337   sender.send(obj, dhi);
00338 }
00339 
00340 void
00341 BESDapTransmit::send_basic_dataddx(BESResponseObject * obj,
00342                                    BESDataHandlerInterface & dhi)
00343 {
00344   SendDataDDX sender;
00345   sender.send(obj, dhi);
00346 }