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 #include "config.h"
00027
00028
00029
00030
00031 #include <cstring>
00032 #include <cstdarg>
00033
00034 #include "BaseType.h"
00035 #include "Byte.h"
00036 #include "Int16.h"
00037 #include "UInt16.h"
00038 #include "Int32.h"
00039 #include "UInt32.h"
00040 #include "Float32.h"
00041 #include "Float64.h"
00042 #include "Str.h"
00043 #include "Url.h"
00044 #include "Array.h"
00045 #include "Structure.h"
00046 #include "Sequence.h"
00047 #include "Grid.h"
00048
00049 #include "DDXParserSAX2.h"
00050
00051 #include "util.h"
00052 #include "mime_util.h"
00053 #include "debug.h"
00054
00055 namespace libdap {
00056
00057 static const not_used char *states[] =
00058 {
00059 "start",
00060
00061 "dataset",
00062
00063 "attribute_container",
00064 "attribute",
00065 "attribute_value",
00066 "other_xml_attribute",
00067
00068 "alias",
00069
00070 "simple_type",
00071
00072 "array",
00073 "dimension",
00074
00075 "grid",
00076 "map",
00077
00078 "structure",
00079 "sequence",
00080
00081 "blob href",
00082
00083 "unknown",
00084 "error"
00085 };
00086
00087
00088
00089
00090 BaseType *DDXParser::factory(Type t, const string & name)
00091 {
00092 switch (t) {
00093 case dods_byte_c:
00094 return d_factory->NewByte(name);
00095 break;
00096
00097 case dods_int16_c:
00098 return d_factory->NewInt16(name);
00099 break;
00100
00101 case dods_uint16_c:
00102 return d_factory->NewUInt16(name);
00103 break;
00104
00105 case dods_int32_c:
00106 return d_factory->NewInt32(name);
00107 break;
00108
00109 case dods_uint32_c:
00110 return d_factory->NewUInt32(name);
00111 break;
00112
00113 case dods_float32_c:
00114 return d_factory->NewFloat32(name);
00115 break;
00116
00117 case dods_float64_c:
00118 return d_factory->NewFloat64(name);
00119 break;
00120
00121 case dods_str_c:
00122 return d_factory->NewStr(name);
00123 break;
00124
00125 case dods_url_c:
00126 return d_factory->NewUrl(name);
00127 break;
00128
00129 case dods_array_c:
00130 return d_factory->NewArray(name);
00131 break;
00132
00133 case dods_structure_c:
00134 return d_factory->NewStructure(name);
00135 break;
00136
00137 case dods_sequence_c:
00138 return d_factory->NewSequence(name);
00139 break;
00140
00141 case dods_grid_c:
00142 return d_factory->NewGrid(name);
00143 break;
00144
00145 default:
00146 return 0;
00147 }
00148 }
00149
00151 static Type get_type(const char *name)
00152 {
00153 if (strcmp(name, "Byte") == 0)
00154 return dods_byte_c;
00155
00156 if (strcmp(name, "Int16") == 0)
00157 return dods_int16_c;
00158
00159 if (strcmp(name, "UInt16") == 0)
00160 return dods_uint16_c;
00161
00162 if (strcmp(name, "Int32") == 0)
00163 return dods_int32_c;
00164
00165 if (strcmp(name, "UInt32") == 0)
00166 return dods_uint32_c;
00167
00168 if (strcmp(name, "Float32") == 0)
00169 return dods_float32_c;
00170
00171 if (strcmp(name, "Float64") == 0)
00172 return dods_float64_c;
00173
00174 if (strcmp(name, "String") == 0)
00175 return dods_str_c;
00176
00177 if (strcmp(name, "Url") == 0)
00178 return dods_url_c;
00179
00180 if (strcmp(name, "Array") == 0)
00181 return dods_array_c;
00182
00183 if (strcmp(name, "Structure") == 0)
00184 return dods_structure_c;
00185
00186 if (strcmp(name, "Sequence") == 0)
00187 return dods_sequence_c;
00188
00189 if (strcmp(name, "Grid") == 0)
00190 return dods_grid_c;
00191
00192 return dods_null_c;
00193 }
00194
00195 static Type is_simple_type(const char *name)
00196 {
00197 Type t = get_type(name);
00198 switch (t) {
00199 case dods_byte_c:
00200 case dods_int16_c:
00201 case dods_uint16_c:
00202 case dods_int32_c:
00203 case dods_uint32_c:
00204 case dods_float32_c:
00205 case dods_float64_c:
00206 case dods_str_c:
00207 case dods_url_c:
00208 return t;
00209 default:
00210 return dods_null_c;
00211 }
00212 }
00213
00214 static bool is_not(const char *name, const char *tag)
00215 {
00216 return strcmp(name, tag) != 0;
00217 }
00218
00219 void DDXParser::set_state(DDXParser::ParseState state)
00220 {
00221 s.push(state);
00222 }
00223
00224 DDXParser::ParseState DDXParser::get_state() const
00225 {
00226 return s.top();
00227 }
00228
00229 void DDXParser::pop_state()
00230 {
00231 s.pop();
00232 }
00233
00237 void DDXParser::transfer_xml_attrs(const xmlChar **attributes, int nb_attributes)
00238 {
00239 if (!attribute_table.empty())
00240 attribute_table.clear();
00241
00242 unsigned int index = 0;
00243 for (int i = 0; i < nb_attributes; ++i, index += 5) {
00244
00245
00246 attribute_table.insert(map<string, XMLAttribute>::value_type(
00247 string((const char *)attributes[index]),
00248 XMLAttribute(attributes + index + 1)));
00249
00250 DBG(cerr << "Attribute '" << (const char *)attributes[index] << "': "
00251 << attribute_table[(const char *)attributes[index]].value << endl);
00252 }
00253 }
00254
00255 void DDXParser::transfer_xml_ns(const xmlChar **namespaces, int nb_namespaces)
00256 {
00257 for (int i = 0; i < nb_namespaces; ++i ) {
00258
00259
00260 namespace_table.insert(map<string,string>::value_type(
00261 namespaces[i*2] != 0 ? (const char *)namespaces[i*2] : "",
00262 (const char *)namespaces[i*2+1]));
00263 }
00264 }
00265
00270 bool DDXParser::check_required_attribute(const string & attr)
00271 {
00272 map < string, XMLAttribute >::iterator i = attribute_table.find(attr);
00273 if (i == attribute_table.end())
00274 ddx_fatal_error(this, "Required attribute '%s' not found.",
00275 attr.c_str());
00276 return true;
00277 }
00278
00284 bool DDXParser::check_attribute(const string & attr)
00285 {
00286 return (attribute_table.find(attr) != attribute_table.end());
00287 }
00288
00297 void DDXParser::process_attribute_element(const xmlChar **attrs, int nb_attributes)
00298 {
00299
00300 transfer_xml_attrs(attrs, nb_attributes);
00301
00302 bool error = !(check_required_attribute(string("name"))
00303 && check_required_attribute(string("type")));
00304 if (error)
00305 return;
00306
00307 if (attribute_table["type"].value == "Container") {
00308 set_state(inside_attribute_container);
00309
00310 AttrTable *child;
00311 AttrTable *parent = at_stack.top();
00312
00313 child = parent->append_container(attribute_table["name"].value);
00314 at_stack.push(child);
00315 DBG2(cerr << "Pushing at" << endl);
00316 }
00317 else if (attribute_table["type"].value == "OtherXML") {
00318 set_state(inside_other_xml_attribute);
00319
00320 dods_attr_name = attribute_table["name"].value;
00321 dods_attr_type = attribute_table["type"].value;
00322 }
00323 else {
00324 set_state(inside_attribute);
00325
00326
00327
00328 dods_attr_name = attribute_table["name"].value;
00329 dods_attr_type = attribute_table["type"].value;
00330 }
00331 }
00332
00336 void DDXParser::process_attribute_alias(const xmlChar **attrs, int nb_attributes)
00337 {
00338 transfer_xml_attrs(attrs, nb_attributes);
00339 if (check_required_attribute(string("name"))
00340 && check_required_attribute(string("attribute"))) {
00341 set_state(inside_alias);
00342 at_stack.top()->attr_alias(attribute_table["name"].value,
00343 attribute_table["attribute"].value);
00344 }
00345 }
00346
00354 void DDXParser::process_variable(Type t, ParseState s, const xmlChar **attrs,
00355 int nb_attributes)
00356 {
00357 transfer_xml_attrs(attrs, nb_attributes);
00358
00359 set_state(s);
00360 if (bt_stack.top()->type() == dods_array_c
00361 || check_required_attribute("name")) {
00362 BaseType *btp = factory(t, attribute_table["name"].value);
00363 if (!btp)
00364 ddx_fatal_error(
00365 this,
00366 "Internal parser error; could not instantiate the variable '%s'.",
00367 attribute_table["name"].value.c_str());
00368
00369
00370
00371
00372
00373 bt_stack.push(btp);
00374 at_stack.push(&btp->get_attr_table());
00375 }
00376 }
00377
00381 void DDXParser::process_dimension(const xmlChar **attrs, int nb_attributes)
00382 {
00383 transfer_xml_attrs(attrs, nb_attributes);
00384 if (check_required_attribute(string("size"))) {
00385 set_state(inside_dimension);
00386 Array *ap = dynamic_cast < Array * >(bt_stack.top());
00387 if (!ap)
00388 ddx_fatal_error(this, "Parse error: Expected an array variable.");
00389
00390 ap->append_dim(atoi(attribute_table["size"].value.c_str()),
00391 attribute_table["name"].value);
00392 }
00393 }
00394
00397 void DDXParser::process_blob(const xmlChar **attrs, int nb_attributes)
00398 {
00399 transfer_xml_attrs(attrs, nb_attributes);
00400 if (check_required_attribute(string("href"))) {
00401 set_state(inside_blob_href);
00402 *blob_href = attribute_table["href"].value;
00403 }
00404 }
00405
00412 inline bool
00413 DDXParser::is_attribute_or_alias(const char *name, const xmlChar **attrs,
00414 int nb_attributes)
00415 {
00416 if (strcmp(name, "Attribute") == 0) {
00417 process_attribute_element(attrs, nb_attributes);
00418
00419 return true;
00420 }
00421 else if (strcmp(name, "Alias") == 0) {
00422 process_attribute_alias(attrs, nb_attributes);
00423
00424 return true;
00425 }
00426
00427 return false;
00428 }
00429
00435 inline bool DDXParser::is_variable(const char *name, const xmlChar **attrs,
00436 int nb_attributes)
00437 {
00438 Type t;
00439 if ((t = is_simple_type(name)) != dods_null_c) {
00440 process_variable(t, inside_simple_type, attrs, nb_attributes);
00441 return true;
00442 }
00443 else if (strcmp(name, "Array") == 0) {
00444 process_variable(dods_array_c, inside_array, attrs, nb_attributes);
00445 return true;
00446 }
00447 else if (strcmp(name, "Structure") == 0) {
00448 process_variable(dods_structure_c, inside_structure, attrs, nb_attributes);
00449 return true;
00450 }
00451 else if (strcmp(name, "Sequence") == 0) {
00452 process_variable(dods_sequence_c, inside_sequence, attrs, nb_attributes);
00453 return true;
00454 }
00455 else if (strcmp(name, "Grid") == 0) {
00456 process_variable(dods_grid_c, inside_grid, attrs, nb_attributes);
00457 return true;
00458 }
00459
00460 return false;
00461 }
00462
00463 void DDXParser::finish_variable(const char *tag, Type t, const char *expected)
00464 {
00465 if (strcmp(tag, expected) != 0) {
00466 DDXParser::ddx_fatal_error(this,
00467 "Expected an end tag for a %s; found '%s' instead.",
00468 expected, tag);
00469 return;
00470 }
00471
00472 pop_state();
00473
00474 BaseType *btp = bt_stack.top();
00475
00476 bt_stack.pop();
00477 at_stack.pop();
00478
00479 if (btp->type() != t) {
00480 DDXParser::ddx_fatal_error(this,
00481 "Internal error: Expected a %s variable.",
00482 expected);
00483 return;
00484 }
00485
00486 if (t == dods_array_c
00487 && dynamic_cast < Array * >(btp)->dimensions() == 0) {
00488 DDXParser::ddx_fatal_error(this,
00489 "No dimension element included in the Array '%s'.",
00490 btp->name().c_str());
00491 return;
00492 }
00493
00494 BaseType *parent = bt_stack.top();
00495
00496 if (!(parent->is_vector_type() || parent->is_constructor_type())) {
00497 DDXParser::ddx_fatal_error(this,
00498 "Tried to add the array variable '%s' to a non-constructor type (%s %s).",
00499 tag,
00500 bt_stack.top()->type_name().c_str(),
00501 bt_stack.top()->name().c_str());
00502 return;
00503 }
00504
00505 parent->add_var(btp);
00506 }
00507
00514
00519 void DDXParser::ddx_start_document(void * p)
00520 {
00521 DDXParser *parser = static_cast<DDXParser*>(p);
00522 parser->error_msg = "";
00523 parser->char_data = "";
00524
00525
00526 parser->at_stack.push(&parser->dds->get_attr_table());
00527
00528
00529
00530
00531 parser->bt_stack.push(new Structure("dummy_dds"));
00532
00533 parser->set_state(parser_start);
00534
00535 DBG2(cerr << "Parser state: " << states[parser->get_state()] << endl);
00536 }
00537
00540 void DDXParser::ddx_end_document(void * p)
00541 {
00542 DDXParser *parser = static_cast<DDXParser*>(p);
00543 DBG2(cerr << "Ending state == " << states[parser->get_state()] <<
00544 endl);
00545
00546 if (parser->get_state() != parser_start)
00547 DDXParser::ddx_fatal_error(parser,
00548 "The document contained unbalanced tags.");
00549
00550
00551
00552 if (parser->get_state() == parser_error)
00553 return;
00554
00555
00556
00557 Constructor *cp = dynamic_cast < Constructor * >(parser->bt_stack.top());
00558 if (!cp)
00559 ddx_fatal_error(parser, "Parse error: Expected a Structure, Sequence or Grid variable.");
00560
00561 for (Constructor::Vars_iter i = cp->var_begin(); i != cp->var_end();
00562 ++i)
00563 parser->dds->add_var(*i);
00564
00565 parser->bt_stack.pop();
00566 delete cp;
00567 }
00568
00569 void DDXParser::ddx_sax2_start_element(void *p,
00570 const xmlChar *l, const xmlChar *prefix, const xmlChar *URI,
00571 int nb_namespaces, const xmlChar **namespaces,
00572 int nb_attributes, int , const xmlChar **attributes)
00573 {
00574 DDXParser *parser = static_cast<DDXParser*>(p);
00575 const char *localname = (const char *)l;
00576
00577 DBG2(cerr << "start element: " << localname << ", states: "
00578 << states[parser->get_state()]);
00579
00580 switch (parser->get_state()) {
00581 case parser_start:
00582 if (strcmp(localname, "Dataset") == 0) {
00583 parser->set_state(inside_dataset);
00584 parser->root_ns = URI != 0 ? (const char *)URI: "";
00585 parser->transfer_xml_attrs(attributes, nb_attributes);
00586
00587 if (parser->check_required_attribute(string("name")))
00588 parser->dds->set_dataset_name(parser->attribute_table["name"].value);
00589
00590 if (parser->check_attribute("dapVersion"))
00591 parser->dds->set_dap_version(parser->attribute_table["dapVersion"].value);
00592 }
00593 else
00594 DDXParser::ddx_fatal_error(parser,
00595 "Expected response to start with a Dataset element; found '%s' instead.",
00596 localname);
00597 break;
00598
00599 case inside_dataset:
00600 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00601 break;
00602 else if (parser->is_variable(localname, attributes, nb_attributes))
00603 break;
00604 else if (strcmp(localname, "blob") == 0 || strcmp(localname, "dataBLOB") == 0) {
00605 parser->process_blob(attributes, nb_attributes);
00606
00607 }
00608 else
00609 DDXParser::ddx_fatal_error(parser,
00610 "Expected an Attribute, Alias or variable element; found '%s' instead.",
00611 localname);
00612 break;
00613
00614 case inside_attribute_container:
00615 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00616 break;
00617 else
00618 DDXParser::ddx_fatal_error(parser,
00619 "Expected an Attribute or Alias element; found '%s' instead.",
00620 localname);
00621 break;
00622
00623 case inside_attribute:
00624 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00625 break;
00626 else if (strcmp(localname, "value") == 0)
00627 parser->set_state(inside_attribute_value);
00628 else
00629 ddx_fatal_error(parser,
00630 "Expected an 'Attribute', 'Alias' or 'value' element; found '%s' instead.",
00631 localname);
00632 break;
00633
00634 case inside_attribute_value:
00635 ddx_fatal_error(parser,
00636 "Internal parser error; unexpected state, inside value while processing element '%s'.",
00637 localname);
00638 break;
00639
00640 case inside_other_xml_attribute:
00641 DBGN(cerr << endl << "\t inside_other_xml_attribute: " << localname << endl);
00642
00643 parser->other_xml_depth++;
00644
00645
00646
00647 parser->other_xml.append("<");
00648 if (prefix) {
00649 parser->other_xml.append((const char *)prefix);
00650 parser->other_xml.append(":");
00651 }
00652 parser->other_xml.append(localname);
00653
00654 if (nb_namespaces != 0) {
00655 parser->transfer_xml_ns(namespaces, nb_namespaces);
00656
00657 for (map<string,string>::iterator i = parser->namespace_table.begin();
00658 i != parser->namespace_table.end();
00659 ++i) {
00660 parser->other_xml.append(" xmlns");
00661 if (!i->first.empty()) {
00662 parser->other_xml.append(":");
00663 parser->other_xml.append(i->first);
00664 }
00665 parser->other_xml.append("=\"");
00666 parser->other_xml.append(i->second);
00667 parser->other_xml.append("\"");
00668 }
00669 }
00670
00671 if (nb_attributes != 0) {
00672 parser->transfer_xml_attrs(attributes, nb_attributes);
00673 for (XMLAttrMap::iterator i = parser->attr_table_begin();
00674 i != parser->attr_table_end();
00675 ++i) {
00676 parser->other_xml.append(" ");
00677 if (!i->second.prefix.empty()) {
00678 parser->other_xml.append(i->second.prefix);
00679 parser->other_xml.append(":");
00680 }
00681 parser->other_xml.append(i->first);
00682 parser->other_xml.append("=\"");
00683 parser->other_xml.append(i->second.value);
00684 parser->other_xml.append("\"");
00685 }
00686 }
00687
00688 parser->other_xml.append(">");
00689 break;
00690
00691 case inside_alias:
00692 ddx_fatal_error(parser,
00693 "Internal parser error; unexpected state, inside alias while processing element '%s'.",
00694 localname);
00695 break;
00696
00697 case inside_simple_type:
00698 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00699 break;
00700 else
00701 ddx_fatal_error(parser,
00702 "Expected an 'Attribute' or 'Alias' element; found '%s' instead.",
00703 localname);
00704 break;
00705
00706 case inside_array:
00707 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00708 break;
00709 else if (is_not(localname, "Array")
00710 && parser->is_variable(localname, attributes, nb_attributes))
00711 break;
00712 else if (strcmp(localname, "dimension") == 0) {
00713 parser->process_dimension(attributes, nb_attributes);
00714
00715 }
00716 else
00717 ddx_fatal_error(parser,
00718 "Expected an 'Attribute' or 'Alias' element; found '%s' instead.",
00719 localname);
00720 break;
00721
00722 case inside_dimension:
00723 ddx_fatal_error(parser,
00724 "Internal parser error; unexpected state, inside dimension while processing element '%s'.",
00725 localname);
00726 break;
00727
00728 case inside_structure:
00729 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00730 break;
00731 else if (parser->is_variable(localname, attributes, nb_attributes))
00732 break;
00733 else
00734 DDXParser::ddx_fatal_error(parser,
00735 "Expected an Attribute, Alias or variable element; found '%s' instead.",
00736 localname);
00737 break;
00738
00739 case inside_sequence:
00740 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00741 break;
00742 else if (parser->is_variable(localname, attributes, nb_attributes))
00743 break;
00744 else
00745 DDXParser::ddx_fatal_error(parser,
00746 "Expected an Attribute, Alias or variable element; found '%s' instead.",
00747 localname);
00748 break;
00749
00750 case inside_grid:
00751 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00752 break;
00753 else if (strcmp(localname, "Array") == 0)
00754 parser->process_variable(dods_array_c, inside_array, attributes, nb_attributes);
00755 else if (strcmp(localname, "Map") == 0)
00756 parser->process_variable(dods_array_c, inside_map, attributes, nb_attributes);
00757 else
00758 DDXParser::ddx_fatal_error(parser,
00759 "Expected an Attribute, Alias or variable element; found '%s' instead.",
00760 localname);
00761 break;
00762
00763 case inside_map:
00764 if (parser->is_attribute_or_alias(localname, attributes, nb_attributes))
00765 break;
00766 else if (is_not(localname, "Array") && is_not(localname, "Sequence")
00767 && is_not(localname, "Grid")
00768 && parser->is_variable(localname, attributes, nb_attributes))
00769 break;
00770 else if (strcmp(localname, "dimension") == 0) {
00771 parser->process_dimension(attributes, nb_attributes);
00772
00773 }
00774 else
00775 ddx_fatal_error(parser,
00776 "Expected an 'Attribute', 'Alias', variable or 'dimension' element; found '%s' instead.",
00777 localname);
00778 break;
00779
00780 case inside_blob_href:
00781 ddx_fatal_error(parser,
00782 "Internal parser error; unexpected state, inside blob href while processing element '%s'.",
00783 localname);
00784 break;
00785
00786 case parser_unknown:
00787
00788 parser->set_state(parser_unknown);
00789 break;
00790
00791 case parser_error:
00792 break;
00793 }
00794
00795 DBGN(cerr << " ... " << states[parser->get_state()] << endl);
00796 }
00797
00798 void DDXParser::ddx_sax2_end_element(void *p, const xmlChar *l,
00799 const xmlChar *prefix, const xmlChar *URI)
00800 {
00801 DDXParser *parser = static_cast<DDXParser*>(p);
00802 const char *localname = (const char *)l;
00803
00804 DBG2(cerr << "End element " << localname << " (state "
00805 << states[parser->get_state()] << ")" << endl);
00806
00807 switch (parser->get_state()) {
00808 case parser_start:
00809 ddx_fatal_error(parser,
00810 "Internal parser error; unexpected state, inside start state while processing element '%s'.",
00811 localname);
00812 break;
00813
00814 case inside_dataset:
00815 if (strcmp(localname, "Dataset") == 0)
00816 parser->pop_state();
00817 else
00818 DDXParser::ddx_fatal_error(parser,
00819 "Expected an end Dataset tag; found '%s' instead.",
00820 localname);
00821 break;
00822
00823 case inside_attribute_container:
00824 if (strcmp(localname, "Attribute") == 0) {
00825 parser->pop_state();
00826 parser->at_stack.pop();
00827 }
00828 else
00829 DDXParser::ddx_fatal_error(parser,
00830 "Expected an end Attribute tag; found '%s' instead.",
00831 localname);
00832 break;
00833
00834 case inside_attribute:
00835 if (strcmp(localname, "Attribute") == 0)
00836 parser->pop_state();
00837 else
00838 DDXParser::ddx_fatal_error(parser,
00839 "Expected an end Attribute tag; found '%s' instead.",
00840 localname);
00841 break;
00842
00843 case inside_attribute_value:
00844 if (strcmp(localname, "value") == 0) {
00845 parser->pop_state();
00846 AttrTable *atp = parser->at_stack.top();
00847 atp->append_attr(parser->dods_attr_name,
00848 parser->dods_attr_type, parser->char_data);
00849 parser->char_data = "";
00850 }
00851 else
00852 DDXParser::ddx_fatal_error(parser,
00853 "Expected an end value tag; found '%s' instead.",
00854 localname);
00855
00856 break;
00857
00858 case inside_other_xml_attribute: {
00859 if (strcmp(localname, "Attribute") == 0
00860 && parser->root_ns == (const char *)URI) {
00861
00862 DBGN(cerr << endl << "\t Popping the 'inside_other_xml_attribute' state"
00863 << endl);
00864
00865 parser->pop_state();
00866
00867 AttrTable *atp = parser->at_stack.top();
00868 atp->append_attr(parser->dods_attr_name,
00869 parser->dods_attr_type, parser->other_xml);
00870
00871 parser->other_xml = "";
00872 }
00873 else {
00874 DBGN(cerr << endl << "\t inside_other_xml_attribute: " << localname
00875 << ", depth: " << parser->other_xml_depth << endl);
00876 if (parser->other_xml_depth == 0)
00877 DDXParser::ddx_fatal_error(parser,
00878 "Expected an OtherXML attribute to end! Instead I found '%s'",
00879 localname);
00880 parser->other_xml_depth--;
00881
00882 parser->other_xml.append("</");
00883 if (prefix) {
00884 parser->other_xml.append((const char *)prefix);
00885 parser->other_xml.append(":");
00886 }
00887 parser->other_xml.append(localname);
00888 parser->other_xml.append(">");
00889 }
00890 break;
00891 }
00892
00893 case inside_alias:
00894 parser->pop_state();
00895 break;
00896
00897 case inside_simple_type:
00898 if (is_simple_type(localname) != dods_null_c) {
00899 parser->pop_state();
00900 BaseType *btp = parser->bt_stack.top();
00901 parser->bt_stack.pop();
00902 parser->at_stack.pop();
00903
00904 BaseType *parent = parser->bt_stack.top();
00905
00906 if (parent->is_vector_type() || parent->is_constructor_type())
00907 parent->add_var(btp);
00908 else
00909 DDXParser::ddx_fatal_error(parser,
00910 "Tried to add the simple-type variable '%s' to a non-constructor type (%s %s).",
00911 localname,
00912 parser->bt_stack.top()->
00913 type_name().c_str(),
00914 parser->bt_stack.top()->name().
00915 c_str());
00916 }
00917 else
00918 DDXParser::ddx_fatal_error(parser,
00919 "Expected an end tag for a simple type; found '%s' instead.",
00920 localname);
00921 break;
00922
00923 case inside_array:
00924 parser->finish_variable(localname, dods_array_c, "Array");
00925 break;
00926
00927 case inside_dimension:
00928 if (strcmp(localname, "dimension") == 0)
00929 parser->pop_state();
00930 else
00931 DDXParser::ddx_fatal_error(parser,
00932 "Expected an end dimension tag; found '%s' instead.",
00933 localname);
00934 break;
00935
00936 case inside_structure:
00937 parser->finish_variable(localname, dods_structure_c, "Structure");
00938 break;
00939
00940 case inside_sequence:
00941 parser->finish_variable(localname, dods_sequence_c, "Sequence");
00942 break;
00943
00944 case inside_grid:
00945 parser->finish_variable(localname, dods_grid_c, "Grid");
00946 break;
00947
00948 case inside_map:
00949 parser->finish_variable(localname, dods_array_c, "Map");
00950 break;
00951
00952 case inside_blob_href:
00953 if (strcmp(localname, "blob") == 0 || strcmp(localname, "dataBLOB") == 0)
00954 parser->pop_state();
00955 else
00956 DDXParser::ddx_fatal_error(parser,
00957 "Expected an end dataBLOB/blob tag; found '%s' instead.",
00958 localname);
00959 break;
00960
00961 case parser_unknown:
00962 parser->pop_state();
00963 break;
00964
00965 case parser_error:
00966 break;
00967 }
00968
00969
00970 DBGN(cerr << " ... " << states[parser->get_state()] << endl);
00971 }
00972
00976 void DDXParser::ddx_get_characters(void * p, const xmlChar * ch, int len)
00977 {
00978 DDXParser *parser = static_cast<DDXParser*>(p);
00979
00980 switch (parser->get_state()) {
00981 case inside_attribute_value:
00982 parser->char_data.append((const char *)(ch), len);
00983 DBG2(cerr << "Characters: '" << parser->char_data << "'" << endl);
00984 break;
00985
00986 case inside_other_xml_attribute:
00987 parser->other_xml.append((const char *)(ch), len);
00988 DBG2(cerr << "Other XML Characters: '" << parser->other_xml << "'" << endl);
00989 break;
00990
00991 default:
00992 break;
00993 }
00994 }
00995
01000 void DDXParser::ddx_ignoreable_whitespace(void *p, const xmlChar *ch,
01001 int len)
01002 {
01003 DDXParser *parser = static_cast<DDXParser*>(p);
01004
01005 switch (parser->get_state()) {
01006 case inside_other_xml_attribute:
01007 parser->other_xml.append((const char *)(ch), len);
01008 break;
01009
01010 default:
01011 break;
01012 }
01013 }
01014
01020 void DDXParser::ddx_get_cdata(void *p, const xmlChar *value, int len)
01021 {
01022 DDXParser *parser = static_cast<DDXParser*>(p);
01023
01024 switch (parser->get_state()) {
01025 case inside_other_xml_attribute:
01026 parser->other_xml.append((const char *)(value), len);
01027 break;
01028
01029 case parser_unknown:
01030 break;
01031
01032 default:
01033 DDXParser::ddx_fatal_error(parser,
01034 "Found a CData block but none are allowed by DAP.");
01035
01036 break;
01037 }
01038 }
01039
01044 xmlEntityPtr DDXParser::ddx_get_entity(void *, const xmlChar * name)
01045 {
01046 return xmlGetPredefinedEntity(name);
01047 }
01048
01056 void DDXParser::ddx_fatal_error(void * p, const char *msg, ...)
01057 {
01058 va_list args;
01059 DDXParser *parser = static_cast<DDXParser*>(p);
01060
01061 parser->set_state(parser_error);
01062
01063 va_start(args, msg);
01064 char str[1024];
01065 vsnprintf(str, 1024, msg, args);
01066 va_end(args);
01067
01068 int line = xmlSAX2GetLineNumber(parser->ctxt);
01069
01070 parser->error_msg += "At line " + long_to_string(line) + ": ";
01071 parser->error_msg += string(str) + string("\n");
01072 }
01073
01075
01076 void DDXParser::cleanup_parse(xmlParserCtxtPtr & context) const
01077 {
01078 if (!context->wellFormed) {
01079 context->sax = NULL;
01080 xmlFreeParserCtxt(context);
01081 throw
01082 DDXParseFailed(string
01083 ("\nThe DDX is not a well formed XML document.\n")
01084 + error_msg);
01085 }
01086
01087 if (!context->valid) {
01088 context->sax = NULL;
01089 xmlFreeParserCtxt(context);
01090 throw DDXParseFailed(string("\nThe DDX is not a valid document.\n")
01091 + error_msg);
01092 }
01093
01094 if (get_state() == parser_error) {
01095 context->sax = NULL;
01096 xmlFreeParserCtxt(context);
01097 throw DDXParseFailed(string("\nError parsing DDX response.\n") +
01098 error_msg);
01099 }
01100
01101 context->sax = NULL;
01102 xmlFreeParserCtxt(context);
01103 }
01104
01107 void DDXParser::intern_stream(FILE *in, DDS *dest_dds, string &cid,
01108 const string &boundary)
01109 {
01110
01111
01112 if (!in || feof(in) || ferror(in))
01113 throw InternalErr(__FILE__, __LINE__,
01114 "Input stream not open or read error");
01115
01116 const int size = 1024;
01117 char chars[size];
01118
01119 int res = fread(chars, 1, 4, in);
01120 if (res > 0) {
01121 xmlParserCtxtPtr context =
01122 xmlCreatePushParserCtxt(NULL, NULL, chars, res, "stream");
01123
01124 ctxt = context;
01125 dds = dest_dds;
01126 blob_href = &cid;
01127
01128 xmlSAXHandler ddx_sax_parser;
01129 memset( &ddx_sax_parser, 0, sizeof(xmlSAXHandler) );
01130
01131 ddx_sax_parser.getEntity = &DDXParser::ddx_get_entity;
01132 ddx_sax_parser.startDocument = &DDXParser::ddx_start_document;
01133 ddx_sax_parser.endDocument = &DDXParser::ddx_end_document;
01134 ddx_sax_parser.characters = &DDXParser::ddx_get_characters;
01135 ddx_sax_parser.ignorableWhitespace = &DDXParser::ddx_ignoreable_whitespace;
01136 ddx_sax_parser.cdataBlock = &DDXParser::ddx_get_cdata;
01137 ddx_sax_parser.warning = &DDXParser::ddx_fatal_error;
01138 ddx_sax_parser.error = &DDXParser::ddx_fatal_error;
01139 ddx_sax_parser.fatalError = &DDXParser::ddx_fatal_error;
01140 ddx_sax_parser.initialized = XML_SAX2_MAGIC;
01141 ddx_sax_parser.startElementNs = &DDXParser::ddx_sax2_start_element;
01142 ddx_sax_parser.endElementNs = &DDXParser::ddx_sax2_end_element;
01143
01144 context->sax = &ddx_sax_parser;
01145 context->userData = this;
01146 context->validate = true;
01147
01148 while ((fgets(chars, size, in) > 0) && !is_boundary(chars, boundary)) {
01149 DBG(cerr << "line: " << chars << endl);
01150 xmlParseChunk(ctxt, chars, strlen(chars), 0);
01151 }
01152
01153
01154 xmlParseChunk(ctxt, chars, 0, 1);
01155
01156 cleanup_parse(context);
01157 }
01158 }
01159
01160
01172 void DDXParser::intern(const string & document, DDS * dest_dds, string &cid)
01173 {
01174
01175
01176
01177
01178
01179
01180
01181 xmlParserCtxtPtr context = xmlCreateFileParserCtxt(document.c_str());
01182 if (!context)
01183 throw
01184 DDXParseFailed(string
01185 ("Could not initialize the parser with the file: '")
01186 + document + string("'."));
01187
01188 dds = dest_dds;
01189 blob_href = &cid;
01190 ctxt = context;
01191
01192 xmlSAXHandler ddx_sax_parser;
01193 memset( &ddx_sax_parser, 0, sizeof(xmlSAXHandler) );
01194
01195 ddx_sax_parser.getEntity = &DDXParser::ddx_get_entity;
01196 ddx_sax_parser.startDocument = &DDXParser::ddx_start_document;
01197 ddx_sax_parser.endDocument = &DDXParser::ddx_end_document;
01198 ddx_sax_parser.characters = &DDXParser::ddx_get_characters;
01199 ddx_sax_parser.ignorableWhitespace = &DDXParser::ddx_ignoreable_whitespace;
01200 ddx_sax_parser.cdataBlock = &DDXParser::ddx_get_cdata;
01201 ddx_sax_parser.warning = &DDXParser::ddx_fatal_error;
01202 ddx_sax_parser.error = &DDXParser::ddx_fatal_error;
01203 ddx_sax_parser.fatalError = &DDXParser::ddx_fatal_error;
01204 ddx_sax_parser.initialized = XML_SAX2_MAGIC;
01205 ddx_sax_parser.startElementNs = &DDXParser::ddx_sax2_start_element;
01206 ddx_sax_parser.endElementNs = &DDXParser::ddx_sax2_end_element;
01207
01208 context->sax = &ddx_sax_parser;
01209 context->userData = this;
01210 context->validate = false;
01211
01212 xmlParseDocument(context);
01213
01214 cleanup_parse(context);
01215 }
01216
01217 }