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