2009-09-03 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / SvcHttpHandler.cs
1 //
2 // SvcHttpHandler.cs
3 //
4 // Author:
5 //      Ankit Jain  <jankit@novell.com>
6 //
7 // Copyright (C) 2006 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Web;
30 using System.Threading;
31
32 using System.ServiceModel;
33 using System.ServiceModel.Activation;
34 using System.ServiceModel.Configuration;
35 using System.ServiceModel.Description;
36
37 namespace System.ServiceModel.Channels {
38
39         internal class SvcHttpHandler : IHttpHandler
40         {
41                 Type type;
42                 Type factory_type;
43                 string path;
44                 Uri request_url;
45                 ServiceHostBase host;
46
47                 AspNetReplyChannel reply_channel;
48                 AutoResetEvent wait = new AutoResetEvent (false);
49                 AutoResetEvent listening = new AutoResetEvent (false);
50
51                 public SvcHttpHandler (Type type, Type factoryType, string path)
52                 {
53                         this.type = type;
54                         this.factory_type = factoryType;
55                         this.path = path;
56                 }
57
58                 public bool IsReusable 
59                 {
60                         get { return true; }
61                 }
62
63                 public bool WaitForRequest (AspNetReplyChannel reply_channel, TimeSpan timeout)
64                 {
65                         this.reply_channel = reply_channel;
66                         listening.Set ();
67
68                         return wait.WaitOne (timeout, false);
69                 }
70
71                 public void ProcessRequest (HttpContext context)
72                 {
73                         request_url = context.Request.Url;
74                         EnsureServiceHost ();
75
76                         reply_channel.Context = context;
77                         wait.Set ();
78
79                         listening.WaitOne ();
80                         reply_channel.Context = null;
81                 }
82
83                 public void Close ()
84                 {
85                         host.Close ();
86                         host = null;
87                 }
88
89                 void ApplyConfiguration (ServiceHost host)
90                 {
91                         foreach (ServiceElement service in ConfigUtil.ServicesSection.Services) {
92                                 foreach (ServiceEndpointElement endpoint in service.Endpoints) {
93                                         // FIXME: consider BindingName as well
94                                         ServiceEndpoint se = host.AddServiceEndpoint (
95                                                 endpoint.Contract,
96                                                 ConfigUtil.CreateBinding (endpoint.Binding, endpoint.BindingConfiguration),
97                                                 new Uri (path));
98                                 }
99                                 // behaviors
100                                 ServiceBehaviorElement behavior = ConfigUtil.BehaviorsSection.ServiceBehaviors.Find (service.BehaviorConfiguration);
101                                 if (behavior != null) {
102                                         foreach (BehaviorExtensionElement bxel in behavior) {
103                                                 IServiceBehavior b = null;
104                                                 ServiceMetadataPublishingElement meta = bxel as ServiceMetadataPublishingElement;
105                                                 if (meta != null) {
106                                                         ServiceMetadataBehavior smb = meta.CreateBehavior () as ServiceMetadataBehavior;
107                                                         smb.HttpGetUrl = request_url;
108                                                         // FIXME: HTTPS as well
109                                                         b = smb;
110                                                 }
111                                                 if (b != null)
112                                                         host.Description.Behaviors.Add (b);
113                                         }
114                                 }
115                         }
116                 }
117
118                 void EnsureServiceHost ()
119                 {
120                         if (reply_channel != null)
121                                 return;
122
123                         //ServiceHost for this not created yet
124                         var baseUri = new Uri (HttpContext.Current.Request.Url.GetLeftPart (UriPartial.Path));
125                         if (factory_type != null) {
126                                 host = ((ServiceHostFactory) Activator.CreateInstance (factory_type)).CreateServiceHost (type, new Uri [] {baseUri});
127                         }
128                         else
129                                 host = new ServiceHost (type, baseUri);
130
131 #if true
132                         //FIXME: Binding: Get from web.config.
133                         host.AddServiceEndpoint (ContractDescription.GetContract (type).Name,
134                                 new BasicHttpBinding (), new Uri (path, UriKind.Relative));
135 #else
136                         ApplyConfiguration (host);
137 #endif
138
139                         host.Open ();
140
141                         listening.WaitOne ();
142                 }
143         }
144 }