Update of /cvsroot/sharpcvslib/sharpcvslib/src/ICSharpCode/SharpCvsLib/Protocols
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31180/src/ICSharpCode/SharpCvsLib/Protocols
Added Files:
AbstractProtocol.cs ExtProtocol.cs IProtocol.cs
PServerProtocol.cs
Log Message:
Factored protocol support out of CvsServerConnection object, created a ProcessEvent handler subset that will eventually record perfomance stats around a cvs server connect and disconnect (between these events) and expose these to clients that are concerned about timing...and maybe other things? Also some more cleanup on the ResponseMessageEvents container class and the associated response events.
--- NEW FILE: PServerProtocol.cs ---
#region "Copyright"
// Copyright (C) 2004 Mike Krueger, Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Mike Krueger</author>
// <author>Clayton Harbour</author>
//
#endregion
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using ICSharpCode.SharpCvsLib.Exceptions;
using ICSharpCode.SharpCvsLib.Messages;
using ICSharpCode.SharpCvsLib.Requests;
using ICSharpCode.SharpCvsLib.Streams;
using log4net;
namespace ICSharpCode.SharpCvsLib.Protocols
{
/// <summary>
/// Handle connect and authentication for the pserver protocol.
/// </summary>
public class PServerProtocol : AbstractProtocol {
private readonly ILog LOGGER =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private const String PSERVER_AUTH_SUCCESS = "I LOVE YOU";
private const String PSERVER_AUTH_FAIL = "I HATE YOU";
private TcpClient tcpClient = null;
/// <summary>
/// The server timeout value.
/// </summary>
private int Timeout {
get {return this.Config.Timeout;}
}
/// <summary>
/// Tcp socket that the connect method should initialize.
/// </summary>
public TcpClient TcpClient {
get {return this.tcpClient;}
}
/// <summary>
/// Create a new instance of the pserver protocol.
/// </summary>
public PServerProtocol() {
}
/// <summary>
/// Connect to the cvs server.
/// </summary>
public override void Connect () {
this.HandlePserverAuthentication(this.Password);
}
/// <summary>
/// Disconnect from the cvs server.
/// </summary>
public override void Disconnect() {
this.TcpClient.Close();
}
///<summary>Either accept the pserver authentication response from the server or if the user
/// is invalid then throw an authentication exception.</summary>
///<param name="password">The password to send.</param>
///<exception cref="AuthenticationException">If the user is not valid.</exception>
private void HandlePserverAuthentication(String password) {
String retStr = this.SendPserverAuthentication(password);
if (retStr.Equals(PSERVER_AUTH_SUCCESS)) {
this.SendConnectedMessageEvent(this, new MessageEventArgs("Connection established"));
} else if (retStr.Equals(PSERVER_AUTH_FAIL)) {
try {
tcpClient.Close();
} finally {
throw new AuthenticationException();
}
} else {
StringBuilder msg = new StringBuilder ();
msg.Append("Unknown Server response : >").Append(retStr).Append("<");
this.SendDisconnectedMessageEvent(this, new MessageEventArgs(msg.ToString()));
try {
tcpClient.Close();
} finally {
throw new AuthenticationException(msg.ToString());
}
}
}
private String SendPserverAuthentication (String password) {
tcpClient = new TcpClient ();
tcpClient.SendTimeout = this.Timeout;
if (LOGGER.IsDebugEnabled) {
StringBuilder msg = new StringBuilder();
msg.Append("Before submitting pserver connect request. ");
msg.Append("this.Repository.CvsRoot.CvsRepository=[").Append(this.Repository.CvsRoot.CvsRepository).Append("]");
msg.Append("this.Repository.CvsRoot.User=[").Append(this.Repository.CvsRoot.User).Append("]");
msg.Append("has password=[").Append(null != password).Append("]");
msg.Append("port=[").Append(this.Repository.CvsRoot.Port).Append("]");
LOGGER.Debug (msg);
}
tcpClient.Connect(this.Repository.CvsRoot.Host, this.Repository.CvsRoot.Port);
SetInputStream(new CvsStream(tcpClient.GetStream()));
SetOutputStream(this.InputStream);
// inputStream = outputStream = new CvsStream(tcpClient.GetStream());
int MAX_RETRY = 1;
for (int i=0; i < MAX_RETRY; i++) {
try {
SubmitRequest(new PServerAuthRequest(this.Repository.CvsRoot.CvsRepository,
this.Repository.CvsRoot.User,
password));
break;
} catch (Exception e) {
LOGGER.Error (e);
}
}
InputStream.Flush();
string retStr;
try {
retStr = InputStream.ReadLine();
} catch (IOException e) {
String msg = "Failed to read line from server. " +
"It is possible that the remote server was down.";
LOGGER.Error (msg, e);
throw new AuthenticationException (msg);
}
return retStr;
}
/// <summary>
/// Submit a request to the cvs repository.
///
/// NOTE: I copied this from the CvsServerConnection because I did not want to create an
/// cyclic dependancy with the class for this one method.
/// </summary>
/// <param name="request"></param>
private void SubmitRequest(IRequest request) {
if (LOGGER.IsDebugEnabled) {
StringBuilder msg = new StringBuilder ();
msg.Append ("\nSubmit Request");
msg.Append ("\n\trequest=[").Append (request).Append ("]");
LOGGER.Debug (msg);
}
OutputStream.SendString(request.RequestString);
// PServer request does not modify the connection.
// if (request.DoesModifyConnection) {
// request.ModifyConnection(this);
// }
// Response is not expected from the pserver authentication...well it is handled seperately from
// this mechanism in any case.
// if (request.IsResponseExpected) {
// HandleResponses();
// }
}
}
}
--- NEW FILE: AbstractProtocol.cs ---
#region "Copyright"
// Copyright (C) 2004 Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Clayton Harbour</author>
//
#endregion
using System;
using ICSharpCode.SharpCvsLib.Config;
using ICSharpCode.SharpCvsLib.Messages;
using ICSharpCode.SharpCvsLib.Misc;
using ICSharpCode.SharpCvsLib.Streams;
using log4net;
namespace ICSharpCode.SharpCvsLib.Protocols
{
/// <summary>
/// Handle connect and authentication for the pserver protocol.
/// </summary>
public abstract class AbstractProtocol : IProtocol {
/// <summary>
/// Event that fires when a connection is made to the cvs server.
/// </summary>
public event MessageEventHandler ConnectedMessageEvent;
/// <summary>
/// Event that fires when a connection is broken to the cvs server.
/// </summary>
public event MessageEventHandler DisconnectedMessageEvent;
private readonly ILog LOGGER =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private string password;
private CvsStream inputStream;
private CvsStream outputStream;
private SharpCvsLibConfig config;
private WorkingDirectory repository;
/// <summary>
/// Configuration settings for sharpcvslib.
/// </summary>
protected SharpCvsLibConfig Config {
get {
if (null == this.config) {
this.config = SharpCvsLibConfig.GetInstance();
}
return this.config;
}
}
/// <summary>
/// Set the internal copy of the input stream.
/// </summary>
/// <param name="stream"></param>
protected void SetInputStream (CvsStream stream) {
this.inputStream = stream;
}
/// <summary>
/// Set the internal copy of the input stream.
/// </summary>
/// <param name="stream"></param>
protected void SetOutputStream (CvsStream stream) {
this.outputStream = stream;
}
/// <summary>
/// Send a connected message event to any clients listening.
/// </summary>
/// <param name="Object"></param>
/// <param name="e"></param>
protected void SendConnectedMessageEvent(object Object, MessageEventArgs e) {
try {
this.ConnectedMessageEvent(Object, e);
} catch (NullReferenceException) {
LOGGER.Debug("No one is listening to the connected event.");
}
}
/// <summary>
/// Send notification that the connection has been broken to the cvs server.
/// </summary>
/// <param name="Object"></param>
/// <param name="e"></param>
protected void SendDisconnectedMessageEvent(object Object, MessageEventArgs e) {
try {
this.DisconnectedMessageEvent(Object, e);
} catch (NullReferenceException) {
LOGGER.Debug("No one is listening to the disconnected event.");
}
}
/// <summary>
/// Sends messages to the cvs server.
/// </summary>
public CvsStream InputStream {
get {return this.inputStream;}
}
/// <summary>
/// Recieves messaages from the cvs server.
/// </summary>
public CvsStream OutputStream {
get {return this.outputStream;}
}
/// <summary>
/// Optional password field.
/// </summary>
public string Password {
get {return this.password;}
set {this.password = value;}
}
/// <summary>
/// The working directory or sandbox.
/// </summary>
public WorkingDirectory Repository {
get {return this.repository;}
set {this.repository = value;}
}
/// <summary>
/// Create a new instance of the ext (ssh) protocol.
/// </summary>
public AbstractProtocol() {
}
/// <summary>
/// Handle the connection.
/// </summary>
public abstract void Connect ();
/// <summary>
/// Handle disconnect from cvs server.
/// </summary>
public abstract void Disconnect();
}
}
--- NEW FILE: ExtProtocol.cs ---
#region "Copyright"
// Copyright (C) 2004 Mike Krueger, Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Mike Krueger</author>
// <author>Clayton Harbour</author>
//
#endregion
using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using ICSharpCode.SharpCvsLib.Config;
using ICSharpCode.SharpCvsLib.Exceptions;
using ICSharpCode.SharpCvsLib.Streams;
using log4net;
namespace ICSharpCode.SharpCvsLib.Protocols
{
/// <summary>
/// Handle connect and authentication for the pserver protocol.
/// </summary>
public class ExtProtocol : AbstractProtocol {
private readonly ILog LOGGER =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Process p = null;
/// <summary>
/// Create a new instance of the ext (ssh) protocol.
/// </summary>
public ExtProtocol() {
}
/// <summary>
/// Connect to the cvs server using the ext method.
/// </summary>
public override void Connect() {
this.HandleExtAuthentication();
}
/// <summary>
/// Disconnect from the cvs server.
/// </summary>
public override void Disconnect() {
if (p != null && !p.HasExited) {
p.Kill();
p.WaitForExit();
p = null;
}
}
private void HandleExtAuthentication () {
StringBuilder processArgs = new StringBuilder ();
processArgs.Append ("-l ").Append (this.Repository.CvsRoot.User);
processArgs.Append (" -q "); // quiet
processArgs.Append (" ").Append (this.Repository.CvsRoot.Host);
processArgs.Append (" \"cvs server\"");
try {
ProcessStartInfo startInfo =
new ProcessStartInfo(this.Config.Shell, processArgs.ToString ());
if (LOGGER.IsDebugEnabled) {
StringBuilder msg = new StringBuilder ();
msg.Append("Process=[").Append(this.Config.Shell).Append("]");
msg.Append("Process Arguments=[").Append(processArgs).Append("]");
LOGGER.Debug(msg);
}
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
p = new Process();
p.StartInfo = startInfo;
p.Exited += new EventHandler(this.ExitShellEvent);
p.Start();
} catch (Exception e) {
if (LOGGER.IsDebugEnabled) {
LOGGER.Debug(e);
}
throw new ExecuteShellException(this.Config.Shell + processArgs.ToString ());
}
BufferedStream errstream = new BufferedStream(p.StandardError.BaseStream);
//inputstream = new CvsStream(new BufferedStream(p.StandardOutput.BaseStream));
//outputstream = new CvsStream(new BufferedStream(p.StandardInput.BaseStream));
StreamWriter streamWriter = p.StandardInput;
StreamReader streamReader = p.StandardOutput;
//streamWriter.AutoFlush = true;
//streamReader.ReadToEnd ();
//streamWriter.WriteLine(password);
SetInputStream(new CvsStream (streamReader.BaseStream));
SetOutputStream(new CvsStream (streamWriter.BaseStream));
}
private void ExitShellEvent(object sender, EventArgs e) {
if (LOGGER.IsDebugEnabled) {
LOGGER.Debug("Process EXITED");
}
if (p.ExitCode != 0) {
throw new AuthenticationException();
}
}
}
}
--- NEW FILE: IProtocol.cs ---
#region "Copyright"
// Copyright (C) 2004 Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Clayton Harbour</author>
//
#endregion
using System;
using ICSharpCode.SharpCvsLib.Messages;
using ICSharpCode.SharpCvsLib.Misc;
using ICSharpCode.SharpCvsLib.Streams;
namespace ICSharpCode.SharpCvsLib.Protocols
{
/// <summary>
/// Handle connect and authentication for the pserver protocol.
/// </summary>
public interface IProtocol {
/// <summary>
/// Message sent when client has successfully connected to the cvs server.
/// </summary>
event MessageEventHandler ConnectedMessageEvent;
/// <summary>
/// Message sent when client has successfully disconnected from the cvs server.
/// </summary>
event MessageEventHandler DisconnectedMessageEvent;
/// <summary>
/// Optional password field.
/// </summary>
string Password {get;set;}
/// <summary>
/// Repository information used to get cvs server connection.
/// </summary>
WorkingDirectory Repository {get;set;}
/// <summary>
/// Input stream that allows sending messages to the cvs server.
/// </summary>
CvsStream InputStream {get;}
/// <summary>
/// Output stream that accepts messages from the cvs server.
/// </summary>
CvsStream OutputStream {get;}
/// <summary>
/// Connect to the remote cvs server.
/// </summary>
/// <exception cref="ICSharpCode.SharpCvsLib.Exceptions.AuthenticationException">If the client does not have the
/// have the proper credentials to access the repository.</exception>
void Connect();
/// <summary>
/// Disconnect and perform any resource clean-up necessary.
/// </summary>
void Disconnect();
}
}

Update of /cvsroot/sharpcvslib/sharpcvslib/src/ICSharpCode/SharpCvsLib/Messages
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31180/src/ICSharpCode/SharpCvsLib/Messages
Added Files:
ProcessEventArgs.cs ProcessEventHandler.cs
Log Message:
Factored protocol support out of CvsServerConnection object, created a ProcessEvent handler subset that will eventually record perfomance stats around a cvs server connect and disconnect (between these events) and expose these to clients that are concerned about timing...and maybe other things? Also some more cleanup on the ResponseMessageEvents container class and the associated response events.
--- NEW FILE: ProcessEventArgs.cs ---
#region "Copyright"
// Copyright (C) 2004 Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Clayton Harbour</author>
//
#endregion
using System;
namespace ICSharpCode.SharpCvsLib.Messages {
/// <summary>
/// Message event arguments.
/// </summary>
public class ProcessEventArgs : EventArgs {
private DateTime date;
/// <summary>
/// Get the date, this is set when the event arguments class is created.
/// </summary>
public DateTime Date {
get {return this.date;}
}
/// <summary>
/// Create a new instance of the message event arugments class.
/// </summary>
public ProcessEventArgs() {
this.date = DateTime.Now;
}
}
}
--- NEW FILE: ProcessEventHandler.cs ---
#region "Copyright"
// Copyright (C) 2004 Clayton Harbour
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
//
// <author>Clayton Harbour</author>
//
#endregion
using System;
namespace ICSharpCode.SharpCvsLib.Messages {
/// <summary>
/// Default process handler for sharpcvslib. This is used to measure information about the
/// executing process, and will eventually be used to measure method starts, etc.
/// </summary>
public delegate void ProcessEventHandler (object sender, ProcessEventArgs e);
}