getdap.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 //
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 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;     // defined in HTTPResponse.h
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     // Changed from a loop that used getc() to one that uses fread(). getc()
00128     // worked fine for transfers of text information, but *not* for binary
00129     // transfers. fread() will handle both.
00130     char c;
00131     while (fp && !feof(fp) && fread(&c, 1, 1, fp))
00132         printf("%c", c);        // stick with stdio
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;              // keep_temp is in Connect.cc
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         // If after processing all the command line options there is nothing
00251         // left (no URL or file) assume that we should read from stdin.
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             // This overrides the value set in the .dodsrc file.
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); // The default case
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;       // Goto the next URL or exit the loop.
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;       // Goto the next URL or exit the loop.
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;       // Goto the next URL or exit the loop.
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                 // if (!get_das && !get_dds && !get_data) This code uses
00461                 // HTTPConnect::fetch_url which cannot be accessed using an
00462                 // instance of Connect. So some of the options supported by
00463                 // other URLs won't work here (e.g., the verbose option
00464                 // doesn't show the server version number).
00465                 HTTPConnect http(RCReader::instance());
00466 
00467                 // This overrides the value set in the .dodsrc file.
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 }

Generated on Mon May 18 10:25:03 2009 for libdap++ by  doxygen 1.4.7