1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Security
6 {
7     using System.Xml;
8     using System.ServiceModel.Channels;
9     using System.ServiceModel;
10     using System.Collections.Generic;
11     using System.Collections.ObjectModel;
12     using System.Runtime.Serialization;
13 
14     public class MessagePartSpecification
15     {
16         List<XmlQualifiedName> headerTypes;
17         bool isBodyIncluded;
18         bool isReadOnly;
19         static MessagePartSpecification noParts;
20 
21         public ICollection<XmlQualifiedName> HeaderTypes
22         {
23             get
24             {
25                 if (headerTypes == null)
26                 {
27                     headerTypes = new List<XmlQualifiedName>();
28                 }
29 
30                 if (isReadOnly)
31                 {
32                     return new ReadOnlyCollection<XmlQualifiedName>(headerTypes);
33                 }
34                 else
35                 {
36                     return headerTypes;
37                 }
38             }
39         }
40 
41         internal bool HasHeaders
42         {
43             get { return this.headerTypes != null && this.headerTypes.Count > 0; }
44         }
45 
46         public bool IsBodyIncluded
47         {
48             get
49             {
50                 return this.isBodyIncluded;
51             }
52             set
53             {
54                 if (isReadOnly)
55                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
56 
57                 this.isBodyIncluded = value;
58             }
59         }
60 
61         public bool IsReadOnly
62         {
63             get
64             {
65                 return this.isReadOnly;
66             }
67         }
68 
69         static public MessagePartSpecification NoParts
70         {
71             get
72             {
73                 if (noParts == null)
74                 {
75                     MessagePartSpecification parts = new MessagePartSpecification();
76                     parts.MakeReadOnly();
77                     noParts = parts;
78                 }
79                 return noParts;
80             }
81         }
82 
Clear()83         public void Clear()
84         {
85             if (isReadOnly)
86                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
87 
88             if (this.headerTypes != null)
89                 this.headerTypes.Clear();
90             this.isBodyIncluded = false;
91         }
92 
Union(MessagePartSpecification specification)93         public void Union(MessagePartSpecification specification)
94         {
95             if (isReadOnly)
96                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
97             if (specification == null)
98                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("specification");
99 
100             this.isBodyIncluded |= specification.IsBodyIncluded;
101 
102             List<XmlQualifiedName> headerTypes = specification.headerTypes;
103             if (headerTypes != null && headerTypes.Count > 0)
104             {
105                 if (this.headerTypes == null)
106                 {
107                     this.headerTypes = new List<XmlQualifiedName>(headerTypes.Count);
108                 }
109 
110                 for (int i = 0; i < headerTypes.Count; i++)
111                 {
112                     XmlQualifiedName qname = headerTypes[i];
113                     this.headerTypes.Add(qname);
114                 }
115             }
116         }
117 
MakeReadOnly()118         public void MakeReadOnly()
119         {
120             if (isReadOnly)
121                 return;
122 
123             if (this.headerTypes != null)
124             {
125                 List<XmlQualifiedName> noDuplicates = new List<XmlQualifiedName>(headerTypes.Count);
126                 for (int i = 0; i < headerTypes.Count; i++)
127                 {
128                     XmlQualifiedName qname = headerTypes[i];
129                     if (qname != null)
130                     {
131                         bool include = true;
132                         for (int j = 0; j < noDuplicates.Count; j++)
133                         {
134                             XmlQualifiedName qname1 = noDuplicates[j];
135 
136                             if (qname.Name == qname1.Name && qname.Namespace == qname1.Namespace)
137                             {
138                                 include = false;
139                                 break;
140                             }
141                         }
142 
143                         if (include)
144                             noDuplicates.Add(qname);
145                     }
146                 }
147 
148                 this.headerTypes = noDuplicates;
149             }
150 
151             this.isReadOnly = true;
152         }
153 
MessagePartSpecification()154         public MessagePartSpecification()
155         {
156             // empty
157         }
158 
MessagePartSpecification(bool isBodyIncluded)159         public MessagePartSpecification(bool isBodyIncluded)
160         {
161             this.isBodyIncluded = isBodyIncluded;
162         }
163 
MessagePartSpecification(params XmlQualifiedName[] headerTypes)164         public MessagePartSpecification(params XmlQualifiedName[] headerTypes)
165             : this(false, headerTypes)
166         {
167             // empty
168         }
169 
MessagePartSpecification(bool isBodyIncluded, params XmlQualifiedName[] headerTypes)170         public MessagePartSpecification(bool isBodyIncluded, params XmlQualifiedName[] headerTypes)
171         {
172             this.isBodyIncluded = isBodyIncluded;
173             if (headerTypes != null && headerTypes.Length > 0)
174             {
175                 this.headerTypes = new List<XmlQualifiedName>(headerTypes.Length);
176                 for (int i = 0; i < headerTypes.Length; i++)
177                 {
178                     this.headerTypes.Add(headerTypes[i]);
179                 }
180             }
181         }
182 
IsHeaderIncluded(MessageHeader header)183         internal bool IsHeaderIncluded(MessageHeader header)
184         {
185             if (header == null)
186                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("header");
187 
188             return IsHeaderIncluded(header.Name, header.Namespace);
189         }
190 
IsHeaderIncluded(string name, string ns)191         internal bool IsHeaderIncluded(string name, string ns)
192         {
193             if (name == null)
194                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
195             if (ns == null)
196                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns");
197 
198             if (this.headerTypes != null)
199             {
200                 for (int i = 0; i < this.headerTypes.Count; i++)
201                 {
202                     XmlQualifiedName qname = this.headerTypes[i];
203                     // Name is an optional attribute. If not present, compare with only the namespace.
204                     if (String.IsNullOrEmpty(qname.Name))
205                     {
206                         if (qname.Namespace == ns)
207                         {
208                             return true;
209                         }
210                     }
211                     else
212                     {
213                         if (qname.Name == name && qname.Namespace == ns)
214                         {
215                             return true;
216                         }
217                     }
218                 }
219             }
220 
221             return false;
222         }
223 
IsEmpty()224         internal bool IsEmpty()
225         {
226             if (this.headerTypes != null && this.headerTypes.Count > 0)
227                 return false;
228 
229             return !this.IsBodyIncluded;
230         }
231     }
232 }
233