bes  Updated for version 3.20.10
StandAloneApp.cc
1 // StandAloneApp.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public 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 University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 
34 #include "config.h"
35 
36 #include <unistd.h>
37 #include <getopt.h>
38 #include <signal.h>
39 
40 #include <iostream>
41 #include <string>
42 #include <vector>
43 #include <fstream>
44 
45 using std::cout;
46 using std::cerr;
47 using std::endl;
48 using std::flush;
49 using std::string;
50 using std::vector;
51 using std::ofstream;
52 using std::ostream;
53 using std::ifstream;
54 
55 #include "StandAloneApp.h"
56 #include "StandAloneClient.h"
57 #include "BESError.h"
58 #include "BESDebug.h"
59 #include "BESDefaultModule.h"
60 #include "BESXMLDefaultCommands.h"
61 #include "TheBESKeys.h"
62 #include "BESCatalogUtils.h"
63 #include "CmdTranslation.h"
64 
65 #define MODULE "standalone"
66 #define prolog string("StandAloneApp::").append(__func__).append("() - ")
67 
68 StandAloneApp::StandAloneApp() :
69  BESModuleApp(), _cmd(""), _outputStrm(0), _repeat(0)
70 {
71 }
72 
73 StandAloneApp::~StandAloneApp()
74 {
75  delete TheBESKeys::TheKeys();
76 }
77 
78 void StandAloneApp::showVersion()
79 {
80  cout << appName() << ": version 3.0" << endl;
81 }
82 
83 void StandAloneApp::showUsage()
84 {
85  cout << endl;
86  cout << appName() << ": the following options are available:" << endl;
87  cout << " -c <file>, --config=<file> - BES configuration file" << endl;
88  cout << " -x <command>, --execute=<command> - command for the server " << endl;
89  cout << " to execute" << endl;
90  cout << " -i <file>, --inputfile=<file> - file with a sequence of input " << endl;
91  cout << " commands, may be used multiple times." << endl;
92  cout << " -f <file>, --outputfile=<file> - write output to this file" << endl;
93  cout << " -d, --debug - turn on debugging for the client session" << endl;
94  cout << " -r <num>, --repeat=<num> - repeat the command(s) <num> times" << endl;
95  cout << " -v, --version - return version information" << endl;
96  cout << " -?, --help - display help information" << endl;
97  cout << endl;
98  cout << "Note: You may provide a bes command with -x OR you may provide one " << endl;
99  cout << " or more BES command file names. One or the other, not neither, not both." << endl;
100  cout << endl;
101  BESDebug::Help(cout);
102 }
103 
104 int StandAloneApp::initialize(int argc, char **argv)
105 {
106  CmdTranslation::initialize(argc, argv);
107 
108  string outputStr = "";
109 // string inputStr = "";
110  string repeatStr = "";
111 
112  bool badUsage = false;
113 
114  int c;
115 
116  static struct option longopts[] = {
117  { "config", 1, 0, 'c' },
118  { "debug", 0, 0, 'd' },
119  { "version", 0, 0, 'v' },
120  { "execute", 1, 0, 'x' },
121  { "outputfile", 1, 0, 'f' },
122  { "inputfile", 1, 0, 'i' },
123  { "repeat", 1, 0, 'r' },
124  { "help", 0, 0, '?' },
125  { 0, 0, 0, 0 }
126  };
127  int option_index = 0;
128 
129  while ((c = getopt_long(argc, argv, "?vc:d:x:f:i:r:", longopts, &option_index)) != -1) {
130  switch (c) {
131  case 'c':
132  TheBESKeys::ConfigFile = optarg;
133  break;
134  case 'd':
135  BESDebug::SetUp(optarg);
136  break;
137  case 'v': {
138  showVersion();
139  exit(0);
140  }
141  break;
142  case 'x':
143  _cmd = optarg;
144  break;
145  case 'f':
146  outputStr = optarg;
147  break;
148  case 'i':
149  _command_file_names.push_back(optarg);
150  break;
151  case 'r':
152  repeatStr = optarg;
153  break;
154  case '?': {
155  showUsage();
156  exit(0);
157  }
158  break;
159  }
160  }
161 
162  if (outputStr != "") {
163  if (_cmd == "" && _command_file_names.empty()) {
164  cerr << "When specifying an output file you must either specify a command or an input file" << endl;
165  badUsage = true;
166  }
167  else if (_cmd != "" && !_command_file_names.empty()) {
168  cerr << "You must specify either a command or an input file on the command line, not both" << endl;
169  badUsage = true;
170  }
171  }
172 
173  if (badUsage == true) {
174  showUsage();
175  return 1;
176  }
177 
178  if (outputStr != "") {
179  _outputStrm = new ofstream(outputStr.c_str());
180  if (!(*_outputStrm)) {
181  cerr << "could not open the output file " << outputStr << endl;
182  badUsage = true;
183  }
184  }
185 
186  if (!repeatStr.empty()) {
187  _repeat = atoi(repeatStr.c_str());
188  if (!_repeat && repeatStr != "0") {
189  cerr << "repeat number invalid: " << repeatStr << endl;
190  badUsage = true;
191  }
192  if (!_repeat) {
193  _repeat = 1;
194  }
195  }
196 
197  if (badUsage == true) {
198  showUsage();
199  return 1;
200  }
201 
202  try {
203  BESDEBUG(MODULE, prolog << "Initializing default module ... " << endl);
204  BESDefaultModule::initialize(argc, argv);
205  BESDEBUG(MODULE, prolog << "Done initializing default module" << endl);
206 
207  BESDEBUG(MODULE, prolog << "Initializing default commands ... " << endl);
209  BESDEBUG(MODULE, prolog << "Done initializing default commands" << endl);
210 
211  BESDEBUG(MODULE, prolog << "Initializing loaded modules ... " << endl);
212  int retval = BESModuleApp::initialize(argc, argv);
213  BESDEBUG(MODULE, prolog << "Done initializing loaded modules" << endl);
214  if (retval) return retval;
215  }
216  catch (BESError &e) {
217  cerr << prolog << "Failed to initialize stand alone app. Message : " << e.get_message() << endl;
218  return 1;
219  }
220 
221  BESDEBUG(MODULE, prolog << "Initialized settings:" << endl << *this);
222 
223  return 0;
224 }
225 
226 
231 {
232  StandAloneClient sac;
233  string msg;
234  try {
235  if (_outputStrm) {
236  sac.setOutput(_outputStrm, true);
237  }
238  else {
239  sac.setOutput(&cout, false);
240  }
241  BESDEBUG(MODULE, prolog << "StandAloneClient instance created." << endl);
242  }
243  catch (BESError &e) {
244  msg = prolog + "FAILED to start StandAloneClient instance. Message: " + e.get_message();
245  BESDEBUG(MODULE, msg << endl);
246  cerr << msg << endl;
247  return 1;
248  }
249 
250  try {
251  if (_cmd != "") {
252  sac.executeCommands(_cmd, _repeat);
253  }
254  else if (!_command_file_names.empty()) {
255  BESDEBUG(MODULE, prolog << "Found " << _command_file_names.size() << " command files." << endl);
256  for(unsigned index=0; index<_command_file_names.size(); index++){
257  string command_filename = _command_file_names[index];
258  BESDEBUG(MODULE, prolog << "Processing BES command file: " << command_filename<< endl);
259  if (!command_filename.empty()) {
260  ifstream cmdStrm(command_filename.c_str());
261  if (!cmdStrm.is_open()) {
262  cerr << prolog << "FAILED to open the input file '" << command_filename << "' SKIPPING." << endl;
263  }
264  else {
265  try {
266  sac.executeCommands(cmdStrm, _repeat);
267  }
268  catch (BESError &e) {
269  cerr << prolog << "Error processing commands. Message: " << e.get_message() << endl;
270  }
271  }
272  }
273  }
274  }
275  else {
276  sac.interact();
277  }
278  }
279  catch (BESError &e) {
280  cerr << prolog << "Error processing commands. Message: " << e.get_message() << endl;
281  }
282 
283  return 0;
284 }
285 
292 {
293  BESDEBUG(MODULE, "ServerApp: terminating loaded modules ... " << endl);
295  BESDEBUG(MODULE, "ServerApp: done terminating loaded modules" << endl);
296 
297  BESDEBUG(MODULE, "ServerApp: terminating default commands ... " << endl);
299  BESDEBUG(MODULE, "ServerApp: done terminating default commands" << endl);
300 
301  BESDEBUG(MODULE, "ServerApp: terminating default module ... " << endl);
302  BESDefaultModule::terminate();
303  BESDEBUG(MODULE, "ServerApp: done terminating default module" << endl);
304 
305  CmdTranslation::terminate();
306 
307  xmlCleanupParser();
308 
309  return sig;
310 }
311 
318 void StandAloneApp::dump(ostream &strm) const
319 {
320  strm << BESIndent::LMarg << "StandAloneApp::dump - (" << (void *) this << ")" << endl;
321  BESIndent::Indent();
322 
323  strm << BESIndent::LMarg << "command: " << _cmd << endl;
324  strm << BESIndent::LMarg << "output stream: " << (void *) _outputStrm << endl;
325  if(_command_file_names.empty()){
326  strm << BESIndent::LMarg << "No command filenames were identified." << endl;
327  }
328  else {
329  strm << BESIndent::LMarg << "Found " << _command_file_names.size() << " command file names." << endl;
330  BESIndent::Indent();
331  for (unsigned index = 0; index < _command_file_names.size(); index++) {
332  strm << BESIndent::LMarg << "command_filename["<<index<<"]: "<< _command_file_names[index] << endl;
333  }
334  BESIndent::UnIndent();
335  }
336  BESApp::dump(strm);
337  BESIndent::UnIndent();
338 }
339 
virtual void dump(std::ostream &strm) const =0
dumps information about this object
Definition: BESApp.cc:115
std::string appName(void) const
Returns the name of the application.
Definition: BESApp.h:128
static void SetUp(const std::string &values)
Sets up debugging for the bes.
Definition: BESDebug.cc:98
static void Help(std::ostream &strm)
Writes help information for so that developers know what can be set for debugging.
Definition: BESDebug.cc:162
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
Base application object for all BES applications.
Definition: BESModuleApp.h:56
virtual int terminate(int sig=0)
clean up after the application
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Definition: BESModuleApp.cc:69
static int terminate(void)
Removes the default set of BES XML commands from the list of possible commands.
static int initialize(int argc, char **argv)
Loads the default set of BES XML commands.
virtual int terminate(int sig=0)
clean up after the application
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
virtual int run()
The body of the application, implementing the primary functionality of the BES application.
void executeCommands(const std::string &cmd_list, int repeat)
Send the command(s) specified to the BES server after wrapping in request document.
void interact()
An interactive BES client that takes BES requests on the command line.
void setOutput(std::ostream *strm, bool created)
Set the output stream for responses from the BES server.
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:71
static std::string ConfigFile
Definition: TheBESKeys.h:185