1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 5 namespace System.ServiceModel.Security 6 { 7 using System.Collections.Generic; 8 using System.ServiceModel.Channels; 9 using System.ServiceModel; 10 using System.Runtime.Serialization; 11 using System.ServiceModel.Security; 12 using System.Xml; 13 14 public class ScopedMessagePartSpecification 15 { 16 MessagePartSpecification channelParts; 17 Dictionary<string, MessagePartSpecification> actionParts; 18 Dictionary<string, MessagePartSpecification> readOnlyNormalizedActionParts; 19 bool isReadOnly; 20 ScopedMessagePartSpecification()21 public ScopedMessagePartSpecification() 22 { 23 this.channelParts = new MessagePartSpecification(); 24 this.actionParts = new Dictionary<string, MessagePartSpecification>(); 25 } 26 27 public ICollection<string> Actions 28 { 29 get 30 { 31 return this.actionParts.Keys; 32 } 33 } 34 35 public MessagePartSpecification ChannelParts 36 { 37 get 38 { 39 return this.channelParts; 40 } 41 } 42 43 public bool IsReadOnly 44 { 45 get 46 { 47 return this.isReadOnly; 48 } 49 } 50 ScopedMessagePartSpecification(ScopedMessagePartSpecification other)51 public ScopedMessagePartSpecification(ScopedMessagePartSpecification other) 52 : this() 53 { 54 if (other == null) 55 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("other")); 56 57 this.channelParts.Union(other.channelParts); 58 if (other.actionParts != null) 59 { 60 foreach (string action in other.actionParts.Keys) 61 { 62 MessagePartSpecification p = new MessagePartSpecification(); 63 p.Union(other.actionParts[action]); 64 this.actionParts[action] = p; 65 } 66 } 67 } 68 ScopedMessagePartSpecification(ScopedMessagePartSpecification other, bool newIncludeBody)69 internal ScopedMessagePartSpecification(ScopedMessagePartSpecification other, bool newIncludeBody) 70 : this(other) 71 { 72 this.channelParts.IsBodyIncluded = newIncludeBody; 73 foreach (string action in this.actionParts.Keys) 74 this.actionParts[action].IsBodyIncluded = newIncludeBody; 75 } 76 AddParts(MessagePartSpecification parts)77 public void AddParts(MessagePartSpecification parts) 78 { 79 if (parts == null) 80 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parts")); 81 82 ThrowIfReadOnly(); 83 84 this.channelParts.Union(parts); 85 } 86 AddParts(MessagePartSpecification parts, string action)87 public void AddParts(MessagePartSpecification parts, string action) 88 { 89 if (action == null) 90 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("action")); 91 if (parts == null) 92 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parts")); 93 94 ThrowIfReadOnly(); 95 96 if (!this.actionParts.ContainsKey(action)) 97 this.actionParts[action] = new MessagePartSpecification(); 98 this.actionParts[action].Union(parts); 99 } 100 AddParts(MessagePartSpecification parts, XmlDictionaryString action)101 internal void AddParts(MessagePartSpecification parts, XmlDictionaryString action) 102 { 103 if (action == null) 104 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("action")); 105 AddParts(parts, action.Value); 106 } 107 IsEmpty()108 internal bool IsEmpty() 109 { 110 bool result; 111 if (!channelParts.IsEmpty()) 112 { 113 result = false; 114 } 115 else 116 { 117 result = true; 118 foreach (string action in this.Actions) 119 { 120 MessagePartSpecification parts; 121 if (TryGetParts(action, true, out parts)) 122 { 123 if (!parts.IsEmpty()) 124 { 125 result = false; 126 break; 127 } 128 } 129 } 130 } 131 132 return result; 133 } 134 TryGetParts(string action, bool excludeChannelScope, out MessagePartSpecification parts)135 public bool TryGetParts(string action, bool excludeChannelScope, out MessagePartSpecification parts) 136 { 137 if (action == null) 138 action = MessageHeaders.WildcardAction; 139 parts = null; 140 141 if (this.isReadOnly) 142 { 143 if (this.readOnlyNormalizedActionParts.ContainsKey(action)) 144 if (excludeChannelScope) 145 parts = this.actionParts[action]; 146 else 147 parts = this.readOnlyNormalizedActionParts[action]; 148 } 149 else if (this.actionParts.ContainsKey(action)) 150 { 151 MessagePartSpecification p = new MessagePartSpecification(); 152 p.Union(this.actionParts[action]); 153 if (!excludeChannelScope) 154 p.Union(this.channelParts); 155 parts = p; 156 } 157 158 return parts != null; 159 } 160 CopyTo(ScopedMessagePartSpecification target)161 internal void CopyTo(ScopedMessagePartSpecification target) 162 { 163 if (target == null) 164 { 165 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("target"); 166 } 167 target.ChannelParts.IsBodyIncluded = this.ChannelParts.IsBodyIncluded; 168 foreach (XmlQualifiedName headerType in ChannelParts.HeaderTypes) 169 { 170 if (!target.channelParts.IsHeaderIncluded(headerType.Name, headerType.Namespace)) 171 { 172 target.ChannelParts.HeaderTypes.Add(headerType); 173 } 174 } 175 foreach (string action in this.actionParts.Keys) 176 { 177 target.AddParts(this.actionParts[action], action); 178 } 179 } 180 TryGetParts(string action, out MessagePartSpecification parts)181 public bool TryGetParts(string action, out MessagePartSpecification parts) 182 { 183 return this.TryGetParts(action, false, out parts); 184 } 185 MakeReadOnly()186 public void MakeReadOnly() 187 { 188 if (!this.isReadOnly) 189 { 190 this.readOnlyNormalizedActionParts = new Dictionary<string, MessagePartSpecification>(); 191 foreach (string action in this.actionParts.Keys) 192 { 193 MessagePartSpecification p = new MessagePartSpecification(); 194 p.Union(this.actionParts[action]); 195 p.Union(this.channelParts); 196 p.MakeReadOnly(); 197 this.readOnlyNormalizedActionParts[action] = p; 198 } 199 this.isReadOnly = true; 200 } 201 } 202 ThrowIfReadOnly()203 void ThrowIfReadOnly() 204 { 205 if (this.isReadOnly) 206 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly))); 207 } 208 } 209 } 210