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 16612 2007-06-04 22:08:57Z jimg $"
00043     };
00044 
00045 #include <stdio.h>
00046 #ifndef WIN32
00047 #include <unistd.h>
00048 #endif
00049 
00050 #include <fstream>
00051 
00052 #include "debug.h"
00053 #include "DataDDS.h"
00054 #include "Connect.h"
00055 #include "escaping.h"
00056 #include "RCReader.h"
00057 #include "DDXParser.h"
00058 
00059 using std::cerr;
00060 using std::endl;
00061 using std::ifstream;
00062 using std::ofstream;
00063 
00064 extern ObjectType get_type(const string &value);
00065 
00068 void
00069 Connect::process_data(DataDDS &data, Response *rs)
00070 {
00071     DBG(cerr << "Entering Connect::process_data" << endl);
00072 
00073     // Use the implementation and protocol versions from the Response object
00074     // since the copies in Connect might go away. Regardless, we must keep the
00075     // Response object alive until we no longer need the stream, since
00076     // destroying it will close the stream. So, might as well use it for the
00077     // version info too...
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 dods_data:
00097     default: {
00098             // Parse the DDS; throw an exception on error.
00099             data.parse(rs->get_stream());
00100             XDR *xdr_stream = new_xdrstdio(rs->get_stream(), XDR_DECODE);
00101 
00102             // Load the DDS with data.
00103             try {
00104                 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end();
00105                      i++) {
00106                     (*i)->deserialize(xdr_stream, &data);
00107                 }
00108             }
00109             catch (Error &e) {
00110                 delete_xdrstdio(xdr_stream);
00111                 throw e;
00112             }
00113 
00114             delete_xdrstdio(xdr_stream);
00115             return;
00116         }
00117 
00118 #if 0
00119         // According to the spec (DAP 2), servers MUST return the dods_data
00120         // Content-Type. But, many older servers do not do this, so the
00121         // default case is not to throw an error, but to treat the response
00122         // as data... See bug 706. 03/22/04 jhrg
00123     default:
00124         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_data').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00125 #endif
00126     }
00127 }
00128 
00129 // This function returns the ObjectType value that matches the given string.
00130 ObjectType
00131 get_type(const string &value)
00132 {
00133     if (value == "dods_das")
00134         return dods_das;
00135     else if (value == "dods_dds")
00136         return dods_dds;
00137     else if (value == "dods_data")
00138         return dods_data;
00139     else if (value == "dods_error")
00140         return dods_error;
00141     else if (value == "web_error")
00142         return web_error;
00143     else
00144         return unknown_type;
00145 }
00146 
00147 // Barely a parser... This is used when reading from local sources of DODS
00148 // Data objects. It simulates the important actions of the libwww MIME header
00149 // parser. Those actions fill in certain fields in the Connect object. jhrg
00150 // 5/20/97
00151 //
00152 // Make sure that this parser reads from data_source without disturbing the
00153 // information in data_source that follows the MIME header. Since the DDS
00154 // (which follows the MIME header) is parsed by a flex/bison scanner/parser,
00155 // make sure to use I/O calls that will mesh with ANSI C I/O calls. In the
00156 // old GNU libg++, the C++ calls were synchronized with the C calls, but that
00157 // may no longer be the case. 5/31/99 jhrg
00158 
00168 void
00169 Connect::parse_mime(/*FILE *data_source, */Response *rs)
00170 {
00171     rs->set_version("dods/0.0"); // initial value; for backward compat.
00172     rs->set_protocol("2.0");
00173 
00174     // If the first line does not start with HTTP, XDODS or XDAP, assume
00175     // there's no MIME header here and return without reading anymore
00176     FILE *data_source = rs->get_stream();
00177 
00178     char line[256];
00179     fgets(line, 255, data_source);
00180 
00181     int slen = strlen(line);
00182     line[slen - 1] = '\0'; // remove the newline
00183     if (line[slen - 2] == '\r') // ...and the preceding carriage return
00184         line[slen - 2] = '\0';
00185 
00186     while (line[0] != '\0') {
00187         char h[256], v[256];
00188         sscanf(line, "%s %s\n", h, v);
00189         string header = h;
00190         string value = v;
00191         downcase(header);
00192         downcase(value);
00193 
00194         if (header == "content-description:") {
00195             DBG(cout << header << ": " << value << endl);
00196             rs->set_type(get_type(value));
00197         }
00198         else if (header == "xdods-server:"
00199                  && rs->get_version() == "dods/0.0") {
00200             DBG(cout << header << ": " << value << endl);
00201             rs->set_version(value);
00202         }
00203         else if (header == "xopendap-server:") {
00204             DBG(cout << header << ": " << value << endl);
00205             rs->set_version(value);
00206         }
00207         else if (header == "xdap:") {
00208             DBG(cout << header << ": " << value << endl);
00209             rs->set_protocol(value);
00210         }
00211         else if (rs->get_version() == "dods/0.0" && header == "server:") {
00212             DBG(cout << header << ": " << value << endl);
00213             rs->set_version(value);
00214         }
00215 
00216         fgets(line, 255, data_source);
00217         slen = strlen(line);
00218         line[slen - 1] = '\0';
00219         if (line[slen - 2] == '\r')
00220             line[slen - 2] = '\0';
00221     }
00222 }
00223 
00224 // public mfuncs
00225 
00233 Connect::Connect(const string &n, string uname, string password)
00234 throw(Error, InternalErr)
00235         : d_http(0), d_version("unknown"), d_protocol("2.0")
00236 {
00237     string name = prune_spaces(n);
00238 
00239     // Figure out if the URL starts with 'http', if so, make sure that we
00240     // talk to an instance of HTTPConnect.
00241     if (name.find("http") == 0) {
00242         DBG(cerr << "Connect: The identifier is an http URL" << endl);
00243         d_http = new HTTPConnect(RCReader::instance());
00244 
00245         // Find and store any CE given with the URL.
00246         string::size_type dotpos = name.find('?');
00247         if (dotpos != name.npos) {
00248             _URL = name.substr(0, dotpos);
00249             string expr = name.substr(dotpos + 1);
00250 
00251             dotpos = expr.find('&');
00252             if (dotpos != expr.npos) {
00253                 _proj = expr.substr(0, dotpos);
00254                 _sel = expr.substr(dotpos); // XXX includes '&'
00255             }
00256             else {
00257                 _proj = expr;
00258                 _sel = "";
00259             }
00260         }
00261         else {
00262             _URL = name;
00263             _proj = "";
00264             _sel = "";
00265         }
00266 
00267         _local = false;
00268     }
00269     else {
00270         DBG(cerr << "Connect: The identifier is a local data source." << endl);
00271 
00272         d_http = 0;
00273         _URL = "";
00274         _local = true;  // local in this case means non-DAP
00275     }
00276 
00277     set_credentials(uname, password);
00278 }
00279 
00280 Connect::~Connect()
00281 {
00282     DBG2(cerr << "Entering the Connect dtor" << endl);
00283 
00284     if (d_http)
00285         delete d_http; d_http = 0;
00286 
00287     DBG2(cerr << "Leaving the Connect dtor" << endl);
00288 }
00289 
00297 string
00298 Connect::request_version()
00299 {
00300     string version_url = _URL + ".ver";
00301     if (_proj.length() + _sel.length())
00302         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00303 
00304     Response *rs = 0;
00305     try {
00306         rs = d_http->fetch_url(version_url);
00307     }
00308     catch (Error &e) {
00309         delete rs; rs = 0;
00310         throw e;
00311     }
00312 
00313     d_version = rs->get_version();
00314     d_protocol = rs->get_protocol();
00315     delete rs; rs = 0;
00316 
00317     return d_version;
00318 }
00319 
00327 string
00328 Connect::request_protocol()
00329 {
00330     string version_url = _URL + ".ver";
00331     if (_proj.length() + _sel.length())
00332         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00333 
00334     Response *rs = 0;
00335     try {
00336         rs = d_http->fetch_url(version_url);
00337     }
00338     catch (Error &e) {
00339         delete rs; rs = 0;
00340         throw e;
00341     }
00342 
00343     d_version = rs->get_version();
00344     d_protocol = rs->get_protocol();
00345     delete rs; rs = 0;
00346 
00347     return d_protocol;
00348 }
00349 
00357 void
00358 Connect::request_das(DAS &das)
00359 {
00360     string das_url = _URL + ".das";
00361     if (_proj.length() + _sel.length())
00362         das_url = das_url + "?" + id2www_ce(_proj + _sel);
00363 
00364     Response *rs = 0;
00365     try {
00366         rs = d_http->fetch_url(das_url);
00367     }
00368     catch (Error &e) {
00369         delete rs; rs = 0;
00370         throw e;
00371     }
00372 
00373     d_version = rs->get_version();
00374     d_protocol = rs->get_protocol();
00375 
00376     switch (rs->get_type()) {
00377     case dods_error: {
00378             Error e;
00379             if (!e.parse(rs->get_stream())) {
00380                 throw InternalErr(__FILE__, __LINE__,
00381                                   "Could not parse error returned from server.");
00382                 break;
00383             }
00384             throw e;
00385             break;
00386         }
00387 
00388     case web_error:
00389         // We should never get here; a web error should be picked up read_url
00390         // (called by fetch_url) and result in a thrown Error object.
00391         break;
00392 
00393     case dods_das:
00394     default:
00395         // DAS::parse throws an exception on error.
00396         try {
00397             das.parse(rs->get_stream()); // read and parse the das from a file
00398         }
00399         catch (Error &e) {
00400             delete rs; rs = 0;
00401             throw e;
00402         }
00403 
00404         break;
00405 
00406 #if 0
00407         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00408     default:
00409         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_das').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00410 #endif
00411     }
00412 
00413     delete rs; rs = 0;
00414 }
00415 
00426 void
00427 Connect::request_das_url(DAS &das)
00428 {
00429     string use_url = _URL + "?" + _proj + _sel ;
00430     Response *rs = 0;
00431     try {
00432         rs = d_http->fetch_url(use_url);
00433     }
00434     catch (Error &e) {
00435         delete rs; rs = 0;
00436         throw e;
00437     }
00438 
00439     d_version = rs->get_version();
00440     d_protocol = rs->get_protocol();
00441 
00442     switch (rs->get_type()) {
00443     case dods_error: {
00444             Error e;
00445             if (!e.parse(rs->get_stream())) {
00446                 throw InternalErr(__FILE__, __LINE__,
00447                                   "Could not parse error returned from server.");
00448                 break;
00449             }
00450             throw e;
00451             break;
00452         }
00453 
00454     case web_error:
00455         // We should never get here; a web error should be picked up read_url
00456         // (called by fetch_url) and result in a thrown Error object.
00457         break;
00458 
00459     case dods_das:
00460     default:
00461         // DAS::parse throws an exception on error.
00462         try {
00463             das.parse(rs->get_stream()); // read and parse the das from a file
00464         }
00465         catch (Error &e) {
00466             delete rs; rs = 0;
00467             throw e;
00468         }
00469 
00470         break;
00471     }
00472 
00473     delete rs; rs = 0;
00474 }
00475 
00489 void
00490 Connect::request_dds(DDS &dds, string expr)
00491 {
00492     string proj, sel;
00493     string::size_type dotpos = expr.find('&');
00494     if (dotpos != expr.npos) {
00495         proj = expr.substr(0, dotpos);
00496         sel = expr.substr(dotpos);
00497     }
00498     else {
00499         proj = expr;
00500         sel = "";
00501     }
00502 
00503     string dds_url = _URL + ".dds" + "?"
00504                      + id2www_ce(_proj + proj + _sel + sel);
00505 
00506     Response *rs = 0;
00507     try {
00508         rs = d_http->fetch_url(dds_url);
00509     }
00510     catch (Error &e) {
00511         delete rs; rs = 0;
00512         throw e;
00513     }
00514 
00515     d_version = rs->get_version();
00516     d_protocol = rs->get_protocol();
00517 
00518     switch (rs->get_type()) {
00519     case dods_error: {
00520             Error e;
00521             if (!e.parse(rs->get_stream())) {
00522                 throw InternalErr(__FILE__, __LINE__,
00523                                   "Could not parse error returned from server.");
00524                 break;
00525             }
00526             throw e;
00527             break;
00528         }
00529 
00530     case web_error:
00531         // We should never get here; a web error should be picked up read_url
00532         // (called by fetch_url) and result in a thrown Error object.
00533         break;
00534 
00535     case dods_dds:
00536     default:
00537         // DDS::prase throws an exception on error.
00538         try {
00539             dds.parse(rs->get_stream()); // read and parse the dds from a file
00540         }
00541         catch (Error &e) {
00542             delete rs; rs = 0;
00543             throw e;
00544         }
00545         break;
00546 
00547 #if 0
00548         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00549     default:
00550         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_dds').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00551 #endif
00552     }
00553 
00554     delete rs; rs = 0;
00555 }
00556 
00573 void
00574 Connect::request_dds_url(DDS &dds)
00575 {
00576     string use_url = _URL + "?" + _proj + _sel ;
00577     Response *rs = 0;
00578     try {
00579         rs = d_http->fetch_url(use_url);
00580     }
00581     catch (Error &e) {
00582         delete rs; rs = 0;
00583         throw e;
00584     }
00585 
00586     d_version = rs->get_version();
00587     d_protocol = rs->get_protocol();
00588 
00589     switch (rs->get_type()) {
00590     case dods_error: {
00591             Error e;
00592             if (!e.parse(rs->get_stream())) {
00593                 throw InternalErr(__FILE__, __LINE__,
00594                                   "Could not parse error returned from server.");
00595                 break;
00596             }
00597             throw e;
00598             break;
00599         }
00600 
00601     case web_error:
00602         // We should never get here; a web error should be picked up read_url
00603         // (called by fetch_url) and result in a thrown Error object.
00604         break;
00605 
00606     case dods_dds:
00607     default:
00608         // DDS::prase throws an exception on error.
00609         try {
00610             dds.parse(rs->get_stream()); // read and parse the dds from a file
00611         }
00612         catch (Error &e) {
00613             delete rs; rs = 0;
00614             throw e;
00615         }
00616         break;
00617     }
00618 
00619     delete rs; rs = 0;
00620 }
00621 
00633 void
00634 Connect::request_ddx(DDS &dds, string expr)
00635 {
00636     string proj, sel;
00637     string::size_type dotpos = expr.find('&');
00638     if (dotpos != expr.npos) {
00639         proj = expr.substr(0, dotpos);
00640         sel = expr.substr(dotpos);
00641     }
00642     else {
00643         proj = expr;
00644         sel = "";
00645     }
00646 
00647     string ddx_url = _URL + ".ddx" + "?"
00648                      + id2www_ce(_proj + proj + _sel + sel);
00649 
00650     Response *rs = 0;
00651     try {
00652         rs = d_http->fetch_url(ddx_url);
00653     }
00654     catch (Error &e) {
00655         delete rs; rs = 0;
00656         throw e;
00657     }
00658 
00659     d_version = rs->get_version();
00660     d_protocol = rs->get_protocol();
00661 
00662     switch (rs->get_type()) {
00663     case dods_error: {
00664             Error e;
00665             if (!e.parse(rs->get_stream())) {
00666                 throw InternalErr(__FILE__, __LINE__,
00667                                   "Could not parse error returned from server.");
00668                 break;
00669             }
00670             throw e;
00671             break;
00672         }
00673 
00674     case web_error:
00675         // We should never get here; a web error should be picked up read_url
00676         // (called by fetch_url) and result in a thrown Error object.
00677         break;
00678 
00679     case dap4_ddx:
00680     default:
00681         // DDS::prase throws an exception on error.
00682         try {
00683             string blob;
00684             DDXParser ddxp(dds.get_factory());
00685             ddxp.intern_stream(rs->get_stream(), &dds, &blob);
00686 #if 0
00687             dds.parse(rs->get_stream()); // read and parse the dds from a file
00688 #endif
00689         }
00690         catch (Error &e) {
00691             delete rs; rs = 0;
00692             throw e;
00693         }
00694         break;
00695 
00696 #if 0
00697         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00698     default:
00699         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_ddx').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00700 #endif
00701     }
00702 
00703     delete rs; rs = 0;
00704 }
00705 
00708 void
00709 Connect::request_ddx_url(DDS &dds)
00710 {
00711     string use_url = _URL + "?" + _proj + _sel ;
00712 
00713     Response *rs = 0;
00714     try {
00715         rs = d_http->fetch_url(use_url);
00716     }
00717     catch (Error &e) {
00718         delete rs; rs = 0;
00719         throw e;
00720     }
00721 
00722     d_version = rs->get_version();
00723     d_protocol = rs->get_protocol();
00724 
00725     switch (rs->get_type()) {
00726     case dods_error: {
00727             Error e;
00728             if (!e.parse(rs->get_stream())) {
00729                 throw InternalErr(__FILE__, __LINE__,
00730                                   "Could not parse error returned from server.");
00731                 break;
00732             }
00733             throw e;
00734             break;
00735         }
00736 
00737     case web_error:
00738         // We should never get here; a web error should be picked up read_url
00739         // (called by fetch_url) and result in a thrown Error object.
00740         break;
00741 
00742     case dap4_ddx:
00743     default:
00744         // DDS::prase throws an exception on error.
00745         try {
00746             dds.parse(rs->get_stream()); // read and parse the dds from a file
00747         }
00748         catch (Error &e) {
00749             delete rs; rs = 0;
00750             throw e;
00751         }
00752         break;
00753 
00754 #if 0
00755         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00756     default:
00757         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_ddx').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00758 #endif
00759     }
00760 
00761     delete rs; rs = 0;
00762 }
00763 
00779 void
00780 Connect::request_data(DataDDS &data, string expr)
00781 {
00782     string proj, sel;
00783     string::size_type dotpos = expr.find('&');
00784     if (dotpos != expr.npos) {
00785         proj = expr.substr(0, dotpos);
00786         sel = expr.substr(dotpos);
00787     }
00788     else {
00789         proj = expr;
00790         sel = "";
00791     }
00792 
00793     string data_url = _URL + ".dods?"
00794                       + id2www_ce(_proj + proj + _sel + sel);
00795 
00796     Response *rs = 0;
00797     // We need to catch Error exceptions to ensure calling close_output.
00798     try {
00799         rs = d_http->fetch_url(data_url);
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         d_version = rs->get_version();
00838         d_protocol = rs->get_protocol();
00839 
00840         process_data(data, rs);
00841         delete rs; rs = 0;
00842     }
00843     catch (Error &e) {
00844         delete rs; rs = 0;
00845         throw e;
00846     }
00847 }
00848 
00849 
00866 void
00867 Connect::read_data(DataDDS &data, Response *rs)
00868 {
00869     if (!rs)
00870         throw InternalErr(__FILE__, __LINE__, "Response object is null.");
00871 
00872     // Read from data_source and parse the MIME headers specific to DAP2.
00873     parse_mime(rs);
00874 
00875     read_data_no_mime(data, rs);
00876 }
00877 
00886 void
00887 Connect::read_data_no_mime(DataDDS &data, Response *rs)
00888 {
00889     d_version = rs->get_version();
00890     d_protocol = rs->get_protocol();
00891 
00892     process_data(data, rs);
00893 }
00894 
00895 bool
00896 Connect::is_local()
00897 {
00898     return _local;
00899 }
00900 
00917 string
00918 Connect::URL(bool ce)
00919 {
00920     if (_local)
00921         throw InternalErr(__FILE__, __LINE__,
00922                           "URL(): This call is only valid for a DAP2 data source.");
00923 
00924     if (ce)
00925         return _URL + "?" + _proj + _sel;
00926     else
00927         return _URL;
00928 }
00929 
00938 string
00939 Connect::CE()
00940 {
00941     if (_local)
00942         throw InternalErr(__FILE__, __LINE__,
00943                           "CE(): This call is only valid for a DAP2 data source.");
00944 
00945     return _proj + _sel;
00946 }
00947 
00953 void
00954 Connect::set_credentials(string u, string p)
00955 {
00956     if (d_http)
00957         d_http->set_credentials(u, p);
00958 }
00959 
00963 void
00964 Connect::set_accept_deflate(bool deflate)
00965 {
00966     if (d_http)
00967         d_http->set_accept_deflate(deflate);
00968 }
00969 
00973 void
00974 Connect::set_cache_enabled(bool cache)
00975 {
00976     if (d_http)
00977         d_http->set_cache_enabled(cache);
00978 }
00979 
00980 bool
00981 Connect::is_cache_enabled()
00982 {
00983     bool status;
00984     DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec
00985         << ")... ");
00986     if (d_http)
00987         status = d_http->is_cache_enabled();
00988     else
00989         status = false;
00990     DBGN(cerr << "exiting" << endl);
00991     return status;
00992 }

Generated on Wed Jun 27 12:56:38 2007 for libdap++ by  doxygen 1.4.7