diff options
Diffstat (limited to 'ACE/apps/JAWS/clients/Caching')
22 files changed, 2711 insertions, 0 deletions
diff --git a/ACE/apps/JAWS/clients/Caching/ID_Generator.cpp b/ACE/apps/JAWS/clients/Caching/ID_Generator.cpp new file mode 100644 index 00000000000..6e868611835 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/ID_Generator.cpp @@ -0,0 +1,61 @@ +// $Id$ + +#if !defined (ACE_ID_GENERATOR_C) +#define ACE_ID_GENERATOR_C + +#include "ace/Object_Manager.h" +#include "ID_Generator.h" + +ACE_RCSID(Caching, ID_Generator, "$Id$") + +time_t ACE_ID_Generator::last_time_ = 0; + +size_t ACE_ID_Generator::last_number_ = 0; + +ACE_SYNCH_MUTEX *ACE_ID_Generator::lock_ = 0; + +char * +ACE_ID_Generator::get_new_id (char *id) +{ + time_t t; + size_t sn; + + ACE_ID_Generator::get_serial_id (t, sn); + ACE_NEW_RETURN (id, char [ACE_OFFER_ID_LENGTH], 0); + + ACE_OS::sprintf (id, "%014d%06d", t, sn); + return id; +} + +void +ACE_ID_Generator::get_serial_id (time_t &t, size_t &s) +{ + ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *ACE_ID_Generator::get_lock ())); + ACE_OS::time (&t); + + if (t != ACE_ID_Generator::last_time_) + { + ACE_ID_Generator::last_time_ = t; + s = ACE_ID_Generator::last_number_ = 0; + } + else + s = ACE_ID_Generator::last_number_++; +} + +ACE_SYNCH_MUTEX * +ACE_ID_Generator::get_lock (void) +{ +#if defined (ACE_HAS_THREADS) + if (ACE_ID_Generator::lock_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *ACE_Static_Object_Lock::instance (), 0)); + + // Double-checked Locking Optimization. + if (ACE_ID_Generator::lock_ == 0) + ACE_NEW_RETURN (ACE_ID_Generator::lock_, ACE_SYNCH_MUTEX, 0); + } +#endif /* ACE_HAS_THREADS */ + return ACE_ID_Generator::lock_; +} + +#endif /* ACE_ID_GENERATOR_C */ diff --git a/ACE/apps/JAWS/clients/Caching/ID_Generator.h b/ACE/apps/JAWS/clients/Caching/ID_Generator.h new file mode 100644 index 00000000000..73c78fc5506 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/ID_Generator.h @@ -0,0 +1,62 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// ID_Generator.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_ID_GENERATOR_H +#define ACE_ID_GENERATOR_h + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#define ACE_OFFER_ID_LENGTH 21 + +class ACE_ID_Generator + // = TITLE + // An unique ID generator. + // + // = DESCRIPTION + + // Generate an offer ID according to current time and avoid + // duplicate ID. It guarantees ID uniqueness within a process, + // i.e. no two threads may get the same ID string. Using a + // similar method like the backery algorithm. +{ +public: + static char *get_new_id (char *id); + // allocate a new ID string and point <id> to it. + +private: + static void get_serial_id (time_t &t, size_t &s); + // Atomically get info required to generate an offer ID. + + static ACE_SYNCH_MUTEX *get_lock (void); + // Get the lock instance. + + static time_t last_time_; + // Record the time last offer ID generated. + + static size_t last_number_; + // Record serial number of last offer ID with same + // generation time. + + static ACE_SYNCH_MUTEX *lock_; + // mutex to access private member. +}; + +#endif /* ACE_ID_GENERATOR_H */ diff --git a/ACE/apps/JAWS/clients/Caching/Local_Locator.cpp b/ACE/apps/JAWS/clients/Caching/Local_Locator.cpp new file mode 100644 index 00000000000..c4502c1bc87 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Local_Locator.cpp @@ -0,0 +1,248 @@ +// $Id$ + +#if !defined (ACE_LOCAL_LOCATOR_C) +#define ACE_LOCAL_LOCATOR_C + +#include "Local_Locator.h" + +#if !defined (__ACE_INLINE__) +#include "Local_Locator.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(Caching, Local_Locator, "$Id$") + +int +ACE_URL_Local_Locator::url_query (const ACE_URL_Locator::ACE_Selection_Criteria how, + const ACE_URL_Property_Seq *pseq, + const size_t how_many, + size_t &num_query, + ACE_URL_Offer_Seq *offer) +{ + ACE_URL_Record *item = 0; + + ACE_NEW_RETURN (offer, ACE_URL_Offer_Seq (how_many), -1); + + if (how >= ACE_URL_Locator::INVALID_SELECTION) + { + errno = ACE_URL_Locator::INVALID_ARGUMENT; + return -1; + } + + num_query = 0; + for (ACE_Unbounded_Set_Iterator<ACE_URL_Record> iter (this->repository_); + iter.next (item) != 0; + iter.advance ()) + { + size_t i_query; + size_t i_db; + int found = 0; + + // Now this is a stupid implementation. Perhaps we can + // implement this using Hash_Map. Better yet, I think we should + // put this in a database and put SQL query here. + for (i_query = 0; found == 0 && i_query < pseq->size (); i_query++) + for (i_db = 0; i_db < item->offer_->url_properties ().size (); i_db++) + { + if ((*pseq)[i_query].name () == item->offer_->url_properties ()[i_db].name ()) + if (how == ACE_URL_Locator::SOME) + ; + + // if match and Some, copy to <offer>, inc <num_query>, advance iterator + + // else if All, advance iterator + + // else if None, check next property in <pseq>. + + if (all properties checked and found and ALL) + copy to <offer>; inc <num_query>; + else if (all properties checked and not found and NONE) + copy to <offer>; inc <num_query>; + else + shouldn't happen, internal error + + if (num_query == how_many) + break; + } + + return 0; +} + +int +ACE_URL_Local_Locator::export_offer (ACE_URL_Offer *offer, + ACE_WString &offer_id) +{ + ACE_URL_Record *item = 0; + + // First check if we have registered this URL already. + for (ACE_Unbounded_Set_Iterator<ACE_URL_Record> iter (this->repository_); + iter.next (item) != 0; + iter.advance ()) + if (*item->offer_->url () == *offer->url ()) + { + errno = ACE_URL_Locator::OFFER_EXIST; + return -1; + } + + ACE_URL_Record *new_offer; + + // Offer is not in repository, we can add new one in safely. + ACE_NEW_RETURN (new_offer, ACE_URL_Record (offer), + ACE_URL_Locator::NOMEM); + + this->repository_.push (*new_offer); + + offer_id = *new_offer->id_; + return 0; +} + +int +ACE_URL_Local_Locator::withdraw_offer (const ACE_WString &offer_id) +{ + ACE_URL_Record *item = 0; + + // Iterate thru repository and remove offer with <offer_id>. + for (ACE_Unbounded_Set_Iterator<ACE_URL_Record> iter (this->repository_); + iter.next (item) != 0; + iter.advance ()) + if (offer_id == *item->id_) + { + if (this->repository_.remove (*item) == 0) + return 0 + else + { + errno = ACE_URL_Locator::UNKNOWN; + return -1; + } + } + + errno = ACE_URL_Locator::NO_SUCH_OFFER; + return 0; +} + +int +ACE_URL_Local_Locator::describe_offer (const ACE_WString &offer_id, + ACE_URL_Offer *offer) +{ + ACE_URL_Record *item = 0; + + // Iterate thru the repository and produce a copy of offer's + // description. + for (ACE_Unbounded_Set_Iterator<ACE_URL_Record> iter (this->repository_); + iter.next (item) != 0; + iter.advance ()) + if (offer_id == *item->id_) + { + ACE_NEW_RETURN (offer, ACE_URL_Offer (*item->offer_), -1); + return 0; + } + + errno = ACE_URL_Locator::NO_SUCH_OFFER; + return -1; +} + +int +ACE_URL_Local_Locator::modify_offer (const ACE_WString &offer_id, + const ACE_WString *url, + const ACE_URL_Property_Seq *del, + const ACE_URL_Property_Seq *modify) +{ + ACE_Unbounded_Set_Iterator<ACE_URL_Record> iter (this->repository_); + ACE_URL_Record *item = 0; + ACE_URL_Record *target = 0; + + // Errno Checking + + for (; iter.next (item) != 0; iter.advance ()) + { + if (url != 0 && *url == item->offer_->url ()) + { + errno = ACE_URL_Locator::OFFER_EXIST; + return -1; + } + if (offer_id == *item->id_) + target = item; + } + + if (target != 0) // Aha, we found a target to work on + { + if (del != 0 && modify != 0) + { + // We need to make a copy of the original property sequence + // so if any error occurs, we can revert our change easily. + + // First we need to calculate the maximum number of perperties. + int psize = target->offer_->url_properties ().size (); + if (del != 0) + if ((psize -= del->size ()) < 0) + { + // If you try to delete more properties than we have, + // you are doomed. No need to proceed. + errno = ACE_URL_Locator::INVALID_ARGUMENT; + return -1; + } + if (modify != 0) + // In the worst case, all properties in <modify> will be added. + psize += modify->size (); + + // Now, create a temporary work space. + ACE_URL_Property_Seq working (psize); + size_t sz = 0; + for (; sz < item->offer_->url_properties ().size ()) + working[sz] = item->offer_->url_properties() [sz]; + + if (del != 0) + { + // Argh, this is really a stupid design. + // Go thru every property we want to delete + for (size_t i = 0; i < del->size () && sz > 0; i++) + // For earch, go thru our property sequence and + // search for the property. + for (size_t j = 0; j < sz; j++) + if ((*del)[i].name () == working[j].name ()) + { + sz -= 1; + working[j] = working[sz]; // pack the array. + break; + } + // Doesn't generate error when we want to delete an + // imaginary property. Is this appropriate? + } + + if (modify != 0) + { + // This is also stupid. + // Go thru every property we want to modify/add + for (size_t i = 0; i < modify->size () && sz > 0; i++) + { + // For each property, go thru our property list + // and search for the matching property + for (size_t j = 0; j < sz; j++) + if ((*modify)[i].name () == working[j].name ()) + { + // A match found. + working[j].value ((*modify)[i].value ().fast_rep ()); + break; + } + + // No matching property name were found, + // We want to add this property into the list. + if (j == sz) + working[sz++] = (*modify)[i]; + } + } + } + + // Yes, all operations passed. We can now copy the working version back. + item->offer_->url_properties (ACE_URL_Property_Seq (sz)); + for (size_t i = 0; i < sz; i ++) + item->offer_->url_properties ()[i] = working[i]; + + if (url != 0) + item->offer_->url (url->fast_rep ()); // replace URL location. + return 0; + } + errno = ACE_URL_Locator::NO_SUCH_OFFER; + return -1; +} + +#endif /* ACE_LOCAL_LOCATOR_C */ diff --git a/ACE/apps/JAWS/clients/Caching/Local_Locator.h b/ACE/apps/JAWS/clients/Caching/Local_Locator.h new file mode 100644 index 00000000000..2c2569db1c8 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Local_Locator.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// Local_Locator.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_LOCAL_LOCATOR_H +#define ACE_LOCAL_LOCATOR_H + +#include "URL_Locator.h" +#include "ace/Containers.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ID_Generator.h" + +class ACE_Svc_Export ACE_URL_Record + // = TITLE + // A URL Record. + // + // = DESCRIPTION + // A record placed in URL repository. Notice that + // both member pointers are own by URL_Record. + // They will get deallocated when the object goes + // out of scope. +{ + friend class ACE_URL_Local_Locator; + friend class ACE_Node<ACE_URL_Record>; + // We are making ACE_Node as friend class because we don't want + // others to access default constructor and pushing in an invalid + // record. However, container classes need to use default constructor + // for its head record. +public: + ACE_URL_Record (ACE_URL_Offer *offer); + // ctor. + + ~ACE_URL_Record (void); + // dtor. + + /// Two records are equal if they have the same offer id. + bool operator== (const ACE_URL_Record &rhs) const; + + /// Unequal, complement of equal. + bool operator!= (const ACE_URL_Record &rhs) const; + + +private: + ACE_URL_Record (void); + // Default ctor. This is put here to prevent users from + // pushing in an invalid record. + + ACE_WString *id_; + // Offer ID in the repository. + + ACE_URL_Offer *offer_; + // Offer (and its properties). +}; + +class ACE_Svc_Export ACE_URL_Local_Locator + // = TITLE + // A simple URL repository to store URL offer locally. + // + // = DESCRIPTION + // This class manage a collection of URL offers + // for local query and registration. But we should + // really use it within a server. +{ + virtual ~ACE_URL_Local_Locator (void); + // Default destructor. + + virtual int url_query (const ACE_URL_Locator::ACE_Selection_Criteria how, + const ACE_URL_Property_Seq *pseq, + const size_t how_many, + size_t &num_query, + ACE_URL_Offer_Seq *offer); + // Query the locator for HTTP with designate properties (none, some, + // or all). The locator being queried will return a sequence of + // offers with <how_many> offers in it. This interface allocates + // <offer> so users must deallocate it after use. + + virtual int export_offer (ACE_URL_Offer *offer, + ACE_WString &offer_id); + // Export an offer to the locator. + + virtual int withdraw_offer (const ACE_WString &offer_id); + // Withdraw an offer. return 0 if succeed, -1 otherwise. + + virtual int describe_offer (const ACE_WString &offer_id, + ACE_URL_Offer *offer); + // Query a specific offer. + + virtual int modify_offer (const ACE_WString &offer_id, + const ACE_WString *url = 0, + const ACE_URL_Property_Seq *del = 0, + const ACE_URL_Property_Seq *modify = 0); + // Modify a previously registered offer. + +protected: + ACE_Unbounded_Set<ACE_URL_Record> repository_; +}; + +#if defined (__ACE_INLINE__) +#include "Local_Locator.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_LOCAL_LOCATOR_H */ diff --git a/ACE/apps/JAWS/clients/Caching/Local_Locator.i b/ACE/apps/JAWS/clients/Caching/Local_Locator.i new file mode 100644 index 00000000000..0ef8e595f86 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Local_Locator.i @@ -0,0 +1,43 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_INLINE +ACE_URL_Record::ACE_URL_Record (void) + : id_ (0), + offer_ (0) +{ +} + +ACE_INLINE +ACE_URL_Record::ACE_URL_Record (ACE_URL_Offer *offer) + : offer_ (offer) +{ + char buf[ACE_OFFER_ID_LENGTH]; + + ACE_NEW (this->id_, ACE_WString (ACE_ID_Generator::get_new_id (buf))); +} + +ACE_INLINE +ACE_URL_Record::~ACE_URL_Record (void) +{ + delete this->id_; + delete this->offer_; +} + +ACE_INLINE bool +ACE_URL_Record::operator== (const ACE_URL_Record &rhs) const +{ + return this == &rhs || *this->id_ == *rhs.id_; +} + +ACE_INLINE bool +ACE_URL_Record::operator!= (const ACE_URL_Record &rhs) const +{ + return !(*this == rhs); +} + +ACE_INLINE +ACE_URL_Local_Locator::~ACE_URL_Local_Locator (void) +{ +} diff --git a/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.cpp b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.cpp new file mode 100644 index 00000000000..6f7a7898e59 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.cpp @@ -0,0 +1,459 @@ +// $Id$ + +#if !defined (ACE_LOCATOR_REQUEST_REPLY_C) +#define ACE_LOCATOR_REQUEST_REPLY_C + +#include "Locator_Request_Reply.h" + +#if !defined (__ACE_INLINE__) +#include "Locator_Request_Reply.i" +#endif + +#include "ace/Auto_Ptr.h" +#include "URL_Properties.h" +#include "URL_Array_Helper.h" +#include "URL_Locator.h" + +ACE_RCSID(Caching, Locator_Request_Reply, "$Id$") + +int +ACE_URL_Locator_Request::url_query (const int how, + const ACE_URL_Property_Seq &pseq, + const int how_many) +{ + ACE_TRACE ("ACE_URL_Locator_Request::url_query"); + + if (how >= ACE_URL_Locator::INVALID_SELECTION) + return -1; + ACE_NEW_RETURN (this->seq1_, ACE_URL_Property_Seq (pseq), -1); + this->how_ = how; + this->how_many_ = how_many; + this->code_ = ACE_URL_Locator::QUERY; + return 0; +} + +int +ACE_URL_Locator_Request::export_offer (const ACE_URL_Offer &offer) +{ + ACE_TRACE ("ACE_URL_Locator_Request::export_offer"); + + ACE_NEW_RETURN (this->offer_, ACE_URL_Offer (offer), -1); + this->code_ = ACE_URL_Locator::EXPORT; + return 0; +} + +int +ACE_URL_Locator_Request::withdraw_offer (const ACE_WString &offer_id) +{ + ACE_TRACE ("ACE_URL_Locator_Request::withdraw_offer"); + + this->id_ = offer_id; + this->code_ = ACE_URL_Locator::WITHDRAW; + return 0; +} + +int +ACE_URL_Locator_Request::describe_offer (const ACE_WString &offer_id) +{ + ACE_TRACE ("ACE_URL_Locator_Request::describe_offer"); + + this->id_ = offer_id; + this->code_ = ACE_URL_Locator::DESCRIBE; + return 0; +} + +int +ACE_URL_Locator_Request::modify_offer (const ACE_WString &offer_id, + const ACE_WString *url, + const ACE_URL_Property_Seq &del, + const ACE_URL_Property_Seq &modify) +{ + ACE_TRACE ("ACE_URL_Locator_Request::modify_offer"); + + ACE_NEW_RETURN (this->seq1_, ACE_URL_Property_Seq (del), -1); + ACE_NEW_RETURN (this->seq2_, ACE_URL_Property_Seq (modify), -1); + + if (url != 0) + this->url_ = *url; + + this->id_ = offer_id; + this->code_ = ACE_URL_Locator::MODIFY; + return 0; +} + +#define ENCODE_UINT32(ADDR,LEN,V) \ + * (ACE_UINT32 *) (ADDR+LEN) = htonl (V); \ + LEN += sizeof (ACE_UINT32); + +#define DECODE_UINT32(ADDR,LEN,V) \ + V = ntohl (* (ACE_UINT32 *) (ADDR+LEN)); \ + LEN += sizeof (ACE_UINT32); + +size_t +ACE_URL_Locator_Request::encode (void) +{ + ACE_TRACE ("ACE_URL_Locator_Request::encode"); + + size_t buf_size = this->size (); + size_t total_length = 0; + + ACE_NEW_RETURN (this->buffer_, char [buf_size], 0); + + ENCODE_UINT32 (this->buffer_, total_length, buf_size); + // Encode buffer size. + + ENCODE_UINT32 (this->buffer_, total_length, this->code_); + // Encode Op code. + + ENCODE_UINT32 (this->buffer_, total_length, this->how_); + // Encode selection criteria. + + ENCODE_UINT32 (this->buffer_, total_length, this->how_many_); + // Encode number of offers interested. + + ENCODE_UINT32 (this->buffer_, total_length, this->valid_ptr_); + // Encode valide pointer flag. + + if (this->seq1_ != 0) + { + ENCODE_UINT32 (this->buffer_, total_length, this->seq1_->size ()); + total_length += ace_array_encode (this->buffer_ + total_length, *this->seq1_); + } + if (this->seq2_ != 0) + { + ENCODE_UINT32 (this->buffer_, total_length, this->seq2_->size ()); + total_length += ace_array_encode (this->buffer_ + total_length, *this->seq2_); + } + if (this->offer_ != 0) + total_length += this->offer_->encode (this->buffer_ + total_length); + + total_length += ACE_WString_Helper::encode (this->buffer_ + total_length, + this->id_); + total_length += ACE_WString_Helper::encode (this->buffer_ + total_length, + this->url_); + + ACE_ASSERT (total_length == buf_size); + return total_length; +} + +size_t +ACE_URL_Locator_Request::decode (void *buffer) +{ + ACE_TRACE ("ACE_URL_Locator_Request::decode"); + + if (buffer == 0) + return 0; + // Check if we have a valid buffer available. + + char *cbuffer = (char *) buffer; + + size_t buf_size; + size_t total_length = 0; + + DECODE_UINT32 (cbuffer, total_length, buf_size); + // Decode length of buffer size first. + + DECODE_UINT32 (cbuffer, total_length, this->code_); + // Get the operation code. + + DECODE_UINT32 (cbuffer, total_length, this->how_); + // Decode selection criteria. + + DECODE_UINT32 (cbuffer, total_length, this->how_many_); + // Decode number of offers interested. + + DECODE_UINT32 (cbuffer, total_length, this->valid_ptr_); + // Decode valide pointer flag. + + if ((this->valid_ptr_ & VALID_SEQ1) != 0) + { + size_t n; + DECODE_UINT32 (cbuffer, total_length, n); + ACE_NEW_RETURN (this->seq1_, ACE_URL_Property_Seq (n), 0); + total_length += ace_array_decode (cbuffer + total_length, *this->seq1_); + } + if ((this->valid_ptr_ & VALID_SEQ2) != 0) + { + size_t n; + DECODE_UINT32 (cbuffer, total_length, n); + ACE_NEW_RETURN (this->seq2_, ACE_URL_Property_Seq (n), 0); + total_length += ace_array_decode (cbuffer + total_length, *this->seq2_); + } + if ((this->valid_ptr_ & VALID_OFFER) != 0) + { + ACE_NEW_RETURN (this->offer_, ACE_URL_Offer, 0); + total_length += this->offer_->decode (cbuffer + total_length); + } + + this->id_ = ACE_WString ((ACE_USHORT16 *) (cbuffer + total_length)); + total_length += ACE_WString_Helper::decode (cbuffer + total_length); + this->url_ = ACE_WString ((ACE_USHORT16 *) (cbuffer + total_length)); + total_length += ACE_WString_Helper::decode (cbuffer + total_length); + + ACE_ASSERT (total_length == buf_size); + return total_length; +} + + +size_t +ACE_URL_Locator_Request::size (void) +{ + ACE_TRACE ("ACE_URL_Locator_Request::size"); + + size_t total_length = 5 * sizeof (ACE_UINT32); + // There are 5 UINT32 variables at the beginning + // of the buffer. <buffer size>, <code>, <how>, + // <how_many>, <valid_ptr>. + + this->valid_ptr_ = 0; + // Check valid pointers and mark corresponding flag in <valid_prt>. + + if (this->seq1_ != 0) + { + this->valid_ptr_ |= VALID_SEQ1; + total_length += ace_array_size (*this->seq1_); + } + if (this->seq2_ != 0) + { + this->valid_ptr_ |= VALID_SEQ2; + total_length += ace_array_size (*this->seq2_); + } + if (this->offer_ != 0) + { + this->valid_ptr_ |= VALID_OFFER; + total_length += this->offer_->size (); + } + + total_length += ACE_WString_Helper::size (this->id_); + total_length += ACE_WString_Helper::size (this->url_); + + return total_length; +} + +void +ACE_URL_Locator_Request::dump (void) const +{ + //ACE_TRACE ("ACE_URL_Locator_Request::dump"); + + size_t i; + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + if (this->code_ < ACE_URL_Locator::INVALID_OPERATION) + ACE_DEBUG ((LM_DEBUG, "%s Request:\n", ACE_URL_Locator::opname[this->code_])); + else + ACE_DEBUG ((LM_DEBUG, "Invalid Operation: %d\n", this->code_)); + + if (this->how_ < ACE_URL_Locator::INVALID_SELECTION) + ACE_DEBUG ((LM_DEBUG, "Select: %s\n", ACE_URL_Locator::selection_name[this->how_])); + else + ACE_DEBUG ((LM_DEBUG, "Invalid selection method: %d\n", this->how_)); + + ACE_DEBUG ((LM_DEBUG, "At most %d reply.\n", this->how_many_)); + + ACE_DEBUG ((LM_DEBUG, "Valid pointer pattern: %x\n", this->valid_ptr_)); + + ACE_DEBUG ((LM_DEBUG, "Property sequence 1: %x\n", this->seq1_)); + if (this->seq1_ != 0) + for (i = 0; i < this->seq1_->size (); i++) + (*this->seq1_)[i].dump (); + + ACE_DEBUG ((LM_DEBUG, "Property sequence 2: %x\n", this->seq2_)); + if (this->seq2_ != 0) + for (i = 0; i < this->seq2_->size (); i++) + (*this->seq2_)[i].dump(); + + ACE_DEBUG ((LM_DEBUG, "Offer: %x\n", this->offer_)); + if (this->offer_ != 0) + this->offer_->dump (); + + if (this->id_.length () > 0) + ACE_DEBUG ((LM_DEBUG, "Offer ID: %s\n", + ACE_Auto_Basic_Array_Ptr<char> (this->id_.char_rep ()).get ())); + else + ACE_DEBUG ((LM_DEBUG, "Offer ID: \"\"\n")); + + if (this->url_.length () > 0) + ACE_DEBUG ((LM_DEBUG, "URL: %s\n", + ACE_Auto_Basic_Array_Ptr<char> (this->url_.char_rep ()).get ())); + else + ACE_DEBUG ((LM_DEBUG, "URL: \"\"\n")); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_URL_Locator_Reply::status_reply (u_int op, int result) +{ + ACE_TRACE ("ACE_URL_Locator_Reply::status_reply"); + + this->code_ = op; + this->status_ = result; + return 0; +} + +int +ACE_URL_Locator_Reply::query_reply (int result, size_t num, + const ACE_URL_Offer_Seq &offers) +{ + ACE_TRACE ("ACE_URL_Locator_Reply::query_reply"); + + this->code_ = ACE_URL_Locator::QUERY; + this->status_ = result; + ACE_NEW_RETURN (this->offers_, ACE_URL_Offer_Seq (offers), -1); + return 0; +} + +int +ACE_URL_Locator_Reply::describe_reply (int result, + const ACE_URL_Offer &offer) +{ + ACE_TRACE ("ACE_URL_Locator_Reply::describe_reply"); + + this->code_ = ACE_URL_Locator::DESCRIBE; + this->status_ = result; + ACE_NEW_RETURN (this->offer_, ACE_URL_Offer (offer), -1); + return 0; +} + +size_t +ACE_URL_Locator_Reply::encode (void) +{ + ACE_TRACE ("ACE_URL_Locator_Reply::encode"); + + size_t buf_size = this->size (); + size_t total_length = 0; + + ACE_NEW_RETURN (this->buffer_, char [buf_size], 0); + + ENCODE_UINT32 (this->buffer_, total_length, buf_size); + // Encode buffer size. + + ENCODE_UINT32 (this->buffer_, total_length, this->code_); + // Encode Op code. + + ENCODE_UINT32 (this->buffer_, total_length, this->status_); + // Encode Op result status. + + ENCODE_UINT32 (this->buffer_, total_length, this->num_offers_); + // Encode number of offers in this->offers_. + + ENCODE_UINT32 (this->buffer_, total_length, this->valid_ptr_); + // Encode valid pointers mask. + + if (this->offer_ != 0) + total_length += this->offer_->encode (this->buffer_ + total_length); + + if (this->offers_ != 0) + { + ENCODE_UINT32 (this->buffer_, total_length, this->offers_->size ()); + total_length += ace_array_encode (this->buffer_ + total_length, *this->offers_); + } + + ACE_ASSERT (total_length == buf_size); + return 0; +} + +size_t +ACE_URL_Locator_Reply::decode (void *buffer) +{ + ACE_TRACE ("ACE_URL_Locator_Reply::decode"); + + if (buffer == 0) + return 0; + // Check if we have a buffer available. + + char *cbuffer = (char *) buffer; + + size_t buf_size; + size_t total_length = 0; + + DECODE_UINT32 (cbuffer, total_length, buf_size); + // Get the length of the buffer first. + + DECODE_UINT32 (cbuffer, total_length, this->code_); + // Decode Op code. + + DECODE_UINT32 (cbuffer, total_length, this->status_); + // Decode Op result status. + + DECODE_UINT32 (cbuffer, total_length, this->num_offers_); + // Decode number of offers in this->offers_. + + DECODE_UINT32 (cbuffer, total_length, this->valid_ptr_); + // Decode valid pointers mask. + + if ((this->valid_ptr_ & VALID_OFFER) != 0) + { + ACE_NEW_RETURN (this->offer_, ACE_URL_Offer, 0); + total_length += this->offer_->decode (cbuffer + total_length); + } + + if ((this->valid_ptr_ & VALID_OFFERS) != 0) + { + size_t n; + DECODE_UINT32 (cbuffer, total_length, n); + ACE_NEW_RETURN (this->offers_, ACE_URL_Offer_Seq (n), 0); + total_length += ace_array_decode (cbuffer + total_length, *this->offers_); + } + + ACE_ASSERT (total_length ==buf_size); + return 0; +} + +size_t +ACE_URL_Locator_Reply::size (void) +{ + ACE_TRACE ("ACE_URL_Locator_Reply:size"); + + size_t total_length = 5 * sizeof (ACE_UINT32); + // size for 5 ACE_UINT32 objects: <buffer size>, <code_>, + // <status_>, <num_offers_>, and <valid_ptr_>. + + this->valid_ptr_ = 0; + if (this->offer_ != 0) + { + this->valid_ptr_ |= VALID_OFFER; + total_length += this->offer_->size (); + } + if (this->offers_ != 0) + { + this->valid_ptr_ |= VALID_OFFERS; + total_length += ace_array_size (*this->offers_); + } + return total_length; +} + +void +ACE_URL_Locator_Reply::dump (void) const +{ + //ACE_TRACE ("ACE_URL_Locator_Reply::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + if (this->code_ < ACE_URL_Locator::INVALID_OPERATION) + ACE_DEBUG ((LM_DEBUG, "Original request: %s\n", ACE_URL_Locator::opname[this->code_])); + else + ACE_DEBUG ((LM_DEBUG, "Invalid Original Request: %d\n", this->code_)); + + if (this->status_ < ACE_URL_Locator::MAX_URL_ERROR) + ACE_DEBUG ((LM_DEBUG, "Reply status: %s\n", ACE_URL_Locator::err_name[this->status_])); + else + ACE_DEBUG ((LM_DEBUG, "Invalid reply status: %d\n", this->status_)); + + ACE_DEBUG ((LM_DEBUG, "Number of offers: %d\n", this->num_offers_)); + + ACE_DEBUG ((LM_DEBUG, "Valid pointer pattern: %x\n", this->valid_ptr_)); + + ACE_DEBUG ((LM_DEBUG, "Offer: %x\n", this->offer_)); + if (this->offer_ != 0) + this->offer_->dump (); + + ACE_DEBUG ((LM_DEBUG, "Offer sequence: %x\n", this->offers_)); + if (this->offers_ != 0) + for (size_t i = 0; i < this->offers_->size (); i++) + (*this->offers_)[i].dump(); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} +#endif /* ACE_LOCATOR_REQUEST_REPLY_C */ diff --git a/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.h b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.h new file mode 100644 index 00000000000..057607c351d --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.h @@ -0,0 +1,220 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// Locator_Request_Response.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_LOCATOR_REQUEST_REPLY_H +#define ACE_LOCATOR_REQUEST_REPLY_H + +#include "URL_Properties.h" + +class ACE_Svc_Export ACE_URL_Locator_Request + // = TITLE + // A URL request message formater/wrapper. + // + // = DESCRIPTION + // This class defines a URL request data. It is used + // to transform requests to an object so that we can + // ship them across network. +{ +public: + ACE_URL_Locator_Request (void); + // Default ctor. + + ~ACE_URL_Locator_Request (void); + // Default dtor. + + int url_query (const int how, + const ACE_URL_Property_Seq &pseq, + const int how_many); + // Query the locator for HTTP with designate properties (none, some, + // or all). The locator being queried will return a sequence of + // offers with <how_many> offers in it. This interface allocates + // <offer> so users must deallocate it after use. + + int export_offer (const ACE_URL_Offer &offer); + // Export an offer to the locator. + + int withdraw_offer (const ACE_WString &offer_id); + // Withdraw an offer. return 0 if succeed, -1 otherwise. + + int describe_offer (const ACE_WString &offer_id); + // Query a specific offer. + + int modify_offer (const ACE_WString &offer_id, + const char *url = 0, + const ACE_URL_Property_Seq &del = 0, + const ACE_URL_Property_Seq &modify = 0); + // Modify a previously registered offer. + + int modify_offer (const ACE_WString &offer_id, + const ACE_WString *url = 0, + const ACE_URL_Property_Seq &del = 0, + const ACE_URL_Property_Seq &modify = 0); + // Modify a previously registered offer. + + size_t encode (void); + // Encode request for network communication. If succeed, + // returns the size of the buffer, otherwise, return 0. + + size_t decode (void *buffer); + // Restore from network data. Returns size of the buffer + // if succeed, 0 otherwise. When passing in a buffer, + // caller must take the responsibility to delete the buffer + // afterward, if so needed. + + const int how (void) const; + const int how_many (void) const; + const u_int opcode (void) const; + const ACE_URL_Property_Seq *seq (void) const; + const ACE_URL_Property_Seq *del (void) const; + const ACE_URL_Property_Seq *modify (void) const; + const ACE_URL_Offer *offer (void) const; + const ACE_WString &id (void) const; + const ACE_WString &url (void) const; + const char *buffer (void) const; + // A bunch of methods to access internal data. + + void dump (void) const; + // Print out this object. + +protected: + size_t size (void); + // Return the size of the buffer required to encode + // this request. + + enum { + VALID_SEQ1 = 0x1, + VALID_SEQ2 = 0X2, + VALID_OFFER = 0X4 + }; + // These constants used to indicate which pointers are valid. + + u_int code_; + // Request type code. + + int how_; + // Query method (if code_ == QUERY.) + + int how_many_; + // How many offers are we interested in in this query. + + int valid_ptr_; + // Bit flag to mark valid pointers within this object. + + ACE_URL_Property_Seq *seq1_; + // For query or del in modify_offer. + + ACE_URL_Property_Seq *seq2_; + // For modify seq. in modify_offer. + + ACE_URL_Offer *offer_; + // Offer to export. + + ACE_WString id_; + // Offer ID. + + ACE_WString url_; + // URL of this offer. + + char *buffer_; + // Buffer to store encoded data. +}; + +class ACE_Svc_Export ACE_URL_Locator_Reply + // = TITLE + // A URL reply message formater/wrapper. + // + // = DESCRIPTION + // This class defines a URL reply data. It is used + // to transform reply messages to an object so that we can + // ship them across network. +{ +public: + ACE_URL_Locator_Reply (void); + // Default ctor. + + ~ACE_URL_Locator_Reply (void); + // Default dtor. + + int status_reply (u_int op, int result); + // Setup a reply message for EXPORT, WITHDRAW, or MODIFY operations. + + int query_reply (int result, size_t num, + const ACE_URL_Offer_Seq &offers); + // Setup a reply for QUERY operation. + + int describe_reply (int result, + const ACE_URL_Offer &offer); + // Construct a reply for DESCRIBE operation. + + size_t encode (void); + // Encode request for network communication. If succeed, + // returns the size of the buffer, otherwise, return 0. + + size_t decode (void *buffer); + // Restore from network data. Returns size of the buffer + // if succeed, 0 otherwise. When passing in a buffer, + // caller must take the responsibility to delete the buffer + // afterward, if so needed. + + // Accessor function. + const size_t num_offers (void) const; + const ACE_URL_Offer *offer (void) const; + const ACE_URL_Offer_Seq *offers (void) const; + const u_int opcode (void) const; + const u_int status (void) const; + const char *buffer (void) const ; + + void dump (void) const ; + // Print out this object. + +protected: + size_t size (void); + // Return the size of the buffer required to encode + // this request. + + enum { + VALID_OFFER = 0x1, + VALID_OFFERS = 0x2 + }; + // Valid pointer masks. + + u_int code_; + // Holds the original op code. + + int status_; + // Holds the result of an operation from the Location Server. + + size_t num_offers_; + // Holds the number of valid offers in the offers_ sequence. + + int valid_ptr_; + // Flag that marks valid internal pointers. + + ACE_URL_Offer *offer_; + // Holds a single offer. Used in query offer property. + + ACE_URL_Offer_Seq *offers_; + // Holds the replying offer sequence from a Locator. + + char *buffer_; + // Buffer to store encoded data. +}; +#if defined (__ACE_INLINE__) +#include "Locator_Request_Reply.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_LOCATOR_REQUEST_REPLY_H */ diff --git a/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.i b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.i new file mode 100644 index 00000000000..9dd2f851ceb --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Locator_Request_Reply.i @@ -0,0 +1,138 @@ +/* -*- C++ -*- */ + +// $Id$ + +#include "URL_Locator.h" + +ACE_INLINE +ACE_URL_Locator_Request::ACE_URL_Locator_Request (void) + : code_(ACE_URL_Locator::INVALID_OPERATION), + seq1_ (0), + seq2_ (0), + offer_ (0), + buffer_ (0) +{ +} + +ACE_INLINE +ACE_URL_Locator_Request::~ACE_URL_Locator_Request (void) +{ + delete this->seq1_; + delete this->seq2_; + delete this->offer_; + delete [] this->buffer_; +} + +ACE_INLINE const int +ACE_URL_Locator_Request::how (void) const +{ + return this-> how_; +} + +ACE_INLINE const int +ACE_URL_Locator_Request::how_many (void) const +{ + return this->how_many_; +} + +ACE_INLINE const u_int +ACE_URL_Locator_Request::opcode (void) const +{ + return this->code_; +} + +ACE_INLINE const ACE_URL_Property_Seq * +ACE_URL_Locator_Request::seq (void) const +{ + return this->seq1_; +} + +ACE_INLINE const ACE_URL_Property_Seq * +ACE_URL_Locator_Request::del (void) const +{ + return this->seq1_; +} + +ACE_INLINE const ACE_URL_Property_Seq * +ACE_URL_Locator_Request::modify (void) const +{ + return this->seq2_; +} + +ACE_INLINE const ACE_URL_Offer * +ACE_URL_Locator_Request::offer (void) const +{ + return this->offer_; +} + +ACE_INLINE const ACE_WString & +ACE_URL_Locator_Request::id (void) const +{ + return this->id_; +} + +ACE_INLINE const ACE_WString & +ACE_URL_Locator_Request::url (void) const +{ + return this->url_; +} + +ACE_INLINE const char * +ACE_URL_Locator_Request::buffer (void) const +{ + return this->buffer_; +} + +ACE_INLINE +ACE_URL_Locator_Reply::ACE_URL_Locator_Reply (void) + : code_ (ACE_URL_Locator::INVALID_OPERATION), + offer_ (0), + offers_ (0), + buffer_ (0) +{ +} + +ACE_INLINE +ACE_URL_Locator_Reply::~ACE_URL_Locator_Reply (void) +{ + delete this->offer_; + delete this->offers_; + delete [] this->buffer_; +} + +ACE_INLINE const size_t +ACE_URL_Locator_Reply::num_offers (void) const +{ + return this->num_offers_; +} + + +ACE_INLINE const ACE_URL_Offer * +ACE_URL_Locator_Reply::offer (void) const +{ + return this->offer_; +} + +ACE_INLINE const ACE_URL_Offer_Seq * +ACE_URL_Locator_Reply::offers (void) const +{ + return this->offers_; +} + +ACE_INLINE const u_int +ACE_URL_Locator_Reply::opcode (void) const +{ + return this->code_; +} + +ACE_INLINE const u_int +ACE_URL_Locator_Reply::status (void) const +{ + return this->status_; +} + +ACE_INLINE const char * +ACE_URL_Locator_Reply::buffer (void) const +{ + return this->buffer_; +} diff --git a/ACE/apps/JAWS/clients/Caching/Makefile.am b/ACE/apps/JAWS/clients/Caching/Makefile.am new file mode 100644 index 00000000000..d7f00231ad6 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/Makefile.am @@ -0,0 +1,44 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu + +ACE_BUILDDIR = $(top_builddir) +ACE_ROOT = $(top_srcdir) + + +## Makefile.http_client.am + +if BUILD_ACE_FILECACHE +if !BUILD_ACE_FOR_TAO +noinst_LTLIBRARIES = libhttp_client.la + +libhttp_client_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) + +libhttp_client_la_SOURCES = \ + http_client.cpp \ + http_handler.cpp + +noinst_HEADERS = \ + Local_Locator.i \ + Locator_Request_Reply.i \ + URL_Properties.i \ + http_handler.h + +endif !BUILD_ACE_FOR_TAO +endif BUILD_ACE_FILECACHE + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/ACE/apps/JAWS/clients/Caching/README b/ACE/apps/JAWS/clients/Caching/README new file mode 100644 index 00000000000..3dcfcd32815 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/README @@ -0,0 +1,83 @@ +# -*- text -*- +# Hey, Emacs! This is a TEXT file. + +---------------------------------- +README for the caching http_client +---------------------------------- + +This is the README file for the simple caching http_client. + +------------ +1. Compiling +------------ + +1a. Compiling on UNIX. + + On UNIX, with a properly configured ACE distribution, just +type make (using GNU make, of course). + +1b. Compiling on NT. + + Thus far, this code has only been tested under UNIX. A +Windows NT version will be out soon. + +------------ +2. Executing +------------ + +2a. Command line parameters. + + The program does not support any command line parameters. + +2b. General information. + + When the program runs, the client offers a ``*'' as a prompt. +At the prompt, you may enter a URL. The client will check to see if +the filename portion of the URL has already been cached. If so, a +message appears saying so. If not, the client will fetch the file +from the HTTP server and then cache it. + + Furthermore, the client supports the ``!'' shell escape +command. The content after the ``!'' will be executed by a shell. + + To exit the session, send the end-of-file character +(typically, ^D in UNIX). + + unix$ ./http_client + * http://www.cs.wustl.edu/cs/Art/brookings.gif + [1] sending request -- + GET /cs/Art/brookings.gif HTTP/1.0 + Accept: HTTP/1.0 + + ``brookings.gif'' is now cached. + * http://www.cs.wustl.edu/cs/Art/brookings.gif + ``brookings.gif'' is already cached. + * !ls + Makefile http_client http_handler.cpp zJAWSAAAa000Yg + brookings.gif http_client.cpp http_handler.h + * ^D + Bye! + unix$ ls + Makefile http_client http_handler.cpp + brookings.gif http_client.cpp http_handler.h + unix$ + +-------------- +3. Limitations +-------------- + + The caching mechanism as currently implemented requires a +``Content-length:'' to appear in the response header of the HTTP +response. This is because the caching utilizes mmap () to allocate +space for the file to be cached before the file is received. Unitl +the caching mecahnism is extended, you are limited to using servers +which will report the size of the file being transmitted. + + Currently, the cache creates temporary files (see the above +sample execution). + + The cache is not persistent between executions. + + Suggestions and other correspondence should be sent to me: + +James Hu <jxh@cs.wustl.edu> diff --git a/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.cpp b/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.cpp new file mode 100644 index 00000000000..c8dbb55e197 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.cpp @@ -0,0 +1,43 @@ +// $Id$ + +// URL_Array_Helper.cpp + +#ifndef ACE_URL_ARRAY_HELPER_C +#define ACE_URL_ARRAY_HELPER_C + +#include "URL_Array_Helper.h" + +ACE_RCSID(Caching, URL_Array_Helper, "$Id$") + +// Some helper functions for encoding/decoding + +template <class T> +size_t ace_array_size (const T &x) +{ + size_t sum = sizeof (ACE_UINT32); + for (size_t i = 0; i < x.size (); i++) + sum += x[i].size (); + return sum; +} + +template <class T> +size_t ace_array_encode (void *buf, const T &x) +{ + size_t len = 0; + for (size_t i = 0; i < x.size (); i++) + len+= x[i].encode ((void *) ((char *) buf + len)); + return len ; +} + +template <class T> +size_t ace_array_decode (void *buf, T &x) +{ + size_t len = 0; + for (size_t i = 0; i < x.size (); i++) + len += x[i].decode ((void *) ((char *) buf + len)); + return len; +} + + + +#endif /* ACE_URL_ARRAY_HELPER_C */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.h b/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.h new file mode 100644 index 00000000000..f38f9ebf5dd --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Array_Helper.h @@ -0,0 +1,40 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// URL_Array_Helper.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_URL_ARRAY_HELPER_H +#define ACE_URL_ARRAY_HELPER_H + +// ### These template functions are probably named improperly. +// You should find some way to avoid name space polution. + +template <class T> +size_t ace_array_size (const T &x); + +template <class T> +size_t ace_array_encode (void *buf, const T &x); + +template <class T> +size_t ace_array_decode (void *buf, T &x); + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "URL_Array_Helper.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("URL_Array_Helper.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_URL_ARRAY_HELPER_H */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Locator.cpp b/ACE/apps/JAWS/clients/Caching/URL_Locator.cpp new file mode 100644 index 00000000000..e7f6fb6c05b --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Locator.cpp @@ -0,0 +1,52 @@ +// $Id$ + +#if !defined (ACE_URL_LOCATOR_C) +#define ACE_URL_LOCATOR_C + +#include "URL_Locator.h" + +ACE_RCSID(Caching, URL_Locator, "$Id$") + +const char * const +ACE_URL_Locator::opname[] = +// Human readable operation name +{ + "Query", + "Export", + "Withdraw", + "Describe", + "Modify", + "Invalid Operation" +}; + +const char * const +ACE_URL_Locator::selection_name[] = +{ + "None", + "Some", + "All", + "Invalid Selection" +}; + +const char * const +ACE_URL_Locator::err_name[] = +{ + "No error", + "Offer already exist", + "no such offer", + "invalid argument", + "function not implemented", + "unknown error" +}; + +ACE_URL_Locator::~ACE_URL_Locator (void) +{ +} + +const char * +ACE_URL_Locator::error_status (void) +{ + return "Not implemented yet."; +} + +#endif /* ACE_URL_LOCATOR_C */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Locator.h b/ACE/apps/JAWS/clients/Caching/URL_Locator.h new file mode 100644 index 00000000000..751de52cfe5 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Locator.h @@ -0,0 +1,112 @@ +/* -*- C++ -*- */ + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// URL_Locator.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_URL_LOCATOR_H +#define ACE_URL_LOCATOR_H + +#include "URL_Properties.h" + +class ACE_Svc_Export ACE_URL_Locator + // = TITLE + // Abstract Base class designates what interfaces a URL_Locator + // should provide. + // + // = DESCRIPTION + // This class defines the basic URL_Locator APIs. + // An URL locator provides services for URL clients to + // query specific URL location that has certain properties + // and URL providers to export their services and a set of + // APIs to maintain their offers. +{ +public: + // Request type + enum ACE_URL_Locator_Op_Type + { + QUERY = 0, + EXPORT, + WITHDRAW, + DESCRIBE, + MODIFY, + INVALID_OPERATION // LAST + }; + + static const char * const opname[]; + // Human Readable operation name. + + // = Specify how to select offers. + enum ACE_Selection_Criteria + { + NONE = 0, // URL that contains none of the properties. + SOME, // URL that contains some of the properties. + ALL, // URL that contains all of the properties. + INVALID_SELECTION // Invalid. + }; + + static const char * const selection_name[]; + + enum ACE_URL_Locator_Error + // errno will set to one of these value. + { + OK, // Everything is fine. + OFFER_EXIST, // trying to register an offer. + // that is already exist in repository. + NO_SUCH_OFFER, // No such offer in the repository. + INVALID_ARGUMENT, // Invalid argument encountered. + UNIMPLEMENTED, // function not implemented. + UNKNOWN, // Unknown error. + MAX_URL_ERROR + }; + // Possible error code of URL_Locator. + + static const char * const err_name[]; + // Human readable error status. + + virtual ~ACE_URL_Locator (void) = 0; + // Default destructor. + + virtual int url_query (const ACE_Selection_Criteria how, + const ACE_URL_Property_Seq *pseq, + const size_t how_many, + size_t &num_query, + ACE_URL_Offer_Seq *offer) = 0; + // Query the locator for HTTP with designate properties (none, some, + // or all). The locator being queried will return a sequence of + // offers with <how_many> offers in it. This interface allocates + // <offer> so users must deallocate it after use. + + virtual int export_offer (ACE_URL_Offer *offer, + ACE_WString &offer_id) = 0; + // Export an offer to the locator. + + virtual int withdraw_offer (const ACE_WString &offer_id) = 0; + // Withdraw an offer. return 0 if succeed, -1 otherwise. + + virtual int describe_offer (const ACE_WString &offer_id, + ACE_URL_Offer *offer) = 0; + // Query a specific offer. + + virtual int modify_offer (const ACE_WString &offer_id, + const ACE_WString *url = 0, + const ACE_URL_Property_Seq *del = 0, + const ACE_URL_Property_Seq *modify = 0) = 0; + // Modify a previously registered offer. + + virtual const char *error_status (void); + // Provide a human readable error status. +}; + +#endif /* ACE_WEB_LOCATOR_H */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Properties.cpp b/ACE/apps/JAWS/clients/Caching/URL_Properties.cpp new file mode 100644 index 00000000000..6568fb0ff8d --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Properties.cpp @@ -0,0 +1,139 @@ +// $Id$ + +#if !defined (ACE_URL_PROPERTIES_C) +#define ACE_URL_PROPERTIES_C + +#include "URL_Properties.h" + +#if !defined (__ACE_INLINE__) +#include "URL_Properties.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/Auto_Ptr.h" +#include "URL_Array_Helper.h" + +ACE_RCSID(Caching, URL_Properties, "$Id$") + +size_t +ACE_WString_Helper::encode (void *buf, const ACE_WString &wstr) +{ + ACE_USHORT16 *wptr = (ACE_USHORT16 *) buf; + size_t i; + + for (i= 0; i <= wstr.length (); i++) + wptr[i] = htons (wstr[i]); + + return i * sizeof (ACE_USHORT16); +} + +size_t +ACE_WString_Helper::decode (void *buf) +{ + ACE_USHORT16 *wptr = (ACE_USHORT16 *) buf; + size_t i; + + for (i = 0; wptr[i] != 0; i++) + wptr[i] = ntohs (wptr[i]); + + return (i + 1) * sizeof (ACE_USHORT16); +} + +size_t +ACE_URL_Property::encode (void *buf) const +{ + size_t blen = ACE_WString_Helper::encode (buf, this->name_); + blen += ACE_WString_Helper::encode ((void *) ((char *) buf + blen), + this->value_); + return blen; +} + +size_t +ACE_URL_Property::decode (void *buf) +{ + char *cbuf = (char *) buf; + size_t len = ACE_WString_Helper::decode(buf); + this->name ((ACE_USHORT16 *) cbuf); + + cbuf += len; + len += ACE_WString_Helper::decode ((void *) cbuf); + this->value ((ACE_USHORT16 *) cbuf); + return len; +} + +void +ACE_URL_Property::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + if (this->name_.length () > 0) + ACE_DEBUG ((LM_DEBUG, "\n name_: \"%s\"\n", + ACE_Auto_Basic_Array_Ptr<char> (this->name_.char_rep ()).get ())); + else + ACE_DEBUG ((LM_DEBUG, "\n name_: \"\"\n")); + + if (this->value_.length () > 0) + ACE_DEBUG ((LM_DEBUG, " value_: \"%s\"\n", + ACE_Auto_Basic_Array_Ptr<char> (this->value_.char_rep ()).get ())); + else + ACE_DEBUG ((LM_DEBUG, " value_: \"\"\n")); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +size_t +ACE_URL_Offer::size (void) const +{ + size_t sum = (this->url_.length () + 1) * sizeof (ACE_USHORT16); + sum += ::ace_array_size (this->prop_); + return sum; +} + +size_t +ACE_URL_Offer::encode (void *buf) const +{ + ACE_UINT32 *s_buf = (ACE_UINT32 *) buf; + *s_buf = htonl (this->prop_.size ()); + + size_t len = sizeof (ACE_UINT32); + len += ACE_WString_Helper::encode ((void *) ((char *) buf + len), + this->url_); + + len += ::ace_array_encode ((void *) ((char *) buf + len), + this->prop_); + return len; +} + +size_t +ACE_URL_Offer::decode (void *buf) +{ + size_t len = sizeof (ACE_UINT32); + size_t a_size = (size_t) ntohl (*(ACE_UINT32 *) buf); + len += ACE_WString_Helper::decode ((void *) ((char *) buf + len)); + this->url ((ACE_USHORT16 *) ((char *) buf + len)); + + ACE_URL_Property_Seq prop_seq (a_size); + this->url_properties (prop_seq); + + len += ::ace_array_decode ((void *)((char *) buf + len), + this->prop_); + return len; +} + +void +ACE_URL_Offer::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + if (this->url_.length () > 0) + ACE_DEBUG ((LM_DEBUG, "\n url_: \"%s\"\n", + ACE_Auto_Basic_Array_Ptr<char> (this->url_.char_rep ()).get ())); + else + ACE_DEBUG ((LM_DEBUG, "\n url_: \"\"\n")); + + for (size_t i = 0; i < this->prop_.size (); i++) + this->prop_[i].dump (); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#endif /* ACE_URL_PROPERTIES_C */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Properties.h b/ACE/apps/JAWS/clients/Caching/URL_Properties.h new file mode 100644 index 00000000000..e62eb9102f6 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Properties.h @@ -0,0 +1,201 @@ +// -*- C++ -*- + +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// none +// +// = FILENAME +// URL_Locator.h +// +// = AUTHOR +// Nanbor Wang +// +// ============================================================================ + +#ifndef ACE_URL_PROPERTIES_H +#define ACE_URL_PROPERTIES_H + +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Containers.h" + +class ACE_Svc_Export ACE_WString_Helper + // = TITLE + // Some helper functions for manipulate ACE_WString. + // + // = DESCRIPTION + // These functions simplify encoding/decoding of + // ACE_WString objects for network communication. +{ +public: + static size_t size (const ACE_WString &wstr); + // Returns the actual size (in bytes) required to contain the + // ACE_WString. + + static size_t encode (void *buf, const ACE_WString &wstr); + // Encode <wstr> into <buf> for network communication. + // Return total octets consumed. + + static size_t decode (void *buf); + // This function doesn't relate to ACE_WString directly. + // It converts an ACE_USHORT16 string from network + // byte order to host byte order. Returns size of the string. +}; + +class ACE_Svc_Export ACE_URL_Property + // = TITLE + // Defines a property of a URL. + // + // = DESCRIPTION + // A property contains a <name> and a <value>. + // A URL may contain some properties and we can "locate" + // the URL's we are looking for by examming URL for certain + // properties that match our need. +{ +public: + ACE_URL_Property (const char *name = 0, + const char *value=0); + // Create a new property. + + ACE_URL_Property (const ACE_USHORT16 *name, + const ACE_USHORT16 *value); + // Create a new property using wchar strings. This is mostly used + // to support DBCS or UNICODE. + + ACE_URL_Property (const ACE_URL_Property &p); + // Copy constructor. + + ~ACE_URL_Property (void); + // Destructor. + + ACE_URL_Property &operator= (const ACE_URL_Property &rhs); + // Assignment operator. + + bool operator== (const ACE_URL_Property &rhs) const; + // Equals operator. + + bool operator!= (const ACE_URL_Property &rhs) const; + // Inequality operator. + + // = Query property name. + ACE_WString &name_rep (void); + const ACE_WString &name (void) const; + + // = Set property name. + void name (const ACE_USHORT16 *n); + void name (const char *n); + + // = Query property value. + ACE_WString &value_rep (void); + const ACE_WString &value (void) const; + + // = Set property value. + void value (const ACE_USHORT16 *v); + void value (const char *v); + + // = Helper functions for encoding and decoding. + size_t size (void) const; + // Returns memory size (in bytes) required to encode this object. + + size_t encode (void *buf) const; + // Encodes this object into buf for network transmission. + + size_t decode (void *buf); + // Decodes buf and modifies this object, you should + // probably create this with default ctor. + + void dump (void) const; + // Dump out this object for debug. + +protected: + ACE_WString name_; + // Property name pointer. + + ACE_WString value_; + // Property value. +} ; + +typedef ACE_Array<ACE_URL_Property> ACE_URL_Property_Seq; +// type of URL_Property collections. + +class ACE_Svc_Export ACE_URL_Offer + // = TITLE + // Defines a URL offer. + // + // = DESCRIPTION + // A URL offer is defined by a <url> and an + // <ACE_URL_Property_Seq>. An offer is stored at server end + // thru registering or reported back to querying client from the + // sever. +{ +public: + ACE_URL_Offer (const size_t size = 1, const char *url = 0); + // Create an offer. + + ACE_URL_Offer (const ACE_URL_Offer &o); + // Copy ctor. + + ~ACE_URL_Offer (void); + // Default destructor. + + ACE_URL_Offer &operator= (const ACE_URL_Offer &rhs); + // Assignment operator. + + bool operator== (const ACE_URL_Offer &rhs) const; + // Equality operator. + + bool operator!= (const ACE_URL_Offer &rhs) const; + // Inequality operator. + + // = Get URL string. + ACE_WString &url_rep (void); + const ACE_WString &url (void) const; + + // = Set URL. + void url (const char *url); + void url (const ACE_USHORT16 *url); + + ACE_URL_Property_Seq &url_properties (void); + // Get properties of this offer. + + void url_properties (const ACE_URL_Property_Seq &prop); + // Set properties of this offer. This operation virtually get a + // copy of the passed in prop. + + // = Helper functions for encoding and decoding. + size_t size (void) const; + // Returns memory size (in bytes) required to encode this object. + + size_t encode (void *buf) const; + // Encodes this object into buf for network transmission. + + size_t decode (void *buf); + // Decodes buf into current object, you better use + // the default ctor. + + void dump (void) const; + // Dump this object for debug. + +protected: + ACE_WString url_; + // URL of this offer. + + ACE_URL_Property_Seq prop_; + // Properties associate with this offer. +}; + +typedef ACE_Array<ACE_URL_Offer> ACE_URL_Offer_Seq; +// type of URL offer collections. + +#if defined (__ACE_INLINE__) +#include "URL_Properties.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_WEB_PROPERTIES_H */ diff --git a/ACE/apps/JAWS/clients/Caching/URL_Properties.i b/ACE/apps/JAWS/clients/Caching/URL_Properties.i new file mode 100644 index 00000000000..768ad967d94 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/URL_Properties.i @@ -0,0 +1,203 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_INLINE size_t +ACE_WString_Helper::size (const ACE_WString &wstr) +{ + return (wstr.length () + 1) * sizeof (ACE_USHORT16); +} + +ACE_INLINE +ACE_URL_Property::ACE_URL_Property (const char *name, const char *value) + : name_ (name), + value_ (value) +{ +} + +ACE_INLINE +ACE_URL_Property::ACE_URL_Property (const ACE_USHORT16 *name, + const ACE_USHORT16 *value) + : name_ (name), + value_ (value) +{ +} + +ACE_INLINE +ACE_URL_Property::ACE_URL_Property (const ACE_URL_Property &p) + : name_ (p.name_), + value_ (p.value_) +{ +} + +ACE_INLINE +ACE_URL_Property::~ACE_URL_Property (void) +{ +} + +ACE_INLINE ACE_URL_Property & +ACE_URL_Property::operator= (const ACE_URL_Property &rhs) +{ + if (this != &rhs) + { + this->name_ = rhs.name_; + this->value_ = rhs.value_; + } + return *this; +} + +ACE_INLINE bool +ACE_URL_Property::operator== (const ACE_URL_Property &rhs) const +{ + if (this == &rhs || this->name_ != rhs.name_ || + this->value_ != rhs.value_) + return true; + else + return false; +} + +ACE_INLINE bool +ACE_URL_Property::operator!= (const ACE_URL_Property &rhs) const +{ + return !(*this == rhs); +} + +ACE_INLINE ACE_WString & +ACE_URL_Property::name_rep (void) +{ + return this->name_; +} + +ACE_INLINE const ACE_WString & +ACE_URL_Property::name (void) const +{ + return this->name_; +} + +ACE_INLINE void +ACE_URL_Property::name (const char *n) +{ + this->name_ = ACE_WString (n); +} + +ACE_INLINE void +ACE_URL_Property::name (const ACE_USHORT16 *n) +{ + this->name_ = ACE_WString (n); +} + +ACE_INLINE ACE_WString & +ACE_URL_Property::value_rep (void) +{ + return this->value_; +} + +ACE_INLINE const ACE_WString & +ACE_URL_Property::value (void) const +{ + return this->value_; +} + +ACE_INLINE void +ACE_URL_Property::value (const char *v) +{ + this->value_ = ACE_WString (v); +} + +ACE_INLINE void +ACE_URL_Property::value (const ACE_USHORT16 *v) +{ + this->value_ = ACE_WString (v); +} + + +ACE_INLINE size_t +ACE_URL_Property::size (void) const +{ + size_t len = 2; + len += this->name_.length () + this->value_.length (); + return len * sizeof (ACE_USHORT16); +} + +ACE_INLINE +ACE_URL_Offer::ACE_URL_Offer (const size_t size, const char *url) + : url_ (url), + prop_ (size) +{ +} + +ACE_INLINE +ACE_URL_Offer::ACE_URL_Offer (const ACE_URL_Offer &o) + : url_ (o.url_), + prop_ (o.prop_) +{ +} + +ACE_INLINE +ACE_URL_Offer::~ACE_URL_Offer (void) +{ +} + +ACE_INLINE ACE_URL_Offer & +ACE_URL_Offer::operator= (const ACE_URL_Offer &rhs) +{ + if (this != &rhs) + { + this->url_ = rhs.url_; + this->prop_ = rhs.prop_; + } + return *this; +} + +ACE_INLINE bool +ACE_URL_Offer::operator== (const ACE_URL_Offer &rhs) const +{ + if (this == &rhs + && this->url_ == rhs.url_ + && this->prop_ == rhs.prop_) + return true; + else + return false; +} + +ACE_INLINE bool +ACE_URL_Offer::operator!= (const ACE_URL_Offer &rhs) const +{ + return !(*this == rhs); +} + +ACE_INLINE ACE_WString & +ACE_URL_Offer::url_rep (void) +{ + return this->url_; +} + +ACE_INLINE const ACE_WString & +ACE_URL_Offer::url (void) const +{ + return this->url_; +} + +ACE_INLINE void +ACE_URL_Offer::url (const ACE_USHORT16 *url) +{ + this->url_ = ACE_WString (url); +} + +ACE_INLINE void +ACE_URL_Offer::url (const char *url) +{ + this->url_ = ACE_WString (url); +} + +ACE_INLINE ACE_URL_Property_Seq & +ACE_URL_Offer::url_properties (void) +{ + return this->prop_; +} + +ACE_INLINE void +ACE_URL_Offer::url_properties (const ACE_URL_Property_Seq &prop) +{ + this->prop_ = prop; +} diff --git a/ACE/apps/JAWS/clients/Caching/caching.mpc b/ACE/apps/JAWS/clients/Caching/caching.mpc new file mode 100644 index 00000000000..fce9d81df4f --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/caching.mpc @@ -0,0 +1,12 @@ +// -*- MPC -*- +// $Id$ + +project(http_client) : aceexe { + avoids += ace_for_tao + requires += ace_filecache + + Source_Files { + http_handler.cpp + http_client.cpp + } +} diff --git a/ACE/apps/JAWS/clients/Caching/http_client.cpp b/ACE/apps/JAWS/clients/Caching/http_client.cpp new file mode 100644 index 00000000000..f0bb20b6d56 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/http_client.cpp @@ -0,0 +1,79 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// apps/JAWS/clients/Caching +// +// = FILENAME +// http_client.cpp +// +// = DESCRIPTION +// This is a very simple client. It accepts URLs from a prompt, and +// will try to fetch them. Also accepts shell escapes. +// +// = AUTHOR +// James Hu +// +// ============================================================================ + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/os_include/os_ctype.h" +#include "http_handler.h" + +ACE_RCSID(Caching, http_client, "$Id$") + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + // Present a command line. + // * Accept a URL. + // Pass it to the HTTP_Connector. + // Connect. + // Report status. + // * Accept shell escape character. + + char buf[BUFSIZ]; + + ACE_DEBUG ((LM_DEBUG, "* ")); + + while (ACE_OS::fgets (buf, sizeof (buf), stdin) != NULL) + { + char *s = buf; + + // get rid of trailing '\n' + int len = ACE_OS::strlen (s); + + if (len > 0 && s[len - 1] == '\n') + s[len - 1] = 0; + + while (isspace (*s)) + s++; + + if (*s == '!') + { + do + s++; + while (isspace (*s)); + + // Shell command. + if (ACE_OS::system (ACE_TEXT_CHAR_TO_TCHAR (s)) == -1) + ACE_ERROR ((LM_ERROR, ACE_TEXT (" ! Error executing: %C\n"), s)); + } + else if (ACE_OS::strncmp (s, "http://", 7) == 0) + { + // URL + HTTP_Connector connector; + connector.connect (s); + } + else + ACE_ERROR ((LM_ERROR, ACE_TEXT (" ? I don't understand: %C\n"), s)); + + ACE_ERROR ((LM_ERROR, ACE_TEXT ("* "))); + } + + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nBye!\n"))); + + return 0; +} diff --git a/ACE/apps/JAWS/clients/Caching/http_handler.cpp b/ACE/apps/JAWS/clients/Caching/http_handler.cpp new file mode 100644 index 00000000000..bfeda511176 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/http_handler.cpp @@ -0,0 +1,238 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// apps/JAWS/clients/Caching +// +// = FILENAME +// http_handler.cpp +// +// = AUTHOR +// James Hu +// +// ============================================================================ + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/Filecache.h" +#include "http_handler.h" + +ACE_RCSID(Caching, http_handler, "$Id$") + +HTTP_Handler::HTTP_Handler (void) +{ +} + +HTTP_Handler::HTTP_Handler (const char * path) +{ + // How long is the request going to be? + this->request_[0] = '\0'; + this->request_size_ = + ACE_OS::strlen ("GET ") + + ACE_OS::strlen (path) + + ACE_OS::strlen (" HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n"); + + // Make the request. + if ((u_int) this->request_size_ < sizeof (this->request_)) + ACE_OS::sprintf (this->request_, + "GET %s HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n", + path); + + // Find the filename. + const char *last = ACE_OS::strrchr (path, '/'); + + if (last == 0) + last = path; + else if (last[1] == '\0') + last = "index.html"; + else + last = last+1; + + ACE_OS::sprintf (this->filename_, "%s", last); +} + +int +HTTP_Handler::open (void *) +{ + // If you want threads, use the activate stuff. +#if 0 + if (this->activate () != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, "HTTP_Handler::open, whups!\n"), -1); + } + + return 0; +#else + return this->svc (); +#endif /* 0 */ +} + +int +HTTP_Handler::svc (void) +{ + static char buf[BUFSIZ]; + int count = 0; + + ACE_DEBUG ((LM_DEBUG, "[%t] sending request --\n%s", this->request_)); + + this->peer ().send_n (this->request_, this->request_size_); + + // Read in characters until encounter \r\n\r\n + int done = 0; + char *contentlength; + + do + { + while (((count += this->peer ().recv_n (buf + count, 1)) > 0) + && ((u_int) count < sizeof (buf))) + { + buf[count] = '\0'; + + if (count < 2) + continue; + done = ACE_OS::strcmp (buf + count - 4, "\n\n") == 0; + + if (done) + break; + + if (count < 4) + continue; + + done = ACE_OS::strcmp (buf + count - 4, "\r\n\r\n") == 0; + + if (done) + break; + } + + if (!done) + { + char *last = ACE_OS::strrchr (buf, '\n'); + last[0] = '\0'; + + if ((contentlength = ACE_OS::strstr (buf, "\nContent-length:")) + || (contentlength = ACE_OS::strstr (buf, "\nContent-Length:"))) + done = 1; + else + { + last[0] = '\n'; + count = ACE_OS::strlen (last); + ACE_OS::memmove (buf, last, count + 1); + } + } + else + { + contentlength = ACE_OS::strstr (buf, "\nContent-length:"); + + if (!contentlength) + contentlength = + ACE_OS::strstr (buf, "\nContent-Length:"); + } + + } + while (!done); + + // ASSERT (contentlength != 0) + if (contentlength + && (::sscanf (contentlength, "\nContent-%*[lL]ength: %d ", + &this->response_size_) == 1)) + { + ACE_Filecache_Handle afh (ACE_TEXT_CHAR_TO_TCHAR (this->filename_), + this->response_size_); + + this->peer ().recv_n (afh.address (), this->response_size_); + + ACE_DEBUG ((LM_DEBUG, + " ``%s'' is now cached.\n", + this->filename_)); + } + else + { + // Maybe we should do something more clever here, such as extend + // ACE_Filecache_Handle to allow the creation of cache objects + // whose size is unknown? + + // Another possibility is to write the contents out to a file, + // and then cache it. + + // Perhaps make ACE_Filecache_Handle more savvy, and allow a + // constructor which accepts a PEER as a parameter. + ACE_DEBUG ((LM_DEBUG, + "HTTP_Handler, no content-length header!\n")); + } + + return 0; +} + +const char * +HTTP_Handler::filename (void) const +{ + return this->filename_; +} + +int +HTTP_Connector::connect (const char * url) +{ + char host[BUFSIZ]; + u_short port; + char path[BUFSIZ]; + + if (this->parseurl (url, host, &port, path) == -1) + { + ACE_DEBUG ((LM_DEBUG, + "HTTP_Connector, error parsing url: %s\n", + url)); + return -1; + } + + HTTP_Handler hh (path); + HTTP_Handler *hhptr = &hh; + + // First check the cache. + if (ACE_Filecache::instance ()->find (ACE_TEXT_CHAR_TO_TCHAR (hh.filename ())) == 0) + { + ACE_DEBUG ((LM_DEBUG, " ``%s'' is already cached.\n", + hh.filename ())); + return 0; + } + + return this->connector_.connect (hhptr, ACE_INET_Addr (port, host)); +} + +#define DEFAULT_SERVER_PORT 80 + +// extract the main components of a URL +int +HTTP_Connector::parseurl (const char *url, + char *host, + u_short *port, + char *path) +{ + int status = 0; + + // hackish, but useful + if (3 != ::sscanf (url, "http://%[^:/]:%hu%s", host, port, path)) + { + if (2 != ::sscanf (url, "http://%[^:/]:%hu", host, port)) + { + if (2 != ::sscanf (url, "http://%[^:/]%s", host, path)) + { + if (1 != ::sscanf (url, "http://%[^:/]", host)) + status = -1; + else + { + *port = DEFAULT_SERVER_PORT; + ACE_OS::strcpy (path, "/"); + } + } + else + *port = DEFAULT_SERVER_PORT; + } + else ACE_OS::strcpy (path, "/"); + } + + // 0 => success + // -1 => error + return status; +} + diff --git a/ACE/apps/JAWS/clients/Caching/http_handler.h b/ACE/apps/JAWS/clients/Caching/http_handler.h new file mode 100644 index 00000000000..3922c1ab857 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/http_handler.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +// Hey, Emacs! This is a C++ file. +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// apps/JAWS/clients/Caching +// +// = FILENAME +// http_handler.h +// +// = AUTHOR +// James Hu +// +// ============================================================================ + +#include "ace/SOCK_Connector.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Connector.h" +#include "ace/Svc_Handler.h" + +class HTTP_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> + // = TITLE + // A simple HTTP protocol handler for clients. + // + // = DESCRIPTION + // Checks to see if the requested file is already cached. If + // so, it says so. If not, the request is issued to the + // connection. The fetched file is cached. +{ +public: + // = Initialization methods. + HTTP_Handler (void); + HTTP_Handler (const char * path); + + virtual int open (void *); + // Open hook. + + virtual int svc (void); + // Entry points defined by the abstract Svc_Handler. + + const char *filename (void) const; + // Accessor to the file being fetched. + +private: + char request_[BUFSIZ]; + int request_size_; + + char filename_[BUFSIZ]; + int response_size_; +}; + +class HTTP_Connector + // = TITLE + // A simple HTTP connector. + // + // = DESCRIPTION + // Creates an HTTP Handler based on the URL, and then delegates + // to to the SOCK_CONNECTOR. Adapter pattern. +{ +public: + int connect (const char * url); + // User entry point into the HTTP connector. + +private: + int parseurl (const char *url, + char *host, + u_short *port, + char *path); + // Helper function. + +private: + ACE_Connector<HTTP_Handler, ACE_SOCK_CONNECTOR> connector_; + // Factory that actively establishes a connection with an HTTP + // server. +}; diff --git a/ACE/apps/JAWS/clients/Caching/test_URL.cpp b/ACE/apps/JAWS/clients/Caching/test_URL.cpp new file mode 100644 index 00000000000..7e81a359f45 --- /dev/null +++ b/ACE/apps/JAWS/clients/Caching/test_URL.cpp @@ -0,0 +1,34 @@ +// $Id$ + +#include "Locator_Request_Reply.h" + +ACE_RCSID(Caching, test_URL, "$Id$") + +int main (int argc, char *argv[]) +{ + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + ACE_URL_Locator_Request original, derived; + + ACE_URL_Property_Seq ouch1(3); + ouch1[0].name ("name 1"); + ouch1[0].value ("value 1"); + ouch1[1].name ("name 2"); + ouch1[1].value ("value 2"); + ouch1[2].name ("name 3"); + ouch1[2].value ("value 3"); + + original.url_query (1, ouch1, 3); + + original.dump (); + derived.dump (); + + original.encode (); + + derived.decode ((void*) original.buffer ()); + + derived.dump (); + + return 0; +} |