OPeNDAP Hyrax Back End Server (BES)
Updated for version 3.8.3
|
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 }