/*
* Copyright (c) 2009 Craig Sutherland
*
* 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.Generic;
using System.Linq;
using System.Text;
using ThoughtWorks.CruiseControl.Remote;
using ThoughtWorks.CruiseControl.Remote.Messages;
using System.Runtime.Remoting;
namespace FastForward.Cache
{
public class CacheConnection
: ServerConnectionBase, IServerConnection, IDisposable
{
#region Private fields
private const string cacheUri = "fastforwardcache.rem";
private readonly Uri serverAddress;
private IMessageProcessor client;
private bool isBusy;
#endregion
#region Constructors
///
/// Initialises a new to a remote server.
///
/// The address of the remote server.
public CacheConnection(string serverAddress)
: this(new Uri(serverAddress))
{
}
///
/// Initialises a new to a remote server.
///
/// The address of the remote server.
public CacheConnection(Uri serverAddress)
{
UriBuilder builder = new UriBuilder(serverAddress);
if (builder.Port == -1) builder.Port = 23571;
this.serverAddress = new Uri(builder.Uri, "/" + cacheUri);
}
#endregion
#region Public properties
#region Type
///
/// The type of connection.
///
public string Type
{
get { return "FastForward.NET Cache (TCP)"; }
}
#endregion
#region ServerName
///
/// The name of the server that this connection is for.
///
public string ServerName
{
get { return serverAddress.Host; }
}
#endregion
#region IsBusy
///
/// Is this connection busy performing an operation.
///
public bool IsBusy
{
get { return isBusy; }
}
#endregion
#region Address
///
/// The address of the client.
///
public virtual string Address
{
get { return serverAddress.AbsoluteUri; }
}
#endregion
#endregion
#region Public methods
#region SendMessage()
///
/// Sends a message via HTTP.
///
///
///
///
public virtual Response SendMessage(string action, ServerRequest request)
{
// Initialise the connection and send the message
try
{
InitialiseRemoting();
FireRequestSending(action, request);
var result = client.ProcessMessage(action, request);
FireResponseReceived(action, result);
return result;
}
catch (Exception error)
{
// Replace the original exception with a communications exception
throw new CommunicationsException(error.Message);
}
}
#endregion
#region SendMessageAsync()
///
/// Sends a message to a remote server asychronously.
///
/// The action to perform.
/// The request to send to the server.
public virtual void SendMessageAsync(string action, ServerRequest request)
{
SendMessageAsync(action, request, null);
}
///
/// Sends a message to a remote server asychronously.
///
/// The action to perform.
/// The request to send to the server.
/// Any user state data.
///
/// This operation will still be done in a synchronous mode.
///
public virtual void SendMessageAsync(string action, ServerRequest request, object userState)
{
if (isBusy) throw new InvalidOperationException();
try
{
isBusy = true;
InitialiseRemoting();
var result = client.ProcessMessage(action, request);
if (SendMessageCompleted != null)
{
var args = new MessageReceivedEventArgs(result, null, false, userState);
SendMessageCompleted(this, args);
}
}
catch (Exception error)
{
if (SendMessageCompleted != null)
{
var args = new MessageReceivedEventArgs(null, error, false, userState);
SendMessageCompleted(this, args);
}
}
finally
{
isBusy = false;
}
}
#endregion
#region CancelAsync()
///
/// Cancels an asynchronous operation.
///
public virtual void CancelAsync()
{
CancelAsync(null);
}
///
/// Cancels an asynchronous operation.
///
///
public void CancelAsync(object userState)
{
// .NET remoting operations are not asynchronous, therefore can't cancel anything
}
#endregion
#region Dispose()
///
/// Disposes the .NET remoting client.
///
public virtual void Dispose()
{
client = null;
}
#endregion
#endregion
#region Public events
#region SendMessageCompleted
///
/// A SendMessageAsync has completed.
///
public event EventHandler SendMessageCompleted;
#endregion
#endregion
#region Private methods
#region InitialiseRemoting()
///
/// Initialises the client connection.
///
private void InitialiseRemoting()
{
if (client == null)
{
// Initialise the actual client
client = RemotingServices.Connect(typeof(IMessageProcessor),
serverAddress.AbsoluteUri) as IMessageProcessor;
}
}
#endregion
#endregion
}
}