|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
// Dan Holloway <dholloway@gso.uri.edu>
|
|
Packit |
a4aae4 |
// Reza Nekovei <reza@intcomm.net>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// (c) COPYRIGHT URI/MIT 1994-2002
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
|
|
Packit |
a4aae4 |
// dan Dan Holloway <dholloway@gso.uri.edu>
|
|
Packit |
a4aae4 |
// reza Reza Nekovei <reza@intcomm.net>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
#define FILE_UN_MARSHALLER 1
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cstring>
|
|
Packit |
a4aae4 |
#include <cerrno>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <fstream>
|
|
Packit |
a4aae4 |
#include <algorithm>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "DataDDS.h"
|
|
Packit |
a4aae4 |
#include "Connect.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
//#include "RCReader.h"
|
|
Packit |
a4aae4 |
#include "DDXParserSAX2.h"
|
|
Packit |
a4aae4 |
#if FILE_UN_MARSHALLER
|
|
Packit |
a4aae4 |
#include "XDRFileUnMarshaller.h"
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
#include "fdiostream.h"
|
|
Packit |
a4aae4 |
#include "XDRStreamUnMarshaller.h"
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#include "mime_util.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
using std::ifstream;
|
|
Packit |
a4aae4 |
using std::ofstream;
|
|
Packit |
a4aae4 |
using std::min;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This private method process data from both local and remote sources. It
|
|
Packit |
a4aae4 |
exists to eliminate duplication of code. */
|
|
Packit |
a4aae4 |
void Connect::process_data(DataDDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering Connect::process_data" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
data.set_version(rs->get_version());
|
|
Packit |
a4aae4 |
data.set_protocol(rs->get_protocol());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream()))
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse the Error object returned by the server!");
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// Web errors (those reported in the return document's MIME header)
|
|
Packit |
a4aae4 |
// are processed by the WWW library.
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__,
|
|
Packit |
a4aae4 |
"An error was reported by the remote httpd; this should have been processed by HTTPConnect..");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// This code triggers a security warning from Coverity; since it is not used,
|
|
Packit |
a4aae4 |
// I have removed it. jhrg 5/5/16
|
|
Packit |
a4aae4 |
case dods_data_ddx: {
|
|
Packit |
a4aae4 |
// Parse the DDX; throw an exception on error.
|
|
Packit |
a4aae4 |
DDXParser ddx_parser(data.get_factory());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read the MPM boundary and then read the subsequent headers
|
|
Packit |
a4aae4 |
string boundary = read_multipart_boundary(rs->get_stream());
|
|
Packit |
a4aae4 |
DBG(cerr << "MPM Boundary: " << boundary << endl);
|
|
Packit |
a4aae4 |
read_multipart_headers(rs->get_stream(), "text/xml", dods_ddx);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Parse the DDX, reading up to and including the next boundary.
|
|
Packit |
a4aae4 |
// Return the CID for the matching data part
|
|
Packit |
a4aae4 |
string data_cid;
|
|
Packit |
a4aae4 |
ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Munge the CID into something we can work with
|
|
Packit |
a4aae4 |
data_cid = cid_to_header_value(data_cid);
|
|
Packit |
a4aae4 |
DBG(cerr << "Data CID: " << data_cid << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read the data part's MPM part headers (boundary was read by
|
|
Packit |
a4aae4 |
// DDXParse::intern)
|
|
Packit |
a4aae4 |
read_multipart_headers(rs->get_stream(), "application/octet-stream", dap4_data, data_cid);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now read the data
|
|
Packit |
a4aae4 |
#if FILE_UN_MARSHALLER
|
|
Packit |
a4aae4 |
XDRFileUnMarshaller um(rs->get_stream());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fpistream in ( rs->get_stream() );
|
|
Packit |
a4aae4 |
XDRStreamUnMarshaller um( in );
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, &data);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_data:
|
|
Packit |
a4aae4 |
default: {
|
|
Packit |
a4aae4 |
// Parse the DDS; throw an exception on error.
|
|
Packit |
a4aae4 |
data.parse(rs->get_stream());
|
|
Packit |
a4aae4 |
#if FILE_UN_MARSHALLER
|
|
Packit |
a4aae4 |
XDRFileUnMarshaller um(rs->get_stream());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fpistream in ( rs->get_stream() );
|
|
Packit |
a4aae4 |
XDRStreamUnMarshaller um( in );
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
// Load the DDS with data.
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, &data);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This private method process data from both local and remote sources. It
|
|
Packit |
a4aae4 |
exists to eliminate duplication of code. */
|
|
Packit |
a4aae4 |
void Connect::process_data(DDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering Connect::process_data" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
data.set_dap_version(rs->get_protocol());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream()))
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse the Error object returned by the server!");
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// Web errors (those reported in the return document's MIME header)
|
|
Packit |
a4aae4 |
// are processed by the WWW library.
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__,
|
|
Packit |
a4aae4 |
"An error was reported by the remote web server; this should have been processed by HTTPConnect.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// FIXME: The following case is never used. There is no such response. jhrg 10/20/15
|
|
Packit |
a4aae4 |
// This code triggers a security warning from Coverity; since it is not used,
|
|
Packit |
a4aae4 |
// I have removed it. jhrg 5/5/16
|
|
Packit |
a4aae4 |
case dods_data_ddx: {
|
|
Packit |
a4aae4 |
// Parse the DDX; throw an exception on error.
|
|
Packit |
a4aae4 |
DDXParser ddx_parser(data.get_factory());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read the MPM boundary and then read the subsequent headers
|
|
Packit |
a4aae4 |
string boundary = read_multipart_boundary(rs->get_stream());
|
|
Packit |
a4aae4 |
DBG(cerr << "MPM Boundary: " << boundary << endl);
|
|
Packit |
a4aae4 |
read_multipart_headers(rs->get_stream(), "text/xml", dods_ddx);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Parse the DDX, reading up to and including the next boundary.
|
|
Packit |
a4aae4 |
// Return the CID for the matching data part
|
|
Packit |
a4aae4 |
string data_cid;
|
|
Packit |
a4aae4 |
ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Munge the CID into something we can work with
|
|
Packit |
a4aae4 |
data_cid = cid_to_header_value(data_cid);
|
|
Packit |
a4aae4 |
DBG(cerr << "Data CID: " << data_cid << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read the data part's MPM part headers (boundary was read by
|
|
Packit |
a4aae4 |
// DDXParse::intern)
|
|
Packit |
a4aae4 |
read_multipart_headers(rs->get_stream(), "application/octet-stream", dap4_data, data_cid);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now read the data
|
|
Packit |
a4aae4 |
XDRFileUnMarshaller um(rs->get_stream());
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, &data);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_data:
|
|
Packit |
a4aae4 |
default: {
|
|
Packit |
a4aae4 |
// Parse the DDS; throw an exception on error.
|
|
Packit |
a4aae4 |
data.parse(rs->get_stream());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XDRFileUnMarshaller um(rs->get_stream());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Load the DDS with data.
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, &data);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Barely a parser... This is used when reading from local sources of DODS
|
|
Packit |
a4aae4 |
// Data objects. It simulates the important actions of the libwww MIME header
|
|
Packit |
a4aae4 |
// parser. Those actions fill in certain fields in the Connect object. jhrg
|
|
Packit |
a4aae4 |
// 5/20/97
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Make sure that this parser reads from data_source without disturbing the
|
|
Packit |
a4aae4 |
// information in data_source that follows the MIME header. Since the DDS
|
|
Packit |
a4aae4 |
// (which follows the MIME header) is parsed by a flex/bison scanner/parser,
|
|
Packit |
a4aae4 |
// make sure to use I/O calls that will mesh with ANSI C I/O calls. In the
|
|
Packit |
a4aae4 |
// old GNU libg++, the C++ calls were synchronized with the C calls, but that
|
|
Packit |
a4aae4 |
// may no longer be the case. 5/31/99 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Use when you cannot use libcurl.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This method tests for MIME headers with lines terminated by CRLF
|
|
Packit |
a4aae4 |
(\r\n) and Newlines (\n). In either case, the line terminators are removed
|
|
Packit |
a4aae4 |
before each header is processed.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note FIXME The code uses tainted data via get_next_mime_header() whcih
|
|
Packit |
a4aae4 |
should be fixed. See the note in mime_util.cc
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param data_source Read from this stream.
|
|
Packit |
a4aae4 |
@param rs Value/Result parameter. Dump version and type information here.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void Connect::parse_mime(Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
rs->set_version("dods/0.0"); // initial value; for backward compatibility.
|
|
Packit |
a4aae4 |
rs->set_protocol("2.0");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
FILE *data_source = rs->get_stream();
|
|
Packit |
a4aae4 |
string mime = get_next_mime_header(data_source);
|
|
Packit |
a4aae4 |
while (!mime.empty()) {
|
|
Packit |
a4aae4 |
string header, value;
|
|
Packit |
a4aae4 |
parse_mime_header(mime, header, value);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Note that this is an ordered list
|
|
Packit |
a4aae4 |
if (header == "content-description:") {
|
|
Packit |
a4aae4 |
DBG(cout << header << ": " << value << endl);
|
|
Packit |
a4aae4 |
rs->set_type(get_description_type(value));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Use the value of xdods-server only if no other value has been read
|
|
Packit |
a4aae4 |
else if (header == "xdods-server:" && rs->get_version() == "dods/0.0") {
|
|
Packit |
a4aae4 |
DBG(cout << header << ": " << value << endl);
|
|
Packit |
a4aae4 |
rs->set_version(value);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// This trumps 'xdods-server' and 'server'
|
|
Packit |
a4aae4 |
else if (header == "xopendap-server:") {
|
|
Packit |
a4aae4 |
DBG(cout << header << ": " << value << endl);
|
|
Packit |
a4aae4 |
rs->set_version(value);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (header == "xdap:") {
|
|
Packit |
a4aae4 |
DBG(cout << header << ": " << value << endl);
|
|
Packit |
a4aae4 |
rs->set_protocol(value);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Only look for 'server' if no other header supplies this info.
|
|
Packit |
a4aae4 |
else if (rs->get_version() == "dods/0.0" && header == "server:") {
|
|
Packit |
a4aae4 |
DBG(cout << header << ": " << value << endl);
|
|
Packit |
a4aae4 |
rs->set_version(value);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
mime = get_next_mime_header(data_source);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// public mfuncs
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The Connect constructor requires a <tt>name</tt>, which is the URL to
|
|
Packit |
a4aae4 |
which the connection is to be made.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n The URL for the virtual connection.
|
|
Packit |
a4aae4 |
@param uname Use this username for authentication. Null by default.
|
|
Packit |
a4aae4 |
@param password Password to use for authentication. Null by default.
|
|
Packit |
a4aae4 |
@brief Create an instance of Connect. */
|
|
Packit |
a4aae4 |
Connect::Connect(const string &n, string uname, string password) :
|
|
Packit |
a4aae4 |
d_http(0), d_version("unknown"), d_protocol("2.0")
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = prune_spaces(n);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Figure out if the URL starts with 'http', if so, make sure that we
|
|
Packit |
a4aae4 |
// talk to an instance of HTTPConnect.
|
|
Packit |
a4aae4 |
if (name.find("http") == 0) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Connect: The identifier is an http URL" << endl);
|
|
Packit |
a4aae4 |
d_http = new HTTPConnect(RCReader::instance());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Find and store any CE given with the URL.
|
|
Packit |
a4aae4 |
string::size_type dotpos = name.find('?');
|
|
Packit |
a4aae4 |
if (dotpos != name.npos) {
|
|
Packit |
a4aae4 |
_URL = name.substr(0, dotpos);
|
|
Packit |
a4aae4 |
string expr = name.substr(dotpos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
dotpos = expr.find('&';;
|
|
Packit |
a4aae4 |
if (dotpos != expr.npos) {
|
|
Packit |
a4aae4 |
_proj = expr.substr(0, dotpos);
|
|
Packit |
a4aae4 |
_sel = expr.substr(dotpos); // XXX includes '&'
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
_proj = expr;
|
|
Packit |
a4aae4 |
_sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
_URL = name;
|
|
Packit |
a4aae4 |
_proj = "";
|
|
Packit |
a4aae4 |
_sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
_local = false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG(cerr << "Connect: The identifier is a local data source." << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_http = 0;
|
|
Packit |
a4aae4 |
_URL = "";
|
|
Packit |
a4aae4 |
_local = true; // local in this case means non-DAP
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
set_credentials(uname, password);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Connect::~Connect()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG2(cerr << "Entering the Connect dtor" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
delete d_http;
|
|
Packit |
a4aae4 |
d_http = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "Leaving the Connect dtor" << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get version information from the server. This is a new method which will
|
|
Packit |
a4aae4 |
ease the transition to DAP 4.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Use request_protocol() to get the DAP protocol version.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return The DAP version string.
|
|
Packit |
a4aae4 |
@see request_protocol() */
|
|
Packit |
a4aae4 |
string Connect::request_version()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string version_url = _URL + ".ver";
|
|
Packit |
a4aae4 |
if (_proj.length() + _sel.length())
|
|
Packit |
a4aae4 |
version_url = version_url + "?" + id2www_ce(_proj + _sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(version_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return d_version;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get protocol version information from the server. This is a new method
|
|
Packit |
a4aae4 |
which will ease the transition to DAP 4. Note that this method returns
|
|
Packit |
a4aae4 |
the version of the DAP protocol implemented by the server. The
|
|
Packit |
a4aae4 |
request_version() method returns the \e server's version number, not
|
|
Packit |
a4aae4 |
the DAP protocol version.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This method actually asks the server for the protocol version - use
|
|
Packit |
a4aae4 |
get_protocol() to get the protocol information from the most recent
|
|
Packit |
a4aae4 |
response (e.g., from the last DDX response returned by the server).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return The DAP protocol version string. */
|
|
Packit |
a4aae4 |
string Connect::request_protocol()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string version_url = _URL + ".ver";
|
|
Packit |
a4aae4 |
if (_proj.length() + _sel.length())
|
|
Packit |
a4aae4 |
version_url = version_url + "?" + id2www_ce(_proj + _sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(version_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return d_protocol;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DAS corresponding to the dataset in the Connect
|
|
Packit |
a4aae4 |
object's URL. Although DAP does not support using CEs with DAS
|
|
Packit |
a4aae4 |
requests, if present in the Connect object's instance, they will be
|
|
Packit |
a4aae4 |
escaped and passed as the query string of the request.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DAS from a server.
|
|
Packit |
a4aae4 |
@param das Result. */
|
|
Packit |
a4aae4 |
void Connect::request_das(DAS &das)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string das_url = _URL + ".das";
|
|
Packit |
a4aae4 |
if (_proj.length() + _sel.length())
|
|
Packit |
a4aae4 |
das_url = das_url + "?" + id2www_ce(_proj + _sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(das_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_das:
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
// DAS::parse throws an exception on error.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
das.parse(rs->get_stream()); // read and parse the das from a file
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DAS corresponding to the dataset in the Connect
|
|
Packit |
a4aae4 |
object's URL. Although DAP does not support using CEs with DAS
|
|
Packit |
a4aae4 |
requests, if present in the Connect object's instance, they will be
|
|
Packit |
a4aae4 |
escaped and passed as the query string of the request.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Different from request_das method in that this method uses the URL as
|
|
Packit |
a4aae4 |
given without attaching .das or projections or selections.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DAS from a server.
|
|
Packit |
a4aae4 |
@param das Result. */
|
|
Packit |
a4aae4 |
void Connect::request_das_url(DAS &das)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string use_url = _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(use_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_das:
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
// DAS::parse throws an exception on error.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
das.parse(rs->get_stream()); // read and parse the das from a file
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DDS corresponding to the dataset in the Connect object's URL.
|
|
Packit |
a4aae4 |
If present in the Connect object's instance, a CE will be escaped,
|
|
Packit |
a4aae4 |
combined with \c expr and passed as the query string of the request.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If you need the DDS to hold specializations of the type classes,
|
|
Packit |
a4aae4 |
be sure to include the factory class which will instantiate those
|
|
Packit |
a4aae4 |
specializations in the DDS. Either pass a pointer to the factory to
|
|
Packit |
a4aae4 |
DDS constructor or use the DDS::set_factory() method after the
|
|
Packit |
a4aae4 |
object is built.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DDS from a server.
|
|
Packit |
a4aae4 |
@param dds Result.
|
|
Packit |
a4aae4 |
@param expr Send this constraint expression to the server. */
|
|
Packit |
a4aae4 |
void Connect::request_dds(DDS &dds, string expr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string proj, sel;
|
|
Packit |
a4aae4 |
string::size_type dotpos = expr.find('&';;
|
|
Packit |
a4aae4 |
if (dotpos != expr.npos) {
|
|
Packit |
a4aae4 |
proj = expr.substr(0, dotpos);
|
|
Packit |
a4aae4 |
sel = expr.substr(dotpos);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
proj = expr;
|
|
Packit |
a4aae4 |
sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string dds_url = _URL + ".dds" + "?" + id2www_ce(_proj + proj + _sel + sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(dds_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_dds:
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
// DDS::prase throws an exception on error.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
dds.parse(rs->get_stream()); // read and parse the dds from a file
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DDS corresponding to the dataset in the Connect object's URL.
|
|
Packit |
a4aae4 |
If present in the Connect object's instance, a CE will be escaped,
|
|
Packit |
a4aae4 |
combined with \c expr and passed as the query string of the request.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Different from request_dds method above in that this method assumes
|
|
Packit |
a4aae4 |
URL is complete and does not add anything to the command, such as .dds
|
|
Packit |
a4aae4 |
or projections or selections.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If you need the DDS to hold specializations of the type classes,
|
|
Packit |
a4aae4 |
be sure to include the factory class which will instantiate those
|
|
Packit |
a4aae4 |
specializations in the DDS. Either pass a pointer to the factory to
|
|
Packit |
a4aae4 |
DDS constructor or use the DDS::set_factory() method after the
|
|
Packit |
a4aae4 |
object is built.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DDS from a server.
|
|
Packit |
a4aae4 |
@param dds Result. */
|
|
Packit |
a4aae4 |
void Connect::request_dds_url(DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string use_url = _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(use_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_dds:
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
// DDS::prase throws an exception on error.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
dds.parse(rs->get_stream()); // read and parse the dds from a file
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DDX corresponding to the dataset in the Connect object's URL.
|
|
Packit |
a4aae4 |
If present in the Connect object's instance, a CE will be escaped,
|
|
Packit |
a4aae4 |
combined with \c expr and passed as the query string of the request.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note A DDX is represented as XML on the wire but in memory libdap uses a
|
|
Packit |
a4aae4 |
DDS object with variables that hold their own attributes (the DDS itself holds
|
|
Packit |
a4aae4 |
the global attributes).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DDX from a server.
|
|
Packit |
a4aae4 |
@param dds Result.
|
|
Packit |
a4aae4 |
@param expr Send this constraint expression to the server. */
|
|
Packit |
a4aae4 |
void Connect::request_ddx(DDS &dds, string expr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string proj, sel;
|
|
Packit |
a4aae4 |
string::size_type dotpos = expr.find('&';;
|
|
Packit |
a4aae4 |
if (dotpos != expr.npos) {
|
|
Packit |
a4aae4 |
proj = expr.substr(0, dotpos);
|
|
Packit |
a4aae4 |
sel = expr.substr(dotpos);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
proj = expr;
|
|
Packit |
a4aae4 |
sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string ddx_url = _URL + ".ddx" + "?" + id2www_ce(_proj + proj + _sel + sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(ddx_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_ddx:
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
string blob;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDXParser ddxp(dds.get_factory());
|
|
Packit |
a4aae4 |
ddxp.intern_stream(rs->get_stream(), &dds, blob);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
ObjectType ot = rs->get_type();
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw Error("Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief The 'url' version of request_ddx
|
|
Packit |
a4aae4 |
@see Connect::request_ddx. */
|
|
Packit |
a4aae4 |
void Connect::request_ddx_url(DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string use_url = _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(use_url);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_error: {
|
|
Packit |
a4aae4 |
Error e;
|
|
Packit |
a4aae4 |
if (!e.parse(rs->get_stream())) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case web_error:
|
|
Packit |
a4aae4 |
// We should never get here; a web error should be picked up read_url
|
|
Packit |
a4aae4 |
// (called by fetch_url) and result in a thrown Error object.
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Web error.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_ddx:
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
string blob;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDXParser ddxp(dds.get_factory());
|
|
Packit |
a4aae4 |
ddxp.intern_stream(rs->get_stream(), &dds, blob);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default: {
|
|
Packit |
a4aae4 |
ObjectType ot = rs->get_type();
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
throw Error("Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DataDDS object corresponding to the dataset in the Connect
|
|
Packit |
a4aae4 |
object's URL. If present in the Connect object's instance, a CE will be
|
|
Packit |
a4aae4 |
escaped, combined with \c expr and passed as the query string of the
|
|
Packit |
a4aae4 |
request. The result is a DataDDS which contains the data values bound to
|
|
Packit |
a4aae4 |
variables.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If you need the DataDDS to hold specializations of the type classes,
|
|
Packit |
a4aae4 |
be sure to include the factory class which will instantiate those
|
|
Packit |
a4aae4 |
specializations in the DataDDS. Either pass a pointer to the factory to
|
|
Packit |
a4aae4 |
DataDDS constructor or use the DDS::set_factory() method after the
|
|
Packit |
a4aae4 |
object is built.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DAS from a server.
|
|
Packit |
a4aae4 |
@param data Result.
|
|
Packit |
a4aae4 |
@param expr Send this constraint expression to the server. */
|
|
Packit |
a4aae4 |
void Connect::request_data(DataDDS &data, string expr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string proj, sel;
|
|
Packit |
a4aae4 |
string::size_type dotpos = expr.find('&';;
|
|
Packit |
a4aae4 |
if (dotpos != expr.npos) {
|
|
Packit |
a4aae4 |
proj = expr.substr(0, dotpos);
|
|
Packit |
a4aae4 |
sel = expr.substr(dotpos);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
proj = expr;
|
|
Packit |
a4aae4 |
sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string data_url = _URL + ".dods?" + id2www_ce(_proj + proj + _sel + sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
// We need to catch Error exceptions to ensure calling close_output.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(data_url);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Reads the DataDDS object corresponding to the dataset in the Connect
|
|
Packit |
a4aae4 |
object's URL. If present in the Connect object's instance, a CE will be
|
|
Packit |
a4aae4 |
escaped, combined with \c expr and passed as the query string of the
|
|
Packit |
a4aae4 |
request. The result is a DataDDS which contains the data values bound to
|
|
Packit |
a4aae4 |
variables.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Different from request_data in that this method uses the syntax of the
|
|
Packit |
a4aae4 |
new OPeNDAP server commands using dispatch
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If you need the DataDDS to hold specializations of the type classes,
|
|
Packit |
a4aae4 |
be sure to include the factory class which will instantiate those
|
|
Packit |
a4aae4 |
specializations in the DataDDS. Either pass a pointer to the factory to
|
|
Packit |
a4aae4 |
DataDDS constructor or use the DDS::set_factory() method after the
|
|
Packit |
a4aae4 |
object is built.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the DAS from a server.
|
|
Packit |
a4aae4 |
@param data Result. */
|
|
Packit |
a4aae4 |
void Connect::request_data_url(DataDDS &data)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string use_url = _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
// We need to catch Error exceptions to ensure calling close_output.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(use_url);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// FIXME Unused?
|
|
Packit |
a4aae4 |
void Connect::request_data_ddx(DataDDS &data, string expr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string proj, sel;
|
|
Packit |
a4aae4 |
string::size_type dotpos = expr.find('&';;
|
|
Packit |
a4aae4 |
if (dotpos != expr.npos) {
|
|
Packit |
a4aae4 |
proj = expr.substr(0, dotpos);
|
|
Packit |
a4aae4 |
sel = expr.substr(dotpos);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
proj = expr;
|
|
Packit |
a4aae4 |
sel = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string data_url = _URL + ".dap?" + id2www_ce(_proj + proj + _sel + sel);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
// We need to catch Error exceptions to ensure calling close_output.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(data_url);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// FIXME Unused?
|
|
Packit |
a4aae4 |
void Connect::request_data_ddx_url(DataDDS &data)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string use_url = _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
Response *rs = 0;
|
|
Packit |
a4aae4 |
// We need to catch Error exceptions to ensure calling close_output.
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
rs = d_http->fetch_url(use_url);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
delete rs;
|
|
Packit |
a4aae4 |
rs = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Read data which is preceded by MIME headers.
|
|
Packit |
a4aae4 |
This method works for both data dds and data ddx responses.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If you need the DataDDS to hold specializations of the type classes,
|
|
Packit |
a4aae4 |
be sure to include the factory class which will instantiate those
|
|
Packit |
a4aae4 |
specializations in the DataDDS. Either pass a pointer to the factory to
|
|
Packit |
a4aae4 |
DataDDS constructor or use the DDS::set_factory() method after the
|
|
Packit |
a4aae4 |
object is built.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see read_data_no_mime()
|
|
Packit |
a4aae4 |
@param data Result.
|
|
Packit |
a4aae4 |
@param rs Read from this Response object. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void Connect::read_data(DataDDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!rs)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Response object is null.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read from data_source and parse the MIME headers specific to DAP2/4.
|
|
Packit |
a4aae4 |
parse_mime(rs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
read_data_no_mime(data, rs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Connect::read_data(DDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!rs)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Response object is null.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Read from data_source and parse the MIME headers specific to DAP2/4.
|
|
Packit |
a4aae4 |
parse_mime(rs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
read_data_no_mime(data, rs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This function looks at the input stream and makes its best guess at what
|
|
Packit |
a4aae4 |
// lies in store for downstream processing code. Definitely heuristic.
|
|
Packit |
a4aae4 |
// Assumptions:
|
|
Packit |
a4aae4 |
// #1 The current file position is past any MIME headers (if they were present).
|
|
Packit |
a4aae4 |
// #2 We must reset the FILE* position to the start of the DDS or DDX headers
|
|
Packit |
a4aae4 |
static void divine_type_information(Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Consume whitespace
|
|
Packit |
a4aae4 |
int c = getc(rs->get_stream());
|
|
Packit |
a4aae4 |
while (!feof(rs->get_stream()) && !ferror(rs->get_stream()) && isspace(c)) {
|
|
Packit |
a4aae4 |
c = getc(rs->get_stream());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (ferror(rs->get_stream()))
|
|
Packit |
a4aae4 |
throw Error("Error reading response type information: " + string(strerror(errno)));
|
|
Packit |
a4aae4 |
if (feof(rs->get_stream()))
|
|
Packit |
a4aae4 |
throw Error("Error reading response type information: Found EOF");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// The heuristic here is that a DataDDX is a multipart MIME document and
|
|
Packit |
a4aae4 |
// The first non space character found after the headers is the start of
|
|
Packit |
a4aae4 |
// the first part which looks like '--<boundary>' while a DataDDS starts
|
|
Packit |
a4aae4 |
// with a DDS (;Dataset {' ...). I take into account that our parsers have
|
|
Packit |
a4aae4 |
// accepted both 'Dataset' and 'dataset' for a long time.
|
|
Packit |
a4aae4 |
switch (c) {
|
|
Packit |
a4aae4 |
case '-':
|
|
Packit |
a4aae4 |
rs->set_type(dods_data_ddx);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
case 'D':
|
|
Packit |
a4aae4 |
case 'd':
|
|
Packit |
a4aae4 |
rs->set_type(dods_data);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not determine type of response object in stream.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ungetc(c, rs->get_stream());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Read data from a file which does not have response MIME headers.
|
|
Packit |
a4aae4 |
This method is a companion to read_data(). While read_data() assumes that
|
|
Packit |
a4aae4 |
the response has MIME headers, this method does not. If you call this
|
|
Packit |
a4aae4 |
with a Response that does contain headers, it will throw an Error (and
|
|
Packit |
a4aae4 |
the message is likely to be inscrutable).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This method will use the 'type' information in the Response object
|
|
Packit |
a4aae4 |
to choose between processing the response as a data dds or data ddx. If
|
|
Packit |
a4aae4 |
there is no type information, it will attempt to figure it out.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param data Result.
|
|
Packit |
a4aae4 |
@param rs Read from this Response object. */
|
|
Packit |
a4aae4 |
void Connect::read_data_no_mime(DataDDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (rs->get_type() == unknown_type)
|
|
Packit |
a4aae4 |
divine_type_information(rs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_data:
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
case dods_data_ddx:
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = data.get_protocol();
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
void Connect::read_data_no_mime(DDS &data, Response *rs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (rs->get_type() == unknown_type)
|
|
Packit |
a4aae4 |
divine_type_information(rs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
switch (rs->get_type()) {
|
|
Packit |
a4aae4 |
case dods_data:
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
d_protocol = rs->get_protocol();
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
case dods_data_ddx:
|
|
Packit |
a4aae4 |
process_data(data, rs);
|
|
Packit |
a4aae4 |
d_version = rs->get_version();
|
|
Packit |
a4aae4 |
// TODO should check to see if this hack is a correct replacement
|
|
Packit |
a4aae4 |
// for get_protocol from DataDDS
|
|
Packit |
a4aae4 |
d_protocol = data.get_dap_version();
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
Connect::is_local()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return _local;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return the Connect object's URL in a string. The URL was set by
|
|
Packit |
a4aae4 |
the class constructor, and may not be reset. If you want to
|
|
Packit |
a4aae4 |
open another URL, you must create another Connect object. There
|
|
Packit |
a4aae4 |
is a Connections class created to handle the management of
|
|
Packit |
a4aae4 |
multiple Connect objects.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the object's URL.
|
|
Packit |
a4aae4 |
@see Connections
|
|
Packit |
a4aae4 |
@return A string containing the URL of the data to which the
|
|
Packit |
a4aae4 |
Connect object refers. If the object refers to local data,
|
|
Packit |
a4aae4 |
the function returns the null string.
|
|
Packit |
a4aae4 |
@param ce If TRUE, the returned URL will include any constraint
|
|
Packit |
a4aae4 |
expression enclosed with the Connect object's URL (including the
|
|
Packit |
a4aae4 |
<tt>?</tt>). If FALSE, any constraint expression will be removed from
|
|
Packit |
a4aae4 |
the URL. The default is TRUE.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string Connect::URL(bool ce)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (_local)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "URL(): This call is only valid for a DAP data source.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (ce)
|
|
Packit |
a4aae4 |
return _URL + "?" + _proj + _sel;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return _URL;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return the constraint expression (CE) part of the Connect URL. Note
|
|
Packit |
a4aae4 |
that this CE is supplied as part of the URL passed to the
|
|
Packit |
a4aae4 |
Connect's constructor. It is not the CE passed to the
|
|
Packit |
a4aae4 |
<tt>request_data()</tt> function.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Get the Connect's constraint expression.
|
|
Packit |
a4aae4 |
@return A string containing the constraint expression (if any)
|
|
Packit |
a4aae4 |
submitted to the Connect object's constructor. */
|
|
Packit |
a4aae4 |
string Connect::CE()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (_local)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "CE(): This call is only valid for a DAP data source.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return _proj + _sel;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Set the credentials for responding to challenges while dereferencing
|
|
Packit |
a4aae4 |
URLs.
|
|
Packit |
a4aae4 |
@param u The username.
|
|
Packit |
a4aae4 |
@param p The password.
|
|
Packit |
a4aae4 |
@see extract_auth_info() */
|
|
Packit |
a4aae4 |
void Connect::set_credentials(string u, string p)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
d_http->set_credentials(u, p);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the \e accept deflate property.
|
|
Packit |
a4aae4 |
@param deflate True if the client can accept compressed responses, False
|
|
Packit |
a4aae4 |
otherwise. */
|
|
Packit |
a4aae4 |
void Connect::set_accept_deflate(bool deflate)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
d_http->set_accept_deflate(deflate);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the \e XDAP-Accept property/header. This is used to send to a server
|
|
Packit |
a4aae4 |
the (highest) DAP protocol version number that this client understands.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param major The client dap protocol major version
|
|
Packit |
a4aae4 |
@param minor The client dap protocol minor version */
|
|
Packit |
a4aae4 |
void Connect::set_xdap_protocol(int major, int minor)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
d_http->set_xdap_protocol(major, minor);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Disable any further use of the client-side cache. In a future version
|
|
Packit |
a4aae4 |
of this software, this should be handled so that the www library is
|
|
Packit |
a4aae4 |
not initialized with the cache running by default. */
|
|
Packit |
a4aae4 |
void Connect::set_cache_enabled(bool cache)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
d_http->set_cache_enabled(cache);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool Connect::is_cache_enabled()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bool status;
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec
|
|
Packit |
a4aae4 |
<< ")... ");
|
|
Packit |
a4aae4 |
if (d_http)
|
|
Packit |
a4aae4 |
status = d_http->is_cache_enabled();
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
status = false;
|
|
Packit |
a4aae4 |
DBGN(cerr << "exiting" << endl);
|
|
Packit |
a4aae4 |
return status;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|