00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef __GNUG__
00034 #pragma implementation
00035 #endif
00036
00037 #include <sstream>
00038
00039 using std::ostringstream ;
00040
00041 #include "BESXMLInfo.h"
00042 #include "BESUtil.h"
00043 #include "BESDataNames.h"
00044
00045 #define MY_ENCODING "ISO-8859-1"
00046 #define BES_SCHEMA "http://xml.opendap.org/ns/bes/1.0#"
00047
00053 BESXMLInfo::BESXMLInfo( )
00054 : BESInfo( ),
00055 _writer( 0 ),
00056 _doc_buf( 0 ),
00057 _started( false ),
00058 _ended( false )
00059 {
00060 }
00061
00062 BESXMLInfo::~BESXMLInfo()
00063 {
00064 cleanup() ;
00065 }
00066
00067 void
00068 BESXMLInfo::cleanup()
00069 {
00070
00071 if( _writer )
00072 {
00073 xmlFreeTextWriter( _writer ) ;
00074 _writer = 0 ;
00075 _doc_buf = 0 ;
00076 }
00077 if( _doc_buf )
00078 {
00079 xmlBufferFree( _doc_buf ) ;
00080 _doc_buf = 0 ;
00081 }
00082
00083
00084
00085
00086 _started = false ;
00087 _ended = false ;
00088 if( _strm )
00089 {
00090 ((ostringstream *)_strm)->str( "" ) ;
00091 }
00092 }
00093
00102 void
00103 BESXMLInfo::begin_response( const string &response_name,
00104 BESDataHandlerInterface &dhi )
00105 {
00106 BESInfo::begin_response( response_name, dhi ) ;
00107
00108 _response_name = response_name ;
00109
00110 LIBXML_TEST_VERSION
00111
00112 int rc = 0 ;
00113
00114
00115
00116 _doc_buf = xmlBufferCreate() ;
00117 if( _doc_buf == NULL )
00118 {
00119 cleanup() ;
00120 string err = (string)"Error creating the xml buffer for response "
00121 + _response_name ;
00122 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00123 }
00124
00125
00126
00127 _writer = xmlNewTextWriterMemory( _doc_buf, 0 ) ;
00128 if( _writer == NULL )
00129 {
00130 cleanup() ;
00131 string err = (string)"Error creating the xml writer for response "
00132 + _response_name ;
00133 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00134 }
00135
00136 _started = true ;
00137
00138
00139
00140
00141 rc = xmlTextWriterStartDocument( _writer, NULL, MY_ENCODING, NULL ) ;
00142 if( rc < 0 )
00143 {
00144 cleanup() ;
00145 string err = (string)"Error starting xml response document for "
00146 + _response_name ;
00147 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00148 }
00149
00150
00151
00152 rc = xmlTextWriterStartElementNS( _writer, NULL,
00153 BAD_CAST "response",
00154 BAD_CAST BES_SCHEMA ) ;
00155 if( rc < 0 )
00156 {
00157 cleanup() ;
00158 string err = (string)"Error starting the response element for response "
00159 + _response_name ;
00160 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00161 }
00162
00163
00164 string reqid = dhi.data[REQUEST_ID] ;
00165 if( !reqid.empty() )
00166 {
00167 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST REQUEST_ID,
00168 BAD_CAST reqid.c_str() ) ;
00169 if( rc < 0 )
00170 {
00171 cleanup() ;
00172 string err = (string)"Error adding attribute " + REQUEST_ID
00173 + " for response " + _response_name ;
00174 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00175 }
00176 }
00177
00178
00179 rc = xmlTextWriterStartElement( _writer, BAD_CAST _response_name.c_str() ) ;
00180 if( rc < 0 )
00181 {
00182 cleanup() ;
00183 string err = (string)"Error creating root element for response "
00184 + _response_name ;
00185 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00186 }
00187 }
00188
00196 void
00197 BESXMLInfo::end_response()
00198 {
00199 BESInfo::end_response() ;
00200
00201 int rc = 0 ;
00202
00203
00204 rc = xmlTextWriterEndElement( _writer ) ;
00205 if( rc < 0 )
00206 {
00207 cleanup() ;
00208 string err = (string)"Error ending response element for response "
00209 + _response_name ;
00210 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00211 }
00212
00213
00214 rc = xmlTextWriterEndElement( _writer ) ;
00215 if( rc < 0 )
00216 {
00217 cleanup() ;
00218 string err = (string)"Error ending specific response element "
00219 + "for response " + _response_name ;
00220 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00221 }
00222
00223 rc = xmlTextWriterEndDocument( _writer ) ;
00224 if( rc < 0 )
00225 {
00226 cleanup() ;
00227 string err = (string)"Error ending the response document for response "
00228 + _response_name ;
00229 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00230 }
00231
00232
00233 xmlFreeTextWriter( _writer ) ;
00234 _writer = 0 ;
00235
00236
00237 if( !_doc_buf->content )
00238 {
00239 cleanup() ;
00240 string err = (string)"Error retrieving response document as string "
00241 + "for response " + _response_name ;
00242 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00243 }
00244 else
00245 {
00246 _doc = (char *)_doc_buf->content ;
00247 }
00248
00249 _ended = true ;
00250
00251 cleanup() ;
00252 }
00253
00260 void
00261 BESXMLInfo::add_tag( const string &tag_name,
00262 const string &tag_data,
00263 map<string,string> *attrs )
00264 {
00265
00266 int rc = xmlTextWriterStartElement( _writer, BAD_CAST tag_name.c_str() ) ;
00267 if( rc < 0 )
00268 {
00269 cleanup() ;
00270 string err = (string)"Error starting element " + tag_name
00271 + " for response " + _response_name ;
00272 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00273 }
00274
00275 if( attrs )
00276 {
00277 map<string,string>::const_iterator i = attrs->begin() ;
00278 map<string,string>::const_iterator e = attrs->end() ;
00279 for( ; i != e; i++ )
00280 {
00281 string name = (*i).first ;
00282 string val = (*i).second ;
00283
00284
00285
00286 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST name.c_str(),
00287 BAD_CAST val.c_str() ) ;
00288 if( rc < 0 )
00289 {
00290 cleanup() ;
00291 string err = (string)"Error adding attribute " + name
00292 + " for response " + _response_name ;
00293 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00294 }
00295 }
00296 }
00297
00298
00299 if( !tag_data.empty() )
00300 {
00301 rc = xmlTextWriterWriteString( _writer, BAD_CAST tag_data.c_str() ) ;
00302 if( rc < 0 )
00303 {
00304 cleanup() ;
00305 string err = (string)"Error writing the value for element "
00306 + tag_name + " for response " + _response_name ;
00307 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00308 }
00309 }
00310
00311
00312 rc = xmlTextWriterEndElement( _writer ) ;
00313 if( rc < 0 )
00314 {
00315 cleanup() ;
00316 string err = (string)"Error ending element " + tag_name
00317 + " for response " + _response_name ;
00318 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00319 }
00320 }
00321
00327 void
00328 BESXMLInfo::begin_tag( const string &tag_name,
00329 map<string,string> *attrs )
00330 {
00331 begin_tag( tag_name, "", "", attrs ) ;
00332 }
00333
00341 void
00342 BESXMLInfo::begin_tag( const string &tag_name,
00343 const string &ns,
00344 const string &uri,
00345 map<string,string> *attrs )
00346 {
00347 BESInfo::begin_tag( tag_name ) ;
00348
00349
00350 int rc = 0 ;
00351 if( ns.empty() && uri.empty() )
00352 {
00353 rc = xmlTextWriterStartElement( _writer, BAD_CAST tag_name.c_str());
00354 if( rc < 0 )
00355 {
00356 cleanup() ;
00357 string err = (string)"Error starting element " + tag_name
00358 + " for response " + _response_name ;
00359 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00360 }
00361 }
00362 else
00363 {
00364 const char *cns = NULL ;
00365 if( !ns.empty() ) cns = ns.c_str() ;
00366 rc = xmlTextWriterStartElementNS( _writer,
00367 BAD_CAST cns,
00368 BAD_CAST tag_name.c_str(),
00369 BAD_CAST uri.c_str() ) ;
00370 if( rc < 0 )
00371 {
00372 cleanup() ;
00373 string err = (string)"Error starting element " + tag_name
00374 + " for response " + _response_name ;
00375 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00376 }
00377 }
00378
00379 if( attrs )
00380 {
00381 map<string,string>::const_iterator i = attrs->begin() ;
00382 map<string,string>::const_iterator e = attrs->end() ;
00383 for( ; i != e; i++ )
00384 {
00385 string name = (*i).first ;
00386 string val = (*i).second ;
00387
00388
00389 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST name.c_str(),
00390 BAD_CAST val.c_str() ) ;
00391 if( rc < 0 )
00392 {
00393 cleanup() ;
00394 string err = (string)"Error adding attribute " + name
00395 + " for response " + _response_name ;
00396 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00397 }
00398 }
00399 }
00400 }
00401
00408 void
00409 BESXMLInfo::end_tag( const string &tag_name )
00410 {
00411 BESInfo::end_tag( tag_name ) ;
00412
00413 int rc = 0 ;
00414
00415 string s = ((ostringstream *)_strm)->str() ;
00416 if( !s.empty() )
00417 {
00418
00419 rc = xmlTextWriterWriteString( _writer, BAD_CAST s.c_str() ) ;
00420 if( rc < 0 )
00421 {
00422 cleanup() ;
00423 string err = (string)"Error writing the value for element "
00424 + tag_name + " for response " + _response_name ;
00425 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00426 }
00427
00428 ((ostringstream *)_strm)->str( "" ) ;
00429 }
00430
00431
00432 rc = xmlTextWriterEndElement( _writer ) ;
00433 if( rc < 0 )
00434 {
00435 cleanup() ;
00436 string err = (string)"Error ending element " + tag_name
00437 + " for response " + _response_name ;
00438 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00439 }
00440 }
00441
00446 void
00447 BESXMLInfo::add_space( unsigned long num_spaces )
00448 {
00449 string to_add ;
00450 for( unsigned long i = 0; i < num_spaces; i++ )
00451 {
00452 to_add += " " ;
00453 }
00454 BESInfo::add_data( to_add ) ;
00455 }
00456
00461 void
00462 BESXMLInfo::add_break( unsigned long num_breaks )
00463 {
00464 string to_add ;
00465 for( unsigned long i = 0; i < num_breaks; i++ )
00466 {
00467 to_add += "\n" ;
00468 }
00469 BESInfo::add_data( to_add ) ;
00470 }
00471
00472 void
00473 BESXMLInfo::add_data( const string &s )
00474 {
00475 BESInfo::add_data( s ) ;
00476 }
00477
00486 void
00487 BESXMLInfo::add_data_from_file( const string &key, const string &name )
00488 {
00489
00490
00491 begin_tag( "html", "", "http://www.w3.org/1999/xhtml" ) ;
00492
00493 string newkey = key + ".HTML" ;
00494 BESInfo::add_data_from_file( newkey, name ) ;
00495
00496 end_tag( "html" ) ;
00497 }
00498
00507 void
00508 BESXMLInfo::transmit( BESTransmitter *transmitter,
00509 BESDataHandlerInterface &dhi )
00510 {
00511 if( _started && !_ended )
00512 {
00513 end_response() ;
00514 }
00515 transmitter->send_text( *this, dhi ) ;
00516 }
00517
00523 void
00524 BESXMLInfo::print( ostream &strm )
00525 {
00526 if( _started && !_ended )
00527 {
00528 end_response() ;
00529 }
00530 strm << _doc ;
00531 }
00532
00540 void
00541 BESXMLInfo::dump( ostream &strm ) const
00542 {
00543 strm << BESIndent::LMarg << "BESXMLInfo::dump - ("
00544 << (void *)this << ")" << endl ;
00545 BESIndent::Indent() ;
00546 BESInfo::dump( strm ) ;
00547 BESIndent::UnIndent() ;
00548 }
00549
00550 BESInfo *
00551 BESXMLInfo::BuildXMLInfo( const string &info_type )
00552 {
00553 return new BESXMLInfo( ) ;
00554 }
00555