/// <summary> /// This method uses a BRE Policy to lookup and return information about another BRE Policy. (Broker Pattern) /// </summary> /// <param name="message">Xml Message for use of the policy lookup process</param> /// <param name="resolution">An instance of the resolution class for use in the policy lookup process</param> /// <param name="PolicyName">The Name of the BRE Policy for looking up which policy information to return</param> /// <param name="itineraryInfo">Instance of an Itinerary class which contains the attached itinerary for use in the policy lookup process</param> /// <param name="factRetreiver">Instance of MessageContextFactRetriever which contains BizTalk Message Promoted and Distinguished properties for use in the policy lookup process</param> /// <param name="major">Major version of the business rule to execute for determining which policyinfo to return</param> /// <param name="minor">Minor version of the business rule to execute for determining which policyinfo to return</param> /// <returns>PolicyBrokerInfo class containing information about the name, version, document type, and namespace of a Policy to execute</returns> public PolicyBrokerInfoCollection GetPolicies(XmlDocument message, Resolution resolution, string PolicyName, ItineraryFact itineraryInfo, MessageContextFactRetriever factRetreiver, int major, int minor) { EventLogger.Write("Executing PolicyBroker!"); string documentType = "Microsoft.Practices.ESB.ResolveProviderMessage"; string docNameSpace = resolution.Namespace(); string docName = resolution.MessageName(); EventLogger.Write("Document Namespace is: " + docNameSpace); EventLogger.Write("Document Name is: " + docName); PolicyBrokerInfo _info = new PolicyBrokerInfo() { DocNamespace = docNameSpace, DocName = docName }; PolicyBrokerInfoCollection infos = new PolicyBrokerInfoCollection(); infos.AddPolicyInfo(docName, docNameSpace, string.Format("{0}#{1}", docNameSpace, docName), ""); object[] facts = new object[5]; TypedXmlDocument document = new TypedXmlDocument(documentType, message); facts[0] = resolution; facts[1] = document; facts[2] = infos; facts[3] = itineraryInfo; facts[4] = factRetreiver; EventLogger.Write("Document Content is: " + message.InnerXml); bool useVersioning = (major > 0 || minor > 0); if (useVersioning) { this.policyExecutor.ExecutePolicy(PolicyName, facts, major, minor); } else { this.policyExecutor.ExecutePolicy(PolicyName, facts); } foreach (var policyInfo in infos.PolicyInfos) { var info = policyInfo.Value; if (string.IsNullOrEmpty(info.PolicyName)) { EventLogger.Write(string.Format( "Policy Broker could not found policy in Policy {0} for message name {1} with namespace {2}!", info.PolicyName, info.DocName, info.DocNamespace)); } EventLogger.Write("Found Policy " + info.PolicyName + "\nVersion: " + info.Version); } return(infos); }
/// <summary> /// Method which executes the BRE Policy which is configured using the config and resolver connection string /// </summary> /// <param name="config">string containing name, value property values</param> /// <param name="resolver">Resolver connection string</param> /// <param name="message">Xml document containing the message to pass to the BRE policies if configured properly</param> /// <param name="resolution">Resolution object</param> /// <param name="bre">BRE Descriptor object</param> /// <param name="ctxtValues">Dictionary collection of BizTalk Message Context property value pairs</param> /// <param name="pCtxt">BizTalk Pipeline Context</param> /// <param name="baseMsg">BizTalk BaseMessage</param> /// <returns>Resolver Dictionary Collection containing resolved entries, such as itinerary name, map name, and endpoint address resolution values</returns> private static Dictionary <string, string> ResolveRules(string config, string resolver, XmlDocument message, Resolution resolution, BRE bre, Dictionary <string, string> ctxtValues, IPipelineContext pCtxt, ref IBaseMessage baseMsg) { Dictionary <string, string> dictionary3; int num = 0; int num2 = 0; Policy policy = null; Dictionary <string, string> dictionary = null; string[] strArray = null; object[] objArray = null; TypedXmlDocument document = null; ItineraryFact itineraryInfo = new ItineraryFact(); string documentSpecNameField = "Microsoft.Practices.ESB.ResolveProviderMessage"; Dictionary <string, string> resolverDictionary = new Dictionary <string, string>(); if (!resolver.Contains(@":\")) { resolver = resolver + @":\"; } try { EventLogger.Write("Resolution strong name is {0}.", new object[] { resolution.DocumentSpecNameField }); if (!string.IsNullOrEmpty(resolution.DocumentSpecNameField) && bre.recognizeMessageFormat) { int index = resolution.DocumentSpecNameField.IndexOf(",", StringComparison.CurrentCultureIgnoreCase); if ((index > 0) && (index < resolution.DocumentSpecNameField.Length)) { documentSpecNameField = resolution.DocumentSpecNameField.Substring(0, index); } else { documentSpecNameField = resolution.DocumentSpecNameField; } } // add root node as non promoted value for purpose of using with Orchestrations if needed if (ctxtValues == null) { ctxtValues = new Dictionary <string, string>(); } ctxtValues.Add("Microsoft.Practices.ESB.ResolveProviderMessage#RootNode", message.DocumentElement.LocalName.ToUpperInvariant()); MessageContextFactRetriever customFactRetriever = new MessageContextFactRetriever(ctxtValues); EventLogger.Write("DocType for typed xml document is {0}.", new object[] { documentSpecNameField }); if (!string.IsNullOrEmpty(bre.version)) { strArray = bre.version.Split(".".ToCharArray()); if (strArray != null) { num = Convert.ToInt16(strArray[0], NumberFormatInfo.CurrentInfo); num2 = Convert.ToInt16(strArray[1], NumberFormatInfo.CurrentInfo); } } if (bre.useMsg) { EventLogger.Write("Xml document Content is {0}.", message.OuterXml); objArray = new object[4]; document = new TypedXmlDocument(documentSpecNameField, message); objArray[0] = resolution; objArray[1] = document; objArray[2] = itineraryInfo; objArray[3] = customFactRetriever; } else { objArray = new object[] { resolution, itineraryInfo, customFactRetriever }; } bool useDebugInterceptor = false; string outputPath = string.Empty; if (bre.useDebugInterceptorSpecified) { useDebugInterceptor = bre.useDebugInterceptor; outputPath = bre.debugOutputPath; policyExecutor = new PolicyExecutor(useDebugInterceptor, outputPath); } else { policyExecutor = new PolicyExecutor(false, string.Empty); } // Check to see if we need to use the Policy Broker if (bre.usePolicyBrokerSpecified) { if (bre.usePolicyBroker) { PolicyBroker broker = new PolicyBroker(useDebugInterceptor, outputPath); PolicyBrokerInfoCollection _policyInfos = broker.GetPolicies(message, resolution, bre.policy, itineraryInfo, customFactRetriever, num, num2); foreach (var policyBrokerInfo in _policyInfos.PolicyInfos) { var policyInfo = policyBrokerInfo.Value; int foundPolicyMajor = 0; int foundPolicyMinor = 0; strArray = policyInfo.Version.Split(".".ToCharArray()); if (strArray != null) { foundPolicyMajor = Convert.ToInt16(strArray[0], NumberFormatInfo.CurrentInfo); foundPolicyMinor = Convert.ToInt16(strArray[1], NumberFormatInfo.CurrentInfo); } policyExecutor.ExecutePolicy(policyInfo.PolicyName, objArray, foundPolicyMajor, foundPolicyMinor); } } else { // don't use policy broker policyExecutor.ExecutePolicy(bre.policy, objArray, num, num2); } } else { // don't use policy broker policyExecutor.ExecutePolicy(bre.policy, objArray, num, num2); } if (objArray[0] == null) { throw new ResolveException("Resolution is not configured correctly after applying BRE Custom Resolver;\nPlease check the Business Rule Policy"); } // Check for Itinerary fact values SetAllResolutionDictionaryEntries(objArray, resolverDictionary, bre); dictionary3 = resolverDictionary; if (bre.useMsg) { TypedXmlDocument doc = (TypedXmlDocument)objArray[1]; dictionary3.Add("message", doc.Document.OuterXml); if (bre.useMsgCtxt) { MessageContextFactRetriever customRetriever = (MessageContextFactRetriever)objArray[3]; dictionary3.Add("contextValues", GetContextValuesString(customRetriever.GetDictionaryCollection())); // Update the context properties UpdateContextProperties(customRetriever, bre, pCtxt, ref baseMsg); } // Modify the Current Message in pipeline context UpdateMessage(doc.Document.OuterXml, pCtxt, ref baseMsg); } else { if (bre.useMsgCtxt) { MessageContextFactRetriever customRetriever = (MessageContextFactRetriever)objArray[2]; dictionary3.Add("contextValues", GetContextValuesString(customRetriever.GetDictionaryCollection())); // Update the context properties UpdateContextProperties(customRetriever, bre, pCtxt, ref baseMsg); } } } catch (Exception exception) { EventLogger.Write(MethodBase.GetCurrentMethod(), exception); throw; } finally { if (objArray != null) { objArray = null; } if (document != null) { document = null; } if (resolution != null) { resolution = null; } if (bre != null) { bre = null; } if (strArray != null) { strArray = null; } if (policy != null) { policy.Dispose(); policy = null; } if (dictionary != null) { dictionary.Clear(); dictionary = null; } if (resolverDictionary != null) { resolverDictionary = null; } if (ctxtValues != null) { ctxtValues = null; } } return(dictionary3); }
/// <summary> /// Updates the BizTalk BaseMessage and Message Context with any new or modified values from the executed BRE Policies. /// </summary> /// <param name="msgCtxt">BizTalk BaseMessage Context value collection to update</param> /// <param name="bre">BRE Descriptor with possible values to read for updating the Message context</param> /// <param name="pCtxt">PipelineContext</param> /// <param name="baseMsg">BizTalk BaseMessage to update</param> private static void UpdateContextProperties(MessageContextFactRetriever msgCtxt, BRE bre, IPipelineContext pCtxt, ref IBaseMessage baseMsg) { try { if (pCtxt == null || baseMsg == null) { return; } IBaseMessageContext baseMsgCtxt = baseMsg.Context; foreach (var updatedCtxt in msgCtxt.GetDictionaryCollection()) { string[] NameNameSpaceValues = updatedCtxt.Key.Split('#'); // no need to check for old values just overwrite and add // Check to see if we need to promote it string name = NameNameSpaceValues[1]; bool shouldPromote = name.Contains("!"); bool isDistinguished = name.Contains("/"); string namesp = NameNameSpaceValues[0]; // check to determine if we should promote and not distinguished if (shouldPromote && !isDistinguished) { string correctName = name; // remove ! char from key name before promoting if (shouldPromote) { correctName = name.Substring(0, name.Length - 1); } // however check to see if already promoted or not bool isAlreadyPromoted = false; var ovalue = baseMsgCtxt.Read(correctName, namesp); if (ovalue != null) { isAlreadyPromoted = baseMsgCtxt.IsPromoted(correctName, namesp); } if (ovalue != null && isAlreadyPromoted) { // we need to remove and re - promote baseMsgCtxt.Write(correctName, namesp, null); baseMsgCtxt.Promote(correctName, namesp, null); baseMsgCtxt.Promote(correctName, namesp, updatedCtxt.Value); } else { // it's not already promoted and we should promote if we can, // this assumes there is a valid property schema, name, and data type associated with it for promotion validation... // dangerous operation which could cause cyclic loop by re-promoting a property that was slated to be demoted *wasPromote*... if (bre.useRepromotionSpecified) { if (bre.useRepromotion) { try { baseMsgCtxt.Write(correctName, namesp, null); baseMsgCtxt.Promote(correctName, namesp, null); baseMsgCtxt.Promote(correctName, namesp, updatedCtxt.Value); } catch (Exception ex) { EventLogger.LogMessage( string.Format( "Namespace: {0}\nName: {1}\n caused an exception:\n{2}\nThis item was not promoted.", namesp, correctName, ex.Message), EventLogEntryType.Error, 1000); } } } } } else if (shouldPromote && isDistinguished) { // can't promote a distinguished field that contains a "/" in it's name, there's no way for BizTalk to validate it using normal BizTalk Property Schemas... // do nothing. } else if (isDistinguished) { // We don't need to promote it, only write it (Distinguished) // we need to remove and re-write it baseMsgCtxt.Write(name, namesp, null); baseMsgCtxt.Write(name, namesp, updatedCtxt.Value); } //else niether promote nore write so do nothing... } pCtxt.ResourceTracker.AddResource(baseMsgCtxt); } catch (Exception ex) { EventLog.WriteEntry("BRE_ResolverProvider::UpdateContextProperties", ex.ToString(), EventLogEntryType.Error, 10000); throw; } }