2009-01-14 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Wed, 14 Jan 2009 06:11:09 +0000 (06:11 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Wed, 14 Jan 2009 06:11:09 +0000 (06:11 -0000)
* ClientBase.cs, ClientRuntimeChannel.cs : added support for
  interactive channel initializers.

* ClientBase_InteractiveChannelInitializerTest.cs : new test, for
  IInteractiveChannelInitializers support in ClientBase<T>.

* System.ServiceModel_test.dll.sources :
  added ClientBase_InteractiveChannelInitializerTest.cs.

svn path=/trunk/mcs/; revision=123316

mcs/class/System.ServiceModel/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel/ClientBase.cs
mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs
mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources
mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog
mcs/class/System.ServiceModel/Test/System.ServiceModel/ClientBase_InteractiveChannelInitializerTest.cs [new file with mode: 0644]

index a6e3a34655ee9d813b3af19cd256d12f20975a51..8aaf4e8d5273c32155eea5c3951b3bb37514b98d 100755 (executable)
@@ -1,3 +1,8 @@
+2009-01-14  Astushi Enomoto  <atsushi@ximian.com>
+
+       * System.ServiceModel_test.dll.sources :
+         added ClientBase_InteractiveChannelInitializerTest.cs.
+
 2009-01-07  Astushi Enomoto  <atsushi@ximian.com>
 
        * net_2_1_raw_System.ServiceModel.dll.sources : add OperationContext
index 4742baf124ef9394cac3c2c89c50cc89e7e5dc28..bd7bf56678e10ec1183fdf53befa3116f7ffeae6 100755 (executable)
@@ -1,3 +1,8 @@
+2009-01-14  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * ClientBase.cs, ClientRuntimeChannel.cs : added support for
+         interactive channel initializers.
+
 2009-01-12  Geoff Norton  <gnorton@novell.com>
 
        * ClientBase.cs: Added a few delegates missing from ChannelBase
index 4e7410867cb5f88efc3614b3f80157aa3b0aa37f..14e1a21aa9ec27fce8db92171e3e4cfa0c312a27 100644 (file)
@@ -167,24 +167,21 @@ namespace System.ServiceModel
                        get { return InnerChannel.State; }
                }
 
-               [MonoTODO]
                public void Abort ()
                {
                        InnerChannel.Abort ();
                }
 
-               [MonoTODO]
                public void Close ()
                {
                        InnerChannel.Close ();
                }
 
-               [MonoTODO]
                public void DisplayInitializationUI ()
                {
+                       InnerChannel.DisplayInitializationUI ();
                }
 
-               [MonoTODO]
                void IDisposable.Dispose ()
                {
                        Close ();
index c3e5cd605e1b460a3096c9f01d6c6bb723ee675f..0c2a90739eb87020f3367cd976d6d8d089807ec3 100644 (file)
@@ -31,6 +31,7 @@ using System.ServiceModel.Channels;
 using System.ServiceModel.Description;
 using System.ServiceModel.Dispatcher;
 using System.ServiceModel.Security;
+using System.Threading;
 
 namespace System.ServiceModel
 {
@@ -57,6 +58,9 @@ namespace System.ServiceModel
                        this.runtime = runtime;
                        this.factory = factory;
                        _processDelegate = new ProcessDelegate (Process);
+
+                       // default values
+                       AllowInitializationUI = true;
                }
 
                public ClientRuntime Runtime {
@@ -65,39 +69,146 @@ namespace System.ServiceModel
 
                #region IClientChannel
 
-               [MonoTODO]
-               public bool AllowInitializationUI {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
-               }
+               bool did_interactive_initialization;
+
+               public bool AllowInitializationUI { get; set; }
 
-               [MonoTODO]
                public bool DidInteractiveInitialization {
-                       get { throw new NotImplementedException (); }
+                       get { return did_interactive_initialization; }
                }
 
                public Uri Via {
                        get { return runtime.Via; }
                }
 
-               [MonoTODO]
+               class DelegatingWaitHandle : WaitHandle
+               {
+                       public DelegatingWaitHandle (IAsyncResult [] results)
+                       {
+                               this.results = results;
+                       }
+
+                       IAsyncResult [] results;
+
+                       protected override void Dispose (bool disposing)
+                       {
+                               if (disposing)
+                                       foreach (var r in results)
+                                               r.AsyncWaitHandle.Close ();
+                       }
+
+                       public override bool WaitOne ()
+                       {
+                               foreach (var r in results)
+                                       r.AsyncWaitHandle.WaitOne ();
+                               return true;
+                       }
+
+                       public override bool WaitOne (int millisecondsTimeout)
+                       {
+                               return WaitOne (millisecondsTimeout, false);
+                       }
+
+                       WaitHandle [] ResultWaitHandles {
+                               get {
+                                       var arr = new WaitHandle [results.Length];
+                                       for (int i = 0; i < arr.Length; i++)
+                                               arr [i] = results [i].AsyncWaitHandle;
+                                       return arr;
+                               }
+                       }
+
+                       public override bool WaitOne (int millisecondsTimeout, bool exitContext)
+                       {
+                               return WaitHandle.WaitAll (ResultWaitHandles, millisecondsTimeout, exitContext);
+                       }
+
+                       public override bool WaitOne (TimeSpan timeout, bool exitContext)
+                       {
+                               return WaitHandle.WaitAll (ResultWaitHandles, timeout, exitContext);
+                       }
+               }
+
+               class DisplayUIAsyncResult : IAsyncResult
+               {
+                       public DisplayUIAsyncResult (IAsyncResult [] results)
+                       {
+                               this.results = results;
+                       }
+
+                       IAsyncResult [] results;
+
+                       internal IAsyncResult [] Results {
+                               get { return results; }
+                       }
+
+                       public object AsyncState {
+                               get { return null; }
+                       }
+
+                       WaitHandle wait_handle;
+
+                       public WaitHandle AsyncWaitHandle {
+                               get {
+                                       if (wait_handle == null)
+                                               wait_handle = new DelegatingWaitHandle (results);
+                                       return wait_handle;
+                               }
+                       }
+
+                       public bool CompletedSynchronously {
+                               get {
+                                       foreach (var r in results)
+                                               if (!r.CompletedSynchronously)
+                                                       return false;
+                                       return true;
+                               }
+                       }
+                       public bool IsCompleted {
+                               get {
+                                       foreach (var r in results)
+                                               if (!r.IsCompleted)
+                                                       return false;
+                                       return true;
+                               }
+                       }
+               }
+
                public IAsyncResult BeginDisplayInitializationUI (
                        AsyncCallback callback, object state)
                {
-                       throw new NotImplementedException ();
+                       OnInitializationUI ();
+                       IAsyncResult [] arr = new IAsyncResult [runtime.InteractiveChannelInitializers.Count];
+                       int i = 0;
+                       foreach (var init in runtime.InteractiveChannelInitializers)
+                               arr [i++] = init.BeginDisplayInitializationUI (this, callback, state);
+                       return new DisplayUIAsyncResult (arr);
                }
 
-               [MonoTODO]
                public void EndDisplayInitializationUI (
                        IAsyncResult result)
                {
-                       throw new NotImplementedException ();
+                       DisplayUIAsyncResult r = (DisplayUIAsyncResult) result;
+                       int i = 0;
+                       foreach (var init in runtime.InteractiveChannelInitializers)
+                               init.EndDisplayInitializationUI (r.Results [i++]);
+
+                       did_interactive_initialization = true;
                }
 
-               [MonoTODO]
                public void DisplayInitializationUI ()
                {
-                       throw new NotImplementedException ();
+                       OnInitializationUI ();
+                       foreach (var init in runtime.InteractiveChannelInitializers)
+                               init.EndDisplayInitializationUI (init.BeginDisplayInitializationUI (this, null, null));
+
+                       did_interactive_initialization = true;
+               }
+
+               void OnInitializationUI ()
+               {
+                       if (!AllowInitializationUI && runtime.InteractiveChannelInitializers.Count > 0)
+                               throw new InvalidOperationException ("AllowInitializationUI is set to false but the client runtime contains one or more InteractiveChannelInitializers.");
                }
 
                public void Dispose ()
@@ -192,6 +303,8 @@ namespace System.ServiceModel
 
                protected override void OnOpen (TimeSpan timeout)
                {
+                       if (runtime.InteractiveChannelInitializers.Count > 0 && !DidInteractiveInitialization)
+                               throw new InvalidOperationException ("The client runtime is assigned interactive channel initializers, and in such case DisplayInitializationUI must be called before the channel is opened.");
                }
 
                // IChannel
@@ -221,6 +334,8 @@ namespace System.ServiceModel
 
                public object Process (MethodBase method, string operationName, object [] parameters)
                {
+                       if (AllowInitializationUI)
+                               DisplayInitializationUI ();
                        OperationDescription od = SelectOperation (method, operationName, parameters);
                        if (!od.IsOneWay)
                                return Request (od, parameters);
index 3a799c37ae444b41a390d6601434906f33bcc12c..06fe2edee996cad39d060302ac429e1be5145913 100644 (file)
@@ -108,6 +108,7 @@ System.ServiceModel/BasicHttpBindingTest.cs
 System.ServiceModel/ChannelFactoryTest.cs
 System.ServiceModel/ChannelFactory_1Test.cs
 System.ServiceModel/ClientBaseTest.cs
+System.ServiceModel/ClientBase_InteractiveChannelInitializerTest.cs
 System.ServiceModel/ClientCredentialsSecurityTokenManagerTest.cs
 System.ServiceModel/CommonUseCases.cs
 System.ServiceModel/EndpointAddress10Test.cs
index 8bf6225382f06036e572532af48e6a4d686d64bd..6c8a1ea6624f917c4a7d4fffca8095678166cdfc 100755 (executable)
@@ -1,3 +1,8 @@
+2009-01-14  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * ClientBase_InteractiveChannelInitializerTest.cs : new test, for
+         IInteractiveChannelInitializers support in ClientBase<T>.
+
 2008-05-22  Roei Erez  <roeie@mainsoft.com>
        * fix ContractDescription.GetContract implementation
        * Refactor Request processing
diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel/ClientBase_InteractiveChannelInitializerTest.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel/ClientBase_InteractiveChannelInitializerTest.cs
new file mode 100644 (file)
index 0000000..c886a97
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// ClientBase_InteractiveChannelInitializerTest.cs
+//
+// Author:
+//     Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2006 Novell, Inc.  http://www.novell.com
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Net.Sockets;
+using System.Reflection;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+using System.ServiceModel.Dispatcher;
+using System.Xml;
+using NUnit.Framework;
+
+namespace MonoTests.System.ServiceModel
+{
+       [TestFixture]
+       // FIXME: it does not contain testcase for successful initialization yet
+       // (MyChannelInitializer implementation hangs on .NET)
+       public class ClientBase_InteractiveChannelInitializerTest
+       {
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void NotAllowedInitializationUI ()
+               {
+                       var f = new FooProxy (new BasicHttpBinding (), new EndpointAddress ("http://localhost:37564"));
+                       f.Endpoint.Contract.Behaviors.Add (new MyContractBehavior ());
+                       f.InnerChannel.AllowInitializationUI = false;
+                       f.DisplayInitializationUI ();
+               }
+
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void OpenBeforeDisplayInitializationUI ()
+               {
+                       var f = new FooProxy (new BasicHttpBinding (), new EndpointAddress ("http://localhost:37564"));
+                       f.Endpoint.Contract.Behaviors.Add (new MyContractBehavior ());
+                       f.Open ();
+               }
+
+               public class MyContractBehavior2 : MyContractBehavior
+               {
+               }
+
+               public class MyContractBehavior : IContractBehavior
+               {
+                       public void AddBindingParameters (ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
+                       {
+                       }
+
+                       public void ApplyClientBehavior (ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
+                       {
+                               clientRuntime.InteractiveChannelInitializers.Add (new MyChannelInitializer ());
+                       }
+
+                       public void ApplyDispatchBehavior (ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
+                       {
+                       }
+
+                       public void Validate (ContractDescription contractDescription, ServiceEndpoint endpoint)
+                       {
+                       }
+               }
+
+               public class MyChannelInitializer : IInteractiveChannelInitializer
+               {
+                       delegate void DoWork ();
+                       DoWork d;
+                       static int instance;
+                       int number;
+
+                       public MyChannelInitializer ()
+                       {
+                               number = instance++;
+                       }
+
+                       public IAsyncResult BeginDisplayInitializationUI (IClientChannel channel, AsyncCallback callback, object state)
+                       {
+                               Console.WriteLine ("Begin");
+                               d = new DoWork (DisplayInitializationUI);
+                               return d.BeginInvoke (null, null);
+                       }
+
+                       public void EndDisplayInitializationUI (IAsyncResult result)
+                       {
+                               Console.WriteLine ("End");
+                               d.EndInvoke (result);
+                       }
+
+                       public void DisplayInitializationUI ()
+                       {
+                               Console.WriteLine ("Core: " + number);
+                       }
+               }
+
+               public class FooProxy : ClientBase<IFoo>, IFoo
+               {
+                       public FooProxy (Binding binding, EndpointAddress address)
+                               : base (binding, address)
+                       {
+                       }
+
+                       public string Echo (string msg)
+                       {
+                               return Channel.Echo (msg);
+                       }
+               }
+
+               [ServiceContract]
+               public interface IFoo
+               {
+                       [OperationContract]
+                       string Echo (string input);
+               }
+
+               public class FooService : IFoo
+               {
+                       public string Echo (string input)
+                       {
+                               return input;
+                       }
+               }
+       }
+}