++ Test/mainsoft/ChangeLog (working copy)
authorDean Brettle <deanb@mono-cvs.ximian.com>
Sun, 9 Mar 2008 22:55:22 +0000 (22:55 -0000)
committerDean Brettle <deanb@mono-cvs.ximian.com>
Sun, 9 Mar 2008 22:55:22 +0000 (22:55 -0000)
* add new resources:
PageWithAdapter.aspx for PageTest and PageAdapterTest.
TestCapability.browser for AppBrowsersTest.

* NunitWebResources/adapters.browser,
NunitWebResources/AppBrowsersTest.browser: modified to support
testing reference nodes with captures, and adapters.

* NunitWeb/NunitWeb/WebTest.cs: ensure that, during AppDomain
unload, no new requests are sent to the app host and any
pending requests are completed before the the unload occurs.
Also added WebTest.AppUnloaded event that tests can use to wait
for the app to unload (e.g. after touching Global.asax), and
WebTest.CleanApp() which can be called to restart the app with
the a skeleton directory structure.  Tests which add files that
could effect other tests (e.g. App_Browsers/*.browser files) should
call WebTest.CleanApp() during TearDown to return the app to a
pristine environment.

++ Test/mainsoft/MainsoftWebTest/ChangeLog (working copy)

* HtmlAgilityPack/AssemblyInfo.cs: made assembly delay signed so that
tests can access System.Web internals now that System.Web is
InternalsVisibleTo this assembly.

++ Test/System.Web/ChangeLog (working copy)

* AppBrowsersTest.cs: added.  Includes tests for Control.Adapter,
Control.ResolveAdapter, Control.TagWriter, and
Control.CreateHtmlTextWriter, when using App_Browsers/*.browser files.
AppBrowsersTest is currently tagged [Ignore], pending a fix for
bug #351878.

* HttpRuntimeTest.cs: added. Includes test for
HttpRuntime.UnloadAppDomain().  Marked [Ignore], pending a fix for
bug #351878.

++ Test/System.Web.UI.Adapters/ChangeLog (revision 0)

* PageAdapterTest.cs: added tests for PageAdapter.

* ControlAdapterTest.cs (ConfigCapabilitiesNotCalled): added test to
ensure that HttpCapabilitiesBase.ConfigCapabilities() is not called
during normal page processing if no files are in App_Browsers.

* ControlAdapterTest.cs: added tests for ControlAdapter.
++ Test/System.Web.UI/ChangeLog (working copy)

* PageTest.cs: add tests for using a PageAdapter.

* ControlTest.cs: moved commented out ResolveAdapter_1 test to
../System.Web/AppBrowsersTest.cs.  Fixed typo in test name.
Added Customcontroladapter.Adapter property for use by AppBrowsersTest.

++ Test/System.Web.UI.WebControls.Adapters/ChangeLog (revision 0)

* MenuAdapterTest.cs: added

* WebControlAdapterTest.cs, HierarchicalDataBoundControlAdapterTest.cs,
DataBoundControlAdapterTest.cs, HideDisabledControlAdapterTest.cs: added
++ Test/System.Web.UI.WebControls/ChangeLog (working copy)

* MenuTest.cs (Menu_RenderStaticItems): added tests to check that
result was the same when using the base MenuAdapter as when using
no adapter.

* MenuTest.cs (Menu_RenderStaticItemsWithAdapter): added test
to ensure that MenuAdapter.RenderItem() is called.

* HierarchicalDataBoundControlTest.cs, WebControlTest.cs,
DataBoundControlTest.cs: added test for use of ControlAdapters
when present.

* WebControl.cs: added test for IsEnabled.

++ System.Web/ChangeLog (working copy)

* HttpApplicationFactory.cs: Added support for detecting
App_Browsers/*.browser files and using them to determine capabilities.
Also restart the app if the App_Browsers, App_Code, or App_GlobalResources
directories are created.

* BrowserCapabilities.cs (TagWriter): get value via internal virtual
GetTagWriter() method, which is overridden in nBrowser.Result.

* HttpRequest.cs (BrowserMightHaveSpecialWriter, BrowserMightHaveAdapters):
internal properties added to allow Page and Control methods to avoid
accessing Request.Browser to get browser-specific HtmlTextWriters or
ControlAdapters.  Those things only exist when there are App_Browsers
files.

++ System.Web.UI.Adapters/ChangeLog (working copy)

* ControlAdapter.cs: made control field internal so
derived internal classes can access it without using base.Control
which can involved several typecasts.

* PageAdapter.cs: implemented all members.

* ControlAdapter.cs: implemented all members.

* PageAdapter.cs, ControlAdapter.cs: add MonoTODO's.
++ System.Web.UI/ChangeLog (working copy)

* Page.cs (SavePageControlState, LoadPageControlState): save/load
adapter state in 2.0 profile.

* Page.cs (CreateHtmlTextWriter): call Browser.CreateHtmlTextWriter()
in 2.0 profile.

* Page.cs (RenderPage): call CreateHtmlTextWriter() to get the writer
in 2.0 profile.

* Page.cs (DeterminePostBackMode, InitOutputCache,
RenderClientScriptFormDeclaration, InternalProcessRequest,
PageStatePersister): added support for PageAdapters.

* Control.cs (Adapter, ResolveAdapter): implemented.  Adapter calls
ResolveAdapter and remembers result.  ResolveAdapter checks for adapters
of the Type hierarchy until it finds one.

* Control.cs (SaveViewStateRecursive, LoadViewStateRecursive): save/load
adapter state in 2.0 profile.

* HtmlTextWriter.cs (BeginRender, EndRender): added empty virtual methods
required by 2.0 profile.  These are called by corresponding methods of
System.Web.UI.Adapters.ControlAdapter.

* Page.cs, Control.cs: don't access Request.Browser if it couldn't have
any adapters/writers because there are no files in App_Browsers/.

++ Assembly/ChangeLog (working copy)

* AssemblyInfo.cs: made InternalsVisibleTo System.Web.test_net_2_0.dll
to support ControlAdapterTest.ConfigCapabilitiesNotCalled().

++ ChangeLog (working copy)

* System.Web_test.dll.sources: added
System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
System.Web.UI.Adapters/PageAdapterTest.cs
System.Web.UI.Adapters/ControlAdapterTest.cs

* Makefile (RESOURCE_FILES_2): added
System.Web.Configuration_2.0/RandomRoboBotKeywords.txt

* Makefile (TEST_RESOURCE_FILES): added
Test/mainsoft/NunitWebResources/PageWithAdapter.aspx

* System.Web.dll.sources: added
System.Web.Configuration_2.0/CapabilitiesBuild.cs
System.Web.Configuration_2.0/CapabilitiesChecksum.cs
System.Web.Configuration_2.0/CapabilitiesResult.cs
System.Web.Configuration_2.0/ICapabilitiesProcess.cs
System.Web.Configuration_2.0/nBrowser/Result.cs
System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
System.Web.Configuration_2.0/nBrowser/Identification.cs
System.Web.Configuration_2.0/nBrowser/File.cs
System.Web.Configuration_2.0/nBrowser/Build.cs
System.Web.Configuration_2.0/nBrowser/Node.cs
System.Web.Configuration_2.0/nBrowser/Exception.cs

++ System.Web.UI.WebControls.Adapters/ChangeLog (working copy)

* WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
DataBoundControlAdapter.cs: changed to use ControlAdapter.control
instead of using base.Control or using a new control field.

* MenuAdapter.cs: added internal constructor that takes a Menu
parameter.  The constructor is used when writing unit tests.

* MenuAdapter.cs (OnInit, OnPreRender, RenderBeginTag,
RenderContents, RenderEndTag): delegate to base instead of
Control.

* MenuAdapter.cs (LoadAdapterControlState, SaveAdapterControlState,
RaisePostBackEvent, RenderItem): implemented.

* WebControlAdapter.cs (RenderContents): changed to call
control.RenderContents() instead of control.Render().

* WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
DataBoundControlAdapter.cs, HideDisabledControlAdapter.cs: added
internal constructor that takes a parameter of the corresponding
Control type.  The construct is used when writing unit tests.

++ System.Web.Configuration_2.0/ChangeLog (working copy)

* nBrowser/Result.cs, nBrowser/NodeTypes.cs, nBrowser/Identification.cs,
nBrowser/File.cs, nBrowser/Build.cs, nBrowser/Node.cs,
nBrowser/Exception.cs: added.  The code under nBrowser handles *.browser
files.  It is based on Owen "Ocean" Brady's code, with the following
changes and improvements.  Replaced Result.Adapter
property with AdapterTypeMap property which maps control Type to adapter
Type.  Added Result.MarkupTextWriter property.  Added overrides for
Result.GetAdapters and Result.GetTagWriter to return MarkupTextWriter
and AdapterTypeMap, resp.  Changed tree building algorithm to not
depend on nodes with id="Default" and to inject defaultBrowser nodes
as parents of regular nodes with the same ids.  Changed Node.cs to use
Item instead of Add when adding a capability or sample header, so that
values get replaced instead of appended.  Added support for reference
nodes (ie. nodes with refID="someID").

* CapabilitiesResult.cs: load RandomRoboBotKeywords.txt resource
using the correct name.

* RandomRoboBotKeywords.txt: added

* HttpCapabilitiesBase.cs (CreateHtmlWriter, Adapters): Added
support for *.browsers.  Adapters property calls internal virtual
GetAdapters() method which is overrided in nBrowser.Result
returned by nBrowser code.  CreateHtmlWriter uses type specified
by TagWriter property.

++ System.Web.UI.WebControls/ChangeLog (working copy)

* DetailsView.cs, ListControl.cs, DataBoundControl.cs,
FormView.cs, HierarchicalDataBoundControl.cs, WebControl.cs:
added support for using ControlAdapters when present.

* WebControl.cs: fixed implementation of IsEnabled to match
documentation.

* Menu.cs (RenderMenuBody): call Adapter.RenderItem() instead of
RenderMenuItem() if an adapter is present.  MenuAdapter.RenderItem()
calls back to new Menu.RenderItem() internal method which calls
RenderMenuItem() with the appropriate parameters.

++ System.Web.Configuration/ChangeLog (working copy)

* HttpCapabilitiesBase.cs: changed to use nBrowser for *.browser
support.  Also added internal GetConfigCapabilities_called
flag used by ControlAdapterTest.ConfigCapabilitiesNotCalled() to
test that GetConfigCapabilities() is not called during normal page
processing when there are no files in App_Browsers/.

svn path=/trunk/mcs/; revision=97824

74 files changed:
mcs/class/System.Web/Assembly/AssemblyInfo.cs
mcs/class/System.Web/Assembly/ChangeLog
mcs/class/System.Web/ChangeLog
mcs/class/System.Web/Makefile
mcs/class/System.Web/System.Web.Configuration/ChangeLog
mcs/class/System.Web/System.Web.Configuration/HttpCapabilitiesBase.cs
mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesBuild.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesChecksum.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesResult.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/ChangeLog
mcs/class/System.Web/System.Web.Configuration_2.0/HttpCapabilitiesBase.cs
mcs/class/System.Web/System.Web.Configuration_2.0/ICapabilitiesProcess.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/RandomRoboBotKeywords.txt [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Build.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Exception.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/File.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Identification.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Node.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/NodeTypes.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Result.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.UI.Adapters/ChangeLog
mcs/class/System.Web/System.Web.UI.Adapters/ControlAdapter.cs
mcs/class/System.Web/System.Web.UI.Adapters/PageAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/ChangeLog
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/DataBoundControlAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/HideDisabledControlAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/MenuAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls.Adapters/WebControlAdapter.cs
mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog
mcs/class/System.Web/System.Web.UI.WebControls/DataBoundControl.cs
mcs/class/System.Web/System.Web.UI.WebControls/DetailsView.cs
mcs/class/System.Web/System.Web.UI.WebControls/FormView.cs
mcs/class/System.Web/System.Web.UI.WebControls/HierarchicalDataBoundControl.cs
mcs/class/System.Web/System.Web.UI.WebControls/ListControl.cs
mcs/class/System.Web/System.Web.UI.WebControls/Menu.cs
mcs/class/System.Web/System.Web.UI.WebControls/WebControl.cs
mcs/class/System.Web/System.Web.UI/ChangeLog
mcs/class/System.Web/System.Web.UI/Control.cs
mcs/class/System.Web/System.Web.UI/HtmlTextWriter.cs
mcs/class/System.Web/System.Web.UI/Page.cs
mcs/class/System.Web/System.Web.dll.sources
mcs/class/System.Web/System.Web/BrowserCapabilities.cs
mcs/class/System.Web/System.Web/ChangeLog
mcs/class/System.Web/System.Web/HttpApplicationFactory.cs
mcs/class/System.Web/System.Web/HttpRequest.cs
mcs/class/System.Web/System.Web_test.dll.sources
mcs/class/System.Web/Test/System.Web.UI.Adapters/ChangeLog [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.Adapters/ControlAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.Adapters/PageAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/ChangeLog [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web.UI.WebControls/ChangeLog
mcs/class/System.Web/Test/System.Web.UI.WebControls/DataBoundControlTest.cs
mcs/class/System.Web/Test/System.Web.UI.WebControls/HierarchicalDataBoundControlTest.cs
mcs/class/System.Web/Test/System.Web.UI.WebControls/MenuTest.cs
mcs/class/System.Web/Test/System.Web.UI.WebControls/WebControlTest.cs
mcs/class/System.Web/Test/System.Web.UI/ChangeLog
mcs/class/System.Web/Test/System.Web.UI/ControlTest.cs
mcs/class/System.Web/Test/System.Web.UI/PageTest.cs
mcs/class/System.Web/Test/System.Web/AppBrowsersTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/System.Web/ChangeLog
mcs/class/System.Web/Test/System.Web/HttpRuntimeTest.cs [new file with mode: 0644]
mcs/class/System.Web/Test/mainsoft/ChangeLog
mcs/class/System.Web/Test/mainsoft/MainsoftWebTest/ChangeLog
mcs/class/System.Web/Test/mainsoft/MainsoftWebTest/HtmlAgilityPack/AssemblyInfo.cs
mcs/class/System.Web/Test/mainsoft/NunitWeb/NunitWeb/WebTest.cs
mcs/class/System.Web/Test/mainsoft/NunitWebResources/PageWithAdapter.aspx [new file with mode: 0644]
mcs/class/System.Web/Test/mainsoft/NunitWebResources/TestCapability.browser [new file with mode: 0644]
mcs/class/System.Web/Test/mainsoft/NunitWebResources/adapters.browser

index 80483894e98773365d12780cfb6141c53f6ca1ab..a59df50e62bacbfb73c888f7095f05b1428ff42d 100644 (file)
@@ -66,6 +66,7 @@ using System.Web.UI;
 
 #if NET_2_0
 [assembly: InternalsVisibleTo ("System.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+[assembly: InternalsVisibleTo ("System.Web_test_net_2_0, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
 #endif
 #endif
 
index 5666626c1e603a18236273e5db091a824f0c1559..4c7c68f8b15de98e10d886a3786a6677aa59738b 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-07  Dean Brettle <dean@brettle.com> 
+
+       * AssemblyInfo.cs: made InternalsVisibleTo System.Web.test_net_2_0.dll
+       to support ControlAdapterTest.ConfigCapabilitiesNotCalled().
+
 2007-11-22  Gert Driesen  <drieseng@users.sourceforge.net>
 
        * AssemblyInfo.cs: InternalsVisibleTo is 2.0 only. Fixes 1.0 profile
index c4ad82c43554f5a1296d37b952b01b5c988bf79f..dfab44fd55f6cf5c714616cbefc21db2b4b033a7 100644 (file)
@@ -1,3 +1,33 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * System.Web_test.dll.sources: added
+               System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
+               System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
+               System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
+               System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
+               System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
+               System.Web.UI.Adapters/PageAdapterTest.cs
+               System.Web.UI.Adapters/ControlAdapterTest.cs
+               
+       * Makefile (RESOURCE_FILES_2): added
+               System.Web.Configuration_2.0/RandomRoboBotKeywords.txt
+
+       * Makefile (TEST_RESOURCE_FILES): added 
+               Test/mainsoft/NunitWebResources/PageWithAdapter.aspx
+
+       * System.Web.dll.sources: added
+               System.Web.Configuration_2.0/CapabilitiesBuild.cs
+               System.Web.Configuration_2.0/CapabilitiesChecksum.cs
+               System.Web.Configuration_2.0/CapabilitiesResult.cs
+               System.Web.Configuration_2.0/ICapabilitiesProcess.cs
+               System.Web.Configuration_2.0/nBrowser/Result.cs
+               System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
+               System.Web.Configuration_2.0/nBrowser/Identification.cs
+               System.Web.Configuration_2.0/nBrowser/File.cs
+               System.Web.Configuration_2.0/nBrowser/Build.cs
+               System.Web.Configuration_2.0/nBrowser/Node.cs
+               System.Web.Configuration_2.0/nBrowser/Exception.cs
+               
 2008-03-01  Marek Habersack  <mhabersack@novell.com>
 
        * Makefile: added a dependency on Mono.Web.dll
index 56553a19f33202d9449d6a1f03f23194823717dd..a3445db27f5a3caf089bb1fb1c4a7f855aecc735 100644 (file)
@@ -64,6 +64,7 @@ RESOURCE_FILES_2 = \
        resources/transparent.gif \
        resources/webform.js \
        resources/WebUIValidation_2.0.js \
+       System.Web.Configuration_2.0/RandomRoboBotKeywords.txt \
        System.Web.UI.WebControls/GridView.js \
        System.Web.UI.WebControls/DetailsView.js \
        System.Web.UI.WebControls/TreeView.js \
@@ -140,6 +141,8 @@ TEST_RESOURCE_FILES = \
        Test/mainsoft/NunitWebResources/TextBoxTestlPage.aspx \
        Test/mainsoft/NunitWebResources/ClearErrorOnError.aspx \
        Test/mainsoft/NunitWebResources/RedirectOnError.aspx \
+       Test/mainsoft/NunitWebResources/TestCapability.browser \
+       Test/mainsoft/NunitWebResources/PageWithAdapter.aspx \
        Test/mainsoft/MainsoftWebTest/nunitweb_config.xml 
 
 RESX_DIST =  resources/TranslationResources.resx
index 818436edf340aea9d46ba6802c341212e732192e..7457a15965255fde681d46b2aca80fd49e5859eb 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * HttpCapabilitiesBase.cs: changed to use nBrowser for *.browser 
+       support.  Also added internal GetConfigCapabilities_called
+       flag used by ControlAdapterTest.ConfigCapabilitiesNotCalled() to 
+       test that GetConfigCapabilities() is not called during normal page
+       processing when there are no files in App_Browsers/.
+
 2008-02-28  Marek Habersack  <mhabersack@novell.com>
 
        * HandlerFactoryConfiguration.cs: ignore case when matching
index bfb2fcac9dbcf367cf710963b68fe817607f8556..cc634c10fb8b7a4e6241c4e66fdc1da3ada93554 100644 (file)
@@ -41,7 +41,7 @@ namespace System.Web.Configuration
        public class HttpCapabilitiesBase
 #endif
        {
-               IDictionary capabilities;
+               internal IDictionary capabilities;
 
                public HttpCapabilitiesBase () { }
 
@@ -72,18 +72,36 @@ namespace System.Web.Configuration
 #endif
                        return ua;
                }
+               private static HttpBrowserCapabilities GetHttpBrowserCapabilitiesFromBrowscapini(string ua)
+               {
+                       HttpBrowserCapabilities bcap = new HttpBrowserCapabilities();
+                       bcap.capabilities = CapabilitiesLoader.GetCapabilities (ua);
+                       return bcap;
+               }
                
                public static HttpCapabilitiesBase GetConfigCapabilities (string configKey, HttpRequest request)
                {
-                       string ua = GetUserAgentForDetection (request);
+                       string ua = GetUserAgentForDetection (request);
 
-                       HttpBrowserCapabilities bcap = new HttpBrowserCapabilities ();
+                       HttpBrowserCapabilities bcap = null;
+#if NET_2_0
+                       GetConfigCapabilities_called = true;
+                       if (HttpApplicationFactory.AppBrowsersFiles.Length > 0)
+                               bcap = HttpApplicationFactory.CapabilitiesProcessor.Process(request);
+                       else
+                               bcap = GetHttpBrowserCapabilitiesFromBrowscapini(ua);
+#else
+                       bcap = GetHttpBrowserCapabilitiesFromBrowscapini(ua);
+#endif
                        bcap.useragent = ua;
-                       bcap.capabilities = CapabilitiesLoader.GetCapabilities (ua);
                        bcap.Init ();
                        return bcap;
                }
 
+#if NET_2_0
+               // Used by unit tests to determine whether GetConfigCapabilities was called.
+               static internal bool GetConfigCapabilities_called;
+#endif
                protected virtual void Init ()
                {
                }
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesBuild.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesBuild.cs
new file mode 100644 (file)
index 0000000..5c11cb6
--- /dev/null
@@ -0,0 +1,118 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+
+       internal abstract class CapabilitiesBuild : ICapabilitiesProcess
+       {
+               /// <summary>
+               /// A list of all headers, that the Browser Detective Code will possibly access.
+               /// </summary>
+               private System.Collections.ObjectModel.Collection<string> AllPossibleheaders;
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="list"></param>
+               /// <returns></returns>
+               protected abstract System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list);
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="userAgent"></param>
+               /// <returns></returns>
+               public System.Web.Configuration.CapabilitiesResult Process(string userAgent)
+               {
+                       System.Collections.Specialized.NameValueCollection header;
+                       header = new System.Collections.Specialized.NameValueCollection(1);
+                       header.Add("User-Agent", userAgent);
+                       return Process(header);
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="request"></param>
+               /// <returns></returns>
+               public System.Web.Configuration.CapabilitiesResult Process(System.Web.HttpRequest request)
+               {
+                       if (request != null)
+                       {
+                               return Process(request.Headers);
+                       }
+                       else
+                       {
+                               return Process("");
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="header"></param>
+               /// <returns></returns>
+               public abstract System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header);
+               /// <summary>
+               /// Creates a Checksum from the Header values used by the Browser Detection System.
+               /// </summary>
+               /// <param name="header">List of Header name/value pairs</param>
+               /// <returns>checksum value to be used for caching/duplicate checks</returns>
+               public virtual string HeaderChecksum(System.Collections.Specialized.NameValueCollection header)
+               {
+                       if (AllPossibleheaders == null)
+                       {
+                               AllPossibleheaders = this.HeaderNames(new System.Collections.ObjectModel.Collection<string>());
+                       }
+                       System.IO.MemoryStream stream = new System.IO.MemoryStream();
+                       System.IO.StreamWriter writer = new System.IO.StreamWriter(stream, System.Text.Encoding.Default);
+
+                       for (int i = 0;i <= AllPossibleheaders.Count - 1;i++)
+                       {
+                               if (String.IsNullOrEmpty(header[AllPossibleheaders[i]]) == false)
+                               {
+                                       writer.WriteLine(header[AllPossibleheaders[i]]);
+                               }
+                       }
+                       writer.Flush();
+                       byte[] array = stream.ToArray();
+                       writer.Close();
+                       return CapabilitiesChecksum.BuildChecksum(array);
+               }
+               /// <summary>
+               /// Provides a Method to Load the Browser Detection class with a default Data file that is
+               /// embeded in the dll.
+               /// </summary>
+               public abstract void LoadDefaultEmbeddedResource();
+
+               public virtual string DataFileVersion
+               {
+                       get
+                       {
+                               return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesChecksum.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesChecksum.cs
new file mode 100644 (file)
index 0000000..497b712
--- /dev/null
@@ -0,0 +1,158 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+using System;
+using System.Collections;
+using System.Text;
+
+namespace System.Web.Configuration
+{
+       internal class CapabilitiesChecksum
+       {
+               public CapabilitiesChecksum()
+               {
+               }
+               public static string BuildChecksum(string raw)
+               {
+                       byte[] array = System.Text.Encoding.Default.GetBytes(raw.ToCharArray());
+                       array = System.Security.Cryptography.MD5.Create().ComputeHash(array);
+                       string[] c = new string[array.Length];
+                       for (int i = 0;i <= array.Length - 1;i++)
+                       {
+                               c[i] = CapabilitiesChecksum.Hex(array[i]);
+                       }
+                       array = null;
+                       return string.Join("", c);
+               }
+               public static string BuildChecksum(byte[] array)
+               {
+                       array = System.Security.Cryptography.MD5.Create().ComputeHash(array);
+                       string[] c = new string[array.Length];
+                       for (int i = 0;i <= array.Length - 1;i++)
+                       {
+                               c[i] = CapabilitiesChecksum.Hex(array[i]);
+                       }
+                       array = null;
+                       return string.Join("", c);
+               }
+
+               private static string Hex(byte b)
+               {
+                       char[] list = new char[2];
+                       BitArray myBA1 = new BitArray(new bool[4] { false, false, false, false });
+                       BitArray myBA2 = new BitArray(new bool[4] { false, false, false, false });
+                       BitArray myBA3 = new BitArray(new byte[] { b });
+
+                       //1 byte = 8 bits
+                       //4 bits = 1 Hex Value.
+                       myBA1.Set(0, myBA3.Get(0));
+                       myBA1.Set(1, myBA3.Get(1));
+                       myBA1.Set(2, myBA3.Get(2));
+                       myBA1.Set(3, myBA3.Get(3));
+
+                       myBA2.Set(0, myBA3.Get(4));
+                       myBA2.Set(1, myBA3.Get(5));
+                       myBA2.Set(2, myBA3.Get(6));
+                       myBA2.Set(3, myBA3.Get(7));
+
+                       list[0] = CapabilitiesChecksum.MapToHex(myBA1);
+                       list[1] = CapabilitiesChecksum.MapToHex(myBA2);
+                       return new string(list, 0, 2);
+               }
+               private static char MapToHex(BitArray a)
+               {
+                       //-----------------------------------------------------------------------------------
+                       //I could of done bit wise comparisons much more efficiant, but that would of given
+                       //me a bigger headach then this. Which I can reason though even half asleep.
+                       //-----------------------------------------------------------------------------------
+                       if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == false && a.Get(3) == false)
+                       {
+                               return '0';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == false && a.Get(3) == false)
+                       {
+                               return '1';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == false && a.Get(3) == false)
+                       {
+                               return '2';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == false && a.Get(3) == false)
+                       {
+                               return '3';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == true && a.Get(3) == false)
+                       {
+                               return '4';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == true && a.Get(3) == false)
+                       {
+                               return '5';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == true && a.Get(3) == false)
+                       {
+                               return '6';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == true && a.Get(3) == false)
+                       {
+                               return '7';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == false && a.Get(3) == true)
+                       {
+                               return '8';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == false && a.Get(3) == true)
+                       {
+                               return '9';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == false && a.Get(3) == true)
+                       {
+                               return 'A';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == false && a.Get(3) == true)
+                       {
+                               return 'B';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == true && a.Get(3) == true)
+                       {
+                               return 'C';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == true && a.Get(3) == true)
+                       {
+                               return 'D';
+                       }
+                       else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == true && a.Get(3) == true)
+                       {
+                               return 'E';
+                       }
+                       else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == true && a.Get(3) == true)
+                       {
+                               return 'F';
+                       }
+                       //this should never ever happen, unless a bit
+                       //gets switched mid way though the checks.
+                       throw new System.Exception("shit fell threw");
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesResult.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/CapabilitiesResult.cs
new file mode 100644 (file)
index 0000000..47bfa4b
--- /dev/null
@@ -0,0 +1,338 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+
+       internal class CapabilitiesResult : System.Web.HttpBrowserCapabilities
+       {
+               private string[] RandomRoboBotKeywords;
+               /// <summary>
+               /// Initializes a new instance of the Result class.
+               /// </summary>
+               /// <param name="items">
+               /// This is the data which this class will be handle request made though this class.
+               /// </param>
+               internal CapabilitiesResult(System.Collections.Generic.Dictionary<string, string> items)
+                       : base()
+               {
+                       base.Capabilities = items;
+
+                       //---------------------------------------------------------------
+                       //Copies out a list of keywords stored in an Embeded file, which 
+                       //will be used to help determine if a browser is 
+                       //IsRandomRoboBotUserAgent.
+                       //---------------------------------------------------------------
+                       System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
+                       System.IO.Stream CP;
+                       CP = asm.GetManifestResourceStream("RandomRoboBotKeywords.txt");
+                       System.IO.StreamReader Read = new System.IO.StreamReader(CP, System.Text.Encoding.Default);
+                       RandomRoboBotKeywords = System.Text.RegularExpressions.Regex.Split(Read.ReadToEnd(), System.Environment.NewLine);
+                       Read.Close();
+                       Read = null;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="name"></param>
+               /// <param name="value"></param>
+               internal void AddCapabilities(string name, string value)
+               {
+                       this.Capabilities[name] = value;
+               }
+               internal virtual string Replace(string item)
+               {
+                       if (item.IndexOf("$") > -1)
+                       {
+                               //nasty hack to convert regular expression replacement text into  Capability item
+                               //which we can use to replace with the actual values they are looking for.
+                               System.Text.RegularExpressions.MatchCollection regxmatch;
+                               regxmatch = System.Text.RegularExpressions.Regex.Matches(item, @"\$\{(?'Capability'\w*)\}");
+                               if (regxmatch.Count == 0)
+                               {
+                                       return item;
+                               }
+                               for (int i = 0;i <= regxmatch.Count - 1;i++)
+                               {
+                                       if (regxmatch[i].Success == true)
+                                       {
+                                               string c = regxmatch[i].Result("${Capability}");
+                                               item = item.Replace("${" + c + "}", this[c]);
+                                       }
+                               }
+                       }
+                       if (item.IndexOf("%") > -1)
+                       {
+                               //nasty hack to convert regular expression replacement text into  Capability item
+                               //which we can use to replace with the actual values they are looking for.
+                               System.Text.RegularExpressions.MatchCollection regxmatch;
+                               regxmatch = System.Text.RegularExpressions.Regex.Matches(item, @"\%\{(?'Capability'\w*)\}");
+                               if (regxmatch.Count == 0)
+                               {
+                                       return item;
+                               }
+                               for (int i = 0;i <= regxmatch.Count - 1;i++)
+                               {
+                                       if (regxmatch[i].Success == true)
+                                       {
+                                               string c = regxmatch[i].Result("${Capability}");
+                                               item = item.Replace("%{" + c + "}", this[c]);
+                                       }
+                               }
+                       }
+                       return item;
+               }
+               /// <summary>
+               /// Gets the Operating System that the browser is running on.
+               /// </summary>
+               public string OS
+               {
+                       get
+                       {
+                               return this["os"];
+                       }
+               }
+               /// <summary>
+               /// Gets the browsers Build.
+               /// </summary>
+               public string BrowserBuild
+               {
+                       get
+                       {
+                               return this["BrowserBuild"];
+                       }
+               }
+               /// <summary>
+               /// Name of the Browser Rendering Engine, when known.
+               /// </summary>
+               public string BrowserRenderingEngine
+               {
+                       get
+                       {
+                               return this["HtmlEngine"];
+                       }
+               }
+               /// <summary>
+               /// Gets if the Browser was identified as a bot, as a mater of elimination of all other possible
+               /// options currently availible.
+               /// </summary>
+               public bool IsRobot
+               {
+                       get
+                       {
+                               if (string.Compare(this["IsMobileDevice"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return false;
+                               }
+                               else if (string.Compare(this["IsBot"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               else if (string.Compare(this["crawler"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               else if (string.Compare(this["Unknown"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               else if (string.Compare(this.Browser, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               else if (string.Compare(this.Browser, "IE", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       //too many fake IE's out there this should remove a few of the low
+                                       //hanging fruit.
+                                       if (string.IsNullOrEmpty(this.Platform) == true)
+                                       {
+                                               return true;
+                                       }
+                                       else if (string.Compare(this.Platform, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                                       {
+                                               return true;
+                                       }
+                                       else if (string.Compare(this[""], "....../1.0", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                                       {
+                                               //I hate Scrapters This one hit me today. Lets see how it like it now geting 403's
+                                               return true;
+                                       }
+
+                               }
+                               return false;
+                       }
+               }
+               public bool IsSyndicationReader
+               {
+                       get
+                       {
+                               if (string.Compare(this["IsSyndicationReader"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+               public bool IsUnknown
+               {
+                       get
+                       {
+                               if (string.Compare(this["Unknown"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+               /// <summary>
+               /// Used to Identify Robobots that are using randomly generated Useragents
+               /// that are nonsensical in nature/gibberish.
+               /// </summary>
+               /// <remarks>
+               /// Current implementation is more of an elimination of common traits, which
+               /// most Useragent/browser have. Which leave us with what can be assumed as
+               /// randomized useragent names, which serve no purpose cept to drive stats
+               /// programs nuts.
+               /// </remarks>
+               public bool IsRandomRobobotUserAgent
+               {
+                       get
+                       {
+                               #region  Check for Common Words in UserAgents
+                               //---------------------------------------------------------------
+                               //Quick Checks to see if the Bot has been identified by a name
+                               //from the headers provided.
+                               //---------------------------------------------------------------
+                               if (this.IsRobot == false)
+                               {
+                                       //---------------------------------------------------------------
+                                       //Since we can determine its not a Robot. We must have enough
+                                       //details to prove its not a random useragent, and we move on.
+                                       //---------------------------------------------------------------
+                                       return false;
+                               }
+                               else if (this.IsSyndicationReader == true)
+                               {
+                                       //---------------------------------------------------------------
+                                       //Since we can determine its not a Rss/Atom Feed Reader. We must 
+                                       //have enough details to prove its not a random useragent, and we
+                                       //move on.
+                                       //---------------------------------------------------------------
+                                       return false;
+                               }
+                               else if (string.Compare(this.Browser, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) != 0)
+                               {
+                                       //---------------------------------------------------------------
+                                       //Browser name was able to be determined then the Useragent had
+                                       //enough details, thus not a random Useragent.
+                                       //---------------------------------------------------------------
+                                       return false;
+                               }
+                               else if (string.Compare(this.Platform, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) != 0)
+                               {
+                                       //---------------------------------------------------------------
+                                       //Assume if a platform was able to be determine then the Useragent
+                                       //is more then likely not randomized name.
+                                       //---------------------------------------------------------------
+                                       return false;
+                               }
+                               else if (string.IsNullOrEmpty(this.UserAgent) == true)
+                               {
+                                       //---------------------------------------------------------------
+                                       //Null or empty. ^he Programer was just to lazy which to give it a
+                                       //name, which is fine with me but doesn't not count as a Randomized
+                                       //Browser Agent, since it doesn't have a Useragent at all to begin
+                                       //with.
+                                       //---------------------------------------------------------------
+                                       return false;
+                               }
+
+                               //---------------------------------------------------------------
+                               //I assume ones under 8 charactors are not really randomly named
+                               //but the coder was just lazy or picked a short name.
+                               //---------------------------------------------------------------
+                               if (this.UserAgent.Length < 8)
+                               {
+                                       return false;
+                               }
+
+                               //---------------------------------------------------------------
+                               //Up to this point I have not seen a randomly generated Agent string
+                               //with a period in it.
+                               //---------------------------------------------------------------
+                               if (this.UserAgent.IndexOf('.') > -1)
+                               {
+                                       return false;
+                               }
+                               //---------------------------------------------------------------
+                               //Compare keywords often found in useragents to the current useragent
+                               //and if we find one we assume its not a randomized useragent.
+                               //---------------------------------------------------------------
+                               foreach (string keyword in RandomRoboBotKeywords)
+                               {
+                                       if (keyword.Length <= this.UserAgent.Length)
+                                       {
+                                               if (this.UserAgent.IndexOf(keyword, StringComparison.CurrentCultureIgnoreCase) != -1)
+                                               {
+                                                       return false;
+                                               }
+                                       }
+                               }
+                               #endregion
+                               //---------------------------------------------------------------
+                               //Since it made it though all the checks I assume that the useragent
+                               //doesn't match any known format that I can determine, and label it
+                               //a randomized Useragent/browser. AKA SPAM / Scraper / Pests Bots.
+                               //---------------------------------------------------------------
+                               return true;
+                       }
+               }
+               /// <summary>
+               /// Gets the keys returned from processing.
+               /// </summary>
+               public System.Collections.Specialized.StringCollection Keys
+               {
+                       get
+                       {
+                               string[] a = new string[this.Capabilities.Keys.Count];
+                               this.Capabilities.Keys.CopyTo(a, 0);
+                               System.Array.Sort(a);
+                               System.Collections.Specialized.StringCollection l;
+                               l = new System.Collections.Specialized.StringCollection();
+                               l.AddRange(a);
+                               return l;
+                       }
+               }
+               public string UserAgent
+               {
+                       get
+                       {
+                               return this[""];
+                       }
+               }
+       }
+}
+#endif
index 880e0f29ed1c5bed483ab1b7a156c77f21154aaf..44a2e80807947cbcbe0b10ad565dd4198d204568 100644 (file)
@@ -1,3 +1,31 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * nBrowser/Result.cs, nBrowser/NodeTypes.cs, nBrowser/Identification.cs,
+       nBrowser/File.cs, nBrowser/Build.cs, nBrowser/Node.cs, 
+       nBrowser/Exception.cs: added.  The code under nBrowser handles *.browser
+       files.  It is based on Owen "Ocean" Brady's code, with the following 
+       changes and improvements.  Replaced Result.Adapter 
+       property with AdapterTypeMap property which maps control Type to adapter
+       Type.  Added Result.MarkupTextWriter property.  Added overrides for
+       Result.GetAdapters and Result.GetTagWriter to return MarkupTextWriter
+       and AdapterTypeMap, resp.  Changed tree building algorithm to not
+       depend on nodes with id="Default" and to inject defaultBrowser nodes
+       as parents of regular nodes with the same ids.  Changed Node.cs to use
+       Item instead of Add when adding a capability or sample header, so that
+       values get replaced instead of appended.  Added support for reference 
+       nodes (ie. nodes with refID="someID").
+               
+       * CapabilitiesResult.cs: load RandomRoboBotKeywords.txt resource
+       using the correct name.
+       
+       * RandomRoboBotKeywords.txt: added 
+
+       * HttpCapabilitiesBase.cs (CreateHtmlWriter, Adapters): Added
+       support for *.browsers.  Adapters property calls internal virtual
+       GetAdapters() method which is overrided in nBrowser.Result 
+       returned by nBrowser code.  CreateHtmlWriter uses type specified
+       by TagWriter property.
+       
 2008-03-03  Vladimir Krasnov  <vladimirk@mainsoft.com>
 
        * ProvidersHelper.cs: fixed thread safety issue in InstantiateProvider
index aaf5acf6ea4fbe2cf535a6536dbfe60939e3b466..36489be3baec78d1ce314cb94b264c562beb711c 100644 (file)
@@ -53,7 +53,7 @@ namespace System.Web.Configuration
 
                public HtmlTextWriter CreateHtmlTextWriter (TextWriter w)
                {
-                       return new HtmlTextWriter (w);
+                       return (HtmlTextWriter) Activator.CreateInstance (TagWriter, new object[] {w});
                }
 
                public void DisableOptimizedCacheKey ()
@@ -65,13 +65,18 @@ namespace System.Web.Configuration
                public IDictionary Adapters {
                        get {
                                if (!Get (HaveAdapters)) {
-                                       adapters = new Hashtable ();
+                                       adapters = GetAdapters();
                                        Set (HaveAdapters);
                                }
 
                                return adapters;
                        }
                }
+               
+               internal virtual IDictionary GetAdapters ()
+               {
+                       return new Hashtable();
+               }
 
                bool canCombineFormsInDeck;
                public virtual bool CanCombineFormsInDeck {
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/ICapabilitiesProcess.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/ICapabilitiesProcess.cs
new file mode 100644 (file)
index 0000000..7bc4b29
--- /dev/null
@@ -0,0 +1,37 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+
+       internal interface ICapabilitiesProcess
+       {
+               System.Web.Configuration.CapabilitiesResult Process(string userAgent);
+               System.Web.Configuration.CapabilitiesResult Process(System.Web.HttpRequest request);
+               System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header);
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/RandomRoboBotKeywords.txt b/mcs/class/System.Web/System.Web.Configuration_2.0/RandomRoboBotKeywords.txt
new file mode 100644 (file)
index 0000000..47b6e96
--- /dev/null
@@ -0,0 +1,118 @@
+/
+\
+_
+Agent
+Auto
+beta
+book
+bot
+Browse
+bug
+build
+check
+class
+client
+cold
+College
+compatible
+Contribute
+crawl
+Desktop
+discovery
+Download
+Eudora
+example
+explore
+favorg
+Fetch
+file
+finder
+flash
+form
+fox
+free
+Friend
+get
+google
+http
+IE 
+Illinois
+Iltrovatore
+Internet
+java
+K-Meleon
+know
+Library
+link
+linux
+load
+locate
+locator
+Lycos
+lynx
+main
+manager
+MASTER
+microsoft
+mind
+Moozilla
+mozilla
+MSIE
+net
+Netscape
+nokia
+Norton
+null
+OpenBSD
+Opera
+play
+Plucker
+Post
+power
+Program
+project
+pure
+proxy
+QuickTime
+Redirector
+Scanner
+scooter
+scrape
+search
+server
+Service
+Site
+sight
+shout
+state
+Sleipnir
+slurp
+Snoopy
+spider
+SPY
+Surf
+source
+telnet
+teoma
+test
+THE
+tool
+tracker
+Tunnel
+Unix
+Update
+URL
+Verified
+Version
+Vista
+Web
+winamp
+Windows
+work
+Xenu
+XML
+Yahoo
+Zeus
+zip
+world
+light
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Build.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Build.cs
new file mode 100644 (file)
index 0000000..89a0667
--- /dev/null
@@ -0,0 +1,342 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+       internal class Build : System.Web.Configuration.CapabilitiesBuild
+       {
+               //This keeps a list of filenames and FileNodes linked
+               private System.Collections.Generic.Dictionary<string, System.Web.Configuration.nBrowser.File> Browserfiles;
+
+               //Just links FileNodes
+               private System.Collections.Generic.List<System.Web.Configuration.nBrowser.File> nbrowserfiles;
+
+               //
+               private System.Collections.Generic.Dictionary<string, string> DefaultKeys;
+               private System.Collections.Generic.Dictionary<string, string> BrowserKeys;
+
+               //
+               private System.Web.Configuration.nBrowser.Node browser;
+
+               /// <summary>
+               /// 
+               /// </summary>
+               public Build()
+                       : base()
+               {
+                       Browserfiles = new System.Collections.Generic.Dictionary<string, System.Web.Configuration.nBrowser.File>();
+                       nbrowserfiles = new System.Collections.Generic.List<System.Web.Configuration.nBrowser.File>();
+
+                       DefaultKeys = new System.Collections.Generic.Dictionary<string, string>();
+                       BrowserKeys = new System.Collections.Generic.Dictionary<string, string>();
+               }
+               /// <summary>
+               /// Reads an entire directory and process's all of the browser files in that
+               /// directory.
+               /// </summary>
+               /// <param name="path"></param>
+               public void AddBrowserDirectory(string path)
+               {
+                       //I allow this function to be a little messy
+                       //just in case they pass in a path that really a file
+                       //name
+                       if (System.IO.Directory.Exists(path) == true)
+                       {
+                               System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path);
+                               System.IO.FileInfo[] file = dir.GetFiles("*.browser");
+                               //we are done with it so let the GC have it early as possible
+                               dir = null;
+                               for (int a = 0;a <= file.Length - 1;a++)
+                               {
+                                       AddBrowserFile(file[a].FullName);
+                               }
+                       }
+                       else if (System.IO.File.Exists(path) == true)
+                       {
+                               AddBrowserFile(path);
+                       }
+               }
+               /// <summary>
+               /// Reads a browser file and builds the Nodes which that file contains.
+               /// </summary>
+               /// <param name="filename"></param>
+               public void AddBrowserFile(string fileName)
+               {
+                       if (Browserfiles.ContainsKey(fileName) == false)
+                       {
+                               nBrowser.File b = new nBrowser.File(fileName);
+                               this.AddBrowserFile(b);
+                       }
+
+               }
+               private void AddBrowserFile(nBrowser.File file)
+               {
+                       if (Browserfiles.ContainsKey(file.FileName) == false)
+                       {
+                               Browserfiles.Add(file.FileName, file);
+                               nbrowserfiles.Add(file);
+
+                               string[] keys = file.Keys;
+                               for (int i = 0;i <= keys.Length - 1;i++)
+                               {
+                                       if (BrowserKeys.ContainsKey(keys[i]) == false)
+                                       {
+                                               BrowserKeys.Add(keys[i], file.FileName);
+                                       }
+                                       else
+                                       {
+                                               throw new nBrowser.Exception("Duplicate Key \"" + keys[i] + "\" found in " + file.FileName + " and in file " + BrowserKeys[keys[i]]);
+                                       }
+                               }
+                               keys = file.DefaultKeys;
+                               for (int i = 0;i <= keys.Length - 1;i++)
+                               {
+                                       if (DefaultKeys.ContainsKey(keys[i]) == false)
+                                       {
+                                               DefaultKeys.Add(keys[i], file.FileName);
+                                       }
+                                       else
+                                       {
+                                               throw new nBrowser.Exception("Duplicate Key \"" + keys[i] + "\" found in " + file.FileName + " and in file " + DefaultKeys[keys[i]]);
+                                       }
+                               }
+                       }
+               }
+               /// <summary>
+               /// Reads a browser file and builds the Nodes which that file contains.
+               /// </summary>
+               /// <param name="file"></param>
+               [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059")]
+               public void AddBrowserFile(System.Xml.XmlDocument browser, string fileName)
+               {
+                       if (Browserfiles.ContainsKey(fileName) == false)
+                       {
+                               nBrowser.File file = new nBrowser.File(browser, fileName);
+                               this.AddBrowserFile(file);
+                       }
+               }
+               /// <summary>
+               /// Returns the root Node of the Browser Tree.
+               /// </summary>
+               /// <returns></returns>
+               public Node Browser()
+               {
+                       if (browser != null)
+                       {
+                               return browser;
+                       }
+                       browser = new Node();
+                       //Custom Sorted List, to allow where Multple files in Diff directorys might have the same
+                       //filename. So still to some degree first come first serve but might be close enough
+                       //to how microsoft System to match much more closely.
+                       System.Collections.Generic.SortedList<string, System.Collections.Generic.List<nBrowser.File>> list;
+                       list = new System.Collections.Generic.SortedList<string, System.Collections.Generic.List<nBrowser.File>>();
+
+                       for (int i = 0;i <= Browserfiles.Count - 1;i++)
+                       {
+                               if (list.ContainsKey(nbrowserfiles[i].FileName) == false)
+                               {
+                                       System.Collections.Generic.List<nBrowser.File> l;
+                                       l = new System.Collections.Generic.List<nBrowser.File>();
+                                       list.Add(nbrowserfiles[i].FileName, l);
+                               }
+                               list[nbrowserfiles[i].FileName].Add(nbrowserfiles[i]);
+                       }
+                       nBrowser.File[] files = new nBrowser.File[Browserfiles.Count];
+
+                       int count = 0;
+                       for (int i = 0;i <= list.Count - 1;i++)
+                       {
+                               System.Collections.Generic.List<nBrowser.File> l = list[list.Keys[i]];
+                               for (int b = 0;b <= l.Count - 1;b++)
+                               {
+                                       files[count] = l[b];
+                                       count++;
+                               }
+                       }
+
+                       #region Connect Nodes
+                       for (int i = 0;i <= Browserfiles.Count - 1;i++)
+                       {
+                               for (int a = 0;a <= files[i].Keys.Length - 1;a++)
+                               {
+                                       Node child = files[i].GetNode(files[i].Keys[a]);
+                                       Node parent = null;
+                                       if (child.ParentId.Length > 0)
+                                       {
+                                               parent = this.GetNode(child.ParentId);
+                                               if (parent == null)
+                                                       throw new nBrowser.Exception(String.Format("Parent not found with = {0}", child.ParentId));
+                                       }
+                                       if (parent == null)
+                                               parent = browser;
+                                       parent.AddChild(child);
+                               }
+                       }
+                       #endregion
+                       
+                       #region Inject DefaultBrowser Nodes
+                       for (int i = 0;i <= Browserfiles.Count - 1;i++)
+                       {
+                               for (int a = 0;a <= files[i].DefaultKeys.Length - 1;a++)
+                               {
+                                       Node defaultNode = files[i].GetDefaultNode(files[i].DefaultKeys[a]);
+                                       Node node = this.GetNode(defaultNode.Id);
+                                       if (node == defaultNode) 
+                                       {
+                                               // there is no regular node so the defaultNode is already at
+                                               // the correct spot in the tree.
+                                               continue;
+                                       }
+                                       Node parentNode = this.GetNode(node.ParentId);
+                                       if (parentNode == null)
+                                               parentNode = browser;
+                                       // insert the default node between the regular node and it's parent.
+                                       parentNode.RemoveChild(node);
+                                       defaultNode.AddChild(node);
+                                       parentNode.AddChild(defaultNode);
+                               }
+                       }
+                       #endregion
+
+                       #region Merge Ref Nodes
+                       for (int i = 0;i <= Browserfiles.Count - 1;i++)
+                       {
+                               foreach (Node refNode in files[i].RefNodes) {
+                                       GetNode(refNode.RefId).MergeFrom(refNode);
+                               }
+                       }
+                       #endregion
+
+                       return browser;
+               }
+                                               
+               /// <summary>
+               /// returns a Node Matching the Key supplied, for either a 
+               /// DefaultBrowser, or Gatway/Browser node.
+               /// </summary>
+               /// <param name="Key"></param>
+               /// <returns></returns>
+               private Node GetNode(string Key)
+               {
+                       if (Key == null || Key.Length == 0)
+                               return null;
+                               
+                       string filename;
+                       //Must find what file node that this key is located in
+                       //so we look it up in the string dictionary's
+                       if (!BrowserKeys.TryGetValue(Key, out filename)
+                               && !DefaultKeys.TryGetValue(Key, out filename))
+                               return null;
+                               
+                       //fxcop sugguested this was faster then
+                       //filename!= string.Empty
+                       if (filename != null && filename.Length > 0)
+                       {
+                               //now that we have a name we look it up in the hasttable containing
+                               //the actual node.
+                               nBrowser.File b = Browserfiles[filename];
+                               Node n = b.GetNode(Key);
+                               return n;
+                       }
+
+                       return null;                    
+               }
+               
+               /// <summary>
+               /// Returns an Array of Nodes that have been built. To be used for Design/Editors of Browser
+               /// files.
+               /// </summary>
+               /// <returns></returns>
+               public Node[] Nodes()
+               {
+                       Node[] browsers;
+                       nBrowser.File[] files = new nBrowser.File[Browserfiles.Count];
+                       Browserfiles.Values.CopyTo(files, 0);
+                       int count = 0;
+                       for (int i = 0;i <= files.Length - 1;i++)
+                       {
+                               count += files[i].Nodes.Length;
+                       }
+                       browsers = new Node[count];
+                       count = 0;
+                       for (int i = 0;i <= files.Length - 1;i++)
+                       {
+                               for (int a = 0;a <= files[i].Nodes.Length - 1;a++)
+                               {
+                                       browsers[count] = files[i].Nodes[a];
+                                       count++;
+                               }
+                       }
+                       return browsers;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="header"></param>
+               /// <returns></returns>
+               public override System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header)
+               {
+                       System.Web.Configuration.nBrowser.Result r = new System.Web.Configuration.nBrowser.Result(new System.Collections.Generic.Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase));
+
+#if trace
+                       System.Diagnostics.Trace.WriteLine(string.Join("+", new string[50]));
+                       for (int i=0;i <= header.Count -1;i++)
+                       {
+                               System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}",header.GetKey(i).PadRight(25),header[i]));
+                       }
+                       System.Diagnostics.Trace.WriteLine(string.Join("+", new string[50]));
+#endif
+                       return Browser().Process(header, r, new System.Collections.Generic.List<System.Web.Configuration.nBrowser.Identification>());
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="list"></param>
+               /// <returns></returns>
+               protected override System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list)
+               {
+                       return this.Browser().HeaderNames(list);
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public override void LoadDefaultEmbeddedResource()
+               {
+                       System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
+                       System.IO.Stream CP;
+                       CP = asm.GetManifestResourceStream("System.Web.Configuration.Resources.CodeProject.browser");
+                       System.Xml.XmlDocument Doc = new System.Xml.XmlDocument();
+                       Doc.Load(CP);
+                       CP.Close();
+
+                       this.AddBrowserFile(Doc, "System.Web.Configuration.Resources.CodeProject.browser");
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Exception.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Exception.cs
new file mode 100644 (file)
index 0000000..78a41b7
--- /dev/null
@@ -0,0 +1,67 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Runtime.Serialization;
+       [
+       System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable"),
+       System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")
+       ]
+       internal class Exception : System.Exception
+       {
+               public Exception()
+                       : base()
+               {
+               }
+               public Exception(string errorMessage)
+                       : base(errorMessage)
+               {
+               }
+               public Exception(string message, Exception innerException)
+                       : base(message, innerException)
+               {
+                       // Add any type-specific logic for inner exceptions.
+               }
+               protected Exception(SerializationInfo info, StreamingContext context)
+                       : base(info, context)
+               {
+                       // Implement type-specific serialization constructor logic.
+               }
+       }
+}
+/*
+Turns off the following Warning in FxCop
+--------------------------------------------------------------------------------------------------------------------
+[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")]
+The System.Runtime.Serialization.ISerializable interface allows the type to customize its serialization, while 
+the Serializable attribute enables the common language runtime to recognize the type as being serializable."
+--------------------------------------------------------------------------------------------------------------------
+System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")
+Multiple constructors are required to correctly implement a custom exception. Missing constructors can make your 
+exception unusable in certain scenarios. For example, the serialization constructor is required for handling 
+exceptions in XML Web services.
+--------------------------------------------------------------------------------------------------------------------
+*/
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/File.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/File.cs
new file mode 100644 (file)
index 0000000..ae1d3f9
--- /dev/null
@@ -0,0 +1,203 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+       using System.Web.Configuration.nBrowser;
+
+       class File
+       {
+               private System.Xml.XmlDocument BrowserFile;
+               internal System.Web.Configuration.nBrowser.Node[] Nodes;
+               private System.Collections.Specialized.ListDictionary Lookup;
+               private System.Collections.Specialized.ListDictionary DefaultLookup;
+               internal List<Node> RefNodes;
+               
+               public string FileName
+               {
+                       get
+                       {
+                               return pFileName;
+                       }
+               }
+               private string pFileName = string.Empty;
+               public File(string file)
+               {
+                       pFileName = file;
+
+                       BrowserFile = new System.Xml.XmlDocument();
+                       //I can put this in a try /catch but I want
+                       //this to bubble up.
+                       BrowserFile.Load(file);
+
+                       this.Load(BrowserFile);
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="file"></param>
+               public File(System.Xml.XmlDocument BrowserFile, string filename)
+               {
+                       pFileName = filename;
+                       this.Load(BrowserFile);
+               }
+               private void Load(System.Xml.XmlDocument BrowserFile)
+               {
+                       Lookup = new System.Collections.Specialized.ListDictionary();
+                       DefaultLookup = new System.Collections.Specialized.ListDictionary();
+                       RefNodes = new List<Node>();
+                       System.Xml.XmlNode node;
+                       //I know this might allocate more nodes then needed but never less.
+                       Nodes = new Node[BrowserFile.DocumentElement.ChildNodes.Count];
+                       for (int a = 0;a <= BrowserFile.DocumentElement.ChildNodes.Count - 1;a++)
+                       {
+                               node = BrowserFile.DocumentElement.ChildNodes[a];
+
+                               if (node.NodeType == System.Xml.XmlNodeType.Comment)
+                               {
+                                       continue;
+                               }
+                               Nodes[a] = new Node(node);
+                               Nodes[a].FileName = FileName;
+                               if (Nodes[a].NameType != NodeType.DefaultBrowser)
+                               {
+                                       //fxcop sugguested this was faster then
+                                       //Nodes[a].refID != string.Empty
+                                       if (Nodes[a].RefId.Length > 0)
+                                       {
+                                               RefNodes.Add(Nodes[a]);
+                                       }
+                                       else if (Lookup.Contains(Nodes[a].Id) == false)
+                                       {
+                                               Lookup.Add(Nodes[a].Id, a);
+                                       }
+                                       else
+                                       {
+                                               throw new nBrowser.Exception("Duplicate ID found \"" + Nodes[a].Id + "\"");
+                                       }
+                               }
+                               else
+                               {
+                                       //fxcop sugguested this was faster then
+                                       //Nodes[a].refID != string.Empty
+                                       if (Nodes[a].RefId.Length > 0)
+                                       {
+                                               RefNodes.Add(Nodes[a]);
+                                       }
+                                       else if (DefaultLookup.Contains(Nodes[a].Id) == false)
+                                       {
+                                               DefaultLookup.Add(Nodes[a].Id, a);
+                                       }
+                                       else
+                                       {
+                                               throw new nBrowser.Exception("Duplicate ID found \"" + Nodes[a].Id + "\"");
+                                       }
+                               }
+                       }
+               }
+               /// <summary>
+               /// Returns a Array of strings, which represent the Id Attributes of all the
+               /// Browser/Gatway Nodes
+               /// </summary>
+               public string[] Keys
+               {
+                       get
+                       {
+
+                               string[] k = new string[Lookup.Keys.Count];
+                               //12-29-05
+                               //This will copy the Keys In Alphabetical Order
+                               //Lookup.Keys.CopyTo(k,0);
+                               //This Method is ment to copy the Keys in the order
+                               //that they were in the xml file.
+                               int b = 0;
+                               for (int i = 0;i <= Nodes.Length - 1;i++)
+                               {
+                                       if (Nodes[i] != null && Nodes[i].NameType != NodeType.DefaultBrowser 
+                                               && Nodes[i].RefId.Length == 0)
+                                       {
+                                               k[b] = Nodes[i].Id;
+                                               b++;
+                                       }
+                               }
+                               return k;
+                       }
+               }
+               /// <summary>
+               /// Returns a Array of strings, which represent the Id Attributes of all the
+               /// DefaultBrowser Nodes
+               /// </summary>
+               public string[] DefaultKeys
+               {
+                       get
+                       {
+                               string[] k = new string[DefaultLookup.Keys.Count];
+                               //12-29-05
+                               //This will copy the Keys In Alphabetical Order
+                               //DefaultLookup.Keys.CopyTo(k,0);
+                               //This Method is ment to copy the Keys in the order
+                               //that they were in the xml file.
+                               int b = 0;
+                               for (int i = 0;i <= Nodes.Length - 1;i++)
+                               {
+                                       if (Nodes[i] != null && Nodes[i].NameType == NodeType.DefaultBrowser)
+                                       {
+                                               k[b] = Nodes[i].Id;
+                                               b++;
+                                       }
+                               }
+                               return k;
+                       }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="Key"></param>
+               /// <returns></returns>
+               internal Node GetNode(string Key)
+               {
+                       object o = Lookup[Key];
+                       if (o == null)
+                               return GetDefaultNode (Key);
+                       return Nodes[(int)o];
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="Key"></param>
+               /// <returns></returns>
+               internal Node GetDefaultNode(string Key)
+               {
+                       object o = DefaultLookup[Key];
+                       if (o == null)
+                               return null;
+                       return Nodes[(int)o];
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Identification.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Identification.cs
new file mode 100644 (file)
index 0000000..40a839a
--- /dev/null
@@ -0,0 +1,168 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+
+       class Identification
+       {
+               private bool MatchType = true;
+               private string MatchName = string.Empty;
+               private string MatchGroup = string.Empty;
+               //FxCop will complain that this is assigned to but never used.
+               //Reason I keep it around is to see the actual regex expresion 
+               //used without having to drill down deep in regex object to find it
+               private string MatchPattern = string.Empty;
+               private System.Text.RegularExpressions.Regex RegexPattern;
+               private System.Text.RegularExpressions.Match PatternMatch;
+
+               /// <summary>
+               /// Sets up Initial Identification Object, So that it is easier debuging
+               /// and passing Regular expression objects around.
+               /// </summary>
+               /// <param name="matchType">True = Match, False = NonMatch</param>
+               /// <param name="matchGroup">Two Options, capability, header</param>
+               /// <param name="matchName">Header Name</param>
+               /// <param name="matchPattern">Regular Expression Pattern</param>
+               public Identification(bool matchType, string matchGroup, string matchName, string matchPattern)
+               {
+                       this.MatchType = matchType;
+                       this.MatchGroup = matchGroup;
+                       this.MatchName = matchName;
+                       this.MatchPattern = matchPattern;
+                       RegexPattern = new System.Text.RegularExpressions.Regex(matchPattern);
+               }
+               /// <summary>
+               /// Builds a Match Object from the result of the regular expression
+               /// </summary>
+               /// <param name="Header">Header Value which the regular expression will evaluate.</param>
+               /// <returns>A Match object created from the regular expression and the passed in header.</returns>
+               public System.Text.RegularExpressions.Match Match(string Header)
+               {
+                       if (string.IsNullOrEmpty(Header) == false)
+                       {
+                               PatternMatch = RegexPattern.Match(Header);
+                               return PatternMatch;
+                       }
+                       else
+                       {
+                               PatternMatch = RegexPattern.Match(string.Empty);
+                               return PatternMatch;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public bool Success
+               {
+                       get
+                       {
+                               if (PatternMatch == null)
+                               {
+                                       throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+                               }
+                               if (MatchType == true)
+                               {
+                                       return PatternMatch.Success;
+                               }
+                               else
+                               {
+                                       return !PatternMatch.Success;
+                               }
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public bool HasCaptureGroups
+               {
+                       get
+                       {
+                               if (PatternMatch == null)
+                               {
+                                       throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+                               }
+                               if (PatternMatch.Groups.Count > 0)
+                               {
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="Template"></param>
+               /// <returns></returns>
+               public string Result(string Template)
+               {
+                       if (PatternMatch == null)
+                       {
+                               throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+                       }
+                       if (MatchType == true && PatternMatch.Success == true)
+                       {
+                               return PatternMatch.Result(Template);
+                       }
+                       return string.Empty;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public void Reset()
+               {
+                       PatternMatch = null;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string Name
+               {
+                       get
+                       {
+                               return this.MatchName;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string Group
+               {
+                       get
+                       {
+                               return this.MatchGroup;
+                       }
+               }
+               public string Pattern
+               {
+                       get
+                       {
+                               return MatchPattern;
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Node.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Node.cs
new file mode 100644 (file)
index 0000000..b7675b3
--- /dev/null
@@ -0,0 +1,1080 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+       internal class Node
+       {
+               #region Public Properties
+               /// <summary>
+               /// 
+               /// </summary>
+               public NodeType NameType
+               {
+                       get
+                       {
+                               return pName;
+                       }
+                       set
+                       {
+                               pName = value;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string Id
+               {
+                       get
+                       {
+                               return pId;
+                       }
+                       set
+                       {
+                               pId = value;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string ParentId
+               {
+                       get
+                       {
+                               return pParentID;
+                       }
+                       set
+                       {
+                               pParentID = value;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string RefId
+               {
+                       get
+                       {
+                               return pRefID;
+                       }
+                       set
+                       {
+                               pRefID = value;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string MarkupTextWriterType
+               {
+                       get
+                       {
+                               return pMarkupTextWriterType;
+                       }
+                       set
+                       {
+                               pMarkupTextWriterType = value;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public string FileName
+               {
+                       get
+                       {
+                               return pFileName;
+                       }
+                       set
+                       {
+                               pFileName = value;
+                       }
+               }
+               #endregion
+
+               private NodeType pName = NodeType.None;
+               private string pId = string.Empty;
+               private string pParentID = string.Empty;
+               private string pRefID = string.Empty;
+               private string pMarkupTextWriterType = string.Empty;
+               private string pFileName = string.Empty;
+
+               private System.Xml.XmlNode xmlNode;
+               private Identification[] Identification;
+               private Identification[] Capture;
+               private System.Collections.Specialized.NameValueCollection Capabilities;
+               private System.Collections.Specialized.NameValueCollection Adapter;
+               private System.Collections.Generic.List<string> ChildrenKeys;
+               private System.Collections.Generic.List<string> DefaultChildrenKeys;
+               private System.Collections.Generic.SortedList<string, nBrowser.Node> Children;
+               private System.Collections.Generic.SortedList<string, nBrowser.Node> DefaultChildren;
+               private System.Collections.Specialized.NameValueCollection sampleHeaders;
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="xmlNode"></param>
+               [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059")]
+               public Node(System.Xml.XmlNode xmlNode)
+               {
+                       this.xmlNode = xmlNode;
+                       this.ResetChildern();
+                       this.Reset();
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               internal Node()
+               {
+                       this.ResetChildern();
+                       Identification = new System.Web.Configuration.nBrowser.Identification[1];
+                       Identification[0] = new System.Web.Configuration.nBrowser.Identification(true, "header", "User-Agent", ".");
+                       this.Id = "[Base Node]";
+                       this.NameType = NodeType.Browser;
+
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="node"></param>
+               private void ProcessIdentification(System.Xml.XmlNode node)
+               {
+                       //I know not all of these will be used but enough will
+                       Identification = new System.Web.Configuration.nBrowser.Identification[node.ChildNodes.Count];
+
+                       int i = -1;
+                       for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+                       {
+                               switch (node.ChildNodes[a].NodeType)
+                               {
+                                       case System.Xml.XmlNodeType.Text:
+                                               continue;
+                                       case System.Xml.XmlNodeType.Comment:
+                                               continue;
+                               }
+
+                               string patterngroup = string.Empty;
+                               string patternname = string.Empty;
+
+                               if (string.Compare(node.ChildNodes[a].Name, "userAgent", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       patterngroup = "header";
+                                       patternname = "User-Agent";
+                               }
+                               else if (string.Compare(node.ChildNodes[a].Name, "header", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       patterngroup = node.ChildNodes[a].Name;
+                                       patternname = node.ChildNodes[a].Attributes["name"].Value;
+                               }
+                               else if (string.Compare(node.ChildNodes[a].Name, "capability", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       patterngroup = node.ChildNodes[a].Name;
+                                       patternname = node.ChildNodes[a].Attributes["name"].Value;
+                               }
+                               else
+                               {
+                                       throw new nBrowser.Exception("Invalid Node found in Identification");
+                               }
+
+                               if (node.ChildNodes[a].Attributes["match"] != null)
+                               {
+                                       i++;
+                                       Identification[i] = new System.Web.Configuration.nBrowser.Identification(true, patterngroup, patternname, node.ChildNodes[a].Attributes["match"].Value);
+                               }
+                               else if (node.ChildNodes[a].Attributes["nonMatch"] != null)
+                               {
+                                       i++;
+                                       Identification[i] = new System.Web.Configuration.nBrowser.Identification(false, patterngroup, patternname, node.ChildNodes[a].Attributes["nonMatch"].Value);
+                               }
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="node"></param>
+               private void ProcessCapture(System.Xml.XmlNode node)
+               {
+                       //I know not all of these will be used but enough will
+                       Capture = new System.Web.Configuration.nBrowser.Identification[node.ChildNodes.Count];
+
+                       int i = -1;
+                       for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+                       {
+                               switch (node.ChildNodes[a].NodeType)
+                               {
+                                       case System.Xml.XmlNodeType.Text:
+                                               continue;
+                                       case System.Xml.XmlNodeType.Comment:
+                                               continue;
+                               }
+
+                               string pattern = string.Empty;
+                               string patterngroup = string.Empty;
+                               string patternname = string.Empty;
+
+                               if (node.ChildNodes[a].Name == "userAgent")
+                               {
+                                       patterngroup = "header";
+                                       patternname = "User-Agent";
+                               }
+                               else
+                               {
+                                       patterngroup = node.ChildNodes[a].Name;
+                                       patternname = node.ChildNodes[a].Attributes["name"].Value;
+                               }
+                               pattern = node.ChildNodes[a].Attributes["match"].Value;
+                               i++;
+                               Capture[i] = new System.Web.Configuration.nBrowser.Identification(true, patterngroup, patternname, pattern);
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="node"></param>
+               private void ProcessCapabilities(System.Xml.XmlNode node)
+               {
+                       Capabilities = new System.Collections.Specialized.NameValueCollection(node.ChildNodes.Count);
+
+                       for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+                       {
+                               if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+                               {
+                                       continue;
+                               }
+                               string name = string.Empty;
+                               string value = string.Empty;
+                               for (int b = 0;b <= node.ChildNodes[a].Attributes.Count - 1;b++)
+                               {
+                                       switch (node.ChildNodes[a].Attributes[b].Name)
+                                       {
+                                               case "name":
+                                                       name = node.ChildNodes[a].Attributes[b].Value;
+                                                       break;
+                                               case "value":
+                                                       value = node.ChildNodes[a].Attributes[b].Value;
+                                                       break;
+                                       }
+                               }
+                               if (name.Length > 0)
+                               {
+                                       Capabilities[name] = value;
+                               }
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="node"></param>
+               private void ProcessControlAdapters(System.Xml.XmlNode node)
+               {
+                       Adapter = new System.Collections.Specialized.NameValueCollection();
+                       for (int b = 0;b <= node.Attributes.Count - 1;b++)
+                       {
+                               switch (node.Attributes[b].Name)
+                               {
+                                       case "markupTextWriterType":
+                                               MarkupTextWriterType = node.Attributes[b].Value;
+                                               break;
+                               }
+                       }
+                       for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+                       {
+                               if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+                               {
+                                       continue;
+                               }
+                               else if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Text)
+                               {
+                                       continue;
+                               }
+                               System.Xml.XmlNode x = node.ChildNodes[a];
+                               string controlType = string.Empty;
+                               string adapterType = string.Empty;
+                               for (int i = 0;i <= x.Attributes.Count - 1;i++)
+                               {
+                                       if (string.Compare(x.Attributes[i].Name, "controlType", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                                       {
+                                               controlType = x.Attributes[i].Value;
+                                       }
+                                       else if (string.Compare(x.Attributes[i].Name, "adapterType", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                                       {
+                                               adapterType = x.Attributes[i].Value;
+                                       }
+                               }
+                               if (controlType.Length > 0 && adapterType.Length > 0)
+                               {
+                                       Adapter[controlType] = adapterType;
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="node"></param>
+               private void ProcessSampleHeaders(System.Xml.XmlNode node)
+               {
+                       sampleHeaders = new System.Collections.Specialized.NameValueCollection(node.ChildNodes.Count);
+
+                       for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+                       {
+                               if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+                               {
+                                       continue;
+                               }
+                               string name = string.Empty;
+                               string value = string.Empty;
+                               for (int b = 0;b <= node.ChildNodes[a].Attributes.Count - 1;b++)
+                               {
+                                       switch (node.ChildNodes[a].Attributes[b].Name)
+                                       {
+                                               case "name":
+                                                       name = node.ChildNodes[a].Attributes[b].Value;
+                                                       break;
+                                               case "value":
+                                                       value = node.ChildNodes[a].Attributes[b].Value;
+                                                       break;
+                                       }
+                               }
+                               if (name.Length > 0)
+                               {
+                                       sampleHeaders[name] = value;
+                               }
+                       }
+               }
+               internal void ResetChildern()
+               {
+                       Children = new System.Collections.Generic.SortedList<string, nBrowser.Node>();
+                       DefaultChildren = new System.Collections.Generic.SortedList<string, nBrowser.Node>();
+                       ChildrenKeys = new System.Collections.Generic.List<string>();
+                       DefaultChildrenKeys = new System.Collections.Generic.List<string>();
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public bool HasChildren
+               {
+                       get
+                       {
+                               if (Children.Count > -1)
+                               {
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public void Reset()
+               {
+                       //Making sure we start off on a good footing.
+                       Capture = null;
+                       Capabilities = null;
+                       Adapter = null;
+                       if (string.Compare(this.xmlNode.Name, "browser", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                       {
+                               this.NameType = NodeType.Browser;
+                       }
+                       else if (string.Compare(this.xmlNode.Name, "defaultBrowser", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                       {
+                               this.NameType = NodeType.DefaultBrowser;
+                       }
+                       else if (string.Compare(this.xmlNode.Name, "gateway", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                       {
+                               this.NameType = NodeType.Gateway;
+                       }
+
+
+                       //-------------------------------------------------------------------------
+                       //Looping though the Attributes is easier since and more efficient
+                       //then doing finds for specific attribute names. This also handles the
+                       //cases where there are no attributes really well. Also it doesn't care
+                       //about the order in witch the attributes are found either
+                       //-------------------------------------------------------------------------
+                       for (int a = 0;a <= xmlNode.Attributes.Count - 1;a++)
+                       {
+                               //Reason I am not using a switch here because I do not have the ability
+                               //to make sure the items are in the same upper/lower case as I am expecting
+                               //so I default to ignore case and compare.
+                               if (string.Compare(xmlNode.Attributes[a].Name, "id", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       Id = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+                               }
+                               else if (string.Compare(xmlNode.Attributes[a].Name, "parentID", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ParentId = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+                               }
+                               else if (string.Compare(xmlNode.Attributes[a].Name, "refID", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       RefId = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+                               }
+                       }
+                       //I include bother upper and lower case so I do not run into trying to compare case and dealing
+                       //with CultureInfo stuff, Less hoops, should be faster I hope.
+                       const string values = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
+                       for (int a = 0;a <= Id.Length - 1;a++)
+                       {
+                               if (values.IndexOf(Id.Substring(a, 1)) == -1)
+                               {
+                                       throw new nBrowser.Exception("Invalid Charactors In ID name");
+                               }
+                       }
+                       for (int a = 0;a <= ParentId.Length - 1;a++)
+                       {
+                               if (values.IndexOf(ParentId.Substring(a, 1)) == -1)
+                               {
+                                       throw new nBrowser.Exception("Invalid Charactors In parentID name");
+                               }
+                       }
+                       for (int a = 0;a <= RefId.Length - 1;a++)
+                       {
+                               if (values.IndexOf(RefId.Substring(a, 1)) == -1)
+                               {
+                                       throw new nBrowser.Exception("Invalid Charactors In refID name");
+                               }
+                       }
+
+                       for (int a = 0;a <= xmlNode.ChildNodes.Count - 1;a++)
+                       {
+                               //Reason I am not using a switch here because I do not have the ability
+                               //to make sure the items are in the same upper/lower case as I am expecting
+                               //so I default to ignore case and compare.
+                               if (string.Compare(xmlNode.ChildNodes[a].Name, "identification", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ProcessIdentification(xmlNode.ChildNodes[a]);
+                               }
+                               else if (string.Compare(xmlNode.ChildNodes[a].Name, "capture", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ProcessCapture(xmlNode.ChildNodes[a]);
+                               }
+                               else if (string.Compare(xmlNode.ChildNodes[a].Name, "capabilities", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ProcessCapabilities(xmlNode.ChildNodes[a]);
+                               }
+                               else if (string.Compare(xmlNode.ChildNodes[a].Name, "controlAdapters", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ProcessControlAdapters(xmlNode.ChildNodes[a]);
+                               }
+                               else if (string.Compare(xmlNode.ChildNodes[a].Name, "sampleHeaders", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       ProcessSampleHeaders(xmlNode.ChildNodes[a]);
+                               }
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="child"></param>
+               public void AddChild(Node child)
+               {
+                       if (child == null)
+                       {
+                               return;
+                       }
+                       if (child.NameType == nBrowser.NodeType.Browser || child.NameType == nBrowser.NodeType.Gateway)
+                       {
+                               Children.Add(child.Id, child);
+                               ChildrenKeys.Add(child.Id);
+                       }
+                       else if (child.NameType == NodeType.DefaultBrowser)
+                       {
+                               DefaultChildren.Add(child.Id, child);
+                               DefaultChildrenKeys.Add(child.Id);
+                       }
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="child"></param>
+               public void RemoveChild(Node child)
+               {
+                       if (child == null)
+                       {
+                               return;
+                       }
+                       if (child.NameType == nBrowser.NodeType.Browser || child.NameType == nBrowser.NodeType.Gateway)
+                       {
+                               Children.Remove(child.Id);
+                               ChildrenKeys.Remove(child.Id);
+                       }
+                       else if (child.NameType == NodeType.DefaultBrowser)
+                       {
+                               DefaultChildren.Remove(child.Id);
+                               DefaultChildrenKeys.Remove(child.Id);
+                       }
+               }
+               
+               
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="header"></param>
+               /// <param name="result"></param>
+               /// <param name="List"></param>
+               /// <returns></returns>
+               internal nBrowser.Result Process(System.Collections.Specialized.NameValueCollection header, nBrowser.Result result, System.Collections.Generic.List<System.Web.Configuration.nBrowser.Identification> List)
+               {
+                       //----------------------------------------------------------------------
+                       //This is just coded over from MS version since if you pass in an empty
+                       //string for the key it returns the UserAgent header as a response.
+                       //----------------------------------------------------------------------
+                       result.AddCapabilities("", header["User-Agent"]);
+
+                       //this step shouldn't really be necessary, if it was checked
+                       //prior to calling this method, but we assume it hasn't and
+                       //recheck anyways.
+                       if (BrowserIdentification(header, result) == false)
+                       {
+                               return result;
+                       }
+                       #region Browser Identification Successfull
+                       //----------------------------------------------------------------------
+                       //By reaching this point, it either means there were no Identification 
+                       //items to be processed or that all the Identification items have been 
+                       //passed. So just for debuging I want to output this Groups unique ID.
+                       //----------------------------------------------------------------------
+                       result.AddTrack("[" + this.NameType + "]\t" + this.Id);
+
+                       //----------------------------------------------------------------------
+                       //Just adding all the Adapters to the current list.
+                       //----------------------------------------------------------------------
+                       if (Adapter != null)
+                       {
+                               for (int i = 0;i <= Adapter.Count - 1;i++)
+                               {
+                                       result.AddAdapter(Adapter.GetKey(i), Adapter[i]);
+                               }
+                       }
+
+                       //----------------------------------------------------------------------
+                       //Set the MarkupTextWriter in the result if set in this node.
+                       //----------------------------------------------------------------------
+                       if (MarkupTextWriterType != null && MarkupTextWriterType.Length > 0)
+                       {
+                               // Look for the type using a case-sensitive search
+                               result.MarkupTextWriter = Type.GetType(MarkupTextWriterType);
+                               // If we don't find it, try again using a case-insensitive search and throw
+                               // and exception if we can't find it.
+                               if (result.MarkupTextWriter == null)
+                                       result.MarkupTextWriter = Type.GetType(MarkupTextWriterType, true, true);
+                       }
+
+                       //----------------------------------------------------------------------
+                       //Adds all the Identifiction matches to the List of Identification
+                       //list.
+                       //----------------------------------------------------------------------
+                       if (this.NameType != NodeType.DefaultBrowser)
+                       {
+                               for (int i = 0;i <= Identification.Length - 1;i++)
+                               {
+                                       if (Identification[i].HasCaptureGroups == true)
+                                       {
+                                               List.Add(Identification[i]);
+                                       }
+                               }
+                       }
+                       #endregion
+                       #region Capture
+                       if (Capture != null)
+                       {
+                               //----------------------------------------------------------------------
+                               //Adds all the sucessfull Capture matches to the List of generic 
+                               //Identification list.
+                               //----------------------------------------------------------------------
+                               for (int i = 0;i <= Capture.Length - 1;i++)
+                               {
+                                       //shouldn't happen often, the null should
+                                       //signal the end of the list, I keep procssing
+                                       //the rest just in case
+                                       if (Capture[i] == null)
+                                       {
+                                               continue;
+                                       }
+                                       //take no chances get back to base state.
+                                       Capture[i].Reset();
+                                       if (Capture[i].Group == "header")
+                                       {
+                                               Capture[i].Match(header[Capture[i].Name]);
+                                       }
+                                       else if (Capture[i].Group == "capability")
+                                       {
+                                               Capture[i].Match(result[Capture[i].Name]);
+                                       }
+                                       if (Capture[i].Success == true && Capture[i].HasCaptureGroups == true)
+                                       {
+                                               List.Add(Capture[i]);
+                                       }
+                               }
+                       }
+                       #endregion
+                       #region Capabilities
+                       if (Capabilities != null)
+                       {
+                               //----------------------------------------------------------------------
+                               //This section is what the whole exercise is about. Determining
+                               //the Browser Capabilities. We know already that the current
+                               //browser matches the criteria, now its a mater of updating
+                               //the results with the new Capabilties listed.
+                               //----------------------------------------------------------------------
+                               for (int i = 0;i <= Capabilities.Count - 1;i++)
+                               {
+                                       //----------------------------------------------------------------------
+                                       //Most items do not have any regular expression in them
+                                       //so we can add them directly to the results.
+                                       //----------------------------------------------------------------------
+                                       if (Capabilities[i].IndexOf("$") == -1 && Capabilities[i].IndexOf("%") == -1)
+                                       {
+                                               result.AddCapabilities(Capabilities.Keys[i], Capabilities[i]);
+                                       }
+                                       else
+                                       {
+                                               //----------------------------------------------------------------------
+                                               //We need to further process these Capabilities to 
+                                               //insert the proper information.
+                                               //----------------------------------------------------------------------
+                                               string v = string.Empty;
+
+                                               //----------------------------------------------------------------------
+                                               //Loop though the list of Identifiction/Capture Matches
+                                               //in reverse order. Meaning the newest Items in the list
+                                               //get checked first, then working to the oldest. Often times
+                                               //Minor /Major revisition numbers will be listed multple times
+                                               //and only the newest one (most recent matches) are the ones
+                                               //we want to insert.
+                                               //----------------------------------------------------------------------
+                                               if (Capabilities[i].IndexOf("$") >= -1)
+                                               {
+                                                       for (int a = List.Count - 1;a >= 0;a--)
+                                                       {
+                                                               v = ((System.Web.Configuration.nBrowser.Identification)List[a]).Result(Capabilities[i]);
+                                                               //----------------------------------------------------------------------
+                                                               //exit the loop once we are able to extract a result.
+                                                               //----------------------------------------------------------------------
+                                                               if (v.Length > 0 && v.IndexOf("$") == -1)
+                                                               {
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               //----------------------------------------------------------------------
+                                               //Checks to make sure we extract the result we where looking for.
+                                               //----------------------------------------------------------------------
+                                               if (v.IndexOf("$") > -1 || v.IndexOf("%") > -1)
+                                               {
+                                                       //----------------------------------------------------------------------
+                                                       //Microsoft has a nasty habbit of using capability items in regular expressions
+                                                       //so I have to figure a nice way to working around it
+                                                       // <capability name="msdomversion"              value="${majorversion}${minorversion}" />
+                                                       //----------------------------------------------------------------------
+
+                                                       //double checks the values against the current Capabilities. to 
+                                                       //find any last minute matches. that are not defined by regluar
+                                                       //expressions
+                                                       v = result.Replace(v);
+                                               }
+
+                                               if (v.Length > 0 && v.IndexOf("$") == -1 && v.IndexOf("%") == -1)
+                                               {
+                                                       result.AddCapabilities(Capabilities.Keys[i], v);
+                                               }
+                                               else
+                                               {
+                                                       //----------------------------------------------------------------------
+                                                       //This happens pretty often, especially when mobile phone browsers
+                                                       //are in use, and different proxie servers send back varying amount
+                                                       //of details, when Items are missing, this will often pop.
+                                                       //----------------------------------------------------------------------
+                                                       //Console.WriteLine(this.Id +"\t"+v);
+                                               }
+                                       }
+                               }
+                       }
+                       #endregion
+                       if (Adapter != null)
+                       {
+                               for (int i = 0;i <= Adapter.Count - 1;i++)
+                               {
+                                       result.AddAdapter(Adapter.GetKey(i), Adapter[i]);
+                               }
+                       }
+                       //----------------------------------------------------------------------
+                       //Run the Default Children after the Parent Node is finished with 
+                       //what it is doing
+                       //----------------------------------------------------------------------
+                       for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+                       {
+                               string key = DefaultChildrenKeys[i];
+                               Node node = DefaultChildren[key];
+                               if (node.NameType == NodeType.DefaultBrowser)
+                               {
+                                       node.Process(header, result, List);
+                               }
+                       }
+                       //----------------------------------------------------------------------
+                       //processing all the children Browsers of this Parent if there are any.
+                       //----------------------------------------------------------------------
+                       //In nBrowser files, the Gateways should of been sorted so they are all 
+                       //at the top so that they can be ran first.
+                       //----------------------------------------------------------------------
+                       //According to the msdn2 documentation Gateways are suppost to be
+                       //all processed first. before the browser objects.
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == NodeType.Gateway)
+                               {
+                                       node.Process(header, result, List);
+                               }
+                       }
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == NodeType.Browser)
+                               {
+                                       if (node.BrowserIdentification(header, result) == true)
+                                       {
+                                               node.Process(header, result, List);
+                                               break;
+                                       }
+                               }
+                       }
+
+                       #region Remove Identification & Caputers from lists
+                       //----------------------------------------------------------------------
+                       //
+                       //---------------------------------------------------------------------
+                       if (Identification != null)
+                       {
+                               for (int i = 0;i <= Identification.Length - 1;i++)
+                               {
+                                       //shouldn't happen often, the null should
+                                       //signal the end of the list, I keep procssing
+                                       //the rest just in case
+                                       if (Identification[i] == null)
+                                       {
+                                               continue;
+                                       }
+                                       if (Identification[i].HasCaptureGroups == true)
+                                       {
+                                               List.Remove(Identification[i]);
+                                       }
+                               }
+                       }
+                       //----------------------------------------------------------------------
+                       //
+                       //---------------------------------------------------------------------
+                       if (Capture != null)
+                       {
+                               for (int i = 0;i <= Capture.Length - 1;i++)
+                               {
+                                       //shouldn't happen often, the null should
+                                       //signal the end of the list, I keep procssing
+                                       //the rest just in case
+                                       if (Capture[i] == null)
+                                       {
+                                               continue;
+                                       }
+                                       if (Capture[i].Success == true && Capture[i].HasCaptureGroups == true)
+                                       {
+                                               List.Remove(Capture[i]);
+                                       }
+                               }
+                       }
+                       #endregion
+
+                       return result;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="header"></param>
+               /// <param name="result"></param>
+               /// <returns></returns>
+               public bool BrowserIdentification(System.Collections.Specialized.NameValueCollection header, System.Web.Configuration.CapabilitiesResult result)
+               {
+                       if (Id.Length > 0 && RefId.Length > 0)
+                       {
+                               throw new nBrowser.Exception("Id and refID Attributes givin when there should only be one set not both");
+                       }
+                       if (RefId.Length > 0)
+                       {
+                               return true;
+                       }
+                       if (this.NameType == NodeType.DefaultBrowser)
+                       {
+                               return true;
+                       }
+                       if (Identification == null || Identification.Length == 0)
+                       {
+                               throw new nBrowser.Exception("Missing Identification Section where one is required");
+                       }
+                       if (header == null)
+                       {
+                               throw new nBrowser.Exception("Null Value where NameValueCollection expected ");
+                       }
+                       if (result == null)
+                       {
+                               throw new nBrowser.Exception("Null Value where Result expected ");
+                       }
+
+#if trace                         
+                       System.Diagnostics.Trace.WriteLine(string.Format("{0}[{1}]", ("[" + this.Id + "]").PadRight(45), this.ParentId));
+#endif
+
+                       for (int i = 0;i <= Identification.Length - 1;i++)
+                       {
+
+                               //shouldn't happen often, the null should
+                               //signal the end of the list, I keep procssing
+                               //the rest just in case
+                               if (Identification[i] == null)
+                               {
+                                       continue;
+                               }
+                               //take no chances get back to base state.
+                               Identification[i].Reset();
+                               string v = string.Empty;
+                               if (string.Compare(Identification[i].Group, "header", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       v = header[Identification[i].Name];
+                               }
+                               else if (string.Compare(Identification[i].Group, "capability", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+                               {
+                                       v = result[Identification[i].Name];
+                               }
+                               //Not all headers will be sent by all browsers.
+                               //so often a header search will return Null.
+                               if (v == null)
+                               {
+                                       v = string.Empty;
+                               }
+                               Identification[i].Match(v);
+                               //----------------------------------------------------------------------
+                               //we exit this method return the orginal Result back to  the calling method.
+                               //----------------------------------------------------------------------
+                               if (Identification[i].Success == false)
+                               {
+#if trace 
+                                       System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}", "Failed:".PadRight(45), Identification[i].Pattern));
+#endif
+                                       //just making sure to cleanup before we leave.
+                                       Identification[i].Reset();
+#if trace
+                                       System.Diagnostics.Trace.WriteLine("");
+#endif
+                                       return false;
+                               }
+                               else
+                               {
+#if trace 
+                                       System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}", "Passed:".PadRight(45), Identification[i].Pattern));
+#endif
+                               }
+                       }
+#if trace
+                       System.Diagnostics.Trace.WriteLine("");
+#endif
+                       return true;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public System.Collections.Specialized.NameValueCollection SampleHeader
+               {
+                       get
+                       {
+                               return sampleHeaders;
+                       }
+               }
+               /// <summary>
+               /// Used to Display a Tree Like View of how the Nodes are organized.
+               /// </summary>
+               /// <param name="writer"></param>
+               /// <param name="Position"></param>
+               public void Tree(System.Xml.XmlTextWriter xmlwriter, int position)
+               {
+                       if (position == 0)
+                       {
+                               xmlwriter.WriteStartDocument();
+                               xmlwriter.WriteStartElement(this.NameType.ToString());
+                               xmlwriter.WriteRaw(System.Environment.NewLine);
+                       }
+
+                       string f = this.FileName;
+                       f = f.Substring(f.LastIndexOfAny("\\".ToCharArray()) + 1);
+                       xmlwriter.WriteStartElement(this.NameType.ToString());
+                       xmlwriter.WriteAttributeString("FileName", f);
+                       xmlwriter.WriteAttributeString("ID", this.Id);
+                       xmlwriter.WriteRaw(System.Environment.NewLine);
+
+                       if (position != int.MaxValue)
+                       {
+                               position++;
+                       }
+                       for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+                       {
+                               string key = (string)DefaultChildrenKeys[i];
+                               Node node = DefaultChildren[key];
+                               if (node.NameType == nBrowser.NodeType.DefaultBrowser)
+                               {
+                                       node.Tree(xmlwriter, position);
+                               }
+                       }
+
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = (string)ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == nBrowser.NodeType.Gateway)
+                               {
+                                       node.Tree(xmlwriter, position);
+                               }
+                       }
+
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = (string)ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == nBrowser.NodeType.Browser)
+                               {
+                                       node.Tree(xmlwriter, position);
+                               }
+                       }
+                       if (position != int.MinValue)
+                       {
+                               position--;
+                       }
+                       xmlwriter.WriteEndElement();
+                       xmlwriter.WriteRaw(System.Environment.NewLine);
+                       if (position == 0)
+                       {
+                               xmlwriter.WriteEndDocument();
+                               xmlwriter.Flush();
+                       }
+               }
+               public System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list)
+               {
+                       if (Identification != null)
+                       {
+                               for (int i = 0;i <= Identification.Length - 1;i++)
+                               {
+                                       if (Identification[i] == null)
+                                       {
+                                               continue;
+                                       }
+                                       if (Identification[i].Group == "header")
+                                       {
+                                               if (list.Contains(Identification[i].Name) == false)
+                                               {
+                                                       list.Add(Identification[i].Name);
+                                               }
+                                       }
+                               }
+                       }
+                       if (Capture != null)
+                       {
+                               for (int i = 0;i <= Capture.Length - 1;i++)
+                               {
+                                       if (Capture[i] == null)
+                                       {
+                                               continue;
+                                       }
+                                       if (Capture[i].Group == "header")
+                                       {
+                                               if (list.Contains(Capture[i].Name) == false)
+                                               {
+                                                       list.Add(Capture[i].Name);
+                                               }
+                                       }
+                               }
+                       }
+                       for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+                       {
+                               string key = (string)DefaultChildrenKeys[i];
+                               Node node = DefaultChildren[key];
+                               if (node.NameType == nBrowser.NodeType.DefaultBrowser)
+                               {
+                                       list = node.HeaderNames(list);
+                               }
+                       }
+
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = (string)ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == nBrowser.NodeType.Gateway)
+                               {
+                                       list = node.HeaderNames(list);
+                               }
+                       }
+
+                       for (int i = 0;i <= Children.Count - 1;i++)
+                       {
+                               string key = (string)ChildrenKeys[i];
+                               Node node = Children[key];
+                               if (node.NameType == nBrowser.NodeType.Browser)
+                               {
+                                       list = node.HeaderNames(list);
+                               }
+                       }
+                       return list;
+               }
+               
+               /// <summary>
+               /// Merge capabilities, captures, markupTextWriters, and adapters from another Node into this Node.
+               /// </summary>
+               /// <param name="n">node to merge with this node</param>
+               public void MergeFrom(Node n)
+               {
+                       foreach (string capName in n.Capabilities)
+                               Capabilities[capName] = n.Capabilities[capName];
+                       
+                       int newLength = 0;
+                       if (Capture != null)
+                               newLength += Capture.Length;
+                       if (n.Capture != null)
+                               newLength += n.Capture.Length;
+                       Identification[] newCapture = new Identification[newLength];
+                       if (Capture != null)
+                               Array.Copy(Capture, 0, newCapture, 0, Capture.Length);
+                       if (n.Capture != null)
+                               Array.Copy(n.Capture, 0, newCapture, Capture.Length, n.Capture.Length);
+                       Capture = newCapture;
+                       
+                       if (n.MarkupTextWriterType != null && n.MarkupTextWriterType.Length > 0)
+                               MarkupTextWriterType = n.MarkupTextWriterType;
+                       
+                       foreach (string controlType in n.Adapter)
+                               Adapter[controlType] = n.Adapter[controlType];                  
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/NodeTypes.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
new file mode 100644 (file)
index 0000000..fbd95cf
--- /dev/null
@@ -0,0 +1,34 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+       internal enum NodeType
+       {
+               None = 0,
+               Browser = 1,
+               Gateway = 2,
+               DefaultBrowser = 3
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Result.cs b/mcs/class/System.Web/System.Web.Configuration_2.0/nBrowser/Result.cs
new file mode 100644 (file)
index 0000000..aff0129
--- /dev/null
@@ -0,0 +1,90 @@
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Text;
+
+       internal class Result : System.Web.Configuration.CapabilitiesResult
+       {
+               private System.Collections.Generic.Dictionary<Type, Type> AdapterTypeMap;
+               private System.Collections.Specialized.StringCollection Track;
+               internal Type MarkupTextWriter;
+
+               internal Result(System.Collections.Generic.Dictionary<string, string> items)
+                       : base(items)
+               {
+                       AdapterTypeMap = new System.Collections.Generic.Dictionary<Type, Type>();
+                       Track = new System.Collections.Specialized.StringCollection();
+                       MarkupTextWriter = typeof (System.Web.UI.HtmlTextWriter);
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="track"></param>
+               internal void AddTrack(string track)
+               {
+                       Track.Add(track);
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="controlTypeName"></param>
+               /// <param name="adapterTypeName"></param>
+               internal void AddAdapter(string controlTypeName, string adapterTypeName)
+               {
+                       Type controlType = System.Type.GetType(controlTypeName); // case-sensitive
+                       if (controlType == null)
+                               controlType = System.Type.GetType(controlTypeName, true, true); // case-insensitive, throw if not found
+                       Type adapterType = System.Type.GetType(adapterTypeName); // case-sensitive
+                       if (adapterType == null)
+                               adapterType = System.Type.GetType(adapterTypeName, true, true); // case-insensitive, throw if not found
+                               
+                       AdapterTypeMap[controlType] = adapterType;
+               }
+               /// <summary>
+               /// 
+               /// </summary>
+               public System.Collections.Specialized.StringCollection Tracks
+               {
+                       get
+                       {
+                               return Track;
+                       }
+               }
+               
+               internal override Type GetTagWriter ()
+               {
+                               return MarkupTextWriter;                        
+               }
+
+               internal override System.Collections.IDictionary GetAdapters ()
+               {
+                               return AdapterTypeMap;                  
+               }
+       }
+}
+#endif
index f7f5909a8dc650ad02f816601e0b63c3bc02a24a..65fd446c12b213a6e119ddc27bfc606ba95c30eb 100644 (file)
@@ -1,6 +1,20 @@
+2008-01-15  Dean Brettle <dean@brettle.com> 
+
+       * ControlAdapter.cs: made control field internal so
+       derived internal classes can access it without using base.Control
+       which can involved several typecasts.
+
+2008-01-12  Dean Brettle <dean@brettle.com> 
+
+       * PageAdapter.cs: implemented all members.
+       
+2008-01-07  Dean Brettle <dean@brettle.com> 
+
+       * ControlAdapter.cs: implemented all members.
+       
 2005-08-24  Chris Toshok  <toshok@ximian.com>
 
-       * PageAdapter.cs, ControlAdapter: add MonoTODO's.
+       * PageAdapter.cs, ControlAdapter.cs: add MonoTODO's.
 
 2005-08-18  Dick Porter  <dick@ximian.com>
 
index 2d5a7a019f3267b8dd70f5df94d2719be1189a32..7eddb8a33be7c350fc99e625388ae7a35daa8e33 100644 (file)
@@ -35,124 +35,114 @@ namespace System.Web.UI.Adapters
 {
        public abstract class ControlAdapter
        {
+               internal ControlAdapter (Control c)
+               {
+                       control = c;
+               }
+               
                protected ControlAdapter ()
                {
                }
 
-               [MonoTODO("Not implemented")]
                protected HttpBrowserCapabilities Browser 
                {
                        get {
-                               throw new NotImplementedException ();
+                               return Page.Request.Browser;
                        }
                }
 
-               [MonoTODO("Not implemented")]
+               internal Control control;
+               
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               protected Control Control 
+               protected internal Control Control 
                {
-                       get {
-                               throw new NotImplementedException ();
+                       protected get {
+                               return control;
+                       }
+                       set {
+                               control = value;
                        }
                }
 
-               [MonoTODO("Not implemented")]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
                protected Page Page 
                {
                        get {
-                               throw new NotImplementedException ();
+                               return Control.Page;
                        }
                }
                
-               [MonoTODO("Not implemented")]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
                protected PageAdapter PageAdapter 
                {
                        get {
-                               throw new NotImplementedException ();
+                               return Control.Page.PageAdapter;
                        }
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void BeginRender (HtmlTextWriter w)
                {
-                       throw new NotImplementedException ();
+                       w.BeginRender();
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void CreateChildControls ()
                {
-                       throw new NotImplementedException ();
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void EndRender (HtmlTextWriter w)
                {
-                       throw new NotImplementedException ();
+                       w.EndRender ();
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void LoadAdapterControlState (object state)
                {
-                       throw new NotImplementedException ();
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void LoadAdapterViewState (object state)
                {
-                       throw new NotImplementedException ();
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void OnInit (EventArgs e)
                {
-                       throw new NotImplementedException ();
+                       Control.OnInit(e);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void OnLoad (EventArgs e)
                {
-                       throw new NotImplementedException ();
+                       Control.OnLoad(e);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void OnPreRender (EventArgs e)
                {
-                       throw new NotImplementedException ();
+                       Control.OnPreRender(e);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void OnUnload (EventArgs e)
                {
-                       throw new NotImplementedException ();
+                       Control.OnUnload(e);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void Render (HtmlTextWriter w)
                {
-                       throw new NotImplementedException ();
+                       Control.Render (w);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual void RenderChildren (HtmlTextWriter w)
                {
-                       throw new NotImplementedException ();
+                       Control.RenderChildren (w);
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual object SaveAdapterControlState ()
                {
-                       throw new NotImplementedException ();
+                       return null;
                }
 
-               [MonoTODO("Not implemented")]
                protected internal virtual object SaveAdapterViewState ()
                {
-                       throw new NotImplementedException ();
+                       return null;
                }
        }
 }
index 6db9407b2d3a86b8d91af4a561e344b65f66c7ef..68deff7275f5be55347d09cbb3ae2b45615e0142 100644 (file)
@@ -40,90 +40,102 @@ namespace System.Web.UI.Adapters
                {
                }
 
-               [MonoTODO("Not implemented")]
-               public virtual StringCollection CacheVaryByHeaders 
+               internal PageAdapter (Page p) : base (p)
                {
-                       get {
-                               throw new NotImplementedException ();
-                       }
                }
 
-               [MonoTODO("Not implemented")]
-               public virtual StringCollection CacheVaryByParams 
-               {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+               public virtual StringCollection CacheVaryByHeaders {
+                       get { return null; }
+               }
+
+               public virtual StringCollection CacheVaryByParams {
+                       get { return null; }
                }
                
-               [MonoTODO("Not implemented")]
                protected string ClientState 
                {
                        get {
-                               throw new NotImplementedException ();
+                               return Page.GetSavedViewState ();
                        }
                }
                
-               [MonoTODO("Not implemented")]
                public virtual NameValueCollection DeterminePostBackMode ()
                {
-                       throw new NotImplementedException ();
+                       return Page.DeterminePostBackMode ();
                }
 
-               [MonoTODO("Not implemented")]
                public virtual ICollection GetRadioButtonsByGroup (string groupName)
                {
-                       throw new NotImplementedException ();
+                       if (radio_button_group == null)
+                               return new ArrayList();
+                       ArrayList radioButtons = (ArrayList) radio_button_group [groupName];
+                       if (radioButtons == null)
+                               return new ArrayList();
+                       return radioButtons;
                }
 
-               [MonoTODO("Not implemented")]
                public virtual PageStatePersister GetStatePersister ()
                {
-                       throw new NotImplementedException ();
+                       return new HiddenFieldPageStatePersister ((Page)Control);
                }
 
-               [MonoTODO("Not implemented")]
                public virtual void RegisterRadioButton (RadioButton radioButton)
                {
-                       throw new NotImplementedException ();
+                       if (radio_button_group == null)
+                               radio_button_group = new ListDictionary();
+                       ArrayList radioButtons = (ArrayList) radio_button_group [radioButton.GroupName];
+                       if (radioButtons == null)
+                               radio_button_group [radioButton.GroupName] = radioButtons = new ArrayList();
+                       if (!radioButtons.Contains(radioButton))
+                               radioButtons.Add(radioButton);
                }
 
-               [MonoTODO("Not implemented")]
                public virtual void RenderBeginHyperlink (HtmlTextWriter w,
                                                          string targetUrl,
                                                          bool encodeUrl,
                                                          string softKeyLabel)
                {
-                       throw new NotImplementedException ();
+                       InternalRenderBeginHyperlink (w, targetUrl, encodeUrl, softKeyLabel, null);
                }
 
-               [MonoTODO("Not implemented")]
                public virtual void RenderBeginHyperlink (HtmlTextWriter w,
                                                          string targetUrl,
                                                          bool encodeUrl,
                                                          string softKeyLabel,
                                                          string accessKey)
                {
-                       throw new NotImplementedException ();
+                       if (accessKey != null && accessKey.Length > 1)
+                               throw new ArgumentOutOfRangeException("accessKey");
+                       InternalRenderBeginHyperlink (w, targetUrl, encodeUrl, softKeyLabel, accessKey);
+               }
+               
+               void InternalRenderBeginHyperlink (HtmlTextWriter w,
+                                                  string targetUrl,
+                                                  bool encodeUrl,
+                                                  string softKeyLabel,
+                                                  string accessKey)
+               {
+                       w.AddAttribute (HtmlTextWriterAttribute.Href, targetUrl, encodeUrl);
+                       if (accessKey != null)
+                               w.AddAttribute (HtmlTextWriterAttribute.Accesskey, accessKey);
+                       w.RenderBeginTag (HtmlTextWriterTag.A);
                }
                
-               [MonoTODO("Not implemented")]
+               
                public virtual void RenderEndHyperlink (HtmlTextWriter w)
                {
-                       throw new NotImplementedException ();
+                       w.RenderEndTag();
                }
 
-               [MonoTODO("Not implemented")]
                public virtual void RenderPostBackEvent (HtmlTextWriter w,
                                                         string target,
                                                         string argument,
                                                         string softKeyLabel,
                                                         string text)
                {
-                       throw new NotImplementedException ();
+                       RenderPostBackEvent (w, target, argument, softKeyLabel, text, Page.Request.FilePath, null, true);
                }
 
-               [MonoTODO("Not implemented")]
                public virtual void RenderPostBackEvent (HtmlTextWriter w,
                                                         string target,
                                                         string argument,
@@ -132,10 +144,9 @@ namespace System.Web.UI.Adapters
                                                         string postUrl,
                                                         string accessKey)
                {
-                       throw new NotImplementedException ();
+                       RenderPostBackEvent (w, target, argument, softKeyLabel, text, postUrl, accessKey, true);
                }
 
-               [MonoTODO("Not implemented")]
                protected void RenderPostBackEvent (HtmlTextWriter w,
                                                    string target,
                                                    string argument,
@@ -145,20 +156,24 @@ namespace System.Web.UI.Adapters
                                                    string accessKey,
                                                    bool encode)
                {
-                       throw new NotImplementedException ();
+                       string url = String.Format ("{0}?__VIEWSTATE={1}&__EVENTTARGET={2}&__EVENTARGUMENT={3}&__PREVIOUSPAGE={4}",
+                               postUrl, HttpUtility.UrlEncode (Page.GetSavedViewState ()), target, argument, Page.Request.FilePath);
+                       RenderBeginHyperlink (w, url, encode, softKeyLabel, accessKey);
+                       w.Write(text);
+                       RenderEndHyperlink(w);
                }
 
-               [MonoTODO("Not implemented")]
                public virtual string TransformText (string text) 
                {
-                       throw new NotImplementedException ();
+                       return text;
                }
                
-               [MonoTODO("Not implemented")]
                protected internal virtual string GetPostBackFormReference (string formID)
                {
-                       throw new NotImplementedException ();
+                       return String.Format("document.forms['{0}']", formID);
                }
+               
+               private ListDictionary radio_button_group;
        }
 }
 #endif
index 361408ebb3b91f8f8b9707e28f24664eabfeedce..f187e39c23e79f34eb0f398635a0abacca825a39 100644 (file)
@@ -1,3 +1,29 @@
+2008-01-15  Dean Brettle <dean@brettle.com> 
+
+       * WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
+       DataBoundControlAdapter.cs: changed to use ControlAdapter.control
+       instead of using base.Control or using a new control field.
+       
+       * MenuAdapter.cs: added internal constructor that takes a Menu
+       parameter.  The constructor is used when writing unit tests.
+       
+       * MenuAdapter.cs (OnInit, OnPreRender, RenderBeginTag, 
+       RenderContents, RenderEndTag): delegate to base instead of
+       Control.
+       
+       * MenuAdapter.cs (LoadAdapterControlState, SaveAdapterControlState,
+       RaisePostBackEvent, RenderItem): implemented.
+       
+2008-01-13  Dean Brettle <dean@brettle.com> 
+
+       * WebControlAdapter.cs (RenderContents): changed to call 
+       control.RenderContents() instead of control.Render().
+       
+       * WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
+       DataBoundControlAdapter.cs, HideDisabledControlAdapter.cs: added
+       internal constructor that takes a parameter of the corresponding
+       Control type.  The construct is used when writing unit tests.
+
 2005-08-24  Chris Toshok  <toshok@ximian.com>
 
        * MenuAdapter.cs (OnInit): Call "Page.RegisterRequiresControlState
index ba1cb24061286a96a59cce51e24223b9d84cb543..40a69be17cf9dcabddc1e2227a765bc61ed192a4 100644 (file)
@@ -40,6 +40,10 @@ namespace System.Web.UI.WebControls.Adapters
                public DataBoundControlAdapter ()
                {
                }
+               
+               internal DataBoundControlAdapter (DataBoundControl c) : base (c)
+               {
+               }
 
                protected internal virtual void PerformDataBinding (IEnumerable data)
                {
@@ -49,7 +53,7 @@ namespace System.Web.UI.WebControls.Adapters
                protected new DataBoundControl Control
                {
                        get {
-                               return (DataBoundControl)base.Control;
+                               return (DataBoundControl)control;
                        }
                }
        }
index 7c99b5fafb36070887e322669e5b5baef6138bc5..437e836e5518673c636a626c512858287d1be61a 100644 (file)
@@ -40,6 +40,10 @@ namespace System.Web.UI.WebControls.Adapters
                {
                }
 
+               internal HideDisabledControlAdapter (WebControl c) : base (c)
+               {
+               }
+
                protected internal override void Render(HtmlTextWriter writer)
                {
                        if (!Control.IsEnabled)
index b92361a80377ea6af078c88614986e76b586bd65..77140d1185ce454f7b767bdcf0923f9d54939c93 100644 (file)
@@ -41,6 +41,10 @@ namespace System.Web.UI.WebControls.Adapters
                {
                }
 
+               internal HierarchicalDataBoundControlAdapter (HierarchicalDataBoundControl c) : base (c)
+               {
+               }
+
                protected internal virtual void PerformDataBinding ()
                {
                        Control.PerformDataBinding ();
@@ -49,7 +53,7 @@ namespace System.Web.UI.WebControls.Adapters
                protected new HierarchicalDataBoundControl Control
                {
                        get {
-                               return (HierarchicalDataBoundControl)base.Control;
+                               return (HierarchicalDataBoundControl)control;
                        }
                }
        }
index 9c2a5a0ddaec1c02c2604f21891ea17e456926bf..0ba1e9ea583b8dcfc5b20e0267e39722dd960e29 100644 (file)
@@ -39,76 +39,66 @@ namespace System.Web.UI.WebControls.Adapters
                public MenuAdapter () 
                {
                }
-
-               protected internal override void OnInit(EventArgs e)
+               
+               internal MenuAdapter (Menu c) : base (c)
                {
-                       /* registers the associated control as one that requires control state */
-                       Page.RegisterRequiresControlState (Control);
+               }
 
-                       /* and calls control.OnInit */
-                       Control.OnInit (e);
+               protected internal override void OnInit (EventArgs e)
+               {
+                       base.OnInit (e);
                }
 
                protected internal override void OnPreRender(EventArgs e)
                {
-                       Control.OnPreRender (e);
+                       base.OnPreRender (e);
                }
 
-               [MonoTODO]
                protected virtual void RaisePostBackEvent (string eventArgument)
                {
-                       throw new NotImplementedException ();
+                       Control.RaisePostBackEvent (eventArgument);
                }
 
                protected override void RenderBeginTag (HtmlTextWriter writer)
                {
-                       Control.RenderBeginTag (writer);
+                       base.RenderBeginTag (writer);
                }
 
                protected override void RenderContents (HtmlTextWriter writer)
                {
-                       // FIXME: we need to iterate over the
-                       // MenuItems here, calling
-                       // MenuAdapter.RenderItem for each one.
-                       
-                       Control.RenderContents (writer);
+                       base.RenderContents (writer);
                }
 
                protected override void RenderEndTag (HtmlTextWriter writer)
                {
-                       Control.RenderEndTag (writer);
+                       base.RenderEndTag (writer);
                }
 
-               [MonoTODO ("Not implemented")]
                protected internal virtual void RenderItem (HtmlTextWriter writer, 
                                                            MenuItem item,
                                                            int position)
                {
-                       throw new NotImplementedException ();
+                       Control.RenderItem (writer, item, position);
                }
          
-               [MonoTODO ("Not implemented")]
                protected internal override void LoadAdapterControlState (object state)
                {
-                       throw new NotImplementedException ();
                }
                    
-               [MonoTODO ("Not implemented")]
                protected internal override object SaveAdapterControlState ()
                {
-                       throw new NotImplementedException ();
+                       return null;
                }
 
-               [MonoTODO ("Not implemented")]
-               void System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
+               void System.Web.UI.IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
                {
-                       throw new NotImplementedException ();
+                       RaisePostBackEvent (eventArgument);
                }
 
                protected new Menu Control
                {
                        get {
-                               return (Menu)base.Control;
+                               return (Menu)control;
                        }
                }
        }
index eebea6d28e9a6fc13bf39177195aff91ac35a866..ababeae304fff945fda59e823681bc10c88ab1cc 100644 (file)
@@ -37,7 +37,11 @@ namespace System.Web.UI.WebControls.Adapters
 {
        public class WebControlAdapter : ControlAdapter
        {
-               public WebControlAdapter()
+               public WebControlAdapter ()
+               {
+               }
+               
+               internal WebControlAdapter (WebControl wc) : base (wc)
                {
                }
 
@@ -50,34 +54,32 @@ namespace System.Web.UI.WebControls.Adapters
 
                protected virtual void RenderBeginTag (HtmlTextWriter writer)
                {
-                       control.RenderBeginTag (writer);
+                       Control.RenderBeginTag (writer);
                }
 
                protected virtual void RenderContents(HtmlTextWriter writer)
                {
-                       control.Render (writer);
+                       Control.RenderContents (writer);
                }
 
                protected virtual void RenderEndTag(HtmlTextWriter writer)
                {
-                       control.RenderEndTag (writer);
+                       Control.RenderEndTag (writer);
                }
 
                protected new WebControl Control
                {
                        get {
-                               return control;
+                               return (WebControl)control;
                        }
                }
 
                protected bool IsEnabled
                {
                        get {
-                               return control.IsEnabled;
+                               return Control.IsEnabled;
                        }
                }
-
-               WebControl control;
        }
 }
 
index c8f2492f8dcb007e24e95d5b41857d45ef1d6e4c..492bfa80cf0162bb1a5a422e3d06a00df633c209 100644 (file)
@@ -1,3 +1,17 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * DetailsView.cs, ListControl.cs, DataBoundControl.cs, 
+       FormView.cs, HierarchicalDataBoundControl.cs, WebControl.cs: 
+       added support for using ControlAdapters when present.
+       
+       * WebControl.cs: fixed implementation of IsEnabled to match 
+       documentation.
+
+       * Menu.cs (RenderMenuBody): call Adapter.RenderItem() instead of 
+       RenderMenuItem() if an adapter is present.  MenuAdapter.RenderItem() 
+       calls back to new Menu.RenderItem() internal method which calls
+       RenderMenuItem() with the appropriate parameters.
+
 2008-02-25 Igor Zelmanovich <igorz@mainsoft.com>
 
        * GridView.cs:
index effe4db403792c7a6fab4d90d2b1973e67d5a100..9bca8ab5c82f4d54c3b31cc78852f3512c92856c 100644 (file)
@@ -37,6 +37,7 @@ using System.Text;
 using System.Web.Util;
 using System.ComponentModel;
 using System.Security.Permissions;
+using System.Web.UI.WebControls.Adapters;
 
 namespace System.Web.UI.WebControls {
 
@@ -218,7 +219,16 @@ namespace System.Web.UI.WebControls {
                        }
                        // The PerformDataBinding method binds the data in the  
                        // retrievedData collection to elements of the data-bound control.
-                       PerformDataBinding (data);
+                       InternalPerformDataBinding (data);
+               }
+               
+               protected void InternalPerformDataBinding (IEnumerable data)
+               {
+                       DataBoundControlAdapter adapter = (DataBoundControlAdapter)Adapter;
+                       if (adapter != null)
+                               adapter.PerformDataBinding (data);
+                       else
+                               PerformDataBinding (data);
                }
                
                protected virtual DataSourceSelectArguments CreateDataSourceSelectArguments ()
index b743883e0f393a76f1cd6a49d2f9facdd452a4cf..5649bc9aca20e9c361a39074a3a8e49f328f1443 100644 (file)
@@ -1217,7 +1217,7 @@ namespace System.Web.UI.WebControls
                                if (RequiresDataBinding) {\r
                                        OnDataBinding (EventArgs.Empty);\r
                                        RequiresDataBinding = false;\r
-                                       PerformDataBinding (null);\r
+                                       InternalPerformDataBinding (null);\r
                                        MarkAsDataBound ();\r
                                        OnDataBound (EventArgs.Empty);\r
                                }\r
index 55a8c5ddede8e6e91df6576cf0cd71a440005602..b988401eaeb327e7602610aac4b2186b83c3dd69 100644 (file)
@@ -865,7 +865,7 @@ namespace System.Web.UI.WebControls
                                if (RequiresDataBinding) {
                                        OnDataBinding (EventArgs.Empty);
                                        RequiresDataBinding = false;
-                                       PerformDataBinding (null);
+                                       InternalPerformDataBinding (null);
                                        MarkAsDataBound ();
                                        OnDataBound (EventArgs.Empty);
                                }
index 79fb2c2dd2b2eccc893782e79c3d415b4b2c84f9..aaaae941b42a52e4cb20efdc6f918e88ddacafe6 100644 (file)
@@ -31,6 +31,7 @@
 #if NET_2_0
 using System.Collections;
 using System.ComponentModel;
+using System.Web.UI.WebControls.Adapters;
 
 namespace System.Web.UI.WebControls
 {
@@ -133,6 +134,16 @@ namespace System.Web.UI.WebControls
                        Initialize ();
                }
                
+               protected void InternalPerformDataBinding ()
+               {
+                       HierarchicalDataBoundControlAdapter adapter 
+                               = (HierarchicalDataBoundControlAdapter)Adapter;
+                       if (adapter != null)
+                               adapter.PerformDataBinding ();
+                       else
+                               PerformDataBinding ();
+               }
+               
                protected internal virtual void PerformDataBinding ()
                {
                }
@@ -140,7 +151,7 @@ namespace System.Web.UI.WebControls
                protected override void PerformSelect ()
                {
                        OnDataBinding (EventArgs.Empty);
-                       PerformDataBinding ();
+                       InternalPerformDataBinding ();
                        // The PerformDataBinding method has completed.
                        RequiresDataBinding = false;
                        MarkAsDataBound ();
index 8a758cbf26f0dd45b3faa32c87f1a3e5782a8dfd..b9f5a9e22658092413f0c867cb55583462e24d12 100644 (file)
@@ -393,10 +393,11 @@ namespace System.Web.UI.WebControls {
 
 #if !NET_2_0
                        IEnumerable list = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
+                       PerformDataBinding (list);
 #else
                        IEnumerable list = GetData ().ExecuteSelect (DataSourceSelectArguments.Empty);
+                       InternalPerformDataBinding (list);
 #endif
-                       PerformDataBinding (list);
 
                }
 
index 9ec7e0cc4f0303172e4e4fe08b48087109f0a6d6..afd0e7d20bea54afe49dc945b8bd5478ada36d36 100644 (file)
@@ -1571,7 +1571,11 @@ namespace System.Web.UI.WebControls
                        int count = items.Count;
                        for (int n = 0; n < count; n++) {
                                MenuItem item = items [n];
-                               RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
+                               Adapters.MenuAdapter adapter = Adapter as Adapters.MenuAdapter;
+                               if (adapter != null)
+                                       adapter.RenderItem (writer, item, n);
+                               else
+                                       RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
                        }
 
                        if (!vertical)
@@ -1606,6 +1610,23 @@ namespace System.Web.UI.WebControls
                        return "javascript:Menu_" + handlerName + "('" + param1 + "','" + param2 + "'," + param3 + ")";
                }
                
+               internal void RenderItem (HtmlTextWriter writer, MenuItem item, int position) {
+                       // notLast should be true if item or any of its ancestors is not a
+                       // last child.
+                       bool notLast = false;
+                       MenuItem parent;
+                       MenuItem child = item;                  
+                       while (null != (parent = child.Parent)) {
+                               if (child.Index != parent.ChildItems.Count - 1) {
+                                       notLast = true;
+                                       break;
+                               }
+                               child = parent;
+                       }
+                       
+                       RenderMenuItem (writer, item, notLast, position == 0);
+               }
+               
                void RenderMenuItem (HtmlTextWriter writer, MenuItem item, bool notLast, bool isFirst) {
                        bool displayChildren = DisplayChildren (item);
                        bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels);
index 1213fdd3045880cb8b77c6a4062840a8f75ee577..a09a225b043fe93c46731a4d28e17614814268a6 100644 (file)
@@ -408,16 +408,13 @@ namespace System.Web.UI.WebControls {
                protected internal bool IsEnabled 
                {
                        get {
-                               if (Enabled)
-                                       return true;
-                               if(!HasControls())
-                                       return false;
-                               for (int i = 0; i < Controls.Count; i++) {
-                                       WebControl wc = Controls [i] as WebControl;
-                                       if (wc != null && wc.IsEnabled)
-                                               return true;
+                               WebControl wc = this;
+                               while (wc != null) {
+                                       if (!wc.Enabled)
+                                               return false;
+                                       wc = wc.Parent as WebControl;
                                }
-                               return false;
+                               return true;
                        }
                }
 #endif         
@@ -577,6 +574,13 @@ namespace System.Web.UI.WebControls {
 #endif         
                override void Render (HtmlTextWriter writer)
                {
+#if NET_2_0
+                       if (Adapter != null) {
+                               Adapters.WebControlAdapter wca = (Adapters.WebControlAdapter) Adapter;
+                               wca.Render(writer);
+                               return;
+                       }
+#endif
                        RenderBeginTag (writer);
                        RenderContents (writer);
                        RenderEndTag (writer);
index e8cdd11b6f5ef645857c53533827970d3b66d4b1..3d8140573dc64cd2d2317e30d3c24b34f4f3e3ee 100644 (file)
@@ -1,3 +1,32 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * Page.cs (SavePageControlState, LoadPageControlState): save/load 
+       adapter state in 2.0 profile.
+       
+       * Page.cs (CreateHtmlTextWriter): call Browser.CreateHtmlTextWriter()
+       in 2.0 profile.
+       
+       * Page.cs (RenderPage): call CreateHtmlTextWriter() to get the writer
+       in 2.0 profile.
+       
+       * Page.cs (DeterminePostBackMode, InitOutputCache, 
+       RenderClientScriptFormDeclaration,      InternalProcessRequest,
+       PageStatePersister): added support for PageAdapters.
+
+       * Control.cs (Adapter, ResolveAdapter): implemented.  Adapter calls
+       ResolveAdapter and remembers result.  ResolveAdapter checks for adapters
+       of the Type hierarchy until it finds one.
+       
+       * Control.cs (SaveViewStateRecursive, LoadViewStateRecursive): save/load
+       adapter state in 2.0 profile.
+       
+       * HtmlTextWriter.cs (BeginRender, EndRender): added empty virtual methods
+       required by 2.0 profile.  These are called by corresponding methods of
+       System.Web.UI.Adapters.ControlAdapter.
+       
+       * Page.cs, Control.cs: don't access Request.Browser if it couldn't have
+       any adapters/writers because there are no files in App_Browsers/.
+
 2008-03-09  Marek Habersack  <mhabersack@novell.com>
 
        * TemplateControlParser.cs: 2.0 allows controls with extensions
index d193d875ce9c60edb164aef3bb71498183246ea6..421070e06fc353889888e5c132e1566a3ca12a48 100644 (file)
@@ -153,17 +153,20 @@ namespace System.Web.UI
                }
 
 #if NET_2_0
-               [MonoTODO ("Not implemented, always returns null")]
-               protected ControlAdapter Adapter {
+               private ControlAdapter adapter = null;
+               private bool has_adapter = true;
+               protected internal ControlAdapter Adapter {
                        get {
-                               // for the time being, fool the
-                               // Control machinery into thinking we
-                               // don't have an Adapter.  This will
-                               // allow us to write all the rest of
-                               // the Adapter handling code without
-                               // having to worry about *having*
-                               // adapters.
-                               return null;
+                               if (has_adapter) {
+                                       if (adapter == null) {
+                                               adapter = ResolveAdapter();
+                                       }
+                                       if (adapter == null)
+                                               has_adapter = false;
+                                       else
+                                               adapter.Control = this;
+                               }
+                               return adapter;
                        }
                }
 
@@ -1119,7 +1122,25 @@ namespace System.Web.UI
 #if NET_2_0
                protected virtual ControlAdapter ResolveAdapter ()
                {
-                       throw new NotImplementedException ();
+                       if (Context == null)
+                               return null;
+
+                       if (!Context.Request.BrowserMightHaveAdapters)
+                               return null;
+                               
+                       // Search up the type hierarchy until we find a control with an adapter.
+                       Type adapterType = null;
+                       Type controlType = GetType();
+                       IDictionary typeMap = Context.Request.Browser.Adapters;
+                       while (adapterType == null && controlType != typeof(object)) {
+                               adapterType = (Type)typeMap [controlType];
+                               controlType = controlType.BaseType;
+                       }
+
+                       ControlAdapter a = null;
+                       if (adapterType != null)
+                               a = (ControlAdapter)Activator.CreateInstance (adapterType);
+                       return a;
                }
 #endif
 
@@ -1575,7 +1596,13 @@ namespace System.Web.UI
                                }
                        }
 
+#if NET_2_0
+                       object thisAdapterViewState = null;
+                       if (Adapter != null)
+                               thisAdapterViewState = Adapter.SaveAdapterViewState ();
+#endif
                        object thisState = SaveViewState ();
+
                        if (thisState == null && controlList == null && controlStates == null) {
                                if (trace != null) {
 #if MONO_TRACE
@@ -1592,6 +1619,9 @@ namespace System.Web.UI
 #endif
                                trace.SaveViewState (this, thisState);
                        }
+#if NET_2_0
+                       thisState = new object[] { thisState, thisAdapterViewState };
+#endif
                        return new Triplet (thisState, controlList, controlStates);
                }
 
@@ -1609,7 +1639,14 @@ namespace System.Web.UI
                        }
 #endif
                        Triplet savedInfo = (Triplet) savedState;
+#if NET_2_0
+                       object[] controlAndAdapterViewStates = (object [])savedInfo.First;
+                       if (Adapter != null)
+                               Adapter.LoadAdapterViewState (controlAndAdapterViewStates [1]);
+                       LoadViewState (controlAndAdapterViewStates [0]);
+#else
                        LoadViewState (savedInfo.First);
+#endif
 
                        ArrayList controlList = savedInfo.Second as ArrayList;
                        if (controlList == null)
index 724132646a101cdbfada9b739bba1f9a7b87c82d..7c65ea3e954b5735c382387ec20ff6da79fbb9bf 100644 (file)
@@ -1224,7 +1224,14 @@ namespace System.Web.UI {
                {
                        throw new NotImplementedException ();
                }
+               
+               public virtual void BeginRender ()
+               {
+               }
 
+               public virtual void EndRender ()
+               {
+               }
 #endif
        }
-}
\ No newline at end of file
+}
index 00ab93a18e8e5ea37145d4d5690c1404527e6104..7fb719d7f4b1d02fa432aab324cb9763b593fd4f 100644 (file)
@@ -814,7 +814,12 @@ public partial class Page : TemplateControl, IHttpHandler
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected virtual HtmlTextWriter CreateHtmlTextWriter (TextWriter tw)
        {
-               return new HtmlTextWriter (tw);
+#if NET_2_0
+               if (Request.BrowserMightHaveSpecialWriter)
+                       return Request.Browser.CreateHtmlTextWriter(tw);
+               else
+#endif
+                       return new HtmlTextWriter (tw);
        }
 
        [EditorBrowsable (EditorBrowsableState.Never)]
@@ -824,7 +829,11 @@ public partial class Page : TemplateControl, IHttpHandler
        }
 
        [EditorBrowsable (EditorBrowsableState.Advanced)]
-       protected virtual NameValueCollection DeterminePostBackMode ()
+       protected 
+#if NET_2_0
+       internal
+#endif
+       virtual NameValueCollection DeterminePostBackMode ()
        {
                // if request was transfered from other page such Transfer
                if (_context.IsProcessingInclude)
@@ -1015,6 +1024,19 @@ public partial class Page : TemplateControl, IHttpHandler
                                foreach (string h in hdrs)
                                        cache.VaryByHeaders [h.Trim ()] = true;
                        }
+#if NET_2_0
+                       if (PageAdapter != null)
+                       {
+                               if (PageAdapter.CacheVaryByParams != null) {
+                                       foreach (string p in PageAdapter.CacheVaryByParams)
+                                               cache.VaryByParams [p] = true;
+                               }
+                               if (PageAdapter.CacheVaryByHeaders != null) {
+                                       foreach (string h in PageAdapter.CacheVaryByHeaders)
+                                               cache.VaryByHeaders [h] = true;
+                               }
+                       }
+#endif
                }
                        
                cache.Duration = duration;
@@ -1126,8 +1148,15 @@ public partial class Page : TemplateControl, IHttpHandler
 
        void RenderClientScriptFormDeclaration (HtmlTextWriter writer, string formUniqueID)
        {
-               writer.WriteLine ("\tvar {0};\n\tif (document.getElementById) {{ {0} = document.getElementById ('{1}'); }}", theForm, formUniqueID);
-               writer.WriteLine ("\telse {{ {0} = document.{1}; }}", theForm, formUniqueID);
+#if NET_2_0
+               if (PageAdapter != null) {
+                       writer.WriteLine ("\tvar {0} = {1};\n", theForm, PageAdapter.GetPostBackFormReference(formUniqueID));
+               } else
+#endif
+               {
+                       writer.WriteLine ("\tvar {0};\n\tif (document.getElementById) {{ {0} = document.getElementById ('{1}'); }}", theForm, formUniqueID);
+                       writer.WriteLine ("\telse {{ {0} = document.{1}; }}", theForm, formUniqueID);
+               }
 #if TARGET_J2EE
                // TODO implement callback on portlet
                string serverUrl = Request.RawUrl;
@@ -1427,7 +1456,15 @@ public partial class Page : TemplateControl, IHttpHandler
 
        void InternalProcessRequest ()
        {
-               _requestValueCollection = this.DeterminePostBackMode();
+#if NET_2_0
+               if (PageAdapter != null) {
+                       _requestValueCollection = PageAdapter.DeterminePostBackMode();
+               }
+               else
+#endif
+               {
+                       _requestValueCollection = this.DeterminePostBackMode();
+               }
 
 #if NET_2_0
                // http://msdn2.microsoft.com/en-us/library/ms178141.aspx
@@ -1617,7 +1654,7 @@ public partial class Page : TemplateControl, IHttpHandler
                
                //--
                Trace.Write ("aspx.page", "Begin Render");
-               HtmlTextWriter output = new HtmlTextWriter (Response.Output);
+               HtmlTextWriter output = CreateHtmlTextWriter (Response.Output);
                RenderControl (output);
                Trace.Write ("aspx.page", "End Render");
        }
@@ -1840,6 +1877,10 @@ public partial class Page : TemplateControl, IHttpHandler
 #endif
        PageStatePersister PageStatePersister {
                get {
+#if NET_2_0
+                       if (page_state_persister == null && PageAdapter != null)
+                                       page_state_persister = PageAdapter.GetStatePersister();                                 
+#endif
                        if (page_state_persister == null)
 #if TARGET_J2EE
                                if (getFacesContext () != null)
@@ -2684,9 +2725,9 @@ public partial class Page : TemplateControl, IHttpHandler
        {
                if (requireStateControls == null) return null;
                object[] state = new object [requireStateControls.Count];
-               
+               object[] adapterState = new object [requireStateControls.Count];
                bool allNull = true;
-               for (int n=0; n<state.Length; n++) {
+               for (int n=0; n<requireStateControls.Count; n++) {
                        state [n] = ((Control) requireStateControls [n]).SaveControlState ();
                        if (state [n] != null) allNull = false;
                        
@@ -2694,21 +2735,31 @@ public partial class Page : TemplateControl, IHttpHandler
                        if (trace != null)
                                trace.SaveControlState ((Control) requireStateControls [n], state [n]);
 
+                       ControlAdapter adapter = ((Control) requireStateControls [n]).Adapter;
+                       if (adapter != null)
+                               adapterState [n] = adapter.SaveAdapterControlState ();
+                       if (adapterState [n] != null) allNull = false;
                }
                if (allNull) return null;
-               else return state;
+               else return new Pair (state, adapterState);
        }
        
        void LoadPageControlState (object data)
        {
-               _savedControlState = (object []) data;
-               
+               _savedControlState = null;
+               if (data == null) return;
+               Pair statePair = (Pair)data;
+               _savedControlState = (object[]) statePair.First;
+               object[] adapterState = (object[]) statePair.Second;
+
                if (requireStateControls == null) return;
 
-               int max = Math.Min (requireStateControls.Count, _savedControlState != null ? _savedControlState.Length : requireStateControls.Count);
-               for (int n=0; n < max; n++) {
+               int min = Math.Min (requireStateControls.Count, _savedControlState != null ? _savedControlState.Length : requireStateControls.Count);
+               for (int n=0; n < min; n++) {
                        Control ctl = (Control) requireStateControls [n];
                        ctl.LoadControlState (_savedControlState != null ? _savedControlState [n] : null);
+                       if (ctl.Adapter != null)
+                               ctl.Adapter.LoadAdapterControlState (adapterState != null ? adapterState [n] : null);
                }
        }
 
index 5cc93855616dce2f04fa46f839821c0e3f584c7f..a42227abe709fe12ae814dfb39a3efab9ddd952a 100644 (file)
@@ -2,6 +2,17 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/Locale.cs
 ../../build/common/MonoTODOAttribute.cs
+System.Web.Configuration_2.0/CapabilitiesBuild.cs
+System.Web.Configuration_2.0/CapabilitiesChecksum.cs
+System.Web.Configuration_2.0/CapabilitiesResult.cs
+System.Web.Configuration_2.0/ICapabilitiesProcess.cs
+System.Web.Configuration_2.0/nBrowser/Result.cs
+System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
+System.Web.Configuration_2.0/nBrowser/Identification.cs
+System.Web.Configuration_2.0/nBrowser/File.cs
+System.Web.Configuration_2.0/nBrowser/Build.cs
+System.Web.Configuration_2.0/nBrowser/Node.cs
+System.Web.Configuration_2.0/nBrowser/Exception.cs
 System.Web/ApplicationShutdownReason.cs
 System.Web/BeginEventHandler.cs
 System.Web.Caching/AggregateCacheDependency.cs
@@ -1154,4 +1165,3 @@ System.Web/WebPageTraceListener.cs
 System.Web/WebROCollection.cs
 System.Web/WebSysDescriptionAttribute.cs
 System.Web/XmlSiteMapProvider.cs
-
index 2b02461d64d50f3176652ad55d42822d3f2c1790..4b0811ce94356fb00a9128ab980520a585401b95 100644 (file)
@@ -150,7 +150,7 @@ namespace System.Web {
                const int HaveSupportsUncheck = 102;
                const int HaveSupportsXmlHttp = 103;
                const int HaveTables = 104; // 18;
-               //const int HaveTagWriter = 105; // 19;
+               const int HaveTagWriter = 105; // 19;
                const int HaveType = 106;
                const int HaveUseOptimizedCacheKey = 107;
                const int HaveVBScript = 108; // 20;
@@ -179,7 +179,7 @@ namespace System.Web {
                Version msDomVersion;
                string platform;
                bool tables;
-               //Type tagWriter;
+               Type tagWriter;
                bool vbscript;
                string version;
                Version w3CDomVersion;
@@ -422,9 +422,18 @@ namespace System.Web {
 
                public Type TagWriter {
                        get {
-                               return typeof (HtmlTextWriter);
+                               if (!Get (HaveTagWriter)) {
+                                       tagWriter = GetTagWriter ();
+                                       Set (HaveTagWriter);
+                               }
+                               return tagWriter;
                        }
                }
+               
+               internal virtual Type GetTagWriter ()
+               {
+                               return typeof (HtmlTextWriter);                 
+               }
 
                public string Type {
                        get {
index 3bebfd8babd142c61d218a232c5c0c3daf896da8..6c83dad1939caed17ea708928031b696e7072343 100644 (file)
@@ -1,3 +1,19 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * HttpApplicationFactory.cs: Added support for detecting 
+       App_Browsers/*.browser files and using them to determine capabilities.
+       Also restart the app if the App_Browsers, App_Code, or App_GlobalResources
+       directories are created.
+
+       * BrowserCapabilities.cs (TagWriter): get value via internal virtual
+       GetTagWriter() method, which is overridden in nBrowser.Result.
+
+       * HttpRequest.cs (BrowserMightHaveSpecialWriter, BrowserMightHaveAdapters):
+       internal properties added to allow Page and Control methods to avoid
+       accessing Request.Browser to get browser-specific HtmlTextWriters or 
+       ControlAdapters.  Those things only exist when there are App_Browsers
+       files.
+
 2008-03-09  Marek Habersack  <mhabersack@novell.com>
 
        * HttpUtility.cs: HTML-decode the query string prior to parsing
index be39334a72820c9b72db633d186a85d22a334809..69eedb38150f9fe620ef54a467d49f3e8981aa16 100644 (file)
@@ -80,6 +80,7 @@ namespace System.Web {
                static bool app_shutdown = false;
 #if NET_2_0
                static bool app_disabled = false;
+               static string[] app_browsers_files = new string[0];
 #endif
                Stack available = new Stack ();
                Stack available_for_end = new Stack ();
@@ -389,6 +390,14 @@ namespace System.Web {
                                        // Todo: Compile code from App_Code here
                                        AppCodeCompiler acc = new AppCodeCompiler ();
                                        acc.Compile ();
+                                       
+                                       // Note whether there are any App_Browsers/*.browser files.  If there
+                                       // are we will be using *.browser files for sniffing instead of browscap.ini
+                                       string app_browsers_path = Path.Combine (physical_app_path, "App_Browsers");
+                                       app_browsers_files = new string[0];
+                                       if (Directory.Exists (app_browsers_path)) {
+                                               app_browsers_files = Directory.GetFiles (app_browsers_path, "*.browser");
+                                       }
 #endif
 
                                        if (app_file != null) {
@@ -458,6 +467,11 @@ namespace System.Web {
                                                foreach (string dir in HttpApplication.BinDirectories)
                                                        WatchLocationForRestart (dir, "*.dll");
 #if NET_2_0
+                                                                       // Restart if the App_* directories are created...
+                                               WatchLocationForRestart (".", "App_Code");
+                                               WatchLocationForRestart (".", "App_Browsers");
+                                               WatchLocationForRestart (".", "App_GlobalResources");
+                                               // ...or their contents is changed.
                                                WatchLocationForRestart ("App_Code", "*", true);
                                                WatchLocationForRestart ("App_Browsers", "*");
                                                WatchLocationForRestart ("App_GlobalResources", "*");
@@ -560,6 +574,25 @@ namespace System.Web {
                        get { return app_disabled; }
                        set { app_disabled = value; }
                }
+
+               internal static string[] AppBrowsersFiles {
+                       get { return app_browsers_files; }
+               }
+               
+               static System.Web.Configuration.nBrowser.Build capabilities_processor = null;
+               static object capabilities_processor_lock = new object();
+               internal static System.Web.Configuration.ICapabilitiesProcess CapabilitiesProcessor {
+                       get {
+                               lock (capabilities_processor_lock) {
+                                       if (capabilities_processor == null) {
+                                               capabilities_processor = new System.Web.Configuration.nBrowser.Build();
+                                               foreach (string f in app_browsers_files)
+                                                       capabilities_processor.AddBrowserFile(f);
+                                       }
+                               }
+                               return capabilities_processor;
+                       }
+               }
 #endif
                
                internal static void DisableWatchers ()
index f2e4744fa5dc77dcfe7ed4e356f9f954c09694d9..59e2e600bc702a592d9db83907831bacaeeb2c02 100644 (file)
@@ -267,6 +267,22 @@ namespace System.Web {
                        }
                }
 
+#if NET_2_0            
+               internal bool BrowserMightHaveSpecialWriter {
+                       get {
+                               return (browser_capabilities != null 
+                                       || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
+                       }
+               }
+
+               internal bool BrowserMightHaveAdapters {
+                       get {
+                               return (browser_capabilities != null 
+                                       || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
+                       }
+               }
+#endif
+
                public HttpClientCertificate ClientCertificate {
                        get {
                                if (client_cert == null)
index 3c8a79f397f7130bae1eecd2791d94709d45a859..8b90050cb546a36aa73359527052048f584fad73 100644 (file)
@@ -31,6 +31,7 @@ mainsoft/NunitWeb/NunitWeb/PostableWorkerRequest.cs
 mainsoft/NunitWeb/NunitWeb/Response.cs
 mainsoft/NunitWeb/NunitWeb/StandardUrl.cs
 mainsoft/NunitWeb/NunitWeb/WebTest.cs
+System.Web/AppBrowsersTest.cs
 System.Web/HttpBrowserCapabilitiesTest.cs
 System.Web/HttpCacheVaryByContentEncodingsTest.cs
 System.Web/HttpCacheVaryByHeadersTest.cs
@@ -41,6 +42,7 @@ System.Web/HttpCookieCollectionTest.cs
 System.Web/HttpCookieTest.cs
 System.Web/HttpRequestTest.cs
 System.Web/HttpResponseTest.cs
+System.Web/HttpRuntimeTest.cs
 System.Web/HttpServerUtilityTest.cs
 System.Web/HttpUtilityTest.cs
 System.Web/SiteMapProviderTest.cs
@@ -97,6 +99,8 @@ System.Web.UI/CssStyleCollectionTest.cs
 System.Web.UI/DataBindingCollectionTest.cs
 System.Web.UI/DataBindingHandlerAttributeTest.cs
 System.Web.UI/LiteralControlTest.cs
+System.Web.UI.Adapters/ControlAdapterTest.cs
+System.Web.UI.Adapters/PageAdapterTest.cs
 System.Web.UI.HtmlControls/HtmlAnchorTest.cs
 System.Web.UI.HtmlControls/HtmlButtonTest.cs
 System.Web.UI.HtmlControls/HtmlContainerControlTest.cs
@@ -132,6 +136,11 @@ System.Web.UI/TemplateInstanceAttributeTest.cs
 System.Web.UI/TestUrlPropertyAttribute.cs
 System.Web.UI/ToolboxDataAttributeTest.cs
 System.Web.UI/XhtmlTextWriterTest.cs
+System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
 System.Web.UI.WebControls/AccessDataSourceTest.cs
 System.Web.UI.WebControls/AdCreatedEventArgsTest.cs
 System.Web.UI.WebControls/AutoGeneratedFieldTest.cs
diff --git a/mcs/class/System.Web/Test/System.Web.UI.Adapters/ChangeLog b/mcs/class/System.Web/Test/System.Web.UI.Adapters/ChangeLog
new file mode 100644 (file)
index 0000000..2e32c90
--- /dev/null
@@ -0,0 +1,14 @@
+2008-01-12  Dean Brettle <dean@brettle.com> 
+
+       * PageAdapterTest.cs: added tests for PageAdapter.
+
+2008-01-07  Dean Brettle <dean@brettle.com> 
+
+       * ControlAdapterTest.cs (ConfigCapabilitiesNotCalled): added test to
+       ensure that HttpCapabilitiesBase.ConfigCapabilities() is not called
+       during normal page processing if no files are in App_Browsers.
+       
+
+2008-01-07  Dean Brettle <dean@brettle.com> 
+
+       * ControlAdapterTest.cs: added tests for ControlAdapter.
diff --git a/mcs/class/System.Web/Test/System.Web.UI.Adapters/ControlAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.Adapters/ControlAdapterTest.cs
new file mode 100644 (file)
index 0000000..a686cae
--- /dev/null
@@ -0,0 +1,388 @@
+//
+// Tests for System.Web.UI.Adapters.ControlAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.Adapters
+{
+       [TestFixture]
+       public class ControlAdapterTest
+       {
+               [Test]
+               public void BeginRender ()
+               {
+                       MyControlAdapter a = new MyControlAdapter ();
+                       MyHtmlTextWriter w = new MyHtmlTextWriter ();
+                       a.CallBeginRender (w);
+                       Assert.IsTrue (w.begin_render_called, "BeginRender #1");
+               }
+               
+               [Test]
+               public void EndRender ()
+               {
+                       MyControlAdapter a = new MyControlAdapter ();
+                       MyHtmlTextWriter w = new MyHtmlTextWriter ();
+                       a.CallEndRender (w);
+                       Assert.IsTrue (w.end_render_called, "EndRender #1");
+               }
+
+               [Test]
+               public void Render ()
+               {
+                       MyControl c = new MyControl();
+                       MyHtmlTextWriter w = new MyHtmlTextWriter ();
+                       c.AdapterCallRender (w);
+                       Assert.IsTrue (c.render_called, "Render #1");
+               }
+               
+               [Test]
+               public void RenderChildren ()
+               {
+                       MyControl c = new MyControl ();
+                       MyHtmlTextWriter w = new MyHtmlTextWriter ();
+                       c.AdapterCallRenderChildren (w);
+                       Assert.IsTrue (c.render_children_called, "RenderChildren #1");
+               }
+
+               [Test]
+               public void OnInit ()
+               {
+                       MyControl c = new MyControl ();
+                       EventArgs e = new EventArgs ();
+                       c.AdapterCallOnInit (e);
+                       Assert.AreEqual (e, c.on_init_arg, "OnInit #1");
+               }
+
+               [Test]
+               public void OnLoad ()
+               {
+                       MyControl c = new MyControl ();
+                       EventArgs e = new EventArgs ();
+                       c.AdapterCallOnLoad (e);
+                       Assert.AreEqual (e, c.on_load_arg, "OnLoad #1");
+               }
+               
+               [Test]
+               public void OnPreRender ()
+               {
+                       MyControl c = new MyControl ();
+                       EventArgs e = new EventArgs ();
+                       c.AdapterCallOnPreRender (e);
+                       Assert.AreEqual (e, c.on_pre_render_arg, "OnPreRender #1");
+               }
+
+               [Test]
+               public void OnUnload ()
+               {
+                       MyControl c = new MyControl ();
+                       EventArgs e = new EventArgs ();
+                       c.AdapterCallOnUnload (e);
+                       Assert.AreEqual (e, c.on_unload_arg, "OnUnload #1");
+               }
+               
+               [Test]
+               public void Page ()
+               {
+                       MyControl c = new MyControl ();
+                       c.Page = new Page ();
+                       c.AdapterGetPage ();
+                       Assert.AreEqual (c.Page, c.AdapterGetPage (), "Page #1");
+               }
+               
+               [Test]
+               public void PageAdapter ()
+               {
+                       MyControl c = new MyControl ();
+                       PageAdapter pa = new MyPageAdapter ();
+                       c.Page = new MyPage (pa);
+                       c.AdapterGetPageAdapter ();
+                       Assert.AreEqual (c.Page.PageAdapter, c.AdapterGetPageAdapter (), "PageAdapter #1");
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void Browser () 
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnInit (Browser_OnInit));
+                       t.Run ();
+               }
+                               
+               public static void Browser_OnInit (Page p) 
+               {
+                       MyControl c = new MyControl ();
+                       p.Controls.Add (c);
+
+                       Assert.AreEqual (p.Request.Browser, c.AdapterGetBrowser (), "Browser #1");
+               }
+               
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void ConfigCapabilitiesNotCalled () 
+               {
+                       WebTest t = new WebTest (new HandlerInvoker (ConfigCapabilitiesNotCalled_Reset));
+                       t.Run ();
+                       t = new WebTest (PageInvoker.CreateOnInit (ConfigCapabilitiesNotCalled_OnInit));
+                       t.Run ();
+               }
+               
+               public static void ConfigCapabilitiesNotCalled_Reset ()
+               {
+                       HttpCapabilitiesBase.GetConfigCapabilities_called = false;
+               }
+                       
+               private static EventHandler end_request_handler;
+               
+               public static void ConfigCapabilitiesNotCalled_OnInit (Page p) 
+               {
+                       end_request_handler = new EventHandler (ConfigCapabilitiesNotCalled_EndRequest);
+                       HttpContext.Current.ApplicationInstance.EndRequest += end_request_handler;
+               }
+               
+               public static void ConfigCapabilitiesNotCalled_EndRequest (object sender, EventArgs args)
+               {
+                       // Ensure that this handler doesn't stick around for other tests.
+                       HttpContext.Current.ApplicationInstance.EndRequest -= end_request_handler;
+               
+                       // GetConfigCapabilities() should not have been called because there are no
+                       // files in App_Browsers/.
+                       Assert.IsFalse (HttpCapabilitiesBase.GetConfigCapabilities_called, 
+                               "ConfigCapabilitiesNotCalled #1");
+               }
+               
+#region Support classes
+               
+               class MyPageAdapter : PageAdapter
+               {
+                       internal MyPageAdapter () : base ()
+                       {
+                       }
+               }
+               
+               class MyPage : Page
+               {
+                       internal MyPage (PageAdapter pa) : base ()
+                       {
+                               page_adapter = pa;
+                       }
+                       
+                       private PageAdapter page_adapter;
+                       
+                       protected override ControlAdapter ResolveAdapter ()
+                       {
+                               return page_adapter;
+                       }
+               }
+
+               class MyControl : Control
+               {
+                       internal bool render_called = false;
+                       protected override void Render (HtmlTextWriter w)
+                       {
+                               render_called = true;
+                       }
+                       
+                       internal bool render_children_called = false;
+                       protected override void RenderChildren (HtmlTextWriter w)
+                       {
+                               render_children_called = true;
+                       }
+
+                       internal EventArgs on_init_arg = null;
+                       protected override void OnInit (EventArgs e)
+                       {
+                               on_init_arg = e;
+                       }
+
+                       internal EventArgs on_load_arg = null;
+                       protected override void OnLoad (EventArgs e)
+                       {
+                               on_load_arg = e;
+                       }
+                       
+                       internal EventArgs on_pre_render_arg = null;
+                       protected override void OnPreRender (EventArgs e)
+                       {
+                               on_pre_render_arg = e;
+                       }
+
+                       internal EventArgs on_unload_arg = null;
+                       protected override void OnUnload (EventArgs e)
+                       {
+                               on_unload_arg = e;
+                       }
+
+                       internal MyControlAdapter adapter = new MyControlAdapter ();
+                       protected override ControlAdapter ResolveAdapter ()
+                       {
+                               return adapter;
+                       }
+                       
+                       internal void AdapterCallRender (HtmlTextWriter w)
+                       {
+                               ((MyControlAdapter)Adapter).CallRender (w);
+                       }
+
+                       internal void AdapterCallRenderChildren (HtmlTextWriter w)
+                       {
+                               ((MyControlAdapter)Adapter).CallRenderChildren (w);
+                       }
+
+                       internal void AdapterCallOnInit (EventArgs e)
+                       {
+                               ((MyControlAdapter)Adapter).CallOnInit (e);
+                       }
+
+                       internal void AdapterCallOnLoad (EventArgs e)
+                       {
+                               ((MyControlAdapter)Adapter).CallOnLoad (e);
+                       }
+
+                       internal void AdapterCallOnPreRender (EventArgs e)
+                       {
+                               ((MyControlAdapter)Adapter).CallOnPreRender (e);
+                       }
+
+                       internal void AdapterCallOnUnload (EventArgs e)
+                       {
+                               ((MyControlAdapter)Adapter).CallOnUnload (e);
+                       }
+
+                       internal Page AdapterGetPage ()
+                       {
+                               return ((MyControlAdapter)Adapter).GetPage ();
+                       }
+
+                       internal PageAdapter AdapterGetPageAdapter ()
+                       {
+                               return ((MyControlAdapter)Adapter).GetPageAdapter ();
+                       }
+
+                       internal HttpBrowserCapabilities AdapterGetBrowser ()
+                       {
+                               return ((MyControlAdapter)Adapter).GetBrowser ();
+                       }
+               }
+
+               class MyControlAdapter : ControlAdapter
+               {
+                       internal MyControlAdapter () : base ()
+                       {
+                       }
+                       
+                       internal void CallBeginRender (HtmlTextWriter w)
+                       {
+                               BeginRender (w);
+                       }
+
+                       internal void CallEndRender (HtmlTextWriter w)
+                       {
+                               EndRender (w);
+                       }
+
+                       internal void CallRender (HtmlTextWriter w)
+                       {
+                               Render (w);
+                       }
+
+                       internal void CallRenderChildren (HtmlTextWriter w)
+                       {
+                               RenderChildren (w);
+                       }
+
+                       internal void CallOnInit (EventArgs e)
+                       {
+                               OnInit (e);
+                       }
+
+                       internal void CallOnLoad (EventArgs e)
+                       {
+                               OnLoad (e);
+                       }
+
+                       internal void CallOnPreRender (EventArgs e)
+                       {
+                               OnPreRender (e);
+                       }
+
+                       internal void CallOnUnload (EventArgs e)
+                       {
+                               OnUnload (e);
+                       }
+
+                       internal Page GetPage ()
+                       {
+                               return Page;
+                       }
+
+                       internal PageAdapter GetPageAdapter ()
+                       {
+                               return PageAdapter;
+                       }
+                       
+                       internal HttpBrowserCapabilities GetBrowser ()
+                       {
+                               return Browser;
+                       }
+               }
+               
+               class MyHtmlTextWriter : HtmlTextWriter
+               {
+                       internal MyHtmlTextWriter () : base (new StringWriter ())
+                       {
+                       }
+                       
+                       internal bool begin_render_called = false;
+                       public override void BeginRender ()
+                       {
+                               begin_render_called = true;
+                       }
+
+                       internal bool end_render_called = false;
+                       public override void EndRender ()
+                       {
+                               end_render_called = true;
+                       }
+               }
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.Adapters/PageAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.Adapters/PageAdapterTest.cs
new file mode 100644 (file)
index 0000000..e8edf8d
--- /dev/null
@@ -0,0 +1,291 @@
+//
+// Tests for System.Web.UI.Adapters.PageAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.Adapters
+{
+       [TestFixture]
+       public class PageAdapterTest
+       {
+               private MyPageAdapter mpa;
+               private MyPage page;
+
+               [TestFixtureSetUp]
+               public void SetUpTest ()
+               {
+#if VISUAL_STUDIO
+                       WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageWithAdapter.aspx", "PageWithAdapter.aspx");
+#else
+                       WebTest.CopyResource (GetType (), "PageWithAdapter.aspx", "PageWithAdapter.aspx");
+#endif
+               }
+               
+               [SetUp]
+               public void SetUp()
+               {
+                       page = new MyPage();
+                       mpa = new MyPageAdapter (page);
+               }
+               
+               [Test]
+               public void CacheVaryByHeaders ()
+               {
+                       Assert.IsNull (mpa.CacheVaryByHeaders, "CacheVaryByHeaders #1");
+               }
+               
+               [Test]
+               public void CacheVaryByParams ()
+               {
+                       Assert.IsNull (mpa.CacheVaryByParams, "CacheVaryByParams #1");
+               }
+               
+               [Test]
+               public void GetStatePersister ()
+               {
+                       PageStatePersister persister = mpa.GetStatePersister ();
+                       Assert.AreEqual (typeof(HiddenFieldPageStatePersister), 
+                               persister.GetType (), "GetStatePersister #1");
+               }
+               
+               [Test]
+               public void GetPostBackFormReference ()
+               {
+                       Assert.AreEqual("document.forms['test']", mpa.GetPostBackFormReference ("test"),
+                               "GetPostBackFormReference #1");
+               }
+               
+               [Test]
+               public void DeterminePostBackMode ()
+               {
+                       Assert.AreEqual(page.DeterminePostBackMode (), mpa.DeterminePostBackMode (),
+                               "DeterminePostBackMode #1");
+               }
+
+               [Test]
+               public void RenderBeginHyperlink_NoEncode ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", false, "softKeyLabel");
+                       Assert.AreEqual("<a href=\"url with &, <, and \"\">", sw.ToString(),
+                               "RenderBeginHyperlink_NoEncode #1");
+               }
+
+               [Test]
+               public void RenderBeginHyperlink_Encode ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel");
+                       Assert.AreEqual("<a href=\"url with &amp;, &lt;, and &quot;\">", sw.ToString(),
+                               "RenderBeginHyperlink_Encode #1");
+               }
+
+               [Test]
+               public void RenderBeginHyperlink_NoEncode_AccessKey ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", false, "softKeyLabel", "X");
+                       Assert.AreEqual("<a href=\"url with &, <, and \"\" accesskey=\"X\">",
+                               sw.ToString(), "RenderBeginHyperlink_NoEncode_AccessKey #1");
+               }
+
+               [Test]
+               public void RenderBeginHyperlink_Encode_AccessKey ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel", "X");
+                       Assert.AreEqual("<a href=\"url with &amp;, &lt;, and &quot;\" accesskey=\"X\">",
+                               sw.ToString(), "RenderBeginHyperlink_Encode_AccessKey #1");
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentOutOfRangeException))]
+               public void RenderBeginHyperlink_LongAccessKey ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel", "accessKey");
+               }
+
+               [Test]
+               public void EndHyperlink ()
+               {
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter htw = new HtmlTextWriter (sw);
+                       mpa.RenderBeginHyperlink (htw, "url", false, null);
+                       mpa.RenderEndHyperlink (htw);
+                       Assert.AreEqual("<a href=\"url\"></a>", sw.ToString(), "RenderEndHyperlink #1");
+               }
+
+               [Test]
+               [Category ("NunitWeb")]
+               public void RenderPostBackEvent ()
+               {
+                       WebTest t = new WebTest ("PageWithAdapter.aspx");
+                       PageDelegates pd = new PageDelegates ();
+                       pd.SaveStateComplete = RenderPostBackEvent_OnSaveStateComplete;
+                       t.Invoker = new PageInvoker (pd);
+                       string html = t.Run ();
+                       File.WriteAllText("response.html", html);
+               }
+               
+               public static void RenderPostBackEvent_OnSaveStateComplete (Page p)
+               {
+                       TestPageWithAdapter pageWithAdapter = (TestPageWithAdapter) p;                  
+                       TestAdapter testAdapter = (TestAdapter)pageWithAdapter.PageAdapter;
+                       {
+                               StringWriter sw = new StringWriter ();
+                               HtmlTextWriter htw = new HtmlTextWriter (sw);
+                               testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X", true);
+                               Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&amp;__EVENTTARGET=target&amp;__EVENTARGUMENT=argument&amp;__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+                                       sw.ToString(), "RenderPostBackEvent #1");
+                       }
+                       {
+                               StringWriter sw = new StringWriter ();
+                               HtmlTextWriter htw = new HtmlTextWriter (sw);
+                               testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X", false);
+                               Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&__EVENTTARGET=target&__EVENTARGUMENT=argument&__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+                                       sw.ToString(), "RenderPostBackEvent #2");
+                       }
+                       {
+                               StringWriter sw = new StringWriter ();
+                               HtmlTextWriter htw = new HtmlTextWriter (sw);
+                               testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X");
+                               Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&amp;__EVENTTARGET=target&amp;__EVENTARGUMENT=argument&amp;__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+                                       sw.ToString(), "RenderPostBackEvent #3");
+                       }
+                       {
+                               StringWriter sw = new StringWriter ();
+                               HtmlTextWriter htw = new HtmlTextWriter (sw);
+                               testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text");
+                               Assert.AreEqual("<a href=\"/NunitWeb/PageWithAdapter.aspx?__VIEWSTATE=DAAAAA%3d%3d&amp;__EVENTTARGET=target&amp;__EVENTARGUMENT=argument&amp;__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\">text</a>",
+                                       sw.ToString(), "RenderPostBackEvent #4");
+                       }
+
+               }
+               
+               [Test]
+               public void RadioButtons ()
+               {
+                       ArrayList group = new ArrayList (mpa.GetRadioButtonsByGroup ("Group1"));
+                       Assert.AreEqual (0, group.Count, "RadioButtons #0");
+
+                       RadioButton g1b1 = new RadioButton ();
+                       g1b1.GroupName = "Group1";
+                       mpa.RegisterRadioButton(g1b1);
+                       RadioButton g1b2 = new RadioButton ();
+                       g1b2.GroupName = "Group1";
+                       mpa.RegisterRadioButton(g1b2);  
+                       RadioButton g2b1 = new RadioButton ();
+                       g2b1.GroupName = "Group2";
+                       mpa.RegisterRadioButton (g2b1);
+                       RadioButton noGroupB1 = new RadioButton ();
+                       mpa.RegisterRadioButton (noGroupB1);
+                       
+                       Assert.AreEqual (0, mpa.GetRadioButtonsByGroup ("Non-existent group").Count, "RadioButtons #1");
+
+                       ArrayList group1 = new ArrayList (mpa.GetRadioButtonsByGroup ("Group1"));                       
+                       Assert.AreEqual (2, group1.Count, "RadioButtons #2");
+                       Assert.IsTrue (group1.Contains (g1b1), "RadioButtons #3");
+                       Assert.IsTrue (group1.Contains (g1b2), "RadioButtons #4");
+                       
+                       ArrayList group2 = new ArrayList (mpa.GetRadioButtonsByGroup ("Group2"));                       
+                       Assert.AreEqual (1, group2.Count, "RadioButtons #5");
+                       Assert.IsTrue (group2.Contains (g2b1), "RadioButtons #6");
+                       
+                       ArrayList noGroup = new ArrayList (mpa.GetRadioButtonsByGroup (""));                    
+                       Assert.AreEqual (1, noGroup.Count, "RadioButtons #7");
+                       Assert.IsTrue (noGroup.Contains (noGroupB1), "RadioButtons #8");
+               }
+
+               [Test]
+               public void ClientState ()
+               {
+                       page.RawViewState = "test";
+                       Assert.AreEqual ("test", mpa.ClientState, "ClientState #1");
+               }
+               
+               [Test]
+               public void TransformText ()
+               {
+                       Assert.AreEqual ("test", mpa.TransformText("test"), "TransformText #1");
+                       Assert.IsNull (mpa.TransformText(null), "TransformText #2");
+               }
+               
+               [TestFixtureTearDown]
+               public void TearDown ()
+               {
+                       WebTest.Unload ();
+               }
+
+               class MyPageAdapter : PageAdapter
+               {
+                       internal MyPageAdapter (Page p) : base (p)
+                       {
+                       }
+                       
+                       new internal string ClientState {
+                               get { return base.ClientState; }
+                       }
+               }
+
+               class MyPage : Page
+               {
+                       internal MyPage () : base ()
+                       {
+                       }
+                       
+                       NameValueCollection post_back_mode = new NameValueCollection ();
+                       
+                       override protected internal NameValueCollection DeterminePostBackMode ()
+                       {
+                               return post_back_mode;
+                       }
+               }
+       }
+       
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/ChangeLog b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/ChangeLog
new file mode 100644 (file)
index 0000000..0f7938e
--- /dev/null
@@ -0,0 +1,8 @@
+2008-01-15  Dean Brettle <dean@brettle.com> 
+
+       * MenuAdapterTest.cs: added
+
+2008-01-13  Dean Brettle <dean@brettle.com> 
+
+       * WebControlAdapterTest.cs, HierarchicalDataBoundControlAdapterTest.cs,
+       DataBoundControlAdapterTest.cs, HideDisabledControlAdapterTest.cs: added
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
new file mode 100644 (file)
index 0000000..9a9b3c9
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tests for System.Web.UI.WebControls.Adapters.DataBoundControlAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+       [TestFixture]
+       public class DataBoundControlAdapterTest
+       {
+               MyDataBoundControl c;
+               MyDataBoundControlAdapter a;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       c = new MyDataBoundControl ();
+                       a = new MyDataBoundControlAdapter (c);
+               }
+               
+               [Test]
+               public void PerformDataBinding ()
+               {
+                       ArrayList data = new ArrayList ();
+                       a.PerformDataBinding (data);
+                       Assert.AreEqual (data, c.data, "PerformDataBinding #1");
+               }
+
+               [Test]
+               public void Control ()
+               {
+                       Assert.AreEqual (c, a.Control, "Control #1");
+               }
+                               
+#region Support classes
+               
+               class MyDataBoundControl : DataBoundControl
+               {
+                       internal IEnumerable data;
+                       
+                       protected internal override void PerformDataBinding (IEnumerable data)
+                       {
+                               this.data = data;
+                       }
+
+               }
+
+               class MyDataBoundControlAdapter : DataBoundControlAdapter
+               {
+                       internal MyDataBoundControlAdapter (DataBoundControl c) : base (c)
+                       {
+                       }
+                       
+                       new internal DataBoundControl Control {
+                               get { return base.Control; }
+                       }
+               }
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
new file mode 100644 (file)
index 0000000..f222d8f
--- /dev/null
@@ -0,0 +1,101 @@
+//
+// Tests for System.Web.UI.WebControls.Adapters.HideDisabledControlAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+       [TestFixture]
+       public class HideDisabledControlAdapterTest
+       {
+               [Test]
+               public void Render ()
+               {
+                       WebControl parent = new MyWebControl();
+                       MyWebControl c = new MyWebControl ();
+                       HideDisabledControlAdapter a = new HideDisabledControlAdapter (c);
+                       StringWriter sw;
+                       HtmlTextWriter w;
+
+                       sw = new StringWriter();
+                       w = new HtmlTextWriter(sw);
+                       a.Render (w);
+                       Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString(), "Render #1");
+                       
+                       
+                       sw = new StringWriter();
+                       w = new HtmlTextWriter(sw);
+                       c.Enabled = false;
+                       a.Render (w);                   
+                       Assert.AreEqual ("", sw.ToString(), "Render #2");
+                       
+                       sw = new StringWriter();
+                       w = new HtmlTextWriter(sw);
+                       parent.Enabled = false;
+                       c.Enabled = true;
+                       parent.Controls.Add(c);
+                       a.Render (w);                   
+                       Assert.AreEqual ("", sw.ToString(), "Render #3");
+               }
+
+#region Support classes
+               
+               class MyWebControl : WebControl
+               {
+                       public override void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderBeginTag");
+                       }
+
+                       protected internal override void RenderContents (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderContents");
+                       }
+
+                       public override void RenderEndTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderEndTag");
+                       }
+               }
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
new file mode 100644 (file)
index 0000000..62147ba
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tests for System.Web.UI.WebControls.Adapters.HierarchicalDataBoundControlAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+       [TestFixture]
+       public class HierarchicalDataBoundControlAdapterTest
+       {
+               MyHierarchicalDataBoundControl c;
+               MyHierarchicalDataBoundControlAdapter a;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       c = new MyHierarchicalDataBoundControl ();
+                       a = new MyHierarchicalDataBoundControlAdapter (c);
+               }
+               
+               [Test]
+               public void PerformDataBinding ()
+               {
+                       a.PerformDataBinding ();
+                       Assert.IsTrue (c.perform_data_binding_called, "PerformDataBinding #1");
+               }
+
+               [Test]
+               public void Control ()
+               {
+                       Assert.AreEqual (c, a.Control, "Control #1");
+               }
+                               
+#region Support classes
+               
+               class MyHierarchicalDataBoundControl : HierarchicalDataBoundControl
+               {
+                       internal bool perform_data_binding_called;
+                       
+                       protected internal override void PerformDataBinding ()
+                       {
+                               perform_data_binding_called = true;
+                       }
+
+               }
+
+               class MyHierarchicalDataBoundControlAdapter : HierarchicalDataBoundControlAdapter
+               {
+                       internal MyHierarchicalDataBoundControlAdapter (HierarchicalDataBoundControl c) : base (c)
+                       {
+                       }
+                       
+                       new internal HierarchicalDataBoundControl Control {
+                               get { return base.Control; }
+                       }
+               }
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
new file mode 100644 (file)
index 0000000..9c0d805
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// Tests for System.Web.UI.WebControls.Adapters.MenuAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+       [TestFixture]
+       public class MenuAdapterTest
+       {
+               MyMenu c;
+               MyMenuAdapter a;
+               StringWriter sw;
+               HtmlTextWriter w;
+               Page p;
+               EventArgs e;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       p = new Page ();
+                       c = new MyMenu ();
+                       a = new MyMenuAdapter (c);
+                       p.Controls.Add(c);
+                       sw = new StringWriter ();
+                       w = new HtmlTextWriter (sw);
+                       e = new EventArgs();
+               }
+               
+               [Test]
+               public void OnInit ()
+               {
+                       a.OnInit (e);
+                       Assert.IsTrue (p.RequiresControlState (c), "OnInit #1");
+                       Assert.AreEqual (e, c.on_init_arg, "OnInit #2");
+               }
+
+               [Test]
+               public void OnPreRender ()
+               {
+                       a.OnPreRender (e);
+                       Assert.AreEqual (e, c.on_pre_render_arg, "OnPreRender #1");
+               }
+
+               [Test]
+               public void RaisePostBackEvent ()
+               {
+                       ((IPostBackEventHandler)a).RaisePostBackEvent ("eventArg");
+                       Assert.AreEqual ("eventArg", c.raise_post_back_event_arg, "RaisePostBackEvent #1");
+               }
+               
+               [Test]
+               public void RenderBeginTag ()
+               {
+                       a.RenderBeginTag (w);
+                       Assert.AreEqual ("RenderBeginTag\n", sw.ToString (), "RenderBeginTag #1");
+               }
+
+               [Test]
+               public void RenderContentsTag ()
+               {
+                       a.RenderContents (w);
+                       Assert.AreEqual ("RenderContents\n", sw.ToString (), "RenderContents #1");
+               }
+
+               [Test]
+               public void RenderEndTag ()
+               {
+                       a.RenderEndTag (w);
+                       Assert.AreEqual ("RenderEndTag\n", sw.ToString (), "RenderEndTag #1");
+               }
+
+               [Test]
+               public void RenderItem ()
+               {
+                       MenuItem item = new MenuItem("menu item text");
+                       a.RenderItem (w, item, 0);
+                       Assert.IsTrue (sw.ToString ().IndexOf("menu item text") != -1, "RenderItem #1");
+               }
+
+               [Test]
+               public void Control ()
+               {
+                       Assert.AreEqual (c, a.Control, "Control #1");
+               }
+               
+
+
+#region Support classes
+               
+               class MyMenu : Menu
+               {
+               
+                       internal EventArgs on_init_arg;
+                       protected internal override void OnInit (EventArgs e)
+                       {
+                               on_init_arg = e;
+                               base.OnInit (e);
+                       }
+                       
+                       internal EventArgs on_pre_render_arg;
+                       protected internal override void OnPreRender (EventArgs e)
+                       {
+                               on_pre_render_arg = e;
+                               base.OnPreRender (e);
+                       }
+                       
+                       internal string raise_post_back_event_arg;
+                       protected internal override void RaisePostBackEvent (string eventArgument)
+                       {
+                               raise_post_back_event_arg = eventArgument;
+                       }
+
+                       public override void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderBeginTag");
+                       }
+
+                       protected internal override void RenderContents (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderContents");
+                       }
+
+                       public override void RenderEndTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderEndTag");
+                       }
+
+               }
+
+               class MyMenuAdapter : MenuAdapter
+               {
+                       internal MyMenuAdapter (Menu c) : base (c)
+                       {
+                       }
+                                                                       
+                       new internal void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               base.RenderBeginTag (w);
+                       }
+
+                       new internal void RenderContents (HtmlTextWriter w)
+                       {
+                               base.RenderContents (w);
+                       }
+
+                       new internal void RenderEndTag (HtmlTextWriter w)
+                       {
+                               base.RenderEndTag (w);
+                       }
+
+                       new internal Menu Control {
+                               get { return base.Control; }
+                       }
+               }
+               
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs b/mcs/class/System.Web/Test/System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
new file mode 100644 (file)
index 0000000..485df55
--- /dev/null
@@ -0,0 +1,168 @@
+//
+// Tests for System.Web.UI.WebControls.Adapters.WebControlAdapter
+//
+// Author:
+//     Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+       [TestFixture]
+       public class WebControlAdapterTest
+       {
+               MyWebControl c;
+               MyWebControlAdapter a;
+               StringWriter sw;
+               HtmlTextWriter w;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       c = new MyWebControl ();
+                       a = new MyWebControlAdapter (c);
+                       sw = new StringWriter ();
+                       w = new HtmlTextWriter (sw);                    
+               }
+               
+               [Test]
+               public void RenderBeginTag ()
+               {
+                       a.RenderBeginTag (w);
+                       Assert.AreEqual ("RenderBeginTag\n", sw.ToString (), "RenderBeginTag #1");
+               }
+
+               [Test]
+               public void RenderContentsTag ()
+               {
+                       a.RenderContents (w);
+                       Assert.AreEqual ("RenderContents\n", sw.ToString (), "RenderContents #1");
+               }
+
+               [Test]
+               public void RenderEndTag ()
+               {
+                       a.RenderEndTag (w);
+                       Assert.AreEqual ("RenderEndTag\n", sw.ToString (), "RenderEndTag #1");
+               }
+
+               [Test]
+               public void Render ()
+               {
+                       a.Render (w);
+                       Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString (), "Render #1");
+               }
+               
+               [Test]
+               public void Control ()
+               {
+                       Assert.AreEqual (c, a.Control, "Control #1");
+               }
+               
+               [Test]
+               public void IsEnabled ()
+               {
+                       MyWebControl parent = new MyWebControl ();
+                       parent.Controls.Add (c);
+                       Assert.IsTrue (a.IsEnabled, "IsEnabled #1");
+                       parent.Enabled = false;
+                       Assert.IsFalse (a.IsEnabled, "IsEnabled #2");
+                       parent.Enabled = true;
+                       c.Enabled = false;
+                       Assert.IsFalse (a.IsEnabled, "IsEnabled #3");
+               }
+               
+#region Support classes
+               
+               class MyWebControl : WebControl
+               {                       
+                       public override void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderBeginTag");
+                       }
+
+                       protected internal override void RenderContents (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderContents");
+                       }
+
+                       public override void RenderEndTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderEndTag");
+                       }
+
+               }
+
+               class MyWebControlAdapter : WebControlAdapter
+               {
+                       internal MyWebControlAdapter (WebControl wc) : base (wc)
+                       {
+                       }
+                       
+                       new internal void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               base.RenderBeginTag(w);
+                       }
+
+                       new internal void RenderContents (HtmlTextWriter w)
+                       {
+                               base.RenderContents(w);
+                       }
+
+                       new internal void RenderEndTag (HtmlTextWriter w)
+                       {
+                               base.RenderEndTag(w);
+                       }
+
+                       new internal void Render (HtmlTextWriter w)
+                       {
+                               base.Render(w);
+                       }
+                       
+                       new internal WebControl Control {
+                               get { return base.Control; }
+                       }
+                       
+                       new internal bool IsEnabled {
+                               get { return base.IsEnabled; }
+                       }
+               }
+#endregion
+       }
+}
+#endif
index 560c9d8e890f86d8dceeefcaef08ea08f76720d9..d05a82b6c8773a578049c07ba411da66c627bbab 100644 (file)
@@ -1,3 +1,18 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * MenuTest.cs (Menu_RenderStaticItems): added tests to check that
+       result was the same when using the base MenuAdapter as when using
+       no adapter.
+       
+       * MenuTest.cs (Menu_RenderStaticItemsWithAdapter): added test
+       to ensure that MenuAdapter.RenderItem() is called.
+
+       * HierarchicalDataBoundControlTest.cs, WebControlTest.cs, 
+       DataBoundControlTest.cs: added test for use of ControlAdapters
+       when present.
+       
+       * WebControl.cs: added test for IsEnabled.
+
 2008-01-08 Igor Zelmanovich <igorz@mainsoft.com>
 
        * DetailsViewTest.cs:
index d66829a5f2ee3bcd433d205df6831681694b492e..f853e5efd5bf2c1a9e2629c34daf52239923cd73 100644 (file)
@@ -36,6 +36,7 @@ using System.Globalization;
 using System.Web;
 using System.Web.UI;
 using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
 using System.Text;
 using System.Collections;
 using System.Data;
@@ -163,6 +164,13 @@ namespace MonoTests.System.Web.UI.WebControls
                        public DataSourceSelectArguments GetSelectArguments () {
                                return SelectArguments;
                        }
+                       
+                       internal DataBoundControlAdapter dataBoundControlAdapter;
+                       protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+                       {
+                               return dataBoundControlAdapter;
+                       }
+
                }
 
                [TestFixtureTearDown]
@@ -344,6 +352,25 @@ namespace MonoTests.System.Web.UI.WebControls
                        c.DoEnsureDataBound ();
                }
 
+               class MyDataBoundControlAdapter : DataBoundControlAdapter
+               {
+                       internal bool perform_data_binding_called;
+                       protected override void PerformDataBinding (IEnumerable data)
+                       {
+                               perform_data_binding_called = true;
+                       }
+               }
+               
+               [Test]
+               public void PerformDataBinding_UsesAdapter ()
+               {
+                       MyDataBoundControl c = new MyDataBoundControl ();
+                       MyDataBoundControlAdapter a = new MyDataBoundControlAdapter();;
+                       c.dataBoundControlAdapter = a;
+                       c.DataBind ();
+                       Assert.IsTrue (a.perform_data_binding_called, "PerformDataBinding_UsesAdapter");
+               }
+
        }
 }
 #endif
index 030e20895c22181435599b4a054981fc083f6006..c1c2d7426e31ec46b31601ac55ac2c55113d877f 100644 (file)
@@ -37,6 +37,7 @@ using System.Text;
 using System.Web;\r
 using System.Web.UI;\r
 using System.Web.UI.WebControls;\r
+using System.Web.UI.WebControls.Adapters;\r
 using System.IO;\r
 using System.Drawing;\r
 using System.Threading;\r
@@ -95,6 +96,12 @@ namespace MonoTests.System.Web.UI.WebControls
                        {\r
                                ValidateDataSource (dataSource);\r
                        }\r
+
+                       internal HierarchicalDataBoundControlAdapter dataBoundControlAdapter;
+                       protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+                       {
+                               return dataBoundControlAdapter;
+                       }
                }\r
 \r
                [Test]\r
@@ -113,6 +120,25 @@ namespace MonoTests.System.Web.UI.WebControls
                        MyHierarchicalDataBoundControl hc = new MyHierarchicalDataBoundControl ();\r
                        hc.DoValidateDataSource (null);\r
                }\r
+
+               class MyHierarchicalDataBoundControlAdapter : HierarchicalDataBoundControlAdapter
+               {
+                       internal bool perform_data_binding_called;
+                       protected override void PerformDataBinding ()
+                       {
+                               perform_data_binding_called = true;
+                       }
+               }
+               
+               [Test]
+               public void PerformDataBinding_UsesAdapter ()
+               {
+                       MyHierarchicalDataBoundControl c = new MyHierarchicalDataBoundControl ();
+                       MyHierarchicalDataBoundControlAdapter a = new MyHierarchicalDataBoundControlAdapter();;
+                       c.dataBoundControlAdapter = a;
+                       c.DataBind ();
+                       Assert.IsTrue (a.perform_data_binding_called, "PerformDataBinding_UsesAdapter");
+               }
 \r
        }\r
 }\r
index f35ac63b61047c1ee54a8900adbb8a1f9d68205b..d1c1e56955a72c766dd1c2777b7f342cd7347bc6 100644 (file)
@@ -135,8 +135,8 @@ namespace MonoTests.System.Web.UI.WebControls
                        WebTest.CopyResource (GetType (), "menuclass.aspx", "menuclass.aspx");\r
                        WebTest.CopyResource (GetType (), "PostBackMenuTest.aspx", "PostBackMenuTest.aspx");\r
 #endif\r
-               }\r
-\r
+               }
+
                [Test]\r
                public void Menu_DefaultProperties ()\r
                {\r
@@ -893,8 +893,6 @@ namespace MonoTests.System.Web.UI.WebControls
                [Category ("NunitWeb")]\r
                public void Menu_RenderStaticItems () {\r
                        string RenderedPageHtml, RenderedControlHtml, OriginControlHtml;\r
-                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Vertical)).Run ();\r
-                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
                        #region OriginControlHtml\r
                        OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&amp;t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
        <tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0"">\r
@@ -1018,9 +1016,13 @@ namespace MonoTests.System.Web.UI.WebControls
        </tr>\r
 </table><a id=""Menu_SkipLink""></a>";\r
                        #endregion\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Vertical)).Run ();\r
+                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
                        HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItems_Vertical");\r
-                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Horizontal)).Run ();\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithBaseAdapter_Vertical)).Run ();\r
                        RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+                       HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithDefaultAdapter_Vertical");\r
+
                        #region OriginControlHtml\r
                        OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&amp;t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
        <tr>\r
@@ -1116,32 +1118,319 @@ namespace MonoTests.System.Web.UI.WebControls
        </tr>\r
 </table><a id=""Menu_SkipLink""></a>";\r
                        #endregion\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Horizontal)).Run ();\r
+                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
                        HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItems_Horizontal");\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithBaseAdapter_Horizontal)).Run ();\r
+                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+                       HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithBaseAdapter_Horizontal");\r
+               }\r
+
+               class MyMenuAdapter : global::System.Web.UI.WebControls.Adapters.MenuAdapter
+               {
+                       protected internal override void RenderItem (HtmlTextWriter writer, 
+                                                                   MenuItem item,
+                                                                   int position)
+                       {
+                               writer.Write ("{");
+                               base.RenderItem (writer, item, position);
+                               writer.Write ("}");                             
+                       }                       
+               }\r
+
+               [Test]\r
+               [Category ("NunitWeb")]\r
+               public void Menu_RenderStaticItemsWithAdapter () {
+                       string RenderedPageHtml, RenderedControlHtml, OriginControlHtml;\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithAdapter_Vertical)).Run ();
+                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+                       #region OriginControlHtml\r
+                       OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&amp;t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
+       {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0"">\r
+               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                       <tr>\r
+                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value')"">one-black</a></td>\r
+                       </tr>\r
+               </table></td>\r
+       </tr><tr>\r
+               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                       {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun1"">\r
+                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value')"" style=""margin-left:16px;"">two-black-1</a></td>\r
+                                       </tr>\r
+                               </table></td>\r
+                       </tr><tr>\r
+                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                       {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun2"">\r
+                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value')"" style=""margin-left:32px;"">three-black-1</a></td>\r
+                                                       </tr>\r
+                                               </table></td>\r
+                                       </tr><tr>\r
+                                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun3"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-1-value')"" style=""margin-left:48px;"">four-black-1</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun4"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-2-value')"" style=""margin-left:48px;"">four-black-2</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}\r
+                                               </table></td>\r
+                                       </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun5"">\r
+                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value')"" style=""margin-left:32px;"">three-black-2</a></td>\r
+                                                       </tr>\r
+                                               </table></td>\r
+                                       </tr><tr>\r
+                                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun6"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-3-value')"" style=""margin-left:48px;"">four-black-3</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun7"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-4-value')"" style=""margin-left:48px;"">four-black-4</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}\r
+                                               </table></td>\r
+                                       </tr>}\r
+                               </table></td>\r
+                       </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun8"">\r
+                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value')"" style=""margin-left:16px;"">two-black-2</a></td>\r
+                                       </tr>\r
+                               </table></td>\r
+                       </tr><tr>\r
+                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                       {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun9"">\r
+                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value')"" style=""margin-left:32px;"">three-black-3</a></td>\r
+                                                       </tr>\r
+                                               </table></td>\r
+                                       </tr><tr>\r
+                                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun10"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-5-value')"" style=""margin-left:48px;"">four-black-5</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun11"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-6-value')"" style=""margin-left:48px;"">four-black-6</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}\r
+                                               </table></td>\r
+                                       </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun12"">\r
+                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value')"" style=""margin-left:32px;"">three-black-4</a></td>\r
+                                                       </tr>\r
+                                               </table></td>\r
+                                       </tr><tr>\r
+                                               <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun13"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-7-value')"" style=""margin-left:48px;"">four-black-7</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun14"">\r
+                                                               <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-8-value')"" style=""margin-left:48px;"">four-black-8</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>\r
+                                                       </tr>}\r
+                                               </table></td>\r
+                                       </tr>}\r
+                               </table></td>\r
+                       </tr>}\r
+               </table></td>\r
+       </tr>}\r
+</table><a id=""Menu_SkipLink""></a>";\r
+                       #endregion\r
+                       HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithAdapter_Vertical");\r
+                       RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithAdapter_Horizontal)).Run ();\r
+                       RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+                       #region OriginControlHtml\r
+                       OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&amp;t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
+       <tr>\r
+               {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                       <tr>\r
+                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value')"">one-black</a></td>\r
+                       </tr>\r
+               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                       <tr>\r
+                               {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun1""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value')"" style=""margin-left:16px;"">two-black-1</a></td>\r
+                                       </tr>\r
+                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun2""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value')"" style=""margin-left:32px;"">three-black-1</a></td>\r
+                                                       </tr>\r
+                                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun3""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-1-value')"" style=""margin-left:48px;"">four-black-1</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun4""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-2-value')"" style=""margin-left:48px;"">four-black-2</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}\r
+                                                       </tr>\r
+                                               </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun5""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value')"" style=""margin-left:32px;"">three-black-2</a></td>\r
+                                                       </tr>\r
+                                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun6""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-3-value')"" style=""margin-left:48px;"">four-black-3</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun7""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-4-value')"" style=""margin-left:48px;"">four-black-4</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}\r
+                                                       </tr>\r
+                                               </table></td>}\r
+                                       </tr>\r
+                               </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun8""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value')"" style=""margin-left:16px;"">two-black-2</a></td>\r
+                                       </tr>\r
+                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                       <tr>\r
+                                               {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun9""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value')"" style=""margin-left:32px;"">three-black-3</a></td>\r
+                                                       </tr>\r
+                                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun10""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-5-value')"" style=""margin-left:48px;"">four-black-5</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun11""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-6-value')"" style=""margin-left:48px;"">four-black-6</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}\r
+                                                       </tr>\r
+                                               </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun12""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value')"" style=""margin-left:32px;"">three-black-4</a></td>\r
+                                                       </tr>\r
+                                               </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+                                                       <tr>\r
+                                                               {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun13""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-7-value')"" style=""margin-left:48px;"">four-black-7</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun14""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+                                                                       <tr>\r
+                                                                               <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-8-value')"" style=""margin-left:48px;"">four-black-8</a></td>\r
+                                                                       </tr>\r
+                                                               </table></td>}\r
+                                                       </tr>\r
+                                               </table></td>}\r
+                                       </tr>\r
+                               </table></td>}\r
+                       </tr>\r
+               </table></td>}\r
+       </tr>\r
+</table><a id=""Menu_SkipLink""></a>";\r
+                       #endregion\r
+                       HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithAdapter_Horizontal");\r
                }\r
-\r
+
                public static void Menu_RenderStaticItems_Vertical (Page p) {\r
-                       Menu m = CreateMenuForRenderTests ();\r
+                       Menu m = CreateMenuForRenderTests (null);\r
                        m.StaticDisplayLevels = 4;\r
                        AddMenuToPage (p, m);\r
                }\r
 \r
                public static void Menu_RenderStaticItems_Horizontal (Page p) {\r
-                       Menu m = CreateMenuForRenderTests ();\r
+                       Menu m = CreateMenuForRenderTests (null);\r
                        m.Orientation = Orientation.Horizontal;\r
                        m.StaticDisplayLevels = 4;\r
                        AddMenuToPage (p, m);\r
                }\r
 \r
+               public static void Menu_RenderStaticItemsWithBaseAdapter_Vertical (Page p) {\r
+                       Menu m = CreateMenuForRenderTests (new MyWebControl.Adapters.MenuAdapter());\r
+                       m.StaticDisplayLevels = 4;\r
+                       AddMenuToPage (p, m);\r
+               }\r
+\r
+               public static void Menu_RenderStaticItemsWithBaseAdapter_Horizontal (Page p) {\r
+                       Menu m = CreateMenuForRenderTests (new MyWebControl.Adapters.MenuAdapter());\r
+                       m.Orientation = Orientation.Horizontal;\r
+                       m.StaticDisplayLevels = 4;\r
+                       AddMenuToPage (p, m);\r
+               }\r
+
+               public static void Menu_RenderStaticItemsWithAdapter_Vertical (Page p) {\r
+                       Menu m = CreateMenuForRenderTests (new MyMenuAdapter());\r
+                       m.StaticDisplayLevels = 4;\r
+                       AddMenuToPage (p, m);\r
+               }\r
+\r
+               public static void Menu_RenderStaticItemsWithAdapter_Horizontal (Page p) {\r
+                       Menu m = CreateMenuForRenderTests (new MyMenuAdapter());\r
+                       m.Orientation = Orientation.Horizontal;\r
+                       m.StaticDisplayLevels = 4;\r
+                       AddMenuToPage (p, m);\r
+               }\r
+
                private static void AddMenuToPage (Page p, Menu m) {\r
                        LiteralControl lcb = new LiteralControl (HtmlDiff.BEGIN_TAG);\r
                        LiteralControl lce = new LiteralControl (HtmlDiff.END_TAG);\r
                        p.Form.Controls.Add (lcb);\r
                        p.Form.Controls.Add (m);\r
                        p.Form.Controls.Add (lce);\r
-               }\r
-\r
-               private static Menu CreateMenuForRenderTests () {\r
-                       Menu menu = new Menu ();\r
+               }
+               
+               class MyMenu : Menu
+               {
+                       internal MyMenu (MyWebControl.Adapters.MenuAdapter adapter) : base ()
+                       {
+                               menu_adapter = adapter;
+                       }
+
+                       MyWebControl.Adapters.MenuAdapter menu_adapter;
+                       protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+                       {
+                               return menu_adapter;
+                       }                       
+               }\r
+\r
+               private static Menu CreateMenuForRenderTests (MyWebControl.Adapters.MenuAdapter adapter) {\r
+                       Menu menu = new MyMenu (adapter);\r
                        menu.ID = "Menu";\r
                        MenuItem R, N1, N2, SN1, SN2, SN3, SN4;\r
                        R = new MenuItem ("one-black", "one-black-value");\r
index 5706c08e68a457792e0e5ba32271f9d0007917be..1cb6b2ab69941d9d9399a6731c47873672819035 100644 (file)
@@ -38,6 +38,9 @@ using System.Web;
 using System.Web.UI;
 using System.Web.UI.WebControls;
 using MonoTests.stand_alone.WebHarness;
+#if NET_2_0
+using System.Web.UI.WebControls.Adapters;
+#endif
 
 namespace MonoTests.System.Web.UI.WebControls
 {
@@ -662,5 +665,58 @@ namespace MonoTests.System.Web.UI.WebControls
                        c.Attributes ["HOla"] = "hi";
                        Assert.AreEqual ("hi", c.Attributes ["hoLA"], "#01");
                }
+
+#if NET_2_0
+               class MyWebControlAdapter : WebControlAdapter
+               {
+                       protected override void RenderBeginTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderBeginTag");
+                       }
+
+                       protected override void RenderContents (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderContents");
+                       }
+
+                       protected override void RenderEndTag (HtmlTextWriter w)
+                       {
+                               w.WriteLine("RenderEndTag");
+                       }
+               }
+               
+               class MyWebControl : WebControl
+               {
+                       WebControlAdapter my_web_control_adapter = new MyWebControlAdapter();
+                       protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+                       {
+                               return my_web_control_adapter;
+                       }
+               }
+               
+               [Test]
+               public void Render ()
+               {
+                       MyWebControl c = new MyWebControl ();
+                       StringWriter sw = new StringWriter ();
+                       HtmlTextWriter w = new HtmlTextWriter (sw);                     
+                       c.Render (w);
+                       Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString (), "Render #1");
+               }
+
+               [Test]
+               public void IsEnabled ()
+               {
+                       WebControl parent = new MyWebControl ();
+                       WebControl child = new MyWebControl ();
+                       parent.Controls.Add (child);
+                       Assert.IsTrue (child.IsEnabled, "IsEnabled #1");
+                       parent.Enabled = false;
+                       Assert.IsFalse (child.IsEnabled, "IsEnabled #2");
+                       parent.Enabled = true;
+                       child.Enabled = false;
+                       Assert.IsFalse (child.IsEnabled, "IsEnabled #3");
+               }
+#endif
        }
 }
index 3ae866d792184391e7a354540e515319f83920f6..d25198e4e373fbe3b9bfb357543f2ec2b407f689 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * PageTest.cs: add tests for using a PageAdapter.
+       
+       * ControlTest.cs: moved commented out ResolveAdapter_1 test to 
+       ../System.Web/AppBrowsersTest.cs.  Fixed typo in test name.  
+       Added Customcontroladapter.Adapter property for use by AppBrowsersTest.
+
 2007-12-31  Vladimir Krasnov  <vladimirk@mainsoft.com>
 
        * PageTest.cs: added tests for Response.End/Redirect
index e0992e975218e44d71e7f6dc70035b3505141408..eae850528725a06c0de035bf495220f1ecd0e411 100644 (file)
@@ -707,27 +707,6 @@ namespace MonoTests.System.Web.UI
                        Stream strem = ctrl.OpenFile ("~/Fake.tmp");
                }
 
-               //// MonoTests.SystemWeb.Framework limitation for Add_browsers - directory include in project
-               //[Test]
-               //[Category ("NunitWeb")]
-               //public void ResolveAdapter_1 ()
-               //{
-               //        WebTest.CopyResource (GetType (), "adapters.browser", "App_Browsers/adapters.browser");
-               //        WebTest t = new WebTest (PageInvoker.CreateOnInit (ResolveAdapter_Init));
-               //        string html = t.Run ();
-               //}
-               //public static void ResolveAdapter_Init (Page p)
-               //{
-               //        Customadaptercontrol ctrl = new Customadaptercontrol ();
-               //        p.Controls.Add (ctrl);
-               //        ctrl.Load += new EventHandler (ctrl_Load);
-               //}
-               //static void ctrl_Load (object sender, EventArgs e)
-               //{
-               //        Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#1");
-               //        Assert.AreEqual ("Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (), "ResolveAdapter Failed#2");
-               //}
-
                [Test]
                [Category ("NunitWeb")]
                public void ResolveClientUrl ()
@@ -973,7 +952,7 @@ namespace MonoTests.System.Web.UI
                }
 #if NET_2_0
                [Test]
-               public void Contorl_Adapter ()
+               public void Control_Adapter ()
                {
                        MyNC ctr = new MyNC ();
                        Assert.AreEqual (null, ctr.Adapter (), "Adapter");
@@ -1174,6 +1153,10 @@ namespace MonoTests.System.Web.UI
 #if NET_2_0
        public class Customadaptercontrol : Control
        {
+               public new ControlAdapter Adapter {
+                       get { return base.Adapter; }
+               }
+
                public new ControlAdapter ResolveAdapter ()
                {
                        return base.ResolveAdapter ();
index d33b29897090a83674361663f7a4942f454d745c..1dd04054d2824cba0c1d32268208b816511dea3d 100644 (file)
@@ -41,10 +41,14 @@ using MonoTests.stand_alone.WebHarness;
 using System.Web.UI.WebControls;
 using System.Web.UI.HtmlControls;
 using System.Collections;
+using System.Collections.Specialized;
 using System.Net;
 
+
+
 namespace MonoTests.System.Web.UI {
 
+
        class TestPage : Page {
 
                private HttpContext ctx;
@@ -121,7 +125,7 @@ namespace MonoTests.System.Web.UI {
                        WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageLifecycleTest.aspx", "PageLifecycleTest.aspx");
                        WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageValidationTest.aspx", "PageValidationTest.aspx");
                        WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.AsyncPage.aspx", "AsyncPage.aspx");
-                       WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.AsyncPage.aspx", "AsyncPage.aspx");
+                       WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageWithAdapter.aspx", "PageWithAdapter.aspx");
                        WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.RedirectOnError.aspx", "RedirectOnError.aspx");
                        WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.ClearErrorOnError.aspx", "ClearErrorOnError.aspx");
 #else
@@ -129,7 +133,7 @@ namespace MonoTests.System.Web.UI {
                        WebTest.CopyResource (GetType (), "PageLifecycleTest.aspx", "PageLifecycleTest.aspx");
                        WebTest.CopyResource (GetType (), "PageValidationTest.aspx", "PageValidationTest.aspx");
                        WebTest.CopyResource (GetType (), "AsyncPage.aspx", "AsyncPage.aspx");
-                       WebTest.CopyResource (GetType (), "AsyncPage.aspx", "AsyncPage.aspx");
+                       WebTest.CopyResource (GetType (), "PageWithAdapter.aspx", "PageWithAdapter.aspx");
                        WebTest.CopyResource (GetType (), "RedirectOnError.aspx", "RedirectOnError.aspx");
                        WebTest.CopyResource (GetType (), "ClearErrorOnError.aspx", "ClearErrorOnError.aspx");
 #endif
@@ -392,6 +396,80 @@ namespace MonoTests.System.Web.UI {
                        Assert.AreEqual (1, page.GetValidators ("VG1").Count, "Page_ValidationGroup#5");
                        Assert.AreEqual (1, page.GetValidators ("VG2").Count, "Page_ValidationGroup#6");
                }
+
+               [Test]
+               [Category("NunitWeb")]
+               public void InitOutputCache_UsesAdapter ()
+               {
+                       WebTest t = new WebTest ("PageWithAdapter.aspx");
+                       
+                       t.Invoker = PageInvoker.CreateOnLoad (InitOutputCache_UsesAdapter_OnLoad);
+                       t.Run ();
+               }
+                               
+               public static void InitOutputCache_UsesAdapter_OnLoad (Page p)
+               {
+                       Assert.IsTrue (p.Response.Cache.VaryByHeaders ["header-from-aspx"], 
+                               "InitOutputCache_UsesAdapter #1");
+                       Assert.IsTrue (p.Response.Cache.VaryByParams ["param-from-aspx"], 
+                               "InitOutputCache_UsesAdapter #2");
+                       Assert.IsTrue (p.Response.Cache.VaryByHeaders ["header-from-adapter"], 
+                               "InitOutputCache_UsesAdapter #3");
+                       Assert.IsTrue (p.Response.Cache.VaryByParams ["param-from-adapter"], 
+                               "InitOutputCache_UsesAdapter #4");
+               }
+               
+               [Test]
+               [Category("NunitWeb")]
+               public void PageStatePersister_UsesAdapter ()
+               {
+                       WebTest t = new WebTest ("PageWithAdapter.aspx");
+                       t.Invoker = PageInvoker.CreateOnLoad (PageStatePersister_UsesAdapter_OnLoad);
+                       t.Run ();
+               }
+               
+               public static void PageStatePersister_UsesAdapter_OnLoad (Page p)
+               {
+                       TestPageWithAdapter pageWithAdapter = (TestPageWithAdapter) p;
+                       Assert.IsTrue (pageWithAdapter.PageStatePersister is TestPersister, 
+                               "PageStatePersister_UsesAdapter #1");
+               }
+               
+               [Test]
+               [Category("NunitWeb")]
+               public void ScriptUsesAdapter ()
+               {
+                       WebTest t = new WebTest ("PageWithAdapter.aspx");
+                       string html = t.Run ();
+                       Assert.IsTrue(html.IndexOf("var theForm = /* testFormReference */document.forms[") != -1, "ScriptUsesAdapter #1");
+               }
+
+               [Test]
+               [Category("NunitWeb")]
+               public void DeterminePostBackMode_UsesAdapter ()
+               {
+                       WebTest t = new WebTest ("PageWithAdapter.aspx");
+                       t.Run ();
+                       t.Request = new FormRequest (t.Response, "form1");
+                       t.Invoker = PageInvoker.CreateOnInit(DeterminePostBackMode_UsesAdapter_OnInit);
+                       t.Run ();
+               }
+               
+               public static void DeterminePostBackMode_UsesAdapter_OnInit (Page p)
+               {
+                       HtmlInputHidden h = new HtmlInputHidden();
+                       h.ID = "DeterminePostBackModeTestField";
+                       p.Controls.Add(h);
+                       p.Load += new EventHandler(DeterminePostBackMode_UsesAdapter_OnLoad);
+               }
+               
+               public static void DeterminePostBackMode_UsesAdapter_OnLoad(object source, EventArgs args)
+               {
+                       Page p = (Page)source;
+                       HtmlInputHidden h = (HtmlInputHidden)p.FindControl("DeterminePostBackModeTestField");
+                       Assert.AreEqual("DeterminePostBackModeTestValue", h.Value, 
+                               "DeterminePostBackMode #1");
+               }
 #endif
 #if NET_2_0
 
@@ -1287,4 +1365,95 @@ namespace MonoTests.System.Web.UI {
                        WebTest.Unload ();
                }
        }
+
+#if NET_2_0
+       class TestAdapter : global::System.Web.UI.Adapters.PageAdapter
+       {
+               public override StringCollection CacheVaryByParams {
+                       get {
+                               StringCollection paramNames = new StringCollection();
+                               paramNames.AddRange (new string[] {"param-from-adapter"});
+                               return paramNames;
+                       }
+               }
+
+               public override StringCollection CacheVaryByHeaders {
+                       get {
+                               StringCollection headerNames = new StringCollection();
+                               headerNames.AddRange (new string[] {"header-from-adapter"});
+                               return headerNames;
+                       }
+               }
+               
+               PageStatePersister persister;
+               public override PageStatePersister GetStatePersister ()
+               {
+                       if (persister == null)
+                               persister = new TestPersister(Page);
+                       return persister;
+               }
+               
+               protected internal override string GetPostBackFormReference (string formId)
+               {
+                       return String.Format("/* testFormReference */{0}", 
+                               base.GetPostBackFormReference (formId));
+               }
+               
+               public override NameValueCollection DeterminePostBackMode ()
+               {
+                       NameValueCollection origRequestValues = base.DeterminePostBackMode ();
+                       if (origRequestValues == null)
+                               return null;
+                       NameValueCollection requestValues = new NameValueCollection ();
+                       requestValues.Add (origRequestValues);
+                       requestValues ["DeterminePostBackModeTestField"] 
+                               = "DeterminePostBackModeTestValue";
+                       return requestValues;
+               }
+               
+               internal new void RenderPostBackEvent (HtmlTextWriter w,
+                                                      string target,
+                                                      string argument,
+                                                      string softKeyLabel,
+                                                      string text,
+                                                      string postUrl,
+                                                      string accessKey,
+                                                      bool encode)
+               {
+                       base.RenderPostBackEvent (w, target, argument, softKeyLabel, text, postUrl,
+                               accessKey, encode);
+               }
+               
+       }
+       
+       class TestPersister : HiddenFieldPageStatePersister
+       {
+               public TestPersister (Page p) : base (p)
+               {
+               }
+       }
+
+       public class TestPageWithAdapter : Page
+       {
+               private global::System.Web.UI.Adapters.PageAdapter page_adapter;
+               
+               public TestPageWithAdapter () : base ()
+               {
+                       page_adapter = new TestAdapter ();
+                       WebTest t = WebTest.CurrentTest;
+                       if (t != null)
+                               t.Invoke (this);
+               }
+               
+               protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+               {
+                       return page_adapter;
+               }
+               
+               public new PageStatePersister PageStatePersister {
+                       get { return base.PageStatePersister; }
+               }
+                                       
+       }
+#endif
 }
diff --git a/mcs/class/System.Web/Test/System.Web/AppBrowsersTest.cs b/mcs/class/System.Web/Test/System.Web/AppBrowsersTest.cs
new file mode 100644 (file)
index 0000000..bb67925
--- /dev/null
@@ -0,0 +1,201 @@
+//
+// System.Web.HttpBrowserCapabilitiesTest.cs - Unit tests for System.Web.HttpBrowserCapabilities
+//
+// Author:
+//     Adar Wesley <adarw@mainsoft.com>
+//
+// Copyright (C) 2007 Mainsoft, Inc (http://www.mainsoft.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Web;
+using System.Web.UI;
+using System.IO;
+using NUnit.Framework;
+using MonoTests.SystemWeb.Framework;
+using MonoTests.System.Web.UI;
+using System.Text;
+using System.Web.Configuration;
+using System.Threading;
+
+namespace MonoTests.System.Web
+{
+       [TestFixture]
+       [Ignore ("Pending fix for bug 351878")]
+       public class AppBrowsersTest
+       {
+               [TestFixtureSetUp]
+               public void TestFixtureSetUp ()
+               {
+                       WebTest.CleanApp(); 
+                       WebTest.CopyResource(typeof(HttpBrowserCapabilitiesTest), "TestCapability.browser", 
+                               Path.Combine("App_Browsers", "TestCapability.browser"));
+                       WebTest.CopyResource (GetType (), "adapters.browser",
+                       Path.Combine("App_Browsers", "adapters.browser"));
+               }
+               
+               [TestFixtureTearDown]
+               public void TestFixtureTearDown ()
+               {
+                       WebTest.CleanApp();
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void AppBrowsersCapabilities () 
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnLoad (AppBrowsersCapabilities_OnLoad));
+                       t.Request.UserAgent = "testUserAgent";
+                       t.Run ();
+               }
+                               
+               public static void AppBrowsersCapabilities_OnLoad (Page p) 
+               {
+                       HttpRequest request = p.Request;
+                       HttpCapabilitiesBase caps = request.Browser;
+
+                       Assert.IsFalse (String.IsNullOrEmpty(caps.Browser), "Browser");
+                       Assert.AreEqual ("testUserAgent", request.UserAgent, "AppBrowsersCapabilities #1");
+                       Assert.AreEqual ("testUserAgent", caps[""], "AppBrowsersCapabilities #2");
+                       Assert.AreEqual ("default", caps["notChanged"], "AppBrowsersCapabilities #3");
+                       Assert.AreEqual ("uaInOrig:testUserAgent", caps["capturedInOrigNode"], "AppBrowsersCapabilities #4");
+                       Assert.AreEqual ("added", caps["addedInRefNode"], "AppBrowsersCapabilities #5");
+                       Assert.AreEqual ("changed", caps["changedInRefNode"], "AppBrowsersCapabilities #6");
+                       Assert.AreEqual ("uaInRef:testUserAgent", caps["capturedInRefNode"], "AppBrowsersCapabilities #7");
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void TagWriter() 
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnLoad (TagWriter_OnLoad));
+                       t.Run ();
+               }
+
+               public static void TagWriter_OnLoad (Page p) 
+               {
+                       HttpRequest request = p.Request;
+                       HttpCapabilitiesBase caps = request.Browser;
+
+                       Assert.AreEqual (typeof(CustomHtmlTextWriter), caps.TagWriter, "TagWriter #1");
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void CreateHtmlTextWriter() 
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnLoad (CreateHtmlTextWriter_OnLoad));
+                       t.Run ();
+                       Assert.IsTrue(t.Response.Body.Contains(@"renderedby=""CustomHtmlTextWriter"""), 
+                               "CreateHtmlTextWriter #2");
+               }
+
+               public static void CreateHtmlTextWriter_OnLoad (Page p) 
+               {
+                       HttpRequest request = p.Request;
+                       HttpCapabilitiesBase caps = request.Browser;
+
+                       Assert.AreEqual (typeof(CustomHtmlTextWriter),
+                               caps.CreateHtmlTextWriter(new StringWriter()).GetType(),
+                               "CreateHtmlTextWriter #1");
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void Adapter ()
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnInit (Adapter_Init));
+                       string html = t.Run ();
+               }
+               
+               public static void Adapter_Init (Page p)
+               {
+                       Customadaptercontrol ctrl = new Customadaptercontrol ();
+                       p.Controls.Add (ctrl);
+                       ctrl.Load += new EventHandler (Adapter_ctrl_Load);
+               }
+               
+               static void Adapter_ctrl_Load (object sender, EventArgs e)
+               {
+                       Assert.IsNotNull (((Customadaptercontrol) sender).Adapter, "Adapter Failed#1");
+                       Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).Adapter.ToString (),
+                               "Adapter Failed#2");
+               }
+               
+               [Test]
+               [Category ("NunitWeb")]
+               public void ResolveAdapter_1 ()
+               {
+                       WebTest t = new WebTest (PageInvoker.CreateOnInit (ResolveAdapter_Init));
+                       string html = t.Run ();
+               }
+               
+               public static void ResolveAdapter_Init (Page p)
+               {
+                       Customadaptercontrol ctrl = new Customadaptercontrol ();
+                       p.Controls.Add (ctrl);
+                       ctrl.Load += new EventHandler (ResolveAdapter_ctrl_Load);
+
+                       Customadaptercontrol derivedCtrl = new DerivedCustomadaptercontrol ();
+                       p.Controls.Add (derivedCtrl);
+                       derivedCtrl.Load += new EventHandler (ResolveAdapter_derivedCtrl_Load);
+               }
+               
+               static void ResolveAdapter_ctrl_Load (object sender, EventArgs e)
+               {
+                       Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#1");
+                       Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (),
+                               "ResolveAdapter Failed#2");
+               }
+               
+               static void ResolveAdapter_derivedCtrl_Load (object sender, EventArgs e)
+               {
+                       Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#2");
+                       Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (),
+                               "ResolveAdapter Failed#2");
+               }
+       }
+       
+       public class CustomHtmlTextWriter : HtmlTextWriter
+       {
+               public CustomHtmlTextWriter (TextWriter tw)
+                       : base (tw)
+               {
+               }
+               
+               public override void WriteBeginTag(string s)
+               {
+                       AddAttribute("renderedby", "CustomHtmlTextWriter");
+                       base.WriteBeginTag(s);
+               }
+       }
+       
+       class DerivedCustomadaptercontrol : Customadaptercontrol
+       {
+               internal  DerivedCustomadaptercontrol () : base ()
+               {
+               }
+       }
+
+
+}
+#endif
index 2106be78b81ca65e6e17d460a57c42c392af3a10..d8bc552154bfa86f06c9fe67419b307dc6ed808f 100644 (file)
@@ -1,3 +1,15 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * AppBrowsersTest.cs: added.  Includes tests for Control.Adapter,
+       Control.ResolveAdapter, Control.TagWriter, and
+       Control.CreateHtmlTextWriter, when using App_Browsers/*.browser files.
+       AppBrowsersTest is currently tagged [Ignore], pending a fix for 
+       bug #351878.
+       
+       * HttpRuntimeTest.cs: added. Includes test for 
+       HttpRuntime.UnloadAppDomain().  Marked [Ignore], pending a fix for
+       bug #351878.
+       
 2008-01-16  Juraj Skripsky  <js@hotfeet.ch>
 
        * HttpRequestTest.cs (TestReferer): added test for invalid referer url.
diff --git a/mcs/class/System.Web/Test/System.Web/HttpRuntimeTest.cs b/mcs/class/System.Web/Test/System.Web/HttpRuntimeTest.cs
new file mode 100644 (file)
index 0000000..52439e9
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// System.Web.HttpRuntimeTest.cs - Unit tests for System.Web.HttpRuntime
+//
+// Author:
+//     Dean Brettle <dean@brettle.com>
+//
+// Copyright (C) 2007 Dean Brettle
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Web;
+using NUnit.Framework;
+using MonoTests.SystemWeb.Framework;
+using System.Web.UI;
+using System.Threading;
+
+namespace MonoTests.System.Web
+{
+       [TestFixture]
+       public class HttpRuntimeTest
+       {
+
+               [Test]
+               [Category ("NunitWeb")]
+               [Ignore ("Pending fix for bug 351878")]
+               public void UnloadAppDomain () 
+               {
+                               WebTest t = new WebTest (PageInvoker.CreateOnLoad (UnloadAppDomain_OnLoad));
+                               t.Run ();
+               }
+               
+               public static void UnloadAppDomain_OnLoad (Page p) 
+               {
+                       HttpRuntime.UnloadAppDomain();
+               }
+
+               [Test]
+               [Category ("NunitWeb")]
+               [Ignore ("Pending fix for bug 351878")]
+               [Explicit]
+               public void UnloadAppDomain100Times () 
+               {
+                       for (int i = 0; i < 100; i++)
+                               UnloadAppDomain();
+               }
+
+       }
+}
index f820f092fdc606c911e19ac10702fe07ccb2f818..de361a02b03e87678198a3c528d3411ecc4d6b12 100644 (file)
@@ -1,3 +1,24 @@
+2008-03-09  Dean Brettle <dean@brettle.com> 
+
+       * add new resources: 
+               PageWithAdapter.aspx for PageTest and PageAdapterTest.
+               TestCapability.browser for AppBrowsersTest.
+
+       * NunitWebResources/adapters.browser, 
+       NunitWebResources/AppBrowsersTest.browser: modified to support
+       testing reference nodes with captures, and adapters.
+
+       * NunitWeb/NunitWeb/WebTest.cs: ensure that, during AppDomain
+       unload, no new requests are sent to the app host and any
+       pending requests are completed before the the unload occurs.
+       Also added WebTest.AppUnloaded event that tests can use to wait
+       for the app to unload (e.g. after touching Global.asax), and 
+       WebTest.CleanApp() which can be called to restart the app with
+       the a skeleton directory structure.  Tests which add files that
+       could effect other tests (e.g. App_Browsers/*.browser files) should
+       call WebTest.CleanApp() during TearDown to return the app to a 
+       pristine environment.
+       
 2008-01-08  Dean Brettle <dean@brettle.com> 
  
        * NunitWeb/NunitWeb/WebTest.cs: copy .mdb or .pdb files with
index fbdf2d914fe15e1455f94df61cdc33d0833b6089..b95abc440b95327847badcf7bfa8f528afaabe9a 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-07  Dean Brettle <dean@brettle.com> 
+
+       * HtmlAgilityPack/AssemblyInfo.cs: made assembly delay signed so that 
+       tests can access System.Web internals now that System.Web is
+       InternalsVisibleTo this assembly.
+
 2007-03-06  Vladimir Krasniv  <vladimirk@mainsoft.com>
        
        * reference20: added reference test for PageDirectories tests
index 65ddb468432e78bc62a736276e52011f90d58413..e2f207a1098e81469bc069504865db447e393bfe 100644 (file)
@@ -62,3 +62,7 @@ using System.Runtime.CompilerServices;
 //   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
 //       documentation for more information on this.
 //
+#if !(TARGET_JVM || TARGET_DOTNET)
+[assembly: AssemblyDelaySign (true)]
+[assembly: AssemblyKeyFile ("../winfx.pub")]
+#endif
index 0225b535a350f278d98aba7756d5e01eb78a2eca..1662c333c2df1cad7060ce47d3c49e46a6e571c3 100644 (file)
@@ -5,7 +5,10 @@
 using System;
 using System.Reflection;
 using System.IO;
+using System.Web;
 using System.Web.Hosting;
+using System.Web.UI;
+using System.Threading;
 
 namespace MonoTests.SystemWeb.Framework
 {
@@ -122,11 +125,16 @@ namespace MonoTests.SystemWeb.Framework
                {
                        if (Request.Url == null)
                                Request.Url = Invoker.GetDefaultUrl ();
-                       WebTest newTestInstance = Host.Run (this);
-                       CopyFrom (newTestInstance);
+                       _unloadHandler.StartingRequest();
+                       try {
+                               WebTest newTestInstance = Host.Run (this);
+                               CopyFrom (newTestInstance);
+                       } finally {
+                               _unloadHandler.FinishedRequest();
+                       }
                        return _response.Body;
                }
-
+               
                private void CopyFrom (WebTest newTestInstance)
                {
                        this._invoker = newTestInstance._invoker;
@@ -188,21 +196,19 @@ namespace MonoTests.SystemWeb.Framework
                /// <summary>
                /// Unload the web appdomain and delete the temporary application root
                /// directory.
-               /// Is never called.
                /// </summary>
-               static void RealUnload ()
+               public static void CleanApp ()
                {
 #if !TARGET_JVM
                        if (host != null) {
-                               AppDomain oldDomain = host.AppDomain;
-                               if (oldDomain == AppDomain.CurrentDomain)
-                               {
-                                       Console.Error.WriteLine ("Some nasty runtime bug happened");
-                                       throw new Exception ("Some nasty runtime bug happened");
-                               }
-                               host = null;
-                               AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, null);
-                               AppDomain.Unload (oldDomain);
+                               lock (_appUnloadedSync) {
+                                       EventHandler handler = new EventHandler(PulseAppUnloadedSync);
+                                       WebTest.AppUnloaded += handler;
+                                       WebTest t = new WebTest (PageInvoker.CreateOnLoad (UnloadAppDomain_OnLoad));
+                                       t.Run ();
+                                       Monitor.Wait(_appUnloadedSync);
+                                       WebTest.AppUnloaded -= handler;
+                               }                       
                        }
                        if (baseDir != null) {
                                Directory.Delete (baseDir, true);
@@ -211,6 +217,19 @@ namespace MonoTests.SystemWeb.Framework
                        }
 #endif
                }
+               
+               private static object _appUnloadedSync = new object();
+               
+               private static void PulseAppUnloadedSync(object source, EventArgs args)
+               {
+                       lock (_appUnloadedSync)
+                               Monitor.PulseAll(_appUnloadedSync);
+               }
+
+               public static void UnloadAppDomain_OnLoad (Page p) 
+               {
+                       HttpRuntime.UnloadAppDomain();
+               }
 
                public static void Unload () {}
 
@@ -326,7 +345,7 @@ namespace MonoTests.SystemWeb.Framework
 #endif
                }
 
-               private static void EnsureHosting ()
+               public static void EnsureHosting ()
                {
                        if (host != null)
                                return;
@@ -347,9 +366,60 @@ namespace MonoTests.SystemWeb.Framework
                        host = (MyHost) ApplicationHost.CreateApplicationHost (typeof (MyHost), VIRTUAL_BASE_DIR, baseDir);
                        AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, host);
                        host.AppDomain.SetData (HOST_INSTANCE_NAME, host);
+                       host.AppDomain.DomainUnload += new EventHandler (_unloadHandler.OnUnload);
 #endif
                }
 
+               private static UnloadHandler _unloadHandler = new UnloadHandler();
+                               
+               public class UnloadHandler : MarshalByRefObject
+               {
+                       AutoResetEvent _unloaded = new AutoResetEvent(false);
+                       
+                       int _numRequestsPending = 0;
+                       object _syncUnloading = new object();
+                       object _syncNumRequestsPending = new object();
+                       
+                       internal void StartingRequest()
+                       {
+                               // If the app domain is about to unload, wait
+                               lock (_syncUnloading)
+                                       lock (_syncNumRequestsPending)
+                                               _numRequestsPending++;
+                       }
+                       
+                       internal void FinishedRequest()
+                       {
+                               // Let any unloading continue once there are not requests pending
+                               lock (_syncNumRequestsPending) {
+                                       _numRequestsPending--;
+                                       if (_numRequestsPending == 0)
+                                               Monitor.PulseAll(_syncNumRequestsPending);
+                               }
+                       }
+                       
+                       public void OnUnload (object o, EventArgs args)
+                       {
+                               // Block new requests from starting
+                               lock (_syncUnloading) {
+                                       // Wait for pending requests to finish
+                                       lock (_syncNumRequestsPending) {
+                                               while (_numRequestsPending > 0)
+                                                       Monitor.Wait(_syncNumRequestsPending);
+                                       }
+                                       // Clear the host so that it will be created again on the next request
+                                       AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, null);
+                                       WebTest.host = null;
+                                       
+                                       EventHandler handler = WebTest.AppUnloaded;
+                                       if (handler != null)
+                                               handler(this, null);
+                               }
+                       }
+               }
+
+               public static event EventHandler AppUnloaded;
+                       
 #if !TARGET_JVM
                const string VIRTUAL_BASE_DIR = "/NunitWeb";
                private static string baseDir;
diff --git a/mcs/class/System.Web/Test/mainsoft/NunitWebResources/PageWithAdapter.aspx b/mcs/class/System.Web/Test/mainsoft/NunitWebResources/PageWithAdapter.aspx
new file mode 100644 (file)
index 0000000..8c30aaa
--- /dev/null
@@ -0,0 +1,18 @@
+<%@ Page Language="C#" AutoEventWireup="true" inherits="MonoTests.System.Web.UI.TestPageWithAdapter" %>
+<%@ OutputCache duration="1" VaryByHeader="header-from-aspx" VaryByParam="*;param-from-aspx" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head runat="server">
+    <title>Untitled Page</title>
+    <script runat="server">
+    </script>
+</head>
+<body>
+    <form id="form1" runat="server">
+    <div>
+    
+    </div>
+    </form>
+</body>
+</html>
diff --git a/mcs/class/System.Web/Test/mainsoft/NunitWebResources/TestCapability.browser b/mcs/class/System.Web/Test/mainsoft/NunitWebResources/TestCapability.browser
new file mode 100644 (file)
index 0000000..32d5fd8
--- /dev/null
@@ -0,0 +1,22 @@
+<browsers>
+       <defaultBrowser id="Default">
+               <capture>
+               </capture>
+               <capabilities>
+               </capabilities>
+               <controlAdapters />
+       </defaultBrowser>
+       <browser id="Default">
+               <identification>
+                       <userAgent match="^(?'capturename'.*)$" />
+               </identification>
+               <capture>
+               </capture>
+               <capabilities>
+                       <capability name="notChanged" value="default" />
+                       <capability name="changedInRefNode" value="unchanged" />
+               <capability name="capturedInDefaultNode" value="ua:${capturename}" />
+               </capabilities>
+               <controlAdapters />
+       </browser>
+</browsers>
index 104627ea30d33c736a6ac8ac731f7851368247b0..c43013c7450c881fa4069d3e98060be166b6d990 100644 (file)
@@ -1,14 +1,23 @@
-<!--\r
-    You can find existing browser definitions at\r
-    <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers\r
--->\r
-<browsers>\r
-  <!--browser refID="Default">\r
-    <controlAdapters>\r
-      <adapter \r
-            controlType="MonoTests.System.Web.UI.Customadaptercontrol, MonoTests.System.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"\r
-            adapterType="MonoTests.System.Web.UI.Customadapter, MonoTests.System.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" \r
-      />\r
-    </controlAdapters>\r
-  </browser-->\r
-</browsers>
\ No newline at end of file
+<!--
+    You can find existing browser definitions at
+    <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
+-->
+<browsers>
+  <browser refID="Default">
+       <capture>
+               <userAgent match="^(?'refuacapturename'.*)$" />
+       </capture>
+    <controlAdapters markupTextWriterType="MonoTests.System.Web.CustomHtmlTextWriter, System.Web_test_net_2_0">
+      <adapter 
+            controlType="MonoTests.System.Web.UI.Customadaptercontrol, System.Web_test_net_2_0"
+            adapterType="MonoTests.System.Web.UI.Customadapter, System.Web_test_net_2_0" 
+      />
+    </controlAdapters>
+    <capabilities>
+       <capability name="addedInRefNode" value="added" />
+       <capability name="changedInRefNode" value="changed" />
+       <capability name="capturedInOrigNode" value="uaInOrig:${capturename}" />
+       <capability name="capturedInRefNode" value="uaInRef:${refuacapturename}" />
+    </capabilities>
+  </browser>
+</browsers>