File: System\ServiceModel\Dispatcher\MessageFilter.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{
    using System;
    using System.ServiceModel.Channels;
    using System.ServiceModel;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Runtime.Serialization;
    using System.ServiceModel.Diagnostics;
    using System.Runtime;
    /// <summary>
    /// Abstract base class for different classes of message filters
    /// </summary>
    [DataContract]
    [KnownType(typeof(XPathMessageFilter))]
    [KnownType(typeof(ActionMessageFilter))]
    [KnownType(typeof(MatchAllMessageFilter))]
    [KnownType(typeof(MatchNoneMessageFilter))]
    //[KnownType(typeof(EndpointAddressMessageFilter))]
    [Fx.Tag.XamlVisible(true)]
    public abstract class MessageFilter
    {
        protected MessageFilter()
        {
        }
 
        protected internal virtual IMessageFilterTable<FilterData> CreateFilterTable<FilterData>()
        {
            return null;
        }
 
        /// <summary>
        /// Tests whether the filter matches the given message.
        /// </summary>                
        public abstract bool Match(MessageBuffer buffer);
 
        /// <summary>
        /// Tests whether the filter matches the given message without examining its body.
        /// Note: since this method never probes the message body, it should NOT close the message
        /// If the filter probes the message body, then the filter must THROW an Exception. The filter should not return false
        /// This is deliberate - we don't want to produce false positives. 
        /// </summary>
        public abstract bool Match(Message message);
    }
 
    internal class SequentialMessageFilterTable<FilterData> : IMessageFilterTable<FilterData>
    {
        Dictionary<MessageFilter, FilterData> filters;
 
        public SequentialMessageFilterTable()
        {
            this.filters = new Dictionary<MessageFilter, FilterData>();
        }
 
        //
        // IMessageFilterTable<FilterData> methods
        //
 
        public int Count
        {
            get
            {
                return this.filters.Count;
            }
        }
 
        public void Clear()
        {
            this.filters.Clear();
        }
 
        public bool GetMatchingValue(Message message, out FilterData data)
        {
            bool dataSet = false;
            MessageFilter filter = null;
            data = default(FilterData);
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(message))
                {
                    if (dataSet)
                    {
                        Collection<MessageFilter> f = new Collection<MessageFilter>();
                        f.Add(filter);
                        f.Add(item.Key);
                        throw TraceUtility.ThrowHelperError(new MultipleFilterMatchesException(SR.GetString(SR.FilterMultipleMatches), null, f), message);
                    }
 
                    filter = item.Key;
                    data = item.Value;
                    dataSet = true;
                }
            }
 
            return dataSet;
        }
 
        public bool GetMatchingValue(MessageBuffer buffer, out FilterData data)
        {
            bool dataSet = false;
            MessageFilter filter = null;
            data = default(FilterData);
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(buffer))
                {
                    if (dataSet)
                    {
                        Collection<MessageFilter> f = new Collection<MessageFilter>();
                        f.Add(filter);
                        f.Add(item.Key);
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MultipleFilterMatchesException(SR.GetString(SR.FilterMultipleMatches), null, f));
                    }
 
                    filter = item.Key;
                    data = item.Value;
                    dataSet = true;
                }
            }
 
            return dataSet;
        }
 
        public bool GetMatchingValues(Message message, ICollection<FilterData> results)
        {
            int count = results.Count;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(message))
                {
                    results.Add(item.Value);
                }
            }
            return count != results.Count;
        }
 
        public bool GetMatchingValues(MessageBuffer buffer, ICollection<FilterData> results)
        {
            int count = results.Count;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(buffer))
                {
                    results.Add(item.Value);
                }
            }
            return count != results.Count;
        }
 
        public bool GetMatchingFilter(Message message, out MessageFilter filter)
        {
            filter = null;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(message))
                {
                    if (filter != null)
                    {
                        Collection<MessageFilter> f = new Collection<MessageFilter>();
                        f.Add(filter);
                        f.Add(item.Key);
                        throw TraceUtility.ThrowHelperError(new MultipleFilterMatchesException(SR.GetString(SR.FilterMultipleMatches), null, f), message);
                    }
 
                    filter = item.Key;
                }
            }
 
            return filter != null;
        }
 
        public bool GetMatchingFilter(MessageBuffer buffer, out MessageFilter filter)
        {
            filter = null;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(buffer))
                {
                    if (filter != null)
                    {
                        Collection<MessageFilter> f = new Collection<MessageFilter>();
                        f.Add(filter);
                        f.Add(item.Key);
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MultipleFilterMatchesException(SR.GetString(SR.FilterMultipleMatches), null, f));
                    }
 
                    filter = item.Key;
                }
            }
 
            return filter != null;
        }
 
        public bool GetMatchingFilters(Message message, ICollection<MessageFilter> results)
        {
            int count = results.Count;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(message))
                {
                    results.Add(item.Key);
                }
            }
            return count != results.Count;
        }
 
        public bool GetMatchingFilters(MessageBuffer buffer, ICollection<MessageFilter> results)
        {
            int count = results.Count;
            foreach (KeyValuePair<MessageFilter, FilterData> item in this.filters)
            {
                if (item.Key.Match(buffer))
                {
                    results.Add(item.Key);
                }
            }
            return count != results.Count;
        }
 
        //
        // IDictionary<MessageFilter,FilterData> methods
        //   
 
        public FilterData this[MessageFilter key]
        {
            get
            {
                return this.filters[key];
            }
            set
            {
                this.filters[key] = value;
            }
        }
 
        public ICollection<MessageFilter> Keys
        {
            get
            {
                return this.filters.Keys;
            }
        }
 
        public ICollection<FilterData> Values
        {
            get
            {
                return this.filters.Values;
            }
        }
 
        public bool ContainsKey(MessageFilter key)
        {
            return this.filters.ContainsKey(key);
        }
 
        public void Add(MessageFilter key, FilterData value)
        {
            this.filters.Add(key, value);
        }
 
        public bool Remove(MessageFilter key)
        {
            return this.filters.Remove(key);
        }
 
        //
        // ICollection<KeyValuePair<MessageFilter,FilterData>> methods
        //
 
        bool ICollection<KeyValuePair<MessageFilter, FilterData>>.IsReadOnly
        {
            get
            {
                return false;
            }
        }
 
        void ICollection<KeyValuePair<MessageFilter, FilterData>>.Add(KeyValuePair<MessageFilter, FilterData> item)
        {
            ((ICollection<KeyValuePair<MessageFilter, FilterData>>)this.filters).Add(item);
        }
 
        bool ICollection<KeyValuePair<MessageFilter, FilterData>>.Contains(KeyValuePair<MessageFilter, FilterData> item)
        {
            return ((ICollection<KeyValuePair<MessageFilter, FilterData>>)this.filters).Contains(item);
        }
 
        void ICollection<KeyValuePair<MessageFilter, FilterData>>.CopyTo(KeyValuePair<MessageFilter, FilterData>[] array, int arrayIndex)
        {
            ((ICollection<KeyValuePair<MessageFilter, FilterData>>)this.filters).CopyTo(array, arrayIndex);
        }
 
        bool ICollection<KeyValuePair<MessageFilter, FilterData>>.Remove(KeyValuePair<MessageFilter, FilterData> item)
        {
            return ((ICollection<KeyValuePair<MessageFilter, FilterData>>)this.filters).Remove(item);
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<KeyValuePair<MessageFilter, FilterData>>)this).GetEnumerator();
        }
 
        IEnumerator<KeyValuePair<MessageFilter, FilterData>> IEnumerable<KeyValuePair<MessageFilter, FilterData>>.GetEnumerator()
        {
            return ((ICollection<KeyValuePair<MessageFilter, FilterData>>)this.filters).GetEnumerator();
        }
 
        public bool TryGetValue(MessageFilter filter, out FilterData data)
        {
            return this.filters.TryGetValue(filter, out data);
        }
    }
}