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 
ExtensionManager()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 			RegisterExtensionType (typeof (Soap12AddressBinding));
68 			RegisterExtensionType (typeof (Soap12Binding));
69 			RegisterExtensionType (typeof (Soap12BodyBinding));
70 			RegisterExtensionType (typeof (Soap12FaultBinding));
71 			RegisterExtensionType (typeof (Soap12HeaderBinding));
72 			RegisterExtensionType (typeof (Soap12OperationBinding));
73 
74 #if !MOBILE && !XAMMAC_4_5
75 			/*
76 			 * Currently, the mobile profile has not support for
77 			 * System.Configuration, so there are no external modules
78 			 * defined
79 			 */
80 			foreach (TypeElement el in WebServicesSection.Current.ServiceDescriptionFormatExtensionTypes)
81 				RegisterExtensionType (el.Type);
82 #endif
83 			CreateExtensionSerializers ();
84 		}
85 
RegisterExtensionType(Type type)86 		static void RegisterExtensionType (Type type)
87 		{
88 			ExtensionInfo ext = new ExtensionInfo();
89 			ext.Type = type;
90 
91 			object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPrefixAttribute), true);
92 
93 			foreach (XmlFormatExtensionPrefixAttribute at in ats)
94 				ext.NamespaceDeclarations.Add (new XmlQualifiedName (at.Prefix, at.Namespace));
95 
96 			ats = type.GetCustomAttributes (typeof(XmlFormatExtensionAttribute), true);
97 			if (ats.Length > 0)
98 			{
99 				XmlFormatExtensionAttribute at = (XmlFormatExtensionAttribute)ats[0];
100 				ext.ElementName = at.ElementName;
101 				if (at.Namespace != null) ext.Namespace = at.Namespace;
102 			}
103 
104 			XmlRootAttribute root = new XmlRootAttribute ();
105 			root.ElementName = ext.ElementName;
106 			if (ext.Namespace != null) root.Namespace = ext.Namespace;
107 
108 			XmlReflectionImporter ri = new XmlReflectionImporter ();
109 			XmlTypeMapping map = ri.ImportTypeMapping (type, root);
110 
111 			if (ext.ElementName == null) throw new InvalidOperationException ("XmlFormatExtensionAttribute must be applied to type " + type);
112 			extensionsByName.Add (ext.Namespace + " " + ext.ElementName, ext);
113 			extensionsByType.Add (type, ext);
114 
115 			maps.Add (map);
116 			extensions.Add (ext);
117 		}
118 
CreateExtensionSerializers()119 		static void CreateExtensionSerializers ()
120 		{
121 			XmlSerializer[] sers = XmlSerializer.FromMappings ((XmlMapping[]) maps.ToArray (typeof(XmlMapping)));
122 			for (int n=0; n<sers.Length; n++)
123 				((ExtensionInfo)extensions[n]).Serializer = sers[n];
124 
125 			maps = null;
126 			extensions = null;
127 		}
128 
GetFormatExtensionInfo(string elementName, string namesp)129 		public static ExtensionInfo GetFormatExtensionInfo (string elementName, string namesp)
130 		{
131 			return (ExtensionInfo) extensionsByName [namesp + " " + elementName];
132 		}
133 
GetFormatExtensionInfo(Type extType)134 		public static ExtensionInfo GetFormatExtensionInfo (Type extType)
135 		{
136 			return (ExtensionInfo) extensionsByType [extType];
137 		}
138 
GetFormatExtensions()139 		public static ICollection GetFormatExtensions ()
140 		{
141 			return extensionsByName.Values;
142 		}
143 
GetExtensionPoint(object ob)144 		public static ServiceDescriptionFormatExtensionCollection GetExtensionPoint (object ob)
145 		{
146 			Type type = ob.GetType ();
147 			object[] ats = type.GetCustomAttributes (typeof(XmlFormatExtensionPointAttribute), true);
148 			if (ats.Length == 0) return null;
149 
150 			XmlFormatExtensionPointAttribute at = (XmlFormatExtensionPointAttribute)ats[0];
151 
152 			PropertyInfo prop = type.GetProperty (at.MemberName);
153 			if (prop != null)
154 				return prop.GetValue (ob, null) as ServiceDescriptionFormatExtensionCollection;
155 			else {
156 				FieldInfo field = type.GetField (at.MemberName);
157 				if (field != null)
158 					return field.GetValue (ob) as ServiceDescriptionFormatExtensionCollection;
159 				else
160 					throw new InvalidOperationException ("XmlFormatExtensionPointAttribute: Member " + at.MemberName + " not found");
161 			}
162 		}
163 
164 		/*
165 		 * The mobile profile lacks support for configuration
166 		 */
167 #if MOBILE || XAMMAC_4_5
BuildExtensionImporters()168 		public static ArrayList BuildExtensionImporters ()
169 		{
170 			return new ArrayList (0);
171 		}
172 
BuildExtensionReflectors()173 		public static ArrayList BuildExtensionReflectors ()
174 		{
175 			return new ArrayList (0);
176 		}
177 
178 #else
BuildExtensionImporters()179 		public static ArrayList BuildExtensionImporters ()
180 		{
181 			return BuildExtensionList (WebServicesSection.Current.SoapExtensionImporterTypes);
182 		}
183 
BuildExtensionReflectors()184 		public static ArrayList BuildExtensionReflectors ()
185 		{
186 			return BuildExtensionList (WebServicesSection.Current.SoapExtensionReflectorTypes);
187 		}
188 
BuildExtensionList(TypeElementCollection exts)189 		public static ArrayList BuildExtensionList (TypeElementCollection exts)
190 		{
191 			ArrayList extensionTypes = new ArrayList ();
192 
193 			if (exts != null)
194 			{
195 				foreach (TypeElement econf in exts)
196 				{
197 					extensionTypes.Add (econf);
198 				}
199 			}
200 
201 			ArrayList extensions = new ArrayList (extensionTypes.Count);
202 			foreach (TypeElement econf in extensionTypes)
203 				extensions.Add (Activator.CreateInstance (econf.Type));
204 
205 			return extensions;
206 		}
207 #endif
208 	}
209 
210 	internal class ExtensionInfo
211 	{
212 		ArrayList _namespaceDeclarations;
213 		string _namespace;
214 		string _elementName;
215 		Type _type;
216 		XmlSerializer _serializer;
217 
218 		public ArrayList NamespaceDeclarations
219 		{
220 			get {
221 				if (_namespaceDeclarations == null) _namespaceDeclarations = new ArrayList ();
222 				return _namespaceDeclarations;
223 			}
224 		}
225 
226 		public string Namespace
227 		{
228 			get { return _namespace; }
229 			set { _namespace = value; }
230 		}
231 
232 		public string ElementName
233 		{
234 			get { return _elementName; }
235 			set { _elementName = value; }
236 		}
237 
238 		public Type Type
239 		{
240 			get { return _type; }
241 			set { _type = value; }
242 		}
243 
244 		public XmlSerializer Serializer
245 		{
246 			get { return _serializer; }
247 			set { _serializer = value; }
248 		}
249 	}
250 }
251