Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / NetFx35 / System.ServiceModel.Web / System / UriTemplateHelpers.cs / 3 / UriTemplateHelpers.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------
namespace System
{
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web;
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel.Channels;
static class UriTemplateHelpers
{
static UriTemplateQueryComparer queryComparer = new UriTemplateQueryComparer();
static UriTemplateQueryKeyComparer queryKeyComperar = new UriTemplateQueryKeyComparer();
[Conditional("DEBUG")]
public static void AssertCanonical(string s)
{
Fx.Assert(s == s.ToUpperInvariant(), "non-canonicalized");
}
public static bool CanMatchQueryInterestingly(UriTemplate ut, NameValueCollection query, bool mustBeEspeciallyInteresting)
{
if (ut.queries.Count == 0)
{
return false; // trivial, not interesting
}
string[] queryKeys = query.AllKeys;
foreach (KeyValuePair kvp in ut.queries)
{
string queryKeyName = kvp.Key;
if (kvp.Value.Nature == UriTemplatePartType.Literal)
{
bool queryKeysContainsQueryVarName = false;
for (int i = 0; i < queryKeys.Length; ++i)
{
if (StringComparer.OrdinalIgnoreCase.Equals(queryKeys[i], queryKeyName))
{
queryKeysContainsQueryVarName = true;
break;
}
}
if (!queryKeysContainsQueryVarName)
{
return false;
}
if (kvp.Value == UriTemplateQueryValue.Empty)
{
if (!string.IsNullOrEmpty(query[queryKeyName]))
{
return false;
}
}
else
{
if (((UriTemplateLiteralQueryValue)(kvp.Value)).AsRawUnescapedString() != query[queryKeyName])
{
return false;
}
}
}
else
{
if (mustBeEspeciallyInteresting && Array.IndexOf(queryKeys, queryKeyName) == -1)
{
return false;
}
}
}
return true;
}
public static bool CanMatchQueryTrivially(UriTemplate ut)
{
return (ut.queries.Count == 0);
}
public static void DisambiguateSamePath(UriTemplate[] array, int a, int b, bool allowDuplicateEquivalentUriTemplates)
{
// [a,b) all have same path
// ensure queries make them unambiguous
Fx.Assert(b > a, "array bug");
// sort empty queries to front
Array.Sort(array, a, b - a, queryComparer);
if (b - a == 1)
{
return; // if only one, cannot be ambiguous
}
if (!allowDuplicateEquivalentUriTemplates)
{
// ensure at most one empty query and ignore it
if (array[a].queries.Count == 0)
{
a++;
}
if (array[a].queries.Count == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
SR2.UTTDuplicate, array[a].ToString(), array[a - 1].ToString())));
}
if (b - a == 1)
{
return; // if only one, cannot be ambiguous
}
}
else
{
while (a < b && array[a].queries.Count == 0) // all equivalent
{
a++;
}
if (b - a <= 1)
{
return;
}
}
Fx.Assert(b > a, "array bug");
// now consider non-empty queries
// more than one, so enforce that
// forall
// exist set of querystringvars S where
// every op has literal value foreach var in S, and
// those literal tuples are different
EnsureQueriesAreDistinct(array, a, b, allowDuplicateEquivalentUriTemplates);
}
public static IEqualityComparer GetQueryKeyComparer()
{
return queryKeyComperar;
}
public static string GetUriPath(Uri uri)
{
return uri.GetComponents(UriComponents.Path | UriComponents.KeepDelimiter, UriFormat.Unescaped);
}
public static bool HasQueryLiteralRequirements(UriTemplate ut)
{
foreach (UriTemplateQueryValue utqv in ut.queries.Values)
{
if (utqv.Nature == UriTemplatePartType.Literal)
{
return true;
}
}
return false;
}
public static UriTemplatePartType IdentifyPartType(string part)
{
// Identifying the nature of a string - Literal|Compound|Variable
// Algorithem is based on the following steps:
// - Finding the position of the first open curlly brace ('{') and close curlly brace ('}')
// in the string
// - If we don't find any this is a Literal
// - otherwise, we validate that position of the close brace is at least two characters from
// the position of the open brace
// - Then we identify if we are dealing with a compound string or a single variable string
// + var name is not at the string start --> Compound
// + var name is shorter then the entire string (End < Length-2 or End==Length-2
// and string ends with '/') --> Compound
// + otherwise --> Variable
int varStartIndex = part.IndexOf("{", StringComparison.Ordinal);
int varEndIndex = part.IndexOf("}", StringComparison.Ordinal);
if (varStartIndex == -1)
{
if (varEndIndex != -1)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(
SR2.GetString(SR2.UTInvalidFormatSegmentOrQueryPart, part)));
}
return UriTemplatePartType.Literal;
}
else
{
if (varEndIndex < varStartIndex + 2)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(
SR2.GetString(SR2.UTInvalidFormatSegmentOrQueryPart, part)));
}
if (varStartIndex > 0)
{
return UriTemplatePartType.Compound;
}
else if ((varEndIndex < part.Length - 2) ||
((varEndIndex == part.Length - 2) && !part.EndsWith("/", StringComparison.Ordinal)))
{
return UriTemplatePartType.Compound;
}
else
{
return UriTemplatePartType.Variable;
}
}
}
public static bool IsWildcardPath(string path)
{
if (path.IndexOf('/') != -1)
{
return false;
}
UriTemplatePartType partType;
return IsWildcardSegment(path, out partType);
}
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", Justification = "This is internal method that needs to return multiple things")]
public static bool IsWildcardSegment(string segment, out UriTemplatePartType type)
{
type = IdentifyPartType(segment);
switch (type)
{
case UriTemplatePartType.Literal:
return (string.Compare(segment, UriTemplate.WildcardPath, StringComparison.Ordinal) == 0);
case UriTemplatePartType.Compound:
return false;
case UriTemplatePartType.Variable:
return ((segment.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) == 1) &&
!segment.EndsWith("/", StringComparison.Ordinal) &&
(segment.Length > UriTemplate.WildcardPath.Length + 2));
default:
Fx.Assert("Bad part type identification !");
return false;
}
}
public static NameValueCollection ParseQueryString(string query)
{
// We are adjusting the parsing of UrlUtility.ParseQueryString, which identify
// ?wsdl as a null key with wsdl as a value
NameValueCollection result = UrlUtility.ParseQueryString(query);
string nullKeyValuesString = result[(string) null];
if (!string.IsNullOrEmpty(nullKeyValuesString))
{
result.Remove(null);
string[] nullKeyValues = nullKeyValuesString.Split(',');
for (int i = 0; i < nullKeyValues.Length; i++)
{
result.Add(nullKeyValues[i], null);
}
}
return result;
}
static bool AllTemplatesAreEquivalent(IList array, int a, int b)
{
for (int i = a; i < b - 1; ++i)
{
if (!array[i].IsEquivalentTo(array[i + 1]))
{
return false;
}
}
return true;
}
static void EnsureQueriesAreDistinct(UriTemplate[] array, int a, int b, bool allowDuplicateEquivalentUriTemplates)
{
Dictionary queryVarNamesWithLiteralVals = new Dictionary(StringComparer.OrdinalIgnoreCase);
for (int i = a; i < b; ++i)
{
foreach (KeyValuePair kvp in array[i].queries)
{
if (kvp.Value.Nature == UriTemplatePartType.Literal)
{
if (!queryVarNamesWithLiteralVals.ContainsKey(kvp.Key))
{
queryVarNamesWithLiteralVals.Add(kvp.Key, 0);
}
}
}
}
// now we have set of possibilities:
// further refine to only those for whom all templates have literals
Dictionary queryVarNamesAllLiterals = new Dictionary(queryVarNamesWithLiteralVals);
for (int i = a; i < b; ++i)
{
foreach (string s in queryVarNamesWithLiteralVals.Keys)
{
if (!array[i].queries.ContainsKey(s) || (array[i].queries[s].Nature != UriTemplatePartType.Literal))
{
queryVarNamesAllLiterals.Remove(s);
}
}
}
queryVarNamesWithLiteralVals = null; // ensure we don't reference this variable any more
// now we have the set of names that every operation has as a literal
if (queryVarNamesAllLiterals.Count == 0)
{
if (allowDuplicateEquivalentUriTemplates && AllTemplatesAreEquivalent(array, a, b))
{
// we're ok, do nothing
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
SR2.UTTOtherAmbiguousQueries, array[a].ToString())));
}
}
// now just ensure that each template has a unique tuple of values for the names
string[][] upsLits = new string[b - a][];
for (int i = 0; i < b - a; ++i)
{
upsLits[i] = GetQueryLiterals(array[i + a], queryVarNamesAllLiterals);
}
for (int i = 0; i < b - a; ++i)
{
for (int j = i + 1; j < b - a; ++j)
{
if (Same(upsLits[i], upsLits[j]))
{
if (!array[i + a].IsEquivalentTo(array[j + a]))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
SR2.UTTAmbiguousQueries, array[a + i].ToString(), array[j + a].ToString())));
}
Fx.Assert(array[i + a].IsEquivalentTo(array[j + a]), "bad equiv logic");
if (!allowDuplicateEquivalentUriTemplates)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
SR2.UTTDuplicate, array[a + i].ToString(), array[j + a].ToString())));
}
}
}
}
// we're good. whew!
}
static string[] GetQueryLiterals(UriTemplate up, Dictionary queryVarNames)
{
string[] queryLitVals = new string[queryVarNames.Count];
int i = 0;
foreach (string queryVarName in queryVarNames.Keys)
{
Fx.Assert(up.queries.ContainsKey(queryVarName), "query doesn't have name");
UriTemplateQueryValue utqv = up.queries[queryVarName];
Fx.Assert(utqv.Nature == UriTemplatePartType.Literal, "query for name is not literal");
if (utqv == UriTemplateQueryValue.Empty)
{
queryLitVals[i] = null;
}
else
{
queryLitVals[i] = ((UriTemplateLiteralQueryValue)(utqv)).AsRawUnescapedString();
}
++i;
}
return queryLitVals;
}
static bool Same(string[] a, string[] b)
{
Fx.Assert(a.Length == b.Length, "arrays not same length");
for (int i = 0; i < a.Length; ++i)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
class UriTemplateQueryComparer : IComparer
{
public int Compare(UriTemplate x, UriTemplate y)
{
// sort the empty queries to the front
return Comparer.Default.Compare(x.queries.Count, y.queries.Count);
}
}
class UriTemplateQueryKeyComparer : IEqualityComparer
{
public bool Equals(string x, string y)
{
return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
}
public int GetHashCode(string obj)
{
if (obj == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("obj");
}
return obj.ToUpperInvariant().GetHashCode();
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ipaddressinformationcollection.cs
- OptimizerPatterns.cs
- ChineseLunisolarCalendar.cs
- Timer.cs
- XamlContextStack.cs
- FilteredDataSetHelper.cs
- EntitySetBase.cs
- Metadata.cs
- InvalidateEvent.cs
- Directory.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- CategoryValueConverter.cs
- JsonFormatGeneratorStatics.cs
- UrlRoutingModule.cs
- DataSourceControl.cs
- EventToken.cs
- QueryMatcher.cs
- SecurityDocument.cs
- DocumentOrderQuery.cs
- ResXBuildProvider.cs
- EntitySetBase.cs
- Annotation.cs
- StrongNameMembershipCondition.cs
- DataPagerFieldCommandEventArgs.cs
- WebServicesInteroperability.cs
- MimeObjectFactory.cs
- RuntimeConfigLKG.cs
- DataBindingHandlerAttribute.cs
- ReferenceEqualityComparer.cs
- XmlReaderSettings.cs
- RadialGradientBrush.cs
- ManagedFilter.cs
- GridViewItemAutomationPeer.cs
- Rectangle.cs
- PersonalizableAttribute.cs
- OSFeature.cs
- DataGridViewColumnHeaderCell.cs
- DispatcherEventArgs.cs
- FormParameter.cs
- ClientRuntimeConfig.cs
- RectConverter.cs
- XmlDocument.cs
- InfoCardPolicy.cs
- CFGGrammar.cs
- UriWriter.cs
- TreeNodeBinding.cs
- PinnedBufferMemoryStream.cs
- CrossContextChannel.cs
- ActiveXContainer.cs
- CustomAttributeBuilder.cs
- CfgRule.cs
- wgx_exports.cs
- DataControlFieldTypeEditor.cs
- wgx_commands.cs
- UserValidatedEventArgs.cs
- ActiveXHost.cs
- WMIGenerator.cs
- XmlArrayAttribute.cs
- StorageModelBuildProvider.cs
- UriScheme.cs
- EntityWrapperFactory.cs
- EntityDataSourceWizardForm.cs
- IIS7UserPrincipal.cs
- FontUnitConverter.cs
- MatrixCamera.cs
- SurrogateEncoder.cs
- SuppressIldasmAttribute.cs
- UiaCoreTypesApi.cs
- InternalControlCollection.cs
- JavaScriptObjectDeserializer.cs
- WebPartEventArgs.cs
- LayoutExceptionEventArgs.cs
- WebPartEditorApplyVerb.cs
- UnknownWrapper.cs
- AppliedDeviceFiltersEditor.cs
- ServerValidateEventArgs.cs
- MatrixTransform3D.cs
- JsonStringDataContract.cs
- PageCodeDomTreeGenerator.cs
- HebrewNumber.cs
- Button.cs
- NavigationFailedEventArgs.cs
- ListViewSelectEventArgs.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- DataServiceProviderMethods.cs
- FixedSOMSemanticBox.cs
- CodeCatchClause.cs
- FunctionUpdateCommand.cs
- EventLogEntry.cs
- SafeNativeMethods.cs
- SiteMapHierarchicalDataSourceView.cs
- PassportAuthenticationModule.cs
- CellParaClient.cs
- ClockController.cs
- Codec.cs
- DataGridColumnCollectionEditor.cs
- PropertyOverridesDialog.cs
- XsltConvert.cs
- HttpVersion.cs
- ExpressionParser.cs