53#include "D4BaseTypeFactory.h"
55#include "D4Sequence.h"
57#include "StdinResponse.h"
58#include "HTTPConnect.h"
64const char *version = CVER
" (" DVR
" DAP/" DAP_PROTOCOL_VERSION
")";
66extern int libdap::dods_keep_temps;
67extern int libdap::www_trace;
69static void usage(
const string &name)
71 cerr <<
"Usage: " << name << endl;
72 cerr <<
" [dD vVikmzstM][-c <expr>][-m <num>] <url> [<url> ...] | <file> [<file> ...]" << endl;
74 cerr <<
"In the first form of the command, dereference the URL and" << endl;
75 cerr <<
"perform the requested operations. This includes routing" << endl;
76 cerr <<
"the returned information through the DAP processing" << endl;
77 cerr <<
"library (parsing the returned objects, et c.). If none" << endl;
78 cerr <<
"of a, d, or D are used with a URL, then the DAP library" << endl;
79 cerr <<
"routines are NOT used and the URLs contents are dumped" << endl;
80 cerr <<
"to standard output." << endl;
81 cerr <<
"Note: If the URL contains a query string the query string" << endl;
82 cerr <<
"will be preserved in the request. However, if the query " << endl;
83 cerr <<
"string contains DAP4 keys they may interfere with the" << endl;
84 cerr <<
"operation of " << name <<
". A warning will be" << endl;
85 cerr <<
"written to stderr when "<< name <<
" identifies" << endl;
86 cerr <<
"the presence of a DAP4 query key in the submitted" << endl;
87 cerr <<
"URL's query string." << endl;
89 cerr <<
"In the second form of the command, assume the files are" << endl;
90 cerr <<
"DataDDS objects (stored in files or read from pipes)" << endl;
91 cerr <<
"and process them as if -D were given. In this case the" << endl;
92 cerr <<
"information *must* contain valid MIME header in order" << endl;
93 cerr <<
"to be processed." << endl;
95 cerr <<
"Options:" << endl;
96 cerr <<
" d: For each URL, get the (DAP4) DMR object. Does not get data." << endl;
97 cerr <<
" D: For each URL, get the DAP4 Data response." << endl;
99 cerr <<
" v: Verbose output." << endl;
100 cerr <<
" V: Version of this client; see 'i' for server version." << endl;
101 cerr <<
" i: For each URL, get the server version." << endl;
103 cerr <<
" m: Request the same URL <num> times." << endl;
104 cerr <<
" z: Ask the server to compress data." << endl;
105 cerr <<
" s: Print Sequences using numbered rows." << endl;
107 cerr <<
" M: Assume data read from a file has no MIME headers; use only with files" << endl;
109 cerr <<
" c: <expr> is a constraint expression. Used with -d/D" << endl;
110 cerr <<
" NB: You can use a `?' for the CE also." << endl;
111 cerr <<
" S: Used in conjunction with -d and will report the total size of the data "
112 "referenced in the DMR." << endl;
116bool read_data(FILE * fp)
119 fprintf(stderr,
"getdap4: Whoa!!! Null stream pointer.\n");
126 while (fp && !feof(fp) && fread(&c, 1, 1, fp))
132static void read_response_from_file(
D4Connect *url,
DMR &dmr,
Response &r,
bool mime_headers,
bool get_dap4_data,
bool get_dmr)
136 url->read_data(dmr, r);
138 url->read_dmr(dmr, r);
140 throw Error(
"Only supports Data or DMR responses");
144 url->read_data_no_mime(dmr, r);
146 url->read_dmr_no_mime(dmr, r);
148 throw Error(
"Only supports Data or DMR responses");
152static void print_group_data(
D4Group *g,
bool print_rows =
false)
154 for (Constructor::Vars_iter i = g->
var_begin(), e = g->
var_end(); i != e; i++) {
155 if (print_rows && (*i)->type() == dods_sequence_c)
156 dynamic_cast<D4Sequence &
>(**i).print_val_by_rows(cout);
158 (*i)->print_val(cout);
161 for (D4Group::groupsIter gi = g->
grp_begin(), ge = g->
grp_end(); gi != ge; ++gi) {
162 print_group_data(*gi, print_rows);
166static void print_data(
DMR &dmr,
bool print_rows =
false)
168 cout <<
"The data:" << endl;
172 print_group_data(g, print_rows);
174 cout << endl << flush;
187unsigned long long get_size(
D4Group *grp,
bool constrained=
false)
189 unsigned long long w = 0;
191 for (
auto var_itr = grp->
var_begin(); var_itr != grp->
var_end(); var_itr++) {
193 if ((*var_itr)->send_p())
194 w += (*var_itr)->width(constrained);
197 w += (*var_itr)->width(constrained);
201 w += get_size(*grp_itr,constrained);
207unsigned long long get_size(
DMR &dmr,
bool constrained=
false)
209 return get_size(dmr.
root(),constrained);
213int main(
int argc,
char *argv[])
215 GetOpt getopt(argc, argv,
"[dDvVikrm:Mzstc:S]");
218 bool get_dmr =
false;
219 bool get_dap4_data =
false;
220 bool get_version =
false;
222 bool verbose =
false;
224 bool accept_deflate =
false;
225 bool print_rows =
false;
226 bool mime_headers =
true;
227 bool report_errors =
false;
229 int dap_client_major = 4;
230 int dap_client_minor = 0;
232 bool compute_size =
false;
235 _setmode(_fileno(stdout), _O_BINARY);
238 while ((option_char = getopt()) != -1)
239 switch (option_char) {
244 get_dap4_data =
true;
250 cerr <<
"getdap4 version: " << version << endl;
264 report_errors =
true;
268 times = atoi(getopt.optarg);
271 accept_deflate =
true;
277 mime_headers =
false;
286 expr = getopt.optarg;
298 for (
int i = getopt.optind; i < argc; ++i) {
300 cerr <<
"Fetching: " << argv[i] << endl;
302 string name = argv[i];
311 if (dap_client_major > 2)
314 if (url->is_local()) {
316 cerr <<
"Assuming " << argv[i] <<
" is a file that contains a response object; decoding." << endl;
322 if (strcmp(argv[i],
"-") == 0) {
325 if (!r.get_cpp_stream())
326 throw Error(
"Could not open standard input.");
328 read_response_from_file(url, dmr, r, mime_headers, get_dap4_data, get_dmr);
331 fstream f(argv[i], std::ios_base::in);
332 if (!f.is_open() || f.bad() || f.eof())
333 throw Error((
string)
"Could not open: " + argv[i]);
337 read_response_from_file(url, dmr, r, mime_headers, get_dap4_data, get_dmr);
341 cerr <<
"DAP version: " << url->
get_protocol().c_str() <<
" Server version: "
347 cout << xml.get_doc() << endl;
350 print_data(dmr, print_rows);
360 for (
int j = 0; j < times; ++j) {
364 url->request_dmr(dmr, expr);
368 cout <<
"DMR:" << endl;
373 cout << xml.get_doc() << endl;
375 cout <<
"DMR References " << get_size(dmr) <<
" bytes of data," << endl;
386 else if (get_dap4_data) {
387 for (
int j = 0; j < times; ++j) {
391 url->request_dap4_data(dmr, expr);
395 cout <<
"DMR:" << endl;
400 cout << xml.get_doc() << endl;
402 print_data(dmr, print_rows);
417 http.set_accept_deflate(accept_deflate);
419 if (dap_client_major > 2)
422 string url_string = argv[i];
423 for (
int j = 0; j < times; ++j) {
427 vector<string> *headers = r->get_headers();
428 copy(headers->begin(), headers->end(), ostream_iterator<string>(cout,
"\n"));
430 if (!read_data(r->get_stream())) {
446 else if (get_version) {
447 fprintf(stderr,
"DAP version: %s, Server version: %s\n",
448 url->request_protocol().c_str(),
467 cerr <<
"Exiting." << endl;
471 catch (exception &e) {
472 cerr <<
"C++ library exception: " << e.what() << endl;
473 cerr <<
"Exiting." << endl;
std::string get_protocol()
void set_accept_deflate(bool deflate)
void set_xdap_protocol(int major, int minor)
std::string get_version()
groupsIter grp_begin()
Get an iterator to the start of the values.
groupsIter grp_end()
Get an iterator to the end of the values.
void print_dap4(XMLWriter &xml, bool constrained=false)
A class for error processing.
ErrorCode get_error_code() const
std::string get_error_message() const
Encapsulate a response read from stdin.
top level DAP object to house generic methods