OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
FFRequestHandler.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of ff_handler, a data handler for the OPeNDAP data
4 // server.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // FFRequestHandler.cc
26 
27 #include "config_ff.h"
28 
29 #include <iostream>
30 #include <string>
31 #include <sstream>
32 #include <exception>
33 
34 #include <DDS.h>
35 #include <DMR.h>
36 #include <D4BaseTypeFactory.h>
37 #include <Ancillary.h>
38 #include <Error.h>
39 #include <InternalErr.h>
40 #include <mime_util.h>
41 #include <escaping.h>
42 
43 #include <BESResponseHandler.h>
44 #include <BESResponseNames.h>
45 #include <BESDapNames.h>
46 #include <BESDASResponse.h>
47 #include <BESDDSResponse.h>
48 #include <BESDataDDSResponse.h>
49 #include <BESDMRResponse.h>
50 #include <BESVersionInfo.h>
51 
52 #include <BESDapError.h>
53 #include <BESInternalFatalError.h>
54 #include <BESDataNames.h>
55 #include <TheBESKeys.h>
56 #include <BESServiceRegistry.h>
57 #include <BESUtil.h>
58 #include <BESDebug.h>
59 #include <BESContextManager.h>
60 
61 #include "FFRequestHandler.h"
62 //#include "D4FFTypeFactory.h"
63 #include "ff_ce_functions.h"
64 #include "util_ff.h"
65 
66 using namespace std;
67 
68 #define FF_NAME "ff"
69 
70 long BufPtr = 0; // cache pointer
71 long BufSiz = 0; // Cache size
72 char *BufVal = NULL; // cache buffer
73 
74 extern void ff_read_descriptors(DDS & dds, const string & filename);
75 extern void ff_get_attributes(DAS & das, string filename);
76 
77 bool FFRequestHandler::d_RSS_format_support = false;
78 string FFRequestHandler::d_RSS_format_files = "";
79 
81  BESRequestHandler(name)
82 {
86 
89 
92 
94 
95  bool key_found = false;
96  string doset;
97  TheBESKeys::TheKeys()->get_value("FF.RSSFormatSupport", doset, key_found);
98  if (key_found) {
99  doset = BESUtil::lowercase(doset);
100  if (doset == "true" || doset == "yes")
101  FFRequestHandler::d_RSS_format_support = true;
102  else
103  FFRequestHandler::d_RSS_format_support = false;
104  }
105  else
106  FFRequestHandler::d_RSS_format_support = false;
107 
108  key_found = false;
109  string path;
110  TheBESKeys::TheKeys()->get_value("FF.RSSFormatFiles", path, key_found);
111  if (key_found)
112  FFRequestHandler::d_RSS_format_files = path;
113  else
114  FFRequestHandler::d_RSS_format_files = "";
115 
116  BESDEBUG("ff", "d_RSS_format_support: " << d_RSS_format_support << endl);
117  BESDEBUG("ff", "d_RSS_format_files: " << d_RSS_format_files << endl);
118 }
119 
121 {
122 }
123 
125 {
127  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(response);
128  if (!bdas)
129  throw BESInternalError("cast error", __FILE__, __LINE__);
130 
131  try {
133  DAS *das = bdas->get_das();
134 
135  string accessed = dhi.container->access();
136  ff_get_attributes(*das, accessed);
137 
138  string name;
140  name = find_ancillary_rss_das(accessed);
141  }
142  else {
143  name = Ancillary::find_ancillary_file(accessed, "das", "", "");
144  }
145 
146  struct stat st;
147  if (!name.empty() && (stat(name.c_str(), &st) == 0)) {
148  das->parse(name);
149  }
150 
151  bdas->clear_container();
152  } catch (InternalErr & e) {
153  BESDapError ex(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
154  throw ex;
155  } catch (Error & e) {
156  BESDapError ex(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
157  throw ex;
158  } catch (...) {
159  BESInternalFatalError ex("unknown exception caught building Freeform DAS", __FILE__, __LINE__);
160  throw ex;
161  }
162 
163  return true;
164 }
165 
167 {
169  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(response);
170  if (!bdds)
171  throw BESInternalError("cast error", __FILE__, __LINE__);
172 
173  try {
175  DDS *dds = bdds->get_dds();
176  string accessed = dhi.container->access();
177  dds->filename(accessed);
178 
179  BESDEBUG("ff", "FFRequestHandler::ff_build_dds, accessed: " << accessed << endl);
180 
181  ff_read_descriptors(*dds, accessed);
182 
183  BESDEBUG("ff", "FFRequestHandler::ff_build_dds, reading attributes" << endl);
184 
185  DAS *das = new DAS;
186  BESDASResponse bdas(das);
188  ff_get_attributes(*das, accessed);
189  Ancillary::read_ancillary_das(*das, accessed);
190 
191  BESDEBUG("ff", "FFRequestHandler::ff_build_dds, transferring attributes" << endl);
192 
193  dds->transfer_attributes(das);
194 
195  bdds->set_constraint(dhi);
196 
197  bdds->clear_container();
198 
199  } catch (InternalErr & e) {
200  BESDapError ex(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
201  throw ex;
202  } catch (Error & e) {
203  BESDapError ex(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
204  throw ex;
205  } catch (...) {
206  BESInternalFatalError ex("unknown exception caught building Freeform DDS", __FILE__, __LINE__);
207  throw ex;
208  }
209 
210  return true;
211 }
212 
214 {
215  BufPtr = 0; // cache pointer
216  BufSiz = 0; // Cache size
217  BufVal = NULL; // cache buffer
218 
220  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
221  if (!bdds)
222  throw BESInternalError("cast error", __FILE__, __LINE__);
223 
224  try {
226  DataDDS *dds = bdds->get_dds();
227  string accessed = dhi.container->access();
228  dds->filename(accessed);
229  ff_read_descriptors(*dds, accessed);
230  Ancillary::read_ancillary_dds(*dds, accessed);
231 
232  DAS *das = new DAS;
233  BESDASResponse bdas(das);
235  ff_get_attributes(*das, accessed);
236  Ancillary::read_ancillary_das(*das, accessed);
237 
238  dds->transfer_attributes(das);
239 
240  bdds->set_constraint(dhi);
241 
242  bdds->clear_container();
243  } catch (InternalErr & e) {
244  BESDapError ex(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
245  throw ex;
246  } catch (Error & e) {
247  BESDapError ex(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
248  throw ex;
249  } catch (...) {
250  BESInternalFatalError ex("unknown exception caught building Freeform DataDDS", __FILE__, __LINE__);
251  throw ex;
252  }
253 
254  return true;
255 }
256 
267 {
268  BufPtr = 0; // cache pointer
269  BufSiz = 0; // Cache size
270  BufVal = NULL; // cache buffer
271 
272  // Because this code does not yet know how to build a DMR directly, use
273  // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
274  // First step, build the 'full DDS'
275  string data_path = dhi.container->access();
276 
277  BaseTypeFactory factory;
278  DDS dds(&factory, name_path(data_path), "3.2");
279  dds.filename(data_path);
280 
281  try {
282  ff_read_descriptors(dds, data_path);
283  // ancillary DDS objects never took off - this does nothing. jhrg 8/12/14
284  // Ancillary::read_ancillary_dds(*dds, data_path);
285 
286  DAS das;
287  ff_get_attributes(das, data_path);
288  Ancillary::read_ancillary_das(das, data_path);
289  dds.transfer_attributes(&das);
290  }
291  catch (InternalErr &e) {
292  throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
293  }
294  catch (Error &e) {
295  throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
296  }
297  catch (...) {
298  throw BESDapError("Caught unknown error build FF DMR response", true, unknown_error, __FILE__, __LINE__);
299  }
300 
301  // Extract the DMR Response object - this holds the DMR used by the
302  // other parts of the framework.
304  BESDMRResponse &bdmr = dynamic_cast<BESDMRResponse &>(*response);
305 
306  // Extract the DMR Response object - this holds the DMR used by the
307  // other parts of the framework.
308  DMR *dmr = bdmr.get_dmr();
309  dmr->set_factory(new D4BaseTypeFactory);
310  dmr->build_using_dds(dds);
311 
312  // Instead of fiddling with the internal storage of the DHI object,
313  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
314  // methods to set the constraints. But, why? Maybe setting data[]
315  // directly is better? jhrg 8/14/14
316  bdmr.set_dap4_constraint(dhi);
317  bdmr.set_dap4_function(dhi);
318 
319  // What about async and store_result? See BESDapTransmit::send_dap4_data()
320 
321  return true;
322 }
323 
325 {
327  BESInfo *info = dynamic_cast<BESInfo *>(response);
328  if (!info)
329  throw BESInternalError("cast error", __FILE__, __LINE__);
330 
331  map < string, string > attrs;
332  attrs["name"] = MODULE_NAME ;
333  attrs["version"] = MODULE_VERSION ;
334 #if 0
335  attrs["name"] = PACKAGE_NAME;
336  attrs["version"] = PACKAGE_VERSION;
337 #endif
338  list < string > services;
340  if (services.size() > 0) {
341  string handles = BESUtil::implode(services, ',');
342  attrs["handles"] = handles;
343  }
344  info->begin_tag("module", &attrs);
345  info->end_tag("module");
346 
347  return true;
348 }
349 
351 {
353  BESVersionInfo *info = dynamic_cast<BESVersionInfo *>(response);
354  if (!info)
355  throw BESInternalError("cast error", __FILE__, __LINE__);
356 
357 #if 0
359 #endif
360  info->add_module(MODULE_NAME, MODULE_VERSION);
361 
362  return true;
363 }
char * BufVal
brief represents simple text information in a response object, such as version and help inforamtion...
#define DAP4DATA_RESPONSE
Definition: BESDapNames.h:86
static bool ff_build_dmr(BESDataHandlerInterface &dhi)
Build the DMR object.
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
#define DMR_RESPONSE
Definition: BESDapNames.h:81
string get_symbolic_name() const
retrieve the symbolic name for this container
Definition: BESContainer.h:197
static string lowercase(const string &s)
Convert a string to all lower case.
Definition: BESUtil.cc:182
Represents an OPeNDAP DDS DAP2 data object within the BES.
virtual void clear_container()
clear the container in the DAP response object
static bool ff_build_help(BESDataHandlerInterface &dhi)
STL namespace.
void ff_read_descriptors(DDS &dds, const string &filename)
Definition: ffdds.cc:71
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
void ff_get_attributes(DAS &das, string filename)
Definition: ffdas.cc:413
virtual string access()=0
returns the true name of this container
virtual void clear_container()
clear the container in the DAP response object
#define HELP_RESPONSE
virtual void set_dap4_function(BESDataHandlerInterface &dhi)
set the constraint depending on the context
informational response object
Definition: BESInfo.h:68
static string implode(const list< string > &values, char delim)
implode a list of values into a single string delimited by delim
Definition: BESUtil.cc:602
virtual BESResponseObject * get_response_object()
return the current response object
#define PACKAGE_NAME
Definition: config.h:244
#define DATA_RESPONSE
Definition: BESDapNames.h:70
static BESServiceRegistry * TheRegistry()
BESResponseHandler * response_handler
#define NULL
Definition: wcsUtil.h:65
virtual void set_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void begin_tag(const string &tag_name, map< string, string > *attrs=0)
Definition: BESInfo.cc:127
Represents an OPeNDAP DMR DAP4 data object within the BES.
virtual void set_container(const string &cn)
set the container in the DAP response object
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:51
virtual ~FFRequestHandler(void)
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
static bool ff_build_dds(BESDataHandlerInterface &dhi)
long BufSiz
virtual void clear_container()
clear the container in the DAP response object
Represents a specific data type request handler.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
Structure storing information used by the BES to handle the request.
static bool ff_build_data(BESDataHandlerInterface &dhi)
void ff_register_functions()
#define VERS_RESPONSE
static bool ff_build_version(BESDataHandlerInterface &dhi)
virtual void set_container(const string &cn)
set the container in the DAP response object
virtual bool add_handler(const string &handler_name, p_request_handler handler_method)
add a handler method to the request handler that knows how to fill in a specific response object ...
#define PACKAGE_VERSION
Definition: config.h:256
Represents an OPeNDAP DAS DAP2 data object within the BES.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:48
virtual void set_container(const string &cn)
set the container in the DAP response object
#define FF_NAME
static bool ff_build_das(BESDataHandlerInterface &dhi)
virtual void add_module(const string &n, const string &v)
Abstract base class representing a specific set of information in response to a request to the BES...
#define DDS_RESPONSE
Definition: BESDapNames.h:60
FFRequestHandler(const string &name)
BESContainer * container
pointer to current container in this interface
#define DAS_RESPONSE
Definition: BESDapNames.h:55
long BufPtr
virtual void end_tag(const string &tag_name)
Definition: BESInfo.cc:132
static bool get_RSS_format_support()
const string find_ancillary_rss_das(const string &dataset, const string &, const string &)
Find the RSS (Remote Sensing Systems) format file using their naming convention.
Definition: util_ff.cc:607
virtual void services_handled(const string &handler, list< string > &services)
returns the list of servies provided by the handler in question