Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / UriPrefixTable.cs / 1 / UriPrefixTable.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Net; using System.ServiceModel.Diagnostics; using System.Text; using System.Threading; using System.Web; using System.Web.Hosting; sealed class UriPrefixTablewhere TItem : class { int count; MruCache lookupCache; // cache matches, for lookup speed // separate table for WeakReference usage MruCache weakLookupCache; SegmentHierarchyNode root; bool useWeakReferences; bool includePortInComparison; public UriPrefixTable() : this(false) { } public UriPrefixTable(bool includePortInComparison) : this(includePortInComparison, false) { } public UriPrefixTable(bool includePortInComparison, bool useWeakReferences) { const int mruWatermark = 128; this.includePortInComparison = includePortInComparison; this.useWeakReferences = useWeakReferences; this.root = new SegmentHierarchyNode (null, useWeakReferences); if (useWeakReferences) { this.weakLookupCache = new MruCache (mruWatermark); } else { this.lookupCache = new MruCache (mruWatermark); } } object ThisLock { get { return this; } } public int Count { get { return this.count; } } public bool IsRegistered(BaseUriWithWildcard key) { Uri uri = key.BaseAddress; // don't need to normalize path since SegmentHierarchyNode is // already OrdinalIgnoreCase string[] paths = UriSegmenter.ToPath(uri, key.HostNameComparisonMode, this.includePortInComparison); bool exactMatch; SegmentHierarchyNode node; lock (ThisLock) { node = FindDataNode(paths, out exactMatch); } return exactMatch && node != null && node.Data != null; } public IEnumerable > GetAll() { lock (ThisLock) { List > result = new List >(); this.root.Collect(result); return result; } } bool TryCacheLookup(BaseUriWithWildcard key, out TItem item) { if (useWeakReferences) { WeakReference itemReference; if (this.weakLookupCache.TryGetValue(key, out itemReference)) { item = itemReference.Target as TItem; if (item != null) { return true; } else // dead link { this.weakLookupCache.Remove(key); } } } else { return this.lookupCache.TryGetValue(key, out item); } item = null; return false; } void AddToCache(BaseUriWithWildcard key, TItem item) { if (useWeakReferences) { this.weakLookupCache.Add(key, new WeakReference(item)); } else { this.lookupCache.Add(key, item); } } void ClearCache() { if (useWeakReferences) { this.weakLookupCache.Clear(); } else { this.lookupCache.Clear(); } } public bool TryLookupUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, out TItem item) { item = null; BaseUriWithWildcard key = new BaseUriWithWildcard(uri, hostNameComparisonMode); lock (ThisLock) { bool isCached = TryCacheLookup(key, out item); if (!isCached) { // exact match failed, perform the full lookup (which will also // catch case-insensitive variations that aren't yet in our cache) bool dummy; SegmentHierarchyNode node = FindDataNode( UriSegmenter.ToPath(key.BaseAddress, hostNameComparisonMode, this.includePortInComparison), out dummy); if (node != null) { item = node.Data; } // We want to cache both positive AND negative results AddToCache(key, item); } return (item != null); } } public void RegisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, TItem item) { DiagnosticUtility.DebugAssert(HostNameComparisonModeHelper.IsDefined(hostNameComparisonMode), "RegisterUri: Invalid HostNameComparisonMode value passed in."); lock (ThisLock) { // Since every newly registered Uri could alter what Prefixes should have matched, we // should clear the cache of any existing results and start over ClearCache(); BaseUriWithWildcard key = new BaseUriWithWildcard(uri, hostNameComparisonMode); SegmentHierarchyNode node = FindOrCreateNode(key); if (node.Data != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString( SR.DuplicateRegistration, uri))); } node.SetData(item, key); count++; } } public void UnregisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode) { lock (ThisLock) { // Since every removed Uri could alter what Prefixes should have matched, we // should clear the cache of any existing results and start over ClearCache(); string[] path = UriSegmenter.ToPath(uri, hostNameComparisonMode, this.includePortInComparison); // Never remove the root if (path.Length == 0) { this.root.RemoveData(); } else { this.root.RemovePath(path, 0); } count--; } } SegmentHierarchyNode FindDataNode(string[] path, out bool exactMatch) { DiagnosticUtility.DebugAssert(path != null, "FindDataNode: path is null"); exactMatch = false; SegmentHierarchyNode current = this.root; SegmentHierarchyNode result = null; for (int i = 0; i < path.Length; ++i) { SegmentHierarchyNode next; if (!current.TryGetChild(path[i], out next)) { break; } else if (next.Data != null) { result = next; exactMatch = (i == path.Length - 1); } current = next; } return result; } SegmentHierarchyNode FindOrCreateNode(BaseUriWithWildcard baseUri) { DiagnosticUtility.DebugAssert(baseUri != null, "FindOrCreateNode: baseUri is null"); string[] path = UriSegmenter.ToPath(baseUri.BaseAddress, baseUri.HostNameComparisonMode, this.includePortInComparison); SegmentHierarchyNode current = this.root; for (int i = 0; i < path.Length; ++i) { SegmentHierarchyNode next; if (!current.TryGetChild(path[i], out next)) { next = new SegmentHierarchyNode (path[i], useWeakReferences); current.SetChildNode(path[i], next); } current = next; } return current; } static class UriSegmenter { internal static string[] ToPath(Uri uriPath, HostNameComparisonMode hostNameComparisonMode, bool includePortInComparison) { if (null == uriPath) { return new string[0]; } UriSegmentEnum segmentEnum = new UriSegmentEnum(uriPath); // struct return segmentEnum.GetSegments(hostNameComparisonMode, includePortInComparison); } struct UriSegmentEnum { string segment; int segmentStartAt; int segmentLength; UriSegmentType type; Uri uri; internal UriSegmentEnum(Uri uri) { DiagnosticUtility.DebugAssert(null != uri, "UreSegmentEnum: null uri"); this.uri = uri; this.type = UriSegmentType.Unknown; this.segment = null; this.segmentStartAt = 0; this.segmentLength = 0; } void ClearSegment() { this.type = UriSegmentType.None; this.segment = string.Empty; this.segmentStartAt = 0; this.segmentLength = 0; } public string[] GetSegments(HostNameComparisonMode hostNameComparisonMode, bool includePortInComparison) { List segments = new List (); while (this.Next()) { switch (this.type) { case UriSegmentType.Path: segments.Add(this.segment.Substring(this.segmentStartAt, this.segmentLength)); break; case UriSegmentType.Host: if (hostNameComparisonMode == HostNameComparisonMode.StrongWildcard) { segments.Add("+"); } else if (hostNameComparisonMode == HostNameComparisonMode.Exact) { segments.Add(this.segment); } else { segments.Add("*"); } break; case UriSegmentType.Port: if (includePortInComparison || hostNameComparisonMode == HostNameComparisonMode.Exact) { segments.Add(this.segment); } break; default: segments.Add(this.segment); break; } } return segments.ToArray(); } public bool Next() { while (true) { switch (this.type) { case UriSegmentType.Unknown: this.type = UriSegmentType.Scheme; this.SetSegment(this.uri.Scheme); return true; case UriSegmentType.Scheme: this.type = UriSegmentType.Host; string host = this.uri.Host; // The userName+password also accompany... string userInfo = this.uri.UserInfo; if (null != userInfo && userInfo.Length > 0) { host = userInfo + '@' + host; } this.SetSegment(host); return true; case UriSegmentType.Host: this.type = UriSegmentType.Port; int port = this.uri.Port; this.SetSegment(port.ToString(CultureInfo.InvariantCulture)); return true; case UriSegmentType.Port: this.type = UriSegmentType.Path; string absPath = this.uri.AbsolutePath; DiagnosticUtility.DebugAssert(null != absPath, "Next: nill absPath"); if (0 == absPath.Length) { this.ClearSegment(); return false; } this.segment = absPath; this.segmentStartAt = 0; this.segmentLength = 0; return this.NextPathSegment(); case UriSegmentType.Path: return this.NextPathSegment(); case UriSegmentType.None: return false; default: DiagnosticUtility.DebugAssert("Next: unknown enum value"); return false; } } } public bool NextPathSegment() { this.segmentStartAt += this.segmentLength; while (this.segmentStartAt < this.segment.Length && this.segment[this.segmentStartAt] == '/') { this.segmentStartAt++; } if (this.segmentStartAt < this.segment.Length) { int next = this.segment.IndexOf('/', this.segmentStartAt); if (-1 == next) { this.segmentLength = this.segment.Length - this.segmentStartAt; } else { this.segmentLength = next - this.segmentStartAt; } return true; } this.ClearSegment(); return false; } void SetSegment(string segment) { this.segment = segment; this.segmentStartAt = 0; this.segmentLength = segment.Length; } enum UriSegmentType { Unknown, Scheme, Host, Port, Path, None } } } } class SegmentHierarchyNode where TData : class { BaseUriWithWildcard path; TData data; string name; Dictionary > children; WeakReference weakData; bool useWeakReferences; public SegmentHierarchyNode(string name, bool useWeakReferences) { this.name = name; this.useWeakReferences = useWeakReferences; this.children = new Dictionary >(StringComparer.OrdinalIgnoreCase); } public TData Data { get { if (useWeakReferences) { if (this.weakData == null) { return null; } else { return this.weakData.Target as TData; } } else { return this.data; } } } public void SetData(TData data, BaseUriWithWildcard path) { this.path = path; if (useWeakReferences) { if (data == null) { this.weakData = null; } else { this.weakData = new WeakReference(data); } } else { this.data = data; } } public void SetChildNode(string name, SegmentHierarchyNode node) { this.children[name] = node; } public void Collect(List > result) { TData localData = this.Data; if (localData != null) { result.Add(new KeyValuePair (path, localData)); } foreach (SegmentHierarchyNode child in this.children.Values) { child.Collect(result); } } public bool TryGetChild(string segment, out SegmentHierarchyNode value) { return children.TryGetValue(segment, out value); } public void RemoveData() { SetData(null, null); } // bool is whether to remove this node public bool RemovePath(string[] path, int seg) { if (seg == path.Length) { RemoveData(); return this.children.Count == 0; } SegmentHierarchyNode node; if (!TryGetChild(path[seg], out node)) { return (this.children.Count == 0 && Data == null); } if (node.RemovePath(path, seg + 1)) { this.children.Remove(path[seg]); return (this.children.Count == 0 && Data == null); } else { return false; } } } } // 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
- SourceChangedEventArgs.cs
- InvalidCommandTreeException.cs
- hwndwrapper.cs
- FieldNameLookup.cs
- RadioButtonList.cs
- DetailsViewCommandEventArgs.cs
- DocComment.cs
- XmlValidatingReaderImpl.cs
- PhysicalOps.cs
- GridViewCancelEditEventArgs.cs
- ISessionStateStore.cs
- TextBoxBase.cs
- FontInfo.cs
- UriSectionReader.cs
- ClickablePoint.cs
- XmlCharCheckingWriter.cs
- PropertyValidationContext.cs
- StrokeNodeEnumerator.cs
- BamlBinaryWriter.cs
- SQLGuid.cs
- PublisherIdentityPermission.cs
- TextCharacters.cs
- RijndaelManagedTransform.cs
- SecurityCriticalDataForSet.cs
- ConfigurationElement.cs
- BamlResourceContent.cs
- TypeDescriptor.cs
- XXXInfos.cs
- HandleDictionary.cs
- AttributeProviderAttribute.cs
- InputProcessorProfiles.cs
- ProcessInputEventArgs.cs
- FixedSOMElement.cs
- ClientUtils.cs
- OutOfProcStateClientManager.cs
- ToolboxBitmapAttribute.cs
- AddDataControlFieldDialog.cs
- SelectManyQueryOperator.cs
- BaseDataList.cs
- ScrollChrome.cs
- Monitor.cs
- ModelPropertyImpl.cs
- DeclaredTypeValidatorAttribute.cs
- PublishLicense.cs
- StateMachineWorkflowDesigner.cs
- IApplicationTrustManager.cs
- DbDataReader.cs
- PagedDataSource.cs
- InputLanguage.cs
- TextInfo.cs
- SQLBinary.cs
- CompositeControl.cs
- ExpressionsCollectionEditor.cs
- FindCriteria11.cs
- TransformProviderWrapper.cs
- QilPatternVisitor.cs
- XamlClipboardData.cs
- PrintPreviewGraphics.cs
- NamespaceDecl.cs
- SymLanguageType.cs
- RowToParametersTransformer.cs
- PrivateFontCollection.cs
- EventsTab.cs
- ReturnType.cs
- HttpSysSettings.cs
- ControlType.cs
- Number.cs
- OleDbParameter.cs
- ObjectStateEntryDbDataRecord.cs
- CallTemplateAction.cs
- SmtpReplyReaderFactory.cs
- ArrangedElement.cs
- CustomPopupPlacement.cs
- ProfileManager.cs
- PropertyMetadata.cs
- AddToCollection.cs
- ManipulationStartedEventArgs.cs
- DataGridViewColumn.cs
- GroupByExpressionRewriter.cs
- PeerEndPoint.cs
- UserControlAutomationPeer.cs
- AnimationStorage.cs
- DbConnectionPool.cs
- CodeDefaultValueExpression.cs
- ExpressionBuilderContext.cs
- TextEditorTables.cs
- WebServiceHandler.cs
- SimpleType.cs
- WebPartEditVerb.cs
- Normalizer.cs
- SqlVisitor.cs
- SystemUdpStatistics.cs
- ThreadAbortException.cs
- UnsafeNativeMethods.cs
- Point3DValueSerializer.cs
- PathGeometry.cs
- XmlSchemaCollection.cs
- NameTable.cs
- TextEncodedRawTextWriter.cs
- CounterSample.cs