38#define FILE_UN_MARSHALLER 1
51#include "DDXParserSAX2.h"
53#include "XDRFileUnMarshaller.h"
55#include "XDRStreamUnMarshaller.h"
56#include "fdiostream.h"
71 DBG(cerr <<
"Entering Connect::process_data" << endl);
73 data.set_version(rs->get_version());
74 data.set_protocol(rs->get_protocol());
76 DBG(cerr <<
"Entering process_data: d_stream = " << rs << endl);
77 switch (rs->get_type()) {
80 if (!e.parse(rs->get_stream()))
81 throw InternalErr(__FILE__, __LINE__,
"Could not parse the Error object returned by the server!");
90 "An error was reported by the remote httpd; this should have been processed by HTTPConnect..");
97 DDXParser ddx_parser(data.get_factory());
101 DBG(cerr <<
"MPM Boundary: " << boundary << endl);
107 ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
111 DBG(cerr <<
"Data CID: " << data_cid << endl);
118#if FILE_UN_MARSHALLER
119 XDRFileUnMarshaller um(rs->get_stream());
121 fpistream in ( rs->get_stream() );
122 XDRStreamUnMarshaller um( in );
124 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
125 (*i)->deserialize(um, &data);
134 data.parse(rs->get_stream());
135#if FILE_UN_MARSHALLER
136 XDRFileUnMarshaller um(rs->get_stream());
138 fpistream in(rs->get_stream());
139 XDRStreamUnMarshaller um(in);
142 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
143 (*i)->deserialize(um, &data);
152void Connect::process_data(
DDS &data,
Response *rs) {
153 DBG(cerr <<
"Entering Connect::process_data" << endl);
155 data.set_dap_version(rs->get_protocol());
157 DBG(cerr <<
"Entering process_data: d_stream = " << rs << endl);
158 switch (rs->get_type()) {
161 if (!e.parse(rs->get_stream()))
162 throw InternalErr(__FILE__, __LINE__,
"Could not parse the Error object returned by the server!");
171 "An error was reported by the remote web server; this should have been processed by HTTPConnect.");
177 case dods_data_ddx: {
179 DDXParser ddx_parser(data.get_factory());
183 DBG(cerr <<
"MPM Boundary: " << boundary << endl);
189 ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
193 DBG(cerr <<
"Data CID: " << data_cid << endl);
200 XDRFileUnMarshaller um(rs->get_stream());
201 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
202 (*i)->deserialize(um, &data);
211 data.parse(rs->get_stream());
213 XDRFileUnMarshaller um(rs->get_stream());
216 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
217 (*i)->deserialize(um, &data);
249void Connect::parse_mime(
Response *rs) {
250 rs->set_version(
"dods/0.0");
251 rs->set_protocol(
"2.0");
253 FILE *data_source = rs->get_stream();
255 while (!mime.empty()) {
256 string header, value;
260 if (header ==
"content-description:") {
261 DBG(cout << header <<
": " << value << endl);
265 else if (header ==
"xdods-server:" && rs->get_version() ==
"dods/0.0") {
266 DBG(cout << header <<
": " << value << endl);
267 rs->set_version(value);
270 else if (header ==
"xopendap-server:") {
271 DBG(cout << header <<
": " << value << endl);
272 rs->set_version(value);
273 }
else if (header ==
"xdap:") {
274 DBG(cout << header <<
": " << value << endl);
275 rs->set_protocol(value);
278 else if (rs->get_version() ==
"dods/0.0" && header ==
"server:") {
279 DBG(cout << header <<
": " << value << endl);
280 rs->set_version(value);
296Connect::Connect(
const string &n,
string uname,
string password) : d_http(0), d_version(
"unknown"), d_protocol(
"2.0") {
301 if (name.find(
"http") == 0) {
302 DBG(cerr <<
"Connect: The identifier is an http URL" << endl);
306 string::size_type dotpos = name.find(
'?');
307 if (dotpos != name.npos) {
308 _URL = name.substr(0, dotpos);
309 string expr = name.substr(dotpos + 1);
311 dotpos = expr.find(
'&');
312 if (dotpos != expr.npos) {
313 _proj = expr.substr(0, dotpos);
314 _sel = expr.substr(dotpos);
327 DBG(cerr <<
"Connect: The identifier is a local data source." << endl);
338 DBG2(cerr <<
"Entering the Connect dtor" << endl);
344 DBG2(cerr <<
"Leaving the Connect dtor" << endl);
355 string version_url = _URL +
".ver";
356 if (_proj.length() + _sel.length())
357 version_url = version_url +
"?" +
id2www_ce(_proj + _sel);
361 rs = d_http->fetch_url(version_url);
368 d_version = rs->get_version();
369 d_protocol = rs->get_protocol();
389 string version_url = _URL +
".ver";
390 if (_proj.length() + _sel.length())
391 version_url = version_url +
"?" +
id2www_ce(_proj + _sel);
395 rs = d_http->fetch_url(version_url);
402 d_version = rs->get_version();
403 d_protocol = rs->get_protocol();
419 string das_url = _URL +
".das";
420 if (_proj.length() + _sel.length())
421 das_url = das_url +
"?" +
id2www_ce(_proj + _sel);
425 rs = d_http->fetch_url(das_url);
432 d_version = rs->get_version();
433 d_protocol = rs->get_protocol();
435 switch (rs->get_type()) {
438 if (!e.
parse(rs->get_stream())) {
441 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
457 das.
parse(rs->get_stream());
482 string use_url = _URL +
"?" + _proj + _sel;
485 rs = d_http->fetch_url(use_url);
492 d_version = rs->get_version();
493 d_protocol = rs->get_protocol();
495 switch (rs->get_type()) {
498 if (!e.
parse(rs->get_stream())) {
501 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
517 das.
parse(rs->get_stream());
546 string::size_type dotpos = expr.find(
'&');
547 if (dotpos != expr.npos) {
548 proj = expr.substr(0, dotpos);
549 sel = expr.substr(dotpos);
555 string dds_url = _URL +
".dds" +
"?" +
id2www_ce(_proj + proj + _sel + sel);
559 rs = d_http->fetch_url(dds_url);
566 d_version = rs->get_version();
567 d_protocol = rs->get_protocol();
569 switch (rs->get_type()) {
572 if (!e.
parse(rs->get_stream())) {
575 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
591 dds.
parse(rs->get_stream());
621 string use_url = _URL +
"?" + _proj + _sel;
624 rs = d_http->fetch_url(use_url);
631 d_version = rs->get_version();
632 d_protocol = rs->get_protocol();
634 switch (rs->get_type()) {
637 if (!e.
parse(rs->get_stream())) {
640 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
656 dds.
parse(rs->get_stream());
682 string::size_type dotpos = expr.find(
'&');
683 if (dotpos != expr.npos) {
684 proj = expr.substr(0, dotpos);
685 sel = expr.substr(dotpos);
691 string ddx_url = _URL +
".ddx" +
"?" +
id2www_ce(_proj + proj + _sel + sel);
695 rs = d_http->fetch_url(ddx_url);
701 d_version = rs->get_version();
702 d_protocol = rs->get_protocol();
704 switch (rs->get_type()) {
707 if (!e.
parse(rs->get_stream())) {
710 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
736 throw Error(
"Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
745 string use_url = _URL +
"?" + _proj + _sel;
749 rs = d_http->fetch_url(use_url);
755 d_version = rs->get_version();
756 d_protocol = rs->get_protocol();
758 switch (rs->get_type()) {
761 if (!e.
parse(rs->get_stream())) {
763 throw InternalErr(__FILE__, __LINE__,
"Could not parse error returned from server.");
773 throw InternalErr(__FILE__, __LINE__,
"Web error.");
791 throw Error(
"Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
815 string::size_type dotpos = expr.find(
'&');
816 if (dotpos != expr.npos) {
817 proj = expr.substr(0, dotpos);
818 sel = expr.substr(dotpos);
824 string data_url = _URL +
".dods?" +
id2www_ce(_proj + proj + _sel + sel);
829 rs = d_http->fetch_url(data_url);
831 d_version = rs->get_version();
832 d_protocol = rs->get_protocol();
834 process_data(data, rs);
862 string use_url = _URL +
"?" + _proj + _sel;
866 rs = d_http->fetch_url(use_url);
868 d_version = rs->get_version();
869 d_protocol = rs->get_protocol();
871 process_data(data, rs);
882void Connect::request_data_ddx(
DataDDS &data,
string expr) {
884 string::size_type dotpos = expr.find(
'&');
885 if (dotpos != expr.npos) {
886 proj = expr.substr(0, dotpos);
887 sel = expr.substr(dotpos);
893 string data_url = _URL +
".dap?" +
id2www_ce(_proj + proj + _sel + sel);
898 rs = d_http->fetch_url(data_url);
900 d_version = rs->get_version();
901 d_protocol = rs->get_protocol();
903 process_data(data, rs);
914void Connect::request_data_ddx_url(
DataDDS &data) {
915 string use_url = _URL +
"?" + _proj + _sel;
919 rs = d_http->fetch_url(use_url);
921 d_version = rs->get_version();
922 d_protocol = rs->get_protocol();
924 process_data(data, rs);
949 throw InternalErr(__FILE__, __LINE__,
"Response object is null.");
958 throw InternalErr(__FILE__, __LINE__,
"Response object is null.");
971static void divine_type_information(Response *rs) {
973 int c = getc(rs->get_stream());
974 while (!feof(rs->get_stream()) && !ferror(rs->get_stream()) && isspace(c)) {
975 c = getc(rs->get_stream());
978 if (ferror(rs->get_stream()))
979 throw Error(
"Error reading response type information: " +
string(strerror(errno)));
980 if (feof(rs->get_stream()))
981 throw Error(
"Error reading response type information: Found EOF");
990 rs->set_type(dods_data_ddx);
994 rs->set_type(dods_data);
997 throw InternalErr(__FILE__, __LINE__,
"Could not determine type of response object in stream.");
1000 ungetc(c, rs->get_stream());
1016 if (rs->get_type() == unknown_type)
1017 divine_type_information(rs);
1019 switch (rs->get_type()) {
1021 d_version = rs->get_version();
1022 d_protocol = rs->get_protocol();
1023 process_data(data, rs);
1026 process_data(data, rs);
1027 d_version = rs->get_version();
1028 d_protocol = data.get_protocol();
1031 throw InternalErr(__FILE__, __LINE__,
"Should have been a DataDDS or DataDDX.");
1035 if (rs->get_type() == unknown_type)
1036 divine_type_information(rs);
1038 switch (rs->get_type()) {
1040 d_version = rs->get_version();
1041 d_protocol = rs->get_protocol();
1042 process_data(data, rs);
1045 process_data(data, rs);
1046 d_version = rs->get_version();
1049 d_protocol = data.get_dap_version();
1052 throw InternalErr(__FILE__, __LINE__,
"Should have been a DataDDS or DataDDX.");
1056bool Connect::is_local() {
return _local; }
1076 throw InternalErr(__FILE__, __LINE__,
"URL(): This call is only valid for a DAP data source.");
1079 return _URL +
"?" + _proj + _sel;
1094 throw InternalErr(__FILE__, __LINE__,
"CE(): This call is only valid for a DAP data source.");
1096 return _proj + _sel;
1106 d_http->set_credentials(u, p);
1114 d_http->set_accept_deflate(deflate);
1124 d_http->set_xdap_protocol(major, minor);
1132 d_http->set_cache_enabled(cache);
1135bool Connect::is_cache_enabled() {
1137 DBG(cerr <<
"Entering is_cache_enabled (" << hex << d_http << dec <<
")... ");
1142 DBGN(cerr <<
"exiting" << endl);
virtual void request_dds_url(DDS &dds)
Get the DDS from a server.
virtual string CE()
Get the Connect's constraint expression.
void set_accept_deflate(bool deflate)
void set_cache_enabled(bool enabled)
virtual void request_ddx(DDS &dds, string expr="")
Get the DDX from a server.
virtual void read_data_no_mime(DataDDS &data, Response *rs)
Read data from a file which does not have response MIME headers. This method is a companion to read_d...
void set_xdap_protocol(int major, int minor)
virtual string URL(bool CE=true)
Get the object's URL.
virtual void request_data(DataDDS &data, string expr="")
Get the DAS from a server.
virtual void request_das(DAS &das)
Get the DAS from a server.
void set_credentials(string u, string p)
Set the credentials for responding to challenges while dereferencing URLs.
virtual void request_ddx_url(DDS &dds)
The 'url' version of request_ddx.
virtual string request_protocol()
virtual void request_dds(DDS &dds, string expr="")
Get the DDS from a server.
virtual void request_das_url(DAS &das)
Get the DAS from a server.
virtual string request_version()
virtual void request_data_url(DataDDS &data)
Get the DAS from a server.
virtual void read_data(DataDDS &data, Response *rs)
Read data which is preceded by MIME headers. This method works for both data dds and data ddx respons...
Hold attribute data for a DAP2 dataset.
virtual void parse(string fname)
Reads a DAS from the named file.
void parse(string fname)
Parse a DDS from a file with the given d_name.
BaseTypeFactory * get_factory() const
void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary="")
Read the DDX from a stream instead of a file.
A class for error processing.
bool parse(FILE *fp)
Parse an Error object.
A class for software fault reporting.
top level DAP object to house generic methods
string read_multipart_boundary(FILE *in, const string &boundary)
ObjectType get_description_type(const string &value)
string cid_to_header_value(const string &cid)
void parse_mime_header(const string &header, string &name, string &value)
string prune_spaces(const string &name)
void read_multipart_headers(FILE *in, const string &content_type, const ObjectType object_type, const string &cid)
string id2www_ce(string in, const string &allowable)
ObjectType
The type of object in the stream coming from the data server.
string get_next_mime_header(FILE *in)