/// <summary>
        /// Factory method to create the light-weight online service context (without fetching service document and metadata document which are known already)
        /// </summary>
        /// <param name="target">The target resource to be crawled</param>
        /// <param name="acceptHeaderValue">The accept header value defined in the Http header</param>
        /// <param name="serviceRoot">The URI pointing to the service document resource</param>
        /// <param name="serviceDocument">The content of service document</param>
        /// <param name="metadataDocument">The content of metadata document</param>
        /// <param name="jobId">The validation job identifier</param>
        /// <param name="maximumPayloadSize">The maximum number of bytes allowed to retrieve from the target resource</param>
        /// <param name="reqHeaders">Http headers sent as part of request</param>
        /// <returns>The constructed service context</returns>
        /// <exception cref="CrawlRuntimeException">Throws exception when target resource exceeds the maximum size allowed</exception>
        public static ServiceContext Create(Uri target,
                                            string acceptHeaderValue,
                                            Uri serviceRoot,
                                            string serviceDocument,
                                            string metadataDocument,
                                            Guid jobId,
                                            int maximumPayloadSize,
                                            IEnumerable <KeyValuePair <string, string> > reqHeaders,
                                            string category = "core")
        {
            Response          response      = WebHelper.Get(target, acceptHeaderValue, maximumPayloadSize, reqHeaders);
            ODataMetadataType odataMetadata = ServiceContextFactory.MapAcceptHeaderToMetadataType(acceptHeaderValue);
            var    payloadFormat            = response.ResponsePayload.GetFormatFromPayload();
            var    payloadType = response.ResponsePayload.GetTypeFromPayload(payloadFormat);
            string entityType  = response.ResponsePayload.GetFullEntityType(payloadType, payloadFormat, metadataDocument);

            return(new ServiceContext(target,
                                      jobId,
                                      response.StatusCode,
                                      response.ResponseHeaders,
                                      response.ResponsePayload,
                                      entityType,
                                      serviceRoot,
                                      serviceDocument,
                                      metadataDocument,
                                      false,
                                      reqHeaders,
                                      odataMetadata,
                                      null,
                                      category));
        }
        /// <summary>
        /// Parse the metadata type of offline payload from header.
        /// </summary>
        /// <param name="offlineHeader">The string offline header.</param>
        /// <returns>The metadata type of offline payload.</returns>
        public static ODataMetadataType GetMetadataTypeFromOfflineHeader(this string offlineHeader)
        {
            ODataMetadataType metadata = ODataMetadataType.MinOnly;

            if (offlineHeader.Contains(Constants.V3AcceptHeaderJsonFullMetadata) || offlineHeader.Contains(Constants.V4AcceptHeaderJsonFullMetadata))
            {
                metadata = ODataMetadataType.FullOnly;
            }

            return(metadata);
        }
        /// <summary>
        /// Creates an instance of ServiceContext.
        /// </summary>
        /// <param name="destination">request Uri of the service context</param>
        /// <param name="jobId">Job identifier</param>
        /// <param name="statusCode">Http status code of the response</param>
        /// <param name="responseHttpHeaders">Header text of the response</param>
        /// <param name="responsePayload">Payload content of the response</param>
        /// <param name="entityType">Fully-qualified name of entity type the repsonse payload is about</param>
        /// <param name="serviceBaseUri">Uri of service document</param>
        /// <param name="serviceDocument">Content of service document</param>
        /// <param name="metadataDocument">Content of metadata document</param>
        /// <param name="offline">Flag of conetxt being offline(true) or live(false)</param>
        /// <param name="reqHeaders">Http headers used as part of header</param>
        /// <param name="odataMetadata">Odata metadata type</param>
        public ServiceContext(
            Uri destination,
            Guid jobId,
            HttpStatusCode?statusCode,
            string responseHttpHeaders,
            string responsePayload,
            string entityType,
            Uri serviceBaseUri,
            string serviceDocument,
            string metadataDocument,
            bool offline,
            IEnumerable <KeyValuePair <string, string> > reqHeaders,
            ODataMetadataType odataMetadata = ODataMetadataType.MinOnly,
            string jsonFullmetadataPayload  = null,
            string category = "core")
        {
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }

            // TODO: uncomment this to enable uri canonicalization
            // this.Destination = destination.Canonicalize();
            this.Destination         = destination;
            this.DestinationBasePath = this.Destination.GetLeftPart(UriPartial.Path).TrimEnd('/');
            AnnotationDVsManager.Instance(this.DestinationBasePath);

            if (!string.IsNullOrEmpty(this.DestinationBasePath))
            {
                string lastLeg = this.DestinationBasePath.Substring(this.DestinationBasePath.LastIndexOf('/'));
                if (!string.IsNullOrEmpty(lastLeg))
                {
                    this.DestinationBaseLastSegment = lastLeg.TrimStart('/');
                }
            }

            this.Projection              = this.Destination.Query.IndexOf("$select=", StringComparison.OrdinalIgnoreCase) >= 0;
            this.JobId                   = jobId;
            this.HttpStatusCode          = statusCode;
            this.ResponseHttpHeaders     = responseHttpHeaders;
            this.OdataMetadataType       = odataMetadata;
            this.JsonFullMetadataPayload = jsonFullmetadataPayload;
            this.MetadataDocument        = metadataDocument;
            int test = responsePayload.Length;

            this.ResponsePayload    = responsePayload;
            this.EntityTypeFullName = entityType;
            this.ServiceBaseUri     = serviceBaseUri;
            this.ServiceDocument    = serviceDocument;
            this.IsOffline          = offline;
            this.RequestHeaders     = reqHeaders;
            this.Category           = category;
            this.ServiceType        = ConformanceServiceType.ReadWrite;
            this.LevelTypes         = new ConformanceLevelType[] { ConformanceLevelType.Minimal };
            if (category.Contains(";"))
            {
                string[] array = category.Split(';');
                this.Category    = array[0];
                this.ServiceType = (ConformanceServiceType)Enum.Parse(typeof(ConformanceServiceType), array[1]);
                if (array.Length > 2 && array[2].Contains(","))
                {
                    string[] levelArray = array[2].Split(',');
                    this.LevelTypes = new ConformanceLevelType[levelArray.Length];
                    for (int i = 0; i < levelArray.Length; i++)
                    {
                        ConformanceLevelType level;
                        if (Enum.TryParse(levelArray[i], out level))
                        {
                            this.LevelTypes[i] = level;
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Filters rules based on odata metadata type
 /// </summary>
 /// <param name="rules">The collection of input rules</param>
 /// <param name="ODataMetadataType">OData metadata type</param>
 /// <returns>The subset of input rules that applies to the context</returns>
 private static IEnumerable<Rule> SelectRulesByMetadataFlag(this IEnumerable<Rule> rules, ODataMetadataType odataMetadataType)
 {
     return from r in rules
            where !r.OdataMetadataType.HasValue || r.OdataMetadataType.Value == odataMetadataType
            select r;
 }
        /// <summary>
        /// Factory method to set up the OData Interop context based on uri, desired format and job id
        /// </summary>
        /// <param name="destination">uri string pointing to a OData service endpoint</param>
        /// <param name="format">format preference, could be either "atom" or "json" - default and falling back to atom</param>
        /// <param name="jobId">unique identifier to tag this context</param>
        /// <param name="maximumPayloadSize">the maximum number of bytes rule engine is willing to retrieve from the Uri provided</param>
        /// <param name="reqHeaders">Http headers sent as part of request</param>
        /// <returns>context object representing the interop request session</returns>
        public static ServiceContext Create(string destination, string format, Guid jobId, int maximumPayloadSize, IEnumerable <KeyValuePair <string, string> > reqHeaders, string category = "core")
        {
            Uri    inputUri;
            Uri    serviceBaseUri          = null;
            string serviceDocument         = null;
            string metadataDocument        = null;
            string entityType              = null;
            string jsonFullMetadataPayload = null;
            var    serviceStatus           = ServiceStatus.GetInstance();

            if (string.IsNullOrEmpty(format))
            {
                throw new ArgumentException(Resource.ArgumentNotNullOrEmpty, "format");
            }

            try
            {
                if (destination.EndsWith(@"/"))
                {
                    destination = destination.TrimEnd('/');
                }

                inputUri = new Uri(destination);
            }
            catch (UriFormatException)
            {
                if (!destination.StartsWith(@"http://") && !destination.StartsWith(@"https://"))
                {
                    inputUri = new Uri(SupportedScheme.SchemeHttp + "://" + destination);
                }
                else
                {
                    inputUri = new Uri(Uri.EscapeUriString(destination));
                }
            }

            if (!SupportedScheme.Instance.Contains(inputUri.Scheme))
            {
                throw new ArgumentException(
                          string.Format(CultureInfo.CurrentCulture, Resource.formatSchemeNotSupported, inputUri.Scheme),
                          "destination");
            }

            string            acceptHeader  = ServiceContextFactory.MapFormatToAcceptValue(format);
            ODataMetadataType odataMetadata = ServiceContextFactory.MapFormatToMetadataType(format);
            Response          response      = WebHelper.Get(inputUri, acceptHeader, maximumPayloadSize, reqHeaders);

            if (response.StatusCode == HttpStatusCode.NotFound)
            {
                return(null);
            }

            var payloadFormat = response.ResponsePayload.GetFormatFromPayload();
            var payloadType   = ContextHelper.GetPayloadType(response.ResponsePayload, payloadFormat, response.ResponseHeaders);

            switch (payloadType)
            {
            case PayloadType.ServiceDoc:
                serviceBaseUri  = inputUri;
                serviceDocument = response.ResponsePayload;
                break;

            case PayloadType.Metadata:
                if (inputUri.AbsoluteUri.EndsWith(Constants.OptionMetadata, StringComparison.Ordinal))
                {
                    if (payloadFormat == PayloadFormat.JsonLight)
                    {
                        serviceBaseUri  = new Uri(serviceStatus.RootURL);
                        serviceDocument = serviceStatus.ServiceDocument;
                    }
                    else
                    {
                        serviceBaseUri = new Uri(inputUri.AbsoluteUri.Substring(0, inputUri.AbsoluteUri.Length - Constants.OptionMetadata.Length));
                        var respSvcDoc = WebHelper.Get(serviceBaseUri, acceptHeader, maximumPayloadSize, reqHeaders);
                        serviceDocument = respSvcDoc.ResponsePayload;
                    }
                }

                break;

            default:
                if (payloadType.IsValidPayload())
                {
                    string   fullPath = inputUri.GetLeftPart(UriPartial.Path).TrimEnd('/');
                    var      uriPath  = new Uri(fullPath);
                    Uri      baseUri;
                    Response serviceDoc;
                    if (ServiceContextFactory.TryGetServiceDocument(maximumPayloadSize, uriPath, acceptHeader, uriPath.AbsoluteUri == fullPath, out baseUri, out serviceDoc, reqHeaders))
                    {
                        serviceBaseUri  = baseUri;
                        serviceDocument = serviceDoc.ResponsePayload;
                    }
                }

                break;
            }

            if (payloadType == PayloadType.Metadata)
            {
                metadataDocument = response.ResponsePayload;
            }
            else
            {
                if (serviceBaseUri != null)
                {
                    if (payloadFormat == PayloadFormat.JsonLight && payloadType == PayloadType.ServiceDoc)
                    {
                        metadataDocument = serviceStatus.MetadataDocument;
                    }
                    else
                    {
                        try
                        {
                            string metadataURL      = serviceBaseUri.AbsoluteUri.EndsWith(@"/") ? Constants.OptionMetadata.TrimStart('/') : Constants.OptionMetadata;
                            var    responseMetadata = WebHelper.Get(new Uri(serviceBaseUri.AbsoluteUri + metadataURL), null, maximumPayloadSize, reqHeaders);
                            if (responseMetadata != null)
                            {
                                metadataDocument = responseMetadata.ResponsePayload;
                            }
                        }
                        catch (OversizedPayloadException)
                        {
                            // do nothing
                        }
                    }
                }
            }

            if (payloadFormat == PayloadFormat.JsonLight)
            {
                try
                {
                    // Specify full metadata accept header
                    string acceptHeaderOfFullMetadata = string.Empty;
                    if (acceptHeader.Equals(Constants.V3AcceptHeaderJsonFullMetadata) ||
                        acceptHeader.Equals(Constants.V3AcceptHeaderJsonMinimalMetadata) ||
                        acceptHeader.Equals(Constants.V3AcceptHeaderJsonNoMetadata))
                    {
                        acceptHeaderOfFullMetadata = Constants.V3AcceptHeaderJsonFullMetadata;
                    }
                    else
                    {
                        acceptHeaderOfFullMetadata = Constants.V4AcceptHeaderJsonFullMetadata;
                    }

                    // Send full metadata request and get full metadata response.
                    var responseFullMetadata = WebHelper.Get(inputUri, acceptHeaderOfFullMetadata, maximumPayloadSize, reqHeaders);
                    if (responseFullMetadata != null)
                    {
                        jsonFullMetadataPayload = responseFullMetadata.ResponsePayload;
                        entityType = jsonFullMetadataPayload.GetFullEntityType(payloadType, payloadFormat, metadataDocument);
                    }
                }
                catch (OversizedPayloadException)
                {
                    // do nothing
                }
            }
            else
            {
                entityType = response.ResponsePayload.GetFullEntityType(payloadType, payloadFormat, metadataDocument);
            }

            return(new ServiceContext(inputUri,
                                      jobId,
                                      response.StatusCode,
                                      response.ResponseHeaders,
                                      response.ResponsePayload,
                                      entityType,
                                      serviceBaseUri,
                                      serviceDocument,
                                      metadataDocument,
                                      false,
                                      reqHeaders,
                                      odataMetadata,
                                      jsonFullMetadataPayload,
                                      category));
        }
        /// <summary>
        /// Creates an offline service context with specified job id from payload context and metadata document.
        /// </summary>
        /// <param name="payload">The payload context</param>
        /// <param name="metadata">The metadata document</param>
        /// <param name="jobId">The job id</param>
        /// <param name="respHeaders">The optional Http response headers</param>
        /// <param name="reqHeaders">The request headers</param>
        /// <returns>Service context object which represents the offline interop validation session</returns>
        public static ServiceContext Create(string payload, string metadata, Guid jobId, string respHeaders, IEnumerable <KeyValuePair <string, string> > reqHeaders)
        {
            if (string.IsNullOrEmpty(payload) && string.IsNullOrEmpty(metadata))
            {
                throw new ArgumentException("invalid parameters");
            }

            if (string.IsNullOrEmpty(payload))
            {
                payload  = metadata;
                metadata = null;
            }

            Uri               inputUri         = new Uri(Constants.DefaultOfflineTarget);
            string            entityType       = null;
            Uri               serviceBaseUri   = null;
            string            serviceDocument  = null;
            string            metadataDocument = null;
            var               payloadFormat    = payload.GetFormatFromPayload();
            var               payloadType      = payload.GetTypeFromPayload(payloadFormat);
            ODataMetadataType metadataType     = ServiceContextFactory.GetMetadataTypeFromOfflineHeader(respHeaders);

            if (payloadType != PayloadType.Metadata && !string.IsNullOrEmpty(metadata))
            {
                var metaFormat = metadata.GetFormatFromPayload();
                if (metaFormat == PayloadFormat.Xml)
                {
                    var metaType = metadata.GetTypeFromPayload(metaFormat);
                    if (metaType == PayloadType.Metadata)
                    {
                        //do sanity check to ensure a matching metadata, should payload be a feed or an entry
                        if (IsMetadataMacthing(payload, metadata, payloadFormat, payloadType))
                        {
                            metadataDocument = metadata;
                        }
                    }
                }
            }

            switch (payloadType)
            {
            case PayloadType.ServiceDoc:
                serviceDocument = payload;
                if (payloadFormat == PayloadFormat.Xml || payloadFormat == PayloadFormat.Atom)
                {
                    XElement   payloadXml = XElement.Parse(payload);
                    XNamespace ns         = "http://www.w3.org/XML/1998/namespace"; // xmlns:xml definition according to http://www.w3.org/TR/REC-xml-names/
                    var        xmlBase    = payloadXml.Attribute(ns + "base");      // rfc5023: it MAY have an "xml:base" attribute ... serving as the base URI
                    if (xmlBase != null && !string.IsNullOrEmpty(xmlBase.Value))
                    {
                        inputUri = new Uri(xmlBase.Value);
                    }
                }
                break;

            case PayloadType.Metadata:
                serviceDocument  = null;
                metadataDocument = payload;
                break;

            case PayloadType.Error:
                break;

            case PayloadType.Feed:
            case PayloadType.Entry:
            {
                entityType = payload.GetFullEntityType(payloadType, payloadFormat, metadataDocument);
                string shortEntityTypeName = entityType.GetLastSegment();
                string target = payload.GetIdFromFeedOrEntry(payloadFormat);
                if (!string.IsNullOrEmpty(target))
                {
                    var projectedProperties = payload.GetProjectedPropertiesFromFeedOrEntry(payloadFormat, metadataDocument, shortEntityTypeName);
                    if (projectedProperties != null && projectedProperties.Any())
                    {
                        var opt = string.Join(",", projectedProperties);
                        try
                        {
                            inputUri = new Uri(target + "?$select=" + opt);
                        }
                        catch (UriFormatException)
                        {
                            //do nothing
                        }
                    }
                    else
                    {
                        try
                        {
                            inputUri = new Uri(target);
                        }
                        catch (UriFormatException)
                        {
                            //do nothing
                        }
                    }
                }
            }
            break;
            }

            return(new ServiceContext(inputUri, jobId, null, respHeaders, payload, entityType, serviceBaseUri, serviceDocument, metadataDocument, true, reqHeaders, metadataType));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Creates an instance of ServiceContext.
        /// </summary>
        /// <param name="destination">request Uri of the service context</param>
        /// <param name="jobId">Job identifier</param>
        /// <param name="statusCode">Http status code of the response</param>
        /// <param name="responseHttpHeaders">Header text of the response</param>
        /// <param name="responsePayload">Payload content of the response</param>
        /// <param name="entityType">Fully-qualified name of entity type the repsonse payload is about</param>
        /// <param name="serviceBaseUri">Uri of service document</param>
        /// <param name="serviceDocument">Content of service document</param>
        /// <param name="metadataDocument">Content of metadata document</param>
        /// <param name="offline">Flag of conetxt being offline(true) or live(false)</param>
        /// <param name="reqHeaders">Http headers used as part of header</param>
        /// <param name="odataMetadata">Odata metadata type</param>
        public ServiceContext(
            Uri destination,
            Guid jobId,
            HttpStatusCode? statusCode,
            string responseHttpHeaders,
            string responsePayload,
            string entityType,
            Uri serviceBaseUri,
            string serviceDocument,
            string metadataDocument,
            bool offline,
            IEnumerable<KeyValuePair<string, string>> reqHeaders,
            ODataMetadataType odataMetadata = ODataMetadataType.MinOnly,
            string jsonFullmetadataPayload = null,
            string category = "core")
        {
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }

            // TODO: uncomment this to enable uri canonicalization
            // this.Destination = destination.Canonicalize();
            this.Destination = destination;
            this.DestinationBasePath = this.Destination.GetLeftPart(UriPartial.Path).TrimEnd('/');
            AnnotationDVsManager.Instance(this.DestinationBasePath);

            if (!string.IsNullOrEmpty(this.DestinationBasePath))
            {
                string lastLeg = this.DestinationBasePath.Substring(this.DestinationBasePath.LastIndexOf('/'));
                if (!string.IsNullOrEmpty(lastLeg))
                {
                    this.DestinationBaseLastSegment = lastLeg.TrimStart('/');
                }
            }

            this.Projection = this.Destination.Query.IndexOf("$select=", StringComparison.OrdinalIgnoreCase) >= 0;
            this.JobId = jobId;
            this.HttpStatusCode = statusCode;
            this.ResponseHttpHeaders = responseHttpHeaders;
            this.OdataMetadataType = odataMetadata;
            this.JsonFullMetadataPayload = jsonFullmetadataPayload;
            this.MetadataDocument = metadataDocument;
            this.ResponsePayload = responsePayload;
            this.EntityTypeFullName = entityType;
            this.ServiceBaseUri = serviceBaseUri;
            this.ServiceDocument = serviceDocument;
            this.IsOffline = offline;
            this.RequestHeaders = reqHeaders;
            this.Category = category;
            this.ServiceType = ConformanceServiceType.ReadWrite;
            this.LevelTypes = new ConformanceLevelType[] { ConformanceLevelType.Minimal };
            if (category.Contains(";"))
            {
                string[] array = category.Split(';');
                this.Category = array[0];
                this.ServiceType = (ConformanceServiceType)Enum.Parse(typeof(ConformanceServiceType), array[1]);
                if (array.Length > 2 && array[2].Contains(","))
                {
                    string[] levelArray = array[2].Split(',');
                    this.LevelTypes = new ConformanceLevelType[levelArray.Length];
                    for (int i = 0; i < levelArray.Length; i++)
                    {
                        ConformanceLevelType level;
                        if (Enum.TryParse(levelArray[i], out level))
                        {
                            this.LevelTypes[i] = level;
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Filters rules based on odata metadata type
 /// </summary>
 /// <param name="rules">The collection of input rules</param>
 /// <param name="ODataMetadataType">OData metadata type</param>
 /// <returns>The subset of input rules that applies to the context</returns>
 private static IEnumerable <Rule> SelectRulesByMetadataFlag(this IEnumerable <Rule> rules, ODataMetadataType odataMetadataType)
 {
     return(from r in rules
            where !r.OdataMetadataType.HasValue || r.OdataMetadataType.Value == odataMetadataType
            select r);
 }