bes  Updated for version 3.20.13
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 <getopt.h>
37 
38 #include <iostream>
39 #include <string>
40 #include <vector>
41 
42 #include "StandAloneApp.h"
43 #include "StandAloneClient.h"
44 #include "BESError.h"
45 #include "BESDebug.h"
46 #include "BESDefaultModule.h"
47 #include "BESXMLDefaultCommands.h"
48 #include "TheBESKeys.h"
49 #include "CmdTranslation.h"
50 
51 #define MODULE "standalone"
52 #define prolog string("StandAloneApp::").append(__func__).append("() - ")
53 
54 using namespace std;
55 
56 StandAloneApp::~StandAloneApp()
57 {
58  delete TheBESKeys::TheKeys();
59 }
60 
61 void StandAloneApp::showVersion()
62 {
63  cout << appName() << ": version 3.0" << endl;
64 }
65 
66 void StandAloneApp::showUsage()
67 {
68  cout << endl;
69  cout << appName() << ": the following options are available:" << endl;
70  cout << " -c <file>, --config=<file> - BES configuration file" << endl;
71  cout << " -x <command>, --execute=<command> - command for the server " << endl;
72  cout << " to execute" << endl;
73  cout << " -i <file>, --inputfile=<file> - file with a sequence of input " << endl;
74  cout << " commands, may be used multiple times." << endl;
75  cout << " -f <file>, --outputfile=<file> - write output to this file" << endl;
76  cout << " -d, --debug - turn on debugging for the client session" << endl;
77  cout << " -r <num>, --repeat=<num> - repeat the command(s) <num> times" << endl;
78  cout << " -v, --version - return version information" << endl;
79  cout << " -?, --help - display help information" << endl;
80  cout << endl;
81  cout << "Note: You may provide a bes command with -x OR you may provide one " << endl;
82  cout << " or more BES command file names. One or the other, not neither, not both." << endl;
83  cout << endl;
84  BESDebug::Help(cout);
85 }
86 
87 int StandAloneApp::initialize(int argc, char **argv)
88 {
89  CmdTranslation::initialize(argc, argv);
90 
91  static struct option longopts[] = {
92  { "config", 1, 0, 'c' },
93  { "debug", 0, 0, 'd' },
94  { "version", 0, 0, 'v' },
95  { "execute", 1, 0, 'x' },
96  { "outputfile", 1, 0, 'f' },
97  { "inputfile", 1, 0, 'i' },
98  { "repeat", 1, 0, 'r' },
99  { "help", 0, 0, '?' },
100  { 0, 0, 0, 0 }
101  };
102 
103  string outputStr;
104  string repeatStr;
105  int option_index = 0;
106  int c;
107  while ((c = getopt_long(argc, argv, "?vc:d:x:f:i:r:", longopts, &option_index)) != -1) {
108  switch (c) {
109  case 'c':
110  TheBESKeys::ConfigFile = optarg;
111  break;
112  case 'd':
113  BESDebug::SetUp(optarg);
114  break;
115  case 'x':
116  _cmd = optarg;
117  break;
118  case 'f':
119  outputStr = optarg;
120  break;
121  case 'i':
122  _command_file_names.emplace_back(optarg);
123  break;
124  case 'r':
125  repeatStr = optarg;
126  break;
127  case 'v':
128  showVersion();
129  exit(0);
130  case '?':
131  default:
132  showUsage();
133  exit(0);
134  }
135  }
136 
137  bool badUsage = false;
138  if (!outputStr.empty()) {
139  if (_cmd.empty() && _command_file_names.empty()) {
140  cerr << "When specifying an output file you must either specify a command or an input file" << endl;
141  badUsage = true;
142  }
143  else if (!_cmd.empty() && !_command_file_names.empty()) {
144  cerr << "You must specify either a command or an input file on the command line, not both" << endl;
145  badUsage = true;
146  }
147  }
148 
149  if (badUsage) {
150  showUsage();
151  return 1;
152  }
153 
154  if (!outputStr.empty()) {
155  _outputStrm = new ofstream(outputStr.c_str());
156  if (!(*_outputStrm)) {
157  cerr << "could not open the output file " << outputStr << endl;
158  badUsage = true;
159  }
160  }
161 
162  if (!repeatStr.empty()) {
163  _repeat = atoi(repeatStr.c_str());
164  if (!_repeat && repeatStr != "0") {
165  cerr << "repeat number invalid: " << repeatStr << endl;
166  badUsage = true;
167  }
168  if (!_repeat) {
169  _repeat = 1;
170  }
171  }
172 
173  if (badUsage) {
174  showUsage();
175  return 1;
176  }
177 
178  try {
179  BESDEBUG(MODULE, prolog << "Initializing default module ... " << endl);
180  BESDefaultModule::initialize(argc, argv);
181  BESDEBUG(MODULE, prolog << "Done initializing default module" << endl);
182 
183  BESDEBUG(MODULE, prolog << "Initializing default commands ... " << endl);
185  BESDEBUG(MODULE, prolog << "Done initializing default commands" << endl);
186 
187  BESDEBUG(MODULE, prolog << "Initializing loaded modules ... " << endl);
188  int retval = BESModuleApp::initialize(argc, argv);
189  BESDEBUG(MODULE, prolog << "Done initializing loaded modules" << endl);
190  if (retval) return retval;
191  }
192  catch (BESError &e) {
193  cerr << prolog << "Failed to initialize stand alone app. Message : " << e.get_message() << endl;
194  return 1;
195  }
196 
197  BESDEBUG(MODULE, prolog << "Initialized settings:" << endl << *this);
198 
199  return 0;
200 }
201 
202 
207 {
208  StandAloneClient sac;
209  string msg;
210  try {
211  if (_outputStrm) {
212  sac.setOutput(_outputStrm, true);
213  }
214  else {
215  sac.setOutput(&cout, false);
216  }
217  BESDEBUG(MODULE, prolog << "StandAloneClient instance created." << endl);
218  }
219  catch (BESError &e) {
220  msg = prolog + "FAILED to start StandAloneClient instance. Message: " + e.get_message();
221  BESDEBUG(MODULE, msg << endl);
222  cerr << msg << endl;
223  return 1;
224  }
225 
226  try {
227  if (!_cmd.empty()) {
228  sac.executeCommands(_cmd, _repeat);
229  }
230  else if (!_command_file_names.empty()) {
231  BESDEBUG(MODULE, prolog << "Found " << _command_file_names.size() << " command files." << endl);
232  for (auto &command_filename: _command_file_names) {
233  BESDEBUG(MODULE, prolog << "Processing BES command file: " << command_filename<< endl);
234  if (!command_filename.empty()) {
235  ifstream cmdStrm(command_filename);
236  if (!cmdStrm.is_open()) {
237  cerr << prolog << "FAILED to open the input file '" << command_filename << "' SKIPPING." << endl;
238  }
239  else {
240  try {
241  sac.executeCommands(cmdStrm, _repeat);
242  }
243  catch (BESError &e) {
244  cerr << prolog << "Error processing commands. Message: " << e.get_message() << endl;
245  }
246  }
247  }
248  }
249  }
250  else {
251  sac.interact();
252  }
253  }
254  catch (BESError &e) {
255  cerr << prolog << "Error processing commands. Message: " << e.get_message() << endl;
256  }
257 
258  return 0;
259 }
260 
267 {
268  BESDEBUG(MODULE, "ServerApp: terminating loaded modules ... " << endl);
270  BESDEBUG(MODULE, "ServerApp: done terminating loaded modules" << endl);
271 
272  BESDEBUG(MODULE, "ServerApp: terminating default commands ... " << endl);
274  BESDEBUG(MODULE, "ServerApp: done terminating default commands" << endl);
275 
276  BESDEBUG(MODULE, "ServerApp: terminating default module ... " << endl);
277  BESDefaultModule::terminate();
278  BESDEBUG(MODULE, "ServerApp: done terminating default module" << endl);
279 
280  CmdTranslation::terminate();
281 
282  xmlCleanupParser();
283 
284  return sig;
285 }
286 
293 void StandAloneApp::dump(ostream &strm) const
294 {
295  strm << BESIndent::LMarg << "StandAloneApp::dump - (" << (void *) this << ")" << endl;
296  BESIndent::Indent();
297 
298  strm << BESIndent::LMarg << "command: " << _cmd << endl;
299  strm << BESIndent::LMarg << "output stream: " << (void *) _outputStrm << endl;
300  if(_command_file_names.empty()){
301  strm << BESIndent::LMarg << "No command filenames were identified." << endl;
302  }
303  else {
304  strm << BESIndent::LMarg << "Found " << _command_file_names.size() << " command file names." << endl;
305  BESIndent::Indent();
306  for (unsigned index = 0; index < _command_file_names.size(); index++) {
307  strm << BESIndent::LMarg << "command_filename["<<index<<"]: "<< _command_file_names[index] << endl;
308  }
309  BESIndent::UnIndent();
310  }
311  BESApp::dump(strm);
312  BESIndent::UnIndent();
313 }
314 
void dump(std::ostream &strm) const override=0
dumps information about this object
Definition: BESApp.cc:113
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
Base exception class for the BES with basic string message.
Definition: BESError.h:59
std::string get_message() const
get the error message for this exception
Definition: BESError.h:111
int terminate(int sig=0) override
clean up after the application
int initialize(int argC, char **argV) override
Load and initialize any BES modules.
Definition: BESModuleApp.cc:71
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.
int terminate(int sig=0) override
clean up after the application
int initialize(int argC, char **argV) override
Load and initialize any BES modules.
void dump(std::ostream &strm) const override
dumps information about this object
int run() override
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