Powered by Twitter Tools.

September 2008
M T W T F S S
« Aug    
1234567
891011121314
15161718192021
22232425262728
2930  

Chris Donnan : Programming - Brooklyn Style

software, trading, family, fun

Google’s open source AjaXSLT project

I just stumbled across googles AjaXSLT open source XPath and XSLT enjine written in JavaScript.

Pretty cool I must say.

-Chris


I need a construct for Link Paths… how I got there… XLink

I need a construct that I can use in general to show a chain of links…

For example:

I was reading Here in article X, then I linked through to Here in article Y, then I linked through to Here in article Z. From there I linked to article B and Article C.

This is a sort of directed graph - I could represent it with a simple XML Construct like:

Link Path

I think a usage of XLink arc traversal coupled with XPointer for excerpts would do perfectly. The trick now is to make something that client app could use.. perhaps a lil’ ajaxy widget to show these things - lets call them xpaths - lol, nah - for some reason I think that would not do.. how about - LinkPaths.For example - this would work for the linking part - XLink arc traversals mostly. I would also like to include references via XPointer - but most of the web is still NON xml. What this menas is that if I where to reference another document - chances are - it would be an Html document - so I could not XPointer it. We could take these LinkPaths and embed them in a hidden div. If this was the case - we could show the data with an ajax widget. This would ALSO allow search engines or bots that support the protocol to find the LinkPaths and ultimately use them (if they needed).

I will work on a simple viewer for these things. I have often wanted to include the ‘path I followed to get somewhere’ This should do.

-Chris

Update: I need to add Comments to each lp:go element so that I can render comments about that reference. These should be XHTML perhaps. Also these could be organized in an OMPL list - outlining my various LinkPaths that I have followed. I also need some ‘ link rel=”tag” ‘ areas so that we could tag these links by topic. Then I could view how I was traversing topics (sort of)… More to come.


ISDA offering an FPML Course in NYC tomorrow

ISDA FPML Course in NYC tomorrow

ISDA - the International Swaps and Derivatives Association is giving an intro level course on FPML (Financial products Mark-up Language) tomorrow in NYC. They will cover the ‘basics’ of FPML/ XML and also go into some product examples with CDS and Interest Rate products. Anyone programming in the capital markets space should have some basic notion of how this stuff works :)

-Chris


Active RDF - a set of tools for semantic web work using ruby

Active RDF - is a set of tools for semantic web work using ruby. I have been looking at the Redland RDF Application Framework from Dave Beckett lately. I believe this makes use of it - good stuff!

read more | digg story


Deep Integration of Ruby with Semantic Web Ontologies

A great article (*warning* PDF) chatting about the match that could/would exist between Ruby and the Semantic web technologies.

I agree that the match between the way of ontoloties and and the way of languages like Java and C# may be off.

I will be curious to see if any supporting frameworks come about in this space.

-Chris

read more | digg story


Atlas for ASP.net 2.0 CTP released

Atlas is microsoft’s framework for developing Ajax applications for ASP.Net 2.0. The latest is now the march CTP -moving up from ‘beta’ status to ‘community technology preview’. As much as I loathe the ‘ajax’ name and all of the hype around this old stuff - It is still as cool as it was when we did it 3 years ago (or longer).

-Chris

read more | digg story


Object Binding (.Net 1.0)

Lately - I have been up to some Presentation Layer programming. I have been making a mechanism to create bind-able things from our entity objects. This will enable us to bind to grids and other UI elements. We need to be able to create N number of views for our Entity objects - and not put code in odd places in our layered architecture. For example; if we have a FooObject entity class (and/ or several derived FooObject types), - we need to make many different views of this same entity - really entity collections - FooObjectCollection(s).
That being said - in the past I have done this a few ways -

#1) Implement the interfaces for binding (needs to be done over and over for all objects). Since our objects are sometimes quite deep aggregates of other objects, this amounts to lots of work in this case. It is not very DRY (Dont Repeat Yourself) - you need to do this again and again for each object that you want to bind.

#2) Attributes on the entity classes to define attributes at binding- the limitation here is that you get 1 view definition and it is embedded in the entity object. This also puts code for the Presentation Layer in the Domain Layer. This involves reflection and there are more ‘reflectiony variations’ on this approach - but they are basically the same.

#3) Manually create datasets, datatables, dataviews, etc. from your entities. This means manually plucking info out of your classes and sticking them into the datasets. This approach results in you loosing your entities and programming to datasets etc. It becomes a mess. You could use many dataset variants - strongly typed datasets, non-strongly typed datasets, yadda yadda….

#4) Our approach in the end was to use metadata to create a bindable something. This metadata is XML that looks something like:

The XML Meta-data for binding looks like this (this is a flat view):
2 <View>
3 <Band DisplayName=”FooObject” Type=”Some.Name.Space.FooObject, Some.Name.Space”>
4 <Column DisplayName=”FooObjectDetails Id” Path=”FooObjectDetails.Id” Type=”System.String” />
5 <Column DisplayName=”FooObjectDetails Version” Path=”FooObjectDetails.Version” Type=”System.Int32″ />
6 <Column DisplayName=”FooObjectDetails Type” Path=”FooObjectDetails.Type” Type=”System.String” />
7 <Column DisplayName=”FooObjectDetails Name” Path=”FooObjectDetails.Name” Type=”System.String” />
8 <Column DisplayName=”FooObjectDetails FlahFlah” Path=”FooObjectDetails.FlahFlah” Type=”System.String” />
9 <Column DisplayName=”FooObjectDetails IsSomething” Path=”FooObjectDetails.IsSomething” Type=”System.Boolean” />
10 <Column DisplayName=”FooObjectDetails State” Path=”FooObjectDetails.State” Type=”Some.Name.Space.State, Some.Name.Space” />
11 <Column DisplayName= “Location” Path=”FooObjectDetails.Location” Type=”Some.Name.Space.Location, Some.Name.Space” />
12 <Column DisplayName= “SizeOfMe” Path=”FooObjectDetails.SizeOfMe” Type=”Some.Name.Space.SizeOfMe, Some.Name.Space” />
13 <Column DisplayName=”FooObjectDetails FooObjectId” Path=”FooObjectDetails.FooObjectId” Type=”System.String” />
14 <Column DisplayName=”FooObjectDetails Approval” Path=”FooObjectDetails.Approval” Type=”System.String” />
15 <Column DisplayName=”FooObjectDetails SuperHat” Path=”FooObjectDetails.SuperHat” Type=”System.Int32″ />
16 <Column DisplayName=”FooObjectDetails SomeScenario” Path=”FooObjectDetails.SomeScenario” Type=”System.String” />
17 <Column DisplayName= “UptraProperty” Path=”FooObjectDetails.UptraProperty” Type=”System.String” />
18 <Column DisplayName=”FooObjectDetails ChildClothing” Path=”FooObjectDetails.ChildClothing” Type=”System.Double” />
19 <Column DisplayName=”FooObjectDetails Gap” Path=”FooObjectDetails.Gap” Type=”System.String” />
20 <Column DisplayName=”FooObjectDetails ProductGroup” Path=”FooObjectDetails.ProductGroup” Type=”System.String” />
21 <Column DisplayName=”FooObjectDetails Blargh Ref” Path=”FooObjectDetails.Blargh.Ref” Type=”System.String” />
22 <Column DisplayName=”FooObjectDetails Blargh Id” Path=”FooObjectDetails.Blargh.Id” Type=”System.String” />
23 <Column DisplayName= “RationaleOfLife” Path=”FooObjectDetails.RationaleOfLife” Type=”Some.Name.Space.RationaleOfLife, Some.Name.Space” />
24 <Column DisplayName= “FeeType” Path=”FooObjectDetails.AProperty.FeeType” Type=”Some.Name.Space.FeeType2, Some.Name.Space” />
25 <Column DisplayName= “SalesPerson” Path=”FooObjectDetails.AProperty.SalesPerson” Type=”System.String” />
26 <Column DisplayName= “KiddieKooKi Farfehn” Path=”FooObjectDetails.AProperty.KiddieKooKi.Farfehn” Type=”System.String” />
27 <Column DisplayName= “AProperty KiddieKooKi Amount” Path=”FooObjectDetails.AProperty.KiddieKooKi.Amount” Type=”System.Double” />
28 <Column DisplayName=”FooObjectDetails AProperty Farfehn” Path=”FooObjectDetails.AProperty.Farfehn” Type=”System.String” />

That Xml is then loaded as part of a IViewDescriptor in IObjectView :
3 public interface IObjectView
4 {
5 ///
6 /// Gets or sets the source object.
7 ///
8 /// The source object.
9 object SourceObject { get; set; }
10
11 ///
12 /// Gets or sets the view descriptor.
13 ///
14 /// The view descriptor.
15 IViewDescriptor ViewDescriptor { get; set; }
16
17 ///
18 /// Gets the bindable object.
19 ///
20 ///
21 object GetBindableObject();
22 }

Then at runtime you get the IViewDefintion, the source object - and call GetBindableObject() to get something to bind to.

Like so:
257 private void BindDemoForm_Load(object sender, EventArgs e)
258 {
262 // Get a view from the view repository
263 IObjectView objectView = appContext.ObjectViewRepository.GetByKey( “BindDemoForm.ModelView3″ );
264
265 //give the view some data to bind to (the fooObjects in the FooObjectRepository in this case)
266 objectView.SourceObject = appContext.FooObjectRepository.Values;
267
268 // bind to the grid
269 gridBinder.SetObjectToGrid( grid, objectView );
270
271 // get underlying objects when grid is clicked
272 gridBinder.RowDoubleClick += new StuckRowClickHandler(gridBinder_RowDoubleClick);
273 }

After that - we hook up some events so that when we select or click on a row in a grid - we get the underlying Entity object in stead of a row. This means that all of your business operations can happen on your business object - not on a dataset, etc.

This looks something like:
345 private void gridBinder_RowDoubleClick(object sender, StuckRowClickEventArgs e)
346 {
347 // get the underlying item in 1 line of code :)
348 FooObject fooObject = e.BoundObject as FooObject;
349 Debug.Assert( fooObject != null );
350 string formatString = “Your underlying object \nFooObject Id = {0}, FooObject Version = {1}, Type = [{2}]“;
351 string fooObjectDescription = string.Format(
352 formatString,
353 fooObject.FooObjectDetails.Id,
354 fooObject.FooObjectDetails.Version,
355 fooObject.GetType().ToString()
356 );
357 fooObject.FooObjectDetails.FooObjectId = new Random().Next().ToString();
358 gridBinder.UpdateRowFromObject( e.GridRow, fooObject );
359 MessageBox.Show( this, fooObjectDescription );
360 }

There are several advantages to this approach: You can flatten your view of a hierarchical object, you can change the look in the hierarchy, or of course - you can use the existing hierarchy. You can define an unlimited number of views. You can do business operations on your objects directly - not on DataSets/ DataTables/ DataRows, etc.

Behind the scenes - in essence - we are inferring a schema from the root object using reflection. From there - we create a series of datatables in a dataset - complete with relations for the hierarchy etc.

It was quite easy to derive classes from DataTable, DataRow and DataColumn. Doing this allowed me to attach the ColumnDescriptor class and the bound object to the DataRow. The ColumnDescriptors keep the translated meta-data at run-time. The underlying object that the row (and child rows) are bound to are in the BoundObject of the DataRow. The DataTable keeps a reference to the translated meta-data - the BandDescriptor and creates new derived DataRows as required.
9 public class StuckDataTable : DataTable
10 {
11 private BandDescriptor bandDescriptor;
12
13 public BandDescriptor BandDescriptor
14 {
15 get { return bandDescriptor; }
16 set { bandDescriptor = value; }
17 }
18
19 public StuckDataTable()
20 : base()
21 {
22 }
23
24 public StuckDataTable( SerializationInfo info, StreamingContext context )
25 : base( info, context )
26 {
27 }
28
29 public StuckDataTable( string tableName )
30 : base( tableName )
31 {
32 }
33
34 protected override DataRow NewRowFromBuilder( DataRowBuilder builder )
35 {
36 return new StuckDataRow( builder );
37 }
38 }

9 public class StuckDataColumn : DataColumn
10 {
11 private ColumnDescriptor columnDescriptor;
12
13 public StuckDataColumn()
14 : base()
15 {
16 }
17
18 public StuckDataColumn( string columnName, Type dataType, string expr, MappingType type )
19 : base( columnName, dataType, expr, type)
20 {
21 }
22
23 public StuckDataColumn( string columnName, Type dataType, string expr )
24 : base( columnName, dataType, expr )
25 {
26 }
27
28 public StuckDataColumn( string columnName, Type dataType )
29 : base( columnName, dataType )
30 {
31 }
32
33 public StuckDataColumn( string columnName )
34 : base( columnName )
35 {
36 }
37
38 public ColumnDescriptor ColumnDescriptor
39 {
40 get { return columnDescriptor; }
41 set { columnDescriptor = value; }
42 }
43
44 }
8 public class StuckDataRow : DataRow
9 {
10 object boundObject;
11
12 public StuckDataRow( DataRowBuilder builder )
13 : base( builder )
14 {
15 }
16
17 public object BoundObject
18 {
19 get { return boundObject; }
20 set { boundObject = value; }
21 }
22 }
To generate the Xml to do the binding required I whipped up a simple little UI. This UI allows you to load an assembly, list it’s types and generate the basic Xml Meta-data - either flattened or to match the full object hierarchy. From there - you can re-arrange the Xml, delete some etc. This gets us far along the path of binding very complex objects to grids and other things.More to come on ObjectBinding - I have flapped enough for tonight. We can chat some more about how Enum binding was handled, the getting and setting of properties using the nifty Object.SubObject.SubObject.Property syntax….. more to come.

-Chris-


Serialization of Interfaces and/ or abstract classes via web services….. Objects vs data elements !
So - working on the latest and greatest solution. Great stuff - win forms app - lots (for us) of developers, I have had proper development practice/ time to plan etc so far.. I feel great about the current architecture. One thing is getting my goat and it seems to be something that i have a specific example of -but many have griped about in general. Objects vs data elements - We are basically using a rich domain model along with an MVC pattern - business tier lies behind a web service - so the web service facade is basically the business tier. In essence -we are passing around these ‘model types’ or ‘entity types’ between our client tier and our business tier -  which again I mentioned is a web service. This pattern is great and enables the application in just about every way.The 1st hurdle to overcome - I found very little written about. So — we have some assmblies that contain (amoungst other things) some ‘model types’. The client tier uses these model types - the business tier does. We XML serialize these model types to communicate between the two. This 1st issues was how to declare our model types on the client side using references NOT WEB REFERENCES. We want to add a reference to the library and then use the class - then just pass it across the wire to the business tier (web services). The web services use the SAME library, deserialize the class and KNOW it is the same type as ITS locally referenced class.

Every example out there - you declare any ‘model types’ as though they belong to the web service- and this is fine for the trivial example, BUT in an application where you are using shared libraries - you WANT the behaviour I am describing. References to assemblies - use your classes - send them to the web service and they stars align.

The answer is dumb. Make your ‘model types’ in your library assembly XML serializable. You can add some simple attributes like:


[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/FooConcreteA.xsd)]

[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/FooConcreteA.xsd", IsNullable=false)]

public class FooConcreteA : AbstractFooBase


You can also get deeper (you will want to) and assign more granular XML serialization attributes. You can add references to this library assembly to your client project as well as to your web service project. This is the dumb part. Now - make a method that returns a model type and build. Now add a web reference to your client project and build. You get - under the ‘web service’ reference node in your project a ‘Reference.map’ - under that is a ‘Reference.cs’ file. See how your web service proxy is created and a new serializable class with the same name as your original class is created (somewhere near the bottom)? - Comment out that class and add a using your library statement on the top of this class. Now - you are apples to apples - you are referencing the SAME class that is from your library - not this new ghost class that was created for you. So - you can simply use your locally referenced class and hand it to the web service :) (PS - remember that each time you update your web reference the Reference.cs file is destroyed)

Problem 2 - Now we have our nice - rich domain mode. We have objects that contain other objects etc. The issue now is…Objects vs data elements. We have some interfaces and/ or abstract classes. When you make a local reference to a class - you ‘have’ all of it’s methods/ properties - you just need to cast to get pointers to the interface/ class members. When you serialize an abstract class - you get the serialized base information only. For example:


WindowsApplication1.WebService1.Service1 svs = new WindowsApplication1.WebService1.Service1();

//HelloWorld() returns AbstractFooBase - like a factory

AbstractTest.FooConcreteA fooConcreteA = (FooConcreteA)svs.HelloWorld();


This type of thing just does not work. You cannot use any object inheritence (as I can see it) via web service. So - when you have a class that contains a collection of abstract types - you need to manage them EACH BY THEIR INDIVIDUAL CONCRETE TYPE - thereby killing the usefullness of objects.

Still workin’ on our incarnation of an answer ….



How to encapsulate a Load Balancer - Server Iron - Foundry Networks :)

using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Configuration;
using System.Web;
using System.Diagnostics;
using System.Collections;
using log4net;

namespace ServerFarm.ServerIron
{
///


/// Available protocols for the Load Balancer’s bindings
///

public enum Protocol
{
Http = 1,
Ssl = 2,
Smtp = 3
}
///
/// possible states of the connection to a load balancer
///

public enum ConnectionState
{
Closed = 1,
Open = 2,
Connecting = 3
}
///
/// All the commands that can be sent to the Server Iron Load Balancer
///

public class Commands
{
public static string Config = “conf t”;
public static string ServerReal = “server real #REALSERVERNAME#”;
public static string HttpDisable = “port http disable”;
public static string SslDisable = “port ssl disable”;
public static string HttpEnable = “no port http disable”;
public static string SslEnable = “no port ssl disable”;
public static string SmtpDisable = “port 25 disable”;
public static string SmtpEnable = “no port 25 disable”;
public static string Show = “show server real”;
public static string ShowBind = “show server bind”;
//public static string NoPage = “enable skip-page-display”;
public static string NoPage = “skip-page-display”;
public static string Page = “page-display”;
}
///
/// Encapsulates all of the LoadBalancer functionality.
///

public class LoadBalancer
{
string loadBalancerIP;
string loadBalancerUserName;
string loadBalancerPassword;
DateTime loginStartTime ;
DateTime wiatForPromptTime;
int timeout;
int wiatForPromptTimeOut;
long startTicks;
long nowTicks;
StringBuilder loadBalancerText = new StringBuilder();
TcpClient telnetServer;
NetworkStream writeStream ;
StreamReader readStream;
StringBuilder bindText = new StringBuilder();
StringBuilder realText = new StringBuilder();
ConnectionState connectionState = ConnectionState.Closed;
bool doPage = true;
// Create a logger for use in this class
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
///
/// zero argument constructor.
/// you must set the IPAddress, UserName and Password
/// properties to use this class’s methods
///

public LoadBalancer()
{
Init();
}
///
/// constructor with all needed values
///

/// IP Address of the load balancer /// a valid username /// a valid password public LoadBalancer(string iPAddress, string userName, string password)
{

//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.Ctor():”+ iPAddress +”,”+ userName +”,”+ password);
this.IPAddress = iPAddress;
this.UserName = userName;
this.Password = password;
Init();
}
private void Init()
{
}
///


/// Paged data back
///

public bool Page
{
get { return doPage; }
set { doPage = value; }
}
///
/// IP Address of the load balancer
///

public string IPAddress
{
get { return loadBalancerIP; }
set { loadBalancerIP = value; }
}
///
/// IP Address of the load balancer
///

public ConnectionState CurrentConnectionState
{
get { return connectionState; }
}
///
/// a valid username for this load balancer
///

public string UserName
{
get { return loadBalancerUserName; }
set { loadBalancerUserName = value; }
}
///
/// password that matches username
///

public string Password
{
get { return loadBalancerPassword; }
set { loadBalancerPassword = value; }
}
///
/// TcpClient that connects to Load Balancer
///

public TcpClient TcpObject
{
get { return telnetServer; }
}
///
/// NetworkStream used to write to Load Balancer
///

public NetworkStream WriteStream
{
get { return writeStream; }
}
///
/// StreamReader used to read from Load Balancer
///

public StreamReader ReadStream
{
get { return readStream; }
}

///


/// string bindings text from Load Balancer
///

public string ShowBindText
{
get { return bindText.ToString(); }
}
///
/// string show server real text from Load Balancer
///

public string ServerRealText
{
get { return realText.ToString(); }
}
public void Close()
{
try
{
if( connectionState == ConnectionState.Open)
{
//if still in config mode, end it
SendLine(”end”);
WiatForPrompt();
SendLine(Commands.Page);
WiatForPrompt();
doPage = true;
}
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
connectionState = ConnectionState.Closed;
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”LoadBalancer.Close() failed”,e);
throw new ApplicationException(”LoadBalancer.Close() failed”, e);
}
}
///
/// enables a site to recieve requests according to
/// it’s currently bound VIP.
///

///
/// note that this will enable both ssl and http.
/// To enable one or the other use the overridden
///
/// SiteEnable(string site,Protocol protocol)
///
method
///

/// the name of the site to be put in service public void SiteEnable(string site)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteEnable(string site):”+ site);
try
{
// connect with the server
Connect();
// Change real server reference
SendLine(Commands.ServerReal.Replace(”#REALSERVERNAME#”,site));
WiatForPrompt();
// Enable Http
SendLine(Commands.HttpEnable);
WiatForPrompt();
// Enable Ssl
SendLine(Commands.SslEnable);
WiatForPrompt();

// Get back global reference
SendLine(”exit”);
WiatForPrompt();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”SiteEnable(string site)”,e);
throw new ApplicationException(”SiteEnable(string site)”, e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// Disables a site from recieving requests according to
/// it’s currently bound VIP
///

///
/// note that this will disable both ssl and http bindings.
/// To disable one or the other use the overridden
///
/// SiteDisable(string site,Protocol protocol)
///
method
///

/// the site name to disable public void SiteDisable(string site)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteDisable(string site):”+ site);
try
{
// connect with the server
Connect();
// Change real server reference
SendLine(Commands.ServerReal.Replace(”#REALSERVERNAME#”,site));
WiatForPrompt();
// Disable Http
SendLine(Commands.HttpDisable);
WiatForPrompt();
// Disable Ssl
SendLine(Commands.SslDisable);
WiatForPrompt();

// Get back global reference
SendLine(”exit”);
WiatForPrompt();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”SiteDisable(string site)”,e);
throw new ApplicationException(”SiteDisable(string site)”, e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// enables a site to recieve requests according to
/// it’s currently bound VIP
///

/// the name of the site to be put in service /// the protocol to enable public void SiteEnable(string site, Protocol protocol)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteEnable(string site, Protocol protocol):”+ site +” : “+ protocol.ToString());
try
{
// connect with the server
Connect();
//return loadBalancerText.ToString();

// Change real server reference
SendLine(Commands.ServerReal.Replace(”#REALSERVERNAME#”,site));
WiatForPrompt();
switch(protocol)
{
case Protocol.Http:
// Enable Http
SendLine(Commands.HttpEnable);
WiatForPrompt();
break;
case Protocol.Ssl:
// Enable Ssl
SendLine(Commands.SslEnable);
WiatForPrompt();
break;
case Protocol.Smtp:
// Enable Smtp
SendLine(Commands.SmtpEnable);
WiatForPrompt();
break;
}
// Get back global reference
SendLine(”exit”);
WiatForPrompt();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”SiteEnable(string site, Protocol protocol)”,e);
throw new ApplicationException(”SiteEnable(string site, Protocol protocol)”, e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// disables a site from recieving requests according to
/// it’s currently bound VIP
///

/// the name of the site to be put out of service /// the protocol to disable public void SiteDisable(string site, Protocol protocol)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteDisable(string site, Protocol protocol):”+ site +” : “+ protocol.ToString());
try
{
// connect with the server
Connect();

// Change real server reference
SendLine(Commands.ServerReal.Replace(”#REALSERVERNAME#”,site));
WiatForPrompt();
switch(protocol)
{
case Protocol.Http:
// Enable Http
SendLine(Commands.HttpDisable);
WiatForPrompt();
break;
case Protocol.Ssl:
// Enable Ssl
SendLine(Commands.SslDisable);
WiatForPrompt();
break;
case Protocol.Smtp:
// Enable Smtp
SendLine(Commands.SmtpDisable);
WiatForPrompt();
break;
}

// Get back global reference
SendLine(”exit”);
WiatForPrompt();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”SiteDisable(string site, Protocol protocol)”,e);
throw new ApplicationException(”SiteDisable(string site, Protocol protocol)”, e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// enable http and ssl for
///

/// a SiteDictionary of sites public void SiteEnable(SiteDictionary sites)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteEnable(SiteDictionary sites)”);
try
{
ArrayList sitesToProcess = new ArrayList();
ICollection keys = sites.Keys;
foreach(int key in keys)
{
Site siteCurrent = (Site)sites[key];
sitesToProcess.Add( siteCurrent.Name );
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(siteCurrent.Name);
}
SiteEnable((string[])sitesToProcess.ToArray(typeof(string)));
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”LoadBalancer.SiteEnable(SiteDictionary sites)”,e);
throw new ApplicationException(”LoadBalancer.SiteEnable(SiteDictionary sites)”, e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///
/// disable http and ssl for
///

/// a SiteDictionary of sites public void SiteDisable(SiteDictionary sites)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteDisable(SiteDictionary sites)”);
ArrayList sitesToProcess = new ArrayList();
ICollection keys = sites.Keys;
foreach(int key in keys)
{
Site siteCurrent = (Site)sites[key];
sitesToProcess.Add( siteCurrent.Name );
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(siteCurrent.Name);
}
SiteDisable((string[])sitesToProcess.ToArray(typeof(string)));
}
///
/// enables a collection of site to recieve requests
/// according to their currently bound VIPs.
///

///
/// note that this will enable both ssl and http.
/// To enable one or the other use the overridden
///
/// SiteEnable(string site[],Protocol protocol)
///
method
///

/// a string array of sites to be enabled public void SiteEnable(string[] sites)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteEnable(string[] sites)”);
try
{
for(int i = 0; i < sites.Length; i++)
{
// Change real server reference
SiteEnable(sites[i]);
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(sites[i]);
}
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error("LoadBalancer.SiteEnable(string[] sites)",e);
throw new ApplicationException("LoadBalancer.SiteEnable(string[] sites)", e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///
/// Disables a collection of sites from recieving
/// requests according to their currently bound VIPs
///

///
/// note that this will disable both ssl and http bindings.
/// To disable one or the other use the overridden
///
/// SiteDisable(string site[],Protocol protocol)
///
method
///

/// an array of strings of the site names to disable public void SiteDisable(string[] sites)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteDisable(string[] sites)”);
try
{
for(int i = 0; i < sites.Length; i++)
{
SiteDisable(sites[i]);
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(sites[i]);
}
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error("LoadBalancer.SiteDisable(string[] sites, Protocol protocol)",e);
throw new ApplicationException("LoadBalancer.SiteDisable(string[] sites)", e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///
/// enables a collection of sites to recieve requests according to
/// it’s currently bound VIP
///

/// a string array of the the names of the
/// sites to be put in service /// the protocol to enable public void SiteEnable(string[] sites, Protocol protocol)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteEnable(string[] sites, Protocol protocol)”);
try
{
for(int i = 0; i < sites.Length; i++)
{
SiteEnable(sites[i],protocol);
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info( sites[i] +" "+ protocol.ToString() );
}
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error("LoadBalancer.SiteEnable(string[] sites, Protocol protocol)",e);
throw new ApplicationException("LoadBalancer.SiteEnable(string[] sites, Protocol protocol",e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///
/// disables a collection of sites from recieving requests according to
/// their currently bound VIP
///

/// string array of the the names of the sites to be put out of service /// the protocol to disable /// Login Timeout
public void SiteDisable(string[] sites, Protocol protocol)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SiteDisable(string[] sites, Protocol protocol)”);
try
{
for(int i = 0; i < sites.Length; i++)
{
SiteDisable(sites[i],protocol);
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info( sites[i] +" "+ protocol.ToString() );
}
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error("LoadBalancer.SiteDisable(string[] sites, Protocol protocol)",e);
throw new ApplicationException("LoadBalancer.SiteDisable(string[] sites, Protocol protocol)",e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///
/// send the show bind command
///

/// bindings raw text
public string GetBindings()
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.GetBindings()”);
try
{
// connect with the server
Connect();

//CLEAR text buffer so we can only store ShowBind data
loadBalancerText.Remove(0,loadBalancerText.Length);
WiatForPrompt();
// ShowBind
SendLine(Commands.ShowBind);
WiatForPrompt();
//set binding text property
bindText.Remove(0,bindText.Length);
bindText.Append(loadBalancerText.ToString());
return loadBalancerText.ToString();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”GetStatus()”,e);
throw new ApplicationException(”LoadBalancer.GetBindings()”,e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// send the show server real command
///

/// show server real command result raw text
public string GetStatus()
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.GetStatus()”);
try
{
// connect with the server
Connect();

//CLEAR text buffer so we can only store Show data
loadBalancerText.Remove(0,loadBalancerText.Length);
// Show
SendLine(Commands.Show);
WiatForPrompt();
//set real text property
realText.Remove(0,realText.Length);
realText.Append(loadBalancerText.ToString());
return loadBalancerText.ToString();
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”GetStatus()”,e);
throw new ApplicationException(”LoadBalancer.GetStatus()”,e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// send the show bind and the show server real commands to the server iron
///

public void SetStatusAndBindings()
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SetStatusAndBindings()”);
try
{

// connect with the server
Connect();

//CLEAR text buffer so we can only store Show and ShowBind data
loadBalancerText.Remove(0,loadBalancerText.Length);
//WiatForPrompt();
// Show
SendLine(Commands.Show);
WiatForPrompt();
//set real text property
realText.Remove(0,realText.Length);
realText.Append(loadBalancerText.ToString());
loadBalancerText.Remove(0,loadBalancerText.Length);
// ShowBind
SendLine(Commands.ShowBind);
WiatForPrompt();
//set binding text property
bindText.Remove(0,bindText.Length);
bindText.Append(loadBalancerText.ToString());
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”SetStatusAndBindings()”,e);
throw new ApplicationException(”LoadBalancer.SetStatusAndBindings”,e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// send the sendString param to the server iron
///

/// string value to send to loadd balancer private void SendLine(string sendString)
{

//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.SendLine(string sendString)<<"+ this.IPAddress +">>”+ sendString);
byte[] dataToSend = Encoding.ASCII.GetBytes(sendString + “\r\n”);
writeStream.Write(dataToSend,0,dataToSend.Length);
}
///


/// wiat for the # character to come back from the Server Iron
///

private void WiatForPrompt()
{

//* * * * * * * * * * log info * * * * * * * * * *
//if(log.IsInfoEnabled)log.Info(”LoadBalancer.WiatForPrompt():<<"+ this.IPAddress +">>” );
StringBuilder logString = new StringBuilder();
int currentCharacter = readStream.Read();
logString.Append((char)currentCharacter);
loadBalancerText.Append((char)currentCharacter);
// setup vairiables for Wiat For Prompt timeout
wiatForPromptTimeOut = Convert.ToInt32(ConfigurationSettings.AppSettings["WiatForPromptTimeoutSeconds"]);
wiatForPromptTime = System.DateTime.Now;
while(currentCharacter != 35)
{
currentCharacter = readStream.Read();
logString.Append((char)currentCharacter);
loadBalancerText.Append((char)currentCharacter);
//timeouts
startTicks = (long)((DateTime)(wiatForPromptTime.AddSeconds(wiatForPromptTimeOut))).Ticks;
nowTicks = System.DateTime.Now.Ticks;
if(startTicks < nowTicks)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsFatalEnabled)log.Fatal("WiatForPrompt timeout failure current return value: "+ logString.ToString());
throw new ApplicationException("WiatForPromptt timeout (timespan)");
}
}
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info("LoadBalancer.WiatForPrompt()<<"+ this.IPAddress +">>”+ logString.ToString() );
}
///


/// Connect to load balancer
///

private void Connect()
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.Connect()”+ connectionState.ToString());

try
{
Connect(true,true);
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”LoadBalancer.Connect()”,e);
throw new ApplicationException(”LoadBalancer.Connect()”,e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
///


/// Connect to load balancer
///

/// send config mode command automatically /// send no page mode command automatically private void Connect(bool configMode, bool noPage)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsInfoEnabled)log.Info(”LoadBalancer.Connect(bool configMode, bool noPage):”+ configMode.ToString() +” : “+ noPage.ToString());
try
{
if(connectionState == ConnectionState.Closed)
{
connectionState = ConnectionState.Connecting;
// connect with the server
telnetServer = new TcpClient(loadBalancerIP,23);
writeStream = telnetServer.GetStream();
readStream = new StreamReader(telnetServer.GetStream());
StringBuilder logonString = new StringBuilder();
int currentLogonCharacter = readStream.Read();
logonString.Append((char)currentLogonCharacter);
// setup vairiables for login timeout
timeout = Convert.ToInt32(ConfigurationSettings.AppSettings["LogInTimeoutSeconds"]);
loginStartTime = System.DateTime.Now;
while(logonString.ToString().IndexOf(”Username: “)<0)
{
currentLogonCharacter = readStream.Read();
logonString.Append((char)currentLogonCharacter);
//timeouts
startTicks = (long)((DateTime)(loginStartTime.AddSeconds(timeout))).Ticks;
nowTicks = System.DateTime.Now.Ticks;
if(startTicks < nowTicks)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsFatalEnabled)log.Fatal(”Username prompt failure current return value: “+ logonString.ToString());
throw new ApplicationException(”Username prompt timeout (timespan)”);
}
if(currentLogonCharacter == -1)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsFatalEnabled)log.Fatal(”Login failure current return value: “+ logonString.ToString());
throw new ApplicationException(”Log on timeout”);
}
}
// sending username to the server
SendLine(loadBalancerUserName);
currentLogonCharacter = readStream.Read();
logonString.Append((char)currentLogonCharacter);
loginStartTime = System.DateTime.Now;
while((logonString.ToString().IndexOf(”Enter PASSCODE: “)<0) && (logonString.ToString().IndexOf(”Password:”)<0))
{
currentLogonCharacter = readStream.Read();
logonString.Append((char)currentLogonCharacter);
//timeouts
startTicks = (long)((DateTime)(loginStartTime.AddSeconds(timeout))).Ticks;
nowTicks = System.DateTime.Now.Ticks;
if(startTicks < nowTicks)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsFatalEnabled)log.Fatal(”Password prompt failure current return value: “+ logonString.ToString());
throw new ApplicationException(”Password prompt timeout (timespan)”);
}
}
// sending password to the server
SendLine(loadBalancerPassword);
loginStartTime = System.DateTime.Now;
while(logonString.ToString().IndexOf(”User login successful.”)<0)
{
currentLogonCharacter = readStream.Read();
logonString.Append((char)currentLogonCharacter);
//timeouts
startTicks = (long)((DateTime)(loginStartTime.AddSeconds(timeout))).Ticks;
nowTicks = System.DateTime.Now.Ticks;
if(startTicks < nowTicks)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsFatalEnabled)log.Fatal(”Login failure current return value: “+ logonString.ToString());
throw new ApplicationException(”Login Timeout (timespan)”);
}
if(currentLogonCharacter == -1)
{
Thread.Sleep(1000);
//* * * * * * * * * * log info * * * * * * * * *
if(log.IsWarnEnabled)log.Warn(”Connect() internal - Thread.Sleep(1000) “);
}
}
WiatForPrompt();
if(noPage)
{
// no page
SendLine(Commands.NoPage);
WiatForPrompt();
doPage = false;
}
if(configMode)
{
// enter config mode
SendLine(Commands.Config);
WiatForPrompt();
}

connectionState = ConnectionState.Open;
}
}
catch(Exception e)
{
//* * * * * * * * * * log info * * * * * * * * * *
if(log.IsErrorEnabled)log.Error(”LoadBalancer.Connect()”,e);
throw new ApplicationException(”LoadBalancer.Connect()”,e);
}
finally
{
if(telnetServer != null)
{
telnetServer.Close();
telnetServer = null;
}
}
}
}
}