CORBALOC_Parser.cpp

Go to the documentation of this file.
00001 #include "tao/CORBALOC_Parser.h"
00002 
00003 #if (TAO_HAS_CORBALOC_PARSER == 1)
00004 
00005 #include "tao/ORB_Core.h"
00006 #include "tao/Stub.h"
00007 #include "tao/MProfile.h"
00008 #include "tao/Connector_Registry.h"
00009 #include "tao/Transport_Connector.h"
00010 #include "tao/Protocol_Factory.h"
00011 #include "tao/debug.h"
00012 #include "tao/SystemException.h"
00013 #include "ace/Vector_T.h"
00014 #include "ace/INET_Addr.h"
00015 #include "ace/OS_NS_string.h"
00016 
00017 #include "ace/os_include/os_netdb.h"
00018 
00019 #if !defined(__ACE_INLINE__)
00020 #include "tao/CORBALOC_Parser.inl"
00021 #endif /* __ACE_INLINE__ */
00022 
00023 ACE_RCSID (tao,
00024            CORBALOC_Parser,
00025            "$Id: CORBALOC_Parser.cpp 79237 2007-08-07 09:48:21Z johnnyw $")
00026 
00027 static const char prefix[] = "corbaloc:";
00028 static const size_t prefix_len = sizeof prefix - 1;
00029 static const char rir_token[] = "rir:";
00030 static const size_t rir_token_len = sizeof rir_token - 1;
00031 static const char iiop_token[] = "iiop:";
00032 static const char iiop_token_len = sizeof iiop_token - 1;
00033 
00034 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00035 
00036 TAO_CORBALOC_Parser::~TAO_CORBALOC_Parser (void)
00037 {
00038 }
00039 
00040 bool
00041 TAO_CORBALOC_Parser::match_prefix (const char *ior_string) const
00042 {
00043   // Check if the prefix is 'corbaloc:' and return the result.
00044   return (ACE_OS::strncmp (ior_string,
00045                            prefix,
00046                            prefix_len) == 0);
00047 }
00048 
00049 CORBA::Object_ptr
00050 TAO_CORBALOC_Parser::make_stub_from_mprofile (CORBA::ORB_ptr orb,
00051                                               TAO_MProfile &mprofile)
00052 {
00053   // Create a TAO_Stub.
00054   TAO_Stub *data = orb->orb_core ()->create_stub ((const char *) 0,
00055                                                   mprofile
00056                                                  );
00057 
00058   TAO_Stub_Auto_Ptr safe_data (data);
00059 
00060   CORBA::Object_var obj = orb->orb_core ()->create_object (data);
00061 
00062   if (!CORBA::is_nil (obj.in ()))
00063     {
00064       /// All is well, so release the stub object from its
00065       /// auto_ptr.
00066       (void) safe_data.release ();
00067 
00068       /// Return the object reference to the application.
00069       return obj._retn ();
00070     }
00071 
00072   /// Shouldnt come here: if so, return nil reference.
00073   return CORBA::Object::_nil ();
00074 }
00075 
00076 CORBA::Object_ptr
00077 TAO_CORBALOC_Parser::parse_string_rir_helper (const char * ior,
00078                                               CORBA::ORB_ptr orb)
00079 {
00080   // Pass the key string as an argument to resolve_initial_references.
00081   // NameService is the default if an empty key string is supplied.
00082   const char *objkey = ior + rir_token_len;
00083   if (*objkey == '/') // there is an explicit object key, which may
00084                       // validly be null.
00085     objkey++;
00086 
00087   CORBA::Object_var rir_obj =
00088     orb->resolve_initial_references (*objkey == '\0' ? "NameService" : objkey);
00089 
00090   return rir_obj._retn ();
00091 }
00092 
00093 CORBA::Object_ptr
00094 TAO_CORBALOC_Parser::parse_string (const char * ior, CORBA::ORB_ptr orb)
00095 {
00096   // The decomposition of a corbaloc string is in Section 13.6.10.
00097   //
00098   // following the "corbaloc:"
00099   //  a comma separated list of <prot_addr> strings
00100   //    for each,
00101   // Separate out the key, delimited by '/'
00102   // Split out the various parts of our corbaloc string, comma-delimited
00103   // For each part
00104   //   Determine the protocol
00105   //     If rir, defer to another function and return the object
00106   //     If iiop, make the profile with <endpoint>:<port>/<key>
00107   //     If another protocol, use <remainder>/<key>
00108   //   Search through the collection of protocols for the correct one
00109   //     If not found, throw exception
00110   //     If found, make our_connector from it.
00111   //     our_connector->make_mprofile_unchecked (...);
00112   //     object = this->make_stub_from_mprofile (...);
00113   // Return the object
00114 
00115   // Skip the prefix.  We know it is there because this method is only
00116   // called if match_prefix() returns 1.
00117   ior += ACE_OS::strlen(prefix);
00118 
00119   //  First check for rir
00120   if (ACE_OS::strncmp (ior,rir_token,rir_token_len) == 0)
00121     return this->parse_string_rir_helper (ior,orb);
00122 
00123   // set up space for parsed endpoints. there will be at least 1, and
00124   // most likely commas will separate endpoints, although they could be
00125   // part of an endpoint address for some protocols.
00126   size_t max_endpoint_count = 1;
00127   for (const char *comma = ACE_OS::strchr (ior,',');
00128        comma;
00129        comma = ACE_OS::strchr (comma+1,','))
00130     ++max_endpoint_count;
00131 
00132   ACE_Array<parsed_endpoint> endpoints(max_endpoint_count);
00133   endpoints.size (0);
00134 
00135   // Get the Connector Registry from the ORB.
00136   TAO_Connector_Registry *conn_reg =
00137     orb->orb_core ()->connector_registry();
00138 
00139   while (1) { // will loop on comma only.
00140     size_t len = 0;
00141     size_t ndx = endpoints.size();
00142     endpoints.size(ndx+1);
00143     int uiop_compatible = 0;
00144     TAO_ConnectorSetIterator conn_iter = 0;
00145     for (conn_iter = conn_reg->begin();
00146          conn_iter != conn_reg->end() &&
00147            endpoints[ndx].profile_ == 0;
00148          conn_iter ++)
00149       {
00150         endpoints[ndx].profile_ =
00151           (*conn_iter)->corbaloc_scan(ior,len);
00152 
00153         if (endpoints[ndx].profile_)
00154           {
00155             endpoints[ndx].obj_key_sep_ =
00156               (*conn_iter)->object_key_delimiter();
00157             uiop_compatible = (endpoints[ndx].obj_key_sep_ == '|');
00158             this->make_canonical (ior,len,endpoints[ndx].prot_addr_);
00159             ior += len;
00160             break;
00161           }
00162       }
00163 
00164     if (endpoints[ndx].profile_ == 0)
00165       {
00166         if (TAO_debug_level)
00167           ACE_ERROR ((LM_ERROR,
00168                       ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ")
00169                       ACE_TEXT("could not parse from %s"),
00170                       ACE_TEXT_CHAR_TO_TCHAR(ior)));
00171         throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
00172       }
00173     if (*ior == ',') // more endpoints follow
00174       {
00175         ior++;
00176         continue;
00177       }
00178 
00179     if (*ior == '/') // found key separator
00180       {
00181         ior ++;
00182         break;
00183       }
00184 
00185     if (*ior == '\0') // no key separator appended, use default key
00186       {
00187         break;
00188       }
00189 
00190     if (uiop_compatible && *(ior - 1) == '|')
00191       // Assume this is an old uiop style corbaloc. No need to warn here,
00192       // the UIOP_Connector::corbaloc_scan already did.
00193       break;
00194 
00195     // anything else is a violation.
00196     if (TAO_debug_level)
00197       ACE_ERROR ((LM_ERROR,
00198                   ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ")
00199                   ACE_TEXT("could not parse from %s"),
00200                   ACE_TEXT_CHAR_TO_TCHAR(ior)));
00201     throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
00202   } // end of while
00203 
00204   // At this point, ior points at the start of the object key
00205   ACE_CString obj_key (*ior ? ior : (const char *)"NameService");
00206 
00207   // now take the collection of endpoints along with the decoded key and
00208   // mix them together to get the mprofile.
00209   TAO_MProfile mprofile (endpoints.size());
00210 
00211   for (size_t i = 0; i < endpoints.size(); i++)
00212     {
00213       ACE_CString full_ep = endpoints[i].prot_addr_ +
00214         endpoints[i].obj_key_sep_ +
00215         obj_key;
00216       const char * str = full_ep.c_str();
00217       endpoints[i].profile_->parse_string (str);
00218       int share = orb->orb_core()->orb_params()->shared_profile();
00219       if (mprofile.give_profile(endpoints[i].profile_, share) != -1)
00220         endpoints[i].profile_ = 0;
00221       else
00222         {
00223           // Although this ought never happen, we want to make some
00224           // indication back to the caller, more as an audit trail than
00225           // anything else. The only failure possible is that there was
00226           // insufficient heap to allocate the mprofile, hence the
00227           // mprofile's size is 0, and give_profile fails.
00228           if (TAO_debug_level)
00229             ACE_ERROR ((LM_ERROR,
00230                         ACE_TEXT("(%P|%t) TAO_CORBALOC_Parser::parse_string ")
00231                         ACE_TEXT("mprofile.give_profile failed for i = %d\n"),
00232                         i));
00233           throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
00234         }
00235     }
00236 
00237   // Get an object stub out.
00238   return this->make_stub_from_mprofile (orb, mprofile);
00239 }
00240 
00241 void
00242 TAO_CORBALOC_Parser::make_canonical (const char *ior,
00243                                      size_t prot_addr_len,
00244                                      ACE_CString &canonical_endpoint)
00245 {
00246   const char *separator = ACE_OS::strchr (ior, ':');
00247 
00248   // A special case for handling iiop
00249   if (ior[0] != ':' && ACE_OS::strncmp (ior,iiop_token,iiop_token_len) != 0)
00250     {
00251       canonical_endpoint.set (separator+1,
00252                               prot_addr_len - (separator - ior) - 1,1);
00253       return;
00254     }
00255 
00256   const char *addr_base = separator+1;
00257   const char *addr_tail = ior + prot_addr_len;
00258   // skip past version, if any
00259   separator = ACE_OS::strchr (addr_base,'@');
00260   if (separator != 0 && separator < addr_tail)
00261     {
00262       canonical_endpoint.set (addr_base,(separator - addr_base)+1,1);
00263       addr_base = separator + 1;
00264     }
00265   else
00266     canonical_endpoint.clear ();
00267 
00268   ACE_CString raw_host;
00269   ACE_CString raw_port;
00270   separator = ACE_OS::strchr (addr_base,':');
00271 #if defined (ACE_HAS_IPV6)
00272   // IPv6 numeric address in host string?
00273 
00274   // Check if this is an address containing a decimal IPv6 address representation.
00275   if (addr_base < addr_tail && addr_base[0] == '[')
00276     {
00277       // In this case we have to find the end of the numeric address and
00278       // start looking for the port separator from there.
00279       const char *cp_pos = ACE_OS::strchr(addr_base, ']');
00280       if (cp_pos == 0 || cp_pos >= addr_tail)
00281         {
00282           // No valid IPv6 address specified but that will come out later.
00283           if (TAO_debug_level > 0)
00284             {
00285               ACE_ERROR ((LM_ERROR,
00286                          ACE_TEXT ("\nTAO (%P|%t) TAO_CORBALOC_Parser: ")
00287                          ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
00288             }
00289           separator = 0;
00290         }
00291       else
00292         {
00293           if (cp_pos[1] == ':')    // Look for a port
00294             separator = cp_pos + 1;
00295           else
00296             separator = 0;
00297         }
00298     }
00299 #endif /* ACE_HAS_IPV6 */
00300 
00301   if (separator != 0 && separator < addr_tail)
00302     {
00303       // we have a port number
00304       raw_host.set (addr_base, (separator - addr_base), 1);
00305       raw_port.set (separator, (addr_tail - separator), 1);
00306     }
00307   else
00308     {
00309       // we must default port #
00310       if (addr_base < addr_tail)
00311         raw_host.set (addr_base, (addr_tail - addr_base),1);
00312       raw_port.set (":2809");
00313     }
00314 
00315   if (raw_host.length() == 0)
00316     {
00317       ACE_INET_Addr host_addr;
00318 
00319       char tmp_host [MAXHOSTNAMELEN + 1];
00320 
00321       // If no host is specified: assign the default host, i.e. the
00322       // local host.
00323       if (host_addr.get_host_name (tmp_host,
00324                                    sizeof (tmp_host)) != 0)
00325         {
00326           // Can't get the IP address since the INET_Addr wasn't
00327           // initialized.  Just throw an exception.
00328 
00329           if (TAO_debug_level > 0)
00330             ACE_DEBUG ((LM_DEBUG,
00331                         ACE_TEXT ("TAO (%P|%t) ")
00332                         ACE_TEXT ("cannot determine hostname.\n")));
00333 
00334           throw ::CORBA::INV_OBJREF
00335                      (CORBA::SystemException::_tao_minor_code
00336                       (TAO::VMCID, EINVAL),
00337                       CORBA::COMPLETED_NO);
00338         }
00339       else
00340         {
00341           canonical_endpoint += tmp_host;
00342         }
00343     }
00344   else
00345     {
00346       canonical_endpoint += raw_host;
00347     }
00348 
00349   canonical_endpoint += raw_port;
00350 }
00351 
00352 TAO_END_VERSIONED_NAMESPACE_DECL
00353 
00354 ACE_STATIC_SVC_DEFINE (TAO_CORBALOC_Parser,
00355                        ACE_TEXT ("CORBALOC_Parser"),
00356                        ACE_SVC_OBJ_T,
00357                        &ACE_SVC_NAME (TAO_CORBALOC_Parser),
00358                        ACE_Service_Type::DELETE_THIS |
00359                        ACE_Service_Type::DELETE_OBJ,
00360                        0)
00361 
00362 ACE_FACTORY_DEFINE (TAO, TAO_CORBALOC_Parser)
00363 
00364 #endif /* TAO_HAS_CORBALOC_PARSER == 1 */

Generated on Tue Feb 2 17:37:51 2010 for TAO by  doxygen 1.4.7