diff options
Diffstat (limited to 'TAO/tao/CORBALOC_Parser.cpp')
-rw-r--r-- | TAO/tao/CORBALOC_Parser.cpp | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/TAO/tao/CORBALOC_Parser.cpp b/TAO/tao/CORBALOC_Parser.cpp new file mode 100644 index 00000000000..d3b8fbb84a7 --- /dev/null +++ b/TAO/tao/CORBALOC_Parser.cpp @@ -0,0 +1,391 @@ +#include "tao/CORBALOC_Parser.h" +#include "tao/ORB_Core.h" +#include "tao/Stub.h" +#include "tao/MProfile.h" +#include "tao/Connector_Registry.h" +#include "tao/Transport_Connector.h" +#include "tao/Protocol_Factory.h" +#include "tao/debug.h" +#include "ace/Vector_T.h" +#include "ace/INET_Addr.h" +#include "ace/OS_NS_string.h" + +#include "ace/os_include/os_netdb.h" + +#if !defined(__ACE_INLINE__) +#include "tao/CORBALOC_Parser.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID (tao, + CORBALOC_Parser, + "$Id$") + +static const char prefix[] = "corbaloc:"; +static const size_t prefix_len = sizeof prefix - 1; +static const char rir_token[] = "rir:"; +static const size_t rir_token_len = sizeof rir_token - 1; +static const char iiop_token[] = "iiop:"; +static const char iiop_token_len = sizeof iiop_token - 1; + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_CORBALOC_Parser::~TAO_CORBALOC_Parser (void) +{ +} + +int +TAO_CORBALOC_Parser::match_prefix (const char *ior_string) const +{ + // Check if the prefix is 'corbaloc:' and return the result. + return (ACE_OS::strncmp (ior_string, + prefix, + prefix_len) == 0); +} + +CORBA::Object_ptr +TAO_CORBALOC_Parser::make_stub_from_mprofile (CORBA::ORB_ptr orb, + TAO_MProfile &mprofile + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Create a TAO_Stub. + TAO_Stub *data = orb->orb_core ()->create_stub ((const char *) 0, + mprofile + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + TAO_Stub_Auto_Ptr safe_data (data); + + CORBA::Object_var obj = orb->orb_core ()->create_object (data); + + if (!CORBA::is_nil (obj.in ())) + { + /// All is well, so release the stub object from its + /// auto_ptr. + (void) safe_data.release (); + + /// Return the object reference to the application. + return obj._retn (); + } + + /// Shouldnt come here: if so, return nil reference. + return CORBA::Object::_nil (); +} + +CORBA::Object_ptr +TAO_CORBALOC_Parser::parse_string_rir_helper (const char * ior, + CORBA::ORB_ptr orb + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Pass the key string as an argument to resolve_initial_references. + // NameService is the default if an empty key string is supplied. + const char *objkey = ior + rir_token_len; + if (*objkey == '/') // there is an explicit object key, which may + // validly be null. + objkey++; + + CORBA::Object_var rir_obj = + orb->resolve_initial_references (*objkey == '\0' ? "NameService" : + objkey + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + return rir_obj._retn (); +} + +CORBA::Object_ptr +TAO_CORBALOC_Parser::parse_string (const char * ior, + CORBA::ORB_ptr orb + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // The decomposition of a corbaloc string is in Section 13.6.10. + // + // following the "corbaloc:" + // a comma separated list of <prot_addr> strings + // for each, + // Separate out the key, delimited by '/' + // Split out the various parts of our corbaloc string, comma-delimited + // For each part + // Determine the protocol + // If rir, defer to another function and return the object + // If iiop, make the profile with <endpoint>:<port>/<key> + // If another protocol, use <remainder>/<key> + // Search through the collection of protocols for the correct one + // If not found, throw exception + // If found, make our_connector from it. + // our_connector->make_mprofile_unchecked (...); + // object = this->make_stub_from_mprofile (...); + // Return the object + + // Skip the prefix. We know it is there because this method is only + // called if match_prefix() returns 1. + ior += ACE_OS::strlen(prefix); + + // First check for rir + if (ACE_OS::strncmp (ior,rir_token,rir_token_len) == 0) + return this->parse_string_rir_helper (ior,orb + ACE_ENV_ARG_PARAMETER); + + // set up space for parsed endpoints. there will be at least 1, and + // most likely commas will separate endpoints, although they could be + // part of an endpoint address for some protocols. + size_t max_endpoint_count = 1; + for (const char *comma = ACE_OS::strchr (ior,','); + comma; + comma = ACE_OS::strchr (comma+1,',')) + max_endpoint_count++; + + ACE_Array<parsed_endpoint> endpoints(max_endpoint_count); + endpoints.size (0); + + // Get the Connector Registry from the ORB. + TAO_Connector_Registry *conn_reg = + orb->orb_core ()->connector_registry(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + while (1) { // will loop on comma only. + size_t len = 0; + size_t ndx = endpoints.size(); + endpoints.size(ndx+1); + int uiop_compatible = 0; + TAO_ConnectorSetIterator conn_iter = 0; + for (conn_iter = conn_reg->begin(); + conn_iter != conn_reg->end() && + endpoints[ndx].profile_ == 0; + conn_iter ++) + { + endpoints[ndx].profile_ = + (*conn_iter)->corbaloc_scan(ior,len + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (endpoints[ndx].profile_) + { + endpoints[ndx].obj_key_sep_ = + (*conn_iter)->object_key_delimiter(); + uiop_compatible = (endpoints[ndx].obj_key_sep_ == '|'); + this->make_canonical (ior,len,endpoints[ndx].prot_addr_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + ior += len; + break; + } + } + + if (endpoints[ndx].profile_ == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ") + ACE_TEXT("could not parse from %s"), + ACE_TEXT_CHAR_TO_TCHAR(ior))); + ACE_THROW_RETURN (CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, + CORBA::COMPLETED_NO), + CORBA::Object::_nil ()); + } + if (*ior == ',') // more endpoints follow + { + ior++; + continue; + } + + if (*ior == '/') // found key separator + { + ior ++; + break; + } + + if (*ior == '\0') // no key separator appended, use default key + { + break; + } + + if (uiop_compatible && *(ior - 1) == '|') + // Assume this is an old uiop style corbaloc. No need to warn here, + // the UIOP_Connector::corbaloc_scan already did. + break; + + // anything else is a violation. + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ") + ACE_TEXT("could not parse from %s"), + ACE_TEXT_CHAR_TO_TCHAR(ior))); + ACE_THROW_RETURN (CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, + CORBA::COMPLETED_NO), + CORBA::Object::_nil ()); + } // end of while + + // At this point, ior points at the start of the object key + ACE_CString obj_key (*ior ? ior : (const char *)"NameService"); + + // now take the collection of endpoints along with the decoded key and + // mix them together to get the mprofile. + TAO_MProfile mprofile (endpoints.size()); + + for (size_t i = 0; i < endpoints.size(); i++) + { + ACE_CString full_ep = endpoints[i].prot_addr_ + + endpoints[i].obj_key_sep_ + + obj_key; + const char * str = full_ep.c_str(); + endpoints[i].profile_->parse_string (str ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + int share = orb->orb_core()->orb_params()->shared_profile(); + if (mprofile.give_profile(endpoints[i].profile_, share) != -1) + endpoints[i].profile_ = 0; + else + { + // Although this ought never happen, we want to make some + // indication back to the caller, more as an audit trail than + // anything else. The only failure possible is that there was + // insufficient heap to allocate the mprofile, hence the + // mprofile's size is 0, and give_profile fails. + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ") + ACE_TEXT("mprofile.give_profile failed for i = %d\n"), + i)); + ACE_THROW_RETURN (CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, + CORBA::COMPLETED_NO), + CORBA::Object::_nil ()); + } + } + + CORBA::Object_ptr object = CORBA::Object::_nil (); + // Get an object stub out. + object = this->make_stub_from_mprofile (orb, + mprofile + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + return object; +} + +void +TAO_CORBALOC_Parser::make_canonical (const char *ior, + size_t prot_addr_len, + ACE_CString &canonical_endpoint + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + const char *separator = ACE_OS::strchr (ior, ':'); + + // A special case for handling iiop + if (ior[0] != ':' && ACE_OS::strncmp (ior,iiop_token,iiop_token_len) != 0) + { + canonical_endpoint.set (separator+1, + prot_addr_len - (separator - ior) - 1,1); + return; + } + + const char *addr_base = separator+1; + const char *addr_tail = ior + prot_addr_len; + // skip past version, if any + separator = ACE_OS::strchr (addr_base,'@'); + if (separator != 0 && separator < addr_tail) + { + canonical_endpoint.set (addr_base,(separator - addr_base)+1,1); + addr_base = separator + 1; + } + else + canonical_endpoint.clear (); + + ACE_CString raw_host; + ACE_CString raw_port; + separator = ACE_OS::strchr (addr_base,':'); +#if defined (ACE_HAS_IPV6) + // IPv6 numeric address in host string? + + // Check if this is an address containing a decimal IPv6 address representation. + if (addr_base < addr_tail && addr_base[0] == '[') + { + // In this case we have to find the end of the numeric address and + // start looking for the port separator from there. + const char *cp_pos = ACE_OS::strchr(addr_base, ']'); + if (cp_pos == 0 || cp_pos >= addr_tail) + { + // No valid IPv6 address specified but that will come out later. + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("\nTAO (%P|%t) TAO_CORBALOC_Parser: ") + ACE_TEXT ("Invalid IPv6 decimal address specified.\n"))); + } + separator = 0; + } + else + { + if (cp_pos[1] == ':') // Look for a port + separator = cp_pos + 1; + else + separator = 0; + } + } +#endif /* ACE_HAS_IPV6 */ + + if (separator != 0 && separator < addr_tail) + { + // we have a port number + raw_host.set (addr_base, (separator - addr_base), 1); + raw_port.set (separator, (addr_tail - separator), 1); + } + else + { + // we must default port # + if (addr_base < addr_tail) + raw_host.set (addr_base, (addr_tail - addr_base),1); + raw_port.set (":2809"); + } + + if (raw_host.length() == 0) + { + ACE_INET_Addr host_addr; + + char tmp_host [MAXHOSTNAMELEN + 1]; + + // If no host is specified: assign the default host, i.e. the + // local host. + if (host_addr.get_host_name (tmp_host, + sizeof (tmp_host)) != 0) + { + // Can't get the IP address since the INET_Addr wasn't + // initialized. Just throw an exception. + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) ") + ACE_TEXT ("cannot determine hostname.\n"))); + + ACE_THROW (CORBA::INV_OBJREF + (CORBA::SystemException::_tao_minor_code + (TAO::VMCID, EINVAL), + CORBA::COMPLETED_NO)); + } + else + { + canonical_endpoint += tmp_host; + } + } + else + { + canonical_endpoint += raw_host; + } + + canonical_endpoint += raw_port; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +ACE_STATIC_SVC_DEFINE (TAO_CORBALOC_Parser, + ACE_TEXT ("CORBALOC_Parser"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_CORBALOC_Parser), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + +ACE_FACTORY_DEFINE (TAO, TAO_CORBALOC_Parser) + |