2006-11-02 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Description / ExtensionManager.cs
1 // \r
2 // System.Web.Services.Description.ExtensionManager.cs\r
3 //\r
4 // Author:\r
5 //   Lluis Sanchez Gual (lluis@ximian.com)\r
6 //\r
7 // Copyright (C) 2003 Ximian, Inc.\r
8 //\r
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 \r
31 using System.Reflection;\r
32 using System.Collections;\r
33 using System.Web.Services.Configuration;\r
34 using System.Xml.Serialization;\r
35 using System.Xml;\r
36 \r
37 namespace System.Web.Services.Description \r
38 {\r
39         internal abstract class ExtensionManager \r
40         {\r
41                 static Hashtable extensionsByName;\r
42                 static Hashtable extensionsByType;\r
43                 static ArrayList maps = new ArrayList ();\r
44                 static ArrayList extensions = new ArrayList ();\r
45 \r
46                 static ExtensionManager ()\r
47                 {\r
48                         extensionsByName = new Hashtable ();\r
49                         extensionsByType = new Hashtable ();\r
50 \r
51                         RegisterExtensionType (typeof (HttpAddressBinding));\r
52                         RegisterExtensionType (typeof (HttpBinding));\r
53                         RegisterExtensionType (typeof (HttpOperationBinding));\r
54                         RegisterExtensionType (typeof (HttpUrlEncodedBinding));\r
55                         RegisterExtensionType (typeof (HttpUrlReplacementBinding));\r
56                         RegisterExtensionType (typeof (MimeContentBinding));\r
57                         RegisterExtensionType (typeof (MimeMultipartRelatedBinding));\r
58                         RegisterExtensionType (typeof (MimeTextBinding));\r
59                         RegisterExtensionType (typeof (MimeXmlBinding));\r
60                         RegisterExtensionType (typeof (SoapAddressBinding));\r
61                         RegisterExtensionType (typeof (SoapBinding));\r
62                         RegisterExtensionType (typeof (SoapBodyBinding));\r
63                         RegisterExtensionType (typeof (SoapFaultBinding));\r
64                         RegisterExtensionType (typeof (SoapHeaderBinding));\r
65 //                      RegisterExtensionType (typeof (SoapHeaderFaultBinding));\r
66                         RegisterExtensionType (typeof (SoapOperationBinding));\r
67                         \r
68                         foreach (Type type in WSConfig.Instance.FormatExtensionTypes)\r
69                                 RegisterExtensionType (type);\r
70                                 \r
71                         CreateExtensionSerializers ();\r
72                 }\r
73         \r
74                 static void RegisterExtensionType (Type type)\r
75                 {\r
76                         ExtensionInfo ext = new ExtensionInfo();\r
77                         ext.Type = type;\r
78                         \r
79                         object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPrefixAttribute), true);\r
80                         \r
81                         foreach (XmlFormatExtensionPrefixAttribute at in ats)\r
82                                 ext.NamespaceDeclarations.Add (new XmlQualifiedName (at.Prefix, at.Namespace));\r
83                         \r
84                         ats = type.GetCustomAttributes (typeof(XmlFormatExtensionAttribute), true);\r
85                         if (ats.Length > 0)\r
86                         {\r
87                                 XmlFormatExtensionAttribute at = (XmlFormatExtensionAttribute)ats[0];\r
88                                 ext.ElementName = at.ElementName;\r
89                                 if (at.Namespace != null) ext.Namespace = at.Namespace;\r
90                         }\r
91 \r
92                         XmlRootAttribute root = new XmlRootAttribute ();\r
93                         root.ElementName = ext.ElementName;\r
94                         if (ext.Namespace != null) root.Namespace = ext.Namespace;\r
95 \r
96                         XmlReflectionImporter ri = new XmlReflectionImporter ();\r
97                         XmlTypeMapping map = ri.ImportTypeMapping (type, root);\r
98                         \r
99                         if (ext.ElementName == null) throw new InvalidOperationException ("XmlFormatExtensionAttribute must be applied to type " + type);\r
100                         extensionsByName.Add (ext.Namespace + " " + ext.ElementName, ext);\r
101                         extensionsByType.Add (type, ext);\r
102                         \r
103                         maps.Add (map);\r
104                         extensions.Add (ext);\r
105                 }\r
106                 \r
107                 static void CreateExtensionSerializers ()\r
108                 {\r
109                         XmlSerializer[] sers = XmlSerializer.FromMappings ((XmlMapping[]) maps.ToArray (typeof(XmlMapping)));\r
110                         for (int n=0; n<sers.Length; n++)\r
111                                 ((ExtensionInfo)extensions[n]).Serializer = sers[n];\r
112                         \r
113                         maps = null;\r
114                         extensions = null;\r
115                 }\r
116                 \r
117                 public static ExtensionInfo GetFormatExtensionInfo (string elementName, string namesp)\r
118                 {\r
119                         return (ExtensionInfo) extensionsByName [namesp + " " + elementName];\r
120                 }\r
121                 \r
122                 public static ExtensionInfo GetFormatExtensionInfo (Type extType)\r
123                 {\r
124                         return (ExtensionInfo) extensionsByType [extType];\r
125                 }\r
126                 \r
127                 public static ICollection GetFormatExtensions ()\r
128                 {\r
129                         return extensionsByName.Values;\r
130                 }\r
131 \r
132                 public static ServiceDescriptionFormatExtensionCollection GetExtensionPoint (object ob)\r
133                 {\r
134                         Type type = ob.GetType ();\r
135                         object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPointAttribute), true);\r
136                         if (ats.Length == 0) return null;\r
137 \r
138                         XmlFormatExtensionPointAttribute at = (XmlFormatExtensionPointAttribute)ats[0];\r
139                         \r
140                         PropertyInfo prop = type.GetProperty (at.MemberName);\r
141                         if (prop != null)\r
142                                 return prop.GetValue (ob, null) as ServiceDescriptionFormatExtensionCollection;\r
143                         else {\r
144                                 FieldInfo field = type.GetField (at.MemberName);\r
145                                 if (field != null)\r
146                                         return field.GetValue (ob) as ServiceDescriptionFormatExtensionCollection;\r
147                                 else\r
148                                         throw new InvalidOperationException ("XmlFormatExtensionPointAttribute: Member " + at.MemberName + " not found");\r
149                         }\r
150                 }\r
151                 \r
152                 public static ArrayList BuildExtensionImporters ()\r
153                 {\r
154                         return BuildExtensionList (WSConfig.Instance.ExtensionImporterTypes);\r
155                 }\r
156                 \r
157                 public static ArrayList BuildExtensionReflectors ()\r
158                 {\r
159                         return BuildExtensionList (WSConfig.Instance.ExtensionReflectorTypes);\r
160                 }\r
161                 \r
162                 public static ArrayList BuildExtensionList (ArrayList exts)\r
163                 {\r
164                         ArrayList extensionTypes = new ArrayList ();\r
165                         \r
166                         if (exts != null)\r
167                         {\r
168                                 foreach (WSExtensionConfig econf in exts)\r
169                                 {\r
170                                         bool added = false;\r
171                                         for (int n=0; n<extensionTypes.Count && !added; n++)\r
172                                         {\r
173                                                 WSExtensionConfig cureconf = (WSExtensionConfig) extensionTypes [n];\r
174         \r
175                                                 if ((econf.Group < cureconf.Group) || ((econf.Group == cureconf.Group) && (econf.Priority < cureconf.Priority))) {\r
176                                                         extensionTypes.Insert (n, econf);\r
177                                                         added = true;\r
178                                                 }\r
179                                         }\r
180                                         if (!added) extensionTypes.Add (econf);\r
181                                 }\r
182                         }\r
183 \r
184                         ArrayList extensions = new ArrayList (extensionTypes.Count);\r
185                         foreach (WSExtensionConfig econf in extensionTypes)\r
186                                 extensions.Add (Activator.CreateInstance (econf.Type));\r
187                                 \r
188                         return extensions;\r
189                 }\r
190         }\r
191         \r
192         internal class ExtensionInfo\r
193         {\r
194                 ArrayList _namespaceDeclarations;\r
195                 string _namespace;\r
196                 string _elementName;\r
197                 Type _type;\r
198                 XmlSerializer _serializer;\r
199 \r
200                 public ArrayList NamespaceDeclarations\r
201                 {\r
202                         get { \r
203                                 if (_namespaceDeclarations == null) _namespaceDeclarations = new ArrayList ();\r
204                                 return _namespaceDeclarations; \r
205                         }\r
206                 }\r
207                 \r
208                 public string Namespace\r
209                 {\r
210                         get { return _namespace; }\r
211                         set { _namespace = value; }\r
212                 }\r
213                 \r
214                 public string ElementName\r
215                 {\r
216                         get { return _elementName; }\r
217                         set { _elementName = value; }\r
218                 }\r
219                 \r
220                 public Type Type\r
221                 {\r
222                         get { return _type; }\r
223                         set { _type = value; }\r
224                 }\r
225                 \r
226                 public XmlSerializer Serializer\r
227                 {\r
228                         get { return _serializer; }\r
229                         set { _serializer = value; }\r
230                 }               \r
231         }\r
232 }