The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlRegisteredNonCachedStream

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlDownloadManager.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml
  16. {
  17.    
  18.     using System;
  19.     using System.IO;
  20.     using System.Net;
  21.     using System.Security;
  22.     using System.Xml.Schema;
  23.     using System.Collections;
  24.     using System.Security.Policy;
  25.    
  26.     //
  27.     // XmlDownloadManager
  28.     //
  29.     internal class XmlDownloadManager
  30.     {
  31.         Hashtable connections;
  32.        
  33.         internal Stream GetStream(Uri uri, ICredentials credentials)
  34.         {
  35.             if (uri.Scheme == "file") {
  36.                 return new FileStream(uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read, 1);
  37.             }
  38.             else {
  39.                 return GetNonFileStream(uri, credentials);
  40.             }
  41.         }
  42.        
  43.         private Stream GetNonFileStream(Uri uri, ICredentials credentials)
  44.         {
  45.             WebRequest req = WebRequest.Create(uri);
  46.             if (credentials != null) {
  47.                 req.Credentials = credentials;
  48.             }
  49.             WebResponse resp = req.GetResponse();
  50.             HttpWebRequest webReq = req as HttpWebRequest;
  51.             if (webReq != null) {
  52.                 lock (this) {
  53.                     if (connections == null) {
  54.                         connections = new Hashtable();
  55.                     }
  56.                     OpenedHost openedHost = (OpenedHost)connections[webReq.Address.Host];
  57.                     if (openedHost == null) {
  58.                         openedHost = new OpenedHost();
  59.                     }
  60.                    
  61.                     if (openedHost.nonCachedConnectionsCount < webReq.ServicePoint.ConnectionLimit - 1) {
  62.                         // we are not close to connection limit -> don't cache the stream
  63.                         if (openedHost.nonCachedConnectionsCount == 0) {
  64.                             connections.Add(webReq.Address.Host, openedHost);
  65.                         }
  66.                         openedHost.nonCachedConnectionsCount++;
  67.                         return new XmlRegisteredNonCachedStream(resp.GetResponseStream(), this, webReq.Address.Host);
  68.                     }
  69.                     else {
  70.                         // cache the stream and save the connection for the next request
  71.                         return new XmlCachedStream(resp.ResponseUri, resp.GetResponseStream());
  72.                     }
  73.                 }
  74.             }
  75.             else {
  76.                 return resp.GetResponseStream();
  77.             }
  78.         }
  79.        
  80.         internal void Remove(string host)
  81.         {
  82.             lock (this) {
  83.                 OpenedHost openedHost = (OpenedHost)connections[host];
  84.                 if (openedHost != null) {
  85.                     if (--openedHost.nonCachedConnectionsCount == 0) {
  86.                         connections.Remove(host);
  87.                     }
  88.                 }
  89.             }
  90.         }
  91.        
  92.     }
  93.    
  94.     //
  95.     // OpenedHost
  96.     //
  97.     internal class OpenedHost
  98.     {
  99.         internal int nonCachedConnectionsCount;
  100.     }
  101.    
  102.     //
  103.     // XmlRegisteredNonCachedStream
  104.     //
  105.     internal class XmlRegisteredNonCachedStream : Stream
  106.     {
  107.         protected Stream stream;
  108.         XmlDownloadManager downloadManager;
  109.         string host;
  110.        
  111.         internal XmlRegisteredNonCachedStream(Stream stream, XmlDownloadManager downloadManager, string host)
  112.         {
  113.             this.stream = stream;
  114.             this.downloadManager = downloadManager;
  115.             this.host = host;
  116.         }
  117.        
  118.         ~XmlRegisteredNonCachedStream()
  119.         {
  120.             if (downloadManager != null) {
  121.                 downloadManager.Remove(host);
  122.             }
  123.             stream = null;
  124.             // The base class, Stream, provides its own finalizer
  125.         }
  126.        
  127.         protected override void Dispose(bool disposing)
  128.         {
  129.             try {
  130.                 if (disposing && stream != null) {
  131.                     if (downloadManager != null) {
  132.                         downloadManager.Remove(host);
  133.                     }
  134.                     stream.Close();
  135.                 }
  136.                 stream = null;
  137.                 GC.SuppressFinalize(this);
  138.                 // do not call finalizer
  139.             }
  140.             finally {
  141.                 base.Dispose(disposing);
  142.             }
  143.         }
  144.        
  145.         //
  146.         // Stream
  147.         //
  148.         public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  149.         {
  150.             return stream.BeginRead(buffer, offset, count, callback, state);
  151.         }
  152.        
  153.         public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  154.         {
  155.             return BeginWrite(buffer, offset, count, callback, state);
  156.         }
  157.        
  158.         public override int EndRead(IAsyncResult asyncResult)
  159.         {
  160.             return stream.EndRead(asyncResult);
  161.         }
  162.        
  163.         public override void EndWrite(IAsyncResult asyncResult)
  164.         {
  165.             stream.EndWrite(asyncResult);
  166.         }
  167.        
  168.         public override void Flush()
  169.         {
  170.             stream.Flush();
  171.         }
  172.        
  173.         public override int Read(byte[] buffer, int offset, int count)
  174.         {
  175.             return stream.Read(buffer, offset, count);
  176.         }
  177.        
  178.         public override int ReadByte()
  179.         {
  180.             return stream.ReadByte();
  181.         }
  182.        
  183.         public override long Seek(long offset, SeekOrigin origin)
  184.         {
  185.             return stream.Seek(offset, origin);
  186.         }
  187.        
  188.         public override void SetLength(long value)
  189.         {
  190.             stream.SetLength(value);
  191.         }
  192.        
  193.         public override void Write(byte[] buffer, int offset, int count)
  194.         {
  195.             stream.Write(buffer, offset, count);
  196.         }
  197.        
  198.         public override void WriteByte(byte value)
  199.         {
  200.             stream.WriteByte(value);
  201.         }
  202.        
  203.         public override bool CanRead {
  204.             get { return stream.CanRead; }
  205.         }
  206.        
  207.         public override bool CanSeek {
  208.             get { return stream.CanSeek; }
  209.         }
  210.        
  211.         public override bool CanWrite {
  212.             get { return stream.CanWrite; }
  213.         }
  214.        
  215.         public override long Length {
  216.             get { return stream.Length; }
  217.         }
  218.        
  219.         public override long Position {
  220.             get { return stream.Position; }
  221.             set { stream.Position = value; }
  222.         }
  223.     }
  224.    
  225.     //
  226.     // XmlCachedStream
  227.     //
  228.     internal class XmlCachedStream : MemoryStream
  229.     {
  230.         private const int MoveBufferSize = 4096;
  231.        
  232.         private Uri uri;
  233.        
  234.         internal XmlCachedStream(Uri uri, Stream stream) : base()
  235.         {
  236.            
  237.             this.uri = uri;
  238.            
  239.             try {
  240.                 byte[] bytes = new byte[MoveBufferSize];
  241.                 int read = 0;
  242.                 while ((read = stream.Read(bytes, 0, MoveBufferSize)) > 0) {
  243.                     this.Write(bytes, 0, read);
  244.                 }
  245.                 base.Position = 0;
  246.             }
  247.             finally {
  248.                 stream.Close();
  249.             }
  250.         }
  251.     }
  252. }

Developer Fusion