/* * MICO --- an Open Source CORBA implementation * Copyright (C) 1998 Frank Pilhofer * Copyright (c) 1999-2023 by The Mico Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * For more information, visit the MICO Home Page at * http://www.mico.org/ */ /* * Portable Server Module */ #ifdef FAST_PCH #include "orb_pch.h" #endif // FAST_PCH #ifdef __COMO__ #pragma hdrstop #endif // __COMO__ #ifndef FAST_PCH #define MICO_CONF_INTERCEPT #include #include #include #include #include #include #include #include #ifdef USE_SL3 #include #include #include #endif // USE_SL3 #endif // FAST_PCH using namespace std; /* * Static data */ namespace MICOPOA { POAOptions poaopts; bool S_initialized_ = false; } MICOPOA::POA_impl::POAMap MICOPOA::POA_impl::AllPOAs; MICOPOA::UniqueIdGenerator MICOPOA::POA_impl::poauid; MICOPOA::UniqueIdGenerator MICOPOA::POA_impl::idfactory ("_"); MICOPOA::POACurrent_impl * MICOPOA::POA_impl::current = NULL; string MICOPOA::POA_impl::oaprefix; string MICOPOA::POA_impl::impl_name; CORBA::IOR MICOPOA::POA_impl::poamed_ior; CORBA::POAMediator_var MICOPOA::POA_impl::poamed; CORBA::Boolean MICOPOA::POA_impl::ever_been_active; MICOMT::Mutex MICOPOA::POA_impl::S_global_invoke_lock; MICOMT::Mutex MICOPOA::POA_impl::S_servant_manager_lock; /* * ---------------------------------------------------------------------- * * Initialization via Init Interceptor * * ---------------------------------------------------------------------- */ namespace MICOPOA { class ORBInitializer : virtual public PortableInterceptor::ORBInitializer, virtual public CORBA::LocalObject { public: ORBInitializer() {} virtual ~ORBInitializer() {} virtual void pre_init(PortableInterceptor::ORBInitInfo_ptr info) { CORBA::StringSeq_var info_args = info->arguments(); vector args; for (CORBA::ULong i = 0; i < info_args->length(); i++) { args.push_back(info_args[i].in()); } CORBA::ORB_var orb = CORBA::ORB_instance("mico-local-orb", FALSE); assert(!CORBA::is_nil(orb)); if (!MICOPOA::poaopts.parse (orb, args)) { // kcg: what to do in case of error? } } virtual void post_init(PortableInterceptor::ORBInitInfo_ptr info) {} }; } void MICOPOA::_init () { // (void) InitPOA; if (!S_initialized_) { PortableInterceptor::register_orb_initializer(new ORBInitializer()); S_initialized_ = true; } } /* * Options parser */ CORBA::Boolean MICOPOA::POAOptions::parse (CORBA::ORB_ptr orb, const vector& args) { MICOGetOpt::OptMap opts; opts["-POARemoteIOR"] = "arg-expected"; opts["-POAImplName"] = "arg-expected"; opts["-POARemoteAddr"] = "arg-expected"; MICOGetOpt opt_parser (opts); CORBA::Boolean r = opt_parser.parse (orb->rcfile(), TRUE); if (!r) return FALSE; r = opt_parser.parse (args, TRUE); if (!r) return FALSE; const MICOGetOpt::OptVec &o = opt_parser.opts(); MICOGetOpt::OptVec parsed_args = opt_parser.opts(); orb->register_options_for_removal(parsed_args); for (MICOGetOpt::OptVec::const_iterator i = o.begin(); i != o.end(); ++i) { string arg = (*i).first; string val = (*i).second; options[arg] = val; } return TRUE; } const char * MICOPOA::POAOptions::operator[] (const char * opt) { map >::iterator it = options.find (opt); if (it == options.end()) { return NULL; } return (*it).second.c_str(); } /* * ---------------------------------------------------------------------- * * POAManager interface * * ---------------------------------------------------------------------- */ MICOPOA::POAManager_impl::POAManager_impl () : managed_lock(FALSE, MICOMT::Mutex::Recursive) { _state = HOLDING; } MICOPOA::POAManager_impl::~POAManager_impl () { } PortableServer::POAManager::State MICOPOA::POAManager_impl::get_state () { return _state; } void MICOPOA::POAManager_impl::add_managed_poa (PortableServer::POA_ptr poa) { MICOMT::AutoLock l(managed_lock); managed.push_back (poa); } void MICOPOA::POAManager_impl::del_managed_poa (PortableServer::POA_ptr poa) { MICOMT::AutoLock l(managed_lock); vector::iterator it = managed.begin (); while (it != managed.end()) { if (*it == poa) { managed.erase (it); return; } it++; } } void MICOPOA::POAManager_impl::change_state (State s, CORBA::Boolean etherealize_objects, CORBA::Boolean wait_for_completion) { if (_state == INACTIVE) { if (s != INACTIVE) mico_throw (PortableServer::POAManager::AdapterInactive()); return; // Manager is already in inactive state } if (_state == s) { return; } _state = s; managed_lock.lock(); vector::iterator it = managed.begin(); while (it != managed.end()) { (*it)->poa_manager_callback (_state, etherealize_objects, wait_for_completion); it++; } managed_lock.unlock(); } void MICOPOA::POAManager_impl::activate () { change_state (ACTIVE); } void MICOPOA::POAManager_impl::hold_requests (CORBA::Boolean wait_for_completion) { change_state (HOLDING, FALSE, wait_for_completion); } void MICOPOA::POAManager_impl::discard_requests (CORBA::Boolean wait_for_completion) { change_state (DISCARDING, FALSE, wait_for_completion); } void MICOPOA::POAManager_impl::deactivate (CORBA::Boolean etherealize_objects, CORBA::Boolean wait_for_completion) { change_state (INACTIVE, etherealize_objects, wait_for_completion); } /* * ---------------------------------------------------------------------- * * Current interface * * ---------------------------------------------------------------------- */ MICOPOA::POACurrent_impl::CurrentState::CurrentState () { // This method exists to make HP aCC happy assert (0); } MICOPOA::POACurrent_impl::CurrentState::CurrentState (PortableServer::POA_ptr _poa, POAObjectReference * _por, PortableServer::Servant _serv) { poa = _poa; por = _por; serv = _serv; serv->_add_ref (); } MICOPOA::POACurrent_impl::CurrentState::CurrentState (const CurrentState & o) { poa = o.poa; por = o.por; serv = o.serv; serv->_add_ref (); } MICOPOA::POACurrent_impl::CurrentState::~CurrentState () { serv->_remove_ref (); } #ifdef HAVE_THREADS static void __current_cleanup(void *css) { MICOPOA::POACurrent_impl::CurrentStateStack *current = static_cast(css); if (current) delete current; } #endif MICOPOA::POACurrent_impl::POACurrent_impl (CORBA::ORB_ptr porb) { #ifndef HAVE_THREADS state_stack_ = NULL; #else // HAVE_THREADS // we get exactly one POACurrent object // therefor no care is nesesary for creating the key MICOMT::Thread::create_key(current_key_, &__current_cleanup); #endif // HAVE_THREADS assert (CORBA::is_nil (PortableServer::_the_poa_current)); PortableServer::_the_poa_current = this; orb = porb; orb->set_initial_reference ("POACurrent", this); } MICOPOA::POACurrent_impl::~POACurrent_impl () { PortableServer::_the_poa_current = NULL; #ifndef HAVE_THREADS delete state_stack_; #else // HAVE_THREADS MICOMT::Thread::delete_key(current_key_); #endif // HAVE_THREADS //FIXME: shouldn't we remove the initial_reference ?? } PortableServer::POA_ptr MICOPOA::POACurrent_impl::get_POA () { if (!this->iscurrent()) { mico_throw(PortableServer::Current::NoContext()); } return PortableServer::POA::_duplicate (this->get_current()->back().poa); } PortableServer::ObjectId * MICOPOA::POACurrent_impl::get_object_id () { if (!this->iscurrent()) { mico_throw(PortableServer::Current::NoContext()); } return this->get_current()->back().por->id(); } CORBA::Object_ptr MICOPOA::POACurrent_impl::get_reference () { if (!this->iscurrent()) { mico_throw(PortableServer::Current::NoContext()); } return this->get_current()->back().por->ref(); } PortableServer::Servant MICOPOA::POACurrent_impl::get_servant () { if (!this->iscurrent()) { mico_throw(PortableServer::Current::NoContext()); } return this->get_current()->back().serv; } CORBA::Boolean MICOPOA::POACurrent_impl::iscurrent () { CurrentStateStack* curr = this->get_current(); if (curr != NULL && !curr->empty()) return TRUE; return FALSE; } MICOPOA::POAObjectReference * MICOPOA::POACurrent_impl::get_por () { MICOPOA::POACurrent_impl::CurrentStateStack *current = get_current(); assert (current); return current->back().por; } void MICOPOA::POACurrent_impl::set (PortableServer::POA_ptr _poa, POAObjectReference * _por, PortableServer::Servant _serv) { if (MICO::Logger::IsLogged (MICO::Logger::POA)) { MICOMT::AutoDebugLock __lock; MICO::Logger::Stream (MICO::Logger::POA) << "void MICOPOA::POACurrent_impl::set( " << "poa=" << _poa << ", POAObjectReference=" << _por << ", Servant=" << _serv << " )" << endl; } MICOPOA::POACurrent_impl::CurrentStateStack *current = get_current(); if (!current) { current = new CurrentStateStack; this->set_current(current); } current->push_back (CurrentState (_poa, _por, _serv)); } void MICOPOA::POACurrent_impl::unset () { if (MICO::Logger::IsLogged (MICO::Logger::POA)) { MICOMT::AutoDebugLock __lock; MICO::Logger::Stream (MICO::Logger::POA) << "void MICOPOA::POACurrent_impl::unset()" << endl; } MICOPOA::POACurrent_impl::CurrentStateStack *current = get_current(); assert (current); assert (!current->empty()); current->pop_back(); } // #endif // HAVE_THREADS /* * ---------------------------------------------------------------------- * * Helper Classes * * ---------------------------------------------------------------------- */ /* * Object Id */ MICOPOA::ObjectId::ObjectId () { octets = NULL; oid = NULL; own = true; idlength = 0; } MICOPOA::ObjectId::ObjectId (const ObjectId & id, bool copy) { oid = NULL; idlength = id.idlength; if ((own = copy)) { octets = CORBA::string_alloc (idlength); memcpy (octets, id.octets, idlength); } else { octets = (char *) id.octets; } } MICOPOA::ObjectId::ObjectId (const PortableServer::ObjectId & id) { own = true; oid = NULL; idlength = id.length (); octets = CORBA::string_alloc (idlength); for (CORBA::ULong i=0; ilength (idlength); for (CORBA::ULong i=0; i(value); if (ref != NULL) { delete ref; } } } #endif // HAVE_THREADS MICOPOA::POAObjectReference::POAObjectReference (POA_impl * _poa, const PortableServer::ObjectId &_i, const char * _repoid, PortableServer::Servant _serv) : poa (_poa), repoid (_repoid), oid (_i), servant (_serv) { assert (_poa); assert (_repoid); poa->_ref(); poaname = poa->get_oaid(); obj = CORBA::Object::_nil (); iddirty = false; if (servant) { servant->_add_ref(); } } MICOPOA::POAObjectReference::POAObjectReference (POA_impl * _poa, CORBA::Object_ptr _obj) : poa (_poa) { assert (_poa); poa->_ref(); obj = CORBA::Object::_duplicate (_obj); iddirty = true; servant = NULL; } MICOPOA::POAObjectReference::POAObjectReference (const POAObjectReference &o) : poa (o.poa), iddirty (o.iddirty), poaname (o.poaname), repoid (o.repoid),oid (o.oid),servant (o.servant) { poa->_ref(); obj = CORBA::Object::_duplicate (o.obj); if (servant) { servant->_add_ref(); } } MICOPOA::POAObjectReference::~POAObjectReference () { CORBA::release (obj); CORBA::release (poa); obj = NULL; if (servant) { servant->_remove_ref(); } } void MICOPOA::POAObjectReference::make_ref () { if (!CORBA::is_nil (obj)) { /* * obj might be a "local" reference. We might need one pointing * to the Mediator. * This happens when the IOR contains a single GIOPSimpleProf, which * has the ID 10000, which is unfortunately hardcoded. So verify * with iop.cc. */ CORBA::IORProfile* prof = NULL; if (obj->_ior() && (prof = obj->_ior()->profile()) && prof->id() == 10000) { const CORBA::Octet * key; CORBA::Long length; key = prof->objectkey (length); CORBA::IOR * ior = new CORBA::IOR (*poa->ior_template()); ior->objectkey ((CORBA::Octet *) key, length); // obj->_repoid() is empty ... ior->objid (obj->_ior()->objid()); CORBA::release (obj); obj = new CORBA::Object (ior); assert (!CORBA::is_nil (obj)); obj->_setup_domains (CORBA::Object::_nil()); } return; } if (iddirty) { // We manage a nil reference return; } /* * key = / * * We escape any slashes in (slashes in poa-name are already * quoted). If poa-name == id, then we collapse both. */ string::size_type poaname_len = poaname.length(); assert(poaname_len < UINT_MAX); CORBA::ULong idlength, length = (CORBA::ULong)poaname_len; string::size_type i, j = poaname.length(); CORBA::Boolean samename = FALSE; const char * iddata = oid.get_data (idlength); if (idlength == length) { for (i=0; i < idlength; i++) { if (iddata[i] != poaname[i]) { break; } } if (i == idlength) { samename = TRUE; } } if (!samename) { for (i=0; i < idlength; i++) { if (iddata[i] == '/' || iddata[i] == '\\') { length++; } length++; } length++; } CORBA::Octet * key = (CORBA::Octet *) CORBA::string_alloc (length); memcpy (key, poaname.c_str(), j); if (!samename) { key[j++] = '/'; for (i=0; i < idlength; i++, j++) { if (iddata[i] == '/' || iddata[i] == '\\') { key[j++] = '\\'; } key[j] = (CORBA::Octet) iddata[i]; } } assert (j == length); /* * Generate a Mobile Object Key if necessary. */ CORBA::ORB_var orb = CORBA::ORB_instance ("mico-local-orb"); if (!orb->plugged()) { CORBA::ULong align; MICO::CDREncoder ec; CORBA::ULong tlen; const CORBA::Octet *tid = orb->terminal_id(tlen); /* * Do encaps by hand since we don't want length in here */ align = ec.buffer()->walign_base(); ec.put_octet(ec.byteorder() == CORBA::LittleEndian ? TRUE : FALSE); ec.put_chars_raw ("MIOR", 4); ec.struct_begin(); { ec.struct_begin(); { ec.put_octet(0x01); ec.put_octet(0x00); } ec.struct_end(); ec.put_octet(0x00); ec.seq_begin(tlen); { ec.put_octets(tid, tlen); } ec.seq_end(); ec.seq_begin(length); { ec.put_octets((CORBA::Octet*)key, length); } ec.seq_end(); } ec.struct_end(); ec.buffer()->walign_base(align); length = ec.buffer()->length(); CORBA::string_free((char *) key); key = (CORBA::Octet *) CORBA::string_alloc (length); memcpy (key, ec.buffer()->data(), length); } CORBA::IOR * ior = new CORBA::IOR (*poa->ior_template()); ior->objectkey (key, length); ior->objid (repoid.c_str()); CORBA::string_free ((char *) key); obj = new CORBA::Object (ior); assert (!CORBA::is_nil (obj)); obj->_setup_domains (CORBA::Object::_nil()); if (servant) { CORBA::Object_ptr stub = servant->_make_stub (poa, obj); if (!CORBA::is_nil (stub)) { CORBA::release (obj); obj = stub; } } } bool MICOPOA::POAObjectReference::decompose_ref () { MICOMT::AutoLock l(_ref_lock); /* * The object key that we are about to decompose might be complete * garbage in case we didn't generate it ourselves. */ if (!iddirty) { // nothing to do return true; } CORBA::IORProfile* prof = NULL; if (CORBA::is_nil (obj) || !obj->_ior() || !(prof = obj->_ior()->profile())) { return false; } CORBA::Long i, j, length, idlength; const CORBA::Octet * key = prof->objectkey (length); if (!key) { return false; } /* * Strip away the beginning if it was a Mobile Object Key */ if (CORBA::ORB::is_mobile_key (key)) { CORBA::Octet bo; CORBA::Buffer *buf = new CORBA::Buffer (const_cast (key)); #ifdef _WIN32 MICO::CDRDecoder dc(buf, TRUE, CORBA::DefaultEndian, 0, TRUE, 0, TRUE); #else MICO::CDRDecoder dc(buf); #endif #define check(exp) if (!(exp)) return false char crap[4]; check(dc.get_octet(bo)); CORBA::ByteOrder sbo = dc.byteorder(); dc.byteorder(bo == 0 ? CORBA::BigEndian : CORBA::LittleEndian); check(dc.get_chars(crap, 4)); check(dc.struct_begin()); { check(dc.get_octets(crap, 2)); } check(dc.struct_end()); CORBA::Octet oc; check(dc.get_octet(oc)); CORBA::ULong l; check(dc.seq_begin(l)); { CORBA::Octet oc; for (CORBA::ULong i = 0; i < l; ++i) check(dc.get_octet(oc)); } check(dc.seq_end()); check(dc.get_ulong(l)); #undef check dc.byteorder(sbo); key = dc.buffer()->data(); length = l; } /* * The poaname is everything up to the last unescaped slash */ for (i=length-1; i>0; i--) { if (key[i] == '/') { for (j=0; j_repoid (); return true; } bool MICOPOA::POAObjectReference::is_legal () { if (!iddirty) { return true; } if (!CORBA::is_nil (obj)) { return decompose_ref (); } return false; } const MICOPOA::ObjectId & MICOPOA::POAObjectReference::get_oid () { if (iddirty) { bool r = decompose_ref (); assert (r); } return oid; } CORBA::Object_ptr MICOPOA::POAObjectReference::get_ref () { MICOMT::AutoLock l(_ref_lock); make_ref (); return obj; } void MICOPOA::POAObjectReference::set_ref (CORBA::Object_ptr o) { MICOMT::AutoLock l(_ref_lock); CORBA::release (obj); obj = CORBA::Object::_duplicate (o); } const PortableServer::ObjectId & MICOPOA::POAObjectReference::get_id () { if (iddirty) { bool r = decompose_ref (); assert (r); } return oid.get_id(); } CORBA::Object_ptr MICOPOA::POAObjectReference::ref () { MICOMT::AutoLock l(_ref_lock); make_ref(); return CORBA::Object::_duplicate (obj); } PortableServer::ObjectId * MICOPOA::POAObjectReference::id () { return new PortableServer::ObjectId (get_id()); } MICOPOA::POAObjectReference & MICOPOA::POAObjectReference::operator= (const CORBA::Object_ptr oref) { MICOMT::AutoLock l(_ref_lock); // assume same POA iddirty = TRUE; CORBA::release (obj); obj = CORBA::Object::_duplicate (oref); return *this; } MICOPOA::POAObjectReference & MICOPOA::POAObjectReference::operator= (const POAObjectReference &o) { MICOMT::AutoLock l(_ref_lock); CORBA::release (obj); poa = o.poa; poaname = o.poaname; repoid = o.repoid; oid = o.oid; iddirty = o.iddirty; obj = CORBA::Object::_duplicate (o.obj); return *this; } const char * MICOPOA::POAObjectReference::poa_name () { bool r = decompose_ref (); assert (r); return poaname.c_str(); } bool MICOPOA::POAObjectReference::in_poa (const char * pname) { if (!decompose_ref()) { return false; } const char * pstr = poaname.c_str(); return !strcmp (pstr, pname); } bool MICOPOA::POAObjectReference::in_descendant_poa (const char * fqn, const char * implname) { if (!decompose_ref()) { return false; } const char * pstr = poaname.c_str(); if (*implname && strncmp (pstr, implname, strlen (implname)) == 0) { pstr += strlen (implname); if (!*pstr) { pstr = poaname.c_str(); // collapsed POA name } else if (*pstr++ != '/') { return false; } } else { return false; } return (!strncmp (pstr, fqn, strlen (fqn)) && (!*fqn || pstr[strlen(fqn)] == '/')); } char * MICOPOA::POAObjectReference::next_descendant_poa (const char * fqn, const char * implname) { bool r = decompose_ref (); assert (r); assert (in_descendant_poa (fqn, implname)); const char * pstr = poaname.c_str(); if (*implname && strncmp (pstr, implname, strlen (implname)) == 0) { pstr += strlen (implname); if (!*pstr) { pstr = poaname.c_str(); // collapsed POA name } else { assert (*pstr == '/'); pstr++; } } else { assert (0); } size_t i, j; char * res; if (*fqn) { pstr += strlen (fqn); assert (*pstr == '/'); pstr++; } for (i=0, j=0; pstr[i] && pstr[i] != '/'; i++, j++) { if (pstr[i] == '\\') { i++; } } assert(i < UINT_MAX); res = CORBA::string_alloc ((CORBA::ULong)i); assert (res); for (i=0, j=0; pstr[i] && pstr[i] != '/'; i++, j++) { if (pstr[i] == '\\') { i++; } res[j] = pstr[i]; } res[j] = '\0'; return res; } /* * Unique Id generator */ MICOPOA::UniqueIdGenerator::UniqueIdGenerator () { uid = NULL; prefix = NULL; pfxlen = 0; } MICOPOA::UniqueIdGenerator::UniqueIdGenerator (const char * pfx) { uid = NULL; prefix = CORBA::string_dup (pfx); pfxlen = strlen (prefix); } MICOPOA::UniqueIdGenerator::~UniqueIdGenerator () { CORBA::string_free (uid); CORBA::string_free (prefix); } char * MICOPOA::UniqueIdGenerator::new_id () { char * id; /* * Generate a new unique id */ if (uid == NULL) { ulen = 1; uid = CORBA::string_alloc ((CORBA::ULong)ulen); assert (uid); uid[0] = '0'; uid[1] = 0; } else { int i; for (i=0; i_add_ref (); } MICOPOA::ObjectMap::ObjectRecord::~ObjectRecord () { delete por; serv->_remove_ref (); } MICOPOA::ObjectMap::~ObjectMap () { clear (); } bool MICOPOA::ObjectMap::empty () const { return objs.empty (); } void MICOPOA::ObjectMap::clear () { iterator it = objs.begin (); while (it != objs.end()) { delete (*it).second; it++; } objs.clear (); servants.clear (); } MICOPOA::ObjectMap::iterator MICOPOA::ObjectMap::begin () { return objs.begin (); } MICOPOA::ObjectMap::iterator MICOPOA::ObjectMap::end () { return objs.end (); } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::pop () { assert (!empty()); iterator oit = objs.begin (); ObjectRecord * orec = (*oit).second; objs.erase (oit); SvMap::iterator sit = servants.find (orec->serv); assert (sit != servants.end()); for (vector::iterator orit = (*sit).second.begin(); orit != (*sit).second.end(); orit++) { if ((*orit) == orec) { (*sit).second.erase (orit); break; } } if ((*sit).second.empty()) { servants.erase (sit); } return orec; } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::add (POAObjectReference * por, PortableServer::Servant serv) { ObjectRecord * orec = new ObjectRecord (por, serv); ObjectId oid (por->get_id()); assert (objs.find (oid) == objs.end()); objs[oid] = orec; servants[serv].push_back (orec); return orec; } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::del (const ObjectId & oid) { iterator it = objs.find (oid); assert (it != objs.end()); ObjectRecord * orec = (*it).second; SvMap::iterator sit = servants.find (orec->serv); assert (sit != servants.end()); for (vector::iterator orit = (*sit).second.begin(); orit != (*sit).second.end(); orit++) { if ((*orit) == orec) { (*sit).second.erase (orit); break; } } if ((*sit).second.empty()) { servants.erase (sit); } objs.erase (it); return orec; } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::del (const PortableServer::ObjectId & id) { return del (ObjectId (id)); } bool MICOPOA::ObjectMap::exists (const ObjectId & oid) { return (objs.find (oid) != objs.end()); } bool MICOPOA::ObjectMap::exists (const PortableServer::ObjectId & id) { return exists (ObjectId (id)); } bool MICOPOA::ObjectMap::exists (const POAObjectReference & por) { // need to cast constness away POAObjectReference * nc = (POAObjectReference *) &por; return (objs.find (nc->get_oid()) != objs.end()); } bool MICOPOA::ObjectMap::exists (PortableServer::Servant serv) { SvMap::iterator sit = servants.find (serv); assert (sit==servants.end() || !(*sit).second.empty()); return (sit != servants.end()); } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::find (const ObjectId & oid) { iterator it = objs.find (oid); if (it == objs.end()) { return NULL; } return (*it).second; } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::find (const PortableServer::ObjectId & id) { return find (ObjectId (id)); } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::find (const POAObjectReference & por) { // need to cast constness away POAObjectReference * nc = (POAObjectReference *) &por; return find (nc->get_oid()); } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::find (POA_impl * poa, CORBA::Object_ptr obj) { CORBA::IORProfile* prof = NULL; if (CORBA::is_nil (obj) || !obj->_ior() || !(prof = obj->_ior()->profile())) { return NULL; } CORBA::Long length, i; const CORBA::Octet * key = prof->objectkey (length); if (!key) { return NULL; } /* * Object Id is everything after the last unescaped slash. We do some * trivial checking if the last slash is unescaped (i.e. if the ObjectId * does not contain a slash). If yes, we can simply point to that data * to speed up the search; else we use a POAObjectReference and save us * the work of unescaping the string by ourselves. */ for (i=length-1; i>0; i--) { if (key[i] == '/') { break; } } if (i==0 || key[i++-1] != '\\') { return find (ObjectId ((const char *) key+i, (CORBA::ULong) length-i, false)); } return find (POAObjectReference (poa, obj)); } MICOPOA::ObjectMap::ObjectRecord * MICOPOA::ObjectMap::find (PortableServer::Servant serv) { SvMap::iterator sit = servants.find (serv); if (sit == servants.end()) { return NULL; } assert ((*sit).second.size() == 1); return (*sit).second[0]; } /* * ---------------------------------------------------------------------- * * The POA * * ---------------------------------------------------------------------- */ MICOPOA::POA_impl::InvocationRecord::InvocationRecord (CORBA::ORBMsgId _id, POAObjectReference * _por, CORBA::ORBRequest * _req, CORBA::Principal_ptr _pr) { por = new POAObjectReference (*_por); req = CORBA::ORBRequest::_duplicate (_req); pr = CORBA::Principal::_duplicate (_pr); svr = CORBA::ServerRequest::_nil (); orbid = CORBA::ORBInvokeRec::_duplicate(_id); } MICOPOA::POA_impl::InvocationRecord::~InvocationRecord () { CORBA::release (req); CORBA::release (pr); CORBA::release (svr); delete por; } void MICOPOA::POA_impl::InvocationRecord::exec (POA_impl * poa) { poa->local_invoke (this); } CORBA::ORBMsgId MICOPOA::POA_impl::InvocationRecord::id () { return CORBA::ORBInvokeRec::_duplicate(orbid); } CORBA::ORBRequest * MICOPOA::POA_impl::InvocationRecord::get_or () { return req; } MICOPOA::POAObjectReference * MICOPOA::POA_impl::InvocationRecord::get_por () { return por; } CORBA::ServerRequestBase_ptr MICOPOA::POA_impl::InvocationRecord::make_req (POA_impl * poa, PortableServer::Servant serv) { assert (serv); assert (CORBA::is_nil (svr)); if (CORBA::is_nil (svr)) { svr = serv->make_request (req, por->get_ref(), orbid, poa, pr); assert (!CORBA::is_nil (svr)); } return svr; } CORBA::ServerRequest_ptr MICOPOA::POA_impl::InvocationRecord::make_dyn_req (POA_impl * poa) { CORBA::ServerRequest_ptr dynsvr; assert (CORBA::is_nil (svr)); dynsvr = new CORBA::ServerRequest (req, por->get_ref(), orbid, poa, pr); svr = dynsvr; assert (!CORBA::is_nil (svr)); return dynsvr; } /* * POA attributes */ char * MICOPOA::POA_impl::the_name () { return CORBA::string_dup (name.c_str()); } PortableServer::POA_ptr MICOPOA::POA_impl::the_parent () { return PortableServer::POA::_duplicate (parent); } PortableServer::POAManager_ptr MICOPOA::POA_impl::the_POAManager () { return PortableServer::POAManager::_duplicate (manager); } PortableServer::POAList * MICOPOA::POA_impl::the_children () { PortableServer::POAList * res = new PortableServer::POAList; POAMap::iterator it = children.begin (); CORBA::ULong i = 0; mico_vec_size_type chsize = children.size(); assert(chsize < UINT_MAX); res->length ((CORBA::ULong)chsize); while (it != children.end()) { (*res)[i++] = PortableServer::POA::_duplicate ((*it++).second); } return res; } PortableServer::AdapterActivator_ptr MICOPOA::POA_impl::the_activator () { return PortableServer::AdapterActivator::_duplicate (adapter_activator); } void MICOPOA::POA_impl::the_activator (PortableServer::AdapterActivator_ptr _aa) { adapter_activator = PortableServer::AdapterActivator::_duplicate (_aa); } CORBA::OctetSeq* MICOPOA::POA_impl::id() { string t_str = this->get_oaid(); string::size_type t_str_len = t_str.length(); assert(t_str_len < UINT_MAX); CORBA::OctetSeq* retval = new CORBA::OctetSeq; retval->length((CORBA::ULong)t_str_len); for (CORBA::ULong i=0; ilength(); i++) { (*retval)[i] = t_str[i]; } return retval; } /* * Factories for Policy objects */ PortableServer::ThreadPolicy_ptr MICOPOA::POA_impl::create_thread_policy (PortableServer::ThreadPolicyValue _v) { return new ThreadPolicy_impl (PortableServer::THREAD_POLICY_ID, _v); } PortableServer::LifespanPolicy_ptr MICOPOA::POA_impl::create_lifespan_policy (PortableServer::LifespanPolicyValue _v) { return new LifespanPolicy_impl (PortableServer::LIFESPAN_POLICY_ID, _v); } PortableServer::IdUniquenessPolicy_ptr MICOPOA::POA_impl::create_id_uniqueness_policy (PortableServer::IdUniquenessPolicyValue _v) { return new IdUniquenessPolicy_impl (PortableServer::ID_UNIQUENESS_POLICY_ID, _v); } PortableServer::IdAssignmentPolicy_ptr MICOPOA::POA_impl::create_id_assignment_policy (PortableServer::IdAssignmentPolicyValue _v) { return new IdAssignmentPolicy_impl (PortableServer::ID_ASSIGNMENT_POLICY_ID, _v); } PortableServer::ImplicitActivationPolicy_ptr MICOPOA::POA_impl::create_implicit_activation_policy (PortableServer::ImplicitActivationPolicyValue _v) { return new ImplicitActivationPolicy_impl (PortableServer::IMPLICIT_ACTIVATION_POLICY_ID, _v); } PortableServer::ServantRetentionPolicy_ptr MICOPOA::POA_impl::create_servant_retention_policy (PortableServer::ServantRetentionPolicyValue _v) { return new ServantRetentionPolicy_impl (PortableServer::SERVANT_RETENTION_POLICY_ID, _v); } PortableServer::RequestProcessingPolicy_ptr MICOPOA::POA_impl::create_request_processing_policy (PortableServer::RequestProcessingPolicyValue _v) { return new RequestProcessingPolicy_impl (PortableServer::REQUEST_PROCESSING_POLICY_ID, _v); } /* * ServantManager registration */ PortableServer::ServantManager_ptr MICOPOA::POA_impl::get_servant_manager () { if (request_processing_policy->value () != PortableServer::USE_SERVANT_MANAGER) { mico_throw (PortableServer::POA::WrongPolicy()); } return PortableServer::ServantManager::_duplicate (servant_manager); } void MICOPOA::POA_impl::set_servant_manager (PortableServer::ServantManager_ptr _s) { if (request_processing_policy->value () != PortableServer::USE_SERVANT_MANAGER) { mico_throw (PortableServer::POA::WrongPolicy()); } if (CORBA::is_nil (_s)) { mico_throw (CORBA::OBJ_ADAPTER (0, CORBA::COMPLETED_NO)); } if ((servant_retention_policy->value() == PortableServer::RETAIN && !_s->_is_a ("IDL:omg.org/PortableServer/ServantActivator:1.0")) || (servant_retention_policy->value() == PortableServer::NON_RETAIN && !_s->_is_a ("IDL:omg.org/PortableServer/ServantLocator:1.0"))) { mico_throw (CORBA::OBJ_ADAPTER (0, CORBA::COMPLETED_NO)); } if (!CORBA::is_nil (servant_manager)) { mico_throw (CORBA::BAD_INV_ORDER (6, CORBA::COMPLETED_NO)); } servant_manager = PortableServer::ServantManager::_duplicate (_s); } PortableServer::Servant MICOPOA::POA_impl::get_servant () { if (request_processing_policy->value () != PortableServer::USE_DEFAULT_SERVANT) { mico_throw (PortableServer::POA::WrongPolicy()); } if (default_servant == NULL) { mico_throw (PortableServer::POA::NoServant()); } default_servant->_add_ref (); return default_servant; } void MICOPOA::POA_impl::set_servant (PortableServer::Servant _s) { if (request_processing_policy->value () != PortableServer::USE_DEFAULT_SERVANT) { mico_throw (PortableServer::POA::WrongPolicy()); } if (default_servant) { default_servant->_remove_ref (); } _s->_add_ref (); default_servant = _s; } /* * POA creation and destruction */ void MICOPOA::POA_impl::set_policies (const CORBA::PolicyList & policies) { thread_policy = PortableServer::ThreadPolicy::_nil(); lifespan_policy = PortableServer::LifespanPolicy::_nil(); id_uniqueness_policy = PortableServer::IdUniquenessPolicy::_nil(); id_assignment_policy = PortableServer::IdAssignmentPolicy::_nil(); implicit_activation_policy = PortableServer::ImplicitActivationPolicy::_nil(); servant_retention_policy = PortableServer::ServantRetentionPolicy::_nil(); request_processing_policy = PortableServer::RequestProcessingPolicy::_nil(); CORBA::PolicyList plist; for (CORBA::ULong i=0; ipolicy_type() == PortableServer::THREAD_POLICY_ID) { thread_policy = PortableServer::ThreadPolicy::_narrow (pol); assert (!CORBA::is_nil (thread_policy)); } else if (pol->policy_type() == PortableServer::LIFESPAN_POLICY_ID) { lifespan_policy = PortableServer::LifespanPolicy::_narrow (pol); assert (!CORBA::is_nil (lifespan_policy)); } else if (pol->policy_type() == PortableServer::ID_UNIQUENESS_POLICY_ID) { id_uniqueness_policy = PortableServer::IdUniquenessPolicy::_narrow (pol); assert (!CORBA::is_nil (id_uniqueness_policy)); } else if (pol->policy_type() == PortableServer::ID_ASSIGNMENT_POLICY_ID) { id_assignment_policy = PortableServer::IdAssignmentPolicy::_narrow (pol); assert (!CORBA::is_nil (id_assignment_policy)); } else if (pol->policy_type() == PortableServer::IMPLICIT_ACTIVATION_POLICY_ID) { implicit_activation_policy = PortableServer::ImplicitActivationPolicy::_narrow (pol); assert (!CORBA::is_nil (implicit_activation_policy)); } else if (pol->policy_type() == PortableServer::SERVANT_RETENTION_POLICY_ID) { servant_retention_policy = PortableServer::ServantRetentionPolicy::_narrow (pol); assert (!CORBA::is_nil (servant_retention_policy)); } else if (pol->policy_type() == PortableServer::REQUEST_PROCESSING_POLICY_ID) { request_processing_policy = PortableServer::RequestProcessingPolicy::_narrow (pol); assert (!CORBA::is_nil (request_processing_policy)); } #ifdef USE_SL3 else if (pol->policy_type() == TransportSecurity::ObjectCredentialsPolicyType) { CORBA::ULong l = plist.length(); plist.length(l + 1); plist[l] = pol; } #endif // USE_SL3 else { // see orbos/99-12-02 p. 14-93 if (PInterceptor::PI::S_pfmap_.find(pol->policy_type()) != PInterceptor::PI::S_pfmap_.end()) { CORBA::ULong l = plist.length(); plist.length(l + 1); plist[l] = pol; } else { PortableServer::POA::InvalidPolicy ex; ex.index = i; mico_throw (ex); } } } if (plist.length() > 0) { for (CORBA::ULong i = 0; i < plist.length(); ++i) { CORBA::ULong j; for (j = 0; j < _policies.length(); ++j) { if (_policies[j]->policy_type() == plist[i]->policy_type()) { _policies[j] = CORBA::Policy::_duplicate (plist[i].in()); break; } } if (j == _policies.length()) { _policies.length (j+1); _policies[j] = CORBA::Policy::_duplicate (plist[i].in()); } } } /* * set default policies */ if (CORBA::is_nil (thread_policy)) { thread_policy = create_thread_policy (PortableServer::ORB_CTRL_MODEL); } if (CORBA::is_nil (lifespan_policy)) { lifespan_policy = create_lifespan_policy (PortableServer::TRANSIENT); } if (CORBA::is_nil (id_uniqueness_policy)) { id_uniqueness_policy = create_id_uniqueness_policy (PortableServer::UNIQUE_ID); } if (CORBA::is_nil (id_assignment_policy)) { id_assignment_policy = create_id_assignment_policy (PortableServer::SYSTEM_ID); } if (CORBA::is_nil (implicit_activation_policy)) { implicit_activation_policy = create_implicit_activation_policy (PortableServer::NO_IMPLICIT_ACTIVATION); } if (CORBA::is_nil (servant_retention_policy)) { servant_retention_policy = create_servant_retention_policy (PortableServer::RETAIN); } if (CORBA::is_nil (request_processing_policy)) { request_processing_policy = create_request_processing_policy (PortableServer::USE_ACTIVE_OBJECT_MAP_ONLY); } } void MICOPOA::POA_impl::register_child (const char * cname, POA_impl * thechild) { assert (children.find(cname) == children.end()); (void) PortableServer::POA::_duplicate (thechild); children[cname] = thechild; } void MICOPOA::POA_impl::unregister_child (const char * cname) { POAMap::iterator it = children.find (cname); assert (it != children.end()); POA_impl * thechild = (*it).second; children.erase (it); CORBA::release (thechild); } void MICOPOA::POA_impl::register_poa (const char * pname, POA_impl * thechild) { assert (AllPOAs.find(pname) == AllPOAs.end()); AllPOAs[pname] = thechild; } void MICOPOA::POA_impl::unregister_poa (const char * pname) { POAMap::iterator it = AllPOAs.find (pname); assert (it != AllPOAs.end()); AllPOAs.erase (it); } void MICOPOA::POA_impl::etherealize () { /* * Clean up the Active Object Map. If RETAIN and USE_SERVANT_MANAGER, * call etherealize() on the Servant Activator. */ PortableServer::ServantActivator_var sav; if (servant_retention_policy->value() == PortableServer::RETAIN && request_processing_policy->value() == PortableServer::USE_SERVANT_MANAGER) { sav = PortableServer::ServantActivator::_narrow (servant_manager); } { MICOMT::AutoLock l(ObjectActivationLock); while (!ActiveObjectMap.empty()) { ObjectMap::ObjectRecord * orec = ActiveObjectMap.pop (); //FIXME: we have make sure, there is no invocation on this orec anymore !! // better wait until it is finished // maybe, we should have a invocation_counter on the orec ? if (!CORBA::is_nil (sav)) { PortableServer::Servant serv = orec->serv; POAObjectReference * por = orec->por; orec->por = NULL; delete orec; CORBA::Boolean other = ActiveObjectMap.exists (serv); #ifdef HAVE_EXCEPTIONS try { #endif if (thread_policy->value() == PortableServer::SINGLE_THREAD_MODEL || thread_policy->value() == PortableServer::MAIN_THREAD_MODEL) { // not optimal but reliable solution // for all POAs with single-thread policy // we will lock global servant manager lock // for main-thread policy this solution is optimal // and right MICOMT::AutoLock t_lock(S_servant_manager_lock); sav->etherealize (por->get_id(), this, serv, TRUE, other); } else { sav->etherealize (por->get_id(), this, serv, TRUE, other); } #ifdef HAVE_EXCEPTIONS } catch (CORBA::SystemException_catch &) { // Exceptions are ignored } #endif delete por; } else { delete orec; } } } } /* * Constructor for child POAs. They are not registered with the ORB */ MICOPOA::POA_impl::POA_impl (const char * _name, PortableServer::POAManager_ptr _manager, const CORBA::PolicyList & policies, POA_impl * _parent, CORBA::ORB_ptr porb) : name (_name), parent(_parent), orb(porb), ObjectActivationLock(FALSE, MICOMT::Mutex::Recursive) { destructed = 0; unique_id = 0; set_policies (policies); ior_template_ = new CORBA::IOR(*porb->ior_template()); #ifdef USE_SL3 TransportSecurity::ObjectCredentialsPolicy_var ocp = TransportSecurity::ObjectCredentialsPolicy::_nil(); for (CORBA::ULong i = 0; i < policies.length(); i++) { if (policies[i]->policy_type() == TransportSecurity::ObjectCredentialsPolicyType) { ocp = TransportSecurity::ObjectCredentialsPolicy::_narrow(policies[i].in()); assert(!CORBA::is_nil(ocp)); break; } } if (!CORBA::is_nil(ocp)) { CORBA::IORProfile* tprof = NULL; TransportSecurity::OwnCredentialsList_var creds = ocp->creds_list(); for (CORBA::ULong i = 0; (tprof = ior_template_->get_profile(i)) != NULL; i++) { bool match = false; if (tprof->id() == CORBA::IORProfile::TAG_INTERNET_IOP) { MICO::IIOPProfile* iiop_prof = dynamic_cast(tprof); assert(iiop_prof != NULL); for (CORBA::ULong j = 0; j < creds->length(); j++) { TransportSecurity::CredentialsAcceptor_var acceptor = creds[j]->the_acceptor(); MICOSL3_SL3TCPIP::TCPIPAcceptor* tcpip_acceptor = dynamic_cast(acceptor.in()); if (tcpip_acceptor != NULL) { if ((*(tcpip_acceptor->bound_addr())) == (*(iiop_prof->addr())) ||(tcpip_acceptor->ior_addr() != NULL && (*(tcpip_acceptor->ior_addr())) == (*(iiop_prof->addr())))) { match = true; break; } } } } else if (tprof->id() == CORBA::IORProfile::TAG_SSL_INTERNET_IOP) { MICOSSL::SSLProfile* ssl_prof = dynamic_cast(tprof); assert(ssl_prof != NULL); for (CORBA::ULong j = 0; j < creds->length(); j++) { TransportSecurity::CredentialsAcceptor_var acceptor = creds[j]->the_acceptor(); MICOSL3_SL3TLS::TLSAcceptor* tls_acceptor = dynamic_cast(acceptor.in()); if (tls_acceptor != NULL) { if ((*(tls_acceptor->bound_addr())) == (*(ssl_prof->addr())) ||(tls_acceptor->ior_addr() != NULL && (*(tls_acceptor->ior_addr())) == (*(ssl_prof->addr())))) { match = true; break; } } } } else if (tprof->id() == CORBA::IORProfile::TAG_MULTIPLE_COMPONENTS) { // we do not want to remove multiple components profile match = true; } if (!match) { // the selected profile does not match OCP credentials // so we need to remove it ior_template_->del_profile(tprof); // we also need to decrease i! i--; } } } #endif // USE_SL3 /* * We keep one reference to ourselves */ (void) PortableServer::POA::_duplicate (this); /* * Use given POA Manager or create a new one (managers are a * dime a dozen, ask Dilbert) */ if (!CORBA::is_nil (_manager)) { manager = PortableServer::POAManager::_duplicate (_manager); } else { manager = new POAManager_impl (); } assert (!CORBA::is_nil (orb)); assert (parent); assert (!CORBA::is_nil (manager)); default_servant = NULL; servant_manager = PortableServer::ServantManager::_nil (); adapter_activator = PortableServer::AdapterActivator::_nil (); if (parent->fqn.length() > 0) { fqn = parent->fqn + "/"; } const char * nptr = name.c_str (); while (*nptr) { if (*nptr == '/' || *nptr == '\\') { fqn += '\\'; } fqn += *nptr++; } state = manager->get_state (); /* * Construction of the POA's unique name depends on the Lifespan Policy. * For a transient POA, a unique name is generated based on IP Address, * the Pid, a timestamp and a unique ID, so that any generated objref * becomes invalid as soon as the server terminates or the POA is * deactivated. * A persistent POA should have received a unique name via the * -OAImplName command line option. * * / /