Connect.cc

Go to the documentation of this file.
00001 
00002 // -*- mode: c++; c-basic-offset:4 -*-
00003 
00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00005 // Access Protocol.
00006 
00007 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00008 // Author: James Gallagher <jgallagher@opendap.org>
00009 //         Dan Holloway <dholloway@gso.uri.edu>
00010 //         Reza Nekovei <reza@intcomm.net>
00011 //
00012 // This library is free software; you can redistribute it and/or
00013 // modify it under the terms of the GNU Lesser General Public
00014 // License as published by the Free Software Foundation; either
00015 // version 2.1 of the License, or (at your option) any later version.
00016 //
00017 // This library is distributed in the hope that it will be useful,
00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00027 
00028 // (c) COPYRIGHT URI/MIT 1994-2002
00029 // Please read the full copyright statement in the file COPYRIGHT_URI.
00030 //
00031 // Authors:
00032 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00033 //      dan             Dan Holloway <dholloway@gso.uri.edu>
00034 //      reza            Reza Nekovei <reza@intcomm.net>
00035 
00036 
00037 #include "config.h"
00038 
00039 //#define DODS_DEBUG
00040 
00041 static char rcsid[] not_used =
00042     { "$Id: Connect.cc 21699 2009-11-05 00:06:01Z jimg $"
00043     };
00044 
00045 #include <cstring>
00046 #include <fstream>
00047 #include <algorithm>
00048 
00049 #include "debug.h"
00050 #include "DataDDS.h"
00051 #include "Connect.h"
00052 #include "escaping.h"
00053 #include "RCReader.h"
00054 #include "DDXParserSAX2.h"
00055 #if FILE_METHODS
00056 #include "XDRFileUnMarshaller.h"
00057 #endif
00058 #include "fdiostream.h"
00059 #include "XDRStreamUnMarshaller.h"
00060 
00061 #include "mime_util.h"
00062 
00063 using std::cerr;
00064 using std::endl;
00065 using std::ifstream;
00066 using std::ofstream;
00067 using std::min;
00068 
00069 namespace libdap {
00070 
00073 void
00074 Connect::process_data(DataDDS &data, Response *rs)
00075 {
00076     DBG(cerr << "Entering Connect::process_data" << endl);
00077 
00078     data.set_version(rs->get_version());
00079     data.set_protocol(rs->get_protocol());
00080 
00081     DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
00082     switch (rs->get_type()) {
00083     case dods_error: {
00084             Error e;
00085             if (!e.parse(rs->get_stream()))
00086                 throw InternalErr(__FILE__, __LINE__,
00087                                   "Could not parse the Error object returned by the server!");
00088             throw e;
00089         }
00090 
00091     case web_error:
00092         // Web errors (those reported in the return document's MIME header)
00093         // are processed by the WWW library.
00094         throw InternalErr(__FILE__, __LINE__, "An error was reported by the remote httpd; this should have been processed by HTTPConnect..");
00095 
00096     case dap4_data_ddx: {
00097             // Parse the DDX; throw an exception on error.
00098             DDXParser ddx_parser(data.get_factory());
00099 
00100             // Read the MPM boundary and then read the subsequent headers
00101             string boundary = read_multipart_boundary(rs->get_stream());
00102             DBG(cerr << "MPM Boundary: " << boundary << endl);
00103             read_multipart_headers(rs->get_stream(), "text/xml", dap4_ddx);
00104 
00105             // Parse the DDX, reading up to and including the next boundary.
00106             // Return the CID for the matching data part
00107             string data_cid;
00108             ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
00109 
00110             // Munge the CID into something we can work with
00111             data_cid = cid_to_header_value(data_cid);
00112             DBG(cerr << "Data CID: " << data_cid << endl);
00113 
00114             // Read the data part's MPM part headers (boundary was read by
00115             // DDXParse::intern)
00116             read_multipart_headers(rs->get_stream(),
00117                     "application/octet-stream", dap4_data, data_cid);
00118 
00119             // Now read the data
00120 #if FILE_METHODS
00121             XDRFileUnMarshaller um( rs->get_stream() ) ;
00122 #else
00123             fpistream in ( rs->get_stream() );
00124             XDRStreamUnMarshaller um( in ) ;
00125 #endif
00126             try {
00127                 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end();
00128                      i++) {
00129                     (*i)->deserialize(um, &data);
00130                 }
00131             }
00132             catch (Error &e) {
00133                 throw e;
00134             }
00135 
00136             return;
00137         }
00138 
00139     case dods_data:
00140     default: {
00141             // Parse the DDS; throw an exception on error.
00142             data.parse(rs->get_stream());
00143 #if FILE_METHODS
00144             XDRFileUnMarshaller um( rs->get_stream() ) ;
00145 #else
00146             fpistream in ( rs->get_stream() );
00147             XDRStreamUnMarshaller um( in ) ;
00148 #endif
00149             // Load the DDS with data.
00150             try {
00151                 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end();
00152                      i++) {
00153                     (*i)->deserialize(um, &data);
00154                 }
00155             }
00156             catch (Error &e) {
00157                 throw e;
00158             }
00159 
00160             return;
00161         }
00162     }
00163 }
00164 
00165 // Barely a parser... This is used when reading from local sources of DODS
00166 // Data objects. It simulates the important actions of the libwww MIME header
00167 // parser. Those actions fill in certain fields in the Connect object. jhrg
00168 // 5/20/97
00169 //
00170 // Make sure that this parser reads from data_source without disturbing the
00171 // information in data_source that follows the MIME header. Since the DDS
00172 // (which follows the MIME header) is parsed by a flex/bison scanner/parser,
00173 // make sure to use I/O calls that will mesh with ANSI C I/O calls. In the
00174 // old GNU libg++, the C++ calls were synchronized with the C calls, but that
00175 // may no longer be the case. 5/31/99 jhrg
00176 
00186 void
00187 Connect::parse_mime(Response *rs)
00188 {
00189     rs->set_version("dods/0.0"); // initial value; for backward compatibility.
00190     rs->set_protocol("2.0");
00191 
00192     FILE *data_source = rs->get_stream();
00193     string mime = get_next_mime_header(data_source);
00194     while (!mime.empty()) {
00195         string header, value;
00196         parse_mime_header(mime, header, value);
00197 
00198         // Note that this is an ordered list
00199         if (header == "content-description:") {
00200             DBG(cout << header << ": " << value << endl);
00201             rs->set_type(get_description_type(value));
00202         }
00203         // Use the value of xdods-server only if no other value has been read
00204         else if (header == "xdods-server:"
00205                  && rs->get_version() == "dods/0.0") {
00206             DBG(cout << header << ": " << value << endl);
00207             rs->set_version(value);
00208         }
00209         // This trumps 'xdods-server' and 'server'
00210         else if (header == "xopendap-server:") {
00211             DBG(cout << header << ": " << value << endl);
00212             rs->set_version(value);
00213         }
00214         else if (header == "xdap:") {
00215             DBG(cout << header << ": " << value << endl);
00216             rs->set_protocol(value);
00217         }
00218         // Only look for 'server' if no other header supplies this info.
00219         else if (rs->get_version() == "dods/0.0" && header == "server:") {
00220             DBG(cout << header << ": " << value << endl);
00221             rs->set_version(value);
00222         }
00223 
00224         mime = get_next_mime_header(data_source);
00225     }
00226 }
00227 
00228 // public mfuncs
00229 
00237 Connect::Connect(const string &n, string uname, string password)
00238 throw(Error, InternalErr)
00239         : d_http(0), d_version("unknown"), d_protocol("2.0")
00240 {
00241     string name = prune_spaces(n);
00242 
00243     // Figure out if the URL starts with 'http', if so, make sure that we
00244     // talk to an instance of HTTPConnect.
00245     if (name.find("http") == 0) {
00246         DBG(cerr << "Connect: The identifier is an http URL" << endl);
00247         d_http = new HTTPConnect(RCReader::instance());
00248 
00249         // Find and store any CE given with the URL.
00250         string::size_type dotpos = name.find('?');
00251         if (dotpos != name.npos) {
00252             _URL = name.substr(0, dotpos);
00253             string expr = name.substr(dotpos + 1);
00254 
00255             dotpos = expr.find('&');
00256             if (dotpos != expr.npos) {
00257                 _proj = expr.substr(0, dotpos);
00258                 _sel = expr.substr(dotpos); // XXX includes '&'
00259             }
00260             else {
00261                 _proj = expr;
00262                 _sel = "";
00263             }
00264         }
00265         else {
00266             _URL = name;
00267             _proj = "";
00268             _sel = "";
00269         }
00270 
00271         _local = false;
00272     }
00273     else {
00274         DBG(cerr << "Connect: The identifier is a local data source." << endl);
00275 
00276         d_http = 0;
00277         _URL = "";
00278         _local = true;  // local in this case means non-DAP
00279     }
00280 
00281     set_credentials(uname, password);
00282 }
00283 
00284 Connect::~Connect()
00285 {
00286     DBG2(cerr << "Entering the Connect dtor" << endl);
00287 
00288     if (d_http)
00289         delete d_http; d_http = 0;
00290 
00291     DBG2(cerr << "Leaving the Connect dtor" << endl);
00292 }
00293 
00301 string
00302 Connect::request_version()
00303 {
00304     string version_url = _URL + ".ver";
00305     if (_proj.length() + _sel.length())
00306         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00307 
00308     Response *rs = 0;
00309     try {
00310         rs = d_http->fetch_url(version_url);
00311     }
00312     catch (Error &e) {
00313         delete rs; rs = 0;
00314         throw e;
00315     }
00316 
00317     d_version = rs->get_version();
00318     d_protocol = rs->get_protocol();
00319 
00320     delete rs; rs = 0;
00321 
00322     return d_version;
00323 }
00324 
00336 string
00337 Connect::request_protocol()
00338 {
00339     string version_url = _URL + ".ver";
00340     if (_proj.length() + _sel.length())
00341         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00342 
00343     Response *rs = 0;
00344     try {
00345         rs = d_http->fetch_url(version_url);
00346     }
00347     catch (Error &e) {
00348         delete rs; rs = 0;
00349         throw e;
00350     }
00351 
00352     d_version = rs->get_version();
00353     d_protocol = rs->get_protocol();
00354 
00355     delete rs; rs = 0;
00356 
00357     return d_protocol;
00358 }
00359 
00367 void
00368 Connect::request_das(DAS &das)
00369 {
00370     string das_url = _URL + ".das";
00371     if (_proj.length() + _sel.length())
00372         das_url = das_url + "?" + id2www_ce(_proj + _sel);
00373 
00374     Response *rs = 0;
00375     try {
00376         rs = d_http->fetch_url(das_url);
00377     }
00378     catch (Error &e) {
00379         delete rs; rs = 0;
00380         throw e;
00381     }
00382 
00383     d_version = rs->get_version();
00384     d_protocol = rs->get_protocol();
00385 
00386     switch (rs->get_type()) {
00387     case dods_error: {
00388             Error e;
00389             if (!e.parse(rs->get_stream())) {
00390                 throw InternalErr(__FILE__, __LINE__,
00391                                   "Could not parse error returned from server.");
00392                 break;
00393             }
00394             throw e;
00395             break;
00396         }
00397 
00398     case web_error:
00399         // We should never get here; a web error should be picked up read_url
00400         // (called by fetch_url) and result in a thrown Error object.
00401         break;
00402 
00403     case dods_das:
00404     default:
00405         // DAS::parse throws an exception on error.
00406         try {
00407             das.parse(rs->get_stream()); // read and parse the das from a file
00408         }
00409         catch (Error &e) {
00410             delete rs; rs = 0;
00411             throw e;
00412         }
00413 
00414         break;
00415     }
00416 
00417     delete rs; rs = 0;
00418 }
00419 
00430 void
00431 Connect::request_das_url(DAS &das)
00432 {
00433     string use_url = _URL + "?" + _proj + _sel ;
00434     Response *rs = 0;
00435     try {
00436         rs = d_http->fetch_url(use_url);
00437     }
00438     catch (Error &e) {
00439         delete rs; rs = 0;
00440         throw e;
00441     }
00442 
00443     d_version = rs->get_version();
00444     d_protocol = rs->get_protocol();
00445 
00446     switch (rs->get_type()) {
00447     case dods_error: {
00448             Error e;
00449             if (!e.parse(rs->get_stream())) {
00450                 throw InternalErr(__FILE__, __LINE__,
00451                                   "Could not parse error returned from server.");
00452                 break;
00453             }
00454             throw e;
00455             break;
00456         }
00457 
00458     case web_error:
00459         // We should never get here; a web error should be picked up read_url
00460         // (called by fetch_url) and result in a thrown Error object.
00461         break;
00462 
00463     case dods_das:
00464     default:
00465         // DAS::parse throws an exception on error.
00466         try {
00467             das.parse(rs->get_stream()); // read and parse the das from a file
00468         }
00469         catch (Error &e) {
00470             delete rs; rs = 0;
00471             throw e;
00472         }
00473 
00474         break;
00475     }
00476 
00477     delete rs; rs = 0;
00478 }
00479 
00493 void
00494 Connect::request_dds(DDS &dds, string expr)
00495 {
00496     string proj, sel;
00497     string::size_type dotpos = expr.find('&');
00498     if (dotpos != expr.npos) {
00499         proj = expr.substr(0, dotpos);
00500         sel = expr.substr(dotpos);
00501     }
00502     else {
00503         proj = expr;
00504         sel = "";
00505     }
00506 
00507     string dds_url = _URL + ".dds" + "?"
00508                      + id2www_ce(_proj + proj + _sel + sel);
00509 
00510     Response *rs = 0;
00511     try {
00512         rs = d_http->fetch_url(dds_url);
00513     }
00514     catch (Error &e) {
00515         delete rs; rs = 0;
00516         throw e;
00517     }
00518 
00519     d_version = rs->get_version();
00520     d_protocol = rs->get_protocol();
00521 
00522     switch (rs->get_type()) {
00523     case dods_error: {
00524             Error e;
00525             if (!e.parse(rs->get_stream())) {
00526                 throw InternalErr(__FILE__, __LINE__,
00527                                   "Could not parse error returned from server.");
00528                 break;
00529             }
00530             throw e;
00531             break;
00532         }
00533 
00534     case web_error:
00535         // We should never get here; a web error should be picked up read_url
00536         // (called by fetch_url) and result in a thrown Error object.
00537         break;
00538 
00539     case dods_dds:
00540     default:
00541         // DDS::prase throws an exception on error.
00542         try {
00543             dds.parse(rs->get_stream()); // read and parse the dds from a file
00544         }
00545         catch (Error &e) {
00546             delete rs; rs = 0;
00547             throw e;
00548         }
00549         break;
00550     }
00551 
00552     delete rs; rs = 0;
00553 }
00554 
00571 void
00572 Connect::request_dds_url(DDS &dds)
00573 {
00574     string use_url = _URL + "?" + _proj + _sel ;
00575     Response *rs = 0;
00576     try {
00577         rs = d_http->fetch_url(use_url);
00578     }
00579     catch (Error &e) {
00580         delete rs; rs = 0;
00581         throw e;
00582     }
00583 
00584     d_version = rs->get_version();
00585     d_protocol = rs->get_protocol();
00586 
00587     switch (rs->get_type()) {
00588     case dods_error: {
00589             Error e;
00590             if (!e.parse(rs->get_stream())) {
00591                 throw InternalErr(__FILE__, __LINE__,
00592                                   "Could not parse error returned from server.");
00593                 break;
00594             }
00595             throw e;
00596             break;
00597         }
00598 
00599     case web_error:
00600         // We should never get here; a web error should be picked up read_url
00601         // (called by fetch_url) and result in a thrown Error object.
00602         break;
00603 
00604     case dods_dds:
00605     default:
00606         // DDS::prase throws an exception on error.
00607         try {
00608             dds.parse(rs->get_stream()); // read and parse the dds from a file
00609         }
00610         catch (Error &e) {
00611             delete rs; rs = 0;
00612             throw e;
00613         }
00614         break;
00615     }
00616 
00617     delete rs; rs = 0;
00618 }
00619 
00631 void
00632 Connect::request_ddx(DDS &dds, string expr)
00633 {
00634     string proj, sel;
00635     string::size_type dotpos = expr.find('&');
00636     if (dotpos != expr.npos) {
00637         proj = expr.substr(0, dotpos);
00638         sel = expr.substr(dotpos);
00639     }
00640     else {
00641         proj = expr;
00642         sel = "";
00643     }
00644 
00645     string ddx_url = _URL + ".ddx" + "?"
00646                      + id2www_ce(_proj + proj + _sel + sel);
00647 
00648     Response *rs = 0;
00649     try {
00650         rs = d_http->fetch_url(ddx_url);
00651     }
00652     catch (Error &e) {
00653         delete rs; rs = 0;
00654         throw e;
00655     }
00656 
00657     d_version = rs->get_version();
00658     d_protocol = rs->get_protocol();
00659 
00660     switch (rs->get_type()) {
00661     case dods_error: {
00662             Error e;
00663             if (!e.parse(rs->get_stream())) {
00664                 throw InternalErr(__FILE__, __LINE__,
00665                                   "Could not parse error returned from server.");
00666                 break;
00667             }
00668             throw e;
00669             break;
00670         }
00671 
00672     case web_error:
00673         // We should never get here; a web error should be picked up read_url
00674         // (called by fetch_url) and result in a thrown Error object.
00675         break;
00676 
00677     case dap4_ddx:
00678     case dods_ddx:
00679         try {
00680             string blob;
00681 
00682             DDXParser ddxp(dds.get_factory());
00683             ddxp.intern_stream(rs->get_stream(), &dds, blob);
00684         }
00685         catch (Error &e) {
00686             delete rs; rs = 0;
00687             throw e;
00688         }
00689         break;
00690 
00691     default:
00692         throw Error("The site did not return a valid response (it lacked the\n\
00693 expected content description header value of 'dap4-ddx' and\n\
00694 instead returned '" + long_to_string(rs->get_type()) + "').\n\
00695 This may indicate that the server at the site is not correctly\n\
00696 configured, or that the URL has changed.");
00697     }
00698 
00699     delete rs; rs = 0;
00700 }
00701 
00704 void
00705 Connect::request_ddx_url(DDS &dds)
00706 {
00707     string use_url = _URL + "?" + _proj + _sel ;
00708 
00709     Response *rs = 0;
00710     try {
00711         rs = d_http->fetch_url(use_url);
00712     }
00713     catch (Error &e) {
00714         delete rs; rs = 0;
00715         throw e;
00716     }
00717 
00718     d_version = rs->get_version();
00719     d_protocol = rs->get_protocol();
00720 
00721     switch (rs->get_type()) {
00722     case dods_error: {
00723             Error e;
00724             if (!e.parse(rs->get_stream())) {
00725                 throw InternalErr(__FILE__, __LINE__,
00726                                   "Could not parse error returned from server.");
00727                 break;
00728             }
00729             throw e;
00730             break;
00731         }
00732 
00733     case web_error:
00734         // We should never get here; a web error should be picked up read_url
00735         // (called by fetch_url) and result in a thrown Error object.
00736         break;
00737 
00738     case dap4_ddx:
00739     case dods_ddx:
00740         try {
00741             string blob;
00742 
00743             DDXParser ddxp(dds.get_factory());
00744             ddxp.intern_stream(rs->get_stream(), &dds, blob);
00745         }
00746         catch (Error &e) {
00747             delete rs; rs = 0;
00748             throw e;
00749         }
00750         break;
00751 
00752     default:
00753         throw Error("The site did not return a valid response (it lacked the\n\
00754 expected content description header value of 'dap4-ddx' and\n\
00755 instead returned '" + long_to_string(rs->get_type()) + "').\n\
00756 This may indicate that the server at the site is not correctly\n\
00757 configured, or that the URL has changed.");
00758     }
00759 
00760     delete rs; rs = 0;
00761 }
00762 
00778 void
00779 Connect::request_data(DataDDS &data, string expr)
00780 {
00781     string proj, sel;
00782     string::size_type dotpos = expr.find('&');
00783     if (dotpos != expr.npos) {
00784         proj = expr.substr(0, dotpos);
00785         sel = expr.substr(dotpos);
00786     }
00787     else {
00788         proj = expr;
00789         sel = "";
00790     }
00791 
00792     string data_url = _URL + ".dods?"
00793                       + id2www_ce(_proj + proj + _sel + sel);
00794 
00795     Response *rs = 0;
00796     // We need to catch Error exceptions to ensure calling close_output.
00797     try {
00798         rs = d_http->fetch_url(data_url);
00799 
00800         d_version = rs->get_version();
00801         d_protocol = rs->get_protocol();
00802 
00803         process_data(data, rs);
00804         delete rs; rs = 0;
00805     }
00806     catch (Error &e) {
00807         delete rs; rs = 0;
00808         throw e;
00809     }
00810 }
00811 
00829 void
00830 Connect::request_data_url(DataDDS &data)
00831 {
00832     string use_url = _URL + "?" + _proj + _sel ;
00833     Response *rs = 0;
00834     // We need to catch Error exceptions to ensure calling close_output.
00835     try {
00836         rs = d_http->fetch_url(use_url);
00837 
00838         d_version = rs->get_version();
00839         d_protocol = rs->get_protocol();
00840 
00841         process_data(data, rs);
00842         delete rs; rs = 0;
00843     }
00844     catch (Error &e) {
00845         delete rs; rs = 0;
00846         throw e;
00847     }
00848 }
00849 
00850 void
00851 Connect::request_data_ddx(DataDDS &data, string expr)
00852 {
00853     string proj, sel;
00854     string::size_type dotpos = expr.find('&');
00855     if (dotpos != expr.npos) {
00856         proj = expr.substr(0, dotpos);
00857         sel = expr.substr(dotpos);
00858     }
00859     else {
00860         proj = expr;
00861         sel = "";
00862     }
00863 
00864     string data_url = _URL + ".dap?"
00865                       + id2www_ce(_proj + proj + _sel + sel);
00866 
00867     Response *rs = 0;
00868     // We need to catch Error exceptions to ensure calling close_output.
00869     try {
00870         rs = d_http->fetch_url(data_url);
00871 
00872         d_version = rs->get_version();
00873         d_protocol = rs->get_protocol();
00874 
00875         process_data(data, rs);
00876         delete rs; rs = 0;
00877     }
00878     catch (Error &e) {
00879         delete rs; rs = 0;
00880         throw e;
00881     }
00882 }
00883 
00884 void
00885 Connect::request_data_ddx_url(DataDDS &data)
00886 {
00887     string use_url = _URL + "?" + _proj + _sel ;
00888     Response *rs = 0;
00889     // We need to catch Error exceptions to ensure calling close_output.
00890     try {
00891         rs = d_http->fetch_url(use_url);
00892 
00893         d_version = rs->get_version();
00894         d_protocol = rs->get_protocol();
00895 
00896         process_data(data, rs);
00897         delete rs; rs = 0;
00898     }
00899     catch (Error &e) {
00900         delete rs; rs = 0;
00901         throw e;
00902     }
00903 }
00904 
00918 void
00919 Connect::read_data(DataDDS &data, Response *rs)
00920 {
00921     if (!rs)
00922         throw InternalErr(__FILE__, __LINE__, "Response object is null.");
00923 
00924     // Read from data_source and parse the MIME headers specific to DAP2/4.
00925     parse_mime(rs);
00926 
00927     read_data_no_mime(data, rs);
00928 }
00929 
00930 // This function looks at the input stream and makes its best guess at what
00931 // lies in store for downstream processing code. Definitely heuristic.
00932 // Assumptions:
00933 // #1 The current file position is past any MIME headers (if they were present).
00934 // #2 We must reset the FILE* position to the start of the DDS or DDX headers
00935 static void
00936 divine_type_information(Response *rs)
00937 {
00938     // Consume whitespace
00939     char c = getc(rs->get_stream());
00940     while (isspace(c)) {
00941         c = getc(rs->get_stream());
00942     }
00943 
00944     // The heuristic here is that a DataDDX is a multipart MIME document and
00945     // The first non space character found after the headers is the start of
00946     // the first part which looks like '--<boundary>' while a DataDDS starts
00947     // with a DDS (;Dataset {' ...). I take into account that our parsers have
00948     // accepted both 'Dataset' and 'dataset' for a long time.
00949     switch (c) {
00950     case '-':
00951         rs->set_type(dap4_data_ddx);
00952         break;
00953     case 'D':
00954     case 'd':
00955         rs->set_type(dods_data);
00956         break;
00957     default:
00958         throw InternalErr(__FILE__, __LINE__, "Could not determine type of response object in stream.");
00959     }
00960 
00961     ungetc(c, rs->get_stream());
00962 }
00963 
00976 void
00977 Connect::read_data_no_mime(DataDDS &data, Response *rs)
00978 {
00979     if (rs->get_type() == unknown_type)
00980         divine_type_information(rs);
00981 
00982     switch (rs->get_type()) {
00983     case dods_data:
00984         d_version = rs->get_version();
00985         d_protocol = rs->get_protocol();
00986         process_data(data, rs);
00987         break;
00988     case dap4_data_ddx:
00989         process_data(data, rs);
00990         d_version = rs->get_version();
00991         d_protocol = data.get_protocol();
00992         break;
00993     default:
00994         throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX.");
00995     }
00996 }
00997 
00998 bool
00999 Connect::is_local()
01000 {
01001     return _local;
01002 }
01003 
01020 string
01021 Connect::URL(bool ce)
01022 {
01023     if (_local)
01024         throw InternalErr(__FILE__, __LINE__,
01025                           "URL(): This call is only valid for a DAP data source.");
01026 
01027     if (ce)
01028         return _URL + "?" + _proj + _sel;
01029     else
01030         return _URL;
01031 }
01032 
01041 string
01042 Connect::CE()
01043 {
01044     if (_local)
01045         throw InternalErr(__FILE__, __LINE__,
01046                           "CE(): This call is only valid for a DAP data source.");
01047 
01048     return _proj + _sel;
01049 }
01050 
01056 void
01057 Connect::set_credentials(string u, string p)
01058 {
01059     if (d_http)
01060         d_http->set_credentials(u, p);
01061 }
01062 
01066 void
01067 Connect::set_accept_deflate(bool deflate)
01068 {
01069     if (d_http)
01070         d_http->set_accept_deflate(deflate);
01071 }
01072 
01078 void
01079 Connect::set_xdap_protocol(int major, int minor)
01080 {
01081     if (d_http)
01082         d_http->set_xdap_protocol(major, minor);
01083 }
01084 
01088 void
01089 Connect::set_cache_enabled(bool cache)
01090 {
01091     if (d_http)
01092         d_http->set_cache_enabled(cache);
01093 }
01094 
01095 bool
01096 Connect::is_cache_enabled()
01097 {
01098     bool status;
01099     DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec
01100         << ")... ");
01101     if (d_http)
01102         status = d_http->is_cache_enabled();
01103     else
01104         status = false;
01105     DBGN(cerr << "exiting" << endl);
01106     return status;
01107 }
01108 
01109 } // namespace libdap

Generated on Wed Feb 10 16:08:01 2010 for libdap++ by  doxygen 1.4.7