diff options
Diffstat (limited to 'trunk/TAO/tao/Strategies/UIOP_Profile.cpp')
-rw-r--r-- | trunk/TAO/tao/Strategies/UIOP_Profile.cpp | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/trunk/TAO/tao/Strategies/UIOP_Profile.cpp b/trunk/TAO/tao/Strategies/UIOP_Profile.cpp new file mode 100644 index 00000000000..1e665915348 --- /dev/null +++ b/trunk/TAO/tao/Strategies/UIOP_Profile.cpp @@ -0,0 +1,454 @@ +#include "tao/Strategies/UIOP_Profile.h" + +#if TAO_HAS_UIOP == 1 + +#include "tao/Strategies/uiop_endpointsC.h" + +#include "tao/CDR.h" +#include "tao/Environment.h" +#include "tao/ORB.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/os_include/os_ctype.h" + +ACE_RCSID (Strategies, + UIOP_Profile, + "$Id$") + +static const char prefix_[] = "uiop"; + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +const char TAO_UIOP_Profile::object_key_delimiter_ = '|'; + +char +TAO_UIOP_Profile::object_key_delimiter (void) const +{ + return TAO_UIOP_Profile::object_key_delimiter_; +} + +TAO_UIOP_Profile::TAO_UIOP_Profile (const ACE_UNIX_Addr &addr, + const TAO::ObjectKey &object_key, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIOP_PROFILE, + orb_core, + object_key, + version), + endpoint_ (addr), + count_ (1) +{ +} + +TAO_UIOP_Profile::TAO_UIOP_Profile (const char *, + const TAO::ObjectKey &object_key, + const ACE_UNIX_Addr &addr, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIOP_PROFILE, + orb_core, + object_key, + version), + endpoint_ (addr), + count_ (1) +{ +} + +TAO_UIOP_Profile::TAO_UIOP_Profile (TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIOP_PROFILE, + orb_core, + TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, + TAO_DEF_GIOP_MINOR)), + endpoint_ (), + count_ (1) +{ +} + +TAO_UIOP_Profile::~TAO_UIOP_Profile (void) +{ + // Clean up the list of endpoints since we own it. + // Skip the head, since it is not dynamically allocated. + TAO_Endpoint *tmp = 0; + + for (TAO_Endpoint *next = this->endpoint ()->next (); + next != 0; + next = tmp) + { + tmp = next->next (); + delete next; + } +} + +TAO_Endpoint* +TAO_UIOP_Profile::endpoint (void) +{ + return &this->endpoint_; +} + +CORBA::ULong +TAO_UIOP_Profile::endpoint_count (void) const +{ + return this->count_; +} + +void +TAO_UIOP_Profile::parse_string_i (const char *string + ACE_ENV_ARG_DECL) +{ + if (!string || !*string) + { + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + 0, + EINVAL), + CORBA::COMPLETED_NO)); + } + + // Remove the "N.n@" version prefix, if it exists, and verify the + // version is one that we accept. + + // Check for version + if (isdigit (string [0]) && + string[1] == '.' && + isdigit (string [2]) && + string[3] == '@') + { + // @@ This may fail for non-ascii character sets [but take that + // with a grain of salt] + this->version_.set_version ((char) (string [0] - '0'), + (char) (string [2] - '0')); + string += 4; + // Skip over the "N.n@" + } + + if (this->version_.major != TAO_DEF_GIOP_MAJOR || + this->version_.minor > TAO_DEF_GIOP_MINOR) + { + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + 0, + EINVAL), + CORBA::COMPLETED_NO)); + } + + + // Pull off the "rendezvous point" part of the objref + // Copy the string because we are going to modify it... + CORBA::String_var copy (string); + + char *start = copy.inout (); + char *cp = ACE_OS::strchr (start, this->object_key_delimiter_); + + if (cp == 0) + { + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + EINVAL), + CORBA::COMPLETED_NO)); + // No rendezvous point specified + } + + CORBA::ULong length = cp - start; + + CORBA::String_var rendezvous = CORBA::string_alloc (length); + + ACE_OS::strncpy (rendezvous.inout (), start, length); + rendezvous[length] = '\0'; + + if (this->endpoint_.object_addr_.set (rendezvous.in ()) != 0) + { + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + EINVAL), + CORBA::COMPLETED_NO)); + } + + start = ++cp; // increment past the object key separator + + TAO::ObjectKey ok; + TAO::ObjectKey::decode_string_to_sequence (ok, + start); + + (void) this->orb_core ()->object_key_table ().bind (ok, + this->ref_object_key_); +} + +CORBA::Boolean +TAO_UIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile) +{ + const TAO_UIOP_Profile *op = + dynamic_cast <const TAO_UIOP_Profile *> (other_profile); + + if (op == 0) + return false; + + // Check endpoints equivalence. + const TAO_UIOP_Endpoint *other_endp = &op->endpoint_; + for (TAO_UIOP_Endpoint *endp = &this->endpoint_; + endp != 0; + endp = endp->next_) + { + if (endp->is_equivalent (other_endp)) + other_endp = other_endp->next_; + else + return false; + } + + return true; +} + +CORBA::ULong +TAO_UIOP_Profile::hash (CORBA::ULong max + ACE_ENV_ARG_DECL_NOT_USED) +{ + // Get the hashvalue for all endpoints. + CORBA::ULong hashval = 0; + for (TAO_UIOP_Endpoint *endp = &this->endpoint_; + endp != 0; + endp = endp->next_) + { + hashval += endp->hash (); + } + + hashval += this->version_.minor; + hashval += this->tag (); + + const TAO::ObjectKey &ok = + this->ref_object_key_->object_key (); + + if (ok.length () >= 4) + { + hashval += ok[1]; + hashval += ok[3]; + } + + hashval += this->hash_service_i (max); + + return hashval % max; +} + +void +TAO_UIOP_Profile::add_endpoint (TAO_UIOP_Endpoint *endp) +{ + endp->next_ = this->endpoint_.next_; + this->endpoint_.next_ = endp; + + this->count_++; +} + + +char * +TAO_UIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) +{ + CORBA::String_var key; + TAO::ObjectKey::encode_sequence_to_string (key.inout(), + this->ref_object_key_->object_key ()); + + u_int buflen = (8 /* "corbaloc" */ + + 1 /* colon separator */ + + ACE_OS::strlen (::prefix_) + + 1 /* colon separator */ + + 1 /* major version */ + + 1 /* decimal point */ + + 1 /* minor version */ + + 1 /* `@' character */ + + ACE_OS::strlen (this->endpoint_.rendezvous_point ()) + + 1 /* object key separator */ + + ACE_OS::strlen (key.in ())); + + char * buf = CORBA::string_alloc (buflen); + + static const char digits [] = "0123456789"; + + ACE_OS::sprintf (buf, + "corbaloc:%s:%c.%c@%s%c%s", + ::prefix_, + digits [this->version_.major], + digits [this->version_.minor], + this->endpoint_.rendezvous_point (), + this->object_key_delimiter_, + key.in ()); + return buf; +} + +const char * +TAO_UIOP_Profile::prefix (void) +{ + return ::prefix_; +} + +int +TAO_UIOP_Profile::decode_profile (TAO_InputCDR& cdr) +{ + char *rendezvous = 0; + + // Get rendezvous_point + if (cdr.read_string (rendezvous) == 0) + { + ACE_DEBUG ((LM_DEBUG, "error decoding UIOP rendezvous_point")); + return -1; + } + + if (this->endpoint_.object_addr_.set (rendezvous) == -1) + { + // In the case of an ACE_UNIX_Addr, this should call should + // never fail! + // + // If the call fails, allow the profile to be created, and rely + // on TAO's connection handling to throw the appropriate + // exception. + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIOP_Profile::decode - ") + ACE_TEXT ("ACE_UNIX_Addr::set() failed\n"))); + } + } + + // Clean up + delete [] rendezvous; + + return 1; +} + +void +TAO_UIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const +{ + // CHAR describing byte order, starting the encapsulation + encap.write_octet (TAO_ENCAP_BYTE_ORDER); + + // The GIOP version + encap.write_octet (this->version_.major); + encap.write_octet (this->version_.minor); + + // STRING rendezvous_pointname from profile + encap.write_string (this->endpoint_.rendezvous_point ()); + + // OCTET SEQUENCE for object key + if (this->ref_object_key_) + encap << this->ref_object_key_->object_key (); + else + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) TAO - UIOP_Profile::create_profile_body " + "no object key marshalled \n")); + } + + if (this->version_.major > 1 + || this->version_.minor > 0) + this->tagged_components ().encode (encap); +} + +int +TAO_UIOP_Profile::encode_endpoints (void) +{ + // Create a data structure and fill it with endpoint info for wire + // transfer. + // We include information for the head of the list + // together with other endpoints because even though its addressing + // info is transmitted using standard ProfileBody components, its + // priority is not! + TAO_UIOPEndpointSequence endpoints; + endpoints.length (this->count_); + + TAO_UIOP_Endpoint *endpoint = &this->endpoint_; + for (size_t i = 0; + i < this->count_; + ++i) + { + endpoints[i].rendezvous_point = endpoint->rendezvous_point (); + endpoints[i].priority = endpoint->priority (); + + endpoint = endpoint->next_; + } + + // Encode the data structure. + TAO_OutputCDR out_cdr; + if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) + == 0) + || (out_cdr << endpoints) == 0) + return -1; + + this->set_tagged_components (out_cdr); + + return 0; +} + +int +TAO_UIOP_Profile::decode_endpoints (void) +{ + IOP::TaggedComponent tagged_component; + tagged_component.tag = TAO_TAG_ENDPOINTS; + + if (this->tagged_components_.get_component (tagged_component)) + { + const CORBA::Octet *buf = + tagged_component.component_data.get_buffer (); + + TAO_InputCDR in_cdr (reinterpret_cast <const char*>(buf), + tagged_component.component_data.length ()); + + // Extract the Byte Order. + CORBA::Boolean byte_order; + if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0) + return -1; + in_cdr.reset_byte_order (static_cast<int>(byte_order)); + + // Extract endpoints sequence. + TAO_UIOPEndpointSequence endpoints; + + if ((in_cdr >> endpoints) == 0) + return -1; + + // Get the priority of the first endpoint (head of the list. + // It's other data is extracted as part of the standard profile + // decoding. + this->endpoint_.priority (endpoints[0].priority); + + // Use information extracted from the tagged component to + // populate the profile. Skip the first endpoint, since it is + // always extracted through standard profile body. Also, begin + // from the end of the sequence to preserve endpoint order, + // since <add_endpoint> method reverses the order of endpoints + // in the list. + for (CORBA::ULong i = endpoints.length () - 1; + i > 0; + --i) + { + TAO_UIOP_Endpoint *endpoint = 0; + ACE_NEW_RETURN (endpoint, + TAO_UIOP_Endpoint, + -1); + this->add_endpoint (endpoint); + if (endpoint->object_addr_.set + (endpoints[i].rendezvous_point) + == -1) + { + // In the case of an ACE_UNIX_Addr, this should call should + // never fail! + // If the call fails, allow the profile to be created, and rely + // on TAO's connection handling to throw the appropriate + // exception. + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIOP_Profile::decode_endpoints - ") + ACE_TEXT ("ACE_UNIX_Addr::set() failed\n"))); + } + + } + endpoint->priority (endpoints[i].priority); + } + } + + return 0; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_HAS_UIOP == 1 */ |