2008-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Description / ExtensionManager.cs
1 // 
2 // System.Web.Services.Description.ExtensionManager.cs
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // Copyright (C) 2003 Ximian, Inc.
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Reflection;
32 using System.Collections;
33 using System.Web.Services.Configuration;
34 using System.Xml.Serialization;
35 using System.Xml;
36
37 namespace System.Web.Services.Description 
38 {
39         internal abstract class ExtensionManager 
40         {
41                 static Hashtable extensionsByName;
42                 static Hashtable extensionsByType;
43                 static ArrayList maps = new ArrayList ();
44                 static ArrayList extensions = new ArrayList ();
45
46                 static ExtensionManager ()
47                 {
48                         extensionsByName = new Hashtable ();
49                         extensionsByType = new Hashtable ();
50
51                         RegisterExtensionType (typeof (HttpAddressBinding));
52                         RegisterExtensionType (typeof (HttpBinding));
53                         RegisterExtensionType (typeof (HttpOperationBinding));
54                         RegisterExtensionType (typeof (HttpUrlEncodedBinding));
55                         RegisterExtensionType (typeof (HttpUrlReplacementBinding));
56                         RegisterExtensionType (typeof (MimeContentBinding));
57                         RegisterExtensionType (typeof (MimeMultipartRelatedBinding));
58                         RegisterExtensionType (typeof (MimeTextBinding));
59                         RegisterExtensionType (typeof (MimeXmlBinding));
60                         RegisterExtensionType (typeof (SoapAddressBinding));
61                         RegisterExtensionType (typeof (SoapBinding));
62                         RegisterExtensionType (typeof (SoapBodyBinding));
63                         RegisterExtensionType (typeof (SoapFaultBinding));
64                         RegisterExtensionType (typeof (SoapHeaderBinding));
65 //                      RegisterExtensionType (typeof (SoapHeaderFaultBinding));
66                         RegisterExtensionType (typeof (SoapOperationBinding));
67 #if NET_2_0
68                         RegisterExtensionType (typeof (Soap12AddressBinding));
69                         RegisterExtensionType (typeof (Soap12Binding));
70                         RegisterExtensionType (typeof (Soap12BodyBinding));
71                         RegisterExtensionType (typeof (Soap12FaultBinding));
72                         RegisterExtensionType (typeof (Soap12HeaderBinding));
73                         RegisterExtensionType (typeof (Soap12OperationBinding));
74
75                         foreach (TypeElement el in WebServicesSection.Current.ServiceDescriptionFormatExtensionTypes)
76                                 RegisterExtensionType (el.Type);
77 #else
78                         foreach (Type type in WSConfig.Instance.FormatExtensionTypes)
79                                 RegisterExtensionType (type);
80 #endif
81                                 
82                         CreateExtensionSerializers ();
83                 }
84         
85                 static void RegisterExtensionType (Type type)
86                 {
87                         ExtensionInfo ext = new ExtensionInfo();
88                         ext.Type = type;
89                         
90                         object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPrefixAttribute), true);
91                         
92                         foreach (XmlFormatExtensionPrefixAttribute at in ats)
93                                 ext.NamespaceDeclarations.Add (new XmlQualifiedName (at.Prefix, at.Namespace));
94                         
95                         ats = type.GetCustomAttributes (typeof(XmlFormatExtensionAttribute), true);
96                         if (ats.Length > 0)
97                         {
98                                 XmlFormatExtensionAttribute at = (XmlFormatExtensionAttribute)ats[0];
99                                 ext.ElementName = at.ElementName;
100                                 if (at.Namespace != null) ext.Namespace = at.Namespace;
101                         }
102
103                         XmlRootAttribute root = new XmlRootAttribute ();
104                         root.ElementName = ext.ElementName;
105                         if (ext.Namespace != null) root.Namespace = ext.Namespace;
106
107                         XmlReflectionImporter ri = new XmlReflectionImporter ();
108                         XmlTypeMapping map = ri.ImportTypeMapping (type, root);
109                         
110                         if (ext.ElementName == null) throw new InvalidOperationException ("XmlFormatExtensionAttribute must be applied to type " + type);
111                         extensionsByName.Add (ext.Namespace + " " + ext.ElementName, ext);
112                         extensionsByType.Add (type, ext);
113                         
114                         maps.Add (map);
115                         extensions.Add (ext);
116                 }
117                 
118                 static void CreateExtensionSerializers ()
119                 {
120                         XmlSerializer[] sers = XmlSerializer.FromMappings ((XmlMapping[]) maps.ToArray (typeof(XmlMapping)));
121                         for (int n=0; n<sers.Length; n++)
122                                 ((ExtensionInfo)extensions[n]).Serializer = sers[n];
123                         
124                         maps = null;
125                         extensions = null;
126                 }
127                 
128                 public static ExtensionInfo GetFormatExtensionInfo (string elementName, string namesp)
129                 {
130                         return (ExtensionInfo) extensionsByName [namesp + " " + elementName];
131                 }
132                 
133                 public static ExtensionInfo GetFormatExtensionInfo (Type extType)
134                 {
135                         return (ExtensionInfo) extensionsByType [extType];
136                 }
137                 
138                 public static ICollection GetFormatExtensions ()
139                 {
140                         return extensionsByName.Values;
141                 }
142
143                 public static ServiceDescriptionFormatExtensionCollection GetExtensionPoint (object ob)
144                 {
145                         Type type = ob.GetType ();
146                         object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPointAttribute), true);
147                         if (ats.Length == 0) return null;
148
149                         XmlFormatExtensionPointAttribute at = (XmlFormatExtensionPointAttribute)ats[0];
150                         
151                         PropertyInfo prop = type.GetProperty (at.MemberName);
152                         if (prop != null)
153                                 return prop.GetValue (ob, null) as ServiceDescriptionFormatExtensionCollection;
154                         else {
155                                 FieldInfo field = type.GetField (at.MemberName);
156                                 if (field != null)
157                                         return field.GetValue (ob) as ServiceDescriptionFormatExtensionCollection;
158                                 else
159                                         throw new InvalidOperationException ("XmlFormatExtensionPointAttribute: Member " + at.MemberName + " not found");
160                         }
161                 }
162                 
163                 public static ArrayList BuildExtensionImporters ()
164                 {
165 #if NET_2_0
166                         return BuildExtensionList (WebServicesSection.Current.SoapExtensionImporterTypes);
167 #else
168                         return BuildExtensionList (WSConfig.Instance.ExtensionImporterTypes);
169 #endif
170                 }
171                 
172                 public static ArrayList BuildExtensionReflectors ()
173                 {
174 #if NET_2_0
175                         return BuildExtensionList (WebServicesSection.Current.SoapExtensionReflectorTypes);
176 #else
177                         return BuildExtensionList (WSConfig.Instance.ExtensionReflectorTypes);
178 #endif
179                 }
180                 
181 #if NET_2_0
182                 public static ArrayList BuildExtensionList (TypeElementCollection exts)
183 #else
184                 public static ArrayList BuildExtensionList (ArrayList exts)
185 #endif
186                 {
187                         ArrayList extensionTypes = new ArrayList ();
188                         
189                         if (exts != null)
190                         {
191 #if NET_2_0
192                                 foreach (TypeElement econf in exts)
193                                 {
194                                         extensionTypes.Add (econf);
195                                 }
196 #else
197                                 foreach (WSExtensionConfig econf in exts)
198                                 {
199                                         bool added = false;
200                                         for (int n=0; n<extensionTypes.Count && !added; n++)
201                                         {
202                                                 WSExtensionConfig cureconf = (WSExtensionConfig) extensionTypes [n];
203         
204                                                 if ((econf.Group < cureconf.Group) || ((econf.Group == cureconf.Group) && (econf.Priority < cureconf.Priority))) {
205                                                         extensionTypes.Insert (n, econf);
206                                                         added = true;
207                                                 }
208                                         }
209                                         if (!added) extensionTypes.Add (econf);
210                                 }
211 #endif
212                         }
213
214                         ArrayList extensions = new ArrayList (extensionTypes.Count);
215 #if NET_2_0
216                         foreach (TypeElement econf in extensionTypes)
217 #else
218                         foreach (WSExtensionConfig econf in extensionTypes)
219 #endif
220                                 extensions.Add (Activator.CreateInstance (econf.Type));
221                                 
222                         return extensions;
223                 }
224         }
225         
226         internal class ExtensionInfo
227         {
228                 ArrayList _namespaceDeclarations;
229                 string _namespace;
230                 string _elementName;
231                 Type _type;
232                 XmlSerializer _serializer;
233
234                 public ArrayList NamespaceDeclarations
235                 {
236                         get { 
237                                 if (_namespaceDeclarations == null) _namespaceDeclarations = new ArrayList ();
238                                 return _namespaceDeclarations; 
239                         }
240                 }
241                 
242                 public string Namespace
243                 {
244                         get { return _namespace; }
245                         set { _namespace = value; }
246                 }
247                 
248                 public string ElementName
249                 {
250                         get { return _elementName; }
251                         set { _elementName = value; }
252                 }
253                 
254                 public Type Type
255                 {
256                         get { return _type; }
257                         set { _type = value; }
258                 }
259                 
260                 public XmlSerializer Serializer
261                 {
262                         get { return _serializer; }
263                         set { _serializer = value; }
264                 }               
265         }
266 }