//============================================================================= /** * @file CosPropertyService_i.cpp * * @author Alexander Babu Arulanthu */ //============================================================================= #include "orbsvcs/Log_Macros.h" #include "orbsvcs/Log_Macros.h" #include "orbsvcs/Property/CosPropertyService_i.h" #include "ace/ACE.h" #include "ace/OS_NS_string.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL // = Methods to deal with ACE_Hash_Map_Manager. CosProperty_Hash_Key::CosProperty_Hash_Key (void) { } CosProperty_Hash_Key::CosProperty_Hash_Key (const char * &name) : pname_ (CORBA::string_dup (name)) { } CosProperty_Hash_Key::CosProperty_Hash_Key (const CosPropertyService::PropertyName &name) : pname_ (CORBA::string_dup (name)) { } CosProperty_Hash_Key::CosProperty_Hash_Key (const CosProperty_Hash_Key &src) : pname_ (src.pname_) { } bool CosProperty_Hash_Key::operator == (const CosProperty_Hash_Key &hash_key) const { return (ACE_OS::strcmp (this->pname_, hash_key.pname_) == 0); } u_long CosProperty_Hash_Key::hash (void) const { u_long ret = ACE::hash_pjw (this->pname_); return ret; } CosProperty_Hash_Key::~CosProperty_Hash_Key (void) { } //====================================================================== CosProperty_Hash_Value::CosProperty_Hash_Value (void) { } CosProperty_Hash_Value::CosProperty_Hash_Value (const CORBA::Any &any, const CosPropertyService::PropertyModeType &mode) : pvalue_ (any), pmode_ (mode) { } CosProperty_Hash_Value::CosProperty_Hash_Value (const CosProperty_Hash_Value &src) : pvalue_ (src.pvalue_), pmode_ (src.pmode_) { } CosProperty_Hash_Value::~CosProperty_Hash_Value (void) { } //====================================================================== // Constructor. TAO_PropertySetFactory::TAO_PropertySetFactory (void) { } // Destructor. TAO_PropertySetFactory::~TAO_PropertySetFactory (void) { } // Returns a new TAO_PropertySet object. "The property set returned // will *not* have any initial properties." Keep sequence of things // new'ed and at the destructor of the factory delete all these New'ed // things. CosPropertyService::PropertySet_ptr TAO_PropertySetFactory::create_propertyset (void) { // New a TAO_PropertySet. TAO_PropertySet *new_set; ACE_NEW_RETURN (new_set, TAO_PropertySet, 0); // Successful, store this in the products sequence and return. CORBA::ULong cur_len = this->propertyset_products_.length (); this->propertyset_products_.length (cur_len + 1); this->propertyset_products_[cur_len] = new_set; return new_set->_this (); } // Allows a client to create a new TAO_PropertySet with specific // constraints. "All the properties will have *fixed-normal* modes". CosPropertyService::PropertySet_ptr TAO_PropertySetFactory::create_constrained_propertyset (const CosPropertyService::PropertyTypes &allowed_property_types, const CosPropertyService::Properties &allowed_properties) { TAO_PropertySet *new_set = 0; CosPropertyService::PropertySet_ptr propset_ptr = 0; try { // New a TAO_PropertySet using these constraints. ACE_NEW_RETURN (new_set, TAO_PropertySet (allowed_property_types, allowed_properties), 0); // Successful, store this in the products sequence. CORBA::ULong products_len = this->propertyset_products_.length (); this->propertyset_products_.length (products_len + 1); this->propertyset_products_[products_len] = new_set; // All done. propset_ptr = new_set->_this (); } catch (const CORBA::UserException& ) { // Release the memory. delete new_set; // Throw the exception. throw CosPropertyService::ConstraintNotSupported(); } catch (const CORBA::SystemException& ) { // Release memory. delete new_set; // Throw the exception. throw; } return propset_ptr; } // Allows a client to create a new TAO_PropertySet with specific // constraints. "All the properties will have *fixed-normal* modes". CosPropertyService::PropertySet_ptr TAO_PropertySetFactory::create_initial_propertyset (const CosPropertyService::Properties &initial_properties) { TAO_PropertySet *new_set = 0; CosPropertyService::PropertySet_ptr propset_ptr = 0; try { // New a TAO_PropertySet. ACE_NEW_RETURN (new_set, TAO_PropertySet (initial_properties), 0); // Successful, store this in the products sequence. CORBA::ULong products_len = this->propertyset_products_.length (); this->propertyset_products_.length (products_len + 1); this->propertyset_products_[products_len] = new_set; // All done. propset_ptr = new_set->_this (); } catch (const CosPropertyService::MultipleExceptions& ) { // Release memory. delete new_set; // Throw the exception. throw; } catch (const CORBA::SystemException& ) { // Release the memory. delete new_set; // Throw the exception. throw; } return propset_ptr; } // Destructor. TAO_PropertySetDefFactory::~TAO_PropertySetDefFactory (void) { // Release all the new'ed products. for (CORBA::ULong pi = 0; pi < this->propertysetdef_products_.length (); pi++) delete this->propertysetdef_products_[pi]; } //====================================================================== // Constrctor. TAO_PropertySetDefFactory::TAO_PropertySetDefFactory (void) { } // Returns a new TAO_PropertySetDef object. "The property setdef // returned will *not* have any initial properties." // Keep sequence of things new'ed and at the destructor of the factory // delete all these New'ed things. CosPropertyService::PropertySetDef_ptr TAO_PropertySetDefFactory::create_propertysetdef (void) { // New a TAO_PropertySetDef. TAO_PropertySetDef *new_set; ACE_NEW_RETURN (new_set, TAO_PropertySetDef, 0); // Successful, store this in the products sequence and return. CORBA::ULong cur_len = this->propertysetdef_products_.length (); this->propertysetdef_products_.length (cur_len + 1); this->propertysetdef_products_[cur_len] = new_set; CosPropertyService::PropertySetDef_ptr propsetdef_ptr = new_set->_this (); return propsetdef_ptr; } CosPropertyService::PropertySetDef_ptr TAO_PropertySetDefFactory::create_constrained_propertysetdef (const CosPropertyService::PropertyTypes &allowed_property_types, const CosPropertyService::PropertyDefs &allowed_property_defs) { TAO_PropertySetDef *new_set = 0; CosPropertyService::PropertySetDef_ptr propsetdef_ptr = 0; try { // New a TAO_PropertySetDef using these constraints. ACE_NEW_RETURN (new_set, TAO_PropertySetDef (allowed_property_types, allowed_property_defs), 0); // Successful, store this in the products sequence. CORBA::ULong products_len = this->propertysetdef_products_.length (); this->propertysetdef_products_.length (products_len + 1); this->propertysetdef_products_[products_len] = new_set; // All done. Return the pointer. propsetdef_ptr = new_set->_this (); } catch (const CORBA::UserException& ) { // Release the memory. delete new_set; // Throw the exception. throw CosPropertyService::ConstraintNotSupported(); } catch (const CORBA::SystemException& ) { // Release memory. delete new_set; // Throw the exception. throw; } return propsetdef_ptr; } // Allows the client to create a new TAO_PropertySetDef with specific // initital constraints. CosPropertyService::PropertySetDef_ptr TAO_PropertySetDefFactory::create_initial_propertysetdef (const CosPropertyService::PropertyDefs &initial_property_defs) { TAO_PropertySetDef *new_set = 0; CosPropertyService::PropertySetDef_ptr propsetdef_ptr = 0; try { // New a TAO_PropertySet using these lengths. ACE_NEW_RETURN (new_set, TAO_PropertySetDef (initial_property_defs), 0); // Successful, store this in the products sequence. CORBA::ULong products_len = this->propertysetdef_products_.length (); this->propertysetdef_products_.length (products_len + 1); this->propertysetdef_products_[products_len] = new_set; // All done. propsetdef_ptr = new_set->_this (); } catch (const CosPropertyService::MultipleExceptions& ) { // Release memory. delete new_set; // Throw the exception. throw; } catch (const CORBA::SystemException& ) { // Release the memory. delete new_set; // Throw the exception. throw; } return propsetdef_ptr; } //====================================================================== // Makes default sized hash_table_. All the sequences are set the max // length as 0. TAO_PropertySet::TAO_PropertySet (void) { } // Init values that the PropertySetFactory will want to specify. Write // the allowed properties in the Hash Table with *fixed-normal* mode. // @@ Need to check for duplicate properties and raise exceptions. TAO_PropertySet::TAO_PropertySet (const CosPropertyService::PropertyTypes allowed_property_types, const CosPropertyService::Properties allowed_properties) : allowed_property_types_ (allowed_property_types), allowed_property_names_ (allowed_properties.length ()) { // Set the length for the sequence, just to make sure. this->allowed_property_names_.length (allowed_properties.length ()); // Keep the allowed property names in the sequence.. for (CORBA::ULong ni = 0; ni < allowed_properties.length (); ni++) this->allowed_property_names_[ni] = allowed_properties[ni].property_name; // Define the allowed properties in the hash table. try { this->define_properties (allowed_properties); } catch (const CORBA::Exception& ex) { ex._tao_print_exception ("TAO_PropertySet-Constructor"); throw; } } // TAO_PropertySetDef's constructor needs this, for initializing the // allowed properties' sequence withe just the maximum length. TAO_PropertySet::TAO_PropertySet (const CosPropertyService::PropertyTypes allowed_property_types, const CORBA::ULong number_of_allowed_properties) : allowed_property_types_ (allowed_property_types), allowed_property_names_ (number_of_allowed_properties) { } // PropertySetFactory needs this constructor. Store all the initial // properies with *normal* modes. TAO_PropertySet::TAO_PropertySet (const CosPropertyService::Properties initial_properties) { // Define all the initial properties in the Property Set. All take // *normal* modes. try { this->define_properties (initial_properties); } catch (const CORBA::Exception& ex) { ex._tao_print_exception ("TAO_PropertySet-Constructor"); throw; } } // Destructor. All sequences will be deleted. TAO_PropertySet::~TAO_PropertySet (void) { } // Function to modify or add a property to the PropertySet: // Adds the name and the value to the set... Doesn't check for Typecode // overwriting, duplicate names, void names etc, yet. // @@ Uses Normal mode as the default mode of properties, We can // change this behavior based on the Initial set of allowed modes, if // there is anything like that set by the client. void TAO_PropertySet::define_property (const char *property_name, const CORBA::Any &property_value) { // Check the name's validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); CORBA::TypeCode_var arg_tc = property_value.type (); // Is this type allowed? if (is_type_allowed (arg_tc.in ()) != 1) throw CosPropertyService::UnsupportedTypeCode(); // Is this property allowed? if (is_property_allowed (property_name) != 1) throw CosPropertyService::UnsupportedProperty(); // Try to bind the property. Use normal mode. CosProperty_Hash_Key hash_key (property_name); CosProperty_Hash_Value hash_value (property_value, CosPropertyService::normal); COSPROPERTY_HASH_ENTRY *entry_ptr = 0; int ret = this->hash_table_.bind (hash_key, hash_value, entry_ptr); CORBA::TypeCode_var mapped_tc; switch (ret) { case 0: break; case 1: // Property already exists. // Is the pointer valid? if (entry_ptr == 0) throw CORBA::UNKNOWN (); mapped_tc = entry_ptr->int_id_.pvalue_.type (); { CORBA::Boolean const equal_tc = mapped_tc.in ()->equal (arg_tc.in ()); // If type is not the same, raise exception. if (!equal_tc) throw CosPropertyService::ConflictingProperty(); } // If mode is read only, raise exception. if ((entry_ptr->int_id_.pmode_ == CosPropertyService::read_only) || (entry_ptr->int_id_.pmode_ == CosPropertyService::fixed_readonly)) throw CosPropertyService::ReadOnlyProperty(); // Use the mode that is already there. hash_value.pmode_ = entry_ptr->int_id_.pmode_; // Everything is fine. Overwrite the value. if (this->hash_table_.rebind (hash_key, hash_value) != 1) { ORBSVCS_DEBUG ((LM_DEBUG, "TAO_PropertySet::Define Property failed\n")); throw CORBA::UNKNOWN (); } break; default: // Error. ret is -1. throw CORBA::UNKNOWN (); } return; } // Tells whether this type is allowed in this property set or no. CORBA::Boolean TAO_PropertySet::is_type_allowed (CORBA::TypeCode_ptr type) { // If the sequence is empty, no constraints. if (this->allowed_property_types_.length () == 0) return 1; // Check in the allowed_property_types sequence. CORBA::Boolean ret_val = 0; for (CORBA::ULong ti = 0; ti < this->allowed_property_types_.length (); ti++) { try { ret_val = this->allowed_property_types_[ti]->equal (type); if (ret_val == 1) return 1; } catch (const CORBA::Exception& ex) { ex._tao_print_exception ("TAO_PropertySet::is_type_allowed failed"); return ret_val; } } // Type not found. return ret_val; } // Tells whether this property is allowed in this property or no. CORBA::Boolean TAO_PropertySet::is_property_allowed (const char* property_name) { // If the sequence is empty, no constraints. if (this->allowed_property_names_.length() == 0) return 1; // Check in the allowed_property_names. for (CORBA::ULong ni = 0; ni < this->allowed_property_names_.length (); ni++) if (ACE_OS::strcmp ((const char *) this->allowed_property_names_[ni], property_name) == 0) return 1; // Name not found in the sequence. return 0; } // Defining a sequence of properties // // Check for overwriting, duplicate names, void names etc and raise // appropriate exceptions. void TAO_PropertySet::define_properties (const CosPropertyService::Properties &nproperties) { // Get the length. CORBA::ULong sequence_length = nproperties.length (); // Define multiple exceptions object. CosPropertyService::MultipleExceptions multi_ex; for (CORBA::ULong pi = 0; pi < sequence_length; pi++) { try { // Define this property. this->define_property (nproperties [pi].property_name.in (), nproperties [pi].property_value); } catch (const CosPropertyService::InvalidPropertyName& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::invalid_property_name; multi_ex.exceptions[len].failing_property_name = nproperties[pi].property_name; } catch (const CosPropertyService::ConflictingProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::conflicting_property; multi_ex.exceptions[len].failing_property_name = nproperties[pi].property_name; } catch (const CosPropertyService::ReadOnlyProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::read_only_property; multi_ex.exceptions[len].failing_property_name = nproperties[pi].property_name; } catch (const CosPropertyService::UnsupportedTypeCode& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_type_code; multi_ex.exceptions[len].failing_property_name = nproperties[pi].property_name; } catch (const CosPropertyService::UnsupportedProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_property; multi_ex.exceptions[len].failing_property_name = nproperties[pi].property_name; } catch (const CORBA::SystemException& ) { throw; } } // Raise the multi exception if needed. if (multi_ex.exceptions.length () > 0) throw CosPropertyService::MultipleExceptions (multi_ex); } // Returns the current number of properties associated with this // PropertySet. CORBA::ULong TAO_PropertySet::get_number_of_properties (void) { return static_cast (this->hash_table_.current_size ()); } // Returns all of the property names currently defined in the // PropertySet. If the PropertySet contains more than // property names, then the remaining property names are put into the // PropertyNamesIterator. void TAO_PropertySet::get_all_property_names (CORBA::ULong how_many, CosPropertyService::PropertyNames_out property_names, CosPropertyService::PropertyNamesIterator_out rest) { // Allocating storage is a must. ACE_NEW (property_names, CosPropertyService::PropertyNames); CORBA::ULong num_of_properties = this->get_number_of_properties (); if (num_of_properties == 0) // Nothing to do. return; // Set the length of the property_names appropriately. CORBA::ULong sequence_length = 0; if (how_many > 0) { if (how_many >= num_of_properties) sequence_length = num_of_properties; else sequence_length = how_many; property_names->length (sequence_length); } // Iterate thru names and put them in the property_names. COSPROPERTY_HASH_ENTRY *entry_ptr; COSPROPERTY_HASH_ITERATOR iterator (this->hash_table_); for (CORBA::ULong ni = 0; ni < sequence_length; ni++, iterator.advance ()) if (iterator.next (entry_ptr) != 0) property_names [ni] = CORBA::string_dup (entry_ptr->ext_id_.pname_.in ()); // If there are some more properties, put them in the // iterator. How?? Make a new PropertySet and use that to create // propertyNames Iterator. if (num_of_properties > how_many) { TAO_PropertySet *property_set; ACE_NEW (property_set, TAO_PropertySet); for (CORBA::ULong i = how_many; i < num_of_properties; i++, iterator.advance ()) if (iterator.next (entry_ptr) != 0) if (property_set->hash_table_.bind (entry_ptr->ext_id_, entry_ptr->int_id_) < 0) ORBSVCS_DEBUG ((LM_DEBUG, "Error:TAO_PropertySet::get_all_property_names\n")); // Make the NamesIterator out of this TAO_PropertySet. TAO_PropertyNamesIterator *names_iterator; ACE_NEW (names_iterator, TAO_PropertyNamesIterator (*property_set)); // Init the out parameter. // Get the Interface ptr. CosPropertyService::PropertyNamesIterator_ptr iterator_ptr = names_iterator->_this (); // POA stuff todo here, since we have method in the // interface. // Give ownership of this servant to the POA. names_iterator->_remove_ref (); // Init the out parameter. rest = iterator_ptr; } } // Returns the value of a property in the PropertySet. CORBA::Any * TAO_PropertySet::get_property_value (const char *property_name) { // Check the name's validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); // Get the value out of the hash table. CosProperty_Hash_Key hash_key (property_name); CosProperty_Hash_Value hash_value; if (this->hash_table_.find (hash_key, hash_value) != 0) throw CosPropertyService::PropertyNotFound(); // Return the any value got. CORBA::Any *any_ptr =0; ACE_NEW_RETURN (any_ptr, CORBA::Any (hash_value.pvalue_), 0); return any_ptr; } // Returns the values of the properties listed in property_names. When // the boolean return value is true, the Properties parameter contains // valid values for all requested property names. If false, then all // properties with a value of type tk_void may have failed due to // or . CORBA::Boolean TAO_PropertySet::get_properties (const CosPropertyService::PropertyNames &property_names, CosPropertyService::Properties_out nproperties) { // Allocate memory for the out parameter. ACE_NEW_RETURN (nproperties, CosPropertyService::Properties, 0); // Validate the length. CORBA::ULong n = property_names.length (); if (n == 0) return 0; // Set the length for the out parameter. nproperties->length (n); // Get values for all the names. CORBA::Any_var any_ptr = 0; CORBA::Boolean ret_val = 1; for (CORBA::ULong i = 0; i < n; i++) { any_ptr = get_property_value (property_names [i]); if (any_ptr != 0) { // Property is found. nproperties [i].property_name = property_names [i]; nproperties [i].property_value = *any_ptr; } else { // Invalid name. Ret value is False. ret_val = 0; // Assign void type to this name in the out parameter. nproperties [i].property_name = property_names [i]; // Make an any value with tk_void type. CORBA::Any any; any._tao_set_typecode (CORBA::_tc_void); nproperties [i].property_value = any; } } return ret_val; } void TAO_PropertySet::get_all_properties (CORBA::ULong how_many, CosPropertyService::Properties_out nproperties, CosPropertyService::PropertiesIterator_out rest) { // Allocate memory for the out parameter. ACE_NEW (nproperties, CosPropertyService::Properties); // Validate the length. CORBA::ULong num_of_properties = this->get_number_of_properties (); if (num_of_properties == 0) return; // Set the length for the nproperties if how_many > 0. CORBA::ULong sequence_length = 0; if (how_many > 0) { if (how_many >= num_of_properties) sequence_length = num_of_properties; else sequence_length = how_many; nproperties->length (sequence_length); } // Prepare an iterator and iterate through the PropertySet. Retrive // the values. COSPROPERTY_HASH_ITERATOR iterator (this->hash_table_); COSPROPERTY_HASH_ENTRY *entry_ptr = 0; for (CORBA::ULong i = 0; i < sequence_length; i++, iterator.advance ()) if (iterator.next (entry_ptr) != 0) { nproperties[i].property_name = CORBA::string_dup (entry_ptr->ext_id_.pname_.in ()); nproperties[i].property_value = entry_ptr->int_id_.pvalue_; } // If there are more properties, put them in the . // Make a new and use that to create an Properties // iterator. put that in a iterator and assign that to the out // paramerter. if (num_of_properties > how_many) { TAO_PropertySet *prop_set; ACE_NEW (prop_set, TAO_PropertySet); for (CORBA::ULong i = sequence_length; i < num_of_properties; i++, iterator.advance ()) { if (iterator.next (entry_ptr) != 0 && prop_set->hash_table_.bind (entry_ptr->ext_id_, entry_ptr->int_id_) < 0) ORBSVCS_DEBUG ((LM_DEBUG, "Error:TAO_PropertySet::get_all_properties\n")); } // Make the iterator out of the new TAO_Propset. TAO_PropertiesIterator *iterator = 0; ACE_NEW (iterator, TAO_PropertiesIterator (*prop_set)); // Init the out parameter. // Get the interface ptr. CosPropertyService::PropertiesIterator_ptr iterator_ptr = iterator->_this (); // POA stuff todo here, since we have method in the // interface. // Give ownership of this servant to the POA. iterator->_remove_ref (); // Init the out parameter. rest = iterator_ptr; } } // Deletes the specified property if it exists from a PropertySet. void TAO_PropertySet::delete_property (const char *property_name) { // Check the name's validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); // Get the entry from the Hash Table. CosProperty_Hash_Key hash_key (property_name); COSPROPERTY_HASH_ENTRY *entry_ptr = 0; if (this->hash_table_.find (hash_key, entry_ptr) == -1) throw CosPropertyService::PropertyNotFound(); // If property is fixed, then raise exception. if ((entry_ptr->int_id_.pmode_ == CosPropertyService::fixed_normal) || (entry_ptr->int_id_.pmode_ == CosPropertyService::fixed_readonly)) throw CosPropertyService::FixedProperty(); // Unbind this property. if (this->hash_table_.unbind (entry_ptr) != 0) { throw CORBA::UNKNOWN (); } return; } // Deletes the properties defined in the property_names // parameter. This is a batch operation that returns the // MultipleExceptions exception if any delete failed. void TAO_PropertySet::delete_properties (const CosPropertyService::PropertyNames &property_names) { // Get the length. CORBA::ULong sequence_length = property_names.length (); // Declare multiple exceptions' object. CosPropertyService::MultipleExceptions multi_ex; for (CORBA::ULong pi = 0; pi < sequence_length; pi++) { try { // Delete this property. this->delete_property (property_names[pi]); } catch (const CosPropertyService::InvalidPropertyName& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::invalid_property_name; multi_ex.exceptions[len].failing_property_name = property_names[pi]; } catch (const CosPropertyService::PropertyNotFound& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::property_not_found; multi_ex.exceptions[len].failing_property_name = property_names[pi]; } catch (const CosPropertyService::FixedProperty& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::fixed_property; multi_ex.exceptions[len].failing_property_name = property_names[pi]; } catch (const CORBA::SystemException& ) { // We cant afford to get this. Throw this. throw; } } // Raise the multiple exceptions if there are any. if (multi_ex.exceptions.length () > 0) throw CosPropertyService::MultipleExceptions (multi_ex); } // Delete all the properties in the current ProperySet : Delete the // properties one by one. CORBA::Boolean TAO_PropertySet::delete_all_properties (void) { // Get all the property names in a names' sequence. CosPropertyService::PropertyNames *names_ptr = 0; CosPropertyService::PropertyNames_out names_out (names_ptr); CosPropertyService::PropertyNames_var names; CosPropertyService::PropertyNamesIterator *iter_ptr = 0; CosPropertyService::PropertyNamesIterator_out iter_out (iter_ptr); CosPropertyService::PropertyNamesIterator_var iter; CORBA::ULong size = this->get_number_of_properties (); this->get_all_property_names (size, names_out, iter_out); // Get the out values on to the var varibles. names = names_out.ptr (); iter = iter_out.ptr (); // Delete all these properties. this->delete_properties (names.in ()); // All properties deleted. return 1; } // Returns TRUE if the property is defined in the PropertySet. CORBA::Boolean TAO_PropertySet::is_property_defined (const char *property_name) { CosProperty_Hash_Key hash_key (property_name); if (this->hash_table_.find (hash_key) == 0) return 1; else return 0; } void TAO_PropertySet::operator= (const TAO_PropertySet &) { // Empty. } //====================================================================== // Makes default sized hash_table_. TAO_PropertySetDef::TAO_PropertySetDef (void) { } // Constructor that the factory uses. TAO_PropertySetDef::TAO_PropertySetDef (const CosPropertyService::PropertyTypes allowed_property_types, const CosPropertyService::PropertyDefs allowed_property_defs) : TAO_PropertySet(allowed_property_types, allowed_property_defs.length ()) { // Set the length of the allowed property names. this->allowed_property_names_.length (allowed_property_defs.length ()); // Copy the allowed properties' names to the sequence. for (CORBA::ULong ni = 0; ni < allowed_property_defs.length (); ni++) this->allowed_property_names_[ni] = allowed_property_defs[ni].property_name; // Define the allowed properties in the hash table. try { this->define_properties_with_modes (allowed_property_defs); } catch (const CORBA::Exception&) { throw; } } // Constructor that the factory uses. TAO_PropertySetDef::TAO_PropertySetDef (const CosPropertyService::PropertyDefs initial_property_defs) { this->define_properties_with_modes (initial_property_defs); } // Destructor. TAO_PropertySetDef::~TAO_PropertySetDef (void) { } // Return the sequence that is there in side. void TAO_PropertySetDef::get_allowed_property_types (CosPropertyService::PropertyTypes_out property_types) { // Copy contents of the sequence. ACE_NEW (property_types, CosPropertyService::PropertyTypes (this->allowed_property_types_)); } void TAO_PropertySetDef::get_allowed_properties (CosPropertyService::PropertyDefs_out property_defs) { // We have all the names, get the values and the modes from the Hash // Table and return. // Allocate memory. ACE_NEW (property_defs, CosPropertyService::PropertyDefs (this->allowed_property_names_.length ())); // Get the modes and property values for all these property // names. Some may not be there in the Hash Table, probably got // deleted because of their modes were not safe. // @@ TO DO. } // Check for name's validity. If name not there define it. If it is // there and if type is equal and if mode allows define it else raise // exception. void TAO_PropertySetDef::define_property_with_mode (const char *property_name, const CORBA::Any &property_value, CosPropertyService::PropertyModeType property_mode) { // Check the names validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); // Is this type allowed? if (is_type_allowed (property_value.type ()) != 1) throw CosPropertyService::UnsupportedTypeCode(); // Is this property allowed? if (is_property_allowed (property_name) != 1) throw CosPropertyService::UnsupportedProperty(); // Is this a valid mode. if (property_mode == CosPropertyService::undefined) throw CosPropertyService::UnsupportedMode(); // Try to bind the Property. CosProperty_Hash_Key hash_key (property_name); CosProperty_Hash_Value hash_value (property_value, property_mode); COSPROPERTY_HASH_ENTRY *entry_ptr; int ret = this->hash_table_.bind (hash_key, hash_value, entry_ptr); //CosProperty_Hash_Value old_value; //CosProperty_Hash_Key old_key; switch (ret) { case 0: break; case 1: // Property name exists. // Is the pointer valid. if (entry_ptr == 0) throw CORBA::UNKNOWN (); // If type is not the same, raise exception. if (entry_ptr->int_id_.pvalue_.type () != property_value.type ()) throw CosPropertyService::ConflictingProperty(); // If mode is read only, raise exception. if ((entry_ptr->int_id_.pmode_ == CosPropertyService::read_only) || (entry_ptr->int_id_.pmode_ == CosPropertyService::fixed_readonly)) throw CosPropertyService::ReadOnlyProperty(); // If current mode is fixed_normal, but the new mode is not // fixed, reject it. if ((entry_ptr->int_id_.pmode_ == CosPropertyService::fixed_normal) && (property_mode < CosPropertyService::fixed_normal)) throw CosPropertyService::UnsupportedMode(); // Everything is fine. Overwrite the value. if (this->hash_table_.rebind (hash_key, hash_value) > 0) { break; } default: // Error. ret is -1 or rebind returned other than 1. throw CORBA::UNKNOWN (); } return; } // Define one by one. If any excceptions raised, build // MultipleExceptions sequence and raise that. void TAO_PropertySetDef::define_properties_with_modes (const CosPropertyService::PropertyDefs &property_defs) { // Get the length. CORBA::ULong sequence_length = property_defs.length (); // Define multiple exceptions object. CosPropertyService::MultipleExceptions multi_ex; // Try defining the propdefs one by one. for (CORBA::ULong i = 0; i < sequence_length; i++) { try { // Define the property. this->define_property_with_mode (property_defs[i].property_name, property_defs[i].property_value, property_defs[i].property_mode); } catch (const CosPropertyService::InvalidPropertyName& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::invalid_property_name; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CosPropertyService::ConflictingProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::conflicting_property; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CosPropertyService::ReadOnlyProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::read_only_property; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CosPropertyService::UnsupportedTypeCode& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_type_code; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CosPropertyService::UnsupportedProperty& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_property; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CosPropertyService::UnsupportedMode& ) { CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_mode; multi_ex.exceptions[len].failing_property_name = property_defs[i].property_name; } catch (const CORBA::SystemException& ) { throw; } } // Raise the multi exception if needed. if (multi_ex.exceptions.length () > 0) throw CosPropertyService::MultipleExceptions (multi_ex); } // Get the mode of a property. Raises InvalidpropertyName, // PropertyNotFound exceptions. CosPropertyService::PropertyModeType TAO_PropertySetDef::get_property_mode (const char *property_name) { // Check for the name's validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); // Find the property in the hash table. CosProperty_Hash_Key hash_key (property_name); CosProperty_Hash_Value hash_value; int ret = this->hash_table_.find (hash_key, hash_value); switch (ret) { case 0: // Property found. return hash_value.pmode_; default: // Error or property is not found. throw CosPropertyService::PropertyNotFound(); } } // Batch operation for getting the property. Invoke get_property_mode // for each name. // Return value False indicates that properties with *undefined* modes // have failed due to PropertyNotFound or InvalidPropertyName exception. // Returning False in case of *Nothing to retun* or New is // failing. The caller has to check the out parameter whether it is // Nil or no, before doing something with it. CORBA::Boolean TAO_PropertySetDef::get_property_modes (const CosPropertyService::PropertyNames &property_names, CosPropertyService::PropertyModes_out property_modes) { // Allocate memory for the out parameter. ACE_NEW_RETURN (property_modes, CosPropertyService::PropertyModes, 1); // Validate the length of names sequence. CORBA::ULong sequence_length = property_names.length (); if (sequence_length == 0) return 1; // Set the length of the sequence. property_modes->length (sequence_length); // Intialize thre return value. CORBA::Boolean ret = 1; // Invoking get_property_mode for each name. CosPropertyService::PropertyModeType mode; for (CORBA::ULong i = 0; i < sequence_length; i++) { try { // Invoke get_property_mode for this name. mode = this->get_property_mode (property_names[i]); // Store the mode in the out sequence. property_modes[i].property_name = property_names[i]; property_modes[i].property_mode = mode; } catch (const CORBA::Exception&) { // Return value becomes false. ret = 1; // Assign this property to the out parameter with undefined // mode. property_modes[i].property_name = property_names[i]; property_modes[i].property_mode = CosPropertyService::undefined; } } return ret; } // Changing the mode of the property. // "Normal" to anything is possible. // "Readonly" mode to "Fixed-Readonly" is possible. Others not possible. // "Fixed-Normal" to "Fixed-Readonly" is possible. Other things are impossible. // "Fixed-Readonly" to anything is *not* possible. void TAO_PropertySetDef::set_property_mode (const char *property_name, CosPropertyService::PropertyModeType property_mode) { // Check the names validity. if (property_name == 0) throw CosPropertyService::InvalidPropertyName(); // Trying to set to undefined mode is not allowed. if (property_mode == CosPropertyService::undefined) throw CosPropertyService::UnsupportedMode(); // Find the property from the Hash Table. CosProperty_Hash_Key hash_key (property_name); CosProperty_Hash_Value hash_value; int ret = this->hash_table_.find (hash_key, hash_value); //CosProperty_Hash_Value old_value; //CosProperty_Hash_Key old_key; // Act acc to the ret value. switch (ret) { case 0: // Property found. // If the new mode is the same as the old one, nothing to do. if (hash_value.pmode_ == property_mode) return; // Check for legality of the mode change. switch (hash_value.pmode_) { case CosPropertyService::normal: // Set the new mode and update the hash table. hash_value.pmode_ = property_mode; if (this->hash_table_.rebind (hash_key, hash_value) != 1) // Return values 0 and -1 are not possible. throw CORBA::UNKNOWN (); break; case CosPropertyService::read_only: // Read_only to fixed read only alone is possible. if (property_mode != CosPropertyService::fixed_readonly) throw CosPropertyService::UnsupportedMode(); else { // Change the mode and update hash table. hash_value.pmode_ = property_mode; if (this->hash_table_.rebind (hash_key, hash_value) != 1) // Return values 0 and -1 are not possible. throw CORBA::UNKNOWN (); } break; case CosPropertyService::fixed_normal: // Fixed_normal to fixed_readonly alone is possible. if (property_mode != CosPropertyService::fixed_readonly) throw CosPropertyService::UnsupportedMode(); else { // Change the mode and update the hash table. hash_value.pmode_ = property_mode; if (this->hash_table_.rebind (hash_key, hash_value) != 1) // Return values 0 and -1 are not possible. throw CORBA::UNKNOWN (); } break; default: // Fixed_readonly to any mode is not possible. throw CosPropertyService::UnsupportedMode(); } break; case -1: default: // Error or property not found in the Hash Table. throw CosPropertyService::PropertyNotFound(); } } // Batch operation for setting the property. Raises // MultipleExceptions. Set the properties one by one, catch // exceptions if any and keep them as in the multiple exceptions // sequence and return. void TAO_PropertySetDef::set_property_modes (const CosPropertyService::PropertyModes &property_modes) { // Get the length of the sequence. CORBA::ULong sequence_length = property_modes.length (); // Multiple exception variable to keep track of exceptions. CosPropertyService::MultipleExceptions multi_ex; // Set modes one by one. for (CORBA::ULong i = 0; i < sequence_length; i++) { try { this->set_property_mode (property_modes[i].property_name, property_modes[i].property_mode); } catch (const CosPropertyService::PropertyNotFound& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::property_not_found; multi_ex.exceptions[len].failing_property_name = property_modes[i].property_name; } catch (const CosPropertyService::InvalidPropertyName& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::invalid_property_name; multi_ex.exceptions[len].failing_property_name = property_modes[i].property_name; } catch (const CosPropertyService::UnsupportedMode& ) { // Put this exception in the multiple exception. CORBA::ULong len = multi_ex.exceptions.length (); multi_ex.exceptions.length (len + 1); multi_ex.exceptions[len].reason = CosPropertyService::unsupported_mode; multi_ex.exceptions[len].failing_property_name = property_modes[i].property_name; } catch (const CORBA::SystemException& ) { throw; } } // Raise the multi_ex, if needed. if (multi_ex.exceptions.length () > 0) throw CosPropertyService::MultipleExceptions (multi_ex); } //====================================================================== // Constructor. Construct the iterator from the PropertySet object. TAO_PropertyNamesIterator::TAO_PropertyNamesIterator (TAO_PropertySet &property_set) : iterator_ (property_set.hash_table_) { } // Destructor. TAO_PropertyNamesIterator::~TAO_PropertyNamesIterator (void) { } // Resets the position in an iterator to the first property name, if // one exists. void TAO_PropertyNamesIterator::reset (void) { this->iterator_ = this->iterator_.map ().begin (); } // The next_one operation returns true if an item exists at the // current position in the iterator with an output parameter of a // property name. A return of false signifies no more items in the // iterator. CORBA::Boolean TAO_PropertyNamesIterator::next_one (CORBA::String_out property_name) { COSPROPERTY_HASH_ENTRY *entry_ptr; if (this->iterator_.next (entry_ptr) != 0) { property_name = CORBA::string_dup (entry_ptr->ext_id_.pname_.in ()); this->iterator_.advance (); return 1; } else return 0; } CORBA::Boolean TAO_PropertyNamesIterator::next_n (CORBA::ULong how_many, CosPropertyService::PropertyNames_out property_names) { // Allocate memory for the out parameter. ACE_NEW_RETURN (property_names, CosPropertyService::PropertyNames, 0); COSPROPERTY_HASH_ENTRY *entry_ptr = 0; if (this->iterator_.next (entry_ptr) == 0 || how_many == 0) return 0; CORBA::ULong size = static_cast (this->iterator_.map ().current_size ()); CORBA::ULong len = 0; if (how_many <= size) len = how_many; else len = size; property_names->length (len); for (CORBA::ULong ni = 0; ni < property_names->length (); ni++, this->iterator_.advance ()) if (this->iterator_.next (entry_ptr) != 0) property_names [ni] = CORBA::string_dup (entry_ptr->ext_id_.pname_.in ()); return 1; } void TAO_PropertyNamesIterator::destroy (void) { // Remove self from POA. Because of reference counting, the POA // will automatically delete the servant when all pending requests // on this servant are complete. PortableServer::POA_var poa = this->_default_POA (); PortableServer::ObjectId_var id = poa->servant_to_id (this); poa->deactivate_object (id.in ()); } //====================================================================== TAO_PropertiesIterator::TAO_PropertiesIterator (TAO_PropertySet &property_set) : iterator_ (property_set.hash_table_) { } TAO_PropertiesIterator::~TAO_PropertiesIterator (void) { } void TAO_PropertiesIterator::reset (void) { this->iterator_ = this->iterator_.map ().begin (); } CORBA::Boolean TAO_PropertiesIterator::next_one (CosPropertyService::Property_out aproperty) { COSPROPERTY_HASH_ENTRY *entry_ptr; if (this->iterator_.next (entry_ptr) != 0) { aproperty = new CosPropertyService::Property; aproperty->property_name = entry_ptr->ext_id_.pname_; aproperty->property_value = entry_ptr->int_id_.pvalue_; this->iterator_.advance (); return 1; } else { aproperty = new CosPropertyService::Property; return 0; } } CORBA::Boolean TAO_PropertiesIterator::next_n (CORBA::ULong how_many, CosPropertyService::Properties_out nproperties) { // Allocate memory for the out parameter. ACE_NEW_RETURN (nproperties, CosPropertyService::Properties, 0); COSPROPERTY_HASH_ENTRY *entry_ptr = 0; if (this->iterator_.next (entry_ptr) == 0 || how_many == 0) return 0; CORBA::ULong size = static_cast (this->iterator_.map ().current_size ()); CORBA::ULong len; if (how_many <= size) len = how_many; else len = size; nproperties->length (len); for (CORBA::ULong ni = 0; ni < nproperties->length (); ni++, this->iterator_.advance ()) { if (this->iterator_.next (entry_ptr) != 0) { nproperties [ni].property_name = entry_ptr->ext_id_.pname_; nproperties [ni].property_value = entry_ptr->int_id_.pvalue_; } else break; } return 1; } void TAO_PropertiesIterator::destroy (void) { // Remove self from POA. Because of reference counting, the POA // will automatically delete the servant when all pending requests // on this servant are complete. PortableServer::POA_var poa = this->_default_POA (); PortableServer::ObjectId_var id = poa->servant_to_id (this); poa->deactivate_object (id.in ()); } TAO_END_VERSIONED_NAMESPACE_DECL