Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
internal enum EpmSerializationKind
{
Attributes,
Elements,
All
}
internal abstract class EpmContentSerializerBase
{
protected EpmContentSerializerBase(EpmTargetTree tree, bool isSyndication, object element, XmlWriter target)
{
this.Root = isSyndication ? tree.SyndicationRoot : tree.NonSyndicationRoot;
this.Element = element;
this.Target = target;
this.Success = false;
}
protected EpmTargetPathSegment Root
{
get;
private set;
}
protected object Element
{
get;
private set;
}
protected XmlWriter Target
{
get;
private set;
}
protected bool Success
{
get;
private set;
}
internal void Serialize()
{
foreach (EpmTargetPathSegment targetSegment in this.Root.SubSegments)
{
this.Serialize(targetSegment, EpmSerializationKind.All);
}
this.Success = true;
}
protected virtual void Serialize(EpmTargetPathSegment targetSegment, EpmSerializationKind kind)
{
IEnumerable<EpmTargetPathSegment> segmentsToSerialize;
switch (kind)
{
case EpmSerializationKind.Attributes:
segmentsToSerialize = targetSegment.SubSegments.Where(s => s.IsAttribute == true);
break;
case EpmSerializationKind.Elements:
segmentsToSerialize = targetSegment.SubSegments.Where(s => s.IsAttribute == false);
break;
default:
Debug.Assert(kind == EpmSerializationKind.All, "Must serialize everything");
segmentsToSerialize = targetSegment.SubSegments;
break;
}
foreach (EpmTargetPathSegment segment in segmentsToSerialize)
{
this.Serialize(segment, kind);
}
}
}
}

View File

@@ -0,0 +1,120 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Services.Client;
using System.Xml;
internal sealed class EpmCustomContentSerializer : EpmContentSerializerBase, IDisposable
{
private bool disposed;
private Dictionary<EpmTargetPathSegment, EpmCustomContentWriterNodeData> visitorContent;
internal EpmCustomContentSerializer(EpmTargetTree targetTree, object element, XmlWriter target)
: base(targetTree, false, element, target)
{
this.InitializeVisitorContent();
}
public void Dispose()
{
if (!this.disposed)
{
foreach (EpmTargetPathSegment subSegmentOfRoot in this.Root.SubSegments)
{
EpmCustomContentWriterNodeData c = this.visitorContent[subSegmentOfRoot];
Debug.Assert(c != null, "Must have custom data for all the children of root");
if (this.Success)
{
c.AddContentToTarget(this.Target);
}
c.Dispose();
}
this.disposed = true;
}
}
protected override void Serialize(EpmTargetPathSegment targetSegment, EpmSerializationKind kind)
{
if (targetSegment.IsAttribute)
{
this.WriteAttribute(targetSegment);
}
else
{
this.WriteElement(targetSegment);
}
}
private void WriteAttribute(EpmTargetPathSegment targetSegment)
{
Debug.Assert(targetSegment.HasContent, "Must have content for attributes");
EpmCustomContentWriterNodeData currentContent = this.visitorContent[targetSegment];
currentContent.XmlContentWriter.WriteAttributeString(
targetSegment.SegmentNamespacePrefix,
targetSegment.SegmentName.Substring(1),
targetSegment.SegmentNamespaceUri,
currentContent.Data);
}
private void WriteElement(EpmTargetPathSegment targetSegment)
{
EpmCustomContentWriterNodeData currentContent = this.visitorContent[targetSegment];
currentContent.XmlContentWriter.WriteStartElement(
targetSegment.SegmentNamespacePrefix,
targetSegment.SegmentName,
targetSegment.SegmentNamespaceUri);
base.Serialize(targetSegment, EpmSerializationKind.Attributes);
if (targetSegment.HasContent)
{
Debug.Assert(currentContent.Data != null, "Must always have non-null data content value");
currentContent.XmlContentWriter.WriteString(currentContent.Data);
}
base.Serialize(targetSegment, EpmSerializationKind.Elements);
currentContent.XmlContentWriter.WriteEndElement();
}
private void InitializeVisitorContent()
{
this.visitorContent = new Dictionary<EpmTargetPathSegment, EpmCustomContentWriterNodeData>(ReferenceEqualityComparer<EpmTargetPathSegment>.Instance);
foreach (EpmTargetPathSegment subSegmentOfRoot in this.Root.SubSegments)
{
this.visitorContent.Add(subSegmentOfRoot, new EpmCustomContentWriterNodeData(subSegmentOfRoot, this.Element));
this.InitializeSubSegmentVisitorContent(subSegmentOfRoot);
}
}
private void InitializeSubSegmentVisitorContent(EpmTargetPathSegment subSegment)
{
foreach (EpmTargetPathSegment segment in subSegment.SubSegments)
{
this.visitorContent.Add(segment, new EpmCustomContentWriterNodeData(this.visitorContent[subSegment], segment, this.Element));
this.InitializeSubSegmentVisitorContent(segment);
}
}
}
}

View File

@@ -0,0 +1,114 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System;
using System.IO;
using System.Xml;
using System.Data.Services.Client;
internal sealed class EpmCustomContentWriterNodeData : IDisposable
{
private bool disposed;
internal EpmCustomContentWriterNodeData(EpmTargetPathSegment segment, object element)
{
this.XmlContentStream = new MemoryStream();
XmlWriterSettings customContentWriterSettings = new XmlWriterSettings();
customContentWriterSettings.OmitXmlDeclaration = true;
customContentWriterSettings.ConformanceLevel = ConformanceLevel.Fragment;
this.XmlContentWriter = XmlWriter.Create(this.XmlContentStream, customContentWriterSettings);
this.PopulateData(segment, element);
}
internal EpmCustomContentWriterNodeData(EpmCustomContentWriterNodeData parentData, EpmTargetPathSegment segment, object element)
{
this.XmlContentStream = parentData.XmlContentStream;
this.XmlContentWriter = parentData.XmlContentWriter;
this.PopulateData(segment, element);
}
internal MemoryStream XmlContentStream
{
get;
private set;
}
internal XmlWriter XmlContentWriter
{
get;
private set;
}
internal String Data
{
get;
private set;
}
public void Dispose()
{
if (!this.disposed)
{
if (this.XmlContentWriter != null)
{
this.XmlContentWriter.Close();
this.XmlContentWriter = null;
}
if (this.XmlContentStream != null)
{
this.XmlContentStream.Dispose();
this.XmlContentStream = null;
}
this.disposed = true;
}
}
internal void AddContentToTarget(XmlWriter target)
{
this.XmlContentWriter.Close();
this.XmlContentWriter = null;
this.XmlContentStream.Seek(0, SeekOrigin.Begin);
XmlReaderSettings customContentReaderSettings = new XmlReaderSettings();
customContentReaderSettings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader reader = XmlReader.Create(this.XmlContentStream, customContentReaderSettings);
this.XmlContentStream = null;
target.WriteNode(reader, false);
}
private void PopulateData(EpmTargetPathSegment segment, object element)
{
if (segment.EpmInfo != null)
{
Object propertyValue;
try
{
propertyValue = segment.EpmInfo.PropValReader.DynamicInvoke(element);
}
catch
(System.Reflection.TargetInvocationException)
{
throw;
}
this.Data = propertyValue == null ? String.Empty : ClientConvert.ToString(propertyValue, false );
}
}
}
}

View File

@@ -0,0 +1,59 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Collections.Generic;
internal class EpmSourcePathSegment
{
#region Fields
private String propertyName;
private List<EpmSourcePathSegment> subProperties;
#endregion
internal EpmSourcePathSegment(String propertyName)
{
this.propertyName = propertyName;
this.subProperties = new List<EpmSourcePathSegment>();
}
#region Properties
internal String PropertyName
{
get
{
return this.propertyName;
}
}
internal List<EpmSourcePathSegment> SubProperties
{
get
{
return this.subProperties;
}
}
internal EntityPropertyMappingInfo EpmInfo
{
get;
set;
}
#endregion
}
}

View File

@@ -0,0 +1,93 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Data.Services.Client;
internal sealed class EpmSourceTree
{
#region Fields
private readonly EpmSourcePathSegment root;
private readonly EpmTargetTree epmTargetTree;
#endregion
internal EpmSourceTree(EpmTargetTree epmTargetTree)
{
this.root = new EpmSourcePathSegment("");
this.epmTargetTree = epmTargetTree;
}
#region Properties
internal EpmSourcePathSegment Root
{
get
{
return this.root;
}
}
#endregion
internal void Add(EntityPropertyMappingInfo epmInfo)
{
String sourceName = epmInfo.Attribute.SourcePath;
EpmSourcePathSegment currentProperty = this.Root;
IList<EpmSourcePathSegment> activeSubProperties = currentProperty.SubProperties;
EpmSourcePathSegment foundProperty = null;
Debug.Assert(!String.IsNullOrEmpty(sourceName), "Must have been validated during EntityPropertyMappingAttribute construction");
foreach (String propertyName in sourceName.Split('/'))
{
if (propertyName.Length == 0)
{
throw new InvalidOperationException(Strings.EpmSourceTree_InvalidSourcePath(epmInfo.DefiningType.Name, sourceName));
}
foundProperty = activeSubProperties.SingleOrDefault(e => e.PropertyName == propertyName);
if (foundProperty != null)
{
currentProperty = foundProperty;
}
else
{
currentProperty = new EpmSourcePathSegment(propertyName);
activeSubProperties.Add(currentProperty);
}
activeSubProperties = currentProperty.SubProperties;
}
if (foundProperty != null)
{
Debug.Assert(Object.ReferenceEquals(foundProperty, currentProperty), "currentProperty variable should have been updated already to foundProperty");
if (foundProperty.EpmInfo.DefiningType.Name == epmInfo.DefiningType.Name)
{
throw new InvalidOperationException(Strings.EpmSourceTree_DuplicateEpmAttrsWithSameSourceName(epmInfo.Attribute.SourcePath, epmInfo.DefiningType.Name));
}
this.epmTargetTree.Remove(foundProperty.EpmInfo);
}
currentProperty.EpmInfo = epmInfo;
this.epmTargetTree.Add(epmInfo);
}
}
}

View File

@@ -0,0 +1,111 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Diagnostics;
using System.Collections.Generic;
[DebuggerDisplay("EpmTargetPathSegment {SegmentName} HasContent={HasContent}")]
internal class EpmTargetPathSegment
{
#region Private fields.
private String segmentName;
private String segmentNamespaceUri;
private String segmentNamespacePrefix;
private List<EpmTargetPathSegment> subSegments;
private EpmTargetPathSegment parentSegment;
#endregion Private fields.
internal EpmTargetPathSegment()
{
this.subSegments = new List<EpmTargetPathSegment>();
}
internal EpmTargetPathSegment(String segmentName, String segmentNamespaceUri, String segmentNamespacePrefix, EpmTargetPathSegment parentSegment)
: this()
{
this.segmentName = segmentName;
this.segmentNamespaceUri = segmentNamespaceUri;
this.segmentNamespacePrefix = segmentNamespacePrefix;
this.parentSegment = parentSegment;
}
internal String SegmentName
{
get
{
return this.segmentName;
}
}
internal String SegmentNamespaceUri
{
get
{
return this.segmentNamespaceUri;
}
}
internal String SegmentNamespacePrefix
{
get
{
return this.segmentNamespacePrefix;
}
}
internal EntityPropertyMappingInfo EpmInfo
{
get;
set;
}
internal bool HasContent
{
get
{
return this.EpmInfo != null;
}
}
internal bool IsAttribute
{
get
{
return this.SegmentName[0] == '@';
}
}
internal EpmTargetPathSegment ParentSegment
{
get
{
return this.parentSegment;
}
}
internal List<EpmTargetPathSegment> SubSegments
{
get
{
return this.subSegments;
}
}
}
}

View File

@@ -0,0 +1,207 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Data.Services.Client;
internal sealed class EpmTargetTree
{
private int countOfNonContentProperties;
internal EpmTargetTree()
{
this.SyndicationRoot = new EpmTargetPathSegment();
this.NonSyndicationRoot = new EpmTargetPathSegment();
}
internal EpmTargetPathSegment SyndicationRoot
{
get;
private set;
}
internal EpmTargetPathSegment NonSyndicationRoot
{
get;
private set;
}
internal bool IsV1Compatible
{
get
{
return this.countOfNonContentProperties == 0;
}
}
internal void Add(EntityPropertyMappingInfo epmInfo)
{
String targetName = epmInfo.Attribute.TargetPath;
bool isSyndication = epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty;
String namespaceUri = epmInfo.Attribute.TargetNamespaceUri;
String namespacePrefix = epmInfo.Attribute.TargetNamespacePrefix;
EpmTargetPathSegment currentSegment = isSyndication ? this.SyndicationRoot : this.NonSyndicationRoot;
IList<EpmTargetPathSegment> activeSubSegments = currentSegment.SubSegments;
Debug.Assert(!String.IsNullOrEmpty(targetName), "Must have been validated during EntityPropertyMappingAttribute construction");
String[] targetSegments = targetName.Split('/');
for (int i = 0; i < targetSegments.Length; i++)
{
String targetSegment = targetSegments[i];
if (targetSegment.Length == 0)
{
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
}
if (targetSegment[0] == '@' && i != targetSegments.Length - 1)
{
throw new InvalidOperationException(Strings.EpmTargetTree_AttributeInMiddle(targetSegment));
}
EpmTargetPathSegment foundSegment = activeSubSegments.SingleOrDefault(
segment => segment.SegmentName == targetSegment &&
(isSyndication || segment.SegmentNamespaceUri == namespaceUri));
if (foundSegment != null)
{
currentSegment = foundSegment;
}
else
{
currentSegment = new EpmTargetPathSegment(targetSegment, namespaceUri, namespacePrefix, currentSegment);
if (targetSegment[0] == '@')
{
activeSubSegments.Insert(0, currentSegment);
}
else
{
activeSubSegments.Add(currentSegment);
}
}
activeSubSegments = currentSegment.SubSegments;
}
if (currentSegment.HasContent)
{
throw new ArgumentException(Strings.EpmTargetTree_DuplicateEpmAttrsWithSameTargetName(EpmTargetTree.GetPropertyNameFromEpmInfo(currentSegment.EpmInfo), currentSegment.EpmInfo.DefiningType.Name, currentSegment.EpmInfo.Attribute.SourcePath, epmInfo.Attribute.SourcePath));
}
if (!epmInfo.Attribute.KeepInContent)
{
this.countOfNonContentProperties++;
}
currentSegment.EpmInfo = epmInfo;
if (EpmTargetTree.HasMixedContent(this.NonSyndicationRoot, false))
{
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
}
}
internal void Remove(EntityPropertyMappingInfo epmInfo)
{
String targetName = epmInfo.Attribute.TargetPath;
bool isSyndication = epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty;
String namespaceUri = epmInfo.Attribute.TargetNamespaceUri;
EpmTargetPathSegment currentSegment = isSyndication ? this.SyndicationRoot : this.NonSyndicationRoot;
List<EpmTargetPathSegment> activeSubSegments = currentSegment.SubSegments;
Debug.Assert(!String.IsNullOrEmpty(targetName), "Must have been validated during EntityPropertyMappingAttribute construction");
String[] targetSegments = targetName.Split('/');
for (int i = 0; i < targetSegments.Length; i++)
{
String targetSegment = targetSegments[i];
if (targetSegment.Length == 0)
{
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
}
if (targetSegment[0] == '@' && i != targetSegments.Length - 1)
{
throw new InvalidOperationException(Strings.EpmTargetTree_AttributeInMiddle(targetSegment));
}
EpmTargetPathSegment foundSegment = activeSubSegments.FirstOrDefault(
segment => segment.SegmentName == targetSegment &&
(isSyndication || segment.SegmentNamespaceUri == namespaceUri));
if (foundSegment != null)
{
currentSegment = foundSegment;
}
else
{
return;
}
activeSubSegments = currentSegment.SubSegments;
}
if (currentSegment.HasContent)
{
if (!currentSegment.EpmInfo.Attribute.KeepInContent)
{
this.countOfNonContentProperties--;
}
do
{
EpmTargetPathSegment parentSegment = currentSegment.ParentSegment;
parentSegment.SubSegments.Remove(currentSegment);
currentSegment = parentSegment;
}
while (currentSegment.ParentSegment != null && !currentSegment.HasContent && currentSegment.SubSegments.Count == 0);
}
}
private static bool HasMixedContent(EpmTargetPathSegment currentSegment, bool ancestorHasContent)
{
foreach (EpmTargetPathSegment childSegment in currentSegment.SubSegments.Where(s => !s.IsAttribute))
{
if (childSegment.HasContent && ancestorHasContent)
{
return true;
}
if (HasMixedContent(childSegment, childSegment.HasContent || ancestorHasContent))
{
return true;
}
}
return false;
}
private static String GetPropertyNameFromEpmInfo(EntityPropertyMappingInfo epmInfo)
{
{
if (epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty)
{
return epmInfo.Attribute.TargetSyndicationItem.ToString();
}
else
{
return epmInfo.Attribute.TargetPath;
}
}
}
}
}

View File

@@ -0,0 +1,399 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Client
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
internal static class HttpProcessUtility
{
internal static readonly UTF8Encoding EncodingUtf8NoPreamble = new UTF8Encoding(false, true);
internal static Encoding FallbackEncoding
{
get
{
return EncodingUtf8NoPreamble;
}
}
private static Encoding MissingEncoding
{
get
{
#if ASTORIA_LIGHT
return Encoding.UTF8;
#else
return Encoding.GetEncoding("ISO-8859-1", new EncoderExceptionFallback(), new DecoderExceptionFallback());
#endif
}
}
internal static KeyValuePair<string, string>[] ReadContentType(string contentType, out string mime, out Encoding encoding)
{
if (String.IsNullOrEmpty(contentType))
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_ContentTypeMissing);
}
MediaType mediaType = ReadMediaType(contentType);
mime = mediaType.MimeType;
encoding = mediaType.SelectEncoding();
return mediaType.Parameters;
}
internal static bool TryReadVersion(string text, out KeyValuePair<Version, string> result)
{
Debug.Assert(text != null, "text != null");
int separator = text.IndexOf(';');
string versionText, libraryName;
if (separator >= 0)
{
versionText = text.Substring(0, separator);
libraryName = text.Substring(separator + 1).Trim();
}
else
{
versionText = text;
libraryName = null;
}
result = default(KeyValuePair<Version, string>);
versionText = versionText.Trim();
bool dotFound = false;
for (int i = 0; i < versionText.Length; i++)
{
if (versionText[i] == '.')
{
if (dotFound)
{
return false;
}
dotFound = true;
}
else if (versionText[i] < '0' || versionText[i] > '9')
{
return false;
}
}
try
{
result = new KeyValuePair<Version, string>(new Version(versionText), libraryName);
return true;
}
catch (Exception e)
{
if (e is FormatException || e is OverflowException || e is ArgumentException)
{
return false;
}
throw;
}
}
private static Encoding EncodingFromName(string name)
{
if (name == null)
{
return MissingEncoding;
}
name = name.Trim();
if (name.Length == 0)
{
return MissingEncoding;
}
else
{
try
{
#if ASTORIA_LIGHT
return Encoding.UTF8;
#else
return Encoding.GetEncoding(name);
#endif
}
catch (ArgumentException)
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_EncodingNotSupported(name));
}
}
}
private static void ReadMediaTypeAndSubtype(string text, ref int textIndex, out string type, out string subType)
{
Debug.Assert(text != null, "text != null");
int textStart = textIndex;
if (ReadToken(text, ref textIndex))
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeUnspecified);
}
if (text[textIndex] != '/')
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeRequiresSlash);
}
type = text.Substring(textStart, textIndex - textStart);
textIndex++;
int subTypeStart = textIndex;
ReadToken(text, ref textIndex);
if (textIndex == subTypeStart)
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeRequiresSubType);
}
subType = text.Substring(subTypeStart, textIndex - subTypeStart);
}
private static MediaType ReadMediaType(string text)
{
Debug.Assert(text != null, "text != null");
string type;
string subType;
int textIndex = 0;
ReadMediaTypeAndSubtype(text, ref textIndex, out type, out subType);
KeyValuePair<string, string>[] parameters = null;
while (!SkipWhitespace(text, ref textIndex))
{
if (text[textIndex] != ';')
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeRequiresSemicolonBeforeParameter);
}
textIndex++;
if (SkipWhitespace(text, ref textIndex))
{
break;
}
ReadMediaTypeParameter(text, ref textIndex, ref parameters);
}
return new MediaType(type, subType, parameters);
}
private static bool ReadToken(string text, ref int textIndex)
{
while (textIndex < text.Length && IsHttpToken(text[textIndex]))
{
textIndex++;
}
return (textIndex == text.Length);
}
private static bool SkipWhitespace(string text, ref int textIndex)
{
Debug.Assert(text != null, "text != null");
Debug.Assert(text.Length >= 0, "text >= 0");
Debug.Assert(textIndex <= text.Length, "text <= text.Length");
while (textIndex < text.Length && Char.IsWhiteSpace(text, textIndex))
{
textIndex++;
}
return (textIndex == text.Length);
}
private static void ReadMediaTypeParameter(string text, ref int textIndex, ref KeyValuePair<string, string>[] parameters)
{
int startIndex = textIndex;
if (ReadToken(text, ref textIndex))
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeMissingValue);
}
string parameterName = text.Substring(startIndex, textIndex - startIndex);
if (text[textIndex] != '=')
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_MediaTypeMissingValue);
}
textIndex++;
string parameterValue = ReadQuotedParameterValue(parameterName, text, ref textIndex);
if (parameters == null)
{
parameters = new KeyValuePair<string, string>[1];
}
else
{
KeyValuePair<string, string>[] grow = new KeyValuePair<string, string>[parameters.Length + 1];
Array.Copy(parameters, grow, parameters.Length);
parameters = grow;
}
parameters[parameters.Length - 1] = new KeyValuePair<string, string>(parameterName, parameterValue);
}
private static string ReadQuotedParameterValue(string parameterName, string headerText, ref int textIndex)
{
StringBuilder parameterValue = new StringBuilder();
bool valueIsQuoted = false;
if (textIndex < headerText.Length)
{
if (headerText[textIndex] == '\"')
{
textIndex++;
valueIsQuoted = true;
}
}
while (textIndex < headerText.Length)
{
char currentChar = headerText[textIndex];
if (currentChar == '\\' || currentChar == '\"')
{
if (!valueIsQuoted)
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_EscapeCharWithoutQuotes(parameterName));
}
textIndex++;
if (currentChar == '\"')
{
valueIsQuoted = false;
break;
}
if (textIndex >= headerText.Length)
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_EscapeCharAtEnd(parameterName));
}
currentChar = headerText[textIndex];
}
else
if (!IsHttpToken(currentChar))
{
break;
}
parameterValue.Append(currentChar);
textIndex++;
}
if (valueIsQuoted)
{
throw Error.HttpHeaderFailure(400, Strings.HttpProcessUtility_ClosingQuoteNotFound(parameterName));
}
return parameterValue.ToString();
}
private static bool IsHttpSeparator(char c)
{
return
c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' ||
c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
c == '{' || c == '}' || c == ' ' || c == '\x9';
}
private static bool IsHttpToken(char c)
{
return c < '\x7F' && c > '\x1F' && !IsHttpSeparator(c);
}
[DebuggerDisplay("MediaType [{type}/{subType}]")]
private sealed class MediaType
{
private readonly KeyValuePair<string, string>[] parameters;
private readonly string subType;
private readonly string type;
internal MediaType(string type, string subType, KeyValuePair<string, string>[] parameters)
{
Debug.Assert(type != null, "type != null");
Debug.Assert(subType != null, "subType != null");
this.type = type;
this.subType = subType;
this.parameters = parameters;
}
internal string MimeType
{
get { return this.type + "/" + this.subType; }
}
internal KeyValuePair<string, string>[] Parameters
{
get { return this.parameters; }
}
internal Encoding SelectEncoding()
{
if (this.parameters != null)
{
foreach (KeyValuePair<string, string> parameter in this.parameters)
{
if (String.Equals(parameter.Key, XmlConstants.HttpCharsetParameter, StringComparison.OrdinalIgnoreCase))
{
string encodingName = parameter.Value.Trim();
if (encodingName.Length > 0)
{
return EncodingFromName(parameter.Value);
}
}
}
}
if (String.Equals(this.type, XmlConstants.MimeTextType, StringComparison.OrdinalIgnoreCase))
{
if (String.Equals(this.subType, XmlConstants.MimeXmlSubType, StringComparison.OrdinalIgnoreCase))
{
return null;
}
else
{
return MissingEncoding;
}
}
else if (String.Equals(this.type, XmlConstants.MimeApplicationType, StringComparison.OrdinalIgnoreCase) &&
String.Equals(this.subType, XmlConstants.MimeJsonSubType, StringComparison.OrdinalIgnoreCase))
{
return FallbackEncoding;
}
else
{
return null;
}
}
}
}
}

View File

@@ -0,0 +1,192 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Parsing
{
using System;
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Data.Services.Client;
internal static class WebConvert
{
private const string HexValues = "0123456789ABCDEF";
private const string XmlHexEncodePrefix = "0x";
internal static string ConvertByteArrayToKeyString(byte[] byteArray)
{
StringBuilder hexBuilder = new StringBuilder(3 + byteArray.Length * 2);
hexBuilder.Append(XmlConstants.XmlBinaryPrefix);
hexBuilder.Append("'");
for (int i = 0; i < byteArray.Length; i++)
{
hexBuilder.Append(HexValues[byteArray[i] >> 4]);
hexBuilder.Append(HexValues[byteArray[i] & 0x0F]);
}
hexBuilder.Append("'");
return hexBuilder.ToString();
}
internal static bool IsKeyTypeQuoted(Type type)
{
Debug.Assert(type != null, "type != null");
return type == typeof(System.Xml.Linq.XElement) || type == typeof(string);
}
internal static bool TryKeyPrimitiveToString(object value, out string result)
{
Debug.Assert(value != null, "value != null");
if (value.GetType() == typeof(byte[]))
{
result = ConvertByteArrayToKeyString((byte[])value);
}
else
{
if (!TryXmlPrimitiveToString(value, out result))
{
return false;
}
Debug.Assert(result != null, "result != null");
if (value.GetType() == typeof(DateTime))
{
result = XmlConstants.LiteralPrefixDateTime + "'" + result + "'";
}
else if (value.GetType() == typeof(Decimal))
{
result = result + XmlConstants.XmlDecimalLiteralSuffix;
}
else if (value.GetType() == typeof(Guid))
{
result = XmlConstants.LiteralPrefixGuid + "'" + result + "'";
}
else if (value.GetType() == typeof(Int64))
{
result = result + XmlConstants.XmlInt64LiteralSuffix;
}
else if (value.GetType() == typeof(Single))
{
result = result + XmlConstants.XmlSingleLiteralSuffix;
}
else if (value.GetType() == typeof(double))
{
result = AppendDecimalMarkerToDouble(result);
}
else if (IsKeyTypeQuoted(value.GetType()))
{
result = "'" + result.Replace("'", "''") + "'";
}
}
return true;
}
internal static bool TryXmlPrimitiveToString(object value, out string result)
{
Debug.Assert(value != null, "value != null");
result = null;
Type valueType = value.GetType();
valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;
if (typeof(String) == valueType)
{
result = (string)value;
}
else if (typeof(Boolean) == valueType)
{
result = XmlConvert.ToString((bool)value);
}
else if (typeof(Byte) == valueType)
{
result = XmlConvert.ToString((byte)value);
}
else if (typeof(DateTime) == valueType)
{
result = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
}
else if (typeof(Decimal) == valueType)
{
result = XmlConvert.ToString((decimal)value);
}
else if (typeof(Double) == valueType)
{
result = XmlConvert.ToString((double)value);
}
else if (typeof(Guid) == valueType)
{
result = value.ToString();
}
else if (typeof(Int16) == valueType)
{
result = XmlConvert.ToString((Int16)value);
}
else if (typeof(Int32) == valueType)
{
result = XmlConvert.ToString((Int32)value);
}
else if (typeof(Int64) == valueType)
{
result = XmlConvert.ToString((Int64)value);
}
else if (typeof(SByte) == valueType)
{
result = XmlConvert.ToString((SByte)value);
}
else if (typeof(Single) == valueType)
{
result = XmlConvert.ToString((Single)value);
}
else if (typeof(byte[]) == valueType)
{
byte[] byteArray = (byte[])value;
result = Convert.ToBase64String(byteArray);
}
#if !ASTORIA_LIGHT
else if (ClientConvert.IsBinaryValue(value))
{
return ClientConvert.TryKeyBinaryToString(value, out result);
}
#endif
else if (typeof(System.Xml.Linq.XElement) == valueType)
{
result = ((System.Xml.Linq.XElement)value).ToString(System.Xml.Linq.SaveOptions.None);
}
else
{
result = null;
return false;
}
Debug.Assert(result != null, "result != null");
return true;
}
private static string AppendDecimalMarkerToDouble(string input)
{
foreach (char c in input)
{
if (!Char.IsDigit(c))
{
return input;
}
}
return input + ".0";
}
}
}

View File

@@ -0,0 +1,35 @@
//Copyright 2010 Microsoft Corporation
//
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and limitations under the License.
namespace System.Data.Services.Common
{
[System.Diagnostics.DebuggerDisplay("EntityPropertyMappingInfo {DefiningType}")]
internal sealed class EntityPropertyMappingInfo
{
public EntityPropertyMappingAttribute Attribute
{
get; set;
}
public Delegate PropValReader
{
get;
set;
}
public Type DefiningType
{
get;
set;
}
}
}