Implement mono_gc_alloc_fixed on Boehm to be uncollectable. This matches SGen behavio...
[mono.git] / mcs / class / referencesource / System.Runtime.Serialization / System / Runtime / Serialization / XmlObjectSerializerContext.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.Runtime.Serialization
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Reflection;
10     using System.Runtime.Serialization.Diagnostics.Application;
11     using System.Security;
12     using System.Xml;
13     using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
14
15 #if USE_REFEMIT
16     public class XmlObjectSerializerContext
17 #else
18     internal class XmlObjectSerializerContext
19 #endif
20     {
21         protected XmlObjectSerializer serializer;
22         protected DataContract rootTypeDataContract;
23         internal ScopedKnownTypes scopedKnownTypes = new ScopedKnownTypes();
24         protected DataContractDictionary serializerKnownDataContracts;
25         bool isSerializerKnownDataContractsSetExplicit;
26         protected IList<Type> serializerKnownTypeList;
27
28         [Fx.Tag.SecurityNote(Critical = "We base the decision whether to Demand SerializationFormatterPermission on this value.")]
29         [SecurityCritical]
30         bool demandedSerializationFormatterPermission;
31
32         [Fx.Tag.SecurityNote(Critical = "We base the decision whether to Demand MemberAccess on this value.")]
33         [SecurityCritical]
34         bool demandedMemberAccessPermission;
35         int itemCount;
36         int maxItemsInObjectGraph;
37         StreamingContext streamingContext;
38         bool ignoreExtensionDataObject;
39         DataContractResolver dataContractResolver;
40         KnownTypeDataContractResolver knownTypeResolver;
41
42         internal XmlObjectSerializerContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject, DataContractResolver dataContractResolver)
43         {
44             this.serializer = serializer;
45             this.itemCount = 1;
46             this.maxItemsInObjectGraph = maxItemsInObjectGraph;
47             this.streamingContext = streamingContext;
48             this.ignoreExtensionDataObject = ignoreExtensionDataObject;
49             this.dataContractResolver = dataContractResolver;
50         }
51
52         internal XmlObjectSerializerContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
53             : this(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject, null)
54         {
55         }
56
57         internal XmlObjectSerializerContext(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
58             : this(serializer,
59             serializer.MaxItemsInObjectGraph,
60             new StreamingContext(StreamingContextStates.All),
61             serializer.IgnoreExtensionDataObject,
62             dataContractResolver)
63         {
64             this.rootTypeDataContract = rootTypeDataContract;
65             this.serializerKnownTypeList = serializer.knownTypeList;
66         }
67
68         internal XmlObjectSerializerContext(NetDataContractSerializer serializer)
69             : this(serializer,
70             serializer.MaxItemsInObjectGraph,
71             serializer.Context,
72             serializer.IgnoreExtensionDataObject)
73         {
74         }
75
76         internal virtual SerializationMode Mode
77         {
78             get { return SerializationMode.SharedContract; }
79         }
80
81         internal virtual bool IsGetOnlyCollection
82         {
83             get { return false; }
84             set { }
85         }
86
87         [Fx.Tag.SecurityNote(Critical = "Demands SerializationFormatter permission. demanding the right permission is critical.",
88             Safe = "No data or control leaks in or out, must be callable from transparent generated IL.")]
89         [SecuritySafeCritical]
90         public void DemandSerializationFormatterPermission()
91         {
92 #if FEATURE_MONO_CAS
93             if (!demandedSerializationFormatterPermission)
94             {
95                 Globals.SerializationFormatterPermission.Demand();
96                 demandedSerializationFormatterPermission = true;
97             }
98 #endif
99         }
100
101         [Fx.Tag.SecurityNote(Critical = "Demands MemberAccess permission. demanding the right permission is critical.",
102             Safe = "No data or control leaks in or out, must be callable from transparent generated IL.")]
103         [SecuritySafeCritical]
104         public void DemandMemberAccessPermission()
105         {
106 #if FEATURE_MONO_CAS
107             if (!demandedMemberAccessPermission)
108             {
109                 Globals.MemberAccessPermission.Demand();
110                 demandedMemberAccessPermission = true;
111             }
112  #endif
113         }
114
115         public StreamingContext GetStreamingContext()
116         {
117             return streamingContext;
118         }
119
120         static MethodInfo incrementItemCountMethod;
121         internal static MethodInfo IncrementItemCountMethod
122         {
123             get
124             {
125                 if (incrementItemCountMethod == null)
126                     incrementItemCountMethod = typeof(XmlObjectSerializerContext).GetMethod("IncrementItemCount", Globals.ScanAllMembers);
127                 return incrementItemCountMethod;
128             }
129         }
130         public void IncrementItemCount(int count)
131         {
132             if (count > maxItemsInObjectGraph - itemCount)
133                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExceededMaxItemsQuota, maxItemsInObjectGraph)));
134             itemCount += count;
135         }
136
137         internal int RemainingItemCount
138         {
139             get { return maxItemsInObjectGraph - itemCount; }
140         }
141
142         internal bool IgnoreExtensionDataObject
143         {
144             get { return ignoreExtensionDataObject; }
145         }
146
147         protected DataContractResolver DataContractResolver
148         {
149             get { return dataContractResolver; }
150         }
151
152         protected KnownTypeDataContractResolver KnownTypeResolver
153         {
154             get
155             {
156                 if (knownTypeResolver == null)
157                 {
158                     knownTypeResolver = new KnownTypeDataContractResolver(this);
159                 }
160                 return knownTypeResolver;
161             }
162         }
163
164         internal DataContract GetDataContract(Type type)
165         {
166             return GetDataContract(type.TypeHandle, type);
167         }
168
169         internal virtual DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
170         {
171             if (IsGetOnlyCollection)
172             {
173                 return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(typeHandle), typeHandle, type, Mode);
174             }
175             else
176             {
177                 return DataContract.GetDataContract(typeHandle, type, Mode);
178             }
179         }
180
181         internal virtual DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
182         {
183             if (IsGetOnlyCollection)
184             {
185                 return DataContract.GetGetOnlyCollectionDataContractSkipValidation(typeId, typeHandle, type);
186             }
187             else
188             {
189                 return DataContract.GetDataContractSkipValidation(typeId, typeHandle, type);
190             }
191         }
192
193
194         internal virtual DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
195         {
196             if (IsGetOnlyCollection)
197             {
198                 return DataContract.GetGetOnlyCollectionDataContract(id, typeHandle, null /*type*/, Mode);
199             }
200             else
201             {
202                 return DataContract.GetDataContract(id, typeHandle, Mode);
203             }
204         }
205
206         internal virtual void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
207         {
208             if (!isMemberTypeSerializable)
209                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeNotSerializable, memberType)));
210         }
211
212         internal virtual Type GetSurrogatedType(Type type)
213         {
214             return type;
215         }
216
217         DataContractDictionary SerializerKnownDataContracts
218         {
219             get
220             {
221                 // This field must be initialized during construction by serializers using data contracts.
222                 if (!this.isSerializerKnownDataContractsSetExplicit)
223                 {
224                     this.serializerKnownDataContracts = serializer.KnownDataContracts;
225                     this.isSerializerKnownDataContractsSetExplicit = true;
226                 }
227                 return this.serializerKnownDataContracts;
228             }
229         }
230
231         DataContract GetDataContractFromSerializerKnownTypes(XmlQualifiedName qname)
232         {
233             DataContractDictionary serializerKnownDataContracts = this.SerializerKnownDataContracts;
234             if (serializerKnownDataContracts == null)
235                 return null;
236             DataContract outDataContract;
237             return serializerKnownDataContracts.TryGetValue(qname, out outDataContract) ? outDataContract : null;
238         }
239
240         internal static DataContractDictionary GetDataContractsForKnownTypes(IList<Type> knownTypeList)
241         {
242             if (knownTypeList == null) return null;
243             DataContractDictionary dataContracts = new DataContractDictionary();
244             Dictionary<Type, Type> typesChecked = new Dictionary<Type, Type>();
245             for (int i = 0; i < knownTypeList.Count; i++)
246             {
247                 Type knownType = knownTypeList[i];
248                 if (knownType == null)
249                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.NullKnownType, "knownTypes")));
250
251                 DataContract.CheckAndAdd(knownType, typesChecked, ref dataContracts);
252             }
253             return dataContracts;
254         }
255
256         internal bool IsKnownType(DataContract dataContract, DataContractDictionary knownDataContracts, Type declaredType)
257         {
258             bool knownTypesAddedInCurrentScope = false;
259             if (knownDataContracts != null)
260             {
261                 scopedKnownTypes.Push(knownDataContracts);
262                 knownTypesAddedInCurrentScope = true;
263             }
264
265             bool isKnownType = IsKnownType(dataContract, declaredType);
266
267             if (knownTypesAddedInCurrentScope)
268             {
269                 scopedKnownTypes.Pop();
270             }
271             return isKnownType;
272         }
273
274         internal bool IsKnownType(DataContract dataContract, Type declaredType)
275         {
276             DataContract knownContract = ResolveDataContractFromKnownTypes(dataContract.StableName.Name, dataContract.StableName.Namespace, null /*memberTypeContract*/, declaredType);
277             return knownContract != null && knownContract.UnderlyingType == dataContract.UnderlyingType;
278         }
279
280         DataContract ResolveDataContractFromKnownTypes(XmlQualifiedName typeName)
281         {
282             DataContract dataContract = PrimitiveDataContract.GetPrimitiveDataContract(typeName.Name, typeName.Namespace);
283             if (dataContract == null)
284             {
285                 dataContract = scopedKnownTypes.GetDataContract(typeName);
286                 if (dataContract == null)
287                 {
288                     dataContract = GetDataContractFromSerializerKnownTypes(typeName);
289                 }
290             }
291             return dataContract;
292         }
293
294         DataContract ResolveDataContractFromDataContractResolver(XmlQualifiedName typeName, Type declaredType)
295         {
296             if (TD.DCResolverResolveIsEnabled())
297             {
298                 TD.DCResolverResolve(typeName.Name + ":" + typeName.Namespace);
299             }
300
301             Type dataContractType = DataContractResolver.ResolveName(typeName.Name, typeName.Namespace, declaredType, KnownTypeResolver);
302             if (dataContractType == null)
303             {
304                 return null;
305             }
306             else
307             {
308                 return GetDataContract(dataContractType);
309             }
310         }
311
312         internal Type ResolveNameFromKnownTypes(XmlQualifiedName typeName)
313         {
314             DataContract dataContract = ResolveDataContractFromKnownTypes(typeName);
315             if (dataContract == null)
316             {
317                 return null;
318             }
319             else
320             {
321                 return dataContract.OriginalUnderlyingType;
322             }
323         }
324
325         protected DataContract ResolveDataContractFromKnownTypes(string typeName, string typeNs, DataContract memberTypeContract, Type declaredType)
326         {
327             XmlQualifiedName qname = new XmlQualifiedName(typeName, typeNs);
328             DataContract dataContract;
329             if (DataContractResolver == null)
330             {
331                 dataContract = ResolveDataContractFromKnownTypes(qname);
332             }
333             else
334             {
335                 dataContract = ResolveDataContractFromDataContractResolver(qname, declaredType);
336             }
337             if (dataContract == null)
338             {
339                 if (memberTypeContract != null
340                     && !memberTypeContract.UnderlyingType.IsInterface
341                     && memberTypeContract.StableName == qname)
342                 {
343                     dataContract = memberTypeContract;
344                 }
345                 if (dataContract == null && rootTypeDataContract != null)
346                 {
347                     dataContract = ResolveDataContractFromRootDataContract(qname);
348                 }
349             }
350             return dataContract;
351         }
352
353         protected virtual DataContract ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
354         {
355             if (rootTypeDataContract.StableName == typeQName)
356                 return rootTypeDataContract;
357
358             CollectionDataContract collectionContract = rootTypeDataContract as CollectionDataContract;
359             while (collectionContract != null)
360             {
361                 DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType));
362                 if (itemContract.StableName == typeQName)
363                 {
364                     return itemContract;
365                 }
366                 collectionContract = itemContract as CollectionDataContract;
367             }
368             return null;
369         }
370
371     }
372
373 }