Пример #1
0
        /// <summary>
        /// Validates an <see cref="ODataStreamReferenceValue"/> to ensure all required information is specified and valid.
        /// </summary>
        /// <param name="streamReference">The stream reference to validate.</param>
        /// <param name="isDefaultStream">true if <paramref name="streamReference"/> is the default stream for an entity; false if it is a named stream property value.</param>
        internal static void ValidateStreamReferenceValue(ODataStreamReferenceValue streamReference, bool isDefaultStream)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(streamReference != null, "streamReference != null");

            if (streamReference.ContentType != null && streamReference.ContentType.Length == 0)
            {
                throw new ODataException(Strings.WriterValidationUtils_StreamReferenceValueEmptyContentType);
            }

            if (isDefaultStream && streamReference.ReadLink == null && streamReference.ContentType != null)
            {
                throw new ODataException(Strings.WriterValidationUtils_DefaultStreamWithContentTypeWithoutReadLink);
            }

            if (isDefaultStream && streamReference.ReadLink != null && streamReference.ContentType == null)
            {
                throw new ODataException(Strings.WriterValidationUtils_DefaultStreamWithReadLinkWithoutContentType);
            }

            // Default stream can be completely empty (no links or anything)
            // that is used to effectively mark the entry as MLE without providing any MR information.
            // OData clients when creating new MLE/MR might not have the MR information (yet) when sending the first PUT, but they still
            // need to mark the entry as MLE so that properties are written out-of-content. In such scenario the client can just set an empty
            // default stream to mark the entry as MLE.
            // That will cause the ATOM writer to write the properties outside the content without producing any content element.
            if (streamReference.EditLink == null && streamReference.ReadLink == null && !isDefaultStream)
            {
                throw new ODataException(Strings.WriterValidationUtils_StreamReferenceValueMustHaveEditLinkOrReadLink);
            }

            if (streamReference.EditLink == null && streamReference.ETag != null)
            {
                throw new ODataException(Strings.WriterValidationUtils_StreamReferenceValueMustHaveEditLinkToHaveETag);
            }
        }
        /// <summary>
        /// Check the <paramref name="property"/> for duplicate property names in an entry or complex value.
        /// If not explicitly allowed throw when duplicate properties are detected.
        /// If duplicate properties are allowed see the comment on ODataWriterBehavior.AllowDuplicatePropertyNames
        /// or ODataReaderBehavior.AllowDuplicatePropertyNames for further details.
        /// </summary>
        /// <param name="property">The property to be checked.</param>
        internal void CheckForDuplicatePropertyNames(ODataProperty property)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(property != null, "property != null");
#if DEBUG
            Debug.Assert(this.startNavigationLinkName == null, "CheckForDuplicatePropertyNamesOnNavigationLinkStart was followed by a CheckForDuplicatePropertyNames(ODataProperty).");
#endif

            string            propertyName    = property.Name;
            DuplicationKind   duplicationKind = GetDuplicationKind(property);
            DuplicationRecord existingDuplicationRecord;
            if (!this.TryGetDuplicationRecord(propertyName, out existingDuplicationRecord))
            {
                this.propertyNameCache.Add(propertyName, new DuplicationRecord(duplicationKind));
            }
            else
            {
                // If either of them prohibits duplication, fail
                // If the existing one is an association link, fail (association links don't allow duplicates with simple properties)
                // If we don't allow duplication in the first place, fail, since there is no valid case where a simple property coexists with anything else with the same name.
                if (existingDuplicationRecord.DuplicationKind == DuplicationKind.Prohibited ||
                    duplicationKind == DuplicationKind.Prohibited ||
                    (existingDuplicationRecord.DuplicationKind == DuplicationKind.NavigationProperty && existingDuplicationRecord.AssociationLinkFound) ||
                    !this.allowDuplicateProperties)
                {
                    throw new ODataException(Strings.DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed(propertyName));
                }
                else
                {
                    // Otherwise allow the duplicate.
                    // Note that we don't modify the existing duplication record in any way if the new property is a simple property.
                    // This is because if the existing one is a simple property which allows duplication as well, there's nothing to change.
                    // and if the existing one is a navigation property the navigation property information is more important than the simple property one.
                }
            }
        }
Пример #3
0
        /// <summary>Reads a Content-Type header and extracts the media type's name (type/subtype) and parameters.</summary>
        /// <param name="contentType">The Content-Type header.</param>
        /// <param name="mediaTypeName">The media type in standard type/subtype form, without parameters.</param>
        /// <param name="mediaTypeCharset">The (optional) charset parameter of the media type.</param>
        /// <returns>The parameters of the media type not including the 'charset' parameter.</returns>
        internal static IList <KeyValuePair <string, string> > ReadMimeType(string contentType, out string mediaTypeName, out string mediaTypeCharset)
        {
            DebugUtils.CheckNoExternalCallers();
            if (String.IsNullOrEmpty(contentType))
            {
                throw new ODataContentTypeException(Strings.HttpUtils_ContentTypeMissing);
            }

            IList <KeyValuePair <MediaType, string> > mediaTypes = ReadMediaTypes(contentType);

            if (mediaTypes.Count != 1)
            {
                throw new ODataContentTypeException(Strings.HttpUtils_NoOrMoreThanOneContentTypeSpecified(contentType));
            }

            MediaType mediaType = mediaTypes[0].Key;

            MediaTypeUtils.CheckMediaTypeForWildCards(mediaType);

            mediaTypeName    = mediaType.FullTypeName;
            mediaTypeCharset = mediaTypes[0].Value;

            return(mediaType.Parameters);
        }
Пример #4
0
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</param>
        /// <param name="undeclaredPropertyBehaviorKinds">Value of UndeclaredPropertyBehaviorKinds in message settings.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataUndeclaredPropertyBehaviorKinds undeclaredPropertyBehaviorKinds)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            if (owningStructuredType == null)
            {
                return(null);
            }

            // .None / .LinkProperty
            bool throwErr = !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty) &&
                            !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.SupportUndeclaredValueProperty);

            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            // verify that the property is declared if the type is not an open type.
            if (throwErr && !owningStructuredType.IsOpen && property == null)
            {
                throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
            }

            return(property);
        }
Пример #5
0
        /// <summary>
        /// Validates that a navigation property with the specified name exists on a given entity type.
        /// The entity type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningEntityType">The owning entity type or null if no metadata is available.</param>
        /// <param name="undeclaredPropertyBehaviorKinds">Value of UndeclaredPropertyBehaviorKinds in message settings.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the navigation property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</returns>
        internal static IEdmNavigationProperty ValidateNavigationPropertyDefined(string propertyName, IEdmEntityType owningEntityType, ODataUndeclaredPropertyBehaviorKinds undeclaredPropertyBehaviorKinds)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

            if (owningEntityType == null)
            {
                return(null);
            }

            IEdmProperty property = ValidatePropertyDefined(propertyName, owningEntityType, undeclaredPropertyBehaviorKinds);

            if (property == null)
            {
                // .None / .LinkProperty
                bool throwErr = !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty) &&
                                !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.SupportUndeclaredValueProperty);

                // We don't support open navigation properties
                // when writing undeclared property is supported, shouldn't throw exception
                if (throwErr)
                {
                    Debug.Assert(owningEntityType.IsOpen, "We should have already failed on non-existing property on a closed type.");
                }

                throw new ODataException(Strings.ValidationUtils_OpenNavigationProperty(propertyName, owningEntityType.ODataFullName()));
            }

            if (property.PropertyKind != EdmPropertyKind.Navigation)
            {
                // The property must be a navigation property
                throw new ODataException(Strings.ValidationUtils_NavigationPropertyExpected(propertyName, owningEntityType.ODataFullName(), property.PropertyKind.ToString()));
            }

            return((IEdmNavigationProperty)property);
        }
Пример #6
0
        /// <summary>
        /// Does an ordinal ignore case comparision of the given media type names.
        /// </summary>
        /// <param name="mediaTypeName1">First media type name.</param>
        /// <param name="mediaTypeName2">Second media type name.</param>
        /// <returns>returns true if the media type names are the same.</returns>
        internal static bool CompareMediaTypeNames(string mediaTypeName1, string mediaTypeName2)
        {
            DebugUtils.CheckNoExternalCallers();

            return(string.Equals(mediaTypeName1, mediaTypeName2, StringComparison.OrdinalIgnoreCase));
        }
Пример #7
0
        internal static string GetStatusMessage(int statusCode)
        {
            DebugUtils.CheckNoExternalCallers();

            // Non-localized messages for status codes.
            // These are the recommended reason phrases as per HTTP RFC 2616, Section 6.1.1
            switch (statusCode)
            {
            case 100:
                return("Continue");

            case 101:
                return("Switching Protocols");

            case 200:
                return("OK");

            case 201:
                return("Created");

            case 202:
                return("Accepted");

            case 203:
                return("Non-Authoritative Information");

            case 204:
                return("No Content");

            case 205:
                return("Reset Content");

            case 206:
                return("Partial Content");

            case 300:
                return("Multiple Choices");

            case 301:
                return("Moved Permanently");

            case 302:
                return("Found");

            case 303:
                return("See Other");

            case 304:
                return("Not Modified");

            case 305:
                return("Use Proxy");

            case 307:
                return("Temporary Redirect");

            case 400:
                return("Bad Request");

            case 401:
                return("Unauthorized");

            case 402:
                return("Payment Required");

            case 403:
                return("Forbidden");

            case 404:
                return("Not Found");

            case 405:
                return("Method Not Allowed");

            case 406:
                return("Not Acceptable");

            case 407:
                return("Proxy Authentication Required");

            case 408:
                return("Request Time-out");

            case 409:
                return("Conflict");

            case 410:
                return("Gone");

            case 411:
                return("Length Required");

            case 412:
                return("Precondition Failed");

            case 413:
                return("Request Entity Too Large");

            case 414:
                return("Request-URI Too Large");

            case 415:
                return("Unsupported Media Type");

            case 416:
                return("Requested range not satisfiable");

            case 417:
                return("Expectation Failed");

            case 500:
                return("Internal Server Error");

            case 501:
                return("Not Implemented");

            case 502:
                return("Bad Gateway");

            case 503:
                return("Service Unavailable");

            case 504:
                return("Gateway Time-out");

            case 505:
                return("HTTP Version not supported");

            default:
                return("Unknown Status Code");
            }
        }
Пример #8
0
 /// <summary>
 /// Asynchronously flushes a stream.
 /// </summary>
 /// <param name="stream">The stream to flush.</param>
 /// <returns>Task which represents the pending Flush operation.</returns>
 internal static Task FlushAsync(this Stream stream)
 {
     DebugUtils.CheckNoExternalCallers();
     return(Task.Factory.StartNew(stream.Flush));
 }
Пример #9
0
        /// <summary>Converts the specified value to a serializable string in ATOM format.</summary>
        /// <param name="value">Non-null value to convert.</param>
        /// <param name="result">The specified value converted to an ATOM string.</param>
        /// <returns>boolean value indicating conversion successful conversion</returns>
        internal static bool TryConvertPrimitiveToString(object value, out string result)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(value != null, "value != null");
            result = null;

            TypeCode typeCode = PlatformHelper.GetTypeCode(value.GetType());

            switch (typeCode)
            {
            case TypeCode.Boolean:
                result = ODataAtomConvert.ToString((bool)value);
                break;

            case TypeCode.Byte:
                result = ODataAtomConvert.ToString((byte)value);
                break;

            case TypeCode.DateTime:
                result = ODataAtomConvert.ToString((DateTime)value);
                break;

            case TypeCode.Decimal:
                result = ODataAtomConvert.ToString((decimal)value);
                break;

            case TypeCode.Double:
                result = ODataAtomConvert.ToString((double)value);
                break;

            case TypeCode.Int16:
                result = ODataAtomConvert.ToString((Int16)value);
                break;

            case TypeCode.Int32:
                result = ODataAtomConvert.ToString((Int32)value);
                break;

            case TypeCode.Int64:
                result = ODataAtomConvert.ToString((Int64)value);
                break;

            case TypeCode.SByte:
                result = ODataAtomConvert.ToString((SByte)value);
                break;

            case TypeCode.String:
                result = (string)value;
                break;

            case TypeCode.Single:
                result = ODataAtomConvert.ToString((Single)value);
                break;

            default:
                byte[] bytes = value as byte[];
                if (bytes != null)
                {
                    result = ODataAtomConvert.ToString(bytes);
                    break;
                }

                if (value is DateTimeOffset)
                {
                    result = ODataAtomConvert.ToString((DateTimeOffset)value);
                    break;
                }

                if (value is Guid)
                {
                    result = ODataAtomConvert.ToString((Guid)value);
                    break;
                }

                if (value is TimeSpan)
                {
                    // Edm.Time
                    result = ODataAtomConvert.ToString((TimeSpan)value);
                    break;
                }

                return(false);
            }

            Debug.Assert(result != null, "result != null");
            return(true);
        }
Пример #10
0
 /// <summary>
 /// Initializes a new <see cref="MediaType"/> read-only instance.
 /// </summary>
 /// <param name="type">Type specification (for example, 'text').</param>
 /// <param name="subType">Sub-type specification (for example, 'plain').</param>
 internal MediaType(string type, string subType)
     : this(type, subType, null)
 {
     DebugUtils.CheckNoExternalCallers();
 }
Пример #11
0
 /// <summary>
 /// Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should be skipped, false otherwise.
 /// </summary>
 /// <param name="annotationName">The name of the annotation in question.</param>
 /// <returns>Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should be skipped, false otherwise.</returns>
 internal bool ShouldSkipAnnotation(string annotationName)
 {
     DebugUtils.CheckNoExternalCallers();
     return(this.MaxProtocolVersion < ODataVersion.V3 || this.ShouldIncludeAnnotation == null || !this.ShouldIncludeAnnotation(annotationName));
 }
 /// <summary>
 /// Create a batch operation read stream over the specified batch stream using the batch delimiter to detect the end of the stream.
 /// </summary>
 /// <param name="batchReaderStream">The batch stream underlying the operation stream to create.</param>
 /// <param name="listener">The batch operation listener.</param>
 /// <returns>A <see cref="ODataBatchOperationReadStream"/> to read the content of a batch operation from.</returns>
 internal static ODataBatchOperationReadStream Create(ODataBatchReaderStream batchReaderStream, IODataBatchOperationListener listener)
 {
     DebugUtils.CheckNoExternalCallers();
     return(new ODataBatchOperationReadStreamWithDelimiter(batchReaderStream, listener));
 }
 /// <summary>
 /// Create a batch operation read stream over the specified batch stream with a given content length.
 /// </summary>
 /// <param name="batchReaderStream">The batch stream underlying the operation stream to create.</param>
 /// <param name="listener">The batch operation listener.</param>
 /// <param name="length">The content length of the operation stream.</param>
 /// <returns>A <see cref="ODataBatchOperationReadStream"/> to read the content of a batch operation from.</returns>
 internal static ODataBatchOperationReadStream Create(ODataBatchReaderStream batchReaderStream, IODataBatchOperationListener listener, int length)
 {
     DebugUtils.CheckNoExternalCallers();
     return(new ODataBatchOperationReadStreamWithLength(batchReaderStream, listener, length));
 }
Пример #14
0
        internal Task FlushAsync()
#endif
        {
            DebugUtils.CheckNoExternalCallers();
            return(this.FlushAsyncInternal());
        }
Пример #15
0
        /// <summary>
        /// Verifies that <paramref name="annotation"/> can be added as an annotation of this.
        /// </summary>
        /// <param name="annotation">Annotation instance.</param>
        internal override void VerifySetAnnotation(object annotation)
        {
            DebugUtils.CheckNoExternalCallers();

            // We block InstanceAnnotationCollection at the ODataAnnotatable level, but specifically allow them here
        }
Пример #16
0
 /// <summary>
 /// Constructor which initializes the enumerable with an empty list storage.
 /// </summary>
 internal ReadOnlyEnumerable()
     : this(new List <T>())
 {
     DebugUtils.CheckNoExternalCallers();
 }
Пример #17
0
 /// <summary>
 /// Gets the empty instance of ReadOnlyEnumerableOfT.
 /// </summary>
 /// <returns>Returns the empty instance of ReadOnlyEnumerableOfT.</returns>
 internal static ReadOnlyEnumerable <T> Empty()
 {
     DebugUtils.CheckNoExternalCallers();
     return(EmptyInstance.Value);
 }
Пример #18
0
        internal static IEdmType ValidateNavigationLink(ODataNavigationLink navigationLink, IEdmEntityType declaringEntityType, ODataPayloadKind?expandedPayloadKind)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(
                !expandedPayloadKind.HasValue ||
                expandedPayloadKind.Value == ODataPayloadKind.EntityReferenceLink ||
                expandedPayloadKind.Value == ODataPayloadKind.Entry ||
                expandedPayloadKind.Value == ODataPayloadKind.Feed,
                "If an expanded payload kind is specified it must be entry, feed or entity reference link.");

            // Navigation link must have a non-empty name
            if (string.IsNullOrEmpty(navigationLink.Name))
            {
                throw new ODataException(Strings.ValidationUtils_LinkMustSpecifyName);
            }

            // If we write an entity reference link, don't validate the multiplicity of the IsCollection
            // property if it is 'false' (since we allow writing a singleton navigation link for
            // a colleciton navigation property in requests) nor the consistency of payload kind and metadata
            // (which is done separately in ODataWriterCore.CheckForNavigationLinkWithContent).
            bool isEntityReferenceLinkPayload = expandedPayloadKind == ODataPayloadKind.EntityReferenceLink;

            // true only if the expandedPayloadKind has a value and the value is 'Feed'
            bool isFeedPayload = expandedPayloadKind == ODataPayloadKind.Feed;

            // Make sure the IsCollection property agrees with the payload kind for entry and feed payloads
            Func <object, string> errorTemplate = null;

            if (!isEntityReferenceLinkPayload && navigationLink.IsCollection.HasValue && expandedPayloadKind.HasValue)
            {
                // For feed/entry make sure the IsCollection property is set correctly.
                if (isFeedPayload != navigationLink.IsCollection.Value)
                {
                    errorTemplate = expandedPayloadKind.Value == ODataPayloadKind.Feed
                        ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent
                        : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent;
                }
            }

            IEdmType navigationPropertyType = null;

            if (declaringEntityType != null)
            {
                IEdmProperty navigationProperty = WriterValidationUtils.ValidateNavigationPropertyDefined(navigationLink.Name, declaringEntityType);
                Debug.Assert(navigationProperty != null, "If we have a declaring type we expect a non-null navigation property since open nav props are not allowed.");

                navigationPropertyType = navigationProperty.Type.Definition;
                bool isCollectionType = navigationPropertyType.TypeKind == EdmTypeKind.Collection;

                // Make sure the IsCollection property agrees with the metadata type for entry and feed payloads
                if (navigationLink.IsCollection.HasValue && isCollectionType != navigationLink.IsCollection)
                {
                    // Ignore the case where IsCollection is 'false' and we are writing an entity reference link
                    // (see comment above)
                    if (!(navigationLink.IsCollection == false && isEntityReferenceLinkPayload))
                    {
                        errorTemplate = isCollectionType
                            ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata
                            : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata;
                    }
                }

                // Make sure that the payload kind agrees with the metadata.
                // For entity reference links we check separately in ODataWriterCore.CheckForNavigationLinkWithContent.
                if (!isEntityReferenceLinkPayload && expandedPayloadKind.HasValue && isCollectionType != isFeedPayload)
                {
                    errorTemplate = isCollectionType
                        ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata
                        : Strings.WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata;
                }
            }

            if (errorTemplate != null)
            {
                string uri = navigationLink.Url == null ? "null" : UriUtilsCommon.UriToString(navigationLink.Url);
                throw new ODataException(errorTemplate(uri));
            }

            return(navigationPropertyType);
        }
Пример #19
0
        /// <summary>
        /// Converts the current <see cref="MediaType"/> to a string representation suitable for use in a content-type header.
        /// </summary>
        /// <returns>The string representation of media type.</returns>
        internal string ToText()
        {
            DebugUtils.CheckNoExternalCallers();

            return(ToText(null));
        }
Пример #20
0
 /// <summary>
 /// true if <paramref name="source"/> is the same instance as ReadOnlyEnumerableOfT.Empty(). false otherwise.
 /// </summary>
 /// <typeparam name="T">The element type of the enumerable.</typeparam>
 /// <param name="source">The enumerable in question.</param>
 /// <returns>Returns true if <paramref name="source"/> is the empty ReadOnlyEnumerableOfT. false otherwise.</returns>
 internal static bool IsEmptyReadOnlyEnumerable <T>(this IEnumerable <T> source)
 {
     DebugUtils.CheckNoExternalCallers();
     return(ReferenceEquals(source, ReadOnlyEnumerable <T> .Empty()));
 }
Пример #21
0
 /// <summary>
 /// Initializes a new <see cref="MediaType"/> read-only instance.
 /// </summary>
 /// <param name="type">Type specification (for example, 'text').</param>
 /// <param name="subType">Sub-type specification (for example, 'plain').</param>
 /// <param name="parameters">The parameters specified on the media type.</param>
 internal MediaType(string type, string subType, params KeyValuePair <string, string>[] parameters)
     : this(type, subType, (IList <KeyValuePair <string, string> >)parameters)
 {
     DebugUtils.CheckNoExternalCallers();
 }
Пример #22
0
 /// <summary>
 /// Create a <see cref="ODataBatchReader"/>.
 /// </summary>
 /// <param name="batchBoundary">The batch boundary to use.</param>
 /// <returns>The newly created <see cref="ODataCollectionReader"/>.</returns>
 internal override ODataBatchReader CreateBatchReader(string batchBoundary)
 {
     DebugUtils.CheckNoExternalCallers();
     return(this.CreateBatchReaderImplementation(batchBoundary, /*synchronous*/ true));
 }
Пример #23
0
        /// <summary>
        /// Converts a string to a primitive value.
        /// </summary>
        /// <param name="text">The string text to convert.</param>
        /// <param name="targetTypeReference">Type to convert the string to.</param>
        /// <returns>The value converted to the target type.</returns>
        /// <remarks>This method does not convert null value.</remarks>
        internal static object ConvertStringToPrimitive(string text, IEdmPrimitiveTypeReference targetTypeReference)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(text != null, "text != null");
            Debug.Assert(targetTypeReference != null, "targetTypeReference != null");

            try
            {
                EdmPrimitiveTypeKind primitiveKind = targetTypeReference.PrimitiveKind();

                switch (primitiveKind)
                {
                case EdmPrimitiveTypeKind.Binary:
                    return(Convert.FromBase64String(text));

                case EdmPrimitiveTypeKind.Boolean:
                    return(ConvertXmlBooleanValue(text));

                case EdmPrimitiveTypeKind.Byte:
                    return(XmlConvert.ToByte(text));

                case EdmPrimitiveTypeKind.DateTime:
                    return(PlatformHelper.ConvertStringToDateTime(text));

                case EdmPrimitiveTypeKind.DateTimeOffset:
                    return(PlatformHelper.ConvertStringToDateTimeOffset(text));

                case EdmPrimitiveTypeKind.Decimal:
                    return(XmlConvert.ToDecimal(text));

                case EdmPrimitiveTypeKind.Double:
                    return(XmlConvert.ToDouble(text));

                case EdmPrimitiveTypeKind.Guid:
                    return(new Guid(text));

                case EdmPrimitiveTypeKind.Int16:
                    return(XmlConvert.ToInt16(text));

                case EdmPrimitiveTypeKind.Int32:
                    return(XmlConvert.ToInt32(text));

                case EdmPrimitiveTypeKind.Int64:
                    return(XmlConvert.ToInt64(text));

                case EdmPrimitiveTypeKind.SByte:
                    return(XmlConvert.ToSByte(text));

                case EdmPrimitiveTypeKind.Single:
                    return(XmlConvert.ToSingle(text));

                case EdmPrimitiveTypeKind.String:
                    return(text);

                case EdmPrimitiveTypeKind.Time:
                    return(XmlConvert.ToTimeSpan(text));

                case EdmPrimitiveTypeKind.Stream:
                case EdmPrimitiveTypeKind.None:
                case EdmPrimitiveTypeKind.Geography:
                case EdmPrimitiveTypeKind.GeographyCollection:
                case EdmPrimitiveTypeKind.GeographyPoint:
                case EdmPrimitiveTypeKind.GeographyLineString:
                case EdmPrimitiveTypeKind.GeographyPolygon:
                case EdmPrimitiveTypeKind.GeometryCollection:
                case EdmPrimitiveTypeKind.GeographyMultiPolygon:
                case EdmPrimitiveTypeKind.GeographyMultiLineString:
                case EdmPrimitiveTypeKind.GeographyMultiPoint:
                case EdmPrimitiveTypeKind.Geometry:
                case EdmPrimitiveTypeKind.GeometryPoint:
                case EdmPrimitiveTypeKind.GeometryLineString:
                case EdmPrimitiveTypeKind.GeometryPolygon:
                case EdmPrimitiveTypeKind.GeometryMultiPolygon:
                case EdmPrimitiveTypeKind.GeometryMultiLineString:
                case EdmPrimitiveTypeKind.GeometryMultiPoint:
                default:
                    // Note that Astoria supports XElement and Binary as well, but they are serialized as string or byte[]
                    // and the metadata will actually talk about string and byte[] as well. Astoria will perform the conversion if necessary.
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.AtomValueUtils_ConvertStringToPrimitive));
                }
            }
            catch (Exception e)
            {
                if (!ExceptionUtils.IsCatchableExceptionType(e))
                {
                    throw;
                }

                throw ReaderValidationUtils.GetPrimitiveTypeConversionException(targetTypeReference, e);
            }
        }
Пример #24
0
 /// <summary>
 /// Read a top-level value.
 /// </summary>
 /// <param name="expectedPrimitiveTypeReference">The expected primitive type for the value to be read; null if no expected type is available.</param>
 /// <returns>An <see cref="object"/> representing the read value.</returns>
 internal override object ReadValue(IEdmPrimitiveTypeReference expectedPrimitiveTypeReference)
 {
     DebugUtils.CheckNoExternalCallers();
     return(this.ReadValueImplementation(expectedPrimitiveTypeReference));
 }
Пример #25
0
        /// <summary>
        /// Converts the given <see cref="MediaType"/> to a string representation suitable for use in a content-type header.
        /// </summary>
        /// <param name="mediaType">The media type to convert to text.</param>
        /// <returns>The string representation of the provided <paramref name="mediaType"/>.</returns>
        internal static string ToText(this MediaType mediaType)
        {
            DebugUtils.CheckNoExternalCallers();

            return(mediaType.ToText(null));
        }
Пример #26
0
 /// <summary>
 /// Private default constructor.
 /// </summary>
 internal ExcludeAllFilter() : base(new AnnotationFilterPattern[0])
 {
     DebugUtils.CheckNoExternalCallers();
 }
Пример #27
0
        /// <summary>
        /// Enumerates each charset part in the specified Accept-Charset header.
        /// </summary>
        /// <param name="headerValue">Non-null and non-empty header value for Accept-Charset.</param>
        /// <returns>
        /// A (non-sorted) enumeration of CharsetPart elements, which include
        /// a charset name and a quality (preference) value, normalized to 0-1000.
        /// </returns>
        private static IEnumerable <CharsetPart> AcceptCharsetParts(string headerValue)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!String.IsNullOrEmpty(headerValue), "!String.IsNullOrEmpty(headerValuer)");

            // PERF: optimize for common patterns.
            bool commaRequired = false; // Whether a comma should be found
            int  headerIndex   = 0;     // Index of character being procesed on headerValue.
            int  headerStart;           // Index into headerValue for the start of the charset name.
            int  headerNameEnd;         // Index into headerValue for the end of the charset name (+1).
            int  headerEnd;             // Index into headerValue for this charset part (+1).
            int  qualityValue;          // Normalized qvalue for this charset.

            while (headerIndex < headerValue.Length)
            {
                if (SkipWhitespace(headerValue, ref headerIndex))
                {
                    yield break;
                }

                if (headerValue[headerIndex] == ',')
                {
                    commaRequired = false;
                    headerIndex++;
                    continue;
                }

                if (commaRequired)
                {
                    // Comma missing between charset elements.
                    throw new ODataException(Strings.HttpUtils_MissingSeparatorBetweenCharsets(headerValue));
                }

                headerStart   = headerIndex;
                headerNameEnd = headerStart;

                bool endReached = ReadToken(headerValue, ref headerNameEnd);
                if (headerNameEnd == headerIndex)
                {
                    // Invalid (empty) charset name.
                    throw new ODataException(Strings.HttpUtils_InvalidCharsetName(headerValue));
                }

                if (endReached)
                {
                    qualityValue = 1000;
                    headerEnd    = headerNameEnd;
                }
                else
                {
                    char afterNameChar = headerValue[headerNameEnd];
                    if (IsHttpSeparator(afterNameChar))
                    {
                        if (afterNameChar == ';')
                        {
                            if (ReadLiteral(headerValue, headerNameEnd, ";q="))
                            {
                                // Unexpected end of qvalue.
                                throw new ODataException(Strings.HttpUtils_UnexpectedEndOfQValue(headerValue));
                            }

                            headerEnd = headerNameEnd + 3;
                            ReadQualityValue(headerValue, ref headerEnd, out qualityValue);
                        }
                        else
                        {
                            qualityValue = 1000;
                            headerEnd    = headerNameEnd;
                        }
                    }
                    else
                    {
                        // Invalid separator character.
                        throw new ODataException(Strings.HttpUtils_InvalidSeparatorBetweenCharsets(headerValue));
                    }
                }

                yield return(new CharsetPart(headerValue.Substring(headerStart, headerNameEnd - headerStart), qualityValue));

                // Prepare for next charset; we require at least one comma before we process it.
                commaRequired = true;
                headerIndex   = headerEnd;
            }
        }
Пример #28
0
 /// <summary>
 /// Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should be read, false otherwise.
 /// </summary>
 /// <param name="annotationName">The name of the annotation in question.</param>
 /// <returns>Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should be read, false otherwise.</returns>
 internal override bool Matches(string annotationName)
 {
     DebugUtils.CheckNoExternalCallers();
     ExceptionUtils.CheckArgumentStringNotNullOrEmpty(annotationName, "annotationName");
     return(false);
 }
Пример #29
0
        /// <summary>
        /// Determines if a property is in a list of projected properties.
        /// </summary>
        /// <param name="propertyName">The name of the property to lookup.</param>
        /// <returns>true if the property is projected; false otherwise.</returns>
        /// <remarks>Note that we allow null and empty property names here for the lookup just so that
        /// we don't have to validate before we skip them. If we would not skip them, the writing would fail later on anyway.</remarks>
        internal bool IsPropertyProjected(string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();

            return(this.projectedProperties.Contains(propertyName));
        }
Пример #30
0
        /// <summary>
        /// Given the Accept and the Accept-Charset headers of the request message computes the media type, encoding and <see cref="ODataFormat"/>
        /// to be used for the response message.
        /// </summary>
        /// <param name="settings">The message writer settings to use for serializing the response payload.</param>
        /// <param name="payloadKind">The kind of payload to be serialized as part of the response message.</param>
        /// <param name="mediaTypeResolver">The media type resolver to use when interpreting the content type.</param>
        /// <param name="mediaType">The media type to be used in the response message.</param>
        /// <param name="encoding">The encoding to be used in the response message.</param>
        /// <returns>The <see cref="ODataFormat"/> used when serializing the response.</returns>
        internal static ODataFormat GetContentTypeFromSettings(
            ODataMessageWriterSettings settings,
            ODataPayloadKind payloadKind,
            MediaTypeResolver mediaTypeResolver,
            out MediaType mediaType,
            out Encoding encoding)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(settings != null, "settings != null");

            // compute format, media type and encoding
            ODataFormat format;

            // get the supported and default media types for the specified payload kind
            MediaTypeWithFormat[] supportedMediaTypes = mediaTypeResolver.GetMediaTypesForPayloadKind(payloadKind);
            if (supportedMediaTypes == null || supportedMediaTypes.Length == 0)
            {
                throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(null, settings.AcceptableMediaTypes));
            }

            if (settings.UseFormat == true)
            {
                Debug.Assert(settings.AcceptableMediaTypes == null, "settings.AcceptableMediaTypes == null");
                Debug.Assert(settings.AcceptableCharsets == null, "settings.AcceptableCharsets == null");

                mediaType = GetDefaultMediaType(supportedMediaTypes, settings.Format, out format);

                // NOTE the default media types don't have any parameters (in particular no 'charset' parameters)
                encoding = mediaType.SelectEncoding();
            }
            else
            {
                // parse the accept header into its parts
                IList <KeyValuePair <MediaType, string> > specifiedTypes = HttpUtils.MediaTypesFromString(settings.AcceptableMediaTypes);

                if (settings.Version == ODataVersion.V3)
                {
                    specifiedTypes = RemoveApplicationJsonFromAcceptableMediaTypes(specifiedTypes, supportedMediaTypes, settings.AcceptableMediaTypes);
                }

                MediaTypeWithFormat selectedMediaTypeWithFormat;
                string specifiedCharset = null;
                if (specifiedTypes == null || specifiedTypes.Count == 0)
                {
                    selectedMediaTypeWithFormat = supportedMediaTypes[0];
                }
                else
                {
                    // match the specified media types against the supported/default ones and get the format
                    MediaTypeMatchInfo matchInfo = MatchMediaTypes(specifiedTypes.Select(kvp => kvp.Key), supportedMediaTypes.Select(smt => smt.MediaType).ToArray());
                    if (matchInfo == null)
                    {
                        // We're calling the ToArray here since not all platforms support the string.Join which takes IEnumerable.
                        string supportedTypesAsString = string.Join(", ", supportedMediaTypes.Select(mt => mt.MediaType.ToText()).ToArray());
                        throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(supportedTypesAsString, settings.AcceptableMediaTypes));
                    }

                    selectedMediaTypeWithFormat = supportedMediaTypes[matchInfo.TargetTypeIndex];
                    specifiedCharset            = specifiedTypes[matchInfo.SourceTypeIndex].Value;
                }

                format    = selectedMediaTypeWithFormat.Format;
                mediaType = selectedMediaTypeWithFormat.MediaType;

                // If a charset was specified with the accept header, consider it for the encoding
                string acceptableCharsets = settings.AcceptableCharsets;
                if (specifiedCharset != null)
                {
                    acceptableCharsets = acceptableCharsets == null ? specifiedCharset : specifiedCharset + "," + acceptableCharsets;
                }

                encoding = GetEncoding(acceptableCharsets, payloadKind, mediaType, /*useDefaultEncoding*/ true);
            }

            return(format);
        }