The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.MetadataServices \ SdlChannelSinkProvider

  1. // ==++==
  2. //
  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. //
  14. // ==--==
  15. //==========================================================================
  16. // File: SdlChannelSink.cs
  17. //
  18. // Summary: Sdl channel sink for generating sdl dynamically on the server.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.Collections;
  23. using System.Globalization;
  24. using System.IO;
  25. using System.Reflection;
  26. using System.Runtime.Remoting.Channels;
  27. using System.Runtime.Remoting.Channels.Http;
  28. using System.Runtime.Remoting.Messaging;
  29. using System.Text;
  30. namespace System.Runtime.Remoting.MetadataServices
  31. {
  32.    
  33.     public class SdlChannelSinkProvider : IServerChannelSinkProvider
  34.     {
  35.         private IServerChannelSinkProvider _next = null;
  36.         private bool _bRemoteApplicationMetadataEnabled = false;
  37.         private bool _bMetadataEnabled = true;
  38.        
  39.         public SdlChannelSinkProvider()
  40.         {
  41.         }
  42.        
  43.         public SdlChannelSinkProvider(IDictionary properties, ICollection providerData)
  44.         {
  45.             if (properties != null) {
  46.                 foreach (DictionaryEntry entry in properties) {
  47.                     switch ((string)entry.Key) {
  48.                         case "remoteApplicationMetadataEnabled":
  49.                             _bRemoteApplicationMetadataEnabled = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  50.                             break;
  51.                         case "metadataEnabled":
  52.                             _bMetadataEnabled = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture);
  53.                             break;
  54.                         default:
  55.                             CoreChannel.ReportUnknownProviderConfigProperty(this.GetType().Name, (string)entry.Key);
  56.                             break;
  57.                     }
  58.                 }
  59.             }
  60.         }
  61.        
  62.         public void GetChannelData(IChannelDataStore localChannelData)
  63.         {
  64.         }
  65.        
  66.         public IServerChannelSink CreateSink(IChannelReceiver channel)
  67.         {
  68.             IServerChannelSink nextSink = null;
  69.             if (_next != null)
  70.                 nextSink = _next.CreateSink(channel);
  71.            
  72.             SdlChannelSink channelSink = new SdlChannelSink(channel, nextSink);
  73.             channelSink.RemoteApplicationMetadataEnabled = _bRemoteApplicationMetadataEnabled;
  74.             channelSink.MetadataEnabled = _bMetadataEnabled;
  75.             return channelSink;
  76.         }
  77.        
  78.         public IServerChannelSinkProvider Next {
  79.             get { return _next; }
  80.             set { _next = value; }
  81.         }
  82.     }
  83.     // class SdlChannelSinkProvider
  84.    
  85.    
  86.    
  87.     public class SdlChannelSink : IServerChannelSink
  88.     {
  89.         private IChannelReceiver _receiver;
  90.         private IServerChannelSink _nextSink;
  91.         private bool _bRemoteApplicationMetadataEnabled = false;
  92.         private bool _bMetadataEnabled = false;
  93.        
  94.        
  95.         public SdlChannelSink(IChannelReceiver receiver, IServerChannelSink nextSink)
  96.         {
  97.             _receiver = receiver;
  98.             _nextSink = nextSink;
  99.         }
  100.         // SdlChannelSink
  101.         internal bool RemoteApplicationMetadataEnabled {
  102.             get { return _bRemoteApplicationMetadataEnabled; }
  103.             set { _bRemoteApplicationMetadataEnabled = value; }
  104.         }
  105.        
  106.         internal bool MetadataEnabled {
  107.             get { return _bMetadataEnabled; }
  108.             set { _bMetadataEnabled = value; }
  109.         }
  110.        
  111.         public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
  112.         {
  113.             if (requestMsg != null) {
  114.                 // The message has already been deserialized so delegate to the next sink.
  115.                 return _nextSink.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
  116.             }
  117.            
  118.             SdlType sdlType;
  119.             if (!ShouldIntercept(requestHeaders, out sdlType))
  120.                 return _nextSink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
  121.            
  122.             // generate sdl and return it
  123.             responseHeaders = new TransportHeaders();
  124.             GenerateSdl(sdlType, sinkStack, requestHeaders, responseHeaders, out responseStream);
  125.             responseMsg = null;
  126.            
  127.             return ServerProcessing.Complete;
  128.         }
  129.         // ProcessMessage
  130.         public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream)
  131.         {
  132.             // We don't need to implement this because we never push ourselves to the sink
  133.             // stack.
  134.         }
  135.         // AsyncProcessResponse
  136.         public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers)
  137.         {
  138.             // We don't need to implement this because we never push ourselves
  139.             // to the sink stack.
  140.             throw new NotSupportedException();
  141.         }
  142.         // GetResponseStream
  143.        
  144.         public IServerChannelSink NextChannelSink {
  145.             get { return _nextSink; }
  146.         }
  147.        
  148.        
  149.         public IDictionary Properties {
  150.             get { return null; }
  151.         }
  152.         // Properties
  153.        
  154.         // Should we intercept the call and return some SDL
  155.         private bool ShouldIntercept(ITransportHeaders requestHeaders, out SdlType sdlType)
  156.         {
  157.             sdlType = SdlType.Sdl;
  158.            
  159.             string requestVerb = requestHeaders["__RequestVerb"] as string;
  160.             string requestURI = requestHeaders["__RequestUri"] as string;
  161.            
  162.             // http verb must be "GET" to return sdl (and request uri must be set)
  163.             if ((requestURI == null) || (requestVerb == null) || !requestVerb.Equals("GET"))
  164.                 return false;
  165.            
  166.             // find last index of ? and look for "sdl" or "sdlx"
  167.             int index = requestURI.LastIndexOf('?');
  168.             if (index == -1)
  169.                 return false;
  170.             // no query string
  171.             string queryString = requestURI.Substring(index).ToLower(CultureInfo.InvariantCulture);
  172.            
  173.             // sdl?
  174.             if ((String.CompareOrdinal(queryString, "?sdl") == 0) || (String.CompareOrdinal(queryString, "?sdlx") == 0)) {
  175.                 sdlType = SdlType.Sdl;
  176.                 return true;
  177.             }
  178.            
  179.             // wsdl?
  180.             if (String.CompareOrdinal(queryString, "?wsdl") == 0) {
  181.                 sdlType = SdlType.Wsdl;
  182.                 return true;
  183.             }
  184.            
  185.             return false;
  186.         }
  187.         // ShouldIntercept
  188.        
  189.         private void GenerateSdl(SdlType sdlType, IServerResponseChannelSinkStack sinkStack, ITransportHeaders requestHeaders, ITransportHeaders responseHeaders, out Stream outputStream)
  190.         {
  191.             if (!MetadataEnabled)
  192.                 throw new RemotingException(CoreChannel.GetResourceString("Remoting_MetadataNotEnabled"));
  193.            
  194.             string requestUri = requestHeaders[CommonTransportKeys.RequestUri] as string;
  195.             string objectUri = HttpChannelHelper.GetObjectUriFromRequestUri(requestUri);
  196.            
  197.             if (!RemoteApplicationMetadataEnabled && (String.Compare(objectUri, "RemoteApplicationMetadata.rem", StringComparison.OrdinalIgnoreCase) == 0))
  198.                 throw new RemotingException(CoreChannel.GetResourceString("Remoting_RemoteApplicationMetadataNotEnabled"));
  199.            
  200.             // If the host header is present, we will use this in the generated uri's
  201.             string hostName = (string)requestHeaders["Host"];
  202.             if (hostName != null) {
  203.                 // filter out port number if present
  204.                 int index = hostName.IndexOf(':');
  205.                 if (index != -1)
  206.                     hostName = hostName.Substring(0, index);
  207.             }
  208.            
  209.            
  210.            
  211.             ServiceType[] types = null;
  212.            
  213.             if (String.Compare(objectUri, "RemoteApplicationMetadata.rem", StringComparison.OrdinalIgnoreCase) == 0) {
  214.                 // get the service description for all registered service types
  215.                
  216.                 ActivatedServiceTypeEntry[] activatedTypes = RemotingConfiguration.GetRegisteredActivatedServiceTypes();
  217.                
  218.                 WellKnownServiceTypeEntry[] wellKnownTypes = RemotingConfiguration.GetRegisteredWellKnownServiceTypes();
  219.                
  220.                 // determine total number of types
  221.                 int typeCount = 0;
  222.                
  223.                 if (activatedTypes != null)
  224.                     typeCount += activatedTypes.Length;
  225.                
  226.                 if (wellKnownTypes != null)
  227.                     typeCount += wellKnownTypes.Length;
  228.                
  229.                 types = new ServiceType[typeCount];
  230.                
  231.                 // collect data
  232.                 int co = 0;
  233.                 if (activatedTypes != null) {
  234.                     foreach (ActivatedServiceTypeEntry entry in activatedTypes) {
  235.                         types[co++] = new ServiceType(entry.ObjectType, null);
  236.                     }
  237.                 }
  238.                
  239.                 if (wellKnownTypes != null) {
  240.                     foreach (WellKnownServiceTypeEntry entry in wellKnownTypes) {
  241.                         string[] urls = _receiver.GetUrlsForUri(entry.ObjectUri);
  242.                         string url = urls[0];
  243.                         if (hostName != null)
  244.                             url = HttpChannelHelper.ReplaceMachineNameWithThisString(url, hostName);
  245.                        
  246.                         types[co++] = new ServiceType(entry.ObjectType, url);
  247.                     }
  248.                 }
  249.                
  250.                 InternalRemotingServices.RemotingAssert(co == typeCount, "Not all types were processed.");
  251.             }
  252.             else {
  253.                 // get the service description for a particular object
  254.                 Type objectType = RemotingServices.GetServerTypeForUri(objectUri);
  255.                 if (objectType == null) {
  256.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, "Object with uri '{0}' does not exist at server.", objectUri));
  257.                 }
  258.                
  259.                 string[] urls = _receiver.GetUrlsForUri(objectUri);
  260.                 string url = urls[0];
  261.                 if (hostName != null)
  262.                     url = HttpChannelHelper.ReplaceMachineNameWithThisString(url, hostName);
  263.                
  264.                 types = new ServiceType[1];
  265.                 types[0] = new ServiceType(objectType, url);
  266.             }
  267.            
  268.             responseHeaders["Content-Type"] = "text/xml";
  269.            
  270.             bool bMemStream = false;
  271.            
  272.             outputStream = sinkStack.GetResponseStream(null, responseHeaders);
  273.             if (outputStream == null) {
  274.                 outputStream = new MemoryStream(1024);
  275.                 bMemStream = true;
  276.             }
  277.            
  278.             MetaData.ConvertTypesToSchemaToStream(types, sdlType, outputStream);
  279.            
  280.             if (bMemStream)
  281.                 outputStream.Position = 0;
  282.         }
  283.         // GenerateXmlForUri
  284.     }
  285.     // class SdlChannelSink
  286.    
  287.    
  288. }
  289. // namespace System.Runtime.Remoting.Channnels

Developer Fusion