pion-net  4.0.9
FileService.hpp
1 // ------------------------------------------------------------------
2 // pion-net: a C++ framework for building lightweight HTTP interfaces
3 // ------------------------------------------------------------------
4 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #ifndef __PION_FILESERVICE_HEADER__
11 #define __PION_FILESERVICE_HEADER__
12 
13 #include <boost/shared_ptr.hpp>
14 #include <boost/functional/hash.hpp>
15 #include <boost/filesystem/path.hpp>
16 #include <boost/thread/once.hpp>
17 #include <boost/thread/mutex.hpp>
18 #include <boost/shared_array.hpp>
19 #include <pion/PionLogger.hpp>
20 #include <pion/PionException.hpp>
21 #include <pion/PionHashMap.hpp>
22 #include <pion/net/WebService.hpp>
23 #include <pion/net/HTTPRequest.hpp>
24 #include <pion/net/HTTPResponseWriter.hpp>
25 #include <pion/net/HTTPServer.hpp>
26 #include <string>
27 #include <map>
28 
29 
30 namespace pion { // begin namespace pion
31 namespace plugins { // begin namespace plugins
32 
33 
37 class DiskFile {
38 public:
40  DiskFile(void)
41  : m_file_size(0), m_last_modified(0) {}
42 
44  DiskFile(const boost::filesystem::path& path,
45  char *content, unsigned long size,
46  std::time_t modified, const std::string& mime)
47  : m_file_path(path), m_file_content(content), m_file_size(size),
48  m_last_modified(modified), m_mime_type(mime)
49  {}
50 
52  DiskFile(const DiskFile& f)
56  {}
57 
59  void update(void);
60 
62  void read(void);
63 
69  bool checkUpdated(void);
70 
72  inline const boost::filesystem::path& getFilePath(void) const { return m_file_path; }
73 
75  inline char *getFileContent(void) { return m_file_content.get(); }
76 
78  inline bool hasFileContent(void) const { return m_file_content; }
79 
81  inline unsigned long getFileSize(void) const { return m_file_size; }
82 
84  inline std::time_t getLastModified(void) const { return m_last_modified; }
85 
87  inline const std::string& getLastModifiedString(void) const { return m_last_modified_string; }
88 
90  inline const std::string& getMimeType(void) const { return m_mime_type; }
91 
93  inline void setFilePath(const boost::filesystem::path& p) { m_file_path = p; }
94 
96  inline void appendFilePath(const std::string& p) { m_file_path /= p; }
97 
99  inline void setMimeType(const std::string& t) { m_mime_type = t; }
100 
102  inline void resetFileContent(unsigned long n = 0) {
103  if (n == 0) m_file_content.reset();
104  else m_file_content.reset(new char[n]);
105  }
106 
107 
108 protected:
109 
111  boost::filesystem::path m_file_path;
112 
114  boost::shared_array<char> m_file_content;
115 
117  std::streamsize m_file_size;
118 
120  std::time_t m_last_modified;
121 
124 
126  std::string m_mime_type;
127 };
128 
129 
134  public boost::enable_shared_from_this<DiskFileSender>,
135  private boost::noncopyable
136 {
137 public:
146  static inline boost::shared_ptr<DiskFileSender>
148  pion::net::HTTPRequestPtr& request,
149  pion::net::TCPConnectionPtr& tcp_conn,
150  unsigned long max_chunk_size = 0)
151  {
152  return boost::shared_ptr<DiskFileSender>(new DiskFileSender(file, request,
153  tcp_conn, max_chunk_size));
154  }
155 
157  virtual ~DiskFileSender() {}
158 
162  void send(void);
163 
165  inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }
166 
168  inline PionLogger getLogger(void) { return m_logger; }
169 
170 
171 protected:
172 
181  DiskFileSender(DiskFile& file,
182  pion::net::HTTPRequestPtr& request,
183  pion::net::TCPConnectionPtr& tcp_conn,
184  unsigned long max_chunk_size);
185 
192  void handleWrite(const boost::system::error_code& write_error,
193  std::size_t bytes_written);
194 
195 
198 
199 
200 private:
201 
203  DiskFile m_disk_file;
204 
206  pion::net::HTTPResponseWriterPtr m_writer;
207 
209  boost::filesystem::ifstream m_file_stream;
210 
212  boost::shared_array<char> m_content_buf;
213 
219  unsigned long m_max_chunk_size;
220 
222  unsigned long m_file_bytes_to_send;
223 
225  unsigned long m_bytes_sent;
226 };
227 
229 typedef boost::shared_ptr<DiskFileSender> DiskFileSenderPtr;
230 
231 
235 class FileService :
236  public pion::net::WebService
237 {
238 public:
239 
242  public:
243  DirectoryNotFoundException(const std::string& dir)
244  : PionException("FileService directory not found: ", dir) {}
245  };
246 
249  public:
250  NotADirectoryException(const std::string& dir)
251  : PionException("FileService option is not a directory: ", dir) {}
252  };
253 
256  public:
257  FileNotFoundException(const std::string& file)
258  : PionException("FileService file not found: ", file) {}
259  };
260 
263  public:
264  NotAFileException(const std::string& file)
265  : PionException("FileService option is not a file: ", file) {}
266  };
267 
270  public:
271  InvalidCacheException(const std::string& value)
272  : PionException("FileService invalid value for cache option: ", value) {}
273  };
274 
277  public:
278  InvalidScanException(const std::string& value)
279  : PionException("FileService invalid value for scan option: ", value) {}
280  };
281 
284  public:
285  InvalidOptionValueException(const std::string& option, const std::string& value)
286  : PionException("FileService invalid value for " + option + " option: ", value) {}
287  };
288 
291  public:
292  FileReadException(const std::string& value)
293  : PionException("FileService unable to read file: ", value) {}
294  };
295 
298  public:
299  UndefinedResponseException(const std::string& value)
300  : PionException("FileService has an undefined response: ", value) {}
301  };
302 
303 
304  // default constructor and destructor
305  FileService(void);
306  virtual ~FileService() {}
307 
318  virtual void setOption(const std::string& name, const std::string& value);
319 
321  virtual void operator()(pion::net::HTTPRequestPtr& request,
322  pion::net::TCPConnectionPtr& tcp_conn);
323 
325  virtual void start(void);
326 
328  virtual void stop(void);
329 
331  inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }
332 
334  inline PionLogger getLogger(void) { return m_logger; }
335 
336 
337 protected:
338 
340  typedef PION_HASH_MAP<std::string, DiskFile, PION_HASH_STRING > CacheMap;
341 
343  typedef PION_HASH_MAP<std::string, std::string, PION_HASH_STRING > MIMETypeMap;
344 
350  void scanDirectory(const boost::filesystem::path& dir_path);
351 
362  std::pair<CacheMap::iterator, bool>
363  addCacheEntry(const std::string& relative_path,
364  const boost::filesystem::path& file_path,
365  const bool placeholder);
366 
373  static std::string findMIMEType(const std::string& file_name);
374 
375  void sendNotFoundResponse(pion::net::HTTPRequestPtr& http_request,
376  pion::net::TCPConnectionPtr& tcp_conn);
377 
380 
381 
382 private:
383 
385  static void createMIMETypes(void);
386 
387 
389  static const std::string DEFAULT_MIME_TYPE;
390 
392  static const unsigned int DEFAULT_CACHE_SETTING;
393 
395  static const unsigned int DEFAULT_SCAN_SETTING;
396 
398  static const unsigned long DEFAULT_MAX_CACHE_SIZE;
399 
401  static const unsigned long DEFAULT_MAX_CHUNK_SIZE;
402 
404  static boost::once_flag m_mime_types_init_flag;
405 
407  static MIMETypeMap * m_mime_types_ptr;
408 
409 
411  boost::filesystem::path m_directory;
412 
414  boost::filesystem::path m_file;
415 
417  CacheMap m_cache_map;
418 
420  boost::mutex m_cache_mutex;
421 
428  unsigned int m_cache_setting;
429 
437  unsigned int m_scan_setting;
438 
443  unsigned long m_max_cache_size;
444 
450  unsigned long m_max_chunk_size;
451 
455  bool m_writable;
456 };
457 
458 
459 } // end namespace plugins
460 } // end namespace pion
461 
462 #endif
virtual void stop(void)
called when the web service's server is stopping
exception thrown if the cache option is set to an invalid value
void scanDirectory(const boost::filesystem::path &dir_path)
DiskFile(void)
default constructor
Definition: FileService.hpp:40
std::streamsize m_file_size
size of the file's content
exception thrown if an option is set to an invalid value
const boost::filesystem::path & getFilePath(void) const
return path to the cached file
Definition: FileService.hpp:72
std::pair< CacheMap::iterator, bool > addCacheEntry(const std::string &relative_path, const boost::filesystem::path &file_path, const bool placeholder)
virtual ~DiskFileSender()
default virtual destructor
void setFilePath(const boost::filesystem::path &p)
sets the path to the cached file
Definition: FileService.hpp:93
exception thrown if the directory configured is not found
void setMimeType(const std::string &t)
sets the mime type for the cached file
Definition: FileService.hpp:99
std::string m_last_modified_string
timestamp that the cached file was last modified (string format)
void read(void)
reads content from disk into file_content buffer (may throw)
DiskFile(const boost::filesystem::path &path, char *content, unsigned long size, std::time_t modified, const std::string &mime)
used to construct new disk file objects
Definition: FileService.hpp:44
void update(void)
updates the file_size and last_modified timestamp to disk
exception thrown if the file configured is not found
PionLogger m_logger
primary logging interface used by this class
exception thrown if we are unable to read a file from disk
unsigned long getFileSize(void) const
returns size of the file's content
Definition: FileService.hpp:81
PionLogger m_logger
primary logging interface used by this class
virtual void setOption(const std::string &name, const std::string &value)
Definition: FileService.cpp:50
exception thrown if we do not know how to respond (should never happen)
std::time_t getLastModified(void) const
returns timestamp that the cached file was last modified (0 = cache disabled)
Definition: FileService.hpp:84
DiskFile(const DiskFile &f)
copy constructor
Definition: FileService.hpp:52
virtual void operator()(pion::net::HTTPRequestPtr &request, pion::net::TCPConnectionPtr &tcp_conn)
handles requests for FileService
PionLogger getLogger(void)
returns the logger currently in use
void setLogger(PionLogger log_ptr)
sets the logger to be used
void resetFileContent(unsigned long n=0)
resets the size of the file content buffer
static boost::shared_ptr< DiskFileSender > create(DiskFile &file, pion::net::HTTPRequestPtr &request, pion::net::TCPConnectionPtr &tcp_conn, unsigned long max_chunk_size=0)
void setLogger(PionLogger log_ptr)
sets the logger to be used
PION_HASH_MAP< std::string, DiskFile, PION_HASH_STRING > CacheMap
data type for map of file names to cache entries
exception thrown if the file configuration option is not a file
boost::filesystem::path m_file_path
path to the cached file
virtual void start(void)
called when the web service's server is starting
std::time_t m_last_modified
timestamp that the cached file was last modified (0 = cache disabled)
exception thrown if the directory configuration option is not a directory
void handleWrite(const boost::system::error_code &write_error, std::size_t bytes_written)
the following enables use of the lock-free cache
const std::string & getMimeType(void) const
returns mime type for the cached file
Definition: FileService.hpp:90
const std::string & getLastModifiedString(void) const
returns timestamp that the cached file was last modified (string format)
Definition: FileService.hpp:87
char * getFileContent(void)
returns content of the cached file
Definition: FileService.hpp:75
static std::string findMIMEType(const std::string &file_name)
PionLogger getLogger(void)
returns the logger currently in use
void appendFilePath(const std::string &p)
appends to the path of the cached file
Definition: FileService.hpp:96
boost::shared_array< char > m_file_content
content of the cached file
exception thrown if the scan option is set to an invalid value
PION_HASH_MAP< std::string, std::string, PION_HASH_STRING > MIMETypeMap
data type for map of file extensions to MIME types
bool hasFileContent(void) const
returns true if there is cached file content
Definition: FileService.hpp:78
std::string m_mime_type
mime type for the cached file
DiskFileSender(DiskFile &file, pion::net::HTTPRequestPtr &request, pion::net::TCPConnectionPtr &tcp_conn, unsigned long max_chunk_size)