static void Validate(UriTemplatePathPartiallyEquivalentSet pes, bool allowDuplicateEquivalentUriTemplates) { // A set with 0 or 1 items is valid by definition if (pes.Items.Count < 2) { return; } // Assert all paths are partially-equivalent for (int i = 0; i < pes.Items.Count - 1; ++i) { Fx.Assert(pes.Items[i].Key.IsPathPartiallyEquivalentAt(pes.Items[i + 1].Key, pes.SegmentsCount), "all elements of a PES must be path partially-equivalent"); } // We will check that the queries disambiguate only for templates, which are // matched completely at the segments count; templates, which are match at // that point due to terminal defaults, will be ruled out. UriTemplate[] a = new UriTemplate[pes.Items.Count]; int arrayIndex = 0; foreach (KeyValuePair <UriTemplate, object> kvp in pes.Items) { if (pes.SegmentsCount < kvp.Key.segments.Count) { continue; } Fx.Assert(arrayIndex < a.Length, "We made enough room for all the items"); a[arrayIndex++] = kvp.Key; } // Ensure that queries disambiguate (if needed) : if (arrayIndex > 0) { UriTemplateHelpers.DisambiguateSamePath(a, 0, arrayIndex, allowDuplicateEquivalentUriTemplates); } }
void VerifyThatFastPathAndSlowPathHaveSameResults(Uri uri, Collection <string> fastPathRelativePathSegments, IList <UriTemplateTableMatchCandidate> fastPathCandidates) { Collection <string> slowPathRelativePathSegments = new Collection <string>(); List <UriTemplateTableMatchCandidate> slowPathCandidates = new List <UriTemplateTableMatchCandidate>(); if (!SlowComputeRelativeSegmentsAndLookup(uri, UriTemplateHelpers.GetUriPath(uri), slowPathRelativePathSegments, slowPathCandidates)) { Fx.Assert("fast path yielded a result but slow path yielded no result"); } // compare results if (fastPathRelativePathSegments.Count != slowPathRelativePathSegments.Count) { Fx.Assert("fast path yielded different number of segments from slow path"); } for (int i = 0; i < fastPathRelativePathSegments.Count; ++i) { if (fastPathRelativePathSegments[i] != slowPathRelativePathSegments[i]) { Fx.Assert("fast path yielded different segments from slow path"); } } if (fastPathCandidates.Count != slowPathCandidates.Count) { Fx.Assert("fast path yielded different number of candidates from slow path"); } for (int i = 0; i < fastPathCandidates.Count; i++) { if (!slowPathCandidates.Contains(fastPathCandidates[i])) { Fx.Assert("fast path yielded different candidates from slow path"); } } }
public static UriTemplatePathSegment CreateFromUriTemplate(string segment, UriTemplate template) { // Identifying the type of segment - Literal|Compound|Variable switch (UriTemplateHelpers.IdentifyPartType(segment)) { case UriTemplatePartType.Literal: return(UriTemplateLiteralPathSegment.CreateFromUriTemplate(segment, template)); case UriTemplatePartType.Compound: return(UriTemplateCompoundPathSegment.CreateFromUriTemplate(segment, template)); case UriTemplatePartType.Variable: if (segment.EndsWith("/", StringComparison.Ordinal)) { string varName = template.AddPathVariable(UriTemplatePartType.Variable, segment.Substring(1, segment.Length - 3)); return(new UriTemplateVariablePathSegment(segment, true, varName)); } else { string varName = template.AddPathVariable(UriTemplatePartType.Variable, segment.Substring(1, segment.Length - 2)); return(new UriTemplateVariablePathSegment(segment, false, varName)); } default: Fx.Assert("Invalid value from IdentifyStringNature"); return(null); } }
private void ConstructFastPathTable() { this.noTemplateHasQueryPart = true; foreach (KeyValuePair <UriTemplate, object> pair in this.templates) { UriTemplate key = pair.Key; if (!UriTemplateHelpers.CanMatchQueryTrivially(key)) { this.noTemplateHasQueryPart = false; } if (key.HasNoVariables && !key.HasWildcard) { if (this.fastPathTable == null) { this.fastPathTable = new Dictionary <string, FastPathInfo>(); } Uri uri = key.BindByPosition(this.originalUncanonicalizedBaseAddress, new string[0]); string uriPath = UriTemplateHelpers.GetUriPath(uri); if (!this.fastPathTable.ContainsKey(uriPath)) { FastPathInfo info = new FastPathInfo(); if (this.ComputeRelativeSegmentsAndLookup(uri, info.RelativePathSegments, info.Candidates)) { info.Freeze(); this.fastPathTable.Add(uriPath, info); } } } } }
public static UriTemplateQueryValue CreateFromUriTemplate(string value, UriTemplate template) { // Checking for empty value if (value == null) { return(UriTemplateQueryValue.Empty); } // Identifying the type of value - Literal|Compound|Variable switch (UriTemplateHelpers.IdentifyPartType(value)) { case UriTemplatePartType.Literal: return(UriTemplateLiteralQueryValue.CreateFromUriTemplate(value)); case UriTemplatePartType.Compound: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString( SR.UTQueryCannotHaveCompoundValue, template.originalTemplate))); case UriTemplatePartType.Variable: return(new UriTemplateVariableQueryValue(template.AddQueryVariable(value.Substring(1, value.Length - 2)))); default: Fx.Assert("Invalid value from IdentifyStringNature"); return(null); } }
static bool AtLeastOneCandidateHasQueryPart(IList <UriTemplateTableMatchCandidate> candidates) { for (int i = 0; i < candidates.Count; i++) { if (!UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) { return(true); } } return(false); }
void PopulateQueryParameters() { if (this.requestUri != null) { this.queryParameters = UriTemplateHelpers.ParseQueryString(this.requestUri.Query); } else { this.queryParameters = new NameValueCollection(); } }
private bool FastComputeRelativeSegmentsAndLookup(Uri uri, out Collection <string> relativePathSegments, out IList <UriTemplateTableMatchCandidate> candidates) { string uriPath = UriTemplateHelpers.GetUriPath(uri); FastPathInfo info = null; if ((this.fastPathTable != null) && this.fastPathTable.TryGetValue(uriPath, out info)) { relativePathSegments = info.RelativePathSegments; candidates = info.Candidates; return(true); } relativePathSegments = new Collection <string>(); candidates = new Collection <UriTemplateTableMatchCandidate>(); return(this.SlowComputeRelativeSegmentsAndLookup(uri, uriPath, relativePathSegments, candidates)); }
static bool NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback( IList <UriTemplateTableMatchCandidate> candidates) { bool thereIsAmEmptyFallback = false; for (int i = 0; i < candidates.Count; i++) { if (UriTemplateHelpers.HasQueryLiteralRequirements(candidates[i].Template)) { return(false); } if (candidates[i].Template.queries.Count == 0) { thereIsAmEmptyFallback = true; } } return(thereIsAmEmptyFallback); }
public static UriTemplatePathSegment CreateFromUriTemplate(string segment, UriTemplate template) { switch (UriTemplateHelpers.IdentifyPartType(segment)) { case UriTemplatePartType.Literal: return(UriTemplateLiteralPathSegment.CreateFromUriTemplate(segment, template)); case UriTemplatePartType.Compound: return(UriTemplateCompoundPathSegment.CreateFromUriTemplate(segment, template)); case UriTemplatePartType.Variable: if (!segment.EndsWith("/", StringComparison.Ordinal)) { return(new UriTemplateVariablePathSegment(segment, false, template.AddPathVariable(UriTemplatePartType.Variable, segment.Substring(1, segment.Length - 2)))); } return(new UriTemplateVariablePathSegment(segment, true, template.AddPathVariable(UriTemplatePartType.Variable, segment.Substring(1, segment.Length - 3)))); } return(null); }
private void NormalizeBaseAddress() { if (this.baseAddress != null) { UriBuilder builder = new UriBuilder(this.baseAddress); if (!builder.Path.EndsWith("/", StringComparison.Ordinal)) { builder.Path = builder.Path + "/"; } builder.Host = "localhost"; builder.Port = -1; builder.UserName = null; builder.Password = null; builder.Path = builder.Path.ToUpperInvariant(); builder.Scheme = Uri.UriSchemeHttp; this.baseAddress = builder.Uri; this.basePath = UriTemplateHelpers.GetUriPath(this.baseAddress); } }
private static bool NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(IList <UriTemplateTableMatchCandidate> candidates) { bool flag = false; for (int i = 0; i < candidates.Count; i++) { UriTemplateTableMatchCandidate candidate = candidates[i]; if (UriTemplateHelpers.HasQueryLiteralRequirements(candidate.Template)) { return(false); } UriTemplateTableMatchCandidate candidate2 = candidates[i]; if (candidate2.Template.queries.Count == 0) { flag = true; } } return(flag); }
public static UriTemplateQueryValue CreateFromUriTemplate(string value, UriTemplate template) { if (value == null) { return(Empty); } switch (UriTemplateHelpers.IdentifyPartType(value)) { case UriTemplatePartType.Literal: return(UriTemplateLiteralQueryValue.CreateFromUriTemplate(value)); case UriTemplatePartType.Compound: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTQueryCannotHaveCompoundValue", new object[] { template.originalTemplate }))); case UriTemplatePartType.Variable: return(new UriTemplateVariableQueryValue(template.AddQueryVariable(value.Substring(1, value.Length - 2)))); } return(null); }
void NormalizeBaseAddress() { if (this.baseAddress != null) { // ensure trailing slash on baseAddress, so that IsBaseOf will work later UriBuilder ub = new UriBuilder(this.baseAddress); if (this.addTrailingSlashToBaseAddress && !ub.Path.EndsWith("/", StringComparison.Ordinal)) { ub.Path = ub.Path + "/"; } ub.Host = "localhost"; // always normalize to localhost ub.Port = -1; ub.UserName = null; ub.Password = null; ub.Path = ub.Path.ToUpperInvariant(); ub.Scheme = Uri.UriSchemeHttp; this.baseAddress = ub.Uri; basePath = UriTemplateHelpers.GetUriPath(this.baseAddress); } }
private void VerifyThatFastPathAndSlowPathHaveSameResults(Uri uri, Collection <string> fastPathRelativePathSegments, IList <UriTemplateTableMatchCandidate> fastPathCandidates) { Collection <string> relativePathSegments = new Collection <string>(); List <UriTemplateTableMatchCandidate> candidates = new List <UriTemplateTableMatchCandidate>(); this.SlowComputeRelativeSegmentsAndLookup(uri, UriTemplateHelpers.GetUriPath(uri), relativePathSegments, candidates); int count = relativePathSegments.Count; int num3 = fastPathRelativePathSegments.Count; for (int i = 0; i < fastPathRelativePathSegments.Count; i++) { bool flag1 = fastPathRelativePathSegments[i] != relativePathSegments[i]; } int num4 = candidates.Count; int num5 = fastPathCandidates.Count; for (int j = 0; j < fastPathCandidates.Count; j++) { candidates.Contains(fastPathCandidates[j]); } }
private static void Validate(UriTemplatePathPartiallyEquivalentSet pes, bool allowDuplicateEquivalentUriTemplates) { if (pes.Items.Count >= 2) { for (int i = 0; i < (pes.Items.Count - 1); i++) { } UriTemplate[] array = new UriTemplate[pes.Items.Count]; int b = 0; foreach (KeyValuePair <UriTemplate, object> pair in pes.Items) { if (pes.SegmentsCount >= pair.Key.segments.Count) { array[b++] = pair.Key; } } if (b > 0) { UriTemplateHelpers.DisambiguateSamePath(array, 0, b, allowDuplicateEquivalentUriTemplates); } } }
// this method checks the literal cache for a match if none, goes through the slower path of cracking the segments bool FastComputeRelativeSegmentsAndLookup(Uri uri, out Collection <string> relativePathSegments, out IList <UriTemplateTableMatchCandidate> candidates) { // Consider fast-path and lookup // return false if not under base uri string uriPath = UriTemplateHelpers.GetUriPath(uri); FastPathInfo fpInfo = null; if ((this.fastPathTable != null) && this.fastPathTable.TryGetValue(uriPath, out fpInfo)) { relativePathSegments = fpInfo.RelativePathSegments; candidates = fpInfo.Candidates; VerifyThatFastPathAndSlowPathHaveSameResults(uri, relativePathSegments, candidates); return(true); } else { relativePathSegments = new Collection <string>(); candidates = new Collection <UriTemplateTableMatchCandidate>(); return(SlowComputeRelativeSegmentsAndLookup(uri, uriPath, relativePathSegments, candidates)); } }
void ConstructFastPathTable() { this.noTemplateHasQueryPart = true; foreach (KeyValuePair <UriTemplate, object> kvp in this.templates) { UriTemplate ut = kvp.Key; if (!UriTemplateHelpers.CanMatchQueryTrivially(ut)) { this.noTemplateHasQueryPart = false; } if (ut.HasNoVariables && !ut.HasWildcard) { // eligible for fast path if (this.fastPathTable == null) { this.fastPathTable = new Dictionary <string, FastPathInfo>(); } Uri uri = ut.BindByPosition(this.originalUncanonicalizedBaseAddress); string uriPath = UriTemplateHelpers.GetUriPath(uri); if (this.fastPathTable.ContainsKey(uriPath)) { // nothing to do, we've already seen it } else { FastPathInfo fpInfo = new FastPathInfo(); if (ComputeRelativeSegmentsAndLookup(uri, fpInfo.RelativePathSegments, fpInfo.Candidates)) { fpInfo.Freeze(); this.fastPathTable.Add(uriPath, fpInfo); } } } } }
public Collection <UriTemplateMatch> Match(Uri uri) { if (uri == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); } if (!uri.IsAbsoluteUri) { return(None()); } this.MakeReadOnly(true); // Matching path : Collection <String> relativeSegments; IList <UriTemplateTableMatchCandidate> candidates; if (!FastComputeRelativeSegmentsAndLookup(uri, out relativeSegments, out candidates)) { return(None()); } // Matching query : NameValueCollection queryParameters = null; if (!this.noTemplateHasQueryPart && AtLeastOneCandidateHasQueryPart(candidates)) { Collection <UriTemplateTableMatchCandidate> nextCandidates = new Collection <UriTemplateTableMatchCandidate>(); Fx.Assert(nextCandidates.Count == 0, "nextCandidates should be empty"); // then deal with query queryParameters = UriTemplateHelpers.ParseQueryString(uri.Query); bool mustBeEspeciallyInteresting = NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(candidates); for (int i = 0; i < candidates.Count; i++) { if (UriTemplateHelpers.CanMatchQueryInterestingly(candidates[i].Template, queryParameters, mustBeEspeciallyInteresting)) { nextCandidates.Add(candidates[i]); } } if (nextCandidates.Count > 1) { Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); } if (nextCandidates.Count == 0) { for (int i = 0; i < candidates.Count; i++) { if (UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) { nextCandidates.Add(candidates[i]); } } } if (nextCandidates.Count == 0) { return(None()); } if (nextCandidates.Count > 1) { Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); } candidates = nextCandidates; } // Verifying that we have not broken the allowDuplicates settings because of terminal defaults // This situation can be caused when we are hosting ".../" and ".../{foo=xyz}" in the same // table. They are not equivalent; yet they reside together in the same path partially-equivalent // set. If we hit a uri that ends up in that particular end-of-path set, we want to provide the // user only the 'best' match and not both; thus preventing inconsistancy between the MakeReadonly // settings and the matching results. We will assume that the 'best' matches will be the ones with // the smallest number of segments - this will prefer ".../" over ".../{x=1}[/...]". if (NotAllCandidatesArePathFullyEquivalent(candidates)) { Collection <UriTemplateTableMatchCandidate> nextCandidates = new Collection <UriTemplateTableMatchCandidate>(); int minSegmentsCount = -1; for (int i = 0; i < candidates.Count; i++) { UriTemplateTableMatchCandidate candidate = candidates[i]; if (minSegmentsCount == -1) { minSegmentsCount = candidate.Template.segments.Count; nextCandidates.Add(candidate); } else if (candidate.Template.segments.Count < minSegmentsCount) { minSegmentsCount = candidate.Template.segments.Count; nextCandidates.Clear(); nextCandidates.Add(candidate); } else if (candidate.Template.segments.Count == minSegmentsCount) { nextCandidates.Add(candidate); } } Fx.Assert(minSegmentsCount != -1, "At least the first entry in the list should be kept"); Fx.Assert(nextCandidates.Count >= 1, "At least the first entry in the list should be kept"); Fx.Assert(nextCandidates[0].Template.segments.Count == minSegmentsCount, "Trivial"); candidates = nextCandidates; } // Building the actual result Collection <UriTemplateMatch> actualResults = new Collection <UriTemplateMatch>(); for (int i = 0; i < candidates.Count; i++) { UriTemplateTableMatchCandidate candidate = candidates[i]; UriTemplateMatch match = candidate.Template.CreateUriTemplateMatch(this.originalUncanonicalizedBaseAddress, uri, candidate.Data, candidate.SegmentsCount, relativeSegments, queryParameters); actualResults.Add(match); } return(actualResults); }
public Collection <UriTemplateMatch> Match(Uri uri) { Collection <string> collection; IList <UriTemplateTableMatchCandidate> list; if (uri == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); } if (!uri.IsAbsoluteUri) { return(None()); } this.MakeReadOnly(true); if (!this.FastComputeRelativeSegmentsAndLookup(uri, out collection, out list)) { return(None()); } NameValueCollection query = null; if (!this.noTemplateHasQueryPart && AtLeastOneCandidateHasQueryPart(list)) { Collection <UriTemplateTableMatchCandidate> collection2 = new Collection <UriTemplateTableMatchCandidate>(); query = UriTemplateHelpers.ParseQueryString(uri.Query); bool mustBeEspeciallyInteresting = NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(list); for (int j = 0; j < list.Count; j++) { UriTemplateTableMatchCandidate candidate3 = list[j]; if (UriTemplateHelpers.CanMatchQueryInterestingly(candidate3.Template, query, mustBeEspeciallyInteresting)) { collection2.Add(list[j]); } } int count = collection2.Count; if (collection2.Count == 0) { for (int k = 0; k < list.Count; k++) { UriTemplateTableMatchCandidate candidate4 = list[k]; if (UriTemplateHelpers.CanMatchQueryTrivially(candidate4.Template)) { collection2.Add(list[k]); } } } if (collection2.Count == 0) { return(None()); } int num6 = collection2.Count; list = collection2; } if (NotAllCandidatesArePathFullyEquivalent(list)) { Collection <UriTemplateTableMatchCandidate> collection3 = new Collection <UriTemplateTableMatchCandidate>(); int num3 = -1; for (int m = 0; m < list.Count; m++) { UriTemplateTableMatchCandidate item = list[m]; if (num3 == -1) { num3 = item.Template.segments.Count; collection3.Add(item); } else if (item.Template.segments.Count < num3) { num3 = item.Template.segments.Count; collection3.Clear(); collection3.Add(item); } else if (item.Template.segments.Count == num3) { collection3.Add(item); } } list = collection3; } Collection <UriTemplateMatch> collection4 = new Collection <UriTemplateMatch>(); for (int i = 0; i < list.Count; i++) { UriTemplateTableMatchCandidate candidate2 = list[i]; UriTemplateMatch match = candidate2.Template.CreateUriTemplateMatch(this.originalUncanonicalizedBaseAddress, uri, candidate2.Data, candidate2.SegmentsCount, collection, query); collection4.Add(match); } return(collection4); }