00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "config.h"
00037
00038 static char rcsid[] not_used =
00039 { "$Id: getdap.cc 19917 2008-11-25 23:47:56Z jimg $"
00040 };
00041
00042 #ifdef WIN32
00043 #include <io.h>
00044 #include <fcntl.h>
00045 #endif
00046
00047 #include <cstring>
00048 #include <string>
00049 #include <sstream>
00050
00051 #include "GetOpt.h"
00052
00053 #include "AISConnect.h"
00054 #include "Response.h"
00055 #include "StdinResponse.h"
00056
00057 using std::cerr;
00058 using std::endl;
00059 using std::flush;
00060
00061 using namespace libdap ;
00062
00063 const char *version = CVER " (" DVR " DAP/" DAP_PROTOCOL_VERSION ")";
00064
00065 extern int libdap::dods_keep_temps;
00066
00067 void usage(string name)
00068 {
00069 cerr << "Usage: " << name << endl;
00070 cerr <<
00071 " [idDaxAVvks] [-B <db>][-c <expr>][-m <num>] <url> [<url> ...]" <<
00072 endl;
00073 cerr << " [VvksM] <file> [<file> ...]" << endl;
00074 cerr << endl;
00075 cerr << "In the first form of the command, dereference the URL and"
00076 << endl;
00077 cerr << "perform the requested operations. This includes routing" <<
00078 endl;
00079 cerr << "the returned information through the DAP processing" << endl;
00080 cerr << "library (parsing the returned objects, et c.). If none" <<
00081 endl;
00082 cerr << "of a, d, or D are used with a URL, then the DAP library" <<
00083 endl;
00084 cerr << "routines are NOT used and the URLs contents are dumped" <<
00085 endl;
00086 cerr << "to standard output." << endl;
00087 cerr << endl;
00088 cerr << "In the second form of the command, assume the files are" <<
00089 endl;
00090 cerr << "DataDDS objects (stored in files or read from pipes)" << endl;
00091 cerr << "and process them as if -D were given. In this case the" <<
00092 endl;
00093 cerr << "information *must* contain valid MIME header in order" <<
00094 endl;
00095 cerr << "to be processed." << endl;
00096 cerr << endl;
00097 cerr << "Options:" << endl;
00098 cerr << " i: For each URL, get the server version." << endl;
00099 cerr << " d: For each URL, get the the DDS." << endl;
00100 cerr << " a: For each URL, get the the DAS." << endl;
00101 cerr << " A: Use the AIS for DAS objects." << endl;
00102 cerr << " D: For each URL, get the the DataDDS." << endl;
00103 cerr <<
00104 " x: For each URL, get the DDX object. Does not get data."
00105 << endl;
00106 cerr << " X: Build a DDX in getdap using the DDS and DAS." << endl;
00107 cerr << " B: <AIS xml dataBase>. Overrides .dodsrc." << endl;
00108 cerr << " v: Verbose." << endl;
00109 cerr << " V: Version." << endl;
00110 cerr << " c: <expr> is a constraint expression. Used with -D." <<
00111 endl;
00112 cerr << " NB: You can use a `?' for the CE also." << endl;
00113 cerr << " k: Keep temporary files created by libdap core" << endl;
00114 cerr << " m: Request the same URL <num> times." << endl;
00115 cerr << " z: Ask the server to compress data." << endl;
00116 cerr << " s: Print Sequences using numbered rows." << endl;
00117 cerr << " M: Assume data read from a file has no MIME headers" << endl;
00118 cerr << " (the default is to assume the headers are present)." << endl;
00119 }
00120
00121 bool read_data(FILE * fp)
00122 {
00123 if (!fp) {
00124 fprintf(stderr, "getdap: Whoa!!! Null stream pointer.\n");
00125 return false;
00126 }
00127
00128
00129
00130 char c;
00131 while (fp && !feof(fp) && fread(&c, 1, 1, fp))
00132 printf("%c", c);
00133
00134 return true;
00135 }
00136
00137 static void print_data(DDS & dds, bool print_rows = false)
00138 {
00139 cout << "The data:" << endl;
00140
00141 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++) {
00142 BaseType *v = *i;
00143 if (print_rows && (*i)->type() == dods_sequence_c)
00144 dynamic_cast < Sequence * >(*i)->print_val_by_rows(cout);
00145 else
00146 v->print_val(cout);
00147 }
00148
00149 cout << endl << flush;
00150 }
00151
00152 int main(int argc, char *argv[])
00153 {
00154 GetOpt getopt(argc, argv, "idaDxXAVvkB:c:m:zshM?Hp:");
00155 int option_char;
00156
00157 bool get_das = false;
00158 bool get_dds = false;
00159 bool get_data = false;
00160 bool get_ddx = false;
00161 bool build_ddx = false;
00162 bool get_version = false;
00163 bool cexpr = false;
00164 bool verbose = false;
00165 bool multi = false;
00166 bool accept_deflate = false;
00167 bool print_rows = false;
00168 bool use_ais = false;
00169 bool mime_headers = true;
00170 int times = 1;
00171 int dap_client_major = 2;
00172 int dap_client_minor = 0;
00173 string expr = "";
00174 string ais_db = "";
00175
00176 #ifdef WIN32
00177 _setmode(_fileno(stdout), _O_BINARY);
00178 #endif
00179
00180 while ((option_char = getopt()) != EOF)
00181 switch (option_char) {
00182 case 'd':
00183 get_dds = true;
00184 break;
00185 case 'a':
00186 get_das = true;
00187 break;
00188 case 'D':
00189 get_data = true;
00190 break;
00191 case 'x':
00192 get_ddx = true;
00193 break;
00194 case 'X':
00195 build_ddx = true;
00196 break;
00197 case 'A':
00198 use_ais = true;
00199 break;
00200 case 'V':
00201 fprintf(stderr, "getdap version: %s\n", version);
00202 exit(0);
00203 case 'i':
00204 get_version = true;
00205 break;
00206 case 'v':
00207 verbose = true;
00208 break;
00209 case 'k':
00210 dods_keep_temps = 1;
00211 break;
00212 case 'c':
00213 cexpr = true;
00214 expr = getopt.optarg;
00215 break;
00216 case 'm':
00217 multi = true;
00218 times = atoi(getopt.optarg);
00219 break;
00220 case 'B':
00221 use_ais = true;
00222 ais_db = getopt.optarg;
00223 break;
00224 case 'z':
00225 accept_deflate = true;
00226 break;
00227 case 's':
00228 print_rows = true;
00229 break;
00230 case 'M':
00231 mime_headers = false;
00232 break;
00233 case 'p': {
00234 istringstream iss(getopt.optarg);
00235 char dot;
00236 iss >> dap_client_major;
00237 iss >> dot;
00238 iss >> dap_client_minor;
00239 break;
00240 }
00241 case 'h':
00242 case '?':
00243 default:
00244 usage(argv[0]);
00245 exit(1);
00246 break;
00247 }
00248
00249 try {
00250
00251
00252 for (int i = getopt.optind; i < argc; ++i) {
00253 if (verbose)
00254 fprintf(stderr, "Fetching: %s\n", argv[i]);
00255
00256 string name = argv[i];
00257 Connect *url = 0;
00258 if (use_ais) {
00259 if (!ais_db.empty())
00260 url = new AISConnect(name, ais_db);
00261 else
00262 url = new AISConnect(name);
00263 }
00264 else {
00265 url = new Connect(name);
00266 }
00267
00268
00269 if (accept_deflate)
00270 url->set_accept_deflate(accept_deflate);
00271
00272 if (dap_client_major > 2)
00273 url->set_xdap_protocol(dap_client_major, dap_client_minor);
00274
00275 if (url->is_local()) {
00276 if (verbose) {
00277 fprintf(stderr,
00278 "Assuming that the argument %s is a file that contains a DAP2 data object; decoding.\n", argv[i]);
00279 }
00280
00281 Response *r = 0;
00282 BaseTypeFactory factory;
00283 DataDDS dds(&factory);
00284
00285 try {
00286 if (strcmp(argv[i], "-") == 0) {
00287 r = new StdinResponse(stdin);
00288
00289 if (!r->get_stream())
00290 throw Error("Could not open standard input.");
00291
00292 if (mime_headers)
00293 url->read_data(dds, r);
00294 else
00295 url->read_data_no_mime(dds, r);
00296 }
00297 else {
00298 r = new Response(fopen(argv[i], "r"), 0);
00299
00300 if (!r->get_stream())
00301 throw Error(string("The input source: ")
00302 + string(argv[i])
00303 + string(" could not be opened"));
00304
00305 url->read_data_no_mime(dds, r);
00306 }
00307 }
00308 catch (Error & e) {
00309 cerr << e.get_error_message() << endl;
00310 delete r;
00311 r = 0;
00312 delete url;
00313 url = 0;
00314 break;
00315 }
00316
00317 if (verbose)
00318 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00319 url->get_protocol().c_str(),
00320 url->get_version().c_str());
00321
00322 print_data(dds, print_rows);
00323
00324 }
00325
00326 else if (get_version) {
00327 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00328 url->request_protocol().c_str(),
00329 url->get_version().c_str());
00330 }
00331
00332 else if (get_das) {
00333 for (int j = 0; j < times; ++j) {
00334 DAS das;
00335 try {
00336 url->request_das(das);
00337 }
00338 catch (Error & e) {
00339 cerr << e.get_error_message() << endl;
00340 delete url;
00341 url = 0;
00342 continue;
00343 }
00344
00345 if (verbose) {
00346 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00347 url->get_protocol().c_str(),
00348 url->get_version().c_str());
00349
00350 fprintf(stderr, "DAS:\n");
00351 }
00352
00353 das.print(stdout);
00354 }
00355 }
00356
00357 else if (get_dds) {
00358 for (int j = 0; j < times; ++j) {
00359 BaseTypeFactory factory;
00360 DDS dds(&factory);
00361 try {
00362 url->request_dds(dds, expr);
00363 }
00364 catch (Error & e) {
00365 cerr << e.get_error_message() << endl;
00366 delete url;
00367 url = 0;
00368 continue;
00369 }
00370
00371 if (verbose) {
00372 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00373 url->get_protocol().c_str(),
00374 url->get_version().c_str());
00375
00376 fprintf(stderr, "DDS:\n");
00377 }
00378
00379 dds.print(cout);
00380 }
00381 }
00382
00383 else if (get_ddx) {
00384 for (int j = 0; j < times; ++j) {
00385 BaseTypeFactory factory;
00386 DDS dds(&factory);
00387 try {
00388 url->request_ddx(dds, expr);
00389 }
00390 catch (Error & e) {
00391 cerr << e.get_error_message() << endl;
00392 continue;
00393 }
00394
00395 if (verbose) {
00396 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00397 url->get_protocol().c_str(),
00398 url->get_version().c_str());
00399
00400 fprintf(stderr, "DDX:\n");
00401 }
00402
00403 dds.print_xml(cout, false, "getdap; no blob yet");
00404 }
00405 }
00406
00407 else if (build_ddx) {
00408 for (int j = 0; j < times; ++j) {
00409 BaseTypeFactory factory;
00410 DDS dds(&factory);
00411 try {
00412 url->request_dds(dds, expr);
00413 DAS das;
00414 url->request_das(das);
00415 dds.transfer_attributes(&das);
00416 }
00417 catch (Error & e) {
00418 cerr << e.get_error_message() << endl;
00419 continue;
00420 }
00421
00422 if (verbose) {
00423 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00424 url->get_protocol().c_str(),
00425 url->get_version().c_str());
00426
00427 fprintf(stderr, "Client-built DDX:\n");
00428 }
00429
00430 dds.print_xml(cout, false, "getdap; no blob yet");
00431 }
00432 }
00433
00434 else if (get_data) {
00435 for (int j = 0; j < times; ++j) {
00436 BaseTypeFactory factory;
00437 DataDDS dds(&factory);
00438 try {
00439 DBG(cerr << "URL: " << url->URL(false) << endl);
00440 DBG(cerr << "CE: " << expr << endl);
00441 url->request_data(dds, expr);
00442
00443 if (verbose)
00444 fprintf(stderr, "DAP version: %s, Server version: %s\n",
00445 url->get_protocol().c_str(),
00446 url->get_version().c_str());
00447
00448 print_data(dds, print_rows);
00449 }
00450 catch (Error & e) {
00451 cerr << e.get_error_message() << endl;
00452 delete url;
00453 url = 0;
00454 continue;
00455 }
00456 }
00457 }
00458
00459 else {
00460
00461
00462
00463
00464
00465 HTTPConnect http(RCReader::instance());
00466
00467
00468 if (accept_deflate)
00469 http.set_accept_deflate(accept_deflate);
00470
00471 if (dap_client_major > 2)
00472 url->set_xdap_protocol(dap_client_major, dap_client_minor);
00473
00474 string url_string = argv[i];
00475 for (int j = 0; j < times; ++j) {
00476 try {
00477 Response *r = http.fetch_url(url_string);
00478 if (!read_data(r->get_stream())) {
00479 continue;
00480 }
00481 delete r;
00482 r = 0;
00483 }
00484 catch (Error & e) {
00485 cerr << e.get_error_message() << endl;
00486 continue;
00487 }
00488 }
00489 }
00490
00491 delete url;
00492 url = 0;
00493 }
00494 }
00495 catch (Error &e) {
00496 cerr << e.get_error_message() << endl;
00497 return 1;
00498 }
00499 catch (exception &e) {
00500 cerr << "C++ library exception: " << e.what() << endl;
00501 return 1;
00502 }
00503
00504 return 0;
00505 }