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 rc = xmlTextWriterSetIndent( _writer, 4 ) ;
00137 if( rc < 0 )
00138 {
00139 cleanup() ;
00140 string err = (string)"Error starting indentation for response document "
00141 + _response_name ;
00142 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00143 }
00144
00145 rc = xmlTextWriterSetIndentString( _writer, BAD_CAST " " ) ;
00146 if( rc < 0 )
00147 {
00148 cleanup() ;
00149 string err = (string)"Error setting indentation for response document "
00150 + _response_name ;
00151 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00152 }
00153
00154 _started = true ;
00155
00156
00157
00158
00159 rc = xmlTextWriterStartDocument( _writer, NULL, MY_ENCODING, NULL ) ;
00160 if( rc < 0 )
00161 {
00162 cleanup() ;
00163 string err = (string)"Error starting xml response document for "
00164 + _response_name ;
00165 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00166 }
00167
00168
00169
00170 rc = xmlTextWriterStartElementNS( _writer, NULL,
00171 BAD_CAST "response",
00172 BAD_CAST BES_SCHEMA ) ;
00173 if( rc < 0 )
00174 {
00175 cleanup() ;
00176 string err = (string)"Error starting the response element for response "
00177 + _response_name ;
00178 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00179 }
00180
00181
00182 string reqid = dhi.data[REQUEST_ID] ;
00183 if( !reqid.empty() )
00184 {
00185 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST REQUEST_ID,
00186 BAD_CAST reqid.c_str() ) ;
00187 if( rc < 0 )
00188 {
00189 cleanup() ;
00190 string err = (string)"Error adding attribute " + REQUEST_ID
00191 + " for response " + _response_name ;
00192 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00193 }
00194 }
00195
00196
00197 rc = xmlTextWriterStartElement( _writer, BAD_CAST _response_name.c_str() ) ;
00198 if( rc < 0 )
00199 {
00200 cleanup() ;
00201 string err = (string)"Error creating root element for response "
00202 + _response_name ;
00203 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00204 }
00205 }
00206
00214 void
00215 BESXMLInfo::end_response()
00216 {
00217 BESInfo::end_response() ;
00218
00219 int rc = 0 ;
00220
00221
00222 rc = xmlTextWriterEndElement( _writer ) ;
00223 if( rc < 0 )
00224 {
00225 cleanup() ;
00226 string err = (string)"Error ending response element for response "
00227 + _response_name ;
00228 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00229 }
00230
00231
00232 rc = xmlTextWriterEndElement( _writer ) ;
00233 if( rc < 0 )
00234 {
00235 cleanup() ;
00236 string err = (string)"Error ending specific response element "
00237 + "for response " + _response_name ;
00238 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00239 }
00240
00241 rc = xmlTextWriterEndDocument( _writer ) ;
00242 if( rc < 0 )
00243 {
00244 cleanup() ;
00245 string err = (string)"Error ending the response document for response "
00246 + _response_name ;
00247 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00248 }
00249
00250
00251 xmlFreeTextWriter( _writer ) ;
00252 _writer = 0 ;
00253
00254
00255 if( !_doc_buf->content )
00256 {
00257 cleanup() ;
00258 string err = (string)"Error retrieving response document as string "
00259 + "for response " + _response_name ;
00260 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00261 }
00262 else
00263 {
00264 _doc = (char *)_doc_buf->content ;
00265 }
00266
00267 _ended = true ;
00268
00269 cleanup() ;
00270 }
00271
00278 void
00279 BESXMLInfo::add_tag( const string &tag_name,
00280 const string &tag_data,
00281 map<string,string> *attrs )
00282 {
00283
00284 int rc = xmlTextWriterStartElement( _writer, BAD_CAST tag_name.c_str() ) ;
00285 if( rc < 0 )
00286 {
00287 cleanup() ;
00288 string err = (string)"Error starting element " + tag_name
00289 + " for response " + _response_name ;
00290 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00291 }
00292
00293 if( attrs )
00294 {
00295 map<string,string>::const_iterator i = attrs->begin() ;
00296 map<string,string>::const_iterator e = attrs->end() ;
00297 for( ; i != e; i++ )
00298 {
00299 string name = (*i).first ;
00300 string val = (*i).second ;
00301
00302
00303
00304 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST name.c_str(),
00305 BAD_CAST val.c_str() ) ;
00306 if( rc < 0 )
00307 {
00308 cleanup() ;
00309 string err = (string)"Error adding attribute " + name
00310 + " for response " + _response_name ;
00311 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00312 }
00313 }
00314 }
00315
00316
00317 if( !tag_data.empty() )
00318 {
00319 rc = xmlTextWriterWriteString( _writer, BAD_CAST tag_data.c_str() ) ;
00320 if( rc < 0 )
00321 {
00322 cleanup() ;
00323 string err = (string)"Error writing the value for element "
00324 + tag_name + " for response " + _response_name ;
00325 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00326 }
00327 }
00328
00329
00330 rc = xmlTextWriterEndElement( _writer ) ;
00331 if( rc < 0 )
00332 {
00333 cleanup() ;
00334 string err = (string)"Error ending element " + tag_name
00335 + " for response " + _response_name ;
00336 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00337 }
00338 }
00339
00345 void
00346 BESXMLInfo::begin_tag( const string &tag_name,
00347 map<string,string> *attrs )
00348 {
00349 begin_tag( tag_name, "", "", attrs ) ;
00350 }
00351
00359 void
00360 BESXMLInfo::begin_tag( const string &tag_name,
00361 const string &ns,
00362 const string &uri,
00363 map<string,string> *attrs )
00364 {
00365 BESInfo::begin_tag( tag_name ) ;
00366
00367
00368 int rc = 0 ;
00369 if( ns.empty() && uri.empty() )
00370 {
00371 rc = xmlTextWriterStartElement( _writer, BAD_CAST tag_name.c_str());
00372 if( rc < 0 )
00373 {
00374 cleanup() ;
00375 string err = (string)"Error starting element " + tag_name
00376 + " for response " + _response_name ;
00377 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00378 }
00379 }
00380 else
00381 {
00382 const char *cns = NULL ;
00383 if( !ns.empty() ) cns = ns.c_str() ;
00384 rc = xmlTextWriterStartElementNS( _writer,
00385 BAD_CAST cns,
00386 BAD_CAST tag_name.c_str(),
00387 BAD_CAST uri.c_str() ) ;
00388 if( rc < 0 )
00389 {
00390 cleanup() ;
00391 string err = (string)"Error starting element " + tag_name
00392 + " for response " + _response_name ;
00393 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00394 }
00395 }
00396
00397 if( attrs )
00398 {
00399 map<string,string>::const_iterator i = attrs->begin() ;
00400 map<string,string>::const_iterator e = attrs->end() ;
00401 for( ; i != e; i++ )
00402 {
00403 string name = (*i).first ;
00404 string val = (*i).second ;
00405
00406
00407 rc = xmlTextWriterWriteAttribute( _writer, BAD_CAST name.c_str(),
00408 BAD_CAST val.c_str() ) ;
00409 if( rc < 0 )
00410 {
00411 cleanup() ;
00412 string err = (string)"Error adding attribute " + name
00413 + " for response " + _response_name ;
00414 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00415 }
00416 }
00417 }
00418 }
00419
00426 void
00427 BESXMLInfo::end_tag( const string &tag_name )
00428 {
00429 BESInfo::end_tag( tag_name ) ;
00430
00431 int rc = 0 ;
00432
00433 string s = ((ostringstream *)_strm)->str() ;
00434 if( !s.empty() )
00435 {
00436
00437 rc = xmlTextWriterWriteString( _writer, BAD_CAST s.c_str() ) ;
00438 if( rc < 0 )
00439 {
00440 cleanup() ;
00441 string err = (string)"Error writing the value for element "
00442 + tag_name + " for response " + _response_name ;
00443 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00444 }
00445
00446 ((ostringstream *)_strm)->str( "" ) ;
00447 }
00448
00449
00450 rc = xmlTextWriterEndElement( _writer ) ;
00451 if( rc < 0 )
00452 {
00453 cleanup() ;
00454 string err = (string)"Error ending element " + tag_name
00455 + " for response " + _response_name ;
00456 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00457 }
00458 }
00459
00464 void
00465 BESXMLInfo::add_space( unsigned long num_spaces )
00466 {
00467 string to_add ;
00468 for( unsigned long i = 0; i < num_spaces; i++ )
00469 {
00470 to_add += " " ;
00471 }
00472 BESInfo::add_data( to_add ) ;
00473 }
00474
00479 void
00480 BESXMLInfo::add_break( unsigned long num_breaks )
00481 {
00482 string to_add ;
00483 for( unsigned long i = 0; i < num_breaks; i++ )
00484 {
00485 to_add += "\n" ;
00486 }
00487 BESInfo::add_data( to_add ) ;
00488 }
00489
00490 void
00491 BESXMLInfo::add_data( const string &s )
00492 {
00493 BESInfo::add_data( s ) ;
00494 }
00495
00504 void
00505 BESXMLInfo::add_data_from_file( const string &key, const string &name )
00506 {
00507
00508
00509 begin_tag( "html", "", "http://www.w3.org/1999/xhtml" ) ;
00510
00511 string newkey = key + ".HTML" ;
00512 BESInfo::add_data_from_file( newkey, name ) ;
00513
00514 end_tag( "html" ) ;
00515 }
00516
00525 void
00526 BESXMLInfo::transmit( BESTransmitter *transmitter,
00527 BESDataHandlerInterface &dhi )
00528 {
00529 if( _started && !_ended )
00530 {
00531 end_response() ;
00532 }
00533 transmitter->send_text( *this, dhi ) ;
00534 }
00535
00541 void
00542 BESXMLInfo::print( ostream &strm )
00543 {
00544 if( _started && !_ended )
00545 {
00546 end_response() ;
00547 }
00548 strm << _doc ;
00549 }
00550
00558 void
00559 BESXMLInfo::dump( ostream &strm ) const
00560 {
00561 strm << BESIndent::LMarg << "BESXMLInfo::dump - ("
00562 << (void *)this << ")" << endl ;
00563 BESIndent::Indent() ;
00564 BESInfo::dump( strm ) ;
00565 BESIndent::UnIndent() ;
00566 }
00567
00568 BESInfo *
00569 BESXMLInfo::BuildXMLInfo( const string &info_type )
00570 {
00571 return new BESXMLInfo( ) ;
00572 }
00573