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

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7