Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / PolicyImportHelper.cs
1 //
2 // PolicyImportHelper.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 using System;
27 using System.Xml;
28 using System.Collections.Generic;
29 using System.ServiceModel.Description;
30
31 using QName = System.Xml.XmlQualifiedName;
32
33 namespace System.ServiceModel.Channels {
34
35         internal static class PolicyImportHelper {
36
37                 internal const string SecurityPolicyNS = "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy";
38                 internal const string PolicyNS = "http://schemas.xmlsoap.org/ws/2004/09/policy";
39                 internal const string MimeSerializationNS = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
40                 internal const string HttpAuthNS = "http://schemas.microsoft.com/ws/06/2004/policy/http";
41
42                 internal const string FramingPolicyNS = "http://schemas.microsoft.com/ws/2006/05/framing/policy";
43                 internal const string NetBinaryEncodingNS = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1";
44
45                 internal const string WSSecurityNS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
46
47                 internal static XmlElement GetTransportBindingPolicy (PolicyAssertionCollection collection)
48                 {
49                         return FindAndRemove (collection, "TransportBinding", SecurityPolicyNS);
50                 }
51                         
52                 internal static XmlElement GetStreamedMessageFramingPolicy (PolicyAssertionCollection collection)
53                 {
54                         return FindAndRemove (collection, "Streamed", FramingPolicyNS); 
55                 }
56
57                 internal static XmlElement GetBinaryMessageEncodingPolicy (PolicyAssertionCollection collection)
58                 {
59                         return FindAndRemove (collection, "BinaryEncoding", NetBinaryEncodingNS);
60                 }
61
62                 internal static XmlElement GetMtomMessageEncodingPolicy (PolicyAssertionCollection collection)
63                 {
64                         return FindAndRemove (collection, "OptimizedMimeSerialization", MimeSerializationNS);
65                 }
66
67                 static XmlElement FindAndRemove (PolicyAssertionCollection collection, string name, string ns)
68                 {
69                         var element = collection.Find (name, ns);
70                         if (element != null)
71                                 collection.Remove (element);
72                         return element;
73                 }
74
75                 internal static List<XmlElement> FindAssertionByNS (
76                         PolicyAssertionCollection collection, string ns)
77                 {
78                         var list = new List<XmlElement> ();
79                         foreach (var assertion in collection) {
80                                 if (assertion.NamespaceURI.Equals (ns))
81                                         list.Add (assertion);
82                         }
83                         return list;
84                 }
85
86                 internal static List<XmlElement> GetPolicyElements (XmlElement root, out bool error)
87                 {
88                         XmlElement policy = null;
89                         var list = new List<XmlElement> ();
90
91                         foreach (var node in root.ChildNodes) {
92                                 var e = node as XmlElement;
93                                 if (e == null)
94                                         continue;
95                                 if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) {
96                                         error = true;
97                                         return list;
98                                 }
99                                 if (policy != null) {
100                                         error = true;
101                                         return list;
102                                 }
103                                 policy = e;
104                         }
105
106                         if (policy == null) {
107                                 error = true;
108                                 return list;
109                         }
110
111                         foreach (var node in policy.ChildNodes) {
112                                 var e = node as XmlElement;
113                                 if (e != null)
114                                         list.Add (e);
115                         }
116
117                         error = false;
118                         return list;
119                 }
120
121                 internal static bool FindPolicyElement (MetadataImporter importer, XmlElement root,
122                                                         QName name, bool required, bool removeWhenFound,
123                                                         out XmlElement element)
124                 {
125                         if (!FindPolicyElement (root, name, removeWhenFound, out element)) {
126                                 importer.AddWarning ("Invalid policy element: {0}", root.OuterXml);
127                                 return false;
128                         }
129                         if (required && (element == null)) {
130                                 importer.AddWarning ("Did not find policy element `{0}'.", name);
131                                 return false;
132                         }
133                         return true;
134                 }
135
136                 internal static bool FindPolicyElement (XmlElement root, QName name,
137                                                         bool removeWhenFound, out XmlElement element)
138                 {
139                         XmlElement policy = null;
140                         foreach (var node in root.ChildNodes) {
141                                 var e = node as XmlElement;
142                                 if (e == null)
143                                         continue;
144                                 if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) {
145                                         element = null;
146                                         return false;
147                                 }
148                                 if (policy != null) {
149                                         element = null;
150                                         return false;
151                                 }
152                                 policy = e;
153                         }
154
155                         if (policy == null) {
156                                 element = null;
157                                 return true;
158                         }
159
160                         element = null;
161                         foreach (var node in policy.ChildNodes) {
162                                 var e = node as XmlElement;
163                                 if (e == null)
164                                         continue;
165                                 if (!name.Namespace.Equals (e.NamespaceURI) || !name.Name.Equals (e.LocalName))
166                                         continue;
167
168                                 element = e;
169                                 break;
170                         }
171
172                         if (!removeWhenFound || (element == null))
173                                 return true;
174
175                         policy.RemoveChild (element);
176
177                         bool foundAnother = false;
178                         foreach (var node in policy.ChildNodes) {
179                                 var e = node as XmlElement;
180                                 if (e != null) {
181                                         foundAnother = true;
182                                         break;
183                                 }
184                         }
185
186                         if (!foundAnother)
187                                 root.RemoveChild (policy);
188                         return true;
189                 }
190
191                 internal static XmlElement GetElement (MetadataImporter importer,
192                                                        XmlElement root, string name, string ns)
193                 {
194                         return GetElement (importer, root, name, ns, false);
195                 }
196
197                 internal static XmlElement GetElement (MetadataImporter importer,
198                                                        XmlElement root, string name, string ns,
199                                                        bool required)
200                 {
201                         return GetElement (importer, root, new QName (name, ns), required);
202                 }
203
204                 internal static XmlElement GetElement (MetadataImporter importer,
205                                                        XmlElement root, QName name, bool required)
206                 {
207                         var list = root.GetElementsByTagName (name.Name, name.Namespace);
208                         if (list.Count < 1) {
209                                 if (required)
210                                         importer.AddWarning ("Did not find required policy element `{0}'", name);
211                                 return null;
212                         }
213
214                         if (list.Count > 1) {
215                                 importer.AddWarning ("Found duplicate policy element `{0}'", name);
216                                 return null;
217                         }
218
219                         var element = list [0] as XmlElement;
220                         if (required && (element == null))
221                                 importer.AddWarning ("Did not find required policy element `{0}'", name);
222                         return element;
223                 }
224
225                 internal static XmlElement WrapPolicy (XmlElement element)
226                 {
227                         var policy = element.OwnerDocument.CreateElement ("wsp", "Policy", PolicyNS);
228                         policy.AppendChild (element);
229                         return policy;
230                 }
231
232                 //
233                 // Add a single element, wrapping it inside <wsp:Policy>
234                 //
235                 internal static void AddWrappedPolicyElement (XmlElement root, XmlElement element)
236                 {
237                         if (root.OwnerDocument != element.OwnerDocument)
238                                 element = (XmlElement)root.OwnerDocument.ImportNode (element, true);
239                         if (!element.NamespaceURI.Equals (PolicyNS) || !element.LocalName.Equals ("Policy"))
240                                 element = WrapPolicy (element);
241                         root.AppendChild (element);
242                 }
243
244                 //
245                 // Add multiple elements, wrapping them inside a single <wsp:Policy>
246                 //
247                 internal static void AddWrappedPolicyElements (XmlElement root, params XmlElement[] elements)
248                 {
249                         var policy = root.OwnerDocument.CreateElement ("wsp", "Policy", PolicyNS);
250                         root.AppendChild (policy);
251
252                         foreach (var element in elements) {
253                                 XmlElement imported;
254                                 if (root.OwnerDocument != element.OwnerDocument)
255                                         imported = (XmlElement)root.OwnerDocument.ImportNode (element, true);
256                                 else
257                                         imported = element;
258                                 policy.AppendChild (element);
259                         }
260                 }
261         }
262 }
263