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

Generated on Wed Mar 5 15:27:11 2008 for libdap++ by  doxygen 1.5.4