OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
|
00001 // CmdTranslation.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 <iostream> 00034 #include <list> 00035 #include <map> 00036 00037 using std::cerr ; 00038 using std::cout ; 00039 using std::list ; 00040 using std::map ; 00041 00042 #include "CmdTranslation.h" 00043 #include "BESTokenizer.h" 00044 #include "BESSyntaxUserError.h" 00045 00046 #define MY_ENCODING "ISO-8859-1" 00047 00048 map< string, CmdTranslation::p_cmd_translator > CmdTranslation::_translations ; 00049 bool CmdTranslation::_is_show = false ; 00050 00051 int 00052 CmdTranslation::initialize(int, char**) 00053 { 00054 _translations["show"] = CmdTranslation::translate_show ; 00055 _translations["show.catalog"] = CmdTranslation::translate_catalog ; 00056 _translations["show.info"] = CmdTranslation::translate_catalog ; 00057 _translations["show.error"] = CmdTranslation::translate_show_error ; 00058 _translations["set"] = CmdTranslation::translate_set ; 00059 _translations["set.context"] = CmdTranslation::translate_context ; 00060 _translations["set.container"] = CmdTranslation::translate_container ; 00061 _translations["define"] = CmdTranslation::translate_define ; 00062 _translations["delete"] = CmdTranslation::translate_delete ; 00063 _translations["get"] = CmdTranslation::translate_get ; 00064 return 0 ; 00065 } 00066 00067 int 00068 CmdTranslation::terminate(void) 00069 { 00070 return 0 ; 00071 } 00072 00073 void 00074 CmdTranslation::add_translation( const string &name, p_cmd_translator func ) 00075 { 00076 CmdTranslation::_translations[name] = func ; 00077 } 00078 00079 void 00080 CmdTranslation::remove_translation( const string &name ) 00081 { 00082 map<string,p_cmd_translator>::iterator i = 00083 CmdTranslation::_translations.find( name ) ; 00084 if( i != CmdTranslation::_translations.end() ) 00085 { 00086 CmdTranslation::_translations.erase( i ) ; 00087 } 00088 } 00089 00090 string 00091 CmdTranslation::translate( const string &commands ) 00092 { 00093 BESTokenizer t ; 00094 try 00095 { 00096 t.tokenize( commands.c_str() ) ; 00097 00098 string token = t.get_first_token() ; 00099 if( token.empty() ) 00100 { 00101 return "" ; 00102 } 00103 } 00104 catch( BESSyntaxUserError &e ) 00105 { 00106 cerr << "failed to build tokenizer for translation" << endl ; 00107 cerr << e.get_message() << endl ; 00108 return "" ; 00109 } 00110 00111 LIBXML_TEST_VERSION; 00112 00113 int rc; 00114 xmlTextWriterPtr writer = 0 ; 00115 xmlBufferPtr buf = 0 ; 00116 xmlChar *tmp = 0 ; 00117 00118 /* Create a new XML buffer, to which the XML document will be 00119 * written */ 00120 buf = xmlBufferCreate() ; 00121 if( buf == NULL ) 00122 { 00123 cerr << "testXmlwriterMemory: Error creating the xml buffer" << endl ; 00124 return "" ; 00125 } 00126 00127 /* Create a new XmlWriter for memory, with no compression. 00128 * Remark: there is no compression for this kind of xmlTextWriter */ 00129 writer = xmlNewTextWriterMemory( buf, 0 ) ; 00130 if( writer == NULL ) 00131 { 00132 cerr << "testXmlwriterMemory: Error creating the xml writer" << endl ; 00133 return "" ; 00134 } 00135 00136 /* Start the document with the xml default for the version, 00137 * encoding ISO 8859-1 and the default for the standalone 00138 * declaration. MY_ENCODING defined at top of this file*/ 00139 rc = xmlTextWriterStartDocument( writer, NULL, MY_ENCODING, NULL ) ; 00140 if( rc < 0 ) 00141 { 00142 cerr << "testXmlwriterMemory: Error at xmlTextWriterStartDocument" 00143 << endl ; 00144 xmlFreeTextWriter( writer ) ; 00145 return "" ; 00146 } 00147 00148 /* Start an element named "request". Since thist is the first 00149 * element, this will be the root element of the document. */ 00150 rc = xmlTextWriterStartElement( writer, BAD_CAST "request" ) ; 00151 if( rc < 0 ) 00152 { 00153 cerr << "testXmlwriterMemory: Error at xmlTextWriterStartElement" 00154 << endl ; 00155 xmlFreeTextWriter( writer ) ; 00156 return "" ; 00157 } 00158 00159 /* Add the request id attribute */ 00160 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "reqID", 00161 BAD_CAST "some_unique_value" ) ; 00162 if( rc < 0 ) 00163 { 00164 cerr << "failed to add the request id attribute" << endl ; 00165 return "" ; 00166 } 00167 00168 bool status = do_translate( t, writer ) ; 00169 if( !status ) 00170 { 00171 xmlFreeTextWriter( writer ) ; 00172 return "" ; 00173 } 00174 00175 // this should end the request element 00176 rc = xmlTextWriterEndElement( writer ) ; 00177 if( rc < 0 ) 00178 { 00179 cerr << "failed to close request element" << endl ; 00180 xmlFreeTextWriter( writer ) ; 00181 return "" ; 00182 } 00183 00184 rc = xmlTextWriterEndDocument( writer ) ; 00185 if( rc < 0 ) 00186 { 00187 cerr << "failed to end the document" << endl ; 00188 return "" ; 00189 } 00190 00191 xmlFreeTextWriter(writer); 00192 00193 // get the xml document as a string and return 00194 string doc ; 00195 if( !buf->content ) 00196 { 00197 cerr << "failed to retrieve document as string" << endl ; 00198 } 00199 else 00200 { 00201 doc = (char *)buf->content ; 00202 } 00203 00204 xmlBufferFree( buf ) ; 00205 00206 xmlCleanupParser(); 00207 00208 return doc ; 00209 } 00210 00211 bool 00212 CmdTranslation::do_translate( BESTokenizer &t, xmlTextWriterPtr writer ) 00213 { 00214 string token = t.get_current_token() ; 00215 CmdTranslation::p_cmd_translator p = _translations[token] ; 00216 if( !p ) 00217 { 00218 cerr << endl << "Invalid command " << token << endl << endl ; 00219 return false ; 00220 } 00221 00222 try 00223 { 00224 bool status = p( t, writer ) ; 00225 if( !status ) 00226 { 00227 return status ; 00228 } 00229 } 00230 catch( BESSyntaxUserError &e ) 00231 { 00232 cerr << e.get_message() << endl ; 00233 return false ; 00234 } 00235 00236 // if this throws an exception then there are no more tokens. Catch it 00237 // and ignore the exception. This means we're done. 00238 try 00239 { 00240 token = t.get_next_token() ; 00241 } 00242 catch( BESSyntaxUserError &e ) 00243 { 00244 token.clear() ; 00245 } 00246 00247 if( token.empty() ) 00248 { 00249 // we are done. 00250 return true ; 00251 } 00252 00253 // more translation to do, so call do_translate again. It will grab the 00254 // current token which we just got. 00255 return do_translate( t, writer ) ; 00256 } 00257 00258 bool 00259 CmdTranslation::translate_show( BESTokenizer &t, xmlTextWriterPtr writer ) 00260 { 00261 CmdTranslation::set_show( true ) ; 00262 00263 string show_what = t.get_next_token() ; 00264 if( show_what.empty() ) 00265 { 00266 t.parse_error( "show command must be followed by target" ) ; 00267 } 00268 00269 string new_cmd = "show." + show_what ; 00270 CmdTranslation::p_cmd_translator p = _translations[new_cmd] ; 00271 if( p ) 00272 { 00273 return p( t, writer ) ; 00274 } 00275 00276 string semi = t.get_next_token() ; 00277 if( semi != ";" ) 00278 { 00279 string err = (string)"show " + show_what 00280 + " commands must end with a semicolon" ; 00281 t.parse_error( err ) ; 00282 } 00283 show_what[0] = toupper( show_what[0] ) ; 00284 string tag = "show" + show_what ; 00285 00286 // start the show element 00287 int rc = xmlTextWriterStartElement( writer, BAD_CAST tag.c_str() ) ; 00288 if( rc < 0 ) 00289 { 00290 cerr << "failed to start " << tag << " element" << endl ; 00291 return false ; 00292 } 00293 00294 // end the show element 00295 rc = xmlTextWriterEndElement( writer ) ; 00296 if( rc < 0 ) 00297 { 00298 cerr << "failed to close " << tag << " element" << endl ; 00299 return false ; 00300 } 00301 00302 return true ; 00303 } 00304 00305 bool 00306 CmdTranslation::translate_show_error( BESTokenizer &t, xmlTextWriterPtr writer) 00307 { 00308 string show_what = t.get_current_token() ; 00309 if( show_what.empty() || show_what != "error" ) 00310 { 00311 t.parse_error( "show command must be error" ) ; 00312 } 00313 00314 string etype = t.get_next_token() ; 00315 if( etype == ";" ) 00316 { 00317 string err = (string)"show " + show_what 00318 + " command must inlude the error type to show" ; 00319 t.parse_error( err ) ; 00320 } 00321 00322 string semi = t.get_next_token() ; 00323 if( semi != ";" ) 00324 { 00325 string err = (string)"show " + show_what 00326 + " commands must end with a semicolon" ; 00327 t.parse_error( err ) ; 00328 } 00329 show_what[0] = toupper( show_what[0] ) ; 00330 string tag = "show" + show_what ; 00331 00332 // start the show element 00333 int rc = xmlTextWriterStartElement( writer, BAD_CAST tag.c_str() ) ; 00334 if( rc < 0 ) 00335 { 00336 cerr << "failed to start " << tag << " element" << endl ; 00337 return false ; 00338 } 00339 00340 /* Add the error type attribute */ 00341 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "type", 00342 BAD_CAST etype.c_str() ) ; 00343 if( rc < 0 ) 00344 { 00345 cerr << "failed to add the get type attribute" << endl ; 00346 return "" ; 00347 } 00348 00349 // end the show element 00350 rc = xmlTextWriterEndElement( writer ) ; 00351 if( rc < 0 ) 00352 { 00353 cerr << "failed to close " << tag << " element" << endl ; 00354 return false ; 00355 } 00356 00357 return true ; 00358 } 00359 00360 bool 00361 CmdTranslation::translate_catalog( BESTokenizer &t, xmlTextWriterPtr writer ) 00362 { 00363 // show catalog|info [for node] 00364 // <showCatalog node="" /> 00365 string show_what = t.get_current_token() ; 00366 if( show_what.empty() || ( show_what != "info" && show_what != "catalog" ) ) 00367 { 00368 t.parse_error( "show command must be info or catalog" ) ; 00369 } 00370 00371 show_what[0] = toupper( show_what[0] ) ; 00372 string tag = "show" + show_what ; 00373 00374 string token = t.get_next_token() ; 00375 string node ; 00376 if( token == "for" ) 00377 { 00378 node = t.get_next_token() ; 00379 if( node == ";" ) 00380 { 00381 t.parse_error( "show catalog command expecting node" ) ; 00382 } 00383 node = t.remove_quotes( node ) ; 00384 token = t.get_next_token() ; 00385 } 00386 if( token != ";" ) 00387 { 00388 t.parse_error( "show command must be terminated by a semicolon" ) ; 00389 } 00390 00391 // start the show element 00392 int rc = xmlTextWriterStartElement( writer, BAD_CAST tag.c_str() ) ; 00393 if( rc < 0 ) 00394 { 00395 cerr << "failed to start " << tag << " element" << endl ; 00396 return false ; 00397 } 00398 00399 /* Add the catalog node */ 00400 if( !node.empty() ) 00401 { 00402 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "node", 00403 BAD_CAST node.c_str() ) ; 00404 if( rc < 0 ) 00405 { 00406 cerr << "failed to add the catalog node attribute" << endl ; 00407 return "" ; 00408 } 00409 } 00410 00411 // end the show element 00412 rc = xmlTextWriterEndElement( writer ) ; 00413 if( rc < 0 ) 00414 { 00415 cerr << "failed to close " << tag << " element" << endl ; 00416 return false ; 00417 } 00418 00419 return true ; 00420 } 00421 00422 bool 00423 CmdTranslation::translate_set( BESTokenizer &t, 00424 xmlTextWriterPtr writer ) 00425 { 00426 string set_what = t.get_next_token() ; 00427 if( set_what.empty() ) 00428 { 00429 t.parse_error( "set command must be followed by target" ) ; 00430 } 00431 00432 string new_cmd = "set." + set_what ; 00433 CmdTranslation::p_cmd_translator p = _translations[new_cmd] ; 00434 if( !p ) 00435 { 00436 cerr << "no such command: set " << set_what << endl ; 00437 return false ; 00438 } 00439 00440 return p( t, writer ) ; 00441 } 00442 00443 bool 00444 CmdTranslation::translate_context( BESTokenizer &t, 00445 xmlTextWriterPtr writer ) 00446 { 00447 // set context blee to blah ; 00448 // <setContext name="dap_format">dap2</setContext> 00449 string name = t.get_next_token() ; 00450 if( name == ";" ) 00451 { 00452 t.parse_error( "missing context name" ) ; 00453 } 00454 string to = t.get_next_token() ; 00455 if( to != "to" ) 00456 { 00457 t.parse_error( "missing word \"to\" in set context" ) ; 00458 } 00459 string value = t.get_next_token() ; 00460 if( value == ";" ) 00461 { 00462 t.parse_error( "missing context value" ) ; 00463 } 00464 string semi = t.get_next_token() ; 00465 if( semi != ";" ) 00466 { 00467 t.parse_error( "set context command must end with semicolon" ) ; 00468 } 00469 00470 // start the setContext element 00471 int rc = xmlTextWriterStartElement( writer, BAD_CAST "setContext" ) ; 00472 if( rc < 0 ) 00473 { 00474 cerr << "failed to start setContext element" << endl ; 00475 return false ; 00476 } 00477 00478 /* Add the context name attribute */ 00479 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "name", 00480 BAD_CAST name.c_str() ) ; 00481 if( rc < 0 ) 00482 { 00483 cerr << "failed to add the context name attribute" << endl ; 00484 return "" ; 00485 } 00486 00487 /* Write the value of the context */ 00488 rc = xmlTextWriterWriteString( writer, BAD_CAST value.c_str() ) ; 00489 if( rc < 0 ) 00490 { 00491 cerr << "failed to write the value of the context" << endl ; 00492 return "" ; 00493 } 00494 00495 // end the setContext element 00496 rc = xmlTextWriterEndElement( writer ) ; 00497 if( rc < 0 ) 00498 { 00499 cerr << "failed to close setContext element" << endl ; 00500 return false ; 00501 } 00502 00503 return true ; 00504 } 00505 00506 bool 00507 CmdTranslation::translate_container( BESTokenizer &t, 00508 xmlTextWriterPtr writer ) 00509 { 00510 // set container in space values name,value,type; 00511 // <setContainer name="c" space="catalog">/data/fnoc1.nc</setContainer> 00512 string token = t.get_next_token() ; 00513 string space ; 00514 if( token == "in" ) 00515 { 00516 space = t.get_next_token() ; 00517 if( space == "values" || space == ";" ) 00518 { 00519 t.parse_error( "expecting name of container storage" ) ; 00520 } 00521 token = t.get_next_token() ; 00522 } 00523 if( token != "values" ) 00524 { 00525 t.parse_error( "missing values for set container" ) ; 00526 } 00527 00528 string name = t.get_next_token() ; 00529 if( name == ";" || name == "," ) 00530 { 00531 t.parse_error( "expecting name of the container" ) ; 00532 } 00533 00534 token = t.get_next_token() ; 00535 if( token != "," ) 00536 { 00537 t.parse_error( "missing comma in set container after name" ) ; 00538 } 00539 00540 string value = t.get_next_token() ; 00541 if( value == "," || value == ";" ) 00542 { 00543 t.parse_error( "expecting location of the container" ) ; 00544 } 00545 00546 token = t.get_next_token() ; 00547 string type ; 00548 if( token == "," ) 00549 { 00550 type = t.get_next_token() ; 00551 if( type == ";" ) 00552 { 00553 t.parse_error( "expecting container type" ) ; 00554 } 00555 token = t.get_next_token() ; 00556 } 00557 00558 if( token != ";" ) 00559 { 00560 t.parse_error( "set container command must end with semicolon" ) ; 00561 } 00562 00563 // start the setContainer element 00564 int rc = xmlTextWriterStartElement( writer, BAD_CAST "setContainer" ) ; 00565 if( rc < 0 ) 00566 { 00567 cerr << "failed to start setContext element" << endl ; 00568 return false ; 00569 } 00570 00571 /* Add the container name attribute */ 00572 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "name", 00573 BAD_CAST name.c_str() ) ; 00574 if( rc < 0 ) 00575 { 00576 cerr << "failed to add the context name attribute" << endl ; 00577 return "" ; 00578 } 00579 00580 if( !space.empty() ) 00581 { 00582 /* Add the container space attribute */ 00583 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "space", 00584 BAD_CAST space.c_str() ) ; 00585 if( rc < 0 ) 00586 { 00587 cerr << "failed to add the container space attribute" << endl ; 00588 return "" ; 00589 } 00590 } 00591 00592 if( !type.empty() ) 00593 { 00594 /* Add the container space attribute */ 00595 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "type", 00596 BAD_CAST type.c_str() ) ; 00597 if( rc < 0 ) 00598 { 00599 cerr << "failed to add the container type attribute" << endl ; 00600 return "" ; 00601 } 00602 } 00603 00604 /* Write the value of the container */ 00605 rc = xmlTextWriterWriteString( writer, BAD_CAST value.c_str() ) ; 00606 if( rc < 0 ) 00607 { 00608 cerr << "failed to write the location of the container" << endl ; 00609 return "" ; 00610 } 00611 00612 // end the setContainer element 00613 rc = xmlTextWriterEndElement( writer ) ; 00614 if( rc < 0 ) 00615 { 00616 cerr << "failed to close setContext element" << endl ; 00617 return false ; 00618 } 00619 00620 return true ; 00621 } 00622 00623 bool 00624 CmdTranslation::translate_define( BESTokenizer &t, 00625 xmlTextWriterPtr writer ) 00626 { 00627 // define <def_name> [in <storage_name>] as <container_list> [where // <container_x>.constraint="<constraint>",<container_x>.attributes="<attribute_list>"] // [aggregate by "<aggregation_command>"]; 00628 00629 // <define name="definition_name" space="store_name"> 00630 // <container name="container_name"> 00631 // <constraint>legal_constraint</constraint> 00632 // <attributes>attribute_list</attributes> 00633 // </container> 00634 // <aggregate handler="someHandler" cmd="someCommand" /> 00635 // </define> 00636 string name = t.get_next_token() ; 00637 string space ; 00638 string token = t.get_next_token() ; 00639 if( token == "in" ) 00640 { 00641 space = t.get_next_token() ; 00642 token = t.get_next_token() ; 00643 } 00644 00645 if( token != "as" ) 00646 { 00647 t.parse_error( "Looking for keyword as in define command" ) ; 00648 } 00649 00650 list<string> containers ; 00651 map<string,string> clist ; 00652 bool done = false ; 00653 while( !done ) 00654 { 00655 token = t.get_next_token() ; 00656 containers.push_back( token ) ; 00657 clist[token] = token ; 00658 token = t.get_next_token() ; 00659 if( token != "," ) 00660 { 00661 done = true ; 00662 } 00663 } 00664 00665 // constraints and attributes 00666 map<string,string> constraints ; 00667 string default_constraint ; 00668 map<string,string> attrs ; 00669 if( token == "with" ) 00670 { 00671 token = t.get_next_token() ; 00672 unsigned int type ; 00673 while( token != "aggregate" && token != ";" ) 00674 { 00675 // see if we have a default constraint for all containers 00676 if( token == "constraint" ) 00677 { 00678 default_constraint = t.remove_quotes( t.get_next_token() ) ; 00679 } 00680 else 00681 { 00682 string c = t.parse_container_name( token, type ) ; 00683 if( clist[c] != c ) 00684 { 00685 t.parse_error( "contstraint container does not exist" ) ; 00686 } 00687 if( type == 1 ) 00688 { 00689 // constraint 00690 constraints[c] = t.remove_quotes( t.get_next_token() ) ; 00691 } 00692 else if( type == 2 ) 00693 { 00694 // attributed 00695 attrs[c] = t.remove_quotes( t.get_next_token() ) ; 00696 } 00697 else 00698 { 00699 t.parse_error( "unknown constraint type" ) ; 00700 } 00701 token = t.get_next_token() ; 00702 if( token == "," ) 00703 { 00704 token = t.get_next_token() ; 00705 } 00706 } 00707 } 00708 } 00709 00710 string agg_handler ; 00711 string agg_cmd ; 00712 if( token == "aggregate" ) 00713 { 00714 token = t.get_next_token() ; 00715 if( token == "by" ) 00716 { 00717 agg_cmd = t.remove_quotes( t.get_next_token() ) ; 00718 token = t.get_next_token() ; 00719 if( token != "using" ) 00720 { 00721 t.parse_error( "aggregation expecting keyword \"using\""); 00722 } 00723 agg_handler = t.get_next_token() ; 00724 } 00725 else if( token == "using" ) 00726 { 00727 agg_handler = t.get_next_token() ; 00728 token = t.get_next_token() ; 00729 if( token != "by" ) 00730 { 00731 t.parse_error( "aggregation expecting keyword \"by\""); 00732 } 00733 agg_cmd = t.remove_quotes( t.get_next_token() ) ; 00734 } 00735 else 00736 { 00737 t.parse_error( "aggregation expecting keyword \"by\" or \"using\""); 00738 } 00739 00740 token = t.get_next_token() ; 00741 } 00742 00743 if( token != ";" ) 00744 { 00745 t.parse_error( "define command must end with semicolon" ) ; 00746 } 00747 00748 // start the define element 00749 int rc = xmlTextWriterStartElement( writer, BAD_CAST "define" ) ; 00750 if( rc < 0 ) 00751 { 00752 cerr << "failed to start setContext element" << endl ; 00753 return false ; 00754 } 00755 00756 /* Add the definition name attribute */ 00757 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "name", 00758 BAD_CAST name.c_str() ) ; 00759 if( rc < 0 ) 00760 { 00761 cerr << "failed to add the context name attribute" << endl ; 00762 return "" ; 00763 } 00764 00765 if( !space.empty() ) 00766 { 00767 /* Add the definition space attribute */ 00768 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "space", 00769 BAD_CAST space.c_str() ) ; 00770 if( rc < 0 ) 00771 { 00772 cerr << "failed to add the container space attribute" << endl ; 00773 return "" ; 00774 } 00775 } 00776 00777 // write the default constraint if we have one 00778 if( !default_constraint.empty() ) 00779 { 00780 // start the constraint element 00781 int rc = xmlTextWriterStartElement( writer, BAD_CAST "constraint" ); 00782 if( rc < 0 ) 00783 { 00784 cerr << "failed to start container constraint element" << endl ; 00785 return false ; 00786 } 00787 00788 /* Write the value of the constraint */ 00789 rc = xmlTextWriterWriteString( writer, BAD_CAST default_constraint.c_str()); 00790 if( rc < 0 ) 00791 { 00792 cerr << "failed to write constraint for container" << endl ; 00793 return "" ; 00794 } 00795 00796 // end the container constraint element 00797 rc = xmlTextWriterEndElement( writer ) ; 00798 if( rc < 0 ) 00799 { 00800 cerr << "failed to close constraint element" << endl ; 00801 return false ; 00802 } 00803 } 00804 00805 list<string>::iterator i = containers.begin() ; 00806 list<string>::iterator e = containers.end() ; 00807 for( ; i != e; i++ ) 00808 { 00809 // start the container element 00810 int rc = xmlTextWriterStartElement( writer, BAD_CAST "container" ) ; 00811 if( rc < 0 ) 00812 { 00813 cerr << "failed to start container element" << endl ; 00814 return false ; 00815 } 00816 00817 /* Add the container name attribute */ 00818 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "name", 00819 BAD_CAST (*i).c_str() ) ; 00820 if( rc < 0 ) 00821 { 00822 cerr << "failed to add the context name attribute" << endl ; 00823 return "" ; 00824 } 00825 00826 // add constraints and attributes elements here 00827 string constraint = constraints[(*i)] ; 00828 if( !constraint.empty() ) 00829 { 00830 // start the constraint element 00831 int rc = xmlTextWriterStartElement( writer, BAD_CAST "constraint" ); 00832 if( rc < 0 ) 00833 { 00834 cerr << "failed to start container constraint element" << endl ; 00835 return false ; 00836 } 00837 00838 /* Write the value of the constraint */ 00839 rc = xmlTextWriterWriteString( writer, BAD_CAST constraint.c_str()); 00840 if( rc < 0 ) 00841 { 00842 cerr << "failed to write constraint for container" << endl ; 00843 return "" ; 00844 } 00845 00846 // end the container constraint element 00847 rc = xmlTextWriterEndElement( writer ) ; 00848 if( rc < 0 ) 00849 { 00850 cerr << "failed to close constraint element" << endl ; 00851 return false ; 00852 } 00853 } 00854 00855 string attr = attrs[(*i)] ; 00856 if( !attr.empty() ) 00857 { 00858 // start the attribute element 00859 int rc = xmlTextWriterStartElement( writer, BAD_CAST "attributes" ); 00860 if( rc < 0 ) 00861 { 00862 cerr << "failed to start container attributes element" << endl ; 00863 return false ; 00864 } 00865 00866 /* Write the value of the constraint */ 00867 rc = xmlTextWriterWriteString( writer, BAD_CAST attr.c_str()); 00868 if( rc < 0 ) 00869 { 00870 cerr << "failed to write attributes for container" << endl ; 00871 return "" ; 00872 } 00873 00874 // end the container constraint element 00875 rc = xmlTextWriterEndElement( writer ) ; 00876 if( rc < 0 ) 00877 { 00878 cerr << "failed to close attributes element" << endl ; 00879 return false ; 00880 } 00881 } 00882 00883 // end the container element 00884 rc = xmlTextWriterEndElement( writer ) ; 00885 if( rc < 0 ) 00886 { 00887 cerr << "failed to close setContext element" << endl ; 00888 return false ; 00889 } 00890 } 00891 00892 if( !agg_cmd.empty() ) 00893 { 00894 // start the aggregation element 00895 int rc = xmlTextWriterStartElement( writer, BAD_CAST "aggregate" ) ; 00896 if( rc < 0 ) 00897 { 00898 cerr << "failed to start aggregate element" << endl ; 00899 return false ; 00900 } 00901 00902 if( !agg_handler.empty() ) 00903 { 00904 /* Add the aggregation handler attribute */ 00905 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "handler", 00906 BAD_CAST agg_handler.c_str() ) ; 00907 if( rc < 0 ) 00908 { 00909 cerr << "failed to add the context name attribute" << endl ; 00910 return "" ; 00911 } 00912 } 00913 00914 /* Add the aggregation command attribute */ 00915 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "cmd", 00916 BAD_CAST agg_cmd.c_str() ) ; 00917 if( rc < 0 ) 00918 { 00919 cerr << "failed to add the context name attribute" << endl ; 00920 return "" ; 00921 } 00922 00923 // end the aggregation element 00924 rc = xmlTextWriterEndElement( writer ) ; 00925 if( rc < 0 ) 00926 { 00927 cerr << "failed to close setContext element" << endl ; 00928 return false ; 00929 } 00930 } 00931 00932 // end the define element 00933 rc = xmlTextWriterEndElement( writer ) ; 00934 if( rc < 0 ) 00935 { 00936 cerr << "failed to close setContext element" << endl ; 00937 return false ; 00938 } 00939 00940 return true ; 00941 } 00942 00943 bool 00944 CmdTranslation::translate_delete( BESTokenizer &t, 00945 xmlTextWriterPtr writer ) 00946 { 00947 // delete container <container_name> [from <storage_name>]; 00948 // delete containers [from <storage_name>] 00949 // delete definition <definition_name> [from <storage_name>]; 00950 // delete definitions [from <storage_name>]; 00951 00952 // <deleteContainer name="container_name" space="store_name" /> 00953 // <deleteContainers space="store_name" /> 00954 // <deleteDefinition name="definition_name" space="store_name" /> 00955 // <deleteDefinitions space="store_name" /> 00956 00957 string del_what = t.get_next_token() ; 00958 string new_cmd = "delete." + del_what ; 00959 00960 CmdTranslation::p_cmd_translator p = _translations[new_cmd] ; 00961 if( p ) 00962 { 00963 return p( t, writer ) ; 00964 } 00965 00966 bool single = true ; 00967 if( del_what == "container" || del_what == "definition" ) 00968 { 00969 single = true ; 00970 } 00971 else if( del_what == "containers" || del_what == "definitions" ) 00972 { 00973 single = false ; 00974 } 00975 else 00976 { 00977 t.parse_error( "unknown delete command" ) ; 00978 } 00979 00980 del_what[0] = toupper( del_what[0] ) ; 00981 string tag = "delete" + del_what ; 00982 00983 string name ; 00984 if( single ) 00985 { 00986 name = t.get_next_token() ; 00987 } 00988 00989 string space ; 00990 string token = t.get_next_token() ; 00991 if( token == "from" ) 00992 { 00993 space = t.get_next_token() ; 00994 token = t.get_next_token() ; 00995 } 00996 00997 if( token != ";" ) 00998 { 00999 t.parse_error( "delete command expected to end with semicolon" ) ; 01000 } 01001 01002 // start the delete element 01003 int rc = xmlTextWriterStartElement( writer, BAD_CAST tag.c_str() ) ; 01004 if( rc < 0 ) 01005 { 01006 cerr << "failed to start aggregate element" << endl ; 01007 return false ; 01008 } 01009 01010 if( !name.empty() ) 01011 { 01012 /* Add the container or definition name attribute */ 01013 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "name", 01014 BAD_CAST name.c_str() ) ; 01015 if( rc < 0 ) 01016 { 01017 cerr << "failed to add the context name attribute" << endl ; 01018 return "" ; 01019 } 01020 } 01021 01022 if( !space.empty() ) 01023 { 01024 /* Add the container or definition storage space attribute */ 01025 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "space", 01026 BAD_CAST space.c_str() ) ; 01027 if( rc < 0 ) 01028 { 01029 cerr << "failed to add the context name attribute" << endl ; 01030 return "" ; 01031 } 01032 } 01033 01034 // end the delete element 01035 rc = xmlTextWriterEndElement( writer ) ; 01036 if( rc < 0 ) 01037 { 01038 cerr << "failed to close setContext element" << endl ; 01039 return false ; 01040 } 01041 01042 return true ; 01043 } 01044 01045 bool 01046 CmdTranslation::translate_get( BESTokenizer &t, 01047 xmlTextWriterPtr writer ) 01048 { 01049 // get das|dds|dods|ddx for <definition_name> [return as <return_name>]; 01050 // <get type="das|dds|dods|ddx" definition="def_name" returnAs="returnAs" /> 01051 // get html_form for <definition> using <url>; 01052 // <get type="das|dds|dods|ddx" definition="def_name" url="url" returnAs="returnAs" /> 01053 string get_what = t.get_next_token() ; 01054 string token = t.get_next_token() ; 01055 if( token != "for" ) 01056 { 01057 t.parse_error( "get command expecting keyword \"for\"" ) ; 01058 } 01059 01060 string def_name = t.get_next_token() ; 01061 string returnAs ; 01062 string url ; 01063 string starting ; 01064 string bounding ; 01065 token = t.get_next_token() ; 01066 bool done = false ; 01067 while( !done ) 01068 { 01069 if( token == "return" ) 01070 { 01071 token = t.get_next_token() ; 01072 if( token != "as" ) 01073 { 01074 t.parse_error( "get command expecting keyword \"as\" for return" ) ; 01075 } 01076 returnAs = t.get_next_token() ; 01077 token = t.get_next_token() ; 01078 } 01079 else if( token == "using" ) 01080 { 01081 url = t.get_next_token() ; 01082 token = t.get_next_token() ; 01083 } 01084 else if( token == "contentStartId" ) 01085 { 01086 starting = t.get_next_token() ; 01087 token = t.get_next_token() ; 01088 } 01089 else if( token == "mimeBoundary" ) 01090 { 01091 bounding = t.get_next_token() ; 01092 token = t.get_next_token() ; 01093 } 01094 else if( token == ";" ) 01095 { 01096 done = true ; 01097 } 01098 else 01099 { 01100 t.parse_error( "unexpected token in get command" ) ; 01101 } 01102 } 01103 01104 // start the get element 01105 int rc = xmlTextWriterStartElement( writer, BAD_CAST "get" ) ; 01106 if( rc < 0 ) 01107 { 01108 cerr << "failed to start aggregate element" << endl ; 01109 return false ; 01110 } 01111 01112 /* Add the get type attribute */ 01113 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "type", 01114 BAD_CAST get_what.c_str() ) ; 01115 if( rc < 0 ) 01116 { 01117 cerr << "failed to add the get type attribute" << endl ; 01118 return "" ; 01119 } 01120 01121 /* Add the get definition attribute */ 01122 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "definition", 01123 BAD_CAST def_name.c_str() ) ; 01124 if( rc < 0 ) 01125 { 01126 cerr << "failed to add the get definition attribute" << endl ; 01127 return "" ; 01128 } 01129 01130 if( !url.empty() ) 01131 { 01132 /* Add the get type attribute */ 01133 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "url", 01134 BAD_CAST url.c_str() ) ; 01135 if( rc < 0 ) 01136 { 01137 cerr << "failed to add the url attribute" << endl ; 01138 return "" ; 01139 } 01140 } 01141 01142 if( !returnAs.empty() ) 01143 { 01144 /* Add the get type attribute */ 01145 rc = xmlTextWriterWriteAttribute( writer, BAD_CAST "returnAs", 01146 BAD_CAST returnAs.c_str() ) ; 01147 if( rc < 0 ) 01148 { 01149 cerr << "failed to add the returnAs attribute" << endl ; 01150 return "" ; 01151 } 01152 } 01153 01154 if( !starting.empty() ) 01155 { 01156 // start the constraint element 01157 int rc = xmlTextWriterStartElement( writer, BAD_CAST "contentStartId" ); 01158 if( rc < 0 ) 01159 { 01160 cerr << "failed to start contentStartId element" << endl ; 01161 return false ; 01162 } 01163 01164 /* Write the value of the contentStartId */ 01165 rc = xmlTextWriterWriteString( writer, BAD_CAST starting.c_str()); 01166 if( rc < 0 ) 01167 { 01168 cerr << "failed to write contentStartId for get request" << endl ; 01169 return "" ; 01170 } 01171 01172 // end the contentStartId constraint element 01173 rc = xmlTextWriterEndElement( writer ) ; 01174 if( rc < 0 ) 01175 { 01176 cerr << "failed to close constraint element" << endl ; 01177 return false ; 01178 } 01179 } 01180 01181 if( !bounding.empty() ) 01182 { 01183 // start the mimeBoundary element 01184 int rc = xmlTextWriterStartElement( writer, BAD_CAST "mimeBoundary" ); 01185 if( rc < 0 ) 01186 { 01187 cerr << "failed to start mimeBoundary element" << endl ; 01188 return false ; 01189 } 01190 01191 /* Write the value of the constraint */ 01192 rc = xmlTextWriterWriteString( writer, BAD_CAST bounding.c_str()); 01193 if( rc < 0 ) 01194 { 01195 cerr << "failed to write mimeBoundary for get request" << endl ; 01196 return "" ; 01197 } 01198 01199 // end the mimeBoundary constraint element 01200 rc = xmlTextWriterEndElement( writer ) ; 01201 if( rc < 0 ) 01202 { 01203 cerr << "failed to close mimeBoundary element" << endl ; 01204 return false ; 01205 } 01206 } 01207 01208 // end the get element 01209 rc = xmlTextWriterEndElement( writer ) ; 01210 if( rc < 0 ) 01211 { 01212 cerr << "failed to close get element" << endl ; 01213 return false ; 01214 } 01215 01216 return true ; 01217 } 01218 01219 void 01220 CmdTranslation::dump( ostream &strm ) 01221 { 01222 strm << BESIndent::LMarg << "CmdTranslation::dump" << endl ; 01223 BESIndent::Indent() ; 01224 if( _translations.empty() ) 01225 { 01226 strm << BESIndent::LMarg << "NO translations registered" << endl ; 01227 } 01228 else 01229 { 01230 strm << BESIndent::LMarg << "translations registered" << endl ; 01231 BESIndent::Indent() ; 01232 map<string,p_cmd_translator>::iterator i = _translations.begin() ; 01233 map<string,p_cmd_translator>::iterator e = _translations.end() ; 01234 for( ; i != e; i++ ) 01235 { 01236 strm << BESIndent::LMarg << (*i).first << endl ; 01237 } 01238 BESIndent::UnIndent() ; 01239 } 01240 BESIndent::UnIndent() ; 01241 } 01242