コード例 #1
0
        public void RunEventRules(string eventName, Item pageItem = null, params string[] values)
        {
            Assert.IsNotNullOrEmpty(eventName, $"{nameof(RulesService)}.{nameof(RunEventRules)} parameter {nameof(eventName)} is required");

            var ruleContext = new EventRuleContext()
            {
                EventName = eventName,
                Item      = pageItem,
                Value1    = ParamUtil.GetValue(1, values),
                Value2    = ParamUtil.GetValue(2, values),
                Value3    = ParamUtil.GetValue(3, values)
            };

            // Run Global Rules
            using (new SecurityDisabler())
            {
                var root = Utils.ItemUtil.GetItemById(ItemIds.GlobalRules.EventRules);
                if (root == null)
                {
                    return; // no root, exit
                }
                RuleList <EventRuleContext> rules = RuleFactory.GetRules <EventRuleContext>(root, "Rule");
                if (rules != null)
                {
                    rules.Run(ruleContext);
                }
            }
        }
コード例 #2
0
        protected virtual string GetEventValue(string optionId, EventRuleContext ruleContext)
        {
            switch (optionId)
            {
            case ItemIds.ValueOptions.Value1:
                return(ruleContext.Value1);

            case ItemIds.ValueOptions.Value2:
                return(ruleContext.Value2);

            case ItemIds.ValueOptions.Value3:
                return(ruleContext.Value3);
            }
            return(null);
        }
コード例 #3
0
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <returns></returns>
        /// 
        private EventRuleContext GetContext()
        {
            EventRuleContext context = new EventRuleContext(null);

            // Set up a name table so we can query based on namespaces
            NameTable SoapNameTable = new NameTable();
            XmlNamespaceManager SoapNamespaceManager = new XmlNamespaceManager(SoapNameTable);
            SoapNamespaceManager.AddNamespace(String.Empty, "urn:none");
            SoapNamespaceManager.AddNamespace("soap", SoapURN);

            // This allows custom namespaces as defined in the config xml
            foreach (XmlElement NamespaceNode in ruleNode.SelectNodes("namespaces/namespace"))
            {
                string NamespaceName = "";
                string NamespaceURN = "urn:none";
                if (NamespaceNode.GetAttributeNode("name") != null)
                {
                    NamespaceName = NamespaceNode.GetAttribute("name");
                }
                if (NamespaceNode.InnerText != "")
                {
                    NamespaceURN = NamespaceNode.InnerText;
                }
                SoapNamespaceManager.AddNamespace(NamespaceName, NamespaceURN);
            }

            context.SoapNameTable = SoapNameTable;
            context.SoapNamespaceManager = SoapNamespaceManager;
            return context;
        }
コード例 #4
0
        /// <summary>
        /// This routine takes a message, finds the appropriate actions, executes
        /// any necessary stylesheet, and executes each in turn.
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        /// <returns></returns>
        /// 
        private bool ApplyRule(EventRuleContext context)
        {
            XmlNodeList actions = ruleNode.SelectNodes("action");
            bool OKToSend = true;
            if (actions.Count == 0)
            {
                OKToSend = ExecuteAction(context, null, null);
            }
            else
            {
                foreach (XmlElement action in actions)
                {
                    if (CheckTests(action, context.SoapMessage, context.SoapNamespaceManager))
                    {
                        foreach (XmlElement actionDescription in action.SelectNodes("*"))
                        {
                            XmlElement actionCommand = null;
                            switch (actionDescription.Name)
                            {
                                case "test":
                                    break;
                                case "xsl:stylesheet":
                                    try
                                    {
                                        actionCommand = Transform(context.SoapMessage, actionDescription);
                                    }
                                    catch (System.Exception exception)
                                    {
                                        if (Logger.IsErrorEnabled)
                                        {
                                            LogError(exception, "failed to transform: {0}.", exception.Message);
                                        }
                                        actionCommand = null;
                                    }
                                    break;
                                default:
                                    actionCommand = actionDescription;
                                    break;
                            }

                            if (actionCommand != null)
                            {
                                // look for nested action node.
                                if (actionCommand.Name == "action")
                                {
                                    foreach (XmlElement tempAction in actionCommand.SelectNodes("*"))
                                    {
                                        if (CheckTests(tempAction, context.SoapMessage, context.SoapNamespaceManager))
                                        {
                                            // process nested action
                                            OKToSend = OKToSend && ExecuteAction(context, tempAction, action);
                                        }
                                    }
                                }
                                else if (CheckTests(actionCommand, context.SoapMessage, context.SoapNamespaceManager))
                                {
                                    // process action
                                    OKToSend = OKToSend && ExecuteAction(context, actionCommand, action);
                                }
                            }
                        }
                    }
                }
            }
            return OKToSend;
        }
コード例 #5
0
        protected virtual void SendApplication(XmlElement xeDestinationNode, EventRuleContext context)
        {
            // if we're looking at a "destinations" node, we should find info on delivery
            if (CheckTests(xeDestinationNode, context.SoapMessage, context.SoapNamespaceManager))
            {
                // timeout stuff here
                TimeSpan tsTimeout = TimeSpan.Zero;
                XmlElement xeTimeout = (XmlElement)xeDestinationNode.SelectSingleNode("timeout");
                if (xeTimeout != null)
                {
                    tsTimeout = new TimeSpan(
                        int.Parse("0" + GetParameter("days", xeTimeout, context.SoapMessage, context.SoapNamespaceManager)),
                        int.Parse("0" + GetParameter("hours", xeTimeout, context.SoapMessage, context.SoapNamespaceManager)),
                        int.Parse("0" + GetParameter("minutes", xeTimeout, context.SoapMessage, context.SoapNamespaceManager)),
                        int.Parse("0" + GetParameter("seconds", xeTimeout, context.SoapMessage, context.SoapNamespaceManager)),
                        int.Parse("0" + GetParameter("milliseconds", xeTimeout, context.SoapMessage, context.SoapNamespaceManager))
                        );
                    XmlElement SoapRouting = context.SoapMessage.CreateElement("soap", "Routing", SoapURN);
                    XmlElement SoapLabel = context.SoapMessage.CreateElement("soap", "Label", SoapURN);
                    SoapLabel.AppendChild(context.SoapMessage.CreateTextNode(context.Label));
                    SoapRouting.AppendChild(SoapLabel);
                    context.SoapMessage.SelectSingleNode("soap:Envelope", context.SoapNamespaceManager).AppendChild(SoapRouting);
                    foreach (XmlElement DestinationQueue in xeTimeout.SelectNodes("queue"))
                    {
                        if (CheckTests(DestinationQueue, context.SoapMessage, context.SoapNamespaceManager))
                        {
                            string QueuePath = GetParameter("", DestinationQueue, context.SoapMessage.SelectSingleNode("*"), context.SoapNamespaceManager);
                            //QueuePath = ResolveQueuePath(QueuePath, DestinationQueue, sIncomingQueueName);
                            //if (QueuePath != "")
                            //{
                            XmlElement DestinationNode = context.SoapMessage.CreateElement("soap", "Destination", SoapURN);
                            DestinationNode.AppendChild(context.SoapMessage.CreateTextNode("QueuePath")); // me
                            SoapRouting.AppendChild(DestinationNode);
                            //}
                        }
                    }
                }

                foreach (XmlElement DestinationQueue in xeDestinationNode.SelectNodes("queue"))
                {
                    // loop over all queues in the destination. All test conditions on the destinations element
                    // have already been performed so get the queue path.
                    string sQueuePath = GetParameter("", DestinationQueue, context.SoapMessage.SelectSingleNode("*"), context.SoapNamespaceManager).Trim();
                    if (Logger.IsInfoEnabled)
                    {
                        LogInfo("destination: {0}.", sQueuePath);
                    }

                    // If we actually have a path...
                    if (sQueuePath != "")
                    {
                        //sQueuePath = ResolveQueuePath(sQueuePath, DestinationQueue, sIncomingQueueName);
                        // Locate the queue we've settled on
                        //MessageQueue CorrectQueue = null;
                        //try
                        //{
                        //    CorrectQueue = FindQueue(sQueuePath);
                        //    // This would only be null if there's a catastrophic queue creation or naming error
                        //    if (CorrectQueue != null)
                        //    {
                        //        lock (CorrectQueue)
                        //        {
                        try
                        {
                            // The Last Queue is useful for running errors back through
                            context.SoapMessage.DocumentElement.RemoveAttribute("lastqueue");
                            if (!silent)
                            {
                                context.SoapMessage.DocumentElement.SetAttribute("lastqueue", sQueuePath);
                            }

                            // Create and send the message
                            //Message AppMessage = new Message();
                            //try
                            //{
                            //    //set timeout here
                            //    if (tsTimeout != TimeSpan.Zero)
                            //    {
                            //        AppMessage.TimeToBeReceived = tsTimeout;
                            //        AppMessage.UseDeadLetterQueue = true;
                            //    }
                            //    AppMessage.Body = context.SoapMessage.DocumentElement;
                            //    AppMessage.Label = context.Label;
                            //    AppMessage.Recoverable = true;
                            //    CorrectQueue.Send(AppMessage);
                            if (Logger.IsInfoEnabled)
                            {
                                LogInfo("sending message: {0}.", context.SoapMessage.DocumentElement.OuterXml);
                            }
                        }
                        finally
                        {
                            //AppMessage.Dispose();
                        }
                    }
                }
            }
        }
コード例 #6
0
 /// <remarks>
 /// Once the processing of a message is complete, it needs to be sent to the next
 /// component via another message queue.  SendApplication() does just that.  The
 /// message is sent out to each queue as specified by the configuration  At this 
 /// point a brief description of the queue naming system is merited:
 /// 
 /// All queues are by default expected to by Private queues on the local machine.  
 /// This is set via the _BaseQueue class level variable, which should be done in
 /// the inherited class configuration method.  The default _BaseQueue is:
 ///		".\\PRIVATE$\\Aggregator."
 /// 
 /// Message queue names consist of a path delineated by "." characters.  Thus,
 ///		".\\PRIVATE$\\Aggregator.Incoming.Complete.AutoLoan"
 ///	is a typical queue name.  By default, when outputing to a queue, the name of the
 ///	queue is determined by apending a new name onto the incoming queue.  Thus, if a
 ///	step of the process outputs to "Processed" and the incoming queue was the one
 ///	specified above, then the message would be output to:
 ///		".\\PRIVATE$\\Aggregator.Incoming.Complete.AutoLoan.Processed"
 ///	This allows "queue affinity".  Suppose we have some step which is very generic, and
 ///	executed on several different queues.  This step defines it's output queue as "C"
 ///	and listens to queues "A" and "B".  With an absolute path, the results would be put
 ///	out to queue "C".  However, with relative paths, the results go out to either "A.C"
 ///	or "B.C", thus it's tied to the incoming queue.
 ///	
 ///	The same logic applies as the number of incoming and outgoing queues increases.  If 
 ///	this same process listens to queues "A", "B", and "C" and outputs to queues "D" and 
 ///	"E", then the results would be output to ("A.D" and "A.E") or ("B.D" and "B.E") or 
 ///	("C.D" and "C.E").
 ///	
 ///	This behavior can be overridden by specifying that the output queue is an absolute 
 ///	path.
 /// 
 /// This routine may be overridden as necessary, though it is not recommended.
 /// </remarks>
 protected virtual void SendApplication(EventRuleContext context)
 {
     // Gotta look at all nodes so we catch any XSL
     // Note, this is uber-gay and needs to be done differently.  Maybe XSL in the
     // destinations, but that breaks some aspects of the overall schema
     foreach (XmlElement ChildElement in ruleNode.SelectNodes("*"))
     {
         XmlElement xeDestination = ChildElement;
         // If this is XSL, transform it and use that as our context
         if (xeDestination.Name == "xsl:stylesheet")
         {
             xeDestination = Transform(context.SoapMessage, ChildElement);
         }
         if (xeDestination.Name == "destinations")
         {
             SendApplication(xeDestination, context);
         }
     }
 }
コード例 #7
0
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// <param name="Action"></param>
        /// <param name="ActionParent"></param>
        /// 
        /// <returns></returns>
        /// 
        public virtual bool ExecuteAction(EventRuleContext context, XmlElement InnerAction, XmlElement ActionParent)
        {
            XmlElement NewChunk = null;
            string UpdateMessage = "";

            Exception Error = null;

            int retryCount = 1;

            // Find out how many times to try this action in case of exception (default is 1)
            if (ActionParent != null && ActionParent.GetAttributeNode("retrycount") != null)
            {
                try
                {
                    retryCount = int.Parse(ActionParent.GetAttribute("retrycount"));
                }
                catch
                {
                }
            }

            // Try to process the application
            for (int x = 0; x < retryCount; x++)
            {
                try
                {
                    Error = null;
                    NewChunk = ProcessApplication(context, InnerAction, ref UpdateMessage);
                    break;
                }
                catch (Exception exception)
                {
                    Error = exception;
                    if (Logger.IsErrorEnabled)
                    {
                        LogError(exception, "failed to process application: {0}.", exception.Message);
                    }
                }
            }

            if (Error != null)
            {
                // If there were errors all [RetryCount] times, send an error message
                //Error.Send(_ErrorQueueName);
                //MonitorSend(MessageType.Error, "", _ErrorQueueName, null);
                return (ActionParent.GetAttribute("failure") == "continue");
            }
            else
            {
                // If it succeeded at all...
                string IncomingQueuePath = "";

                //if (IncomingQueue != null)
                //{
                //    IncomingQueuePath = IncomingQueue.Path;
                //}

                // if there was data back, stamp it in the app
                if (NewChunk != null)
                {
                    // Console.WriteLine("CHUNK: " + NewChunk.OuterXml);

                    string actionId = null;
                    bool blankDatasetId = false;

                    if (ActionParent != null)
                    {
                        actionId = ActionParent.GetAttribute("id");
                        if (ActionParent.HasAttribute("allowblankdatasetid"))
                        {
                            try
                            {
                                blankDatasetId = Convert.ToBoolean(ActionParent.GetAttribute("allowblankdatasetid"));
                            }
                            catch
                            {
                                //ignore, default to false
                            }
                        }
                    }
                    StampApplication(context, actionId, blankDatasetId, UpdateMessage, IncomingQueuePath, NewChunk, true, (ActionParent.GetAttribute("results").ToLower() != "ignore"));
                }
                return true;
            }
        }
コード例 #8
0
        /// <summary>
        /// Stamps the application with Header information and associates that with the data
        /// being added to the application.
        /// </summary>
        /// 
        /// <param name="SoapMessage">The Application</param>
        /// <param name="SoapNamespaceManager">Namespace Manager for the Application</param>
        /// <param name="ActionID">ID for this action</param>
        /// <param name="bBlankDatasetID">A flag that says whether to allow a blank dataset ID</param>
        /// <param name="UpdateMessage">Components Message about what was done</param>
        /// <param name="IncomingQueuePath">Queue this message was read from</param>
        /// <param name="NewChunk">The chunk to add to the application</param>
        /// <param name="WriteHeader">Should the header be written</param>
        /// <param name="WriteData">Should the data be written</param>
        /// 
        /// <returns></returns>
        /// 
        public XmlElement StampApplication(EventRuleContext context, string ActionID, bool bBlankDatasetID, string UpdateMessage, string IncomingQueuePath, XmlNode NewChunk, bool WriteHeader, bool WriteData)
        {
            // Don't bother if the app doesn't exist
            if (context.SoapMessage != null)
            {
                if (ActionID == null)
                {
                    ActionID = "";
                }
                if (ActionID == "" && !bBlankDatasetID)
                {
                    ActionID = "[Unspecified]";
                }

                // Set an index so this ActionID can be uniquely identified
                int Index = context.SoapMessage.SelectNodes("/soap:Envelope/soap:Body/dataset[@id='" + ActionID + "']", context.SoapNamespaceManager).Count + 1;

                // Try to write the header data
                int ActorID = -1;
                if (WriteHeader)
                {
                    ActorID = MarkUsersApplication(context.SoapMessage, context.SoapNamespaceManager, UpdateMessage, IncomingQueuePath);
                }
                // Try to write the NewChunk
                if (WriteData)
                {
                    XmlElement NewDataSet = context.SoapMessage.CreateElement("dataset");
                    NewDataSet.SetAttribute("id", ActionID);
                    NewDataSet.SetAttribute("index", Index.ToString());
                    NewDataSet.SetAttribute("tool", ruleName);
                    // If there was no actor, don't write the attribute
                    if (ActorID > 0)
                    {
                        NewDataSet.SetAttribute("actor", ActorID.ToString());
                    }
                    // If there was actually a new chunk, slap it in there
                    if (NewChunk != null)
                    {
                        try
                        {
                            XmlNode xnNamespacesStripped = NewDataSet.OwnerDocument.ReadNode(new XmlTextReader(RemoveNamespaces(NewChunk), XmlNodeType.Element, null));
                            NewDataSet.AppendChild(xnNamespacesStripped);
                        }
                        catch (Exception exx)
                        {
                            //ReportErrorNow(SoapMessage, exx);
                            NewDataSet.AppendChild(NewDataSet.OwnerDocument.ImportNode(NewChunk, true));
                        }
                    }
                    // Add to the Soap Message
                    XmlNode Target = context.SoapMessage.SelectSingleNode("/soap:Envelope/soap:Body", context.SoapNamespaceManager);
                    if (Target == null)
                    {
                        Target = context.SoapMessage.DocumentElement;
                    }
                    Target.AppendChild(NewDataSet);
                    return NewDataSet;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }
コード例 #9
0
 /// <summary>
 /// ProcessApplication() is the heart of the processing of individual messages.  It takes
 /// the original message along with the appropriate action node from the config file.  It
 /// uses these to create a third XML document which specifies how to handle the message.
 /// Finally, it creates an optional XML fragment.  This fragment is then integrated into
 /// the SOAP message so that the results are available during later processes
 /// 
 /// This routine is expected to be overridden.
 /// </summary>
 /// 
 public abstract XmlElement ProcessApplication(EventRuleContext context, XmlElement ActionNode, ref string Actions);