bes  Updated for version 3.20.8
GatewayContainer.cc
1 // GatewayContainer.cc
2 
3 // -*- mode: c++; c-basic-offset:4 -*-
4 
5 // This file is part of gateway_module, A C++ module that can be loaded in to
6 // the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
7 
8 // Copyright (c) 2002,2003 OPeNDAP, Inc.
9 // Author: Patrick West <pwest@ucar.edu>
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26 
27 // Authors:
28 // pcw Patrick West <pwest@ucar.edu>
29 
30 #include <BESSyntaxUserError.h>
31 #include <BESInternalError.h>
32 #include <BESDebug.h>
33 #include <BESUtil.h>
34 #include <AllowedHosts.h>
35 
36 #include "GatewayContainer.h"
37 #include "GatewayNames.h"
38 #include "RemoteResource.h"
39 
40 using namespace std;
41 using namespace gateway;
42 using namespace bes;
43 
44 
45 #define prolog std::string("GatewayContainer::").append(__func__).append("() - ")
46 
57 GatewayContainer::GatewayContainer(const string &sym_name,
58  const string &real_name, const string &type) :
59  BESContainer(sym_name, real_name, type), d_remoteResource(0) {
60 
61  if (type.empty())
62  set_container_type(GATEWAY_CONTAINER_TYPE);
63 
64  BESUtil::url url_parts;
65  BESUtil::url_explode(real_name, url_parts);
66  url_parts.uname = "";
67  url_parts.psswd = "";
68  string use_real_name = BESUtil::url_create(url_parts);
69 
70  if (!AllowedHosts::theHosts()->is_allowed(use_real_name)) {
71  string err = (string) "The specified URL " + real_name
72  + " does not match any of the accessible services in"
73  + " the allowed hosts list.";
74  throw BESSyntaxUserError(err, __FILE__, __LINE__);
75  }
76 
77  // Because we know the name is really a URL, then we know the "relative_name" is meaningless
78  // So we set it to be the same as "name"
79  set_relative_name(real_name);
80 }
81 
85 GatewayContainer::GatewayContainer(const GatewayContainer &copy_from) :
86  BESContainer(copy_from), d_remoteResource(copy_from.d_remoteResource) {
87  // we can not make a copy of this container once the request has
88  // been made
89  if (d_remoteResource) {
90  string err = (string) "The Container has already been accessed, "
91  + "can not create a copy of this container.";
92  throw BESInternalError(err, __FILE__, __LINE__);
93  }
94 }
95 
96 void GatewayContainer::_duplicate(GatewayContainer &copy_to) {
97  if (copy_to.d_remoteResource) {
98  string err = (string) "The Container has already been accessed, "
99  + "can not duplicate this resource.";
100  throw BESInternalError(err, __FILE__, __LINE__);
101  }
102  copy_to.d_remoteResource = d_remoteResource;
103  BESContainer::_duplicate(copy_to);
104 }
105 
106 BESContainer *
108  GatewayContainer *container = new GatewayContainer;
109  _duplicate(*container);
110  return container;
111 }
112 
113 GatewayContainer::~GatewayContainer() {
114  if (d_remoteResource) {
115  release();
116  }
117 }
118 
125 
126  BESDEBUG( MODULE, prolog << "BEGIN" << endl);
127 
128  // Since this the Gateway we know that the real_name is a URL.
129  string url = get_real_name();
130 
131  BESDEBUG( MODULE, prolog << "Accessing " << url << endl);
132 
133  string type = get_container_type();
134  if (type == GATEWAY_CONTAINER_TYPE)
135  type = "";
136 
137  if(!d_remoteResource) {
138  BESDEBUG( MODULE, prolog << "Building new RemoteResource." << endl );
139  d_remoteResource = new http::RemoteResource(url);
140  d_remoteResource->retrieveResource();
141  }
142  BESDEBUG( MODULE, prolog << "Located remote resource." << endl );
143 
144 
145  string cachedResource = d_remoteResource->getCacheFileName();
146  BESDEBUG( MODULE, prolog << "Using local cache file: " << cachedResource << endl );
147 
148  type = d_remoteResource->getType();
149  set_container_type(type);
150  BESDEBUG( MODULE, prolog << "Type: " << type << endl );
151 
152  BESDEBUG( MODULE, prolog << "Done accessing " << get_real_name() << " returning cached file " << cachedResource << endl);
153  BESDEBUG( MODULE, prolog << "Done accessing " << *this << endl);
154  BESDEBUG( MODULE, prolog << "END" << endl);
155 
156  return cachedResource; // this should return the file name from the GatewayCache
157 }
158 
159 
160 
168  BESDEBUG( MODULE, prolog << "BEGIN" << endl);
169  if (d_remoteResource) {
170  BESDEBUG( MODULE, prolog << "Releasing RemoteResource" << endl);
171  delete d_remoteResource;
172  d_remoteResource = 0;
173  }
174  BESDEBUG( MODULE, prolog << "END" << endl);
175  return true;
176 }
177 
185 void GatewayContainer::dump(ostream &strm) const {
186  strm << BESIndent::LMarg << "GatewayContainer::dump - (" << (void *) this
187  << ")" << endl;
188  BESIndent::Indent();
189  BESContainer::dump(strm);
190  if (d_remoteResource) {
191  strm << BESIndent::LMarg << "RemoteResource.getCacheFileName(): " << d_remoteResource->getCacheFileName()
192  << endl;
193  strm << BESIndent::LMarg << "response headers: ";
194  vector<string> *hdrs = d_remoteResource->getResponseHeaders();
195  if (hdrs) {
196  strm << endl;
197  BESIndent::Indent();
198  vector<string>::const_iterator i = hdrs->begin();
199  vector<string>::const_iterator e = hdrs->end();
200  for (; i != e; i++) {
201  string hdr_line = (*i);
202  strm << BESIndent::LMarg << hdr_line << endl;
203  }
204  BESIndent::UnIndent();
205  } else {
206  strm << "none" << endl;
207  }
208  } else {
209  strm << BESIndent::LMarg << "response not yet obtained" << endl;
210  }
211  BESIndent::UnIndent();
212 }
A container is something that holds data. E.G., a netcdf file or a database entry.
Definition: BESContainer.h:65
void set_container_type(const std::string &type)
set the type of data that this container represents, such as cedar or netcdf.
Definition: BESContainer.h:161
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESContainer.cc:73
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:232
void set_relative_name(const std::string &relative)
Set the relative name of the object in this container.
Definition: BESContainer.h:152
void _duplicate(BESContainer &copy_to)
duplicate this instance into the passed container
Definition: BESContainer.cc:54
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:180
exception thrown if internal error encountered
error thrown if there is a user syntax error in the request or any other user error
static void url_explode(const std::string &url_str, BESUtil::url &url_parts)
Given a url, break the url into its different parts.
Definition: BESUtil.cc:678
Container representing a remote request.
virtual std::string access()
access the remote target response by making the remote request
virtual bool release()
release the resources
virtual BESContainer * ptr_duplicate()
pure abstract method to duplicate this instances of BESContainer
virtual void dump(std::ostream &strm) const
dumps information about this object
std::string getCacheFileName()
std::vector< std::string > * getResponseHeaders()
std::string getType()