1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
namespace System.Runtime.Serialization.Json
{
using System.Threading;
using System.Xml;
using System.Security;
class JsonCollectionDataContract : JsonDataContract
{
[Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization."
+ "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
[SecurityCritical]
JsonCollectionDataContractCriticalHelper helper;
[Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
Safe = "Doesn't leak anything.")]
[SecuritySafeCritical]
public JsonCollectionDataContract(CollectionDataContract traditionalDataContract)
: base(new JsonCollectionDataContractCriticalHelper(traditionalDataContract))
{
this.helper = base.Helper as JsonCollectionDataContractCriticalHelper;
}
internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate
{
[Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatReaderDelegate property.",
Safe = "JsonFormatReaderDelegate only needs to be protected for write.")]
[SecuritySafeCritical]
get
{
if (helper.JsonFormatReaderDelegate == null)
{
lock (this)
{
if (helper.JsonFormatReaderDelegate == null)
{
if (TraditionalCollectionDataContract.IsReadOnlyContract)
{
DataContract.ThrowInvalidDataContractException(TraditionalCollectionDataContract.DeserializationExceptionMessage, null /*type*/);
}
JsonFormatCollectionReaderDelegate tempDelegate = new JsonFormatReaderGenerator().GenerateCollectionReader(TraditionalCollectionDataContract);
Thread.MemoryBarrier();
helper.JsonFormatReaderDelegate = tempDelegate;
}
}
}
return helper.JsonFormatReaderDelegate;
}
}
internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate
{
[Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatGetOnlyReaderDelegate property.",
Safe = "JsonFormatGetOnlyReaderDelegate only needs to be protected for write; initialized in getter if null.")]
[SecuritySafeCritical]
get
{
if (helper.JsonFormatGetOnlyReaderDelegate == null)
{
lock (this)
{
if (helper.JsonFormatGetOnlyReaderDelegate == null)
{
CollectionKind kind = this.TraditionalCollectionDataContract.Kind;
if (this.TraditionalDataContract.UnderlyingType.IsInterface && (kind == CollectionKind.Enumerable || kind == CollectionKind.Collection || kind == CollectionKind.GenericEnumerable))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GetOnlyCollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(this.TraditionalDataContract.UnderlyingType))));
}
if (TraditionalCollectionDataContract.IsReadOnlyContract)
{
DataContract.ThrowInvalidDataContractException(TraditionalCollectionDataContract.DeserializationExceptionMessage, null /*type*/);
}
JsonFormatGetOnlyCollectionReaderDelegate tempDelegate = new JsonFormatReaderGenerator().GenerateGetOnlyCollectionReader(TraditionalCollectionDataContract);
Thread.MemoryBarrier();
helper.JsonFormatGetOnlyReaderDelegate = tempDelegate;
}
}
}
return helper.JsonFormatGetOnlyReaderDelegate;
}
}
internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate
{
[Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatWriterDelegate property.",
Safe = "JsonFormatWriterDelegate only needs to be protected for write.")]
[SecuritySafeCritical]
get
{
if (helper.JsonFormatWriterDelegate == null)
{
lock (this)
{
if (helper.JsonFormatWriterDelegate == null)
{
JsonFormatCollectionWriterDelegate tempDelegate = new JsonFormatWriterGenerator().GenerateCollectionWriter(TraditionalCollectionDataContract);
Thread.MemoryBarrier();
helper.JsonFormatWriterDelegate = tempDelegate;
}
}
}
return helper.JsonFormatWriterDelegate;
}
}
CollectionDataContract TraditionalCollectionDataContract
{
[Fx.Tag.SecurityNote(Critical = "Fetches the critical TraditionalCollectionDataContract property.",
Safe = "TraditionalCollectionDataContract only needs to be protected for write.")]
[SecuritySafeCritical]
get { return this.helper.TraditionalCollectionDataContract; }
}
public override object ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
{
jsonReader.Read();
object o = null;
if (context.IsGetOnlyCollection)
{
// IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
context.IsGetOnlyCollection = false;
JsonFormatGetOnlyReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract);
}
else
{
o = JsonFormatReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract);
}
jsonReader.ReadEndElement();
return o;
}
public override void WriteJsonValueCore(XmlWriterDelegator jsonWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
{
// IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
context.IsGetOnlyCollection = false;
JsonFormatWriterDelegate(jsonWriter, obj, context, TraditionalCollectionDataContract);
}
[Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing types."
+ "Since the data is cached statically, we lock down access to it.")]
#if !NO_SECURITY_ATTRIBUTES
#pragma warning disable 618 // have not moved to the v4 security model yet
[SecurityCritical(SecurityCriticalScope.Everything)]
#pragma warning restore 618
#endif
class JsonCollectionDataContractCriticalHelper : JsonDataContractCriticalHelper
{
JsonFormatCollectionReaderDelegate jsonFormatReaderDelegate;
JsonFormatGetOnlyCollectionReaderDelegate jsonFormatGetOnlyReaderDelegate;
JsonFormatCollectionWriterDelegate jsonFormatWriterDelegate;
CollectionDataContract traditionalCollectionDataContract;
public JsonCollectionDataContractCriticalHelper(CollectionDataContract traditionalDataContract)
: base(traditionalDataContract)
{
this.traditionalCollectionDataContract = traditionalDataContract;
}
internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate
{
get { return this.jsonFormatReaderDelegate; }
set { this.jsonFormatReaderDelegate = value; }
}
internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate
{
get { return this.jsonFormatGetOnlyReaderDelegate; }
set { this.jsonFormatGetOnlyReaderDelegate = value; }
}
internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate
{
get { return this.jsonFormatWriterDelegate; }
set { this.jsonFormatWriterDelegate = value; }
}
internal CollectionDataContract TraditionalCollectionDataContract
{
get { return this.traditionalCollectionDataContract; }
}
}
}
}
|