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 (KeyValuePairkvp 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
- SimpleMailWebEventProvider.cs
- Rules.cs
- TearOffProxy.cs
- WindowsTooltip.cs
- DrawingContextWalker.cs
- StaticExtension.cs
- TextReader.cs
- AutomationProperties.cs
- StandardBindingElement.cs
- SurrogateChar.cs
- ScriptControl.cs
- RegexGroupCollection.cs
- SHA384Managed.cs
- HtmlInputText.cs
- EffectiveValueEntry.cs
- BaseDataBoundControl.cs
- CheckedListBox.cs
- Win32Exception.cs
- ListBoxItemAutomationPeer.cs
- Schema.cs
- _SafeNetHandles.cs
- ZipIOExtraFieldPaddingElement.cs
- StrongNameMembershipCondition.cs
- HelpProvider.cs
- ConnectionOrientedTransportManager.cs
- XmlArrayAttribute.cs
- Token.cs
- RegistryPermission.cs
- IgnoreFileBuildProvider.cs
- WebControlsSection.cs
- FileSystemEventArgs.cs
- Errors.cs
- EventDescriptorCollection.cs
- ResetableIterator.cs
- Utility.cs
- WeakHashtable.cs
- TextWriter.cs
- MergablePropertyAttribute.cs
- PersonalizablePropertyEntry.cs
- smtppermission.cs
- WebPartDisplayModeCancelEventArgs.cs
- SerialPinChanges.cs
- TranslateTransform3D.cs
- SpellCheck.cs
- XomlCompilerError.cs
- PreservationFileReader.cs
- dbdatarecord.cs
- ProfileBuildProvider.cs
- XmlNamespaceMappingCollection.cs
- Vector3D.cs
- XamlTreeBuilder.cs
- CRYPTPROTECT_PROMPTSTRUCT.cs
- InterleavedZipPartStream.cs
- GenerateScriptTypeAttribute.cs
- HandlerBase.cs
- ExpressionVisitor.cs
- HttpResponseInternalWrapper.cs
- DesignBindingValueUIHandler.cs
- MenuScrollingVisibilityConverter.cs
- AuthenticationSection.cs
- BufferedGraphics.cs
- Config.cs
- MessageHeaderT.cs
- SuppressMergeCheckAttribute.cs
- ViewKeyConstraint.cs
- LogReserveAndAppendState.cs
- GridViewColumnHeader.cs
- MemberBinding.cs
- AjaxFrameworkAssemblyAttribute.cs
- SchemaComplexType.cs
- IApplicationTrustManager.cs
- DefaultPropertyAttribute.cs
- MenuAdapter.cs
- XamlPointCollectionSerializer.cs
- CodeTypeOfExpression.cs
- PersonalizationStateInfoCollection.cs
- XmlQueryType.cs
- WebPartEditorOkVerb.cs
- MonitorWrapper.cs
- BasicCellRelation.cs
- QilInvokeLateBound.cs
- PageContent.cs
- CapabilitiesAssignment.cs
- QuaternionAnimationBase.cs
- CookieHandler.cs
- EntitySetDataBindingList.cs
- AncillaryOps.cs
- FixUp.cs
- DomainUpDown.cs
- SafeProcessHandle.cs
- MethodImplAttribute.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- InitializerFacet.cs
- DataGridTextBoxColumn.cs
- ColorTransformHelper.cs
- Currency.cs
- VerificationException.cs
- SamlAdvice.cs
- HttpConfigurationContext.cs
- DeferredTextReference.cs