// $Id$ #include "orbsvcs/Trader/Trader_Utils.h" #include "ace/OS_NS_string.h" ACE_RCSID(Trader, Trader_Utils, "$Id$") TAO_BEGIN_VERSIONED_NAMESPACE_DECL bool operator== (CORBA::String_var const & lhs, CORBA::String_var const & rhs) { return (ACE_OS::strcmp (lhs.in (), rhs.in ()) == 0); } TAO_Policy_Creator::TAO_Policy_Creator (int num_policies) : policies_ (num_policies), num_policies_ (0) { for (int i = 0; i < TAO_Policies::REQUEST_ID + 1; i++) this->poltable_[i] = -1; } void TAO_Policy_Creator::search_card (CORBA::ULong scard) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::SEARCH_CARD); policy.value <<= scard; } void TAO_Policy_Creator::match_card (CORBA::ULong mcard) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::MATCH_CARD); policy.value <<= mcard; } void TAO_Policy_Creator::return_card (CORBA::ULong rcard) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::RETURN_CARD); policy.value <<= rcard; } void TAO_Policy_Creator::use_modifiable_properties (CORBA::Boolean mod_props) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::USE_MODIFIABLE_PROPERTIES); policy.value <<= CORBA::Any::from_boolean (mod_props); } void TAO_Policy_Creator::use_dynamic_properties (CORBA::Boolean dyn_props) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::USE_DYNAMIC_PROPERTIES); policy.value <<= CORBA::Any::from_boolean (dyn_props); } void TAO_Policy_Creator::use_proxy_offers (CORBA::Boolean prox_offs) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::USE_PROXY_OFFERS); policy.value <<= CORBA::Any::from_boolean (prox_offs); } void TAO_Policy_Creator::starting_trader (const CosTrading::TraderName& name) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::STARTING_TRADER); policy.value <<= name; } void TAO_Policy_Creator::starting_trader (CosTrading::TraderName* name) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::STARTING_TRADER); policy.value <<= name; } void TAO_Policy_Creator:: link_follow_rule (CosTrading::FollowOption follow_option) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::LINK_FOLLOW_RULE); policy.value <<= follow_option; } void TAO_Policy_Creator::hop_count (CORBA::ULong hop_count) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::HOP_COUNT); policy.value <<= hop_count; } void TAO_Policy_Creator::exact_type_match (CORBA::Boolean exact_type) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::EXACT_TYPE_MATCH); policy.value <<= CORBA::Any::from_boolean (exact_type); } void TAO_Policy_Creator::request_id (const CosTrading::Admin::OctetSeq& request_id) { CosTrading::Policy& policy = this->fetch_next_policy (TAO_Policies::REQUEST_ID); policy.value <<= request_id; } TAO_Policy_Creator::operator const CosTrading::PolicySeq& (void) const { return this->policies_; } const CosTrading::PolicySeq& TAO_Policy_Creator::policy_seq (void) const { return this->policies_; } CosTrading::Policy& TAO_Policy_Creator::fetch_next_policy (TAO_Policies::POLICY_TYPE pol_type) { CORBA::ULong index = 0; if (this->poltable_[pol_type] == -1) { // Expand the policy sequence, and copy in the policy name into // the new element. CORBA::ULong length = this->policies_.length (); this->num_policies_++; if (length < this->num_policies_) this->policies_.length (this->num_policies_); index = this->num_policies_ - 1; // Ensure the starting trader policy gets the first slot. if (pol_type != TAO_Policies::STARTING_TRADER || index == 0) { this->policies_[index].name = TAO_Policies::POLICY_NAMES[pol_type]; this->poltable_[pol_type] = index; } else { // Copy the element in the first slot to the newly // allocated slot. TAO_Policies::POLICY_TYPE occupying_policy = TAO_Policies::STARTING_TRADER; for (CORBA::ULong i = 0; i < this->num_policies_ - 1; i++) { if (this->poltable_[i] == 0) { occupying_policy = static_cast (i); break; } } this->poltable_[occupying_policy] = index; this->poltable_[TAO_Policies::STARTING_TRADER] = 0; this->policies_[index].name = TAO_Policies::POLICY_NAMES[occupying_policy]; this->policies_[index].value = this->policies_[0].value; this->policies_[0].name = TAO_Policies::POLICY_NAMES[TAO_Policies::STARTING_TRADER]; index = 0; } } else index = this->poltable_[pol_type]; return this->policies_[index]; } // Constructor TAO_Property_Evaluator:: TAO_Property_Evaluator(const CosTrading::PropertySeq& props, CORBA::Boolean supports_dp) : props_ (props), supports_dp_ (supports_dp), dp_cache_ (new CORBA::Any*[props.length ()]) { if (this->dp_cache_ != 0) { for (CORBA::ULong i = 0; i < this->props_.length (); i++) this->dp_cache_[i] = 0; } } TAO_Property_Evaluator:: TAO_Property_Evaluator(CosTrading::Offer& offer, CORBA::Boolean supports_dp) : props_ (offer.properties), supports_dp_ (supports_dp), dp_cache_ (new CORBA::Any*[offer.properties.length ()]) { if (this->dp_cache_ != 0) for (CORBA::ULong i = 0; i < this->props_.length (); i++) this->dp_cache_[i] = 0; } TAO_Property_Evaluator::~TAO_Property_Evaluator (void) { // Clean up the results of any dynamic properties. for (CORBA::ULong i = 0; i < this->props_.length (); i++) if (this->dp_cache_[i] != 0) delete this->dp_cache_[i]; delete [] this->dp_cache_; } int TAO_Property_Evaluator::is_dynamic_property (int index) { int return_value = 0; int num_properties = this->props_.length(); // Ensure index is in bounds. if (index >= 0 && index < num_properties) { // Obtain the value of the property at index . const CORBA::Any& value = this->props_[index].value; CORBA::TypeCode_var type = value.type (); // @@ Seth, this will not work on platforms using environment variable. ACE_DECLARE_NEW_CORBA_ENV; CORBA::Boolean equal = type->equal (CosTradingDynamic::_tc_DynamicProp ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (0); if (equal) return_value = 1; } return return_value; } CORBA::Any* TAO_Property_Evaluator::property_value (int index ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTradingDynamic::DPEvalFailure)) { CORBA::Any* prop_val = 0; CORBA::Boolean in_cache = this->dp_cache_ != 0 && this->dp_cache_[index] != 0; int dynamic = this->is_dynamic_property (index); if (!dynamic) prop_val = (CORBA::Any *) &(this->props_[index].value); else if (this->supports_dp_ && in_cache) prop_val = this->dp_cache_[index]; else if (this->supports_dp_) { // Property is defined at this point. CosTradingDynamic::DynamicProp* dp_struct; const CORBA::String_var name = this->props_[index].name.in (); const CORBA::Any& value = this->props_[index].value; // Extract the DP_Struct. value >>= dp_struct; CosTradingDynamic::DynamicPropEval_var dp_eval = CosTradingDynamic::DynamicPropEval::_duplicate (dp_struct->eval_if.in ()); if (CORBA::is_nil (dp_eval.in ())) { ACE_THROW_RETURN (CosTradingDynamic:: DPEvalFailure (name, CORBA::TypeCode::_nil (), CORBA::Any ()), prop_val); } else { CORBA::TypeCode* type = dp_struct->returned_type.in (); CORBA::Any& info = dp_struct->extra_info; ACE_TRY { // Retrieve the value of the dynamic property. prop_val = dp_eval->evalDP(name, type, info ACE_ENV_ARG_PARAMETER); ACE_TRY_CHECK; if (this->dp_cache_ != 0) this->dp_cache_[index] = prop_val; } ACE_CATCH (CORBA::SystemException, excp) { ACE_TRY_THROW (CosTradingDynamic::DPEvalFailure (name, type, info)); } ACE_ENDTRY; ACE_CHECK_RETURN (prop_val); } } return prop_val; } CORBA::TypeCode_ptr TAO_Property_Evaluator::property_type (int index) { CORBA::TypeCode_ptr prop_type = CORBA::TypeCode::_nil(); // Determine if property is both defined and dynamic. if (this->is_dynamic_property (index)) { // Extract type information from the DP_Struct. const CORBA::Any& value = this->props_[index].value; CosTradingDynamic::DynamicProp* dp_struct = 0; value >>= dp_struct; // Grab a pointer to the returned_type description prop_type = CORBA::TypeCode::_duplicate (dp_struct->returned_type.in ()); } else // TypeCode is self-evident at this point. prop_type = this->props_[index].value.type (); return prop_type; } TAO_Property_Evaluator_By_Name:: TAO_Property_Evaluator_By_Name (const CosTrading::PropertySeq& properties ACE_ENV_ARG_DECL, CORBA::Boolean supports_dp) ACE_THROW_SPEC ((CosTrading::DuplicatePropertyName, CosTrading::IllegalPropertyName)) : TAO_Property_Evaluator (properties, supports_dp) { int length = this->props_.length(); for (int i = 0; i < length; i++) { const CosTrading::Property& prop = this->props_[i]; if (! TAO_Trader_Base::is_valid_property_name (prop.name)) ACE_THROW (CosTrading::IllegalPropertyName (prop.name)); CORBA::String_var prop_name = prop.name.in (); if (this->table_.bind (prop_name, i)) ACE_THROW (CosTrading::DuplicatePropertyName (prop.name)); } } TAO_Property_Evaluator_By_Name:: TAO_Property_Evaluator_By_Name(CosTrading::Offer& offer, CORBA::Boolean supports_dp) : TAO_Property_Evaluator(offer, supports_dp) { int length = this->props_.length(); for (int i = 0; i < length; i++) { CORBA::String_var prop_name = (const char*) this->props_[i].name; this->table_.bind (prop_name, i); } } int TAO_Property_Evaluator_By_Name:: is_dynamic_property(const char* property_name) { int predicate = 0; int index = 0; CORBA::String_var prop_name (property_name); // If the property name is in the map, delegate evaluation to our // superclass. Otherwise, throw an exception. if (this->table_.find (prop_name, index) == 0) predicate = this->TAO_Property_Evaluator::is_dynamic_property(index); return predicate; } CORBA::Any* TAO_Property_Evaluator_By_Name::property_value (const char* property_name ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTradingDynamic::DPEvalFailure)) { int index = 0; CORBA::Any* prop_value = 0; CORBA::String_var prop_name (property_name); // If the property name is in the map, delegate evaluation to our // superclass. Otherwise, throw an exception. if (this->table_.find (prop_name, index) == 0) { prop_value = this->TAO_Property_Evaluator::property_value (index ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (0); } return prop_value; } CORBA::TypeCode_ptr TAO_Property_Evaluator_By_Name::property_type (const char* property_name) { int index = 0; CORBA::String_var prop_name (property_name); CORBA::TypeCode_ptr prop_type = CORBA::TypeCode::_nil(); // If the property name is in the map, delegate evaluation to our // superclass. Otherwise, throw an exception. if (this->table_.find (prop_name, index) == 0) prop_type = this->TAO_Property_Evaluator::property_type (index); return prop_type; } const CosTrading::Property* TAO_Property_Evaluator_By_Name::get_property (const char* property_name) { int index = 0; CosTrading::Property* property = 0; CORBA::String_var prop_name (property_name); if (this->table_.find (prop_name, index) == 0) property = (CosTrading::Property *) &this->props_[index]; return property; } TAO_Dynamic_Property::~TAO_Dynamic_Property (void) { } CosTradingDynamic::DynamicProp* TAO_Dynamic_Property:: construct_dynamic_prop (const char* name, CORBA::TypeCode_ptr returned_type, const CORBA::Any& extra_info) { ACE_UNUSED_ARG (name); CosTradingDynamic::DynamicProp* dp_struct = 0; ACE_NEW_RETURN (dp_struct, CosTradingDynamic::DynamicProp, 0); if (this->prop_.in () == CosTradingDynamic::DynamicPropEval::_nil ()) { // Seth, we need a way to either propagate exceptions out. ACE_DECLARE_NEW_CORBA_ENV; this->prop_ = this->_this (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (0); this->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (0); } dp_struct->eval_if = CosTradingDynamic::DynamicPropEval::_duplicate (this->prop_.in ()); dp_struct->returned_type = CORBA::TypeCode::_duplicate (returned_type); dp_struct->extra_info = extra_info; return dp_struct; } void TAO_Dynamic_Property::destroy (void) { if (this->prop_.in () != CosTradingDynamic::DynamicPropEval::_nil ()) { // @@ Seth, we need a way to propagate exceptions out. ACE_DECLARE_NEW_CORBA_ENV; PortableServer::POA_var poa = this->_default_POA (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; PortableServer::ObjectId_var id = poa->servant_to_id (this ACE_ENV_ARG_PARAMETER); ACE_CHECK; poa->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); ACE_CHECK; } } const char* TAO_Policies::POLICY_NAMES[] = { "starting_trader", "exact_type_match", "hop_count", "link_follow_rule", "match_card", "return_card", "search_card", "use_dynamic_properties", "use_modifiable_properties", "use_proxy_offers", "request_id" }; TAO_Policies::TAO_Policies (TAO_Trader_Base& trader, const CosTrading::PolicySeq& policies ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTrading::Lookup::IllegalPolicyName, CosTrading::DuplicatePolicyName)) : trader_ (trader) { for (int i = 0; i < TAO_NUM_POLICIES; i++) this->policies_[i] = 0; for (CORBA::ULong j = 0; j < policies.length (); j++) { const char *pol_name = (const char *) policies[j].name; size_t length = (pol_name == 0) ? 0 : ACE_OS::strlen (pol_name); int index = -1; if (length < ACE_OS::strlen (POLICY_NAMES[HOP_COUNT])) ACE_THROW (CosTrading::Lookup::IllegalPolicyName (pol_name)); switch (pol_name[0]) { case 'e': index = EXACT_TYPE_MATCH; break; case 'h': index = HOP_COUNT; break; case 'l': index = LINK_FOLLOW_RULE; break; case 'm': index = MATCH_CARD; break; case 'r': if (pol_name[2] == 't') index = RETURN_CARD; else if (pol_name[2] == 'q') index = REQUEST_ID; break; case 's': if (pol_name[1] == 't') index = STARTING_TRADER; else if (pol_name[1] == 'e') index = SEARCH_CARD; break; case 'u': if (pol_name[4] == 'd') index = USE_DYNAMIC_PROPERTIES; if (pol_name[4] == 'm') index = USE_MODIFIABLE_PROPERTIES; if (pol_name[4] == 'p') index = USE_PROXY_OFFERS; } // Match the name of the policy, and insert its value into the // vector. if (index == -1 || ACE_OS::strcmp (POLICY_NAMES[index], pol_name) != 0) ACE_THROW (CosTrading::Lookup::IllegalPolicyName (pol_name)); else if (this->policies_[index] != 0) ACE_THROW (CosTrading::DuplicatePolicyName (pol_name)); else this->policies_[index] = (CosTrading::Policy *) &(policies[j]); } } TAO_Policies::~TAO_Policies (void) { } CORBA::ULong TAO_Policies::ulong_prop (POLICY_TYPE pol ACE_ENV_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { CORBA::ULong return_value = 0, max_value = 0; const TAO_Import_Attributes_i& import_attrs = this->trader_.import_attributes (); // Discover the default values for each of the possible cardinality // policies. switch (pol) { case SEARCH_CARD: return_value = import_attrs.def_search_card (); max_value = import_attrs.max_search_card (); break; case MATCH_CARD: return_value = import_attrs.def_match_card (); max_value = import_attrs.max_match_card (); break; case RETURN_CARD: return_value = import_attrs.def_return_card (); max_value = import_attrs.max_return_card (); break; case HOP_COUNT: return_value = import_attrs.def_hop_count (); max_value = import_attrs.max_hop_count (); break; default: break; } if (this->policies_[pol] != 0) { // Extract the desired policy value. const CosTrading::Policy* policy = this->policies_[pol]; const CosTrading::PolicyValue& value = policy->value; CORBA::TypeCode_var type = value.type (); CORBA::Boolean equal_ulong = type->equal (CORBA::_tc_ulong ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (return_value); if (!equal_ulong) ACE_THROW_RETURN (CosTrading::Lookup::PolicyTypeMismatch (*policy), return_value); else value >>= return_value; if (max_value < return_value) return_value = max_value; } return return_value; } CORBA::ULong TAO_Policies::search_card (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->ulong_prop (SEARCH_CARD ACE_ENV_ARG_PARAMETER); } CORBA::ULong TAO_Policies::match_card (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->ulong_prop (MATCH_CARD ACE_ENV_ARG_PARAMETER); } CORBA::ULong TAO_Policies::return_card (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->ulong_prop (RETURN_CARD ACE_ENV_ARG_PARAMETER); } CORBA::Boolean TAO_Policies::boolean_prop (POLICY_TYPE pol ACE_ENV_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { CORBA::Boolean def_value = 1, return_value = 1; const TAO_Support_Attributes_i& support_attrs = this->trader_.support_attributes (); switch (pol) { case USE_MODIFIABLE_PROPERTIES: def_value = support_attrs.supports_modifiable_properties (); break; case USE_DYNAMIC_PROPERTIES: def_value = support_attrs.supports_dynamic_properties (); break; case USE_PROXY_OFFERS: def_value = support_attrs.supports_proxy_offers (); break; case EXACT_TYPE_MATCH: def_value = 0; break; default: break; } if (this->policies_[pol] != 0) { const CosTrading::Policy* policy = this->policies_[pol]; const CosTrading::PolicyValue& value = policy->value; CORBA::TypeCode_var type = value.type (); CORBA::Boolean equal_boolean = type->equal (CORBA::_tc_boolean ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (return_value); if (!equal_boolean) ACE_THROW_RETURN (CosTrading::Lookup::PolicyTypeMismatch (*policy), return_value); else value >>= CORBA::Any::to_boolean (return_value); if (def_value == 0 && pol != EXACT_TYPE_MATCH) return_value = 0; } else return_value = def_value; return return_value; } CORBA::Boolean TAO_Policies::use_modifiable_properties (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->boolean_prop (USE_MODIFIABLE_PROPERTIES ACE_ENV_ARG_PARAMETER); } CORBA::Boolean TAO_Policies::use_dynamic_properties (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->boolean_prop (USE_DYNAMIC_PROPERTIES ACE_ENV_ARG_PARAMETER); } CORBA::Boolean TAO_Policies::use_proxy_offers (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->boolean_prop (USE_PROXY_OFFERS ACE_ENV_ARG_PARAMETER); } CORBA::Boolean TAO_Policies::exact_type_match (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->boolean_prop (EXACT_TYPE_MATCH ACE_ENV_ARG_PARAMETER); } CosTrading::TraderName* TAO_Policies::starting_trader (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue)) { CosTrading::TraderName* trader_name = 0; if (this->policies_[STARTING_TRADER] != 0) { CosTrading::Policy* policy = this->policies_[STARTING_TRADER]; CosTrading::PolicyValue& value = policy->value; CORBA::TypeCode_var type = value.type (); CORBA::Boolean equal_tradername = type->equal (CosTrading::_tc_TraderName ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (trader_name); CORBA::Boolean equal_linknameseq = type->equal (CosTrading::_tc_LinkNameSeq ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (trader_name); if (!equal_tradername || !equal_linknameseq) ACE_THROW_RETURN (CosTrading::Lookup::PolicyTypeMismatch (*policy), trader_name); else value >>= trader_name; } return trader_name; } CosTrading::FollowOption TAO_Policies::link_follow_rule (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { CosTrading::FollowOption return_value = this->trader_.import_attributes ().def_follow_policy (); if (this->policies_[LINK_FOLLOW_RULE] != 0) { CosTrading::FollowOption max_follow_policy = this->trader_.import_attributes ().max_follow_policy (); CosTrading::Policy* policy = this->policies_[LINK_FOLLOW_RULE]; CosTrading::PolicyValue& value = policy->value; CORBA::TypeCode_var type = value.type (); // Extract the link follow rule CORBA::Boolean type_equal = type->equal (CosTrading::_tc_FollowOption ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (return_value); if (!type_equal) ACE_THROW_RETURN (CosTrading::Lookup::PolicyTypeMismatch (*policy), return_value); else value >>= return_value; if (return_value > max_follow_policy) return_value = max_follow_policy; } return return_value; } CosTrading::FollowOption TAO_Policies::link_follow_rule (const CosTrading::Link::LinkInfo& link_info ACE_ENV_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue, CosTrading::Link::IllegalLinkName, CosTrading::Link::UnknownLinkName)) { CosTrading::FollowOption return_value = CosTrading::local_only; CosTrading::FollowOption trader_max_follow_policy = this->trader_.import_attributes ().max_follow_policy (); CosTrading::FollowOption link_limiting_follow_rule = link_info.limiting_follow_rule; // If not defined defaults to trader.def_link_follow_rule CosTrading::FollowOption query_link_follow_rule = this->link_follow_rule (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (return_value); return_value = (query_link_follow_rule < trader_max_follow_policy) ? query_link_follow_rule : trader_max_follow_policy; return_value = (return_value < link_limiting_follow_rule) ? return_value : link_limiting_follow_rule; return return_value; } CORBA::ULong TAO_Policies::hop_count (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { return this->ulong_prop (HOP_COUNT ACE_ENV_ARG_PARAMETER); } CosTrading::Admin::OctetSeq* TAO_Policies::request_id (ACE_ENV_SINGLE_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch)) { CosTrading::Admin::OctetSeq* request_id = 0; if (this->policies_[REQUEST_ID] != 0) { CosTrading::Policy* policy = this->policies_[REQUEST_ID]; CosTrading::PolicyValue& value = policy->value; CORBA::TypeCode_var type = value.type (); CORBA::Boolean equal_octetseq = type->equal (CosTrading::Admin::_tc_OctetSeq ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (request_id); if (!equal_octetseq) ACE_THROW_RETURN (CosTrading::Lookup::PolicyTypeMismatch (*policy), request_id); else value >>= request_id; } return request_id; } void TAO_Policies:: copy_in_follow_option (CosTrading::PolicySeq& policy_seq, const CosTrading::Link::LinkInfo& link_info ACE_ENV_ARG_DECL) const ACE_THROW_SPEC ((CosTrading::Lookup::PolicyTypeMismatch, CosTrading::Lookup::InvalidPolicyValue)) { CosTrading::FollowOption follow_option = CosTrading::local_only; CosTrading::FollowOption trader_max_follow_policy = this->trader_.import_attributes ().max_follow_policy (); if (this->policies_[LINK_FOLLOW_RULE] != 0) { CosTrading::FollowOption query_link_follow_rule = this->link_follow_rule (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; follow_option = (CosTrading::FollowOption) (link_info.limiting_follow_rule < trader_max_follow_policy ? (link_info.limiting_follow_rule < query_link_follow_rule ? link_info.limiting_follow_rule : query_link_follow_rule) : (trader_max_follow_policy < query_link_follow_rule ? trader_max_follow_policy : query_link_follow_rule)); } else follow_option = (CosTrading::FollowOption) (link_info.def_pass_on_follow_rule < trader_max_follow_policy ? link_info.def_pass_on_follow_rule : trader_max_follow_policy); CORBA::ULong i = 0; for (i = 0; i < policy_seq.length (); i++) if (ACE_OS::strcmp (policy_seq[i].name, POLICY_NAMES[LINK_FOLLOW_RULE]) == 0) { policy_seq[i].value <<= follow_option; break; } if (i == policy_seq.length ()) { policy_seq.length (i + 1); policy_seq[i].name = POLICY_NAMES[LINK_FOLLOW_RULE]; policy_seq[i].value <<= follow_option; } } void TAO_Policies:: copy_to_pass (CosTrading::PolicySeq& policy_seq, const CosTrading::Admin::OctetSeq& request_id ACE_ENV_ARG_DECL) const { CORBA::ULong counter = 0; CosTrading::Policy* policy_buffer = CosTrading::PolicySeq::allocbuf (REQUEST_ID + 1); if (policy_buffer == 0) return; for (int i = 0; i <= REQUEST_ID; i++) { CosTrading::Policy& new_policy = policy_buffer[counter]; if (i == REQUEST_ID) { // Set the new request id. new_policy.name = POLICY_NAMES[REQUEST_ID]; new_policy.value <<= request_id; counter++; } else if (this->policies_[i] != 0) { // Copy in the existing policies. new_policy.name = POLICY_NAMES[i]; new_policy.value = this->policies_[i]->value; counter++; } // We always require a hop count. if (i == HOP_COUNT) { CORBA::ULong count = this->hop_count (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; new_policy.name = POLICY_NAMES[HOP_COUNT]; new_policy.value <<= count - 1; // Don't count hop count twice. if (this->policies_[i] == 0) counter++; } } policy_seq.replace (REQUEST_ID + 1, counter, policy_buffer, 1); } void TAO_Policies::copy_to_forward (CosTrading::PolicySeq& policy_seq, const CosTrading::TraderName& trader_name) const { // Create a new policy sequence, shortening the starting trader // policy by one link. CORBA::ULong counter = 0; CosTrading::Policy* policy_buffer = CosTrading::PolicySeq::allocbuf (REQUEST_ID + 1); if (policy_buffer == 0) return; for (int i = 0; i <= REQUEST_ID; i++) { CosTrading::Policy& new_policy = policy_buffer[counter]; if (this->policies_[i] != 0) { // Copy in the existing policies. if (i == STARTING_TRADER && trader_name.length () > 1) { // Eliminate the first link of the trader name. // Only pass on the property if the sequence // contains more links after us. // The any will sieze control of this memory. // Allocating here avoids copying in the policy // any. CORBA::ULong length = trader_name.length (); CosTrading::LinkName* buf = CosTrading::TraderName::allocbuf (length - 1); if (buf != 0) { for (CORBA::ULong j = 1; j < length; j++) buf[j - 1] = CORBA::string_dup (trader_name[j]); new_policy.name = this->policies_[i]->name; CosTrading::TraderName new_name (length - 1, length - 1, buf, 1); new_policy.value <<= new_name; counter++; } } else if (i != STARTING_TRADER) { new_policy.name = this->policies_[i]->name; new_policy.value = this->policies_[i]->value; counter++; } } } // Create the new sequence policy_seq.replace (REQUEST_ID + 1, counter, policy_buffer, 1); } TAO_Offer_Modifier:: TAO_Offer_Modifier (const char* type_name, const CosTradingRepos::ServiceTypeRepository::TypeStruct& type_struct, CosTrading::Offer* offer) : type_ (type_name), offer_ (offer) { const CosTradingRepos::ServiceTypeRepository::PropStructSeq& pstructs = type_struct.props; CosTrading::PropertySeq& prop_seq = this->offer_->properties; CORBA::ULong pstructs_length = pstructs.length (), props_length = prop_seq.length (), i = 0; // Create a mapping of property names to their types. for (i = 0; i < pstructs_length; i++) { CORBA::String_var prop_name = pstructs[i].name.in (); CORBA::TypeCode_ptr type_code = CORBA::TypeCode::_duplicate (pstructs[i].value_type.in ()); this->prop_types_.bind (prop_name, type_code); } // Separate the type defined properties into mandatory and readonly for (i = 0; i < pstructs_length; i++) { const char* pname = pstructs[i].name; if (pstructs[i].mode == CosTradingRepos::ServiceTypeRepository::PROP_MANDATORY) { CORBA::String_var prop_name (pname); this->mandatory_.insert (prop_name); } else if (pstructs[i].mode == CosTradingRepos::ServiceTypeRepository::PROP_READONLY) { CORBA::String_var prop_name (pname); this->readonly_.insert (prop_name); } } // Insert the indices of the offer properties into a map. for (i = 0; i < props_length; i++) { CORBA::String_var prop_name = static_cast (prop_seq[i].name); this->props_.bind (prop_name, &prop_seq[i]); } } TAO_Offer_Modifier::~TAO_Offer_Modifier (void) { for (TAO_Typecode_Table::iterator type_iter (this->prop_types_); ! type_iter.done (); type_iter++) { CORBA::TypeCode_ptr corba_type = (*type_iter).int_id_; CORBA::release (corba_type); } } void TAO_Offer_Modifier:: delete_properties (const CosTrading::PropertyNameSeq& deletes ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTrading::Register::UnknownPropertyName, CosTrading::Register::MandatoryProperty, CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName)) { // Validate that the listed property names can be deleted CORBA::ULong i = 0, length = deletes.length (); TAO_String_Set delete_me; for (i = 0; i < length; i++) { const char* dname = static_cast (deletes[i]); if (! TAO_Trader_Base::is_valid_property_name (dname)) ACE_THROW (CosTrading::IllegalPropertyName (dname)); else { CORBA::String_var prop_name (dname); if (this->mandatory_.find (prop_name) == 0) ACE_THROW (CosTrading::Register::MandatoryProperty (this->type_, dname)); else if (delete_me.insert (prop_name) == 1) ACE_THROW (CosTrading::DuplicatePropertyName (dname)); else if (this->props_.find (prop_name) == -1) ACE_THROW (CosTrading::Register::UnknownPropertyName (dname)); } } // Delete those properties from the offer. for (i = 0; i < length; i++) { CORBA::String_var prop_name = static_cast (deletes[i]); this->props_.unbind (prop_name); } } void TAO_Offer_Modifier:: merge_properties (const CosTrading::PropertySeq& modifies ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName, CosTrading::PropertyTypeMismatch, CosTrading::ReadonlyDynamicProperty, CosTrading::Register::ReadonlyProperty)) { int i = 0, length = 0; TAO_String_Set modify_me; // Ensure that the proposed changes aren't to readonly properties or // otherwise invalid. TAO_Property_Evaluator prop_eval (modifies); for (i = 0, length = modifies.length (); i < length; i++) { const char* mname = modifies[i].name; if (TAO_Trader_Base::is_valid_property_name (mname)) { CORBA::String_var prop_name (mname); if (this->readonly_.find (prop_name) == 0) { // Can't assign a dynamic property to a property with // readonly mode, and can't reassign a readonly property. if (prop_eval.is_dynamic_property (i)) ACE_THROW (CosTrading::ReadonlyDynamicProperty (this->type_, mname)); else if (this->props_.find (prop_name) == 0) ACE_THROW (CosTrading::Register::ReadonlyProperty (this->type_, mname)); } // Validate the property type if the property is defined in // the service type description. CORBA::TypeCode_ptr type_def = 0; if (this->prop_types_.find (prop_name, type_def) == 0) { CORBA::TypeCode_var prop_type = prop_eval.property_type (i); // @@ Frank: This code used to have this comment and line // of code before I fixed the "ACE_TRY" fuzz warning here. // @@ Seth, are we trying to ignore the exception here? // CORBA::Environment ACE_TRY_ENV; // @@ Frank: It seems clear that this is not going to work as // expected. Is the purpose to ignore any exceptions from // equal ()? For now, exceptions are returned since this // seemed "safest". CORBA::Boolean td_equal = type_def->equal (prop_type.in () ACE_ENV_ARG_PARAMETER); ACE_CHECK; if (!td_equal) ACE_THROW (CosTrading::PropertyTypeMismatch (mname, modifies[i])); } if (modify_me.insert (prop_name) == 1) ACE_THROW (CosTrading::DuplicatePropertyName (mname)); } else ACE_THROW (CosTrading::IllegalPropertyName (mname)); } } void TAO_Offer_Modifier::affect_change (const CosTrading::PropertySeq& modifies) { // Create a new property list reflecting the deletes, modifies, and // add operations performed, and place this property list in the // offer. // Merge these properties with the original set. CORBA::ULong i = 0, merge_length = modifies.length (); for (i = 0; i < merge_length; i++) { Property_Table::ENTRY* entry = 0; CORBA::String_var prop_name = modifies[i].name.in (); CosTrading::Property* prop = const_cast (&modifies[i]); if (this->props_.bind (prop_name, prop, entry) == 1) // We need to rebind here. entry->int_id_ = prop; } CORBA::ULong num_modified = 0, original_length = this->offer_->properties.length (), total_length = static_cast (this->props_.current_size ()); // Scrap the existing property sequence and begin a new one CosTrading::PropertySeq prop_seq (total_length); // this->offer_->properties.length (total_length); // Copy in the unaffected and modified props into the offer, // excluding those that were deleted. Let's try and retain their // relative ordering. for (i = 0; i < original_length; i++) { CosTrading::Property* prop_value = 0; const char* name = this->offer_->properties[i].name; CORBA::String_var prop_name (name); if (this->props_.unbind (prop_name, prop_value) == 0) prop_seq[num_modified++] = *prop_value; } for (i = 0; i < merge_length; i++) { CosTrading::Property* prop_value = 0; const char* name = modifies[i].name; CORBA::String_var prop_name (name); if (this->props_.unbind (prop_name, prop_value) == 0) prop_seq[num_modified++] = *prop_value; } this->offer_->properties.length (total_length); for (i = 0; i < total_length; i++) this->offer_->properties[i] = prop_seq[i]; // Free the old, orphaned sequence. // CosTrading::PropertySeq::freebuf (prop_buf); } TAO_Offer_Filter::TAO_Offer_Filter (TAO_Policies& policies ACE_ENV_ARG_DECL) { search_card_ = policies.search_card (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; match_card_ = policies.match_card (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; return_card_ = policies.return_card (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; dp_ = policies.use_dynamic_properties (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; mod_ = policies.use_modifiable_properties (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; CORBA::Boolean exact_type_match = policies.exact_type_match (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK; if (exact_type_match == 1) { CORBA::String_var exact_match (TAO_Policies::POLICY_NAMES[TAO_Policies::EXACT_TYPE_MATCH]); this->limits_.insert (exact_match); } } void TAO_Offer_Filter:: configure_type (CosTradingRepos::ServiceTypeRepository::TypeStruct* type_struct) { CosTradingRepos::ServiceTypeRepository::PropStructSeq& prop_seq = type_struct->props; // Take note of non-modifiable properties in the type_struct this->not_mod_props_.reset (); for (int i = prop_seq.length () - 1; i >= 0; i--) { CosTradingRepos::ServiceTypeRepository::PropertyMode mode = prop_seq[i].mode; if (mode == CosTradingRepos::ServiceTypeRepository::PROP_MANDATORY_READONLY || mode == CosTradingRepos::ServiceTypeRepository::PROP_READONLY) { CORBA::String_var prop_name ((const char*) prop_seq[i].name); this->not_mod_props_.insert (prop_name); } } } CORBA::Boolean TAO_Offer_Filter::ok_to_consider (CosTrading::Offer* offer) { CORBA::String_var use_mods = TAO_Policies::POLICY_NAMES[TAO_Policies::USE_MODIFIABLE_PROPERTIES]; CORBA::String_var use_dyns = TAO_Policies::POLICY_NAMES[TAO_Policies::USE_DYNAMIC_PROPERTIES]; CORBA::Boolean return_value = 1; TAO_Property_Evaluator prop_eval (*offer); // If we should screen offers, determine if this offer is unworthy // for consideration. if (! (this->mod_ && this->dp_)) { for (int i = offer->properties.length () - 1; i >= 0 && return_value; i--) { // Winnow away the unwanted offers with modifiable or // dynamic properties. if (! this->mod_) { // Determine if this property name is found in the set // of modifiable properties for the type being considered. CORBA::String_var prop_name ((const char*) offer->properties[i].name); if (this->not_mod_props_.find (prop_name) == -1) { this->limits_.insert (use_mods); return_value = 0; } } if (! this->dp_ && return_value) { // Determine if this property is dynamic. if (prop_eval.is_dynamic_property (i)) { this->limits_.insert (use_dyns); return_value = 0; } } if (return_value == 0) break; } } // If we're good to go, consider this offer considered and decrement // the search cardinality counter. if (return_value) { this->search_card_--; if (this->search_card_ == 0) { CORBA::String_var search_card = TAO_Policies::POLICY_NAMES[TAO_Policies::SEARCH_CARD]; this->limits_.insert (search_card); } } return return_value; } CORBA::Boolean TAO_Offer_Filter::ok_to_consider_more (void) { return this->search_card_ > 0 && this->match_card_ > 0; } void TAO_Offer_Filter::matched_offer (void) { this->match_card_--; this->return_card_--; if (this->match_card_ == 0) { CORBA::String_var match_card = TAO_Policies::POLICY_NAMES[TAO_Policies::MATCH_CARD]; this->limits_.insert (match_card); } if (this->return_card_ == 0) { CORBA::String_var return_card = TAO_Policies::POLICY_NAMES[TAO_Policies::MATCH_CARD]; this->limits_.insert (return_card); } } CORBA::ULong TAO_Offer_Filter::search_card_remaining (void) const { return this->search_card_; } CORBA::ULong TAO_Offer_Filter::match_card_remaining (void) const { return this->match_card_; } CosTrading::PolicyNameSeq* TAO_Offer_Filter::limits_applied (void) { int i = 0; CORBA::ULong size = static_cast (this->limits_.size ()); CosTrading::PolicyName* temp = CosTrading::PolicyNameSeq::allocbuf (size); for (TAO_String_Set::iterator p_iter (this->limits_.begin()); ! p_iter.done (); p_iter.advance ()) { CORBA::String_var* policy_name_ptr = 0; p_iter.next (policy_name_ptr); temp[i++] = CORBA::string_dup (policy_name_ptr->in ()); } return new CosTrading::PolicyNameSeq (size, size, temp, 1); } TAO_Property_Filter:: TAO_Property_Filter (const SPECIFIED_PROPS& desired_props ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CosTrading::IllegalPropertyName, CosTrading::DuplicatePropertyName)) : policy_ (desired_props._d ()) { if (this->policy_ == CosTrading::Lookup::some) { const CosTrading::PropertyNameSeq& prop_seq = desired_props.prop_names (); int length = prop_seq.length (); for (int i = 0; i < length; i++) { const char* pname = prop_seq[i]; // Check for errors or duplicates if (TAO_Trader_Base::is_valid_property_name (pname)) { CORBA::String_var prop_name (pname); if (this->props_.insert (prop_name) == 1) ACE_THROW (CosTrading::DuplicatePropertyName (pname)); } else ACE_THROW (CosTrading::IllegalPropertyName (pname)); } } } TAO_Property_Filter:: TAO_Property_Filter (const TAO_Property_Filter& prop_filter) : props_ (prop_filter.props_), policy_ (prop_filter.policy_) { } TAO_Property_Filter& TAO_Property_Filter::operator= (const TAO_Property_Filter& other) { this->props_ = other.props_; this->policy_ = other.policy_; return *this; } void TAO_Property_Filter::filter_offer (CosTrading::Offer* source, CosTrading::Offer& destination) { Prop_Queue prop_queue; CosTrading::PropertySeq& s_props = source->properties; CosTrading::PropertySeq& d_props = destination.properties; CORBA::ULong length = static_cast (s_props.length ()), elem = 0; destination.reference = CORBA::Object::_duplicate (source->reference.in ()); if (this->policy_ == CosTrading::Lookup::some) { for (CORBA::ULong i = 0; i < length; i++) { if (this->policy_ == CosTrading::Lookup::all) prop_queue.enqueue_tail (&s_props[i]); else { const char* p_name = s_props[i].name; CORBA::String_var prop_name (p_name); // Save those property that match. if (this->props_.find (prop_name) == 0) prop_queue.enqueue_tail (&s_props[i]); } } // Shove the matched properties into the destination property // sequence. length = static_cast (prop_queue.size ()); d_props.length (length); for (Prop_Queue::ITERATOR prop_iter (prop_queue); ! prop_iter.done (); prop_iter.advance (), elem++) { CosTrading::Property** prop_ptr = 0; prop_iter.next (prop_ptr); d_props[elem] = **prop_ptr; } } else if (this->policy_ == CosTrading::Lookup::all) // CosTrading::Property* props = s_props.get_buffer (0); // d_props.replace (length, length, props, 0); d_props = s_props; } TAO_END_VERSIONED_NAMESPACE_DECL