/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.ObjectModel; using System.ServiceModel; using System.ServiceModel.Channels; namespace Apache.NMS.WCF { /// /// Factory for message channels. /// public class NmsChannelFactory : ChannelFactoryBase { #region Constructors /// /// Initializes a new instance of the class. /// /// The binding element. /// The context. internal NmsChannelFactory(NmsTransportBindingElement bindingElement, BindingContext context) : base(context.Binding) { _bindingElement = bindingElement; Collection messageEncoderBindingElements = context.BindingParameters.FindAll(); if(messageEncoderBindingElements.Count > 1) { throw new InvalidOperationException("More than one MessageEncodingBindingElement was found in the BindingParameters of the BindingContext"); } _encoderFactory = (messageEncoderBindingElements.Count == 0) ? NmsConstants.DefaultMessageEncoderFactory : messageEncoderBindingElements[0].CreateMessageEncoderFactory(); _bufferManager = BufferManager.CreateBufferManager(bindingElement.MaxBufferPoolSize, Int32.MaxValue); _destination = bindingElement.Destination; _destinationType = bindingElement.DestinationType; Tracer.DebugFormat("Destination ({0}) : {1}", _destinationType, _destination); } #endregion #region Implementation of ChannelFactoryBase /// /// Inserts processing on a communication object after it transitions into the opening state which must complete within a specified interval of time. /// /// The that specifies how long the on open operation has to complete before timing out. /// is less than zero. /// The interval of time specified by that was allotted for the operation was exceeded before the operation was completed. protected override void OnOpen(TimeSpan timeout) { NmsChannelHelper.ValidateTimeout(timeout); } /// /// Inserts processing on a communication object after it transitions to the opening state due to the invocation of an asynchronous open operation. /// /// /// The that references the asynchronous on open operation. /// /// The that specifies how long the on open operation has to complete before timing out. /// The delegate that receives notification of the completion of the asynchronous on open operation. /// An object, specified by the application, that contains state information associated with the asynchronous on open operation. /// is less than zero. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { return new CompletedAsyncResult(callback, state); } /// /// Completes an asynchronous operation on the open of a communication object. /// /// The that is returned by a call to the method. protected override void OnEndOpen(IAsyncResult result) { CompletedAsyncResult.End(result); } /// /// When implemented in a derived class, provides an extensibility point when creating channels. /// /// /// An NMS channel with the specified addresses. /// /// The of the remote endpoint to which the channel sends messages. /// The that contains the transport address to which messages are sent on the output channel. protected override TChannel OnCreateChannel(EndpointAddress address, Uri via) { if(!String.Equals(address.Uri.Scheme, _bindingElement.Scheme, StringComparison.InvariantCultureIgnoreCase)) { throw new ArgumentException(String.Format("The scheme {0} specified in address is not supported.", address.Uri.Scheme), "remoteAddress"); } if(typeof(TChannel) == typeof(IOutputChannel)) { return (TChannel) (object) new NmsOutputChannel(this, address, via, BufferManager, MessageEncoderFactory, Destination, DestinationType); } if(typeof(TChannel) == typeof(IOutputSessionChannel)) { return (TChannel) (object) new NmsOutputSessionChannel(this, via, address, BufferManager, MessageEncoderFactory, Destination, DestinationType); } throw new NotSupportedException(String.Format("The requested channel type {0} is not supported", typeof(TChannel))); } #endregion /// /// Invoked during the transition of a communication object into the closing state. /// protected override void OnClosed() { base.OnClosed(); _bufferManager.Clear(); } /// /// Gets the buffer manager. /// public BufferManager BufferManager { get { return _bufferManager; } } /// /// Gets the message encoder factory. /// public MessageEncoderFactory MessageEncoderFactory { get { return _encoderFactory; } } /// /// Gets the destination. /// /// The destination. public string Destination { get { return _destination; } } /// /// Gets the type of the destination. /// /// The type of the destination. public DestinationType DestinationType { get { return _destinationType; } } #region Private members private readonly BufferManager _bufferManager; private readonly MessageEncoderFactory _encoderFactory; private readonly string _destination; private readonly DestinationType _destinationType; private readonly NmsTransportBindingElement _bindingElement; #endregion } }