libdap
Updated for version 3.17.0
|
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 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1997-1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 // This is the source to `getdap'; a simple tool to exercise the Connect 00033 // class. It can be used to get naked URLs as well as the DAP2 DAS and DDS 00034 // objects. jhrg. 00035 00036 #include "config.h" 00037 00038 #ifdef WIN32 00039 #include <io.h> 00040 #include <fcntl.h> 00041 #endif 00042 00043 #include <cstring> 00044 #include <string> 00045 #include <sstream> 00046 00047 #include "GetOpt.h" 00048 00049 #include "DMR.h" 00050 #include "XMLWriter.h" 00051 #include "D4BaseTypeFactory.h" 00052 #include "D4Group.h" 00053 #include "D4Sequence.h" 00054 #include "D4Connect.h" 00055 #include "StdinResponse.h" 00056 #include "HTTPConnect.h" 00057 #include "RCReader.h" 00058 00059 using namespace std; 00060 using namespace libdap ; 00061 00062 const char *version = CVER " (" DVR " DAP/" DAP_PROTOCOL_VERSION ")"; 00063 #if 0 00064 extern int libdap::dods_keep_temps; // defined in HTTPResponse.h 00065 extern int libdap::www_trace; 00066 #endif 00067 static void usage(const string &name) 00068 { 00069 cerr << "Usage: " << name << endl; 00070 cerr << " [dD vVikmzstM][-c <expr>][-m <num>] <url> [<url> ...] | <file> [<file> ...]" << endl; 00071 cerr << endl; 00072 cerr << "In the first form of the command, dereference the URL and" << endl; 00073 cerr << "perform the requested operations. This includes routing" << endl; 00074 cerr << "the returned information through the DAP processing" << endl; 00075 cerr << "library (parsing the returned objects, et c.). If none" << endl; 00076 cerr << "of a, d, or D are used with a URL, then the DAP library" << endl; 00077 cerr << "routines are NOT used and the URLs contents are dumped" << endl; 00078 cerr << "to standard output." << endl; 00079 cerr << endl; 00080 cerr << "In the second form of the command, assume the files are" << endl; 00081 cerr << "DataDDS objects (stored in files or read from pipes)" << endl; 00082 cerr << "and process them as if -D were given. In this case the" << endl; 00083 cerr << "information *must* contain valid MIME header in order" << endl; 00084 cerr << "to be processed." << endl; 00085 cerr << endl; 00086 cerr << "Options:" << endl; 00087 cerr << " d: For each URL, get the (DAP4) DMR object. Does not get data." << endl; 00088 cerr << " D: For each URL, get the DAP4 Data response." << endl; 00089 cerr << endl; 00090 cerr << " v: Verbose output." << endl; 00091 cerr << " V: Version of this client; see 'i' for server version." << endl; 00092 cerr << " i: For each URL, get the server version." << endl; 00093 cerr << " k: Keep temporary files created by libdap." << endl; 00094 cerr << " m: Request the same URL <num> times." << endl; 00095 cerr << " z: Ask the server to compress data." << endl; 00096 cerr << " s: Print Sequences using numbered rows." << endl; 00097 cerr << " t: Trace www accesses." << endl; 00098 cerr << " M: Assume data read from a file has no MIME headers; use only with files" << endl; 00099 cerr << endl; 00100 cerr << " c: <expr> is a constraint expression. Used with -d/D" << endl; 00101 cerr << " NB: You can use a `?' for the CE also." << endl; 00102 } 00103 00104 // Used for raw http access/transfer 00105 bool read_data(FILE * fp) 00106 { 00107 if (!fp) { 00108 fprintf(stderr, "getdap4: Whoa!!! Null stream pointer.\n"); 00109 return false; 00110 } 00111 // Changed from a loop that used getc() to one that uses fread(). getc() 00112 // worked fine for transfers of text information, but *not* for binary 00113 // transfers. fread() will handle both. 00114 char c; 00115 while (fp && !feof(fp) && fread(&c, 1, 1, fp)) 00116 printf("%c", c); // stick with stdio 00117 00118 return true; 00119 } 00120 00121 static void read_response_from_file(D4Connect *url, DMR &dmr, Response &r, bool mime_headers, bool get_dap4_data, bool get_dmr) 00122 { 00123 if (mime_headers) { 00124 if (get_dap4_data) 00125 url->read_data(dmr, r); 00126 else if (get_dmr) 00127 url->read_dmr(dmr, r); 00128 else 00129 throw Error("Only supports Data or DMR responses"); 00130 } 00131 else { 00132 if (get_dap4_data) 00133 url->read_data_no_mime(dmr, r); 00134 else if (get_dmr) 00135 url->read_dmr_no_mime(dmr, r); 00136 else 00137 throw Error("Only supports Data or DMR responses"); 00138 } 00139 } 00140 00141 static void print_group_data(D4Group *g, bool print_rows = false) 00142 { 00143 for (Constructor::Vars_iter i = g->var_begin(), e = g->var_end(); i != e; i++) { 00144 if (print_rows && (*i)->type() == dods_sequence_c) 00145 dynamic_cast<D4Sequence &>(**i).print_val_by_rows(cout); 00146 else 00147 (*i)->print_val(cout); 00148 } 00149 00150 for (D4Group::groupsIter gi = g->grp_begin(), ge = g->grp_end(); gi != ge; ++gi) { 00151 print_group_data(*gi, print_rows); 00152 } 00153 } 00154 00155 static void print_data(DMR &dmr, bool print_rows = false) 00156 { 00157 cout << "The data:" << endl; 00158 00159 D4Group *g = dmr.root(); 00160 00161 print_group_data(g, print_rows); 00162 00163 cout << endl << flush; 00164 } 00165 00166 int main(int argc, char *argv[]) 00167 { 00168 GetOpt getopt(argc, argv, "[dDvVikrm:Mzstc:]"); 00169 int option_char; 00170 00171 bool get_dmr = false; 00172 bool get_dap4_data = false; 00173 bool get_version = false; 00174 bool cexpr = false; 00175 bool verbose = false; 00176 bool multi = false; 00177 bool accept_deflate = false; 00178 bool print_rows = false; 00179 bool mime_headers = true; 00180 bool report_errors = false; 00181 int times = 1; 00182 int dap_client_major = 4; 00183 int dap_client_minor = 0; 00184 string expr = ""; 00185 00186 #ifdef WIN32 00187 _setmode(_fileno(stdout), _O_BINARY); 00188 #endif 00189 00190 while ((option_char = getopt()) != -1) 00191 switch (option_char) { 00192 case 'd': 00193 get_dmr = true; 00194 break; 00195 case 'D': 00196 get_dap4_data = true; 00197 break; 00198 case 'v': 00199 verbose = true; 00200 break; 00201 case 'V': 00202 cerr << "getdap4 version: " << version << endl; 00203 exit(0); 00204 case 'i': 00205 get_version = true; 00206 break; 00207 #if 0 00208 case 'k': 00209 dods_keep_temps = 1; 00210 break; // keep_temp is in Connect.cc 00211 #endif 00212 case 'r': 00213 report_errors = true; 00214 break; 00215 case 'm': 00216 multi = true; 00217 times = atoi(getopt.optarg); 00218 break; 00219 case 'z': 00220 accept_deflate = true; 00221 break; 00222 case 's': 00223 print_rows = true; 00224 break; 00225 case 'M': 00226 mime_headers = false; 00227 break; 00228 #if 0 00229 case 't': 00230 www_trace = 1; 00231 break; 00232 #endif 00233 case 'c': 00234 cexpr = true; 00235 expr = getopt.optarg; 00236 break; 00237 case 'h': 00238 case '?': 00239 default: 00240 usage(argv[0]); 00241 exit(1); 00242 break; 00243 } 00244 00245 try { 00246 // If after processing all the command line options there is nothing 00247 // left (no URL or file) assume that we should read from stdin. 00248 for (int i = getopt.optind; i < argc; ++i) { 00249 if (verbose) 00250 cerr << "Fetching: " << argv[i] << endl; 00251 00252 string name = argv[i]; 00253 D4Connect *url = 0; 00254 // auto_ptr? jhrg 10/19/15 00255 url = new D4Connect(name); 00256 00257 // This overrides the value set in the .dodsrc file. 00258 if (accept_deflate) 00259 url->set_accept_deflate(accept_deflate); 00260 00261 if (dap_client_major > 2) 00262 url->set_xdap_protocol(dap_client_major, dap_client_minor); 00263 00264 if (url->is_local()) { 00265 if (verbose) 00266 cerr << "Assuming " << argv[i] << " is a file that contains a response object; decoding." << endl; 00267 00268 try { 00269 D4BaseTypeFactory factory; 00270 DMR dmr(&factory); 00271 00272 if (strcmp(argv[i], "-") == 0) { 00273 StdinResponse r(cin); 00274 00275 if (!r.get_cpp_stream()) 00276 throw Error("Could not open standard input."); 00277 00278 read_response_from_file(url, dmr, r, mime_headers, get_dap4_data, get_dmr); 00279 } 00280 else { 00281 fstream f(argv[i], std::ios_base::in); 00282 if (!f.is_open() || f.bad() || f.eof()) 00283 throw Error((string)"Could not open: " + argv[i]); 00284 00285 Response r(&f, 0); 00286 00287 read_response_from_file(url, dmr, r, mime_headers, get_dap4_data, get_dmr); 00288 } 00289 00290 if (verbose) 00291 cerr << "DAP version: " << url->get_protocol().c_str() << " Server version: " 00292 << url->get_version().c_str() << endl; 00293 00294 // Always write the DMR 00295 XMLWriter xml; 00296 dmr.print_dap4(xml); 00297 cout << xml.get_doc() << endl; 00298 00299 if (get_dap4_data) 00300 print_data(dmr, print_rows); 00301 } 00302 catch (Error & e) { 00303 cerr << "Error: " << e.get_error_message() << endl; 00304 delete url; url = 0; 00305 if (report_errors) 00306 return EXIT_FAILURE; 00307 } 00308 } 00309 else if (get_dmr) { 00310 for (int j = 0; j < times; ++j) { 00311 D4BaseTypeFactory factory; 00312 DMR dmr(&factory); 00313 try { 00314 url->request_dmr(dmr, expr); 00315 00316 if (verbose) { 00317 cout << "DAP version: " << url->get_protocol() << ", Server version: " << url->get_version() << endl; 00318 cout << "DMR:" << endl; 00319 } 00320 00321 XMLWriter xml; 00322 dmr.print_dap4(xml); 00323 cout << xml.get_doc() << endl; 00324 } 00325 catch (Error & e) { 00326 cerr << e.get_error_message() << endl; 00327 if (report_errors) 00328 return EXIT_FAILURE; 00329 continue; // Goto the next URL or exit the loop. 00330 } 00331 } 00332 } 00333 else if (get_dap4_data) { 00334 for (int j = 0; j < times; ++j) { 00335 D4BaseTypeFactory factory; 00336 DMR dmr(&factory); 00337 try { 00338 url->request_dap4_data(dmr, expr); 00339 00340 if (verbose) { 00341 cout << "DAP version: " << url->get_protocol() << ", Server version: " << url->get_version() << endl; 00342 cout << "DMR:" << endl; 00343 } 00344 00345 XMLWriter xml; 00346 dmr.print_dap4(xml); 00347 cout << xml.get_doc() << endl; 00348 00349 print_data(dmr, print_rows); 00350 } 00351 catch (Error & e) { 00352 cerr << e.get_error_message() << endl; 00353 if (report_errors) 00354 return EXIT_FAILURE; 00355 continue; // Goto the next URL or exit the loop. 00356 } 00357 } 00358 } 00359 else { 00360 HTTPConnect http(RCReader::instance()); 00361 00362 // This overrides the value set in the .dodsrc file. 00363 if (accept_deflate) 00364 http.set_accept_deflate(accept_deflate); 00365 00366 if (dap_client_major > 2) 00367 url->set_xdap_protocol(dap_client_major, dap_client_minor); 00368 00369 string url_string = argv[i]; 00370 for (int j = 0; j < times; ++j) { 00371 try { 00372 HTTPResponse *r = http.fetch_url(url_string); 00373 if (verbose) { 00374 vector<string> *headers = r->get_headers(); 00375 copy(headers->begin(), headers->end(), ostream_iterator<string>(cout, "\n")); 00376 } 00377 if (!read_data(r->get_stream())) { 00378 continue; 00379 } 00380 delete r; 00381 r = 0; 00382 } 00383 catch (Error & e) { 00384 cerr << e.get_error_message() << endl; 00385 if (report_errors) 00386 return EXIT_FAILURE; 00387 continue; 00388 } 00389 } 00390 } 00391 00392 #if 0 00393 else if (get_version) { 00394 fprintf(stderr, "DAP version: %s, Server version: %s\n", 00395 url->request_protocol().c_str(), 00396 url->get_version().c_str()); 00397 } 00398 #endif 00399 00400 delete url; url = 0; 00401 } 00402 } 00403 catch (Error &e) { 00404 cerr << "Error: " << e.get_error_message() << endl; 00405 cerr << "exiting" << endl; 00406 return 1; 00407 } 00408 catch (exception &e) { 00409 cerr << "C++ library exception: " << e.what() << endl; 00410 cerr << "exiting" << endl; 00411 return 1; 00412 } 00413 00414 return 0; 00415 }