// -*- C++ -*- // $Id$ #include "orbsvcs/PortableGroup/PG_PropertyManager.h" #include "orbsvcs/PortableGroup/PG_ObjectGroupManager.h" #include "orbsvcs/PortableGroup/PG_Property_Utils.h" #include "tao/ORB_Constants.h" #include "ace/SString.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL TAO_PG_PropertyManager::TAO_PG_PropertyManager ( TAO_PG_ObjectGroupManager & object_group_manager) : object_group_manager_ (object_group_manager), default_properties_ (), type_properties_ (), lock_ (), property_validator_ () { } void TAO_PG_PropertyManager::set_default_properties ( const PortableGroup::Properties & props) { // First verify that the "Factories" property is not in the // Properties sequence. According to the spec, it is not allowed to // be set as part of the default properties. PortableGroup::Name factories; factories.length (1); factories[0].id = CORBA::string_dup ("org.omg.PortableGroup.Factories"); CORBA::ULong len = props.length (); for (CORBA::ULong i = 0; i < len; ++i) { PortableGroup::Property property = props[i]; if (property.nam == factories) throw PortableGroup::InvalidProperty (property.nam, property.val); } this->property_validator_.validate_property (props); ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_); this->default_properties_ = props; } PortableGroup::Properties * TAO_PG_PropertyManager::get_default_properties () { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0); PortableGroup::Properties * props = 0; ACE_NEW_THROW_EX (props, PortableGroup::Properties (this->default_properties_), CORBA::NO_MEMORY ( CORBA::SystemException::_tao_minor_code ( TAO::VMCID, ENOMEM), CORBA::COMPLETED_NO)); return props; } void TAO_PG_PropertyManager::remove_default_properties ( const PortableGroup::Properties &props) { if (props.length () == 0) return; // @@ Throw CORBA::BAD_PARAM instead? ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_); this->remove_properties (props, this->default_properties_); } void TAO_PG_PropertyManager::set_type_properties ( const char * type_id, const PortableGroup::Properties & overrides) { this->property_validator_.validate_property (overrides); CORBA::ULong num_overrides = overrides.length (); if (num_overrides == 0) return; // Throw CORBA::BAD_PARAM exception instead? ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_); Type_Prop_Table::ENTRY * entry = 0; if (this->type_properties_.find (type_id, entry) != 0) throw CORBA::BAD_PARAM (); PortableGroup::Properties & props = entry->int_id_; props = overrides; } PortableGroup::Properties * TAO_PG_PropertyManager::get_type_properties ( const char * type_id) { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->lock_, 0); Type_Prop_Table::ENTRY * entry = 0; PortableGroup::Properties * type_properties = 0; if (this->type_properties_.find (type_id, entry) == 0) type_properties = &entry->int_id_; const CORBA::ULong def_props_len = this->default_properties_.length (); const CORBA::ULong type_props_len = (type_properties == 0 ? 0 : type_properties->length ()); const CORBA::ULong props_len = (def_props_len > type_props_len ? def_props_len : type_props_len); PortableGroup::Properties * tmp_properties = 0; ACE_NEW_THROW_EX (tmp_properties, PortableGroup::Properties (props_len), CORBA::NO_MEMORY ( CORBA::SystemException::_tao_minor_code ( TAO::VMCID, ENOMEM), CORBA::COMPLETED_NO)); PortableGroup::Properties_var properties = tmp_properties; // Set the length to the length of the largest of the two property // sequences. The idea is to keep the cost of the incremental // growth that may occur in TAO_PG::override_properties() to a // minimum. properties->length (props_len); *tmp_properties = this->default_properties_; if (type_properties != 0 && type_props_len > 0) TAO_PG::override_properties (*type_properties, *tmp_properties); return properties._retn (); } void TAO_PG_PropertyManager::remove_type_properties ( const char * type_id, const PortableGroup::Properties & props) { if (props.length () == 0) return; // @@ Throw CORBA::BAD_PARAM instead? ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_); Type_Prop_Table::ENTRY * entry = 0; if (this->type_properties_.find (type_id, entry) != 0) throw CORBA::BAD_PARAM (); PortableGroup::Properties & type_properties = entry->int_id_; this->remove_properties (props, type_properties); } void TAO_PG_PropertyManager::set_properties_dynamically ( PortableGroup::ObjectGroup_ptr /* object_group */, const PortableGroup::Properties & /* overrides */) { #if 0 // First verify that the "InitialNumberMembers" property is not in // the Properties sequence. According to the spec, it is not // allowed to be set as part of the default properties. PortableGroup::Name factories; factories.length (1); factories[0].id = CORBA::string_dup ("org.omg.PortableGroup.InitialNumberMembers"); CORBA::ULong len = props.length (); for (CORBA::ULong i = 0; i < len; ++i) { PortableGroup::Property property = props[i]; if (property.nam == factories) throw PortableGroup::InvalidProperty (property.nam, property.val); } this->property_validator_.validate_property (overrides); // @todo Set the properties in the object group map entry. #endif /* 0 */ throw CORBA::NO_IMPLEMENT (); } PortableGroup::Properties * TAO_PG_PropertyManager::get_properties ( PortableGroup::ObjectGroup_ptr object_group) { CORBA::ULong properties_len = 0; ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, property_map_guard, this->lock_, 0); // @@ Race condition here! PortableGroup::Properties_var dynamic_properties = this->object_group_manager_.get_properties (object_group); CORBA::ULong dyn_props_len = dynamic_properties->length (); if (dyn_props_len > properties_len) properties_len = dyn_props_len; CORBA::String_var type_id = this->object_group_manager_.type_id (object_group); CORBA::ULong type_props_len = 0; PortableGroup::Properties * type_properties = 0; Type_Prop_Table::ENTRY * type_entry = 0; if (this->type_properties_.find (type_id.in (), type_entry) == 0) { type_properties = &type_entry->int_id_; type_props_len = type_properties->length (); if (type_props_len > properties_len) properties_len = type_props_len; } CORBA::ULong def_props_len = this->default_properties_.length (); if (def_props_len > properties_len) properties_len = def_props_len; PortableGroup::Properties * tmp_properties = 0; ACE_NEW_THROW_EX (tmp_properties, PortableGroup::Properties (properties_len), CORBA::NO_MEMORY ( CORBA::SystemException::_tao_minor_code ( TAO::VMCID, ENOMEM), CORBA::COMPLETED_NO)); PortableGroup::Properties_var properties = tmp_properties; // Set the length to the length of the largest of the three property // sequences. The idea is to keep the cost of the incremental // growth that may occur in TAO_PG::override_properties() to a // minimum. properties->length (properties_len); // Start out with a copy of the default properties. *tmp_properties = this->default_properties_; // Override default properties with type-specific properties. if (type_properties != 0) TAO_PG::override_properties (*type_properties, *tmp_properties); // Now override with the dynamic (object group) properties. TAO_PG::override_properties (dynamic_properties.in (), *tmp_properties); return properties._retn (); } void TAO_PG_PropertyManager::remove_properties ( const PortableGroup::Properties & to_be_removed, PortableGroup::Properties &properties) { const CORBA::ULong num_removed = to_be_removed.length (); if (num_removed == 0) return; // @@ Throw CORBA::BAD_PARAM instead? const CORBA::ULong old_length = properties.length (); const CORBA::ULong new_length = old_length - num_removed; PortableGroup::Properties new_properties (new_length); new_properties.length (new_length); // @@ Slow O(n^2) operation. Switching to a faster container for // the default properties might be a good idea at some point in // the future. CORBA::ULong n = 0; for (CORBA::ULong i = 0; i < num_removed; ++i) { const CORBA::ULong old_n = n; const PortableGroup::Property &remove = to_be_removed[i]; for (CORBA::ULong j = 0; j < old_length; ++j) if (remove.nam != properties[j].nam) new_properties[n++] = properties[j]; // The property to be removed doesn't exist in the current list // of default properties. if (n == old_n) throw PortableGroup::InvalidProperty (remove.nam, remove.val); } // All properties were successfully removed, and the remaining ones // were placed in the "new_properties" variable. Now copy that // variable. properties = new_properties; } TAO_END_VERSIONED_NAMESPACE_DECL