OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
FoDapJsonTransmitter.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 //
3 // FoDapJsonTransmitter.cc
4 //
5 // This file is part of BES JSON File Out Module
6 //
7 // Copyright (c) 2014 OPeNDAP, Inc.
8 // Author: Nathan Potter <ndp@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 // (c) COPYRIGHT URI/MIT 1995-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 
29 #include "config.h"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 
38 #include <sys/types.h> // For umask
39 #include <sys/stat.h>
40 
41 #include <iostream>
42 #include <fstream>
43 
44 #include <DataDDS.h>
45 #include <BaseType.h>
46 #include <escaping.h>
47 #include <ConstraintEvaluator.h>
48 
49 #include <BESInternalError.h>
50 #include <TheBESKeys.h>
51 #include <BESContextManager.h>
52 #include <BESDataDDSResponse.h>
53 #include <BESDDSResponse.h>
54 #include <BESDapNames.h>
55 #include <BESDataNames.h>
56 #include <BESDebug.h>
57 
58 #include "FoDapJsonTransmitter.h"
59 #include "FoDapJsonTransform.h"
60 
61 
62 using namespace ::libdap;
63 
64 #define FO_JSON_TEMP_DIR "/tmp"
65 
66 string FoDapJsonTransmitter::temp_dir;
67 
80 {
83 
84  if (FoDapJsonTransmitter::temp_dir.empty()) {
85  // Where is the temp directory for creating these files
86  bool found = false;
87  string key = "FoJson.Tempdir";
88  TheBESKeys::TheKeys()->get_value(key, FoDapJsonTransmitter::temp_dir, found);
89  if (!found || FoDapJsonTransmitter::temp_dir.empty()) {
90  FoDapJsonTransmitter::temp_dir = FO_JSON_TEMP_DIR;
91  }
92  string::size_type len = FoDapJsonTransmitter::temp_dir.length();
93  if (FoDapJsonTransmitter::temp_dir[len - 1] == '/') {
94  FoDapJsonTransmitter::temp_dir = FoDapJsonTransmitter::temp_dir.substr(0, len - 1);
95  }
96  }
97 }
98 
115 {
116  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
117  if (!bdds)
118  throw BESInternalError("cast error", __FILE__, __LINE__);
119 
120  DataDDS *dds = bdds->get_dds();
121  if (!dds)
122  throw BESInternalError("No DataDDS has been created for transmit", __FILE__, __LINE__);
123 
124  BESDEBUG("fojson", "FoDapJsonTransmitter::send_data - parsing the constraint" << endl);
125 
126  ConstraintEvaluator &eval = bdds->get_ce();
127 
128  ostream &o_strm = dhi.get_output_stream();
129  if (!o_strm)
130  throw BESInternalError("Output stream is not set, can not return as JSON", __FILE__, __LINE__);
131 
132  // ticket 1248 jhrg 2/23/09
133  string ce = www2id(dhi.data[POST_CONSTRAINT], "%", "%20%26");
134  try {
135  eval.parse_constraint(ce, *dds);
136  }
137  catch (Error &e) {
138  throw BESInternalError("Failed to parse the constraint expression: " + e.get_error_message(), __FILE__, __LINE__);
139  }
140  catch (...) {
141  throw BESInternalError("Failed to parse the constraint expression: Unknown exception caught", __FILE__, __LINE__);
142  }
143 
144  // now we need to read the data
145  BESDEBUG("fojson", "FoDapJsonTransmitter::send_data - reading data into DataDDS" << endl);
146 
147  try {
148  // Handle *functional* constraint expressions specially
149  if (eval.function_clauses()) {
150  BESDEBUG("fojson", "processing a functional constraint clause(s)." << endl);
151  DataDDS *tmp_dds = eval.eval_function_clauses(*dds);
152  bdds->set_dds(tmp_dds);
153  delete dds;
154  dds = tmp_dds;
155  }
156  else {
157  // Iterate through the variables in the DataDDS and read
158  // in the data if the variable has the send flag set.
159  for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
160  if ((*i)->send_p()) {
161  (*i)->intern_data(eval, *dds);
162  }
163  }
164  }
165  }
166  catch (Error &e) {
167  throw BESInternalError("Failed to read data: " + e.get_error_message(), __FILE__, __LINE__);
168  }
169  catch (...) {
170  throw BESInternalError("Failed to read data: Unknown exception caught", __FILE__, __LINE__);
171  }
172 
173  try {
174  FoDapJsonTransform ft(dds, dhi, &o_strm);
175 
176  ft.transform( true /* send data too */ );
177  }
178  catch (BESError &e) {
179  throw;
180  }
181  catch (...) {
182  throw BESInternalError("fileout_json: Failed to transform to JSON, unknown error", __FILE__, __LINE__);
183  }
184 
185  BESDEBUG("fojson", "FoDapJsonTransmitter::send_data - done transmitting JSON" << endl);
186 }
187 
204 {
205  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
206  if (!bdds)
207  throw BESInternalError("cast error", __FILE__, __LINE__);
208 
209  DDS *dds = bdds->get_dds();
210  if (!dds)
211  throw BESInternalError("No DDS has been created for transmit", __FILE__, __LINE__);
212 
213  BESDEBUG("fojson", "FoDapJsonTransmitter::send_metadata - parsing the constraint" << endl);
214 
215  ConstraintEvaluator &eval = bdds->get_ce();
216 
217  ostream &o_strm = dhi.get_output_stream();
218  if (!o_strm)
219  throw BESInternalError("Output stream is not set, can not return as JSON", __FILE__, __LINE__);
220 
221  // ticket 1248 jhrg 2/23/09
222  string ce = www2id(dhi.data[POST_CONSTRAINT], "%", "%20%26");
223  try {
224  eval.parse_constraint(ce, *dds);
225  }
226  catch (Error &e) {
227  throw BESInternalError("Failed to parse the constraint expression: " + e.get_error_message(), __FILE__, __LINE__);
228  }
229  catch (...) {
230  throw BESInternalError("Failed to parse the constraint expression: Unknown exception caught", __FILE__, __LINE__);
231  }
232 
233  // now we need to read the data
234  BESDEBUG("fojson", "FoDapJsonTransmitter::send_data - reading data into DataDDS" << endl);
235 
236  try {
237  // Handle *functional* constraint expressions specially
238  if (eval.function_clauses()) {
239  BESDEBUG("fojson", "processing a functional constraint clause(s)." << endl);
240  DDS *tmp_dds = eval.eval_function_clauses(*dds);
241  delete dds;
242  dds = tmp_dds;
243  }
244  else {
245  // Iterate through the variables in the DataDDS and read
246  // in the data if the variable has the send flag set.
247  for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
248  if ((*i)->send_p()) {
249  (*i)->intern_data(eval, *dds);
250  }
251  }
252  }
253  }
254  catch (Error &e) {
255  throw BESInternalError("Failed to read data: " + e.get_error_message(), __FILE__, __LINE__);
256  }
257  catch (...) {
258  throw BESInternalError("Failed to read data: Unknown exception caught", __FILE__, __LINE__);
259  }
260 
261  try {
262  FoDapJsonTransform ft(dds, dhi, &o_strm /*&temp_full[0]*/);
263 
264  ft.transform( false /* send metadata only */ );
265 
266  // FoW10nJsonTransmitter::return_temp_stream(&temp_full[0], o_strm);
267  }
268  catch (...) {
269  throw BESInternalError("FoDapJsonTransmitter: Failed to transform to JSON, unknown error", __FILE__, __LINE__);
270  }
271 
272  BESDEBUG("fojson", "FoDapJsonTransmitter::send_data - done transmitting JSON" << endl);
273 }
274 
284 void FoDapJsonTransmitter::return_temp_stream(const string &filename, ostream &strm)
285 {
286  // int bytes = 0 ; // Not used; jhrg 3/16/11
287  ifstream os;
288  os.open(filename.c_str(), ios::binary | ios::in);
289  if (!os) {
290  string err = "Can not connect to file " + filename;
291  BESInternalError pe(err, __FILE__, __LINE__);
292  throw pe;
293  }
294  int nbytes;
295  char block[4096];
296 
297  os.read(block, sizeof block);
298  nbytes = os.gcount();
299  if (nbytes > 0) {
300  strm.write(block, nbytes);
301  //bytes += nbytes ;
302  }
303  else {
304  // close the stream before we leave.
305  os.close();
306 
307  string err = (string) "0XAAE234F: failed to stream. Internal server "
308  + "error, got zero count on stream buffer." + filename;
309  BESInternalError pe(err, __FILE__, __LINE__);
310  throw pe;
311  }
312  while (os) {
313  os.read(block, sizeof block);
314  nbytes = os.gcount();
315  strm.write(block, nbytes);
316  //write( fileno( stdout ),(void*)block, nbytes ) ;
317  //bytes += nbytes ;
318  }
319  os.close();
320 }
321 
#define DATA_SERVICE
Definition: BESDapNames.h:71
Used to transform a DDS into a w10n JSON metadata or w10n JSON data document.
void set_dds(DataDDS *ddsIn)
Set the response object's DDS.
exception thrown if inernal error encountered
ConstraintEvaluator & get_ce()
Represents an OPeNDAP DDS DAP2 data object within the BES.
virtual bool add_method(string method_name, p_transmitter trans_method)
static void send_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a JSON file.
static class NCMLUtil overview
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
#define FO_JSON_TEMP_DIR
#define DDX_SERVICE
Definition: BESDapNames.h:66
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
#define POST_CONSTRAINT
Definition: BESDataNames.h:43
ConstraintEvaluator & get_ce()
Structure storing information used by the BES to handle the request.
map< string, string > data
the map of string data that will be required for the current request.
FoDapJsonTransmitter()
Construct the FoW10nJsonTransmitter.
#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
Abstract base class representing a specific set of information in response to a request to the BES...
static void send_metadata(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a JSON file.