<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>PageBox for .NET customization</title>
<meta name="Description" content="How to deploy presentation with publish and subscribe using .NET">
<meta name="keywords" content=".NET, publish, subscribe, repository"><link rel="stylesheet" href="cuckoo.css" type="text/css"><script src="cuckoo.js"></script><script>
if (is_nav) document.write('<link rel="stylesheet" href="cuckoo-nav6.css" type="text/css">');
</script><body>
<div id="tooltip" style="position:absolute;visibility:hidden;border:1px solid black;font-size:small;layer-background-color:#ffffaa;color:black;background:#ffffaa;padding:1px">
</div><table width="100%"><tr><td width="90">
<img src="logo.gif" alt="PageBox: presentation deployment using .NET"></td>
<td align="left"><font class="title">PageBox</font></td>
<td><font class="seek">
<form method="get" action="http://siteLevel.whatUseek.com/query.go" target="_self">
<br>
<table width="100%">
<tr><td width="100%"><table cellspacing="0" cellpadding="2" border="0">
<tr><td valign="middle" align="right">
<input type="submit" value="Search" name="B1"></td>
<td align="center" valign="middle" nowrap="true"><font><select name="slice_title">
<option selected="true">This Site</option>
<option>The Web</option></select></font></td>
<td align="center" valign="middle" nowrap="true"><font size="1">for </font></td>
<td align="center" valign="middle" nowrap="true">
<input type="text" name="query" size="17" maxlength="100"></td></tr>
</table></td></tr></table>
<input type="hidden" name="crid" value="27265223696b23cd"></form></font></td>
<td align="right"><font class="seek"><a href="mailto:support@pagebox.net"> <img src="mail.gif" alt="support@pagebox.net" border="0"></a> <a href="../home.html" title="PageBox: presentation deployment"> <img src="home.gif" alt="PageBox: presentation deploy on J2EE, PHP, .NET" BORDER="0"></a> <a href="dotnet-custom-doc.zip" style="text-decoration:none;background:white;color:white" title="C# PageBox for .NET"> <img src="word.gif" alt="Word version of this document" border="0"></a> <a href="dotnet-customForPrinters.html" style="text-decoration:none;background:white;color:white" title="C# PageBox for .NET"> <img src="Print.gif" alt="Printer-friendly version of this document" border="0"></a> <a href="http://pagebox.net/cuckoo/cuckoo-pres.html" style="text-decoration:none;background:white;color:white" title="Cuckoo Word VBA authoring"> <img src="cuckoo4.gif" alt="Cuckoo generated" border="0"></a>
</font></td></tr>
</table>
<table class="stripe"><tr>
<td class="stripe-item" align="center" width="16%">
<a href="http://pagebox.sourceforge.net/rationale.html" class="stripe-item" title="PageBox rationale">
             Rationale</a></td>
<td class="stripe-item" align="center" width="16%">
<a href="../faq.htm" class="stripe-item" title="PageBox FAQ">FAQ</a></td>
<td class="stripe-item" align="center" width="16%">
<a href="http://pagebox.sourceforge.net/index.html" class="stripe-item" title="Sourceforge site">
             Dev site</a></td>
<td class="stripe-item" align="center" width="16%">
<a href="dotnet-index.html" class="stripe-item" title="PageBox for .NET presentation">
             .NET version</a></td>
<td class="stripe-item" align="center" width="16%">
<a href="dotnet-install.html" class="stripe-item" title="PageBox for .NET installation">Install</a></td>
<td class="stripe-item" align="center" width="16%">
<a href="dotnet-custom.html" class="stripe-item" title="PageBox for .NET customization">Customization</a></td>
</tr></table><table width="100%"><tr><td valign="top">
<p>
</p>
<p style="font-size:large;font-family:Verdana;color:#336699;">PageBox for .NET customization</p><p>
</p><a name="toc0"><h2><font class="Heading-2">Deliveries</font></h2></a><p>You can download PageBox and its repository for .NET in Zip format:</p>
<ul><li><p class="FormGet"><a href="pagebox.zip">pagebox.zip</a></p></li>
<li><p class="FormGet"><a href="repository.zip">repository.zip</a></p></li>
</ul>
<p class="FormGet"></p>
<p>The repository of PageBox for .NET is made of the following files:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Name</p></th><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Purpose</p></th></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/publisher.html">Repository/publisher.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Publisher page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/publisher.aspx.cs">Repository/publisher.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Server code of the publisher page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/subscriber.html">Repository/subscriber.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Subscriber page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/subscriber.aspx.cs">Repository/subscriber.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Server code of the subscriber page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Global.asax.cs">Repository/Global.asax.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Server code of global.asax</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/login-form.html">Repository/login-form.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Login form</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/login-form.aspx.cs">Repository/login-form.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Server code of login-form.aspx</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Subscriber.cs">Repository/Subscriber.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Class describing a subscribed PageBox</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/RepoSubs.cs">Repository/RepoSubs.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Class describing the subscribed PageBoxes of a Repository</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/RepoArchs.cs">Repository/RepoArchs.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Class describing the publications of a Repository</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Deployer.cs">Repository/Deployer.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Class responsible of the presentation deployment</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Deploy.cs">Repository/Deploy.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Web service proxy</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/pagebox.css">Repository/pagebox.css</a></p></td><td class="cuckoo-td" valign="top"><p>CSS used to display repository pages</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/logo.gif">Repository/logo.gif</a></p></td><td class="cuckoo-td" valign="top"><p>PageBox logo</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/mail.gif">Repository/mail.gif</a></p></td><td class="cuckoo-td" valign="top"><p>PageBox mail icon</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Web.config">Repository/Web.config</a></p></td><td class="cuckoo-td" valign="top"><p>Example of configuration file</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/authorization.txt">Repository/authorization.xml</a></p></td><td class="cuckoo-td" valign="top"><p>Example of authorization file (users allowed to publish archives)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/asubscriber.html">Repository/asubscriber.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Archive subscriber page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/asubscriber.aspx.cs">Repository/asubscriber.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of archive subscriber page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/aselect.html">Repository/aselect.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Page of archive selection (for archive subscriber)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/aselect.aspx.cs">Repository/aselect.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of archive selection page (for archive subscriber)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/download.html">Repository/download.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Download page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/download.aspx.cs">Repository/download.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of download page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/audit.html">Repository/audit.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Log display page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/audit.aspx.cs">Repository/audit.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of log display page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/Log.cs">Repository/Log.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Log writer</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/WebServices/Retry.asmx.cs">Repository/WebServices/Retry.asmx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of Retry.asmx Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="Repository/WebServices/RepoQuery.asmx.cs">Repository/WebServices/RepoQuery.asmx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of Query.asmx Web service of the Repository</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepositoryMG/MultiGrid.cs">RepositoryMG/MultiGrid.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Datagrid for aselect (multiselection)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepoCleanup/Cleanup.cs">RepoCleanup/Cleanup.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Main class of Cleanup Windows service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepoCleanup/CleanupThread.cs">RepoCleanup/CleanupThread.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Worker thread invoking the Retry Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepoCleanup/Retry.cs">RepoCleanup/Retry.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Web service proxy</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepoCleanup/ProjectInstaller.cs">RepoCleanup/ProjectInstaller.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Generated by Visual Studio for the installation of the Windows service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="RepoCleanup/cleanup.txt">RepoCleanup/cleanup.xml</a></p></td><td class="cuckoo-td" valign="top"><p>Example of configuration file for retries</p></td></tr></table>
<p></p>
<p>The Repository archive also includes a TestRepoCleanup directory that you can use</p>
<ol><li><p>To modify the Windows service (even with .NET it is still not easy to test the former NT services)</p></li>
<li><p>To set the service cleanup.xml path and logging mode</p></li>
</ol>
<p></p>
<p>TestRepoCleanup contains the following files:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Name</p></th><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Purpose</p></th></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="TestRepoCleanup/TestCleanup.cs">TestCleanup.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Window form application</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="TestRepoCleanup/CleanupThread.cs">CleanupThread.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Worker thread invoking the Retry Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="TestRepoCleanup/Retry.cs">Retry.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Web service proxy</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="TestRepoCleanup/cleanup.txt">cleanup.xml</a></p></td><td class="cuckoo-td" valign="top"><p>Example of configuration file for retries</p></td></tr></table>
<p></p>
<p>PageBox for .NET is made of the following files:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Name</p></th><th class="cuckoo-td" valign="top" align="left"><p class="TableHeader">Purpose</p></th></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Update.html">update.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>PageBox page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Update.aspx.cs">update.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of PageBox page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Deploy.asmx.cs">Deploy.asmx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of Deploy.asmx Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Query.asmx.cs">Query.asmx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of Query.asmx Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/RepoQuery.cs">RepoQuery.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Proxy of the RepoQuery Web service</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Global.asax.cs">Global.asax.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Server code of Global.asax</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p>unzip.exe</p></td><td class="cuckoo-td" valign="top"><p>From Infozip. Example of archive installation</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/inflate.bat">inflate.bat</a></p></td><td class="cuckoo-td" valign="top"><p>Example of archive installation script (DOS)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/inflate.js">inflate.js</a></p></td><td class="cuckoo-td" valign="top"><p>Example of JavaScript installation and de-installation script (WSH)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/remove.bat">remove.bat</a></p></td><td class="cuckoo-td" valign="top"><p>Example of archive de-installation script (DOS)</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/pagebox.css">pagebox.css</a></p></td><td class="cuckoo-td" valign="top"><p>CSS used to display repository pages</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/logo.gif">logo.gif</a></p></td><td class="cuckoo-td" valign="top"><p>PageBox logo</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/mail.gif">mail.gif</a></p></td><td class="cuckoo-td" valign="top"><p>PageBox mail icon</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/PbCmd.txt">PbCmd.xml</a></p></td><td class="cuckoo-td" valign="top"><p>Example of configuration for archive installation/de-installation</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/audit.html">audit.aspx</a></p></td><td class="cuckoo-td" valign="top"><p>Log display page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/audit.aspx.cs">audit.aspx.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Code of log display page</p></td></tr><tr name="tr0"><td class="cuckoo-td" valign="top"><p><a href="PageBox/Log.cs">Log.cs</a></p></td><td class="cuckoo-td" valign="top"><p>Log writer</p></td></tr></table><a name="toc1"><h2><font class="Heading-2">Repository</font></h2></a><a name="toc2"><h3><font class="Heading-3">Subscriber.cs</font></h3></a><p>The Subscriber class contains archs, an associative array of the presentations deployed or pending for deployment.</p>
<p></p>
<p>Subscriber has three methods:</p>
<ul><li><p>A constructor without parameter to create a new Subscriber</p></li>
<li><p>A constructor with an XmlReader to restore a Subscriber from subscribers.xml</p></li>
<li><p>WriteXml to serialize a Subscriber in subscribers.xml</p></li>
</ul><a name="toc3"><h3><font class="Heading-3">RepoSubs.cs</font></h3></a><p>The RepoSubs class contains subscribers, an associative array of the subscribing PageBoxes and asubscribers, an associative array of the archive subscribers.</p>
<p></p>
<p>RepoSubs has eleven methods:</p>
<ul><li><p>A constructor with an XmlReader to restore a RepoSubs from subscribers.xml. To restore subscribers and asubscribers, it calls restoreSubs</p></li>
<li><p>restoreSubs restores a associative table from subscribers.xml</p></li>
<li><p>WriteXml serializes a RepoSubs in subscribers.xml</p></li>
<li><p>subscribe adds a subscriber to the repository</p></li>
<li><p>unsubscribe removes a subscriber from the repository</p></li>
<li><p>asubscribe adds an archive subscriber to the repository</p></li>
<li><p>unasubscribe removes a archive subscriber from the repository</p></li>
<li><p>add adds a presentation to an archive subscriber</p></li>
<li><p>delete removes a presentation from an archive subscriber</p></li>
<li><p>cleanup invokes cleanup2 for subscribers and archive subscribers. cleanup is invoked by the Retry Web Service</p></li>
<li><p>cleanup2 tries to remove pending state. If an archive is in "pending deploy" cleanup2 deploys the archive again. If an archive is in "pending undeploy" cleanup2 undeploys the archive again. If cleanup2 succeeded to undeploy all archives deployed on a subscribing PageBox and if this PageBox is in "pending unsubscribe" state cleanup2 removes the PageBox from the subscriber list.</p></li>
</ul>
<p></p>
<p>When a new PageBox is subscribed, it receives all presentations defined in RepoArchs.</p>
<p>RepoSubs manages subscribers.xml. Here is an example:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><?xml version="1.0"?></p><p><RepoSubs></p><p>  <subscribers></p><p>    <entry></p><p>      <url>127.0.0.1/PageBox/PageBox/Deploy.asmx</url></p><p>      <Subscriber></p><p>        <arch></p><p>          <name>art030_UploadFile.zip</name></p><p>          <status>art030_UploadFile.zip installed</status></p><p>        </arch></p><p>        <arch></p><p>          <name>MasterDetailDPLCHK.zip</name></p><p>          <status>MasterDetailDPLCHK.zip installed</status></p><p>        </arch></p><p>        <state>active</state></p><p>      </Subscriber></p><p>    </entry></p><p>    <entry></p><p>      <url>127.0.0.1/PageBox/PageBox2/Deploy.asmx</url></p><p>      <Subscriber></p><p>        <arch></p><p>          <name>art030_UploadFile.zip</name></p><p>          <status>art030_UploadFile.zip installed</status></p><p>        </arch></p><p>        <arch></p><p>          <name>MasterDetailDPLCHK.zip</name></p><p>          <status>MasterDetailDPLCHK.zip installed</status></p><p>        </arch></p><p>        <state>active</state></p><p>      </Subscriber></p><p>    </entry></p><p>  </subscribers></p><p>  <asubscribers /></p><p></RepoSubs></p></td></tr></table><a name="toc4"><h3><font class="Heading-3">RepoArch.cs</font></h3></a><p>The RepoArchs class contains four associative arrays:</p>
<ul><li><p>archives contains the archive names and owners</p></li>
<li><p>docs contains the archive names and documentation URLs</p></li>
<li><p>administrators contains the administrator user ids</p></li>
<li><p>publishers contains the publisher user ids</p></li>
</ul>
<p></p>
<p>RepoArch has nine methods:</p>
<ul><li><p>A constructor with an XmlReader to restore archives and docs from archives.xml. To restore subscribers and asubscribers, it calls restoreHash2</p></li>
<li><p>restoreAuth restores administrators and publishers from authorization.xml. It calls restoreHash to restore administrators and publishers</p></li>
<li><p>restoreHash restores a user array (administrators or publishers) from authorization.xml</p></li>
<li><p>restoreHash2 restores an associative table from archives.xml</p></li>
<li><p>WriteXml serializes associative tables in archives.xml</p></li>
<li><p>add adds an archive to the repository</p></li>
<li><p>delete removes an archive from the repository</p></li>
<li><p>isAdministrator returns true if a user is an administrator</p></li>
<li><p>isPublisher returns true if a user is a publisher</p></li>
</ul>
<p></p>
<p>When a new presentation is added, it is deployed on every subscriber and added to the Subscriber objects. Presentations are not automatically added to archive subscribers but when an archive subscriber has subscribed a presentation, it receives presentation updates.</p>
<p></p>
<p>RepoArchs manages archives.xml. Here is an example:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><?xml version="1.0"?></p><p><RepoArchs></p><p>  <archives></p><p>    <entry></p><p>      <arch>art030_UploadFile.zip</arch></p><p>      <val>admin</val></p><p>    </entry></p><p>    <entry></p><p>      <arch>MasterDetailDPLCHK.zip</arch></p><p>      <val /></p><p>    </entry></p><p>  </archives></p><p>  <docs></p><p>    <entry></p><p>      <arch>art030_UploadFile.zip</arch></p><p>      <val>http://localhost/home2/php/php-index.html</val></p><p>    </entry></p><p>    <entry></p><p>      <arch>MasterDetailDPLCHK.zip</arch></p><p>      <val>http://localhost/home2/php/php-index.html</val></p><p>    </entry></p><p>  </docs></p><p></RepoArchs></p></td></tr></table><a name="toc5"><h3><font class="Heading-3">Deployer.cs</font></h3></a><p>The Deployer class has two static methods:</p>
<ul><li><p>deploy deploys a presentation on a PageBox using the add method of the Deploy Web Service</p></li>
<li><p>undeploy undeploys a presentation on a PageBox using the delete method of the Deploy Web Service</p></li>
</ul>
<p></p>
<p>RepoArchs and RepoSubs extend Deployer and invoke its methods.</p><a name="toc6"><h3><font class="Heading-3">Deploy.cs</font></h3></a><p>Deploy.cs is a SOAP proxy. It has been generated from the Deploy Web service of PageBox using wsdl.exe. The constructor has been modified to set the Web service URL, which has to be the subscriber URL.</p><a name="toc7"><h3><font class="Heading-3">Global.asax.cs</font></h3></a><p>Global class contains two static members, subRep, a RepoSubs singleton and archRep, a RepoArchs singleton. Global restores archRep and subRep at the first request performed on the Repository application in Application_BeginRequest.</p>
<p></p>
<p>Application_BeginRequest calls restore to restore subRep and archRep.</p>
<p>restore uses RepoArchs and RepoSubs's constructors with an XmlReader to restore subRep and archRep from subscribers.xml and archives.xml.</p>
<p></p>
<p>Global class contains two methods, saveSubRep to save subRep on subscribers.xml and saveArchRep to save archRep on archives.xml. These methods call the WriteXml methods of RepoSubs and RepoArchs.</p><a name="toc8"><h3><font class="Heading-3">subcriber.aspx.cs</font></h3></a><p>The SubscriberWF class manages a form that</p>
<ul><li><p>Lists the Repository subscribers using a DataGrid</p></li>
<li><p>Allows adding and removing subscribers</p></li>
</ul>
<p></p>
<p>The bind method binds an ArrayList to the Datagrid. This ArrayList contains SubscriberEntry objects.</p>
<p>bind populates the ArrayList from RepoSubs.subscribers.</p>
<p>bind is called by Page_Load, subscriberDB_unsubscribe, Form1_subscribe, Form1_unsubscribe, Form1_force, Form1_refresh.</p>
<p></p>
<p>subscriber.aspx provides two buttons to remove subscribers Unsubscribe and Force and a button to refresh the Datagrid, refresh. When the user clicks one of these buttons, Form1_subscribe, Form1_unsubscribe, Form1_force or Form1_refresh is invoked.</p>
<p>Form1_subscribe invokes RepoSubs.subscribe.</p>
<p>Form1_unsubscribe and Form1_force invoke RepoSubs.unsubscribe.</p>
<p></p>
<p>Force allows removing a PageBox that doesn't exist (anymore) whereas Unsubscribe keeps the subscriber in "pending unsubscribe" state. In that state the subscriber doesn't receive new archives.</p>
<p></p>
<p>The Datagrid rows have also two buttons, unsub and force.</p>
<p>In InitializeComponent we added subscriberDB_unsubscribe to the Datagrid's ItemCommand as DataGridCommandEventHandler. When the user clicks either on unsub or force buttons, subscriberDB_unsubscribe is called. subscriberDB_unsubscribe calls RepoSubs.unsubscribe.</p><a name="toc9"><h3><font class="Heading-3">publisher.aspx.cs</font></h3></a><p>The publisher class manages a form that</p>
<ul><li><p>Lists the uploaded presentations and batchs using a Datagrid.</p></li>
<li><p>Allows uploading and removing presentations and batchs.</p></li>
</ul>
<p></p>
<p>If you put authentication in place then only publishers and administrators can use that form and a publisher can only see the presentations and batchs that she or he has published.</p>
<p>A user is a publisher if its user id is defined in RepoArchs.publishers.</p>
<p>A user is an administrator if its user id is defined in RepoArchs.administrators.</p>
<p>RepoArchs restores publishers and administrators from authorization.xml. Here is an example of authorization.xml:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><authorization></p><p>  <administrators></p><p>    <user>admin</user></p><p>  </administrators></p><p>  <publishers></p><p>    <user>publisher1</user></p><p>    <user>publisher2</user></p><p>  </publishers>  </p><p></authorization></p></td></tr></table>
<p></p>
<p>authorization.xml handles role authorizations. Authentication is defined in web.config. By default we use Form based authentication with login-form.aspx:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>    <authentication mode="Forms"></p><p>          <forms loginUrl="login-form.aspx"></p><p>              <credentials passwordFormat="Clear"></p><p>                 <user name="admin" password="admin" /></p><p>                 <user name="subscriber1" password="subscriber" /></p><p>                 <user name="subscriber2" password="subscriber" /></p><p>                 <user name="publisher1" password="publisher" /></p><p>                 <user name="publisher2" password="publisher" /></p><p>              </credentials></p><p>          </forms></p><p>    </authentication></p><p>    <authorization></p><p>          <deny users="?" /></p><p>    </authorization></p></td></tr></table>
<p></p>
<p>It is very important to define the <authorization> element and to forbid unauthenticated access to the Repository application.</p>
<p></p>
<p>When authentication is in place:</p>
<ol><li><p>In case of publication, publisher registers the user id as the owner of the presentation</p></li>
<li><p>A user B cannot publish a presentation with the same name as a presentation previously published by a user A</p></li>
<li><p>update.aspx displays the owner of deployed archives</p></li>
</ol>
<p></p>
<p></p>
<p>The bind method binds an ArrayList to the Datagrid. This ArrayList contains PublisherEntry objects.</p>
<p>bind populates the ArrayList from RepoArchs.archives and RepoArchs.docs.</p>
<p>bind is called by Page_Load, archUpload, refresh, archiveDB_delete.</p>
<p></p>
<p>publisher.aspx provides a button to upload archives Upload and a button to refresh the Datagrid, Refresh. When the user clicks one of these buttons, archUpload or refresh is invoked.</p>
<p></p>
<p>archUpload processes POST method upload as defined in RFC 1867. The upload code is quite simple:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>string arch = archFile.PostedFile.FileName;</p><p>int pos = arch.LastIndexOf("\\");</p><p>arch = arch.Substring(pos + 1);</p><p>if (!Directory.Exists(Global.archRep.downloadPath))</p><p>	Directory.CreateDirectory(Global.archRep.downloadPath);</p><p>archFile.PostedFile.SaveAs(Global.archRep.downloadPath + arch);</p><p>LabStatus.Text = Global.archRep.add(arch, owner, docURL.Value);</p><p>bind();</p></td></tr></table>
<p></p>
<p>archUpload saves the uploaded file in downloadPath, which is Repository-Directory\..\download as defined in Global.asax.cs with a Repository  name which is the same as the uploaded file (arch). Then it calls RepoArchs.add to add the archive to RepoArchs.archives and trigger the deployment of the presentation/batch on subscribers.</p>
<p></p>
<p>Beside the presentation location, publisher.aspx allows specifying the URL of the presentation documentation. archUpload retrieves it in docURL.value. </p>
<p></p>
<p>The Datagrid rows have also two buttons, Delete and Force.</p>
<p>In InitializeComponent we added archiveDB_delete to the Datagrid's ItemCommand as DataGridCommandEventHandler. When the user clicks either on Delete or Force buttons, archiveDB_delete is called. archiveDB_delete calls RepoArchs.delete.</p>
<p></p>
<p>In both cases publisher send an undeploy(<font class="test-style2">presentation</font><font class="Normal">) to all subscribers and removes the presentation file from the repository. If the undeploy succeeds, the presentation is removed from the archive list of the subscriber.</font></p>
<p></p>
<p>If the undeploy fails for one subscriber:</p>
<ul><li><p>The presentation is removed from the archive list of the subscriber in case of Force</p></li>
<li><p>The presentation is kept in the archive list of the subscriber in case of Delete</p></li>
</ul><a name="toc10"><h3><font class="Heading-3">asubscriber.aspx.cs</font></h3></a><p>The asubscriber class is very similar to subscriber.aspx.cs. It manages a form that</p>
<ul><li><p>Lists the Archive subscribers of the Repository using a DataGrid</p></li>
<li><p>Allows adding and removing Archive subscribers</p></li>
</ul>
<p></p>
<p>The bind method binds an ArrayList to the Datagrid. This ArrayList contains SubscriberEntry objects.</p>
<p>bind populates the ArrayList from RepoSubs.subscribers.</p>
<p>bind is called by Page_Load, subscriberDB_handle, Form1_subscribe, Form1_unsubscribe, Form1_force, Form1_refresh.</p>
<p></p>
<p>asubscriber.aspx provides two buttons to remove subscribers Unsubscribe and Force and a button to refresh the Datagrid, refresh. When the user clicks one of these buttons, Form1_subscribe, Form1_unsubscribe, Form1_force or Form1_refresh is invoked.</p>
<p>Form1_subscribe invokes RepoSubs.asubscribe.</p>
<p>Form1_unsubscribe and Form1_force invoke RepoSubs.unasubscribe.</p>
<p></p>
<p>Force allows removing a PageBox that doesn't exist (anymore) whereas Unsubscribe keeps the subscriber in "pending unsubscribe" state. In that state the subscriber doesn't receive new archives.</p>
<p></p>
<p>The Datagrid rows have also two buttons, unsub and force.</p>
<p>In InitializeComponent we added subscriberDB_handle to the Datagrid's ItemCommand as DataGridCommandEventHandler. When the user clicks either on unsub or force buttons, subscriberDB_handle is called. subscriberDB_handle calls RepoSubs.unasubscribe.</p>
<p></p>
<p>The Datagrid rows also contain a link to the aselect page. This link is created in asubscriber.aspx by</p>
<p><asp:HyperLinkColumn HeaderText=" " ItemStyle-Width="7%" Text="Archives" DataNavigateUrlField="PageBox" DataNavigateUrlFormatString="aselect.aspx?subscriber={0}"/></p>
<p>When you click on such a link, aselect is invoked in GET mode with a subscriber parameter containing the URL of the PageBox Web service.</p><a name="toc11"><h3><font class="Heading-3">aselect.aspx.cs</font></h3></a><p>aselect.aspx.cs manages a form that:</p>
<ul><li><p>Lists the repository archives with a checkbox checked when the archive is deployed on this Archive subscriber</p></li>
<li><p>Allows adding or removing archives on the subscription</p></li>
</ul>
<p></p>
<p>The form operates by delta:</p>
<ul><li><p>If you check a checkbox the corresponding archive is deployed</p></li>
<li><p>If you uncheck a checkbox the corresponding archive is undeployed</p></li>
<li><p>You can make multiple changes before submitting the changes</p></li>
</ul>
<p></p>
<p>To support this feature we use a MultiGrid class that extends DataGrid.</p>
<p>MultiGrid is based on the <a href="http://msdn.microsoft.com/msdnmag/issues/02/01/cutting/cutting0201.asp">article</a><font class="Normal"> of Dino Esposito published in the MSDN issue of January 2002.</font></p>
<p>It includes two changes:</p>
<ol><li><p>The BindName method of SelectColumnTemplate sets the checkbox after the archive status (deployed/not deployed)</p></li>
<li><p>The SelectedItems property of MultiGrid returns an array of SelectedEntry objects. A SelectedEntry object contains the checkbox status and the row number</p></li>
</ol>
<p>
</p>
<p>The bind method binds an ArrayList to the MultiGrid. This ArrayList contains SelectorEntry objects.</p>
<p>bind populates the ArrayList from RepoArchs.archives and RepoArchs.docs.</p>
<p>bind is called by Page_Load and Form1_refresh.</p>
<p></p>
<p>Form1_refresh reads SelectedItems, enumerates the archives and adds or remove archives on the subscription list accordingly.</p><a name="toc12"><h3><font class="Heading-3">download.aspx.cs</font></h3></a><p>download.aspx allows downloading presentations from Repositories without subscription:</p>
<p>When the presentation is updated, it is not deployed on the download site.</p>
<p>The download site doesn't need a PageBox.</p>
<p></p>
<p>The download class manages a form that lists the uploaded presentations and batches using a Datagrid.</p>
<p>It implements one method, Page_Load that populates an ArrayList from RepoArchs.archives and RepoArchs.docs and binds it to the Datagrid. This ArrayList contains DownloadEntry objects.</p>
<p>A DownloadEntry contains both the presentation name (Archive) and download URL (ArchiveURL).</p>
<p></p>
<p>download.aspx provides a link to download presentations and batches, defined with:</p>
<p><asp:HyperLinkColumn Target="_self" DataNavigateUrlField="ArchiveURL" DataTextField="Archive" ItemStyle-Width="28%" HeaderText="Archive"/></p><a name="toc13"><h3><font class="Heading-3">Log.cs</font></h3></a><p>Log.cs provides a write static method. write writes on log.rep entries that contain:</p>
<ol><li><p>The time when write was invoked</p></li>
<li><p>The user and IP address that triggered the write invocation</p></li>
<li><p>The invoked method name, parameter and response</p></li>
</ol><a name="toc14"><h3><font class="Heading-3">audit.aspx.cs</font></h3></a><p>audit.aspx manages a form that displays log.rep and allows removing log.rep.</p>
<p>If you put authentication in place then only administrators can use that form.</p>
<p></p>
<p>The audit class implements two methods, clear and include.</p>
<p>Both methods first check that the user is an administrator.</p>
<p>clear removes the log.rep file.</p>
<p>include calls Response.WriteFile("log.rep")</p>
<p></p>
<p>clear is invoked through the Clear button.</p>
<p>include is invoked by <% include(); %>.</p><a name="toc15"><h3><font class="Heading-3">Retry.asmx</font></h3></a><p>If it is properly configured, RepoCleanup calls the Retry.asmx every 30 minutes to retry pending deploys and undeploys. With this mechanism PageBox for .NET can cope with transient conditions such as Pagebox server reboot.</p>
<p></p>
<p>Because Retry.asmx is implemented as a Web Service a single RepoCleanup can monitor a set of Repositories on different machines.</p>
<p></p>
<p>Retry.asmx invokes the cleanup method of RepoSubs.cs.</p>
<p></p>
<p>Form based authentication, which is the preferred authentication scheme for the Repository, is not suitable for Web services. Therefore Retry.asmx is installed on a WebServices subdirectory of the repository.</p>
<p>WebServices contains a specific web.config that disables form-based authentication:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><configuration>   </p><p>  <system.web></p><p>    <authorization></p><p>       <allow users="?" /></p><p>    </authorization></p><p>  </system.web></p><p></configuration></p></td></tr></table>
<p></p>
<p class="FormGet">Retry.asmx implements a custom authentication and authorization mechanism consistent with the rest of the Repository: only Repository administrators are allowed to issue cleanup requests. This mechanism is quite simple.</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>public string Cleanup(string user, string password) {</p><p>if (!FormsAuthentication.Authenticate(user, password) ||</p><p>!Global.archRep.isAdministrator(user))</p><p>return "Retry.Cleanup failed: invalid credentials";</p><p>Global.subRep.cleanup();</p><p>return "Retry.Cleanup performed";</p><p class="test-style">}</p></td></tr></table>
<p></p>
<ol><li><p>Retry.asmx has a single method, Cleanup whose parameters are the user name and password to check</p></li>
<li><p>Cleanup uses  FormsAuthentication.Authenticate to check if the user is defined and if its password is correct</p></li>
<li><p>Then Cleanup checks if the user is a Repository administrator</p></li>
<li><p>If the user credentials are OK, Cleanup calls the RepoSub's cleanup method</p></li>
</ol><a name="toc16"><h3><font class="Heading-3">RepoQuery.asmx</font></h3></a><p>RepoQuery has two methods:</p>
<ol><li><p>GetSubscribers, the single method of the RepoQuery Web service. GetSubscribers returns an array that contains the URL of all subscribers and archive subscribers to a presentation but the requesting subscriber. GetSubscriber is called by the Query Web service of PageBox. GetSubscribers invokes the populate method to retrieve subscribers or archive subscribers.</p></li>
<li><p>populate enumerates the subscribers or archive subscribers and select the subscribers to the presentation</p></li>
</ol><a name="toc17"><h2><font class="Heading-2">PageBox</font></h2></a><a name="toc18"><h3><font class="Heading-3">PbArch.cs</font></h3></a><p>The PbArch class describes presentations and batchs deployed on a PageBox.</p>
<p>PbArch contains three associative tables:</p>
<ul><li><p>archives. archives contains Archive objects and describes deployed archives</p></li>
<li><p>inflate. inflate contains InstallCommand objects and describes supported extensions and how to install a presentation with a given extension</p></li>
<li><p>remove. remove also contains InstallCommand objects and describes how to uninstall a presentation with a given extension</p></li>
</ul>
<p></p>
<p>The InstallCommand class has three fields:</p>
<ul><li><p>cmd</p></li>
<li><p>paramPrefix</p></li>
<li><p>useShell</p></li>
</ul>
<p></p>
<p>To process a command, PbArch uses a ProcessStartInfo object:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>ProcessStartInfo psi = new ProcessStartInfo();</p><p>psi.FileName = ic.cmd;</p><p>psi.UseShellExecute = ic.useShell;</p><p>psi.Arguments = ic.paramPrefix + Global.path + "\\" + a;</p><p>Process p = Process.Start(psi);</p></td></tr></table>
<p></p>
<p>A command has a mandatory parameter, which is the archive path.</p>
<p>The parameter string is built like this:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>Parameter-prefix + archive-directory + "\\" + archive-name</p></td></tr></table>
<p></p>
<p>You can put more than one parameter in Parameter-prefix but they must be followed by the archive full path.</p>
<p></p>
<p>restorePbCmd restores inflate and remove associative tables from pbCmd.xml. To restore inflate or remove, it invokes the restoreHash method.</p>
<p></p>
<p>Here is an example of pbCmd.xml file:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><commands></p><p>  <inflate></p><p>    <entry></p><p>      <extension>.zip</extension></p><p>      <command>inflate.js</command></p><p>      <param-prefix>/arch:</param-prefix></p><p>      <use-shell>true</use-shell></p><p>    </entry></p><p>    <entry></p><p>      <extension>.jar</extension></p><p>      <command>-</command></p><p>      <param-prefix>-</param-prefix></p><p>      <use-shell>true</use-shell></p><p>    </entry></p><p>  </inflate></p><p>  <remove></p><p>    <entry></p><p>      <extension>.zip</extension></p><p>      <command>inflate.js</command></p><p>      <param-prefix>/del /arch:</param-prefix></p><p>      <use-shell>true</use-shell></p><p>    </entry></p><p>    <entry></p><p>      <extension>.jar</extension></p><p>      <command>-</command></p><p>      <param-prefix>-</param-prefix></p><p>      <use-shell>true</use-shell></p><p>    </entry></p><p>  </remove></p><p></commands></p></td></tr></table>
<p></p>
<p>When the PageBox receives a deployment request for an archive xxxx.zip, it will call a WSH script</p>
<p>inflate.js /arch:archive-directory\\xxxx.zip</p>
<p>When the PageBox receives a undeployment request for an archive xxxx.zip, it will call a WSH script</p>
<p>inflate.js /del /arch;archive-directory\\xxxx.zip</p>
<p>When the PageBox receives a deployment request for an archive xxxx.jar, it won't call a script because "-" stands for "Just copy this archive".</p>
<p></p>
<p>Here is an example of command (inflate.js):</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p>var argsNamed = WScript.Arguments.Named;</p><p>if (argsNamed.Exists("arch")) {</p><p>    var arch = argsNamed.Item("arch");</p><p>    var pos = arch.lastIndexOf(".");</p><p>    var dir = arch.substring(0, pos);</p><p>    var sh = new ActiveXObject("WScript.Shell");</p><p>    if (argsNamed.Exists("del")) {</p><p>        var fso = new ActiveXObject("Scripting.FileSystemObject");</p><p>        fso.DeleteFolder(dir);</p><p>        // WScript.Echo("rmdir /S /Q " + dir);</p><p>    } else {</p><p>        sh.exec("unzip -o " + arch + " -d " + dir);</p><p>        // WScript.Echo("unzip -o " + arch + " -d " + dir);</p><p>    }</p><p>}</p></td></tr></table>
<p></p>
<p>The archives associative table contains Archive objects.</p>
<p>The Archive class maintains the download location, the owner, size, upload time, documentation URL and state of the archive. Archive has a constructor to create a new Archive object, a constructor to restore an Archive object from PbArchives.xml (with a XmlReader parameter) and a method WriteXml to serialize onto  PbArchives.xml.</p>
<p></p>
<p>The PbArchs constructor with a XMLReader parameter restores the archives associative table from PbArchive.xml whereas PbArchs' WriteXml serializes the archive associative table onto PbArchives.xml.</p>
<p>PbArchive.xml looks like this:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><?xml version="1.0"?></p><p><PbArchs></p><p>  <archives></p><p>    <entry></p><p>      <arch>MasterDetailDPLCHK.zip</arch></p><p>      <Archive></p><p>        <downloadURL>127.0.0.1/download/</downloadURL></p><p>        <owner>publisher1</owner></p><p>        <size>16207</size></p><p>        <date>2002-02-16T18:04:34.0047628+01:00</date></p><p>        <docURL>http://agrandem/home2/cuckoo/cuckoo-pres.html</docURL></p><p>      </Archive></p><p>    </entry></p><p>  </archives></p><p></PbArchs></p></td></tr></table>
<p></p>
<p>PbArchs has two other methods:</p>
<ul><li><p>add. add adds a presentation to the archives associative table, downloads and installs the presentation</p></li>
<li><p>delete. delete removes a presentation from the archives associative table, removes and uninstalls the presentation</p></li>
</ul><a name="toc19"><h3><font class="Heading-3">Global.asax.cs</font></h3></a><p>Global class contains a static member, pbArchives, a PbArchs singleton. Global restores pbArchives at the first request performed on the Repository application in Application_BeginRequest.</p>
<p></p>
<p>Application_BeginRequest calls restore to restore pbArchives.</p>
<p>restore uses PbArchs' constructor with an XmlReader to restore pbArchives from pbArchives.xml.</p>
<p></p>
<p>Global class contains a savePbArchives method to save pbArchives on pbArchives.xml. This method call the WriteXml method of PbArchs.</p><a name="toc20"><h3><font class="Heading-3">Deploy.asmx.cs</font></h3></a><p>Deploy.asmx is the deployment Web service.</p>
<p>Deploy.asmx.cs implements two Web methods, add that invokes the add method of the PbArchs singleton and delete that invokes the delete method of the PbArchs singleton.</p><a name="toc21"><h3><font class="Heading-3">update.aspx.cs</font></h3></a><p>The update class manages a form that lists the deployed presentations</p>
<p></p>
<p>The Page_Load method binds an ArrayList to the Datagrid. This ArrayList contains UpdateEntry objects.</p>
<p>Page_Load populates the ArrayList from PbArchs.archives.</p><a name="toc22"><h3><font class="Heading-3">Log.cs</font></h3></a><p>Log.cs provides a write static method. write writes on log.html entries that contain:</p>
<ol><li><p>The time when write was invoked</p></li>
<li><p>The user and IP address that triggered the write invocation</p></li>
<li><p>The invoked method name, parameter and response</p></li>
</ol><a name="toc23"><h3><font class="Heading-3">audit.aspx.cs</font></h3></a><p>audit.aspx manages a form that displays log.rep and allows removing log.html.</p>
<p></p>
<p>The audit class implements two methods, clear and include.</p>
<p>clear removes the log.html file.</p>
<p>include calls Response.WriteFile("log.html")</p>
<p></p>
<p>clear is invoked through the Clear button.</p>
<p>include is invoked by <% include(); %>.</p><a name="toc24"><h3><font class="Heading-3">Query.asmx</font></h3></a><p>Query.asmx has a single method of the Query Web service, GetSubscribers.</p>
<p>GetSubscribers retrieves the URL of the Repository RepoQuery Web service, invokes this RepoQuery Web service to get the URLs of all other subscribers and archive subscribers to the presentation and returns this list to the requestor - typically a presentation or application installed by the PageBox.</p><a name="toc25"><h2><font class="Heading-2">RepoCleanup</font></h2></a><p>RepoCleanup is a Windows service (what used to be called a NT service).</p>
<p>RepoCleanup manages a set of Repositories.</p>
<p>Every 30 minutes RepoCleanup calls the Retry.asmx of every Repository that it knows to retry pending deploys and undeploys. With this mechanism PageBox for .NET can cope with transient conditions such as Pagebox server reboot.</p><a name="toc26"><h3><font class="Heading-3">Cleanup.cs</font></h3></a><p>Cleanup.cs is the core class of the Windows service. It implements two methods:</p>
<ul><li><p>OnStart invoked when the Windows service is started</p></li>
<li><p>OnStop invoked when the Windows service is stopped</p></li>
</ul>
<p></p>
<p>OnStart first retrieves the full path of the configuration file (cleanup.xml) and the logging mode.</p>
<p>It first looks in the registry.</p>
<p>As a regular Windows service, Cleanup is defined in the HKEY_LOCAL_MACHINE hive in SYSTEM\CurrentControlSet\Services\Cleanup.</p>
<p>OnStart expects to find the configuration path in SYSTEM\CurrentControlSet\Services\Cleanup\Parameters\ConfigFile and the logging mode in SYSTEM\CurrentControlSet\Services\Cleanup\Parameters\LogDebug.</p>
<p></p>
<p>Then OnStart looks at the startup parameters. It expects to find the path and optionally the logging mode.</p>
<p>If the path is not set either in the registry or as a startup parameter, OnStart writes an error on the Application event log with RepoCleanup as source:</p>
<p><pre>Cleanup.OnStart service without startup parameter (cleanup.xml full path)</pre></p>
<p></p>
<p>If the startup parameters are set, OnStart creates or updates the corresponding registry entries.</p>
<p></p>
<p>Then OnStart creates a CleanupThread and a worker thread where the ThreadRun method of CleanupThread will run.</p>
<p></p>
<p>ThreadRun waits 30 minutes or for a pulse. Then it checks a toStop Boolean. It toStop is true, it terminates. OnStop just sets toStop and issues the pulse to gracefully terminate the worker thread.</p><a name="toc27"><h3><font class="Heading-3">CleanupThread.cs</font></h3></a><p>CleanupThread implements</p>
<ul><li><p>A constructor that restores the configuration from cleanup.xml</p></li>
<li><p>Two logging methods, error and log</p></li>
<li><p>ThreadRun</p></li>
</ul>
<p></p>
<p>Here is an example of cleanup.xml:</p>
<p></p>
<table class="cuckoo-table"><tr name="tr0"><td class="cuckoo-td" valign="top"><p><cleanup></p><p><repository></p><p><url>http://localhost/PageBox/Repository/WebServices/Retry.asmx</url></p><p><user>admin</user></p><p><password>admin</password></p><p></repository></p><p><repository></p><p><url>http://localhost/PageBox/Repository2/WebServices/Retry.asmx</url></p><p><user>admin</user></p><p><password>admin</password></p><p></repository></p><p></cleanup></p></td></tr></table>
<p></p>
<p>For each Repository, cleanup.xml contains</p>
<ol><li><p class="FormGet">The URL of its Retry Web Service</p></li>
<li><p class="FormGet">A user name and password of a valid administrator account on that Repository</p></li>
</ol>
<p></p>
<p>The CleanupThread restores cleanup.xml on an ArrayList of RepositoryEntry.</p>
<p>At each loop, ThreadRun enumerates the ArrayList and calls for each Repository the Cleanup method of the Retry proxy.</p>
<p></p>
<p>error writes an error entry on the Application Event log with a RepoCleanup source.</p>
<p>log writes an information entry on the Application Event log with a RepoCleanup source if the logging mode, toLog is true.</p><a name="toc28"><h3><font class="Heading-3">Retry.cs</font></h3></a><p>Retry.cs is a SOAP proxy. It has been generated from the Retry Web service of the Repository using wsdl.exe. The constructor has been modified to set the Web service URL, which has to be the Repository URL.</p><a name="toc29"><h3><font class="Heading-3">ProjectInstaller.cs</font></h3></a><p>ProjectInstaller.cs is a generated class responsible for the installation and de-installation of the Windows service.</p>
<p></p>
<p>In .NET beta 2, we must set the service user and password. Even in Release version, because RepoCleanup can invoke Retry on other machines, we should use a network-enabled account with write access to the registry.</p>
<p></p>
<p>To avoid hard coding the user and password, during installation and de-installation, ProjectInstaller prompts for the user name and password.</p><a name="toc30"><h2><font class="Heading-2">TestRepoCleanup</font></h2></a><p>TestRepoCleanup was designed to test RepoCleanup functions.</p>
<p>Therefore it includes the same classes as RepoCleanup:</p>
<ul><li><p>CleanupThread.cs</p></li>
<li><p>Retry.cs</p></li>
</ul>
<p></p>
<p>You can use it to test your modifications.</p>
<p>It is also user-friendlier than regedit and the Windows service startup parameters to set the registry entries.</p>
<p></p>
<p>TestRepoCleanup uses a Windows form, TestCleanup.</p><a name="toc31"><h3><font class="Heading-3">TestCleanup.cs</font></h3></a><p>The TestCleanup form contains two buttons, Start and Stop.</p>
<p>The TestCleanup class contains three methods:</p>
<ul><li><p>The constructor that retrieves the cleanup.xml path and the logging mode from the registry. It also sets a text box and a check box accordingly</p></li>
<li><p>OnStart called when you click on the Start button. It retrieves the content of the text box and the check box, updates the registry and creates a CleanupThread and a worker thread where the ThreadRun method of CleanupThread will run</p></li>
<li><p>OnStop called when you click on the Stop button. It sets toStop and issues a pulse to gracefully terminate the worker thread</p></li>
</ul>
<p></p>
<p></p>
<p></p>
<p></p><script> var tip=new Array;
</script><p align="center">
    Contact:<a HREF="mailto:support@pagebox.net">support@pagebox.net</a><br>2001 Alexis Grandemange. 
    <font class="timestamp">Last modified
    <script>
        document.write(document.lastModified);
    </script>.
    </font></p>
</td><td valign="top" align="right" width="250">
<table>
<tr><td>
<!-- #include file="GoogleInclude.aspx" -->
</td></tr>
<tr><td style="background-color:#99ff99"><p>Version 0.0.2</p>
<ul><li><p>Repository allows subscribing a subset of the Repository presentations (asubscribe.aspx and aselect.aspx)</p></li>
<li><p>Repository supports presentation download (download.aspx)</p></li>
<li><p>Repository and PageBox locking</p></li>
<li><p>Repository and PageBox audit</p></li>
</ul>
<p></p>
<p>Version 0.0.3</p>
<ul><li><p>Windows service (RepoCleanup) and Web Service (Retry.asmx) to retry Repository deploy and undeploy</p></li>
</ul>
<p></p>
<p>Version 0.0.4</p>
<ul><li><p>Support for Application to Application communication (Query.asmx and RepoQuery.asmx)</p></li>
<li><p>Bug fixes</p></li>
</ul>
<p></p></td></tr></table>
<p align="center"><table class="toc-table"><tr><th class="toc-title">Table of Content</th></tr><tr><td><a href="#toc0" class="toc-h2">Deliveries</a><br> <a href="#toc1" class="toc-h2">Repository</a><br> <a href="#toc2" class="toc-h3">Subscriber.cs</a><br> <a href="#toc3" class="toc-h3">RepoSubs.cs</a><br> <a href="#toc4" class="toc-h3">RepoArch.cs</a><br> <a href="#toc5" class="toc-h3">Deployer.cs</a><br> <a href="#toc6" class="toc-h3">Deploy.cs</a><br> <a href="#toc7" class="toc-h3">Global.asax.cs</a><br> <a href="#toc8" class="toc-h3">subcriber.aspx.cs</a><br> <a href="#toc9" class="toc-h3">publisher.aspx.cs</a><br> <a href="#toc10" class="toc-h3">asubscriber.aspx.cs</a><br> <a href="#toc11" class="toc-h3">aselect.aspx.cs</a><br> <a href="#toc12" class="toc-h3">download.aspx.cs</a><br> <a href="#toc13" class="toc-h3">Log.cs</a><br> <a href="#toc14" class="toc-h3">audit.aspx.cs</a><br> <a href="#toc15" class="toc-h3">Retry.asmx</a><br> <a href="#toc16" class="toc-h3">RepoQuery.asmx</a><br> <a href="#toc17" class="toc-h2">PageBox</a><br> <a href="#toc18" class="toc-h3">PbArch.cs</a><br> <a href="#toc19" class="toc-h3">Global.asax.cs</a><br> <a href="#toc20" class="toc-h3">Deploy.asmx.cs</a><br> <a href="#toc21" class="toc-h3">update.aspx.cs</a><br> <a href="#toc22" class="toc-h3">Log.cs</a><br> <a href="#toc23" class="toc-h3">audit.aspx.cs</a><br> <a href="#toc24" class="toc-h3">Query.asmx</a><br> <a href="#toc25" class="toc-h2">RepoCleanup</a><br> <a href="#toc26" class="toc-h3">Cleanup.cs</a><br> <a href="#toc27" class="toc-h3">CleanupThread.cs</a><br> <a href="#toc28" class="toc-h3">Retry.cs</a><br> <a href="#toc29" class="toc-h3">ProjectInstaller.cs</a><br> <a href="#toc30" class="toc-h2">TestRepoCleanup</a><br> <a href="#toc31" class="toc-h3">TestCleanup.cs</a><br>
</td></tr></table></p></td></tr></table>
</body></html>