* Class: AdRotator\r
* \r
* Author: Gaurav Vaish\r
+ * Maintainer: gvaish@iitk.ac.in\r
+ * Implementation: yes\r
* Contact: <gvaish@iitk.ac.in>\r
- * Status: 10??%\r
+ * Status: 100%\r
* \r
* (C) Gaurav Vaish (2001)\r
*/\r
\r
using System;\r
+using System.IO;\r
using System.Collections;\r
+using System.Collections.Specialized;\r
+using System.Web;\r
+using System.Web.Caching;\r
+using System.Web.UI;\r
+using System.Xml;\r
+using System.Web.Utils;\r
\r
namespace System.Web.UI.WebControls\r
{\r
{\r
\r
private string advertisementFile;\r
- private string keywordFilter;\r
- private string target;\r
+ private static readonly object AdCreatedEvent = new object();\r
\r
- public event AdCreatedEventHandler AdCreated;\r
+ // Will be set values during (On)PreRender-ing\r
+ private string alternateText;\r
+ private string imageUrl;\r
+ private string navigateUrl;\r
\r
- public AdRotator()\r
+ private string fileDirectory;\r
+\r
+ private class AdRecord\r
+ {\r
+ public IDictionary adProps;\r
+ public int hits; // or impressions or clicks\r
+ public string keyword;\r
+\r
+ public AdRecord(IDictionary adProps)\r
+ {\r
+ this.adProps = adProps;\r
+ hits = 0;\r
+ keyword = String.Empty;\r
+ }\r
+ }\r
+\r
+/*\r
+ * Loading / Saving data from/to ad file and all the manipulations wrt to the URL...\r
+ * are incorporated by the following functions.\r
+ * GetData(string)\r
+ * LoadAdFile(string)\r
+ * IsAdMatching(AdRecord)\r
+ * ResolveAdUrl(string)\r
+ * SelectAd()\r
+ * The exact control flow will be detailed. Let me first write the functions\r
+ */\r
+\r
+ private AdRecord[] LoadAdFile(string file)\r
+ {\r
+ Stream fStream;\r
+ ArrayList list;\r
+ XmlReader reader;\r
+ XmlDocument document;\r
+ XmlNode topNode, innerNode;\r
+ IDictionary hybridDict = null;\r
+ AdRecord[] adsArray = null;\r
+ try\r
+ {\r
+ fStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);\r
+ } catch(Exception e)\r
+ {\r
+ throw new HttpException("AdRotator: Unable to open file");\r
+ }\r
+ try\r
+ {\r
+ list = new ArrayList();\r
+ reader = new XmlTextReader(fStream);\r
+ document = new XmlDocument();\r
+ document.Load(reader);\r
+ if(document.DocumentElement!=null)\r
+ {\r
+ if(document.DocumentElement.LocalName=="Advertisements")\r
+ {\r
+ topNode = document.DocumentElement.FirstChild;\r
+ while(topNode!=null)\r
+ {\r
+ if(topNode.LocalName=="Ad")\r
+ {\r
+ innerNode = topNode.FirstChild;\r
+ while(innerNode!=null)\r
+ {\r
+ if(innerNode.NodeType==XmlNodeType.Element)\r
+ {\r
+ if(hybridDict==null)\r
+ {\r
+ hybridDict = new HybridDictionary();\r
+ }\r
+ hybridDict.Add(innerNode.LocalName, innerNode.InnerText);\r
+ }\r
+ innerNode = innerNode.NextSibling;\r
+ }\r
+ if(hybridDict!=null)\r
+ list.Add(hybridDict);\r
+ }\r
+ topNode = topNode.NextSibling;\r
+ }\r
+ }\r
+ }\r
+ if(list.Count>0)\r
+ {\r
+ adsArray = new AdRecord[list.Count];\r
+ for(int i=0; i < list.Count; i++)\r
+ {\r
+ adsArray[i] = new AdRecord((IDictionary)list[i]);\r
+ }\r
+ }\r
+ } catch(Exception e)\r
+ {\r
+ throw new HttpException("AdRotator_Parse_Error" + file);\r
+ } finally\r
+ {\r
+ fStream.Close();\r
+ }\r
+ if(adsArray == null)\r
+ {\r
+ throw new HttpException("AdRotator_No_Advertisements_Found");\r
+ }\r
+ return adsArray;\r
+ }\r
+ \r
+ private AdRecord[] GetData(string file)\r
+ {\r
+ string physPath = MapPathSecure(file);\r
+ string AdKey = "AdRotatorCache: " + physPath;\r
+ fileDirectory = UrlUtils.GetDirectory(UrlUtils.Combine(TemplateSourceDirectory, file));\r
+ Cache cache = HttpRuntime.Cache;\r
+ AdRecord[] records = (AdRecord[])cache[AdKey];\r
+ if(records==null)\r
+ {\r
+ records = LoadAdFile(physPath);\r
+ if(records==null)\r
+ {\r
+ return null;\r
+ }\r
+ cache.Insert(AdKey, records, new CacheDependency(physPath));\r
+ }\r
+ return records;\r
+ }\r
+ \r
+ private IDictionary SelectAd()\r
+ {\r
+ AdRecord[] records = GetData(AdvertisementFile);\r
+ if(records!=null && records.Length!=0)\r
+ {\r
+ int impressions = 0;\r
+ for(int i=0 ; i < records.Length; i++)\r
+ {\r
+ if(IsAdMatching(records[i]))\r
+ impressions += records[1].hits;\r
+ }\r
+ if(impressions!=0)\r
+ {\r
+ int rnd = (new Random()).Next(impressions) + 1;\r
+ int counter = 0;\r
+ int index = 0;\r
+ for(int i=0; i < records.Length; i++)\r
+ {\r
+ if(IsAdMatching(records[i]))\r
+ {\r
+ if(rnd <= (counter + records[i].hits))\r
+ {\r
+ index = i;\r
+ break;\r
+ }\r
+ counter += records[i].hits;\r
+ }\r
+ }\r
+ return records[index].adProps;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private bool IsAdMatching(AdRecord currAd)\r
+ {\r
+ if(KeywordFilter!=String.Empty)\r
+ {\r
+ if(currAd.keyword.ToLower() == KeywordFilter.ToLower())\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ private string ResolveAdUrl(string relativeUrl)\r
+ {\r
+ if(relativeUrl.Length==0 || !UrlUtils.IsRelativeUrl(relativeUrl))\r
+ return relativeUrl;\r
+ string fullUrl = String.Empty;\r
+ if(fileDirectory != null)\r
+ fullUrl = fileDirectory;\r
+ if(fullUrl.Length == 0)\r
+ fullUrl = TemplateSourceDirectory;\r
+ if(fullUrl.Length == 0)\r
+ return relativeUrl;\r
+ return (fullUrl + relativeUrl);\r
+ }\r
+ \r
+ public event AdCreatedEventHandler AdCreated\r
+ {\r
+ add\r
+ {\r
+ Events.AddHandler(AdCreatedEvent, value);\r
+ }\r
+ remove\r
+ {\r
+ Events.RemoveHandler(AdCreatedEvent, value);\r
+ }\r
+ }\r
+ \r
+ public AdRotator(): base()\r
{\r
advertisementFile = string.Empty;\r
- keywordFilter = string.Empty;\r
- target = string.Empty;\r
+ fileDirectory = null;\r
}\r
\r
public string AdvertisementFile\r
{\r
get\r
{\r
- return keywordFilter;\r
+ object o = ViewState["KeywordFilter"];\r
+ if(o!=null)\r
+ return (string)o;\r
+ return String.Empty;\r
}\r
set\r
{\r
- keywordFilter = value;\r
+ if(value!=null)\r
+ ViewState["KeywordFilter"] = value.Trim();\r
}\r
}\r
- \r
+\r
public string Target\r
{\r
get\r
{\r
- return target;\r
+ object o = ViewState["Target"];\r
+ if(o!=null)\r
+ return (string)o;\r
+ return String.Empty;\r
}\r
set\r
{\r
- target = value;\r
+ ViewState["Target"] = value;\r
+ }\r
+ }\r
+ \r
+ protected override ControlCollection CreateControlCollection()\r
+ {\r
+ return new EmptyControlCollection(this);\r
+ }\r
+ \r
+ protected virtual void OnAdCreated(AdCreatedEventArgs e)\r
+ {\r
+ if(Events!=null)\r
+ {\r
+ AdCreatedEventHandler aceh = (AdCreatedEventHandler)(Events[AdCreatedEvent]);\r
+ if(aceh!=null)\r
+ aceh(this, e);\r
+ }\r
+ }\r
+\r
+ protected override void OnPreRender(EventArgs e)\r
+ {\r
+ if(AdvertisementFile!=String.Empty)\r
+ {\r
+ AdCreatedEventArgs acea = new AdCreatedEventArgs(SelectAd());\r
+ imageUrl = acea.ImageUrl;\r
+ navigateUrl = acea.NavigateUrl;\r
+ alternateText = acea.AlternateText;\r
}\r
}\r
\r
protected override void Render(HtmlTextWriter writer)\r
{\r
HyperLink hLink = new HyperLink();\r
- Image image;\r
-\r
- AttributeCollection attributeColl = base.Attributes;\r
- ICollection keys = attributeColl.Keys;\r
- IEnumerator iterator = keys.GetEnumerator();\r
- \r
- \r
+ Image adImage = new Image();\r
+ foreach(IEnumerable current in Attributes.Keys)\r
+ {\r
+ hLink.Attributes[(string)current] = Attributes[(string)current];\r
+ }\r
+ if(ID != null && ID.Length > 0)\r
+ hLink.ID = ID;\r
+ hLink.Target = Target;\r
+ hLink.AccessKey = AccessKey;\r
+ hLink.Enabled = Enabled;\r
+ hLink.TabIndex = TabIndex;\r
+ hLink.RenderBeginTag(writer);\r
+ if(ControlStyleCreated)\r
+ {\r
+ adImage.ApplyStyle(ControlStyle);\r
+ }\r
+ if(imageUrl!=null && imageUrl.Length > 0)\r
+ adImage.ImageUrl = ResolveAdUrl(imageUrl);\r
+ adImage.AlternateText = alternateText;\r
+ adImage.ToolTip = ToolTip;\r
+ adImage.RenderControl(writer);\r
+ hLink.RenderEndTag(writer);\r
}\r
}\r
}\r