made Spring.NET partial trust ready
This commit is contained in:
@@ -21,19 +21,19 @@ public partial class DataBinding_EmployeeInfo_Default : Spring.Web.UI.Page
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtId.Text", "Employee.Id");
|
||||
BindingManager.AddBinding("txtFirstName.Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("txtLastName.Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("txtDOB.Text", "Employee.DateOfBirth");
|
||||
BindingManager.AddBinding("txtSalary.Text", "Employee.Salary");
|
||||
BindingManager.AddBinding("rbgGender.Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("ddlAddressType.SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("txtStreet1.Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("txtStreet2.Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("txtCity.Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("txtState.Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("txtPostalCode.Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("txtCountry.Text", "Employee.MailingAddress.Country");
|
||||
BindingManager.AddBinding("FindControl('txtId').Text", "Employee.Id");
|
||||
BindingManager.AddBinding("FindControl('txtFirstName').Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("FindControl('txtLastName').Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("FindControl('txtDOB').Text", "Employee.DateOfBirth");
|
||||
BindingManager.AddBinding("FindControl('txtSalary').Text", "Employee.Salary");
|
||||
BindingManager.AddBinding("FindControl('rbgGender').Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("FindControl('ddlAddressType').SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("FindControl('txtStreet1').Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("FindControl('txtStreet2').Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("FindControl('txtCity').Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("FindControl('txtState').Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("FindControl('txtPostalCode').Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("FindControl('txtCountry').Text", "Employee.MailingAddress.Country");
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%@ Page Language="C#" EnableViewState="false" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="DataBinding_EventHandling_Default" %>
|
||||
<%@ Page Language="C#" Debug="true" EnableViewState="false" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="DataBinding_EventHandling_Default" %>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Web.UI.WebControls;
|
||||
using Spring.DataBinding;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,8 +23,8 @@ public partial class DataBinding_EventHandling_Default : Spring.Web.UI.Page
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtName.Text", "Name");
|
||||
BindingManager.AddBinding("lblName.Text", "Name", BindingDirection.TargetToSource);
|
||||
BindingManager.AddBinding("FindControl('txtName').Text", "Name");
|
||||
BindingManager.AddBinding("FindControl('lblName').Text", "Name", BindingDirection.TargetToSource);
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
||||
@@ -22,8 +22,8 @@ public partial class DataBinding_HelloWorld_Default : Spring.Web.UI.Page
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtName.Text", "Name");
|
||||
BindingManager.AddBinding("lblName.Text", "Name", BindingDirection.TargetToSource);
|
||||
BindingManager.AddBinding("FindControl('txtName').Text", "Name");
|
||||
BindingManager.AddBinding("FindControl('lblName').Text", "Name", BindingDirection.TargetToSource);
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
||||
@@ -26,19 +26,19 @@ public partial class DataBinding_Lists_Default : Page
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtId.Text", "Employee.Id");
|
||||
BindingManager.AddBinding("txtFirstName.Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("FindControl('txtId').Text", "Employee.Id");
|
||||
BindingManager.AddBinding("FindControl('txtFirstName').Text", "Employee.FirstName");
|
||||
|
||||
// this is rather verbose to show how it works
|
||||
|
||||
// the formatter must convert between ListControl values and domain objects identified by these values (e.g. a key)
|
||||
IFormatter dsFormatter = new DataSourceItemFormatter("DataSource", "DataValueField");
|
||||
// bind the lstHobbies control to Employee.Hobbies IList
|
||||
MultipleSelectionListControlBinding listBinding = new MultipleSelectionListControlBinding("lstHobbies", "Employee.Hobbies", BindingDirection.Bidirectional, dsFormatter);
|
||||
MultipleSelectionListControlBinding listBinding = new MultipleSelectionListControlBinding("FindControl('lstHobbies')", "Employee.Hobbies", BindingDirection.Bidirectional, dsFormatter);
|
||||
BindingManager.AddBinding(listBinding);
|
||||
|
||||
// use simple name=value binding
|
||||
BindingManager.AddBinding(new MultipleSelectionListControlBinding("lstFavoriteFood", "Employee.FavoriteFood", BindingDirection.Bidirectional, new NullFormatter()));
|
||||
BindingManager.AddBinding(new MultipleSelectionListControlBinding("FindControl('lstFavoriteFood')", "Employee.FavoriteFood", BindingDirection.Bidirectional, new NullFormatter()));
|
||||
}
|
||||
|
||||
protected override void OnInitializeControls(EventArgs e)
|
||||
|
||||
@@ -18,22 +18,22 @@ public partial class EmployeeInfoEditor : Spring.Web.UI.UserControl
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtId.Text", "Employee.Id")
|
||||
BindingManager.AddBinding("FindControl('txtId').Text", "Employee.Id")
|
||||
.SetErrorMessage("ID has to be an integer", "id.errors", "summary");
|
||||
BindingManager.AddBinding("txtFirstName.Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("txtLastName.Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("txtDOB.Text", "Employee.DateOfBirth")
|
||||
BindingManager.AddBinding("FindControl('txtFirstName').Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("FindControl('txtLastName').Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("FindControl('txtDOB').Text", "Employee.DateOfBirth")
|
||||
.SetErrorMessage("Invalid date value", "dob.errors", "summary");
|
||||
BindingManager.AddBinding("txtSalary.Text", "Employee.Salary", new CurrencyFormatter())
|
||||
BindingManager.AddBinding("FindControl('txtSalary').Text", "Employee.Salary", new CurrencyFormatter())
|
||||
.SetErrorMessage("Salary must be a valid currency value.", "salary.errors", "summary");
|
||||
BindingManager.AddBinding("rbgGender.Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("ddlAddressType.SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("txtStreet1.Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("txtStreet2.Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("txtCity.Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("txtState.Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("txtPostalCode.Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("txtCountry.Text", "Employee.MailingAddress.Country");
|
||||
BindingManager.AddBinding("FindControl('rbgGender').Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("FindControl('ddlAddressType').SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("FindControl('txtStreet1').Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("FindControl('txtStreet2').Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("FindControl('txtCity').Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("FindControl('txtState').Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("FindControl('txtPostalCode').Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("FindControl('txtCountry').Text", "Employee.MailingAddress.Country");
|
||||
}
|
||||
|
||||
protected void btnSave_Click(object sender, EventArgs e)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
so you can see how Employee object was populated by the framework.
|
||||
</p>
|
||||
<!-- this summary control captures validation errors on this page -->
|
||||
<spring:ValidationSummary ID="summary" Provider="summary" ValidationContainerName="Editor" runat="server" />
|
||||
<spring:ValidationSummary ID="summary" Provider="summary" runat="server" />
|
||||
<table cellpadding="3" cellspacing="3" border="0">
|
||||
<tr>
|
||||
<td>Employee ID:</td>
|
||||
|
||||
@@ -22,22 +22,26 @@ public partial class DataBinding_RobustEmployeeInfo_Default : Spring.Web.UI.Page
|
||||
/// </summary>
|
||||
protected override void InitializeDataBindings()
|
||||
{
|
||||
BindingManager.AddBinding("txtId.Text", "Employee.Id")
|
||||
// the line below would also work in full trusted environments due to control members
|
||||
// being generated as protected members by ASP.NET:
|
||||
// BindingManager.AddBinding("txtId.Text", "Employee.Id")
|
||||
|
||||
BindingManager.AddBinding("FindControl('txtId').Text", "Employee.Id")
|
||||
.SetErrorMessage("ID has to be an integer", "id.errors"); // send msg to "id.errors" provider
|
||||
BindingManager.AddBinding("txtFirstName.Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("txtLastName.Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("txtDOB.Text", "Employee.DateOfBirth")
|
||||
BindingManager.AddBinding("FindControl('txtFirstName').Text", "Employee.FirstName");
|
||||
BindingManager.AddBinding("FindControl('txtLastName').Text", "Employee.LastName");
|
||||
BindingManager.AddBinding("FindControl('txtDOB').Text", "Employee.DateOfBirth")
|
||||
.SetErrorMessage("Invalid date value", "dob.errors");
|
||||
BindingManager.AddBinding("txtSalary.Text", "Employee.Salary", new CurrencyFormatter())
|
||||
BindingManager.AddBinding("FindControl('txtSalary').Text", "Employee.Salary", new CurrencyFormatter())
|
||||
.SetErrorMessage("Salary must be a valid currency value.", "salary.errors");
|
||||
BindingManager.AddBinding("rbgGender.Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("ddlAddressType.SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("txtStreet1.Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("txtStreet2.Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("txtCity.Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("txtState.Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("txtPostalCode.Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("txtCountry.Text", "Employee.MailingAddress.Country");
|
||||
BindingManager.AddBinding("FindControl('rbgGender').Value", "Employee.Gender");
|
||||
BindingManager.AddBinding("FindControl('ddlAddressType').SelectedValue", "Employee.MailingAddress.AddressType");
|
||||
BindingManager.AddBinding("FindControl('txtStreet1').Text", "Employee.MailingAddress.Street1");
|
||||
BindingManager.AddBinding("FindControl('txtStreet2').Text", "Employee.MailingAddress.Street2");
|
||||
BindingManager.AddBinding("FindControl('txtCity').Text", "Employee.MailingAddress.City");
|
||||
BindingManager.AddBinding("FindControl('txtState').Text", "Employee.MailingAddress.State");
|
||||
BindingManager.AddBinding("FindControl('txtPostalCode').Text", "Employee.MailingAddress.PostalCode");
|
||||
BindingManager.AddBinding("FindControl('txtCountry').Text", "Employee.MailingAddress.Country");
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Spring.Web allows for "symbolic" names for navigation targets and navigate to such a target by
|
||||
calling SetResult( symbolicName ) on the page object.
|
||||
</p>
|
||||
<spring:DataBindingPanel runat="server">
|
||||
<spring:DataBindingPanel ID="ctlDataBindingPanel" runat="server">
|
||||
<table cellpadding="3" cellspacing="3" border="0">
|
||||
<spring:Panel VisibleIf="Context.Request['fromInvalidInput'] != null" runat="server">
|
||||
<tr>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="spring">
|
||||
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
|
||||
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
|
||||
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" requirePermission="false"/>
|
||||
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
<sectionGroup name="common">
|
||||
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
|
||||
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<!-- to see logging output in the attached debugger -->
|
||||
@@ -18,6 +18,13 @@
|
||||
</logging>
|
||||
</common>
|
||||
<system.web>
|
||||
|
||||
<securityPolicy>
|
||||
<trustLevel name="Custom" policyFile="web_mediumtrust.config"/>
|
||||
</securityPolicy>
|
||||
<trust level="Full" /> <!-- install Spring assemblies in GAC and change to level to 'Custom' to run in partial trust -->
|
||||
|
||||
<globalization culture="en-US" uiCulture="en-US"/>
|
||||
<customErrors mode="Off"/>
|
||||
<compilation debug="true">
|
||||
</compilation>
|
||||
@@ -31,9 +38,9 @@
|
||||
-->
|
||||
<httpModules>
|
||||
<add name="SpringModule" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
|
||||
<add name="HtmlCommentAppender" type="HtmlCommentAppenderModule"/>
|
||||
<!-- this custom module is only for DI demonstration purposes -->
|
||||
</httpModules>
|
||||
<!-- this custom module is only for DI demonstration purposes -->
|
||||
<add name="HtmlCommentAppender" type="HtmlCommentAppenderModule"/>
|
||||
</httpModules>
|
||||
<httpHandlers>
|
||||
<add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
|
||||
</httpHandlers>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<configuration>
|
||||
<mscorlib>
|
||||
<security>
|
||||
<policy>
|
||||
<PolicyLevel version="1">
|
||||
<SecurityClasses>
|
||||
<SecurityClass Name="AllMembershipCondition" Description="System.Security.Policy.AllMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="AspNetHostingPermission" Description="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="DnsPermission" Description="System.Net.DnsPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="EnvironmentPermission" Description="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="FileIOPermission" Description="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="FirstMatchCodeGroup" Description="System.Security.Policy.FirstMatchCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="IsolatedStorageFilePermission" Description="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="NamedPermissionSet" Description="System.Security.NamedPermissionSet"/>
|
||||
<SecurityClass Name="PrintingPermission" Description="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
|
||||
<SecurityClass Name="SecurityPermission" Description="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="SmtpPermission" Description="System.Net.Mail.SmtpPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="SqlClientPermission" Description="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="StrongNameMembershipCondition" Description="System.Security.Policy.StrongNameMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="UIPermission" Description="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="UnionCodeGroup" Description="System.Security.Policy.UnionCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="UrlMembershipCondition" Description="System.Security.Policy.UrlMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="WebPermission" Description="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="ZoneMembershipCondition" Description="System.Security.Policy.ZoneMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<SecurityClass Name="ReflectionPermission" Description="System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/></SecurityClasses>
|
||||
<NamedPermissionSets>
|
||||
<PermissionSet class="NamedPermissionSet" version="1" Unrestricted="true" Name="FullTrust" Description="Allows full access to all resources"/>
|
||||
<PermissionSet class="NamedPermissionSet" version="1" Name="Nothing" Description="Denies all resources, including the right to execute"/>
|
||||
<PermissionSet class="NamedPermissionSet" version="1" Name="ASP.Net">
|
||||
<IPermission class="AspNetHostingPermission" version="1" Level="Medium"/>
|
||||
<IPermission class="DnsPermission" version="1" Unrestricted="true"/>
|
||||
<IPermission class="EnvironmentPermission" version="1" Read="TEMP;TMP;USERNAME;OS;COMPUTERNAME"/>
|
||||
<IPermission class="FileIOPermission" version="1" Read="$AppDir$" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$"/>
|
||||
<IPermission class="IsolatedStorageFilePermission" version="1" Allowed="AssemblyIsolationByUser" UserQuota="9223372036854775807"/>
|
||||
<IPermission class="PrintingPermission" version="1" Level="DefaultPrinting"/>
|
||||
<IPermission class="SecurityPermission" version="1" Flags="Assertion, Execution, ControlThread, ControlPrincipal, RemotingConfiguration"/>
|
||||
<IPermission class="SmtpPermission" version="1" Access="Connect"/>
|
||||
<IPermission class="SqlClientPermission" version="1" Unrestricted="true"/>
|
||||
<IPermission class="WebPermission" version="1">
|
||||
<ConnectAccess>
|
||||
<URI uri="$OriginHost$"/>
|
||||
</ConnectAccess>
|
||||
</IPermission>
|
||||
<IPermission class="ReflectionPermission" version="1" Flags="RestrictedMemberAccess"/></PermissionSet>
|
||||
</NamedPermissionSets>
|
||||
<CodeGroup class="FirstMatchCodeGroup" version="1" PermissionSetName="Nothing">
|
||||
<IMembershipCondition class="AllMembershipCondition" version="1"/>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="NetCommon_Strong_Name" Description="This code group grants code signed with the NetCommon strong name full trust. ">
|
||||
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="0024000004800000940000000602000000240000525341310004000001000100f14d9774aa0ccf08735569d219a51874fc424da7375e4951e1be94416cd27ad28615485a08145acad9b624e0d71f78972051eba675e203eff9b72710b5b68ba970afdccdec36f5ccc4ae30f2962915333fbaba9801da256f0382e201b025b7bb22a835be59cca993e2dec9b8c2ce4738b697087430a37470d0889987b0af8fab"/>
|
||||
</CodeGroup>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="Spring_Strong_Name" Description="This code group grants code signed with the Spring.NET strong name full trust. ">
|
||||
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="0024000004800000940000000602000000240000525341310004000001000100b5af6fc0c5a1a93adbee2cb424fe0a23ca6430fe0620dd9a00393be236e5d8ab481c8ad4a68c35a62e474695d63658313e4f35a2f29cd38c072f73227eaec5f0b6fb6f9e0ed6ab4f105a393f709eae6cfd010febebb004dd230d51b5e8aec839b6832c21ec7ac3b6cadba8d9b8870b1ab1507cabea54dcacd2c74ea45231a3bd"/>
|
||||
</CodeGroup>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="ASP.Net">
|
||||
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="$AppDirUrl$/*"/>
|
||||
</CodeGroup>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="ASP.Net">
|
||||
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="$CodeGen$/*"/>
|
||||
</CodeGroup>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="Nothing">
|
||||
<IMembershipCondition class="ZoneMembershipCondition" version="1" Zone="MyComputer"/>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="Microsoft_Strong_Name" Description="This code group grants code signed with the Microsoft strong name full trust. ">
|
||||
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293"/>
|
||||
</CodeGroup>
|
||||
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="Ecma_Strong_Name" Description="This code group grants code signed with the ECMA strong name full trust. ">
|
||||
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="00000000000000000400000000000000"/>
|
||||
</CodeGroup>
|
||||
</CodeGroup>
|
||||
</CodeGroup>
|
||||
</PolicyLevel>
|
||||
</policy>
|
||||
</security>
|
||||
</mscorlib>
|
||||
</configuration>
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using System.Security;
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyTitle("Spring.Core")]
|
||||
@@ -29,7 +30,24 @@ using System.Security.Permissions;
|
||||
//
|
||||
// Security Permissions
|
||||
//
|
||||
// we need full, unrestricted access to reflection metadata...
|
||||
[assembly: ReflectionPermission(SecurityAction.RequestMinimum, Unrestricted=true)]
|
||||
// we need full, unrestricted access to reflection metadata...
|
||||
//[assembly: ReflectionPermission(SecurityAction.RequestMinimum, Unrestricted = true)]
|
||||
//[assembly: AssemblyKeyFile(@"C:\users\aseovic\projects\OpenSource\Spring.Net\Spring.Net.PrivateKey.keys")]
|
||||
//[assembly: AssemblyKeyFile(@"C:\projects\Spring.Net\Spring.Net.snk")]
|
||||
//[assembly: AssemblyKeyFile(@"C:\projects\Spring.Net\Spring.Net.snk")]
|
||||
[assembly: AllowPartiallyTrustedCallers]
|
||||
|
||||
[assembly: SecurityCritical]
|
||||
|
||||
#if NET_1_0 || NET_1_1
|
||||
namespace System.Security
|
||||
{
|
||||
///<summary>
|
||||
///</summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method)]
|
||||
internal class SecurityCriticalAttribute : Attribute
|
||||
{ }
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
internal class SecurityTreatAsSafeAttribute : Attribute
|
||||
{ }
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#region License
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2004 the original author or authors.
|
||||
*
|
||||
@@ -14,273 +14,277 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
using Spring.Context.Support;
|
||||
using Spring.Core.TypeResolution;
|
||||
using Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
|
||||
namespace Spring.Core.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Registry class that allows users to register and retrieve protocol handlers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Resource handler is an implementation of <see cref="IResource"/> interface
|
||||
/// that should be used to process resources with the specified protocol.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// They are used throughout the framework to access resources from various
|
||||
/// sources. For example, application context loads object definitions from the resources
|
||||
/// that are processed using one of the registered resource handlers.
|
||||
/// </para>
|
||||
/// <para>Following resource handlers are registered by default:</para>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Protocol</term>
|
||||
/// <term>Handler Type</term>
|
||||
/// <term>Description</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <description>config</description>
|
||||
/// <description><see cref="Spring.Core.IO.ConfigSectionResource"/></description>
|
||||
/// <description>Resolves the resources by loading specified configuration section from the standard .NET config file.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>file</description>
|
||||
/// <description><see cref="Spring.Core.IO.FileSystemResource"/></description>
|
||||
/// <description>Resolves filesystem resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>http</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves remote web resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>https</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves remote web resources via HTTPS.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>ftp</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves ftp resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>assembly</description>
|
||||
/// <description><see cref="Spring.Core.IO.AssemblyResource"/></description>
|
||||
/// <description>Resolves resources that are embedded into an assembly.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>web</description>
|
||||
/// <description><c>Spring.Core.IO.WebResource, Spring.Web</c>*</description>
|
||||
/// <description>Resolves resources relative to the web application's virtual directory.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// * only available in web applications.
|
||||
/// <para>
|
||||
/// Users can create and register their own protocol handlers by implementing <see cref="IResource"/> interface
|
||||
/// and mapping custom protocol name to that implementation. See <see cref="ResourceHandlersSectionHandler"/> for details
|
||||
/// on how to register custom protocol handler.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public class ResourceHandlerRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the .Net config section that contains definitions
|
||||
/// for custom resource handlers.
|
||||
/// </summary>
|
||||
private const string ResourcesSectionName = "spring/resourceHandlers";
|
||||
|
||||
private static IDictionary resourceHandlers = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
/// Registers standard and user-configured resource handlers.
|
||||
/// </summary>
|
||||
static ResourceHandlerRegistry()
|
||||
{
|
||||
lock (resourceHandlers.SyncRoot)
|
||||
{
|
||||
RegisterResourceHandler("config", typeof(ConfigSectionResource));
|
||||
RegisterResourceHandler("file", typeof(FileSystemResource));
|
||||
RegisterResourceHandler("http", typeof(UrlResource));
|
||||
RegisterResourceHandler("https", typeof(UrlResource));
|
||||
#if NET_2_0
|
||||
RegisterResourceHandler("ftp", typeof(UrlResource));
|
||||
#endif
|
||||
RegisterResourceHandler("assembly", typeof(AssemblyResource));
|
||||
|
||||
// register custom resource handlers
|
||||
ConfigurationUtils.GetSection(ResourcesSectionName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns resource handler for the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This method returns <see cref="ConstructorInfo"/> object that should be used
|
||||
/// to create an instance of the <see cref="IResource"/>-derived type by passing
|
||||
/// resource location as a parameter.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">Name of the protocol to get the handler for.</param>
|
||||
/// <returns>Resource handler constructor for the specified protocol name.</returns>
|
||||
/// <exception cref="ArgumentNullException">If <paramref name="protocolName"/> is <c>null</c>.</exception>
|
||||
public static IDynamicConstructor GetResourceHandler(string protocolName)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(protocolName, "protocolName");
|
||||
return (IDynamicConstructor) resourceHandlers[protocolName];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if a handler is registered for the specified protocol,
|
||||
/// <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
/// <param name="protocolName">Name of the protocol.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if a handler is registered for the specified protocol, <c>false</c> otherwise.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">If <paramref name="protocolName"/> is <c>null</c>.</exception>
|
||||
public static bool IsHandlerRegistered(string protocolName)
|
||||
{
|
||||
return resourceHandlers.Contains(protocolName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers resource handler and maps it to the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// If the mapping already exists, the existing mapping will be
|
||||
/// silently overwritten with the new mapping.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">
|
||||
/// The protocol to add (or override).
|
||||
/// </param>
|
||||
/// <param name="handlerTypeName">
|
||||
/// The type name of the concrete implementation of the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface that will handle
|
||||
/// the specified protocol.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="protocolName"/> is
|
||||
/// <see langword="null"/> or contains only whitespace character(s); or
|
||||
/// if the supplied <paramref name="handlerTypeName"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// If the supplied <paramref name="handlerTypeName"/> is not a
|
||||
/// <see cref="Type"/> that derives from the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface; or (having passed
|
||||
/// this first check), the supplied <paramref name="handlerTypeName"/>
|
||||
/// does not expose a constructor that takes a single
|
||||
/// <see cref="System.String"/> parameter.
|
||||
/// </exception>
|
||||
public static void RegisterResourceHandler(string protocolName, string handlerTypeName)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(protocolName, "protocolName");
|
||||
AssertUtils.ArgumentHasText(handlerTypeName, "handlerTypeName");
|
||||
|
||||
Type handlerType = TypeResolutionUtils.ResolveType(handlerTypeName);
|
||||
RegisterResourceHandler(protocolName, handlerType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers resource handler and maps it to the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// If the mapping already exists, the existing mapping will be
|
||||
/// silently overwritten with the new mapping.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">
|
||||
/// The protocol to add (or override).
|
||||
/// </param>
|
||||
/// <param name="handlerType">
|
||||
/// The concrete implementation of the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface that will handle
|
||||
/// the specified protocol.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="protocolName"/> is
|
||||
/// <see langword="null"/> or contains only whitespace character(s); or
|
||||
/// if the supplied <paramref name="handlerType"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// If the supplied <paramref name="handlerType"/> is not a
|
||||
/// <see cref="Type"/> that derives from the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface; or (having passed
|
||||
/// this first check), the supplied <paramref name="handlerType"/>
|
||||
/// does not expose a constructor that takes a single
|
||||
/// <see cref="System.String"/> parameter.
|
||||
/// </exception>
|
||||
public static void RegisterResourceHandler(string protocolName, Type handlerType)
|
||||
{
|
||||
#region Sanity Checks
|
||||
|
||||
AssertUtils.ArgumentHasText(protocolName, "protocolName");
|
||||
AssertUtils.ArgumentNotNull(handlerType, "handlerType");
|
||||
if (!typeof(IResource).IsAssignableFrom(handlerType))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("[{0}] does not implement [{1}] interface (it must).", handlerType.FullName, typeof(IResource).FullName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
lock (resourceHandlers.SyncRoot)
|
||||
{
|
||||
#if NET_2_0
|
||||
// register generic uri parser for this scheme
|
||||
if (!UriParser.IsKnownScheme(protocolName))
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using Spring.Context.Support;
|
||||
using Spring.Core.TypeResolution;
|
||||
using Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
|
||||
namespace Spring.Core.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Registry class that allows users to register and retrieve protocol handlers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Resource handler is an implementation of <see cref="IResource"/> interface
|
||||
/// that should be used to process resources with the specified protocol.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// They are used throughout the framework to access resources from various
|
||||
/// sources. For example, application context loads object definitions from the resources
|
||||
/// that are processed using one of the registered resource handlers.
|
||||
/// </para>
|
||||
/// <para>Following resource handlers are registered by default:</para>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Protocol</term>
|
||||
/// <term>Handler Type</term>
|
||||
/// <term>Description</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <description>config</description>
|
||||
/// <description><see cref="Spring.Core.IO.ConfigSectionResource"/></description>
|
||||
/// <description>Resolves the resources by loading specified configuration section from the standard .NET config file.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>file</description>
|
||||
/// <description><see cref="Spring.Core.IO.FileSystemResource"/></description>
|
||||
/// <description>Resolves filesystem resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>http</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves remote web resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>https</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves remote web resources via HTTPS.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>ftp</description>
|
||||
/// <description><see cref="Spring.Core.IO.UrlResource"/></description>
|
||||
/// <description>Resolves ftp resources.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>assembly</description>
|
||||
/// <description><see cref="Spring.Core.IO.AssemblyResource"/></description>
|
||||
/// <description>Resolves resources that are embedded into an assembly.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>web</description>
|
||||
/// <description><c>Spring.Core.IO.WebResource, Spring.Web</c>*</description>
|
||||
/// <description>Resolves resources relative to the web application's virtual directory.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// * only available in web applications.
|
||||
/// <para>
|
||||
/// Users can create and register their own protocol handlers by implementing <see cref="IResource"/> interface
|
||||
/// and mapping custom protocol name to that implementation. See <see cref="ResourceHandlersSectionHandler"/> for details
|
||||
/// on how to register custom protocol handler.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public class ResourceHandlerRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the .Net config section that contains definitions
|
||||
/// for custom resource handlers.
|
||||
/// </summary>
|
||||
private const string ResourcesSectionName = "spring/resourceHandlers";
|
||||
|
||||
private static IDictionary resourceHandlers = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
/// Registers standard and user-configured resource handlers.
|
||||
/// </summary>
|
||||
static ResourceHandlerRegistry()
|
||||
{
|
||||
lock (resourceHandlers.SyncRoot)
|
||||
{
|
||||
RegisterResourceHandler("config", typeof(ConfigSectionResource));
|
||||
RegisterResourceHandler("file", typeof(FileSystemResource));
|
||||
RegisterResourceHandler("http", typeof(UrlResource));
|
||||
RegisterResourceHandler("https", typeof(UrlResource));
|
||||
#if NET_2_0
|
||||
RegisterResourceHandler("ftp", typeof(UrlResource));
|
||||
#endif
|
||||
RegisterResourceHandler("assembly", typeof(AssemblyResource));
|
||||
|
||||
// register custom resource handlers
|
||||
ConfigurationUtils.GetSection(ResourcesSectionName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns resource handler for the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This method returns <see cref="ConstructorInfo"/> object that should be used
|
||||
/// to create an instance of the <see cref="IResource"/>-derived type by passing
|
||||
/// resource location as a parameter.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">Name of the protocol to get the handler for.</param>
|
||||
/// <returns>Resource handler constructor for the specified protocol name.</returns>
|
||||
/// <exception cref="ArgumentNullException">If <paramref name="protocolName"/> is <c>null</c>.</exception>
|
||||
public static IDynamicConstructor GetResourceHandler(string protocolName)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(protocolName, "protocolName");
|
||||
return (IDynamicConstructor)resourceHandlers[protocolName];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if a handler is registered for the specified protocol,
|
||||
/// <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
/// <param name="protocolName">Name of the protocol.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if a handler is registered for the specified protocol, <c>false</c> otherwise.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">If <paramref name="protocolName"/> is <c>null</c>.</exception>
|
||||
public static bool IsHandlerRegistered(string protocolName)
|
||||
{
|
||||
return resourceHandlers.Contains(protocolName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers resource handler and maps it to the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// If the mapping already exists, the existing mapping will be
|
||||
/// silently overwritten with the new mapping.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">
|
||||
/// The protocol to add (or override).
|
||||
/// </param>
|
||||
/// <param name="handlerTypeName">
|
||||
/// The type name of the concrete implementation of the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface that will handle
|
||||
/// the specified protocol.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="protocolName"/> is
|
||||
/// <see langword="null"/> or contains only whitespace character(s); or
|
||||
/// if the supplied <paramref name="handlerTypeName"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// If the supplied <paramref name="handlerTypeName"/> is not a
|
||||
/// <see cref="Type"/> that derives from the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface; or (having passed
|
||||
/// this first check), the supplied <paramref name="handlerTypeName"/>
|
||||
/// does not expose a constructor that takes a single
|
||||
/// <see cref="System.String"/> parameter.
|
||||
/// </exception>
|
||||
public static void RegisterResourceHandler(string protocolName, string handlerTypeName)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(protocolName, "protocolName");
|
||||
AssertUtils.ArgumentHasText(handlerTypeName, "handlerTypeName");
|
||||
|
||||
Type handlerType = TypeResolutionUtils.ResolveType(handlerTypeName);
|
||||
RegisterResourceHandler(protocolName, handlerType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers resource handler and maps it to the specified protocol name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// If the mapping already exists, the existing mapping will be
|
||||
/// silently overwritten with the new mapping.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <param name="protocolName">
|
||||
/// The protocol to add (or override).
|
||||
/// </param>
|
||||
/// <param name="handlerType">
|
||||
/// The concrete implementation of the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface that will handle
|
||||
/// the specified protocol.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="protocolName"/> is
|
||||
/// <see langword="null"/> or contains only whitespace character(s); or
|
||||
/// if the supplied <paramref name="handlerType"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// If the supplied <paramref name="handlerType"/> is not a
|
||||
/// <see cref="Type"/> that derives from the
|
||||
/// <see cref="Spring.Core.IO.IResource"/> interface; or (having passed
|
||||
/// this first check), the supplied <paramref name="handlerType"/>
|
||||
/// does not expose a constructor that takes a single
|
||||
/// <see cref="System.String"/> parameter.
|
||||
/// </exception>
|
||||
public static void RegisterResourceHandler(string protocolName, Type handlerType)
|
||||
{
|
||||
#region Sanity Checks
|
||||
|
||||
AssertUtils.ArgumentHasText(protocolName, "protocolName");
|
||||
AssertUtils.ArgumentNotNull(handlerType, "handlerType");
|
||||
if (!typeof(IResource).IsAssignableFrom(handlerType))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("[{0}] does not implement [{1}] interface (it must).", handlerType.FullName, typeof(IResource).FullName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
lock (resourceHandlers.SyncRoot)
|
||||
{
|
||||
#if NET_2_0
|
||||
SecurityCritical.ExecutePrivileged( new SecurityPermission(SecurityPermissionFlag.Infrastructure), delegate
|
||||
{
|
||||
UriParser.Register(new TolerantUriParser(), protocolName, 0);
|
||||
}
|
||||
#endif
|
||||
IDynamicConstructor ctor = GetResourceConstructor(handlerType);
|
||||
resourceHandlers[protocolName] = ctor;
|
||||
}
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
// register generic uri parser for this scheme
|
||||
if (!UriParser.IsKnownScheme(protocolName))
|
||||
{
|
||||
UriParser.Register(new TolerantUriParser(), protocolName, 0);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
IDynamicConstructor ctor = GetResourceConstructor(handlerType);
|
||||
resourceHandlers[protocolName] = ctor;
|
||||
}
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Allows to create any arbitrary Url format
|
||||
/// </summary>
|
||||
private class TolerantUriParser : GenericUriParser
|
||||
/// </summary>
|
||||
private class TolerantUriParser : GenericUriParser
|
||||
{
|
||||
private const GenericUriParserOptions DefaultOptions = GenericUriParserOptions.Default
|
||||
|GenericUriParserOptions.GenericAuthority
|
||||
|GenericUriParserOptions.AllowEmptyAuthority;
|
||||
| GenericUriParserOptions.GenericAuthority
|
||||
| GenericUriParserOptions.AllowEmptyAuthority;
|
||||
|
||||
public TolerantUriParser()
|
||||
public TolerantUriParser()
|
||||
: base(DefaultOptions)
|
||||
{}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static IDynamicConstructor GetResourceConstructor(Type handlerType)
|
||||
{
|
||||
ConstructorInfo ctor = handlerType.GetConstructor(new Type[] {typeof(string)});
|
||||
if (ctor == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("[{0}] does not have a constructor that takes a single string as an argument (it must).", handlerType.FullName));
|
||||
}
|
||||
return DynamicConstructor.Create(ctor);
|
||||
}
|
||||
}
|
||||
{ }
|
||||
}
|
||||
#endif
|
||||
|
||||
private static IDynamicConstructor GetResourceConstructor(Type handlerType)
|
||||
{
|
||||
ConstructorInfo ctor = handlerType.GetConstructor(new Type[] { typeof(string) });
|
||||
if (ctor == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("[{0}] does not have a constructor that takes a single string as an argument (it must).", handlerType.FullName));
|
||||
}
|
||||
return new SafeConstructor(ctor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using Common.Logging;
|
||||
using Spring.Globalization;
|
||||
using Spring.Validation;
|
||||
|
||||
@@ -13,6 +15,7 @@ namespace Spring.DataBinding
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private IFormatter formatter;
|
||||
|
||||
#endregion
|
||||
@@ -132,8 +135,9 @@ namespace Spring.DataBinding
|
||||
{
|
||||
DoBindTargetToSource(source, target, variables);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Warn(string.Format("Failed binding[{0}]:{1}", this.Id, ex));
|
||||
if (!SetInvalid(validationErrors)) throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,16 +273,21 @@ namespace Spring.Expressions
|
||||
{
|
||||
if (indexer == null)
|
||||
{
|
||||
Type contextType = context.GetType();
|
||||
Type[] argTypes = ReflectionUtils.GetTypes(indices);
|
||||
PropertyInfo indexerProperty = context.GetType().GetProperty("Item", BINDING_FLAGS, null, null, argTypes, null);
|
||||
string defaultMember = "Item";
|
||||
object[] atts = contextType.GetCustomAttributes(typeof(DefaultMemberAttribute), true);
|
||||
if (atts != null && atts.Length > 0)
|
||||
{
|
||||
defaultMember = ((DefaultMemberAttribute) atts[0]).MemberName;
|
||||
}
|
||||
PropertyInfo indexerProperty = contextType.GetProperty(defaultMember, BINDING_FLAGS, null, null, argTypes, null);
|
||||
if (indexerProperty == null)
|
||||
{
|
||||
throw new ArgumentException("Indexer property with specified number and types of arguments does not exist.");
|
||||
}
|
||||
else
|
||||
{
|
||||
indexer = new SafeProperty(indexerProperty);
|
||||
}
|
||||
|
||||
indexer = new SafeProperty(indexerProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using Spring.Util;
|
||||
|
||||
#if NET_2_0
|
||||
@@ -40,14 +43,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
/// <param name="target">the target instance when calling an instance method</param>
|
||||
/// <returns>the value return by the Get method</returns>
|
||||
public delegate object FieldGetterDelegate( object target );
|
||||
public delegate object FieldGetterDelegate(object target);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Set method
|
||||
/// </summary>
|
||||
/// <param name="target">the target instance when calling an instance method</param>
|
||||
/// <param name="value">the value to be set</param>
|
||||
public delegate void FieldSetterDelegate( object target, object value );
|
||||
public delegate void FieldSetterDelegate(object target, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Represents an Indexer Get method
|
||||
@@ -55,7 +58,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="target">the target instance when calling an instance method</param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns>the value return by the Get method</returns>
|
||||
public delegate object PropertyGetterDelegate( object target, params object[] index );
|
||||
public delegate object PropertyGetterDelegate(object target, params object[] index);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Set method
|
||||
@@ -63,7 +66,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="target">the target instance when calling an instance method</param>
|
||||
/// <param name="value">the value to be set</param>
|
||||
/// <param name="index"></param>
|
||||
public delegate void PropertySetterDelegate( object target, object value, params object[] index );
|
||||
public delegate void PropertySetterDelegate(object target, object value, params object[] index);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a method
|
||||
@@ -71,35 +74,35 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="target">the target instance when calling an instance method</param>
|
||||
/// <param name="args">arguments to be passed to the method</param>
|
||||
/// <returns>the value return by the method. <value>null</value> when calling a void method</returns>
|
||||
public delegate object FunctionDelegate( object target, params object[] args );
|
||||
public delegate object FunctionDelegate(object target, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a constructor
|
||||
/// </summary>
|
||||
/// <param name="args">arguments to be passed to the method</param>
|
||||
/// <returns>the new object instance</returns>
|
||||
public delegate object ConstructorDelegate( params object[] args );
|
||||
public delegate object ConstructorDelegate(params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a callback method used to create an <see cref="IDynamicProperty"/> from a <see cref="PropertyInfo"/> instance.
|
||||
/// </summary>
|
||||
internal delegate IDynamicProperty CreatePropertyCallback( PropertyInfo property );
|
||||
internal delegate IDynamicProperty CreatePropertyCallback(PropertyInfo property);
|
||||
/// <summary>
|
||||
/// Represents a callback method used to create an <see cref="IDynamicField"/> from a <see cref="FieldInfo"/> instance.
|
||||
/// </summary>
|
||||
internal delegate IDynamicField CreateFieldCallback( FieldInfo property );
|
||||
internal delegate IDynamicField CreateFieldCallback(FieldInfo property);
|
||||
/// <summary>
|
||||
/// Represents a callback method used to create an <see cref="IDynamicMethod"/> from a <see cref="MethodInfo"/> instance.
|
||||
/// </summary>
|
||||
internal delegate IDynamicMethod CreateMethodCallback( MethodInfo method );
|
||||
internal delegate IDynamicMethod CreateMethodCallback(MethodInfo method);
|
||||
/// <summary>
|
||||
/// Represents a callback method used to create an <see cref="IDynamicConstructor"/> from a <see cref="ConstructorInfo"/> instance.
|
||||
/// </summary>
|
||||
internal delegate IDynamicConstructor CreateConstructorCallback( ConstructorInfo constructor );
|
||||
internal delegate IDynamicConstructor CreateConstructorCallback(ConstructorInfo constructor);
|
||||
/// <summary>
|
||||
/// Represents a callback method used to create an <see cref="IDynamicIndexer"/> from a <see cref="PropertyInfo"/> instance.
|
||||
/// </summary>
|
||||
internal delegate IDynamicIndexer CreateIndexerCallback( PropertyInfo indexer );
|
||||
internal delegate IDynamicIndexer CreateIndexerCallback(PropertyInfo indexer);
|
||||
|
||||
/// <summary>
|
||||
/// Allows easy access to existing and creation of new dynamic relection members.
|
||||
@@ -156,14 +159,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// The base name to use for the reflection type name.
|
||||
/// </param>
|
||||
/// <returns>The type builder to use.</returns>
|
||||
internal static TypeBuilder CreateTypeBuilder( string name )
|
||||
internal static TypeBuilder CreateTypeBuilder(string name)
|
||||
{
|
||||
// Generates type name
|
||||
string typeName = String.Format( "{0}.{1}_{2}",
|
||||
ASSEMBLY_NAME, name, Guid.NewGuid().ToString( "N" ) );
|
||||
string typeName = String.Format("{0}.{1}_{2}",
|
||||
ASSEMBLY_NAME, name, Guid.NewGuid().ToString("N"));
|
||||
|
||||
ModuleBuilder module = DynamicCodeManager.GetModuleBuilder( ASSEMBLY_NAME );
|
||||
return module.DefineType( typeName, TYPE_ATTRIBUTES );
|
||||
ModuleBuilder module = DynamicCodeManager.GetModuleBuilder(ASSEMBLY_NAME);
|
||||
return module.DefineType(typeName, TYPE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -172,14 +175,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="property">Property to look up.</param>
|
||||
/// <param name="createCallback">callback function that will be called to create the dynamic property</param>
|
||||
/// <returns>An <see cref="IDynamicProperty"/> for the given property info.</returns>
|
||||
internal static IDynamicProperty GetDynamicProperty( PropertyInfo property, CreatePropertyCallback createCallback )
|
||||
internal static IDynamicProperty GetDynamicProperty(PropertyInfo property, CreatePropertyCallback createCallback)
|
||||
{
|
||||
lock (propertyCache.SyncRoot)
|
||||
{
|
||||
IDynamicProperty dynamicProperty = (IDynamicProperty)propertyCache[property];
|
||||
if (dynamicProperty == null)
|
||||
{
|
||||
dynamicProperty = createCallback( property );
|
||||
dynamicProperty = createCallback(property);
|
||||
propertyCache[property] = dynamicProperty;
|
||||
}
|
||||
return dynamicProperty;
|
||||
@@ -192,14 +195,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="field">Field to look up.</param>
|
||||
/// <param name="createCallback">callback function that will be called to create the dynamic field</param>
|
||||
/// <returns>An <see cref="IDynamicField"/> for the given field info.</returns>
|
||||
internal static IDynamicField GetDynamicField( FieldInfo field, CreateFieldCallback createCallback )
|
||||
internal static IDynamicField GetDynamicField(FieldInfo field, CreateFieldCallback createCallback)
|
||||
{
|
||||
lock (fieldCache.SyncRoot)
|
||||
{
|
||||
IDynamicField dynamicField = (IDynamicField)fieldCache[field];
|
||||
if (dynamicField == null)
|
||||
{
|
||||
dynamicField = createCallback( field );
|
||||
dynamicField = createCallback(field);
|
||||
fieldCache[field] = dynamicField;
|
||||
}
|
||||
return dynamicField;
|
||||
@@ -212,14 +215,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="indexer">Indexer to look up.</param>
|
||||
/// <param name="createCallback">callback function that will be called to create the dynamic indexer</param>
|
||||
/// <returns>An <see cref="IDynamicIndexer"/> for the given indexer.</returns>
|
||||
internal static IDynamicIndexer GetDynamicIndexer( PropertyInfo indexer, CreateIndexerCallback createCallback )
|
||||
internal static IDynamicIndexer GetDynamicIndexer(PropertyInfo indexer, CreateIndexerCallback createCallback)
|
||||
{
|
||||
lock (indexerCache.SyncRoot)
|
||||
{
|
||||
IDynamicIndexer dynamicIndexer = (IDynamicIndexer)indexerCache[indexer];
|
||||
if (dynamicIndexer == null)
|
||||
{
|
||||
dynamicIndexer = createCallback( indexer );
|
||||
dynamicIndexer = createCallback(indexer);
|
||||
indexerCache[indexer] = dynamicIndexer;
|
||||
}
|
||||
return dynamicIndexer;
|
||||
@@ -232,14 +235,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="method">Method to look up.</param>
|
||||
/// <param name="createCallback">callback function that will be called to create the dynamic method</param>
|
||||
/// <returns>An <see cref="IDynamicMethod"/> for the given method.</returns>
|
||||
internal static IDynamicMethod GetDynamicMethod( MethodInfo method, CreateMethodCallback createCallback )
|
||||
internal static IDynamicMethod GetDynamicMethod(MethodInfo method, CreateMethodCallback createCallback)
|
||||
{
|
||||
lock (methodCache.SyncRoot)
|
||||
{
|
||||
IDynamicMethod dynamicMethod = (IDynamicMethod)methodCache[method];
|
||||
if (dynamicMethod == null)
|
||||
{
|
||||
dynamicMethod = createCallback( method );
|
||||
dynamicMethod = createCallback(method);
|
||||
methodCache[method] = dynamicMethod;
|
||||
}
|
||||
return dynamicMethod;
|
||||
@@ -252,14 +255,14 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="constructor">Constructor to look up.</param>
|
||||
/// <param name="createCallback">callback function that will be called to create the dynamic constructor</param>
|
||||
/// <returns>An <see cref="IDynamicConstructor"/> for the given constructor.</returns>
|
||||
internal static IDynamicConstructor GetDynamicConstructor( ConstructorInfo constructor, CreateConstructorCallback createCallback )
|
||||
internal static IDynamicConstructor GetDynamicConstructor(ConstructorInfo constructor, CreateConstructorCallback createCallback)
|
||||
{
|
||||
lock (constructorCache.SyncRoot)
|
||||
{
|
||||
IDynamicConstructor dynamicConstructor = (IDynamicConstructor)constructorCache[constructor];
|
||||
if (dynamicConstructor == null)
|
||||
{
|
||||
dynamicConstructor = createCallback( constructor );
|
||||
dynamicConstructor = createCallback(constructor);
|
||||
constructorCache[constructor] = dynamicConstructor;
|
||||
}
|
||||
return dynamicConstructor;
|
||||
@@ -270,10 +273,10 @@ namespace Spring.Reflection.Dynamic
|
||||
/// Saves dynamically generated assembly to disk.
|
||||
/// Can only be called in DEBUG mode, per ConditionalAttribute rules.
|
||||
/// </summary>
|
||||
[Conditional( "DEBUG_DYNAMIC" )]
|
||||
[Conditional("DEBUG_DYNAMIC")]
|
||||
public static void SaveAssembly()
|
||||
{
|
||||
DynamicCodeManager.SaveAssembly( ASSEMBLY_NAME );
|
||||
DynamicCodeManager.SaveAssembly(ASSEMBLY_NAME);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -284,14 +287,16 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
/// <param name="fieldInfo">the field to create the delegate for</param>
|
||||
/// <returns>a delegate that can be used to read the field</returns>
|
||||
public static FieldGetterDelegate CreateFieldGetter( FieldInfo fieldInfo )
|
||||
public static FieldGetterDelegate CreateFieldGetter(FieldInfo fieldInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( fieldInfo, "You cannot create a delegate for a null value." );
|
||||
AssertUtils.ArgumentNotNull(fieldInfo, "You cannot create a delegate for a null value.");
|
||||
|
||||
System.Reflection.Emit.DynamicMethod dmGetter = new System.Reflection.Emit.DynamicMethod( "getter", typeof( object ), new Type[] { typeof( object ) }, fieldInfo.DeclaringType.Module, true );
|
||||
bool skipVisibility = !IsPublic(fieldInfo);
|
||||
Type[] argumentTypes = new Type[] { typeof(object) };
|
||||
System.Reflection.Emit.DynamicMethod dmGetter = CreateDynamicMethod("get_" + fieldInfo.Name, typeof(object), argumentTypes, fieldInfo, skipVisibility);
|
||||
ILGenerator il = dmGetter.GetILGenerator();
|
||||
EmitFieldGetter( il, fieldInfo, false );
|
||||
return (FieldGetterDelegate)dmGetter.CreateDelegate( typeof( FieldGetterDelegate ) );
|
||||
EmitFieldGetter(il, fieldInfo, false);
|
||||
return (FieldGetterDelegate)dmGetter.CreateDelegate(typeof(FieldGetterDelegate));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -303,14 +308,15 @@ namespace Spring.Reflection.Dynamic
|
||||
/// If the field's <see cref="FieldInfo.IsLiteral"/> returns true, the returned method
|
||||
/// will throw an <see cref="InvalidOperationException"/> when called.
|
||||
/// </remarks>
|
||||
public static FieldSetterDelegate CreateFieldSetter( FieldInfo fieldInfo )
|
||||
public static FieldSetterDelegate CreateFieldSetter(FieldInfo fieldInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( fieldInfo, "You cannot create a delegate for a null value." );
|
||||
AssertUtils.ArgumentNotNull(fieldInfo, "You cannot create a delegate for a null value.");
|
||||
|
||||
System.Reflection.Emit.DynamicMethod dmSetter = new System.Reflection.Emit.DynamicMethod( "setter", null, new Type[] { typeof( object ), typeof( object ) }, fieldInfo.DeclaringType.Module, true );
|
||||
bool skipVisibility = !IsPublic(fieldInfo);
|
||||
System.Reflection.Emit.DynamicMethod dmSetter = CreateDynamicMethod("set_" + fieldInfo.Name, null, new Type[] { typeof(object), typeof(object) }, fieldInfo, skipVisibility);
|
||||
ILGenerator il = dmSetter.GetILGenerator();
|
||||
EmitFieldSetter( il, fieldInfo, false );
|
||||
return (FieldSetterDelegate)dmSetter.CreateDelegate( typeof( FieldSetterDelegate ) );
|
||||
EmitFieldSetter(il, fieldInfo, false);
|
||||
return (FieldSetterDelegate)dmSetter.CreateDelegate(typeof(FieldSetterDelegate));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -322,14 +328,16 @@ namespace Spring.Reflection.Dynamic
|
||||
/// If the property's <see cref="PropertyInfo.CanRead"/> returns false, the returned method
|
||||
/// will throw an <see cref="InvalidOperationException"/> when called.
|
||||
/// </remarks>
|
||||
public static PropertyGetterDelegate CreatePropertyGetter( PropertyInfo propertyInfo )
|
||||
public static PropertyGetterDelegate CreatePropertyGetter(PropertyInfo propertyInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( propertyInfo, "You cannot create a delegate for a null value." );
|
||||
AssertUtils.ArgumentNotNull(propertyInfo, "You cannot create a delegate for a null value.");
|
||||
|
||||
NetDynamicMethod dm = new NetDynamicMethod( string.Empty, typeof( object ), new Type[] { typeof( object ), typeof( object[] ) }, propertyInfo.DeclaringType.Module, true );
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod();
|
||||
bool skipVisibility = (null == getMethod || !IsPublic(getMethod)); // getter is public
|
||||
NetDynamicMethod dm = CreateDynamicMethod("get_" + propertyInfo.Name, typeof(object), new Type[] { typeof(object), typeof(object[]) }, propertyInfo, skipVisibility);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
EmitPropertyGetter( il, propertyInfo, false );
|
||||
return (PropertyGetterDelegate)dm.CreateDelegate( typeof( PropertyGetterDelegate ) );
|
||||
EmitPropertyGetter(il, propertyInfo, false);
|
||||
return (PropertyGetterDelegate)dm.CreateDelegate(typeof(PropertyGetterDelegate));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -341,14 +349,17 @@ namespace Spring.Reflection.Dynamic
|
||||
/// If the property's <see cref="PropertyInfo.CanWrite"/> returns false, the returned method
|
||||
/// will throw an <see cref="InvalidOperationException"/> when called.
|
||||
/// </remarks>
|
||||
public static PropertySetterDelegate CreatePropertySetter( PropertyInfo propertyInfo )
|
||||
public static PropertySetterDelegate CreatePropertySetter(PropertyInfo propertyInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( propertyInfo, "You cannot create a delegate for a null value." );
|
||||
AssertUtils.ArgumentNotNull(propertyInfo, "You cannot create a delegate for a null value.");
|
||||
|
||||
NetDynamicMethod dm = new NetDynamicMethod( string.Empty, null, new Type[] { typeof( object ), typeof( object ), typeof( object[] ) }, propertyInfo.DeclaringType.Module, true );
|
||||
MethodInfo setMethod = propertyInfo.GetSetMethod();
|
||||
bool skipVisibility = (null == setMethod || !IsPublic(setMethod)); // setter is public
|
||||
Type[] argumentTypes = new Type[] { typeof(object), typeof(object), typeof(object[]) };
|
||||
NetDynamicMethod dm = CreateDynamicMethod("set_" + propertyInfo.Name, null, argumentTypes, propertyInfo, skipVisibility);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
EmitPropertySetter( il, propertyInfo, false );
|
||||
return (PropertySetterDelegate)dm.CreateDelegate( typeof( PropertySetterDelegate ) );
|
||||
EmitPropertySetter(il, propertyInfo, false);
|
||||
return (PropertySetterDelegate)dm.CreateDelegate(typeof(PropertySetterDelegate));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -356,14 +367,15 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
/// <param name="methodInfo">the method to create the delegate for</param>
|
||||
/// <returns>a delegate that can be used to invoke the method.</returns>
|
||||
public static FunctionDelegate CreateMethod( MethodInfo methodInfo )
|
||||
public static FunctionDelegate CreateMethod(MethodInfo methodInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( methodInfo, "You cannot create a delegate for a null value." );
|
||||
AssertUtils.ArgumentNotNull(methodInfo, "You cannot create a delegate for a null value.");
|
||||
|
||||
NetDynamicMethod dm = new NetDynamicMethod( string.Empty, typeof( object ), new Type[] { typeof( object ), typeof( object[] ) }, methodInfo.DeclaringType.Module, true );
|
||||
bool skipVisibility = !IsPublic(methodInfo);
|
||||
NetDynamicMethod dm = CreateDynamicMethod(methodInfo.Name, typeof(object), new Type[] { typeof(object), typeof(object[]) }, methodInfo, skipVisibility);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
EmitInvokeMethod( il, methodInfo, false );
|
||||
return (FunctionDelegate)dm.CreateDelegate( typeof( FunctionDelegate ) );
|
||||
EmitInvokeMethod(il, methodInfo, false);
|
||||
return (FunctionDelegate)dm.CreateDelegate(typeof(FunctionDelegate));
|
||||
}
|
||||
|
||||
///<summary>
|
||||
@@ -371,45 +383,140 @@ namespace Spring.Reflection.Dynamic
|
||||
///</summary>
|
||||
///<param name="constructorInfo">the constructor to create the delegate for</param>
|
||||
///<returns>delegate that can be used to invoke the constructor.</returns>
|
||||
public static ConstructorDelegate CreateConstructor(ConstructorInfo constructorInfo)
|
||||
public static ConstructorDelegate CreateConstructor(ConstructorInfo constructorInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(constructorInfo, "You cannot create a dynamic constructor for a null value.");
|
||||
AssertUtils.ArgumentNotNull(constructorInfo, "You cannot create a dynamic constructor for a null value.");
|
||||
|
||||
System.Reflection.Emit.DynamicMethod dmGetter = new System.Reflection.Emit.DynamicMethod( string.Empty, typeof( object ), new Type[] { typeof( object[] ) }, constructorInfo.DeclaringType.Module, true );
|
||||
bool skipVisibility = !IsPublic(constructorInfo);
|
||||
System.Reflection.Emit.DynamicMethod dmGetter;
|
||||
Type[] argumentTypes = new Type[] { typeof(object[]) };
|
||||
dmGetter = CreateDynamicMethod(constructorInfo.Name, typeof(object), argumentTypes, constructorInfo, skipVisibility);
|
||||
ILGenerator il = dmGetter.GetILGenerator();
|
||||
EmitInvokeConstructor( il, constructorInfo, false );
|
||||
ConstructorDelegate ctor = (ConstructorDelegate)dmGetter.CreateDelegate( typeof( ConstructorDelegate ) );
|
||||
EmitInvokeConstructor(il, constructorInfo, false);
|
||||
ConstructorDelegate ctor = (ConstructorDelegate)dmGetter.CreateDelegate(typeof(ConstructorDelegate));
|
||||
return ctor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="System.Reflection.Emit.DynamicMethod"/> instance with the highest possible code access security.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If allowed by security policy, associates the method with the <paramref name="member"/>s declaring type.
|
||||
/// Otherwise associates the dynamic method with <see cref="DynamicReflectionManager"/>.
|
||||
/// </remarks>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static NetDynamicMethod CreateDynamicMethod(string methodName, Type returnType, Type[] argumentTypes, MemberInfo member, bool skipVisibility)
|
||||
{
|
||||
NetDynamicMethod dmGetter = null;
|
||||
methodName = "_dynamic_" + member.DeclaringType.Name + "." + methodName;
|
||||
try
|
||||
{
|
||||
new PermissionSet(PermissionState.Unrestricted).Demand();
|
||||
dmGetter = CreateDynamicMethodInternal(methodName, returnType, argumentTypes, member, skipVisibility);
|
||||
}
|
||||
catch(SecurityException)
|
||||
{
|
||||
dmGetter = CreateDynamicMethodInternal(methodName, returnType, argumentTypes, MethodBase.GetCurrentMethod(), false);
|
||||
}
|
||||
return dmGetter;
|
||||
}
|
||||
|
||||
private static NetDynamicMethod CreateDynamicMethodInternal(string methodName, Type returnType, Type[] argumentTypes, MemberInfo member, bool skipVisibility)
|
||||
{
|
||||
NetDynamicMethod dm;
|
||||
dm = new NetDynamicMethod(methodName, returnType, argumentTypes, member.Module, skipVisibility);
|
||||
// if (member is FieldInfo)
|
||||
// {
|
||||
// // workaround for DynamicMethod bug not invoking type initializer before accessing static field
|
||||
// // it seems all works correct if the DM is created with limited accessibility
|
||||
// bool isStatic = (((FieldInfo) member).IsStatic);
|
||||
// if (isStatic)
|
||||
// {
|
||||
// new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).PermitOnly();
|
||||
// }
|
||||
// dm = new NetDynamicMethod(methodName, returnType, argumentTypes, member.DeclaringType, true);
|
||||
// if (isStatic)
|
||||
// {
|
||||
// CodeAccessPermission.RevertPermitOnly();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dm = new NetDynamicMethod(methodName, returnType, argumentTypes, member.DeclaringType, true);
|
||||
// }
|
||||
return dm;
|
||||
}
|
||||
|
||||
private static bool IsPublic(MemberInfo member)
|
||||
{
|
||||
if (member == null) return true;
|
||||
|
||||
switch(member.MemberType)
|
||||
{
|
||||
case MemberTypes.Event:
|
||||
{
|
||||
bool isPublic = ((EventInfo) member).GetAddMethod() != null;
|
||||
return isPublic && IsPublic(member.DeclaringType);
|
||||
}
|
||||
case MemberTypes.Field:
|
||||
{
|
||||
bool isPublic = ((FieldInfo)member).IsPublic;
|
||||
return isPublic && IsPublic(member.DeclaringType);
|
||||
}
|
||||
case MemberTypes.Property:
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
case MemberTypes.Constructor:
|
||||
case MemberTypes.Method:
|
||||
{
|
||||
bool isPublic = ((MethodBase)member).IsPublic;
|
||||
return isPublic && IsPublic(member.DeclaringType);
|
||||
}
|
||||
case MemberTypes.NestedType:
|
||||
{
|
||||
bool isPublic = ((Type)member).IsPublic;
|
||||
return isPublic && IsPublic(member.DeclaringType);
|
||||
}
|
||||
case MemberTypes.TypeInfo:
|
||||
{
|
||||
bool isPublic = ((Type)member).IsPublic;
|
||||
return isPublic;
|
||||
}
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#region Shared Code Generation
|
||||
|
||||
private static void EmitFieldGetter( ILGenerator il, FieldInfo fieldInfo, bool isInstanceMethod )
|
||||
private static void EmitFieldGetter(ILGenerator il, FieldInfo fieldInfo, bool isInstanceMethod)
|
||||
{
|
||||
if (fieldInfo.IsLiteral)
|
||||
{
|
||||
object value = fieldInfo.GetValue( null );
|
||||
EmitConstant( il, value );
|
||||
object value = fieldInfo.GetValue(null);
|
||||
EmitConstant(il, value);
|
||||
}
|
||||
else if (fieldInfo.IsStatic)
|
||||
{
|
||||
il.Emit( OpCodes.Ldsfld, fieldInfo );
|
||||
// object v = fieldInfo.GetValue(null); // ensure type is initialized...
|
||||
il.Emit(OpCodes.Ldsfld, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitTarget( il, fieldInfo.DeclaringType, isInstanceMethod );
|
||||
il.Emit( OpCodes.Ldfld, fieldInfo );
|
||||
EmitTarget(il, fieldInfo.DeclaringType, isInstanceMethod);
|
||||
il.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
}
|
||||
|
||||
if (fieldInfo.FieldType.IsValueType)
|
||||
{
|
||||
il.Emit( OpCodes.Box, fieldInfo.FieldType );
|
||||
il.Emit(OpCodes.Box, fieldInfo.FieldType);
|
||||
}
|
||||
il.Emit( OpCodes.Ret );
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
internal static void EmitFieldSetter( ILGenerator il, FieldInfo fieldInfo, bool isInstanceMethod )
|
||||
internal static void EmitFieldSetter(ILGenerator il, FieldInfo fieldInfo, bool isInstanceMethod)
|
||||
{
|
||||
if (!fieldInfo.IsLiteral
|
||||
&& !fieldInfo.IsInitOnly
|
||||
@@ -417,51 +524,51 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
EmitTarget( il, fieldInfo.DeclaringType, isInstanceMethod );
|
||||
EmitTarget(il, fieldInfo.DeclaringType, isInstanceMethod);
|
||||
}
|
||||
|
||||
il.Emit( OpCodes.Ldarg_1 );
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
if (fieldInfo.FieldType.IsValueType)
|
||||
{
|
||||
EmitUnbox( il, fieldInfo.FieldType );
|
||||
EmitUnbox(il, fieldInfo.FieldType);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, fieldInfo.FieldType );
|
||||
il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
|
||||
}
|
||||
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
il.Emit( OpCodes.Stsfld, fieldInfo );
|
||||
il.Emit(OpCodes.Stsfld, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Stfld, fieldInfo );
|
||||
il.Emit(OpCodes.Stfld, fieldInfo);
|
||||
}
|
||||
il.Emit( OpCodes.Ret );
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitThrowInvalidOperationException( il, string.Format( "Cannot write to read-only field '{0}.{1}'", fieldInfo.DeclaringType.FullName, fieldInfo.Name ) );
|
||||
EmitThrowInvalidOperationException(il, string.Format("Cannot write to read-only field '{0}.{1}'", fieldInfo.DeclaringType.FullName, fieldInfo.Name));
|
||||
}
|
||||
}
|
||||
|
||||
internal static void EmitPropertyGetter( ILGenerator il, PropertyInfo propertyInfo, bool isInstanceMethod )
|
||||
internal static void EmitPropertyGetter(ILGenerator il, PropertyInfo propertyInfo, bool isInstanceMethod)
|
||||
{
|
||||
if (propertyInfo.CanRead)
|
||||
{
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod( true );
|
||||
EmitInvokeMethod( il, getMethod, isInstanceMethod );
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod(true);
|
||||
EmitInvokeMethod(il, getMethod, isInstanceMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitThrowInvalidOperationException( il, string.Format( "Cannot read from write-only property '{0}.{1}'", propertyInfo.DeclaringType.FullName, propertyInfo.Name ) );
|
||||
EmitThrowInvalidOperationException(il, string.Format("Cannot read from write-only property '{0}.{1}'", propertyInfo.DeclaringType.FullName, propertyInfo.Name));
|
||||
}
|
||||
}
|
||||
|
||||
internal static void EmitPropertySetter( ILGenerator il, PropertyInfo propertyInfo, bool isInstanceMethod )
|
||||
internal static void EmitPropertySetter(ILGenerator il, PropertyInfo propertyInfo, bool isInstanceMethod)
|
||||
{
|
||||
MethodInfo method = propertyInfo.GetSetMethod( true );
|
||||
MethodInfo method = propertyInfo.GetSetMethod(true);
|
||||
|
||||
if (propertyInfo.CanWrite
|
||||
&& !(propertyInfo.DeclaringType.IsValueType && !method.IsStatic))
|
||||
@@ -475,184 +582,184 @@ namespace Spring.Reflection.Dynamic
|
||||
ParameterInfo[] args = propertyInfo.GetIndexParameters(); // get indexParameters here!
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
// load target
|
||||
if (!method.IsStatic)
|
||||
{
|
||||
EmitTarget( il, method.DeclaringType, isInstanceMethod );
|
||||
EmitTarget(il, method.DeclaringType, isInstanceMethod);
|
||||
}
|
||||
|
||||
// load indexer arguments
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupMethodArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupMethodArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
// load value
|
||||
il.Emit( OpCodes.Ldarg_1 );
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
if (propertyInfo.PropertyType.IsValueType)
|
||||
{
|
||||
EmitUnbox( il, propertyInfo.PropertyType );
|
||||
EmitUnbox(il, propertyInfo.PropertyType);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, propertyInfo.PropertyType );
|
||||
il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
|
||||
}
|
||||
|
||||
// call setter
|
||||
EmitCall( il, method );
|
||||
EmitCall(il, method);
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
ProcessOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
ProcessOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
il.Emit( OpCodes.Ret );
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitThrowInvalidOperationException( il, string.Format( "Cannot write to read-only property '{0}.{1}'", propertyInfo.DeclaringType.FullName, propertyInfo.Name ) );
|
||||
EmitThrowInvalidOperationException(il, string.Format("Cannot write to read-only property '{0}.{1}'", propertyInfo.DeclaringType.FullName, propertyInfo.Name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegates a Method(object target, params object[] args) call to the actual underlying method.
|
||||
/// </summary>
|
||||
internal static void EmitInvokeMethod( ILGenerator il, MethodInfo method, bool isInstanceMethod )
|
||||
internal static void EmitInvokeMethod(ILGenerator il, MethodInfo method, bool isInstanceMethod)
|
||||
{
|
||||
int paramsArrayPosition = (isInstanceMethod) ? 2 : 1;
|
||||
ParameterInfo[] args = method.GetParameters();
|
||||
IDictionary outArgs = new Hashtable();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
if (!method.IsStatic)
|
||||
{
|
||||
EmitTarget( il, method.DeclaringType, isInstanceMethod );
|
||||
EmitTarget(il, method.DeclaringType, isInstanceMethod);
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupMethodArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupMethodArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
EmitCall( il, method );
|
||||
EmitCall(il, method);
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
ProcessOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
ProcessOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
EmitMethodReturn( il, method.ReturnType );
|
||||
EmitMethodReturn(il, method.ReturnType);
|
||||
}
|
||||
|
||||
internal static void EmitInvokeConstructor(ILGenerator il, ConstructorInfo constructor, bool isInstanceMethod)
|
||||
{
|
||||
int paramsArrayPosition = (isInstanceMethod) ? 1 : 0;
|
||||
ParameterInfo[] args = constructor.GetParameters();
|
||||
|
||||
ParameterInfo[] args = constructor.GetParameters();
|
||||
|
||||
IDictionary outArgs = new Hashtable();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupMethodArgument(il, paramsArrayPosition, args[i], null);
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Newobj, constructor);
|
||||
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
ProcessOutputArgument( il, paramsArrayPosition, args[i], outArgs );
|
||||
SetupMethodArgument(il, paramsArrayPosition, args[i], null);
|
||||
}
|
||||
|
||||
EmitMethodReturn(il, constructor.DeclaringType);
|
||||
}
|
||||
|
||||
|
||||
il.Emit(OpCodes.Newobj, constructor);
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
ProcessOutputArgument(il, paramsArrayPosition, args[i], outArgs);
|
||||
}
|
||||
|
||||
EmitMethodReturn(il, constructor.DeclaringType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static OpCode[] LdArgOpCodes = { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2 };
|
||||
|
||||
private static void SetupOutputArgument( ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs )
|
||||
private static void SetupOutputArgument(ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
if (!IsOutputOrRefArgument( argInfo ))
|
||||
if (!IsOutputOrRefArgument(argInfo))
|
||||
return;
|
||||
|
||||
Type argType = argInfo.ParameterType.GetElementType();
|
||||
|
||||
LocalBuilder lb = il.DeclareLocal( argType );
|
||||
LocalBuilder lb = il.DeclareLocal(argType);
|
||||
if (!argInfo.IsOut)
|
||||
{
|
||||
PushParamsArgumentValue( il, paramsArrayPosition, argType, argInfo.Position );
|
||||
il.Emit( OpCodes.Stloc, lb );
|
||||
PushParamsArgumentValue(il, paramsArrayPosition, argType, argInfo.Position);
|
||||
il.Emit(OpCodes.Stloc, lb);
|
||||
}
|
||||
outArgs[argInfo.Position] = lb;
|
||||
}
|
||||
|
||||
private static bool IsOutputOrRefArgument( ParameterInfo argInfo )
|
||||
private static bool IsOutputOrRefArgument(ParameterInfo argInfo)
|
||||
{
|
||||
return argInfo.IsOut || argInfo.ParameterType.Name.EndsWith( "&" );
|
||||
return argInfo.IsOut || argInfo.ParameterType.Name.EndsWith("&");
|
||||
}
|
||||
|
||||
private static void ProcessOutputArgument( ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs )
|
||||
private static void ProcessOutputArgument(ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
if (!IsOutputOrRefArgument( argInfo ))
|
||||
if (!IsOutputOrRefArgument(argInfo))
|
||||
return;
|
||||
|
||||
Type argType = argInfo.ParameterType.GetElementType();
|
||||
|
||||
il.Emit( LdArgOpCodes[paramsArrayPosition] );
|
||||
il.Emit( OpCodes.Ldc_I4, argInfo.Position );
|
||||
il.Emit( OpCodes.Ldloc, (LocalBuilder)outArgs[argInfo.Position] );
|
||||
il.Emit(LdArgOpCodes[paramsArrayPosition]);
|
||||
il.Emit(OpCodes.Ldc_I4, argInfo.Position);
|
||||
il.Emit(OpCodes.Ldloc, (LocalBuilder)outArgs[argInfo.Position]);
|
||||
if (argType.IsValueType)
|
||||
{
|
||||
il.Emit( OpCodes.Box, argType );
|
||||
il.Emit(OpCodes.Box, argType);
|
||||
}
|
||||
il.Emit( OpCodes.Stelem_Ref );
|
||||
il.Emit(OpCodes.Stelem_Ref);
|
||||
}
|
||||
|
||||
private static void SetupMethodArgument( ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs )
|
||||
private static void SetupMethodArgument(ILGenerator il, int paramsArrayPosition, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
if ( IsOutputOrRefArgument( argInfo ))
|
||||
if (IsOutputOrRefArgument(argInfo))
|
||||
{
|
||||
il.Emit( OpCodes.Ldloca_S, (LocalBuilder)outArgs[argInfo.Position] );
|
||||
il.Emit(OpCodes.Ldloca_S, (LocalBuilder)outArgs[argInfo.Position]);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushParamsArgumentValue( il, paramsArrayPosition, argInfo.ParameterType, argInfo.Position );
|
||||
PushParamsArgumentValue(il, paramsArrayPosition, argInfo.ParameterType, argInfo.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private static void PushParamsArgumentValue( ILGenerator il, int paramsArrayPosition, Type argumentType, int argumentPosition )
|
||||
private static void PushParamsArgumentValue(ILGenerator il, int paramsArrayPosition, Type argumentType, int argumentPosition)
|
||||
{
|
||||
il.Emit( LdArgOpCodes[paramsArrayPosition] );
|
||||
il.Emit( OpCodes.Ldc_I4, argumentPosition );
|
||||
il.Emit( OpCodes.Ldelem_Ref );
|
||||
il.Emit(LdArgOpCodes[paramsArrayPosition]);
|
||||
il.Emit(OpCodes.Ldc_I4, argumentPosition);
|
||||
il.Emit(OpCodes.Ldelem_Ref);
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
// call ConvertArgumentIfNecessary() to convert e.g. int32 to double if necessary
|
||||
il.Emit( OpCodes.Ldtoken, argumentType );
|
||||
EmitCall( il, FnGetTypeFromHandle );
|
||||
il.Emit( OpCodes.Ldc_I4, argumentPosition );
|
||||
EmitCall( il, FnConvertArgumentIfNecessary );
|
||||
EmitUnbox( il, argumentType );
|
||||
il.Emit(OpCodes.Ldtoken, argumentType);
|
||||
EmitCall(il, FnGetTypeFromHandle);
|
||||
il.Emit(OpCodes.Ldc_I4, argumentPosition);
|
||||
EmitCall(il, FnConvertArgumentIfNecessary);
|
||||
EmitUnbox(il, argumentType);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, argumentType );
|
||||
il.Emit(OpCodes.Castclass, argumentType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitUnbox( ILGenerator il, Type argumentType )
|
||||
private static void EmitUnbox(ILGenerator il, Type argumentType)
|
||||
{
|
||||
#if NET_2_0
|
||||
il.Emit( OpCodes.Unbox_Any, argumentType );
|
||||
il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
#else
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
@@ -664,23 +771,23 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
/// <param name="il">IL generator to use.</param>
|
||||
/// <param name="returnValueType">Type of the return value.</param>
|
||||
private static void EmitMethodReturn( ILGenerator il, Type returnValueType )
|
||||
private static void EmitMethodReturn(ILGenerator il, Type returnValueType)
|
||||
{
|
||||
if (returnValueType == typeof( void ))
|
||||
if (returnValueType == typeof(void))
|
||||
{
|
||||
il.Emit( OpCodes.Ldnull );
|
||||
il.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
else if (returnValueType.IsValueType)
|
||||
{
|
||||
il.Emit( OpCodes.Box, returnValueType );
|
||||
il.Emit(OpCodes.Box, returnValueType);
|
||||
}
|
||||
il.Emit( OpCodes.Ret );
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
private delegate Type GetTypeFromHandleDelegate( RuntimeTypeHandle handle );
|
||||
private static readonly MethodInfo FnGetTypeFromHandle = new GetTypeFromHandleDelegate( Type.GetTypeFromHandle ).Method;
|
||||
private delegate object ChangeTypeDelegate( object value, Type targetType, int argIndex );
|
||||
private static readonly MethodInfo FnConvertArgumentIfNecessary = new ChangeTypeDelegate( ConvertValueTypeArgumentIfNecessary ).Method;
|
||||
private delegate Type GetTypeFromHandleDelegate(RuntimeTypeHandle handle);
|
||||
private static readonly MethodInfo FnGetTypeFromHandle = new GetTypeFromHandleDelegate(Type.GetTypeFromHandle).Method;
|
||||
private delegate object ChangeTypeDelegate(object value, Type targetType, int argIndex);
|
||||
private static readonly MethodInfo FnConvertArgumentIfNecessary = new ChangeTypeDelegate(ConvertValueTypeArgumentIfNecessary).Method;
|
||||
|
||||
/// <summary>
|
||||
/// Converts <paramref name="value"/> to an instance of <paramref name="targetType"/> if necessary to
|
||||
@@ -696,7 +803,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// Note: <paramref name="targetType"/> is expected to be a value type!
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static object ConvertValueTypeArgumentIfNecessary( object value, Type targetType, int argIndex )
|
||||
public static object ConvertValueTypeArgumentIfNecessary(object value, Type targetType, int argIndex)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
@@ -704,12 +811,12 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw new InvalidCastException( string.Format( "Cannot convert NULL at position {0} to argument type {1}", argIndex, targetType.FullName ) );
|
||||
throw new InvalidCastException(string.Format("Cannot convert NULL at position {0} to argument type {1}", argIndex, targetType.FullName));
|
||||
}
|
||||
|
||||
Type valueType = value.GetType();
|
||||
#if NET_2_0
|
||||
if (ReflectionUtils.IsNullableType( targetType ))
|
||||
if (ReflectionUtils.IsNullableType(targetType))
|
||||
{
|
||||
targetType = Nullable.GetUnderlyingType(targetType);
|
||||
}
|
||||
@@ -723,47 +830,47 @@ namespace Spring.Reflection.Dynamic
|
||||
if (!valueType.IsValueType)
|
||||
{
|
||||
// we're facing a reftype/valuetype mix that never can convert
|
||||
throw new InvalidCastException( string.Format( "Cannot convert value '{0}' of type {1} at position {2} to argument type {3}", value, valueType.FullName, argIndex, targetType.FullName ) );
|
||||
throw new InvalidCastException(string.Format("Cannot convert value '{0}' of type {1} at position {2} to argument type {3}", value, valueType.FullName, argIndex, targetType.FullName));
|
||||
}
|
||||
|
||||
// we're dealing only with ValueType's now - try to convert them
|
||||
try
|
||||
{
|
||||
// TODO: allow widening conversions only
|
||||
return Convert.ChangeType( value, targetType );
|
||||
return Convert.ChangeType(value, targetType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidCastException( string.Format( "Cannot convert value '{0}' of type {1} at position {2} to argument type {3}", value, valueType.FullName, argIndex, targetType.FullName ), ex );
|
||||
throw new InvalidCastException(string.Format("Cannot convert value '{0}' of type {1} at position {2} to argument type {3}", value, valueType.FullName, argIndex, targetType.FullName), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitTarget( ILGenerator il, Type targetType, bool isInstanceMethod )
|
||||
private static void EmitTarget(ILGenerator il, Type targetType, bool isInstanceMethod)
|
||||
{
|
||||
il.Emit( (isInstanceMethod) ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0 );
|
||||
il.Emit((isInstanceMethod) ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0);
|
||||
if (targetType.IsValueType)
|
||||
{
|
||||
LocalBuilder local = il.DeclareLocal( targetType );
|
||||
EmitUnbox( il, targetType );
|
||||
il.Emit( OpCodes.Stloc_0 );
|
||||
il.Emit( OpCodes.Ldloca_S, 0 );
|
||||
LocalBuilder local = il.DeclareLocal(targetType);
|
||||
EmitUnbox(il, targetType);
|
||||
il.Emit(OpCodes.Stloc_0);
|
||||
il.Emit(OpCodes.Ldloca_S, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, targetType );
|
||||
il.Emit(OpCodes.Castclass, targetType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitCall( ILGenerator il, MethodInfo method )
|
||||
private static void EmitCall(ILGenerator il, MethodInfo method)
|
||||
{
|
||||
il.EmitCall( (method.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call, method, null );
|
||||
il.EmitCall((method.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call, method, null);
|
||||
}
|
||||
|
||||
private static void EmitConstant( ILGenerator il, object value )
|
||||
private static void EmitConstant(ILGenerator il, object value)
|
||||
{
|
||||
if (value is String)
|
||||
{
|
||||
il.Emit( OpCodes.Ldstr, (string)value );
|
||||
il.Emit(OpCodes.Ldstr, (string)value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -771,78 +878,78 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
if ((bool)value)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4_1 );
|
||||
il.Emit(OpCodes.Ldc_I4_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4_0 );
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (value is Char)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (Char)value );
|
||||
il.Emit( OpCodes.Conv_I2 );
|
||||
il.Emit(OpCodes.Ldc_I4, (Char)value);
|
||||
il.Emit(OpCodes.Conv_I2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value is byte)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (byte)value );
|
||||
il.Emit( OpCodes.Conv_I1 );
|
||||
il.Emit(OpCodes.Ldc_I4, (byte)value);
|
||||
il.Emit(OpCodes.Conv_I1);
|
||||
}
|
||||
else if (value is Int16)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (Int16)value );
|
||||
il.Emit( OpCodes.Conv_I2 );
|
||||
il.Emit(OpCodes.Ldc_I4, (Int16)value);
|
||||
il.Emit(OpCodes.Conv_I2);
|
||||
}
|
||||
else if (value is Int32)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (Int32)value );
|
||||
il.Emit(OpCodes.Ldc_I4, (Int32)value);
|
||||
}
|
||||
else if (value is Int64)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I8, (Int64)value );
|
||||
il.Emit(OpCodes.Ldc_I8, (Int64)value);
|
||||
}
|
||||
else if (value is UInt16)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (UInt16)value );
|
||||
il.Emit( OpCodes.Conv_U2 );
|
||||
il.Emit(OpCodes.Ldc_I4, (UInt16)value);
|
||||
il.Emit(OpCodes.Conv_U2);
|
||||
}
|
||||
else if (value is UInt32)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I4, (UInt32)value );
|
||||
il.Emit( OpCodes.Conv_U4 );
|
||||
il.Emit(OpCodes.Ldc_I4, (UInt32)value);
|
||||
il.Emit(OpCodes.Conv_U4);
|
||||
}
|
||||
else if (value is UInt64)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_I8, (UInt64)value );
|
||||
il.Emit( OpCodes.Conv_U8 );
|
||||
il.Emit(OpCodes.Ldc_I8, (UInt64)value);
|
||||
il.Emit(OpCodes.Conv_U8);
|
||||
}
|
||||
else if (value is Single)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_R4, (Single)value );
|
||||
il.Emit(OpCodes.Ldc_R4, (Single)value);
|
||||
}
|
||||
else if (value is Double)
|
||||
{
|
||||
il.Emit( OpCodes.Ldc_R8, (Double)value );
|
||||
il.Emit(OpCodes.Ldc_R8, (Double)value);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConstructorInfo NewInvalidOperationException =
|
||||
typeof( InvalidOperationException ).GetConstructor( new Type[] { typeof( string ) } );
|
||||
typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) });
|
||||
|
||||
/// <summary>
|
||||
/// Generates code that throws <see cref="InvalidOperationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="il">IL generator to use.</param>
|
||||
/// <param name="message">Error message to use.</param>
|
||||
private static void EmitThrowInvalidOperationException( ILGenerator il, string message )
|
||||
private static void EmitThrowInvalidOperationException(ILGenerator il, string message)
|
||||
{
|
||||
il.Emit( OpCodes.Ldstr, message );
|
||||
il.Emit( OpCodes.Newobj, NewInvalidOperationException );
|
||||
il.Emit( OpCodes.Throw );
|
||||
il.Emit(OpCodes.Ldstr, message);
|
||||
il.Emit(OpCodes.Newobj, NewInvalidOperationException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Spring.Core</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
@@ -38,6 +36,8 @@
|
||||
<IsWebBootstrapper>true</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\..\Spring.Net.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Core\Debug\</OutputPath>
|
||||
@@ -1013,6 +1013,7 @@
|
||||
<Compile Include="Util\ITextPosition.cs" />
|
||||
<Compile Include="Util\ObjectUtils.cs" />
|
||||
<Compile Include="Util\ReflectionException.cs" />
|
||||
<Compile Include="Util\SecurityCritical.cs" />
|
||||
<Compile Include="Util\SystemUtils.cs" />
|
||||
<Compile Include="Util\DynamicCodeManager.cs" />
|
||||
<Compile Include="Util\Generic\CollectionUtils.cs" />
|
||||
|
||||
@@ -247,8 +247,7 @@ namespace Spring.Util
|
||||
#endif
|
||||
try
|
||||
{
|
||||
// replaced with SafeConstructor() to avoid nasty "TargetInvocationException"s
|
||||
//return constructor.Invoke(arguments);
|
||||
// replaced with SafeConstructor() to avoid nasty "TargetInvocationException"s in NET >= 2.0
|
||||
return (new SafeConstructor(constructor)).Invoke(arguments);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
50
src/Spring/Spring.Core/Util/SecurityCritical.cs
Normal file
50
src/Spring/Spring.Core/Util/SecurityCritical.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class to be used from within this assembly for executing security critical code
|
||||
/// NEVER EVER MAKE THIS PUBLIC!
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
internal class SecurityCritical
|
||||
{
|
||||
internal delegate void PrivilegedCallback();
|
||||
|
||||
[SecurityCritical, SecurityTreatAsSafe]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static void ExecutePrivileged(IStackWalk permission, PrivilegedCallback callback)
|
||||
{
|
||||
permission.Assert();
|
||||
try
|
||||
{
|
||||
callback();
|
||||
}
|
||||
finally
|
||||
{
|
||||
CodeAccessPermission.RevertAssert();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,8 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Spring.EnterpriseServices
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Use Spring context to configure the serviced components.
|
||||
/// Use Spring context to configure the serviced components within COM.
|
||||
///</summary>
|
||||
public bool UseSpring
|
||||
{
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Web.UI;
|
||||
|
||||
[assembly: AssemblyTitle("Spring.Web")]
|
||||
[assembly: AssemblyDescription("Interfaces and classes that provide web application support in Spring.Net")]
|
||||
[assembly: TagPrefix("Spring.Web.UI.Controls", "spring")]
|
||||
//[assembly: AssemblyKeyFile(@"C:\users\aseovic\projects\OpenSource\Spring.Net\Spring.Net.PrivateKey.keys")]
|
||||
//[assembly: AssemblyKeyFile(@"C:\users\aseovic\projects\OpenSource\Spring.Net\Spring.Net.PrivateKey.keys")]
|
||||
[assembly: AllowPartiallyTrustedCallers]
|
||||
[assembly: SecurityCritical]
|
||||
|
||||
#if NET_1_0 || NET_1_1
|
||||
namespace System.Security
|
||||
{
|
||||
///<summary>
|
||||
///</summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method)]
|
||||
internal class SecurityCriticalAttribute : Attribute
|
||||
{ }
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
internal class SecurityTreatAsSafeAttribute : Attribute
|
||||
{ }
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.SessionState;
|
||||
@@ -80,8 +82,8 @@ namespace Spring.Context.Support
|
||||
private static CacheItemRemovedCallback s_originalCallback;
|
||||
#if NET_2_0
|
||||
// required to enable accessing HttpContext.Request during IHttpModule.Init() in integrated mode
|
||||
private static readonly FieldInfo fiHideRequestResponse = typeof(HttpContext).GetField("HideRequestResponse", BindingFlags.Instance|BindingFlags.NonPublic);
|
||||
private static readonly SafeField ContextHideRequestResponse = (fiHideRequestResponse!=null)?new SafeField(fiHideRequestResponse):null;
|
||||
private static readonly FieldInfo fiHideRequestResponse;
|
||||
private static readonly SafeField ContextHideRequestResponse;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -95,6 +97,20 @@ namespace Spring.Context.Support
|
||||
static WebSupportModule()
|
||||
{
|
||||
s_log = LogManager.GetLogger(typeof(WebSupportModule));
|
||||
#if NET_2_0
|
||||
// required to enable accessing HttpContext.Request during IHttpModule.Init() in integrated mode
|
||||
ContextHideRequestResponse = null;
|
||||
try
|
||||
{
|
||||
fiHideRequestResponse = typeof(HttpContext).GetField("HideRequestResponse", BindingFlags.Instance|BindingFlags.NonPublic);
|
||||
// fiHideRequestResponse.SetValue(HttpContext.Current, false);
|
||||
ContextHideRequestResponse = (fiHideRequestResponse!=null)?new SafeField(fiHideRequestResponse):null;
|
||||
}
|
||||
catch(SecurityException sec)
|
||||
{
|
||||
s_log.Warn(string.Format("failed reflecting field HttpContext.HideRequestResponse due to security restrictions {0}", sec));
|
||||
}
|
||||
#endif
|
||||
|
||||
// register additional resource handler
|
||||
ResourceHandlerRegistry.RegisterResourceHandler(WebUtils.DEFAULT_RESOURCE_PROTOCOL, typeof(WebResource));
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\..\Spring.Net.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Web\Debug\</OutputPath>
|
||||
@@ -124,6 +126,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Util\ISessionState.cs" />
|
||||
<Compile Include="Util\SecurityCritical.cs" />
|
||||
<Compile Include="Web\Support\DefaultHandlerFactory.cs" />
|
||||
<Compile Include="Web\Support\DefaultResultFactory.cs" />
|
||||
<Compile Include="Web\Support\HandlerMap.cs" />
|
||||
|
||||
66
src/Spring/Spring.Web/Util/SecurityCritical.cs
Normal file
66
src/Spring/Spring.Web/Util/SecurityCritical.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright © 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class to be used from within this assembly for executing security critical code
|
||||
/// NEVER EVER MAKE THIS PUBLIC!
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
internal class SecurityCritical
|
||||
{
|
||||
internal delegate void PrivilegedCallback();
|
||||
|
||||
[SecurityCritical, SecurityTreatAsSafe]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static void ExecutePrivileged(IStackWalk permission, PrivilegedCallback callback)
|
||||
{
|
||||
permission.Assert();
|
||||
try
|
||||
{
|
||||
callback();
|
||||
}
|
||||
finally
|
||||
{
|
||||
CodeAccessPermission.RevertAssert();
|
||||
}
|
||||
}
|
||||
|
||||
// internal delegate TResult PrivilegedCallback<TResult>();
|
||||
//
|
||||
// [SecurityCritical, SecurityTreatAsSafe]
|
||||
// internal static TResult ExecutePrivileged<TResult>(IStackWalk permission, PrivilegedCallback<TResult> callback)
|
||||
// {
|
||||
// permission.Assert();
|
||||
// try
|
||||
// {
|
||||
// return callback();
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// CodeAccessPermission.RevertAssert();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using Common.Logging;
|
||||
@@ -94,7 +96,25 @@ namespace Spring.Web.Support
|
||||
/// <summary>
|
||||
/// Holds an instance of the instrinsic System.Web.UI.SimpleHandlerFactory
|
||||
/// </summary>
|
||||
private static IHttpHandlerFactory s_simpleHandlerFactory;
|
||||
private static readonly IHttpHandlerFactory s_simpleHandlerFactory;
|
||||
|
||||
static AbstractHandlerFactory()
|
||||
{
|
||||
PrivilegedCommand cmd = new PrivilegedCommand();
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), new SecurityCritical.PrivilegedCallback(cmd.Execute));
|
||||
s_simpleHandlerFactory = cmd.Result;
|
||||
}
|
||||
|
||||
private class PrivilegedCommand
|
||||
{
|
||||
public IHttpHandlerFactory Result = null;
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
Type simpleHandlerFactoryType = typeof(IHttpHandler).Assembly.GetType("System.Web.UI.SimpleHandlerFactory");
|
||||
Result = (IHttpHandlerFactory)Activator.CreateInstance(simpleHandlerFactoryType, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the global instance of System.Web.UI.SimpleHandlerFactory
|
||||
@@ -110,8 +130,6 @@ namespace Spring.Web.Support
|
||||
// instantiate lazy to avoid security exceptions in restricted reflection environments
|
||||
if (s_simpleHandlerFactory == null)
|
||||
{
|
||||
Type simpleHandlerFactoryType = typeof(IHttpHandler).Assembly.GetType("System.Web.UI.SimpleHandlerFactory");
|
||||
s_simpleHandlerFactory = (IHttpHandlerFactory)Activator.CreateInstance(simpleHandlerFactoryType, true);
|
||||
}
|
||||
return s_simpleHandlerFactory;
|
||||
}
|
||||
@@ -128,7 +146,7 @@ namespace Spring.Web.Support
|
||||
/// </summary>
|
||||
protected AbstractHandlerFactory()
|
||||
{
|
||||
this.Log = LogManager.GetLogger( this.GetType() );
|
||||
this.Log = LogManager.GetLogger(this.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -149,14 +167,14 @@ namespace Spring.Web.Support
|
||||
/// A new <see cref="System.Web.IHttpHandler"/> object that processes
|
||||
/// the request.
|
||||
/// </returns>
|
||||
public virtual IHttpHandler GetHandler( HttpContext context, string requestType, string url, string physicalPath )
|
||||
public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string physicalPath)
|
||||
{
|
||||
bool isDebug = Log.IsDebugEnabled;
|
||||
|
||||
#region Instrumentation
|
||||
|
||||
if (isDebug)
|
||||
Log.Debug( string.Format( "GetHandler():resolving url '{0}'", url ) );
|
||||
Log.Debug(string.Format("GetHandler():resolving url '{0}'", url));
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -172,7 +190,7 @@ namespace Spring.Web.Support
|
||||
|
||||
if (isDebug)
|
||||
{
|
||||
Log.Debug( string.Format( "GetHandler():resolved url '{0}' from reusable handler cache", url ) );
|
||||
Log.Debug(string.Format("GetHandler():resolved url '{0}' from reusable handler cache", url));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -187,7 +205,7 @@ namespace Spring.Web.Support
|
||||
{
|
||||
IConfigurableApplicationContext appContext = GetCheckedApplicationContext(url);
|
||||
|
||||
handler = CreateHandlerInstance( appContext, context, requestType, url, physicalPath );
|
||||
handler = CreateHandlerInstance(appContext, context, requestType, url, physicalPath);
|
||||
|
||||
ApplyDependencyInjectionInfrastructure(handler, appContext);
|
||||
|
||||
@@ -207,7 +225,7 @@ namespace Spring.Web.Support
|
||||
/// <param name="handler">
|
||||
/// The <see cref="System.Web.IHttpHandler"/> object to release.
|
||||
/// </param>
|
||||
public virtual void ReleaseHandler( IHttpHandler handler )
|
||||
public virtual void ReleaseHandler(IHttpHandler handler)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
@@ -219,7 +237,7 @@ namespace Spring.Web.Support
|
||||
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
|
||||
/// <param name="physicalPath">The physical path of the requested resource.</param>
|
||||
/// <returns>A handler instance for processing the current request.</returns>
|
||||
protected abstract IHttpHandler CreateHandlerInstance( IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath );
|
||||
protected abstract IHttpHandler CreateHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath);
|
||||
|
||||
/// <summary>
|
||||
/// Get the application context instance corresponding to the given absolute url and checks
|
||||
@@ -236,16 +254,16 @@ namespace Spring.Web.Support
|
||||
/// <remarks>
|
||||
/// Calls <see cref="GetContext"/> to obtain a context instance.
|
||||
/// </remarks>
|
||||
protected IConfigurableApplicationContext GetCheckedApplicationContext( string url )
|
||||
protected IConfigurableApplicationContext GetCheckedApplicationContext(string url)
|
||||
{
|
||||
IApplicationContext appContext = GetContext( url );
|
||||
IApplicationContext appContext = GetContext(url);
|
||||
if (appContext == null)
|
||||
{
|
||||
throw new ArgumentException( string.Format( "no application context for virtual path '{0}'", url ) );
|
||||
throw new ArgumentException(string.Format("no application context for virtual path '{0}'", url));
|
||||
}
|
||||
if (!(appContext is IConfigurableApplicationContext))
|
||||
{
|
||||
throw new InvalidOperationException( string.Format( "application context '{0}' for virtual path '{1}' must implement IConfigurableApplicationContext", appContext.ToString(), url ) );
|
||||
throw new InvalidOperationException(string.Format("application context '{0}' for virtual path '{1}' must implement IConfigurableApplicationContext", appContext.ToString(), url));
|
||||
}
|
||||
return (IConfigurableApplicationContext)appContext;
|
||||
}
|
||||
@@ -259,9 +277,9 @@ namespace Spring.Web.Support
|
||||
/// Subclasses may override this method to change the context source.
|
||||
/// By default, <see cref="WebApplicationContext.GetContext"/> is used for obtaining context instances.
|
||||
/// </remarks>
|
||||
protected virtual IApplicationContext GetContext( string virtualPath )
|
||||
protected virtual IApplicationContext GetContext(string virtualPath)
|
||||
{
|
||||
return WebApplicationContext.GetContext( virtualPath );
|
||||
return WebApplicationContext.GetContext(virtualPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -276,27 +294,27 @@ namespace Spring.Web.Support
|
||||
/// <remarks>
|
||||
/// Resolve an object definition by url.
|
||||
/// </remarks>
|
||||
protected internal static NamedObjectDefinition FindWebObjectDefinition( string appRelativeVirtualPath, IConfigurableListableObjectFactory objectFactory )
|
||||
protected internal static NamedObjectDefinition FindWebObjectDefinition(string appRelativeVirtualPath, IConfigurableListableObjectFactory objectFactory)
|
||||
{
|
||||
ILog Log = LogManager.GetLogger( typeof( AbstractHandlerFactory ) );
|
||||
ILog Log = LogManager.GetLogger(typeof(AbstractHandlerFactory));
|
||||
bool isDebug = Log.IsDebugEnabled;
|
||||
|
||||
// lookup definition using app-relative url
|
||||
if (isDebug)
|
||||
Log.Debug( string.Format( "GetHandler():looking up definition for app-relative url '{0}'", appRelativeVirtualPath ) );
|
||||
Log.Debug(string.Format("GetHandler():looking up definition for app-relative url '{0}'", appRelativeVirtualPath));
|
||||
string objectDefinitionName = appRelativeVirtualPath;
|
||||
IObjectDefinition pageDefinition = objectFactory.GetObjectDefinition( appRelativeVirtualPath, true );
|
||||
IObjectDefinition pageDefinition = objectFactory.GetObjectDefinition(appRelativeVirtualPath, true);
|
||||
|
||||
if (pageDefinition == null)
|
||||
{
|
||||
// try using pagename+extension and pagename only
|
||||
string pageExtension = Path.GetExtension( appRelativeVirtualPath );
|
||||
string pageName = WebUtils.GetPageName( appRelativeVirtualPath );
|
||||
string pageExtension = Path.GetExtension(appRelativeVirtualPath);
|
||||
string pageName = WebUtils.GetPageName(appRelativeVirtualPath);
|
||||
// only looks in the specified object factory -- it will *not* search parent contexts
|
||||
pageDefinition = objectFactory.GetObjectDefinition( pageName + pageExtension, false );
|
||||
pageDefinition = objectFactory.GetObjectDefinition(pageName + pageExtension, false);
|
||||
if (pageDefinition == null)
|
||||
{
|
||||
pageDefinition = objectFactory.GetObjectDefinition( pageName, false );
|
||||
pageDefinition = objectFactory.GetObjectDefinition(pageName, false);
|
||||
if (pageDefinition != null)
|
||||
objectDefinitionName = pageName;
|
||||
}
|
||||
@@ -308,21 +326,21 @@ namespace Spring.Web.Support
|
||||
if (pageDefinition != null)
|
||||
{
|
||||
if (isDebug)
|
||||
Log.Debug( string.Format( "GetHandler():found definition for page-name '{0}'", objectDefinitionName ) );
|
||||
Log.Debug(string.Format("GetHandler():found definition for page-name '{0}'", objectDefinitionName));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDebug)
|
||||
Log.Debug( string.Format( "GetHandler():no definition found for page-name '{0}'", pageName ) );
|
||||
Log.Debug(string.Format("GetHandler():no definition found for page-name '{0}'", pageName));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDebug)
|
||||
Log.Debug( string.Format( "GetHandler():found definition for page-url '{0}'", appRelativeVirtualPath ) );
|
||||
Log.Debug(string.Format("GetHandler():found definition for page-url '{0}'", appRelativeVirtualPath));
|
||||
}
|
||||
|
||||
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition( objectDefinitionName, pageDefinition );
|
||||
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition(objectDefinitionName, pageDefinition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -338,8 +356,8 @@ namespace Spring.Web.Support
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (handler is ISupportsWebDependencyInjection)
|
||||
&& (((ISupportsWebDependencyInjection)handler).DefaultApplicationContext == null) )
|
||||
if ((handler is ISupportsWebDependencyInjection)
|
||||
&& (((ISupportsWebDependencyInjection)handler).DefaultApplicationContext == null))
|
||||
{
|
||||
((ISupportsWebDependencyInjection)handler).DefaultApplicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web.UI;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using Spring.Web.Support;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -36,26 +38,20 @@ namespace Spring.Web.Support
|
||||
/// <author>Erich Eichinger</author>
|
||||
internal class ControlAccessor
|
||||
{
|
||||
private static readonly MethodInfo s_miClear = GetMethod("Clear");
|
||||
private static MethodInfo GetMethod(string name)
|
||||
{
|
||||
return typeof(Control).GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
}
|
||||
private static FieldInfo GetField(string name)
|
||||
{
|
||||
return typeof(Control).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
}
|
||||
|
||||
private delegate ControlCollection CreateControlCollectionDelegate(Control target);
|
||||
private delegate void AddedControlDelegate(Control target, Control control, int index);
|
||||
private delegate void RemovedControlDelegate(Control target, Control control);
|
||||
private delegate void VoidMethodDelegate(Control target);
|
||||
|
||||
private static readonly MethodInfo s_miClear;
|
||||
private static readonly SafeField ControlsArrayField;
|
||||
|
||||
#if NET_2_0
|
||||
private static readonly CreateControlCollectionDelegate BaseCreateControlCollection = (CreateControlCollectionDelegate) Delegate.CreateDelegate(typeof(CreateControlCollectionDelegate), GetMethod("CreateControlCollection"));
|
||||
private static readonly AddedControlDelegate BaseAddedControl = (AddedControlDelegate) Delegate.CreateDelegate(typeof (AddedControlDelegate), GetMethod("AddedControl"));
|
||||
private static readonly RemovedControlDelegate BaseRemovedControl = (RemovedControlDelegate) Delegate.CreateDelegate(typeof (RemovedControlDelegate), GetMethod("RemovedControl"));
|
||||
private static readonly VoidMethodDelegate BaseClearNamingContainer = (VoidMethodDelegate) Delegate.CreateDelegate(typeof (VoidMethodDelegate), GetMethod("ClearNamingContainer"));
|
||||
private static readonly CreateControlCollectionDelegate BaseCreateControlCollection;
|
||||
private static readonly AddedControlDelegate BaseAddedControl;
|
||||
private static readonly RemovedControlDelegate BaseRemovedControl;
|
||||
private static readonly VoidMethodDelegate BaseClearNamingContainer;
|
||||
|
||||
#else
|
||||
private class DynamicMethodWrapper
|
||||
{
|
||||
@@ -117,6 +113,56 @@ namespace Spring.Web.Support
|
||||
private static readonly VoidMethodDelegate BaseClearNamingContainer = DynamicMethodWrapper.ClearNamingContainer(GetMethod("ClearNamingContainer"));
|
||||
#endif
|
||||
|
||||
static ControlAccessor()
|
||||
{
|
||||
SafeField fldControls = null;
|
||||
MethodInfo fnClear = null;
|
||||
#if NET_2_0
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
#endif
|
||||
fnClear = GetMethod("Clear");
|
||||
fldControls = new SafeField(typeof(ControlCollection).GetField("_controls", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
#if NET_2_0
|
||||
});
|
||||
#endif
|
||||
s_miClear = fnClear;
|
||||
ControlsArrayField = fldControls;
|
||||
|
||||
#if NET_2_0
|
||||
CreateControlCollectionDelegate fnBaseCreateControlCollection = null;
|
||||
AddedControlDelegate fnBaseAddedControl = null;
|
||||
RemovedControlDelegate fnBaseRemovedControl = null;
|
||||
VoidMethodDelegate fnBaseClearNamingContainer = null;
|
||||
#if NET_2_0
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
#endif
|
||||
fnBaseCreateControlCollection = (CreateControlCollectionDelegate)Delegate.CreateDelegate(typeof(CreateControlCollectionDelegate), GetMethod("CreateControlCollection"));
|
||||
fnBaseAddedControl = (AddedControlDelegate)Delegate.CreateDelegate(typeof(AddedControlDelegate), GetMethod("AddedControl"));
|
||||
fnBaseRemovedControl = (RemovedControlDelegate)Delegate.CreateDelegate(typeof(RemovedControlDelegate), GetMethod("RemovedControl"));
|
||||
fnBaseClearNamingContainer = (VoidMethodDelegate)Delegate.CreateDelegate(typeof(VoidMethodDelegate), GetMethod("ClearNamingContainer"));
|
||||
#if NET_2_0
|
||||
});
|
||||
#endif
|
||||
BaseCreateControlCollection = fnBaseCreateControlCollection;
|
||||
BaseAddedControl = fnBaseAddedControl;
|
||||
BaseRemovedControl = fnBaseRemovedControl;
|
||||
BaseClearNamingContainer = fnBaseClearNamingContainer;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private static MethodInfo GetMethod(string name)
|
||||
{
|
||||
return typeof(Control).GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
}
|
||||
private static FieldInfo GetField(string name)
|
||||
{
|
||||
return typeof(Control).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
}
|
||||
|
||||
|
||||
private readonly Control _targetControl;
|
||||
|
||||
/// <summary>
|
||||
@@ -187,7 +233,6 @@ namespace Spring.Web.Support
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly SafeField ControlsArrayField = new SafeField(typeof(ControlCollection).GetField("_controls", BindingFlags.Instance|BindingFlags.NonPublic));
|
||||
public void SetControlAt(Control control, int index)
|
||||
{
|
||||
Control[] controls = (Control[]) ControlsArrayField.GetValue(this.Controls);
|
||||
@@ -217,24 +262,29 @@ namespace Spring.Web.Support
|
||||
MethodInfo ensureOccasionalFields = GetMethod("EnsureOccasionalFields");
|
||||
FieldInfo controls = occasionalFields.FieldType.GetField("Controls");
|
||||
|
||||
System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("get_Controls", typeof(ControlCollection), new Type[] { typeof(Control) }, typeof(Control).Module, true);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
Label occFieldsNull = il.DefineLabel();
|
||||
Label retControls = il.DefineLabel();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Brfalse_S, occFieldsNull);
|
||||
il.MarkLabel(retControls);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Ldfld, controls);
|
||||
il.Emit(OpCodes.Ret);
|
||||
il.MarkLabel(occFieldsNull);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, ensureOccasionalFields);
|
||||
il.Emit(OpCodes.Br, retControls);
|
||||
GetControlsDelegate handler = null;
|
||||
|
||||
return (GetControlsDelegate) dm.CreateDelegate(typeof(GetControlsDelegate));
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("get_Controls", typeof(ControlCollection), new Type[] { typeof(Control) }, typeof(Control).Module, true);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
Label occFieldsNull = il.DefineLabel();
|
||||
Label retControls = il.DefineLabel();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Brfalse_S, occFieldsNull);
|
||||
il.MarkLabel(retControls);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Ldfld, controls);
|
||||
il.Emit(OpCodes.Ret);
|
||||
il.MarkLabel(occFieldsNull);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, ensureOccasionalFields);
|
||||
il.Emit(OpCodes.Br, retControls);
|
||||
handler = (GetControlsDelegate) dm.CreateDelegate(typeof(GetControlsDelegate));
|
||||
});
|
||||
return handler;
|
||||
}
|
||||
|
||||
private static SetControlsDelegate GetSetControlsDelegate()
|
||||
@@ -243,53 +293,30 @@ namespace Spring.Web.Support
|
||||
MethodInfo ensureOccasionalFields = GetMethod("EnsureOccasionalFields");
|
||||
FieldInfo controls = occasionalFields.FieldType.GetField("Controls");
|
||||
|
||||
System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("set_Controls", null, new Type[] { typeof(Control), typeof(ControlCollection) }, typeof(Control).Module, true);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
Label occFieldsNull = il.DefineLabel();
|
||||
Label setControls = il.DefineLabel();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Brfalse_S, occFieldsNull);
|
||||
il.MarkLabel(setControls);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Stfld, controls);
|
||||
il.Emit(OpCodes.Ret);
|
||||
il.MarkLabel(occFieldsNull);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, ensureOccasionalFields);
|
||||
il.Emit(OpCodes.Br, setControls);
|
||||
|
||||
return (SetControlsDelegate) dm.CreateDelegate(typeof(SetControlsDelegate));
|
||||
SetControlsDelegate handler = null;
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("set_Controls", null, new Type[] { typeof(Control), typeof(ControlCollection) }, typeof(Control).Module, true);
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
Label occFieldsNull = il.DefineLabel();
|
||||
Label setControls = il.DefineLabel();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Brfalse_S, occFieldsNull);
|
||||
il.MarkLabel(setControls);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, occasionalFields);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Stfld, controls);
|
||||
il.Emit(OpCodes.Ret);
|
||||
il.MarkLabel(occFieldsNull);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, ensureOccasionalFields);
|
||||
il.Emit(OpCodes.Br, setControls);
|
||||
handler = (SetControlsDelegate) dm.CreateDelegate(typeof(SetControlsDelegate));
|
||||
});
|
||||
return handler;
|
||||
}
|
||||
|
||||
// private static readonly Type s_tOccasionalFields = typeof(Control).GetNestedType("OccasionalFields", BindingFlags.NonPublic);
|
||||
//
|
||||
// private static readonly VoidMethodDelegate EnsureOccasionalFields = (VoidMethodDelegate) Delegate.CreateDelegate(typeof (VoidMethodDelegate), GetMethod("EnsureOccasionalFields"));
|
||||
// private static readonly IDynamicField _occasionalFields = SafeField.CreateFrom(GetField("_occasionalFields"));
|
||||
// private static readonly IDynamicField _controls = SafeField.CreateFrom(s_tOccasionalFields.GetField("Controls"));
|
||||
//
|
||||
// private ControlCollection GetChildControlCollection()
|
||||
// {
|
||||
// // we *must not* simply call control.Controls here!
|
||||
// // Some controls (e.g. Repeater overload this property and call Control.EnsureChildControls()
|
||||
// // which causes Control.ChildControlsCreated flag to be set and prevents children from being created after loading viewstate!
|
||||
//
|
||||
// EnsureOccasionalFields(_targetControl);
|
||||
//
|
||||
// object occasionalFields = _occasionalFields.GetValue(_targetControl);
|
||||
// object childControls = _controls.GetValue(occasionalFields);
|
||||
// return (ControlCollection) childControls;
|
||||
// }
|
||||
//
|
||||
// private void SetChildControlCollection( ControlCollection controls )
|
||||
// {
|
||||
// EnsureOccasionalFields(_targetControl);
|
||||
//
|
||||
// object occasionalFields = _occasionalFields.GetValue(_targetControl);
|
||||
// _controls.SetValue(occasionalFields, controls);
|
||||
// }
|
||||
#else
|
||||
private static readonly IDynamicField fControls = SafeField.CreateFrom(GetField("_controls"));
|
||||
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web.UI;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -33,12 +36,25 @@ namespace Spring.Web.Support
|
||||
/// <author>Erich Eichinger</author>
|
||||
internal class ControlCollectionAccessor
|
||||
{
|
||||
#if MONO_2_0
|
||||
private static readonly IDynamicField _owner = new SafeField(typeof (ControlCollection).GetField("owner", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
#else
|
||||
private static readonly IDynamicField _owner = new SafeField(typeof (ControlCollection).GetField("_owner", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
private static readonly IDynamicField _owner;
|
||||
static ControlCollectionAccessor()
|
||||
{
|
||||
IDynamicField owner = null;
|
||||
#if NET_2_0
|
||||
SecurityCritical.ExecutePrivileged( new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
#endif
|
||||
|
||||
#if MONO_2_0
|
||||
owner = new SafeField(typeof (ControlCollection).GetField("owner", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
#else
|
||||
owner = new SafeField(typeof (ControlCollection).GetField("_owner", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
#endif
|
||||
#if NET_2_0
|
||||
});
|
||||
#endif
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
private readonly ControlCollection _controls;
|
||||
private readonly Type _controlsType;
|
||||
|
||||
|
||||
@@ -133,14 +133,13 @@ namespace Spring.Web.Support
|
||||
factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[ownerType];
|
||||
if (factoryMethod == null)
|
||||
{
|
||||
Type interceptedCollectionType =
|
||||
GetInterceptedCollectionType(collectionType, WebDependencyInjectionUtils.InjectDependenciesRecursive);
|
||||
Type interceptedCollectionType = GetInterceptedCollectionType(
|
||||
collectionType
|
||||
, WebDependencyInjectionUtils.InjectDependenciesRecursive
|
||||
);
|
||||
|
||||
ConstructorInfo ctor =
|
||||
interceptedCollectionType.GetConstructor(new Type[] { typeof(Control) });
|
||||
DynamicMethod dm =
|
||||
new System.Reflection.Emit.DynamicMethod(string.Empty, typeof(ControlCollection),
|
||||
new Type[] { typeof(Control) });
|
||||
ConstructorInfo ctor = interceptedCollectionType.GetConstructor(new Type[] { typeof(Control) });
|
||||
DynamicMethod dm = new DynamicMethod(string.Empty, typeof(ControlCollection), new Type[] { typeof(Control) });
|
||||
ILGenerator il = dm.GetILGenerator();
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Newobj, ctor);
|
||||
|
||||
@@ -24,6 +24,8 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web;
|
||||
using System.Web.Compilation;
|
||||
using System.Web.UI;
|
||||
@@ -46,17 +48,33 @@ namespace Spring.Web.Support
|
||||
internal abstract class LocalResourceManager : ResourceManager
|
||||
{
|
||||
private delegate IResourceProvider GetResourceProviderDelegate( TemplateControl control );
|
||||
private static readonly GetResourceProviderDelegate getLocalResourceProvider = (GetResourceProviderDelegate)Delegate.CreateDelegate( typeof( GetResourceProviderDelegate ), typeof( ResourceExpressionBuilder ).GetMethod( "GetLocalResourceProvider", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof( TemplateControl ) }, null ) );
|
||||
private static readonly Type LocalResXResourceProviderFactoryType = typeof( IResourceProvider ).Assembly.GetType( "System.Web.Compilation.ResXResourceProviderFactory", true );
|
||||
private static readonly Type LocalResXResourceProviderType = typeof( IResourceProvider ).Assembly.GetType( "System.Web.Compilation.LocalResXResourceProvider", true );
|
||||
private static readonly ResourceProviderFactory LocalResXResourceProviderFactory = (ResourceProviderFactory)Activator.CreateInstance( LocalResXResourceProviderFactoryType, true );
|
||||
private static readonly SafeMethod fnGetLocalResourceAssembly = new SafeMethod( LocalResXResourceProviderType.GetMethod( "GetLocalResourceAssembly", BindingFlags.Instance | BindingFlags.NonPublic ) );
|
||||
private static readonly GetResourceProviderDelegate getLocalResourceProvider;
|
||||
private static readonly Type LocalResXResourceProviderFactoryType;
|
||||
private static readonly Type LocalResXResourceProviderType;
|
||||
private static readonly ResourceProviderFactory LocalResXResourceProviderFactory;
|
||||
private static readonly SafeMethod fnGetLocalResourceAssembly;
|
||||
|
||||
/// <summary>
|
||||
/// Avoid beforeFieldInit
|
||||
/// </summary>
|
||||
static LocalResourceManager()
|
||||
{ }
|
||||
{
|
||||
LocalResXResourceProviderFactoryType = typeof(IResourceProvider).Assembly.GetType("System.Web.Compilation.ResXResourceProviderFactory", true);
|
||||
LocalResXResourceProviderType = typeof(IResourceProvider).Assembly.GetType("System.Web.Compilation.LocalResXResourceProvider", true);
|
||||
|
||||
GetResourceProviderDelegate fnGetResourceProvider = null;
|
||||
ResourceProviderFactory rpf = null;
|
||||
SafeMethod glra = null;
|
||||
SecurityCritical.ExecutePrivileged(new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
fnGetResourceProvider = (GetResourceProviderDelegate)Delegate.CreateDelegate(typeof(GetResourceProviderDelegate), typeof(ResourceExpressionBuilder).GetMethod("GetLocalResourceProvider", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(TemplateControl) }, null));
|
||||
rpf = (ResourceProviderFactory)Activator.CreateInstance( LocalResXResourceProviderFactoryType, true );
|
||||
glra = new SafeMethod(LocalResXResourceProviderType.GetMethod("GetLocalResourceAssembly", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
});
|
||||
getLocalResourceProvider = fnGetResourceProvider;
|
||||
LocalResXResourceProviderFactory = rpf;
|
||||
fnGetLocalResourceAssembly = glra;
|
||||
}
|
||||
|
||||
internal static ResourceManager GetLocalResourceManager( TemplateControl control )
|
||||
{
|
||||
|
||||
@@ -74,8 +74,6 @@ namespace Spring.Web.Support
|
||||
/// <returns>Instance of the IHttpHandler object that should be used to process request.</returns>
|
||||
public override IHttpHandler GetHandler(HttpContext context, string requestType, string url, string physicalPath)
|
||||
{
|
||||
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
|
||||
|
||||
return base.GetHandler(context, requestType, url, physicalPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
#region Imports
|
||||
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Web.UI;
|
||||
using Spring.Context;
|
||||
using Spring.Context.Support;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using Spring.Util;
|
||||
using Spring.Web.Support;
|
||||
|
||||
#endregion
|
||||
@@ -90,7 +93,17 @@ namespace Spring.Web.Support
|
||||
, INamingContainer
|
||||
{
|
||||
#if NET_2_0
|
||||
private static readonly SafeField refOccasionalFields = new SafeField(typeof(Control).GetField("_occasionalFields", BindingFlags.Instance|BindingFlags.NonPublic));
|
||||
private static readonly SafeField refOccasionalFields;
|
||||
|
||||
static NamingContainerSupportsWebDependencyInjectionOwnerProxy()
|
||||
{
|
||||
SafeField fld = null;
|
||||
SecurityCritical.ExecutePrivileged( new PermissionSet(PermissionState.Unrestricted), delegate
|
||||
{
|
||||
fld = new SafeField(typeof(Control).GetField("_occasionalFields", BindingFlags.Instance | BindingFlags.NonPublic));
|
||||
});
|
||||
refOccasionalFields = fld;
|
||||
}
|
||||
#endif
|
||||
|
||||
public NamingContainerSupportsWebDependencyInjectionOwnerProxy(IApplicationContext defaultApplicationContext, Control targetControl) : base(defaultApplicationContext, targetControl)
|
||||
|
||||
@@ -174,6 +174,13 @@ namespace Spring.Web.UI.Controls
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expose the context of this panel for medium trust safe access in e.g. <see cref="VisibleIf"/>.
|
||||
/// </summary>
|
||||
public new virtual HttpContext Context
|
||||
{
|
||||
get { return base.Context; }
|
||||
}
|
||||
#region Dependency Injection Support
|
||||
|
||||
private IApplicationContext _defaultApplicationContext;
|
||||
|
||||
@@ -740,6 +740,8 @@ namespace Spring.Web.UI
|
||||
set { this.sharedState = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Overrides the default PreviousPage property to return an instance of <see cref="Spring.Web.UI.Page"/>,
|
||||
@@ -750,8 +752,16 @@ namespace Spring.Web.UI
|
||||
get { return this.Context.PreviousHandler as Page; }
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
///<summary>
|
||||
/// Publish <see cref="HttpContext"/> associated with this page for convenient usage in Binding Expressions
|
||||
///</summary>
|
||||
[Browsable(false)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public new virtual HttpContext Context
|
||||
{
|
||||
get {
|
||||
return base.Context; }
|
||||
}
|
||||
|
||||
#region Master Page support
|
||||
|
||||
|
||||
@@ -1110,6 +1110,19 @@ namespace Spring.Web.UI
|
||||
get { return (Page)base.Page; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Publish <see cref="HttpContext"/> associated with this page for convenient usage in Binding Expressions
|
||||
///</summary>
|
||||
[Browsable(false)]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public new virtual HttpContext Context
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Context;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.CodeDom.Compiler;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Spring.Context.Support;
|
||||
@@ -264,14 +265,26 @@ namespace Spring.Reflection.Dynamic
|
||||
public class MyStaticClass
|
||||
{
|
||||
public const Int64 MyConst = 3456;
|
||||
public static readonly string myReadonlyField = "hohoho";
|
||||
public static readonly string myReadonlyField;
|
||||
private static readonly string myPrivateReadonlyField;
|
||||
public static string myField;
|
||||
|
||||
static MyStaticClass()
|
||||
{
|
||||
myReadonlyField = "hohoho";
|
||||
myPrivateReadonlyField = "hahaha";
|
||||
}
|
||||
|
||||
public static string MyProperty
|
||||
{
|
||||
get { return myField; }
|
||||
set { myField = value; }
|
||||
}
|
||||
|
||||
public static string MyPrivateReadOnylFieldAccessor
|
||||
{
|
||||
get { return myPrivateReadonlyField; }
|
||||
}
|
||||
}
|
||||
|
||||
public struct MyStaticStruct
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using NUnit.Framework;
|
||||
using Spring.Context.Support;
|
||||
|
||||
@@ -125,10 +127,54 @@ namespace Spring.Reflection.Dynamic
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
IDynamicField myReadonlyField = Create( typeof( MyStaticClass ).GetField( "myReadonlyField" ) );
|
||||
Assert.AreEqual( "hohoho", myReadonlyField.GetValue( null ) );
|
||||
string s2 = (string) myReadonlyField.GetValue(null);
|
||||
string s1 = MyStaticClass.myReadonlyField;
|
||||
Assert.AreEqual(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
#if NET_2_0
|
||||
|
||||
[Test]
|
||||
public void CanReadPrivateReadOnlyField()
|
||||
{
|
||||
IDynamicField myPrivateReadonlyField2 = null;
|
||||
FieldInfo fieldInfo = typeof(MyStaticClass).GetField("myPrivateReadonlyField", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
myPrivateReadonlyField2 = Create(fieldInfo);
|
||||
|
||||
string u2 = (string)myPrivateReadonlyField2.GetValue(null);
|
||||
string u1 = "hahaha";
|
||||
Assert.AreEqual(u1, u2);
|
||||
}
|
||||
|
||||
[Test, Ignore("TODO: this works as expected when run using TD.NET & R# (in VS2k8), but fails with nant/NET 2.0 ?!?")]
|
||||
public void CannotReadPrivateReadOnlyFieldIfNoReflectionPermission()
|
||||
{
|
||||
FieldInfo fieldInfo = typeof(MyStaticClass).GetField("myPrivateReadonlyField", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
try
|
||||
{
|
||||
myReadonlyField.SetValue( null, "some other string" );
|
||||
SecurityTemplate.MediumTrustInvoke( delegate
|
||||
{
|
||||
IDynamicField myPrivateReadonlyField2 = Create(fieldInfo);
|
||||
});
|
||||
Assert.Fail("private field must not be accessible in medium trust: " + fieldInfo);
|
||||
}
|
||||
catch (SecurityException sex)
|
||||
{
|
||||
Assert.IsTrue( sex.Message.IndexOf("ReflectionPermission") > -1 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void CannotSetStaticReadOnlyField()
|
||||
{
|
||||
IDynamicField myReadonlyField = Create(typeof(MyStaticClass).GetField("myReadonlyField"));
|
||||
try
|
||||
{
|
||||
myReadonlyField.SetValue(null, "some other string");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (InvalidOperationException) { }
|
||||
}
|
||||
|
||||
526
test/Spring/Spring.Core.Tests/SecurityTemplate.cs
Normal file
526
test/Spring/Spring.Core.Tests/SecurityTemplate.cs
Normal file
@@ -0,0 +1,526 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Data.SqlClient;
|
||||
using System.Drawing.Printing;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
//using System.Net.Mail;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
|
||||
namespace Spring
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows to invoke parts of your code within the context of a certain PermissionSet.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// You may also use the static method <see cref="LoadDomainPolicyFromAppConfig"/> and
|
||||
/// <see cref="LoadDomainPolicyFromUri"/> to load a <see cref="PolicyLevel"/> instance
|
||||
/// yourself and apply it on your application domain using <see cref="AppDomain.SetAppDomainPolicy"/>. Note,
|
||||
/// that you must set the policy *before* an assembly gets loaded to apply that policy on that assembly!
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The policy file format is the one used by <see cref="SecurityManager.LoadPolicyLevelFromString"/>.
|
||||
/// You get good examples from your %FrameworkDir%/CONFIG/ directory (e.g. 'web_mediumtrust.config').
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public class SecurityTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// The default full trust permission set name ("FullTrust")
|
||||
/// </summary>
|
||||
public static readonly string PERMISSIONSET_FULLTRUST = "FullTrust";
|
||||
/// <summary>
|
||||
/// The default no trust permission set name ("Nothing")
|
||||
/// </summary>
|
||||
public static readonly string PERMISSIONSET_NOTHING = "Nothing";
|
||||
/// <summary>
|
||||
/// The default medium trust permission set name ("MediumTrust")
|
||||
/// </summary>
|
||||
public static readonly string PERMISSIONSET_MEDIUMTRUST = "MediumTrust";
|
||||
/// <summary>
|
||||
/// The default low trust permission set name ("LowTrust")
|
||||
/// </summary>
|
||||
public static readonly string PERMISSIONSET_LOWTRUST = "LowTrust";
|
||||
/// <summary>
|
||||
/// The default asp.net permission set name ("ASP.NET")
|
||||
/// </summary>
|
||||
public static readonly string PERMISSIONSET_ASPNET = "ASP.Net";
|
||||
|
||||
private readonly PolicyLevel _domainPolicy;
|
||||
// private readonly Dictionary<string, SecurityContext> securityContextCache = new Dictionary<string, SecurityContext>();
|
||||
private bool throwOnUnknownPermissionSet = true;
|
||||
|
||||
/// <summary>
|
||||
/// Avoid beforeFieldInit
|
||||
/// </summary>
|
||||
static SecurityTemplate()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Invoke the specified callback in a medium trusted context
|
||||
/// </summary>
|
||||
public static void MediumTrustInvoke( ThreadStart callback )
|
||||
{
|
||||
SecurityTemplate template = new SecurityTemplate(false);
|
||||
template.PartialTrustInvoke(PERMISSIONSET_MEDIUMTRUST, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access the domain <see cref="PolicyLevel"/> of this <see cref="SecurityTemplate"/> instance.
|
||||
/// </summary>
|
||||
public PolicyLevel DomainPolicy
|
||||
{
|
||||
get { return _domainPolicy; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether to throw an <see cref="ArgumentOutOfRangeException"/> in case
|
||||
/// the permission set name is not found when invoking <see cref="PartialTrustInvoke(string,ThreadStart)"/>.
|
||||
/// Defaults to <c>true</c>.
|
||||
/// </summary>
|
||||
public bool ThrowOnUnknownPermissionSet
|
||||
{
|
||||
get { return throwOnUnknownPermissionSet; }
|
||||
set
|
||||
{
|
||||
throwOnUnknownPermissionSet = value;
|
||||
// securityContextCache.Clear(); // clear cache
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance providing default "FullTrust", "Nothing", "MediumTrust" and "LowTrust" permissionsets
|
||||
/// </summary>
|
||||
/// <param name="allowUnmanagedCode">NCover requires unmangaged code permissions, set this flag <c>true</c> in this case.</param>
|
||||
private SecurityTemplate(bool allowUnmanagedCode)
|
||||
{
|
||||
PolicyLevel pLevel = PolicyLevel.CreateAppDomainLevel();
|
||||
|
||||
// NOTHING permissionset
|
||||
if (null == pLevel.GetNamedPermissionSet(PERMISSIONSET_NOTHING))
|
||||
{
|
||||
NamedPermissionSet noPermissionSet = new NamedPermissionSet(PERMISSIONSET_NOTHING, PermissionState.None);
|
||||
noPermissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.NoFlags));
|
||||
pLevel.AddNamedPermissionSet(noPermissionSet);
|
||||
}
|
||||
|
||||
// FULLTRUST permissionset
|
||||
if (null == pLevel.GetNamedPermissionSet(PERMISSIONSET_FULLTRUST))
|
||||
{
|
||||
NamedPermissionSet fulltrustPermissionSet = new NamedPermissionSet(PERMISSIONSET_FULLTRUST, PermissionState.Unrestricted);
|
||||
pLevel.AddNamedPermissionSet(fulltrustPermissionSet);
|
||||
}
|
||||
// MEDIUMTRUST permissionset (corresponds to ASP.Net permission set in web_mediumtrust.config)
|
||||
NamedPermissionSet mediumTrustPermissionSet = new NamedPermissionSet(PERMISSIONSET_MEDIUMTRUST, PermissionState.None);
|
||||
mediumTrustPermissionSet.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Medium));
|
||||
mediumTrustPermissionSet.AddPermission(new DnsPermission(PermissionState.Unrestricted));
|
||||
mediumTrustPermissionSet.AddPermission(new EnvironmentPermission(EnvironmentPermissionAccess.Read,
|
||||
"TEMP;TMP;USERNAME;OS;COMPUTERNAME"));
|
||||
mediumTrustPermissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess,
|
||||
AppDomain.CurrentDomain.BaseDirectory));
|
||||
IsolatedStorageFilePermission isolatedStorageFilePermission = new IsolatedStorageFilePermission(PermissionState.None);
|
||||
isolatedStorageFilePermission.UsageAllowed = IsolatedStorageContainment.AssemblyIsolationByUser;
|
||||
isolatedStorageFilePermission.UserQuota = 9223372036854775807;
|
||||
mediumTrustPermissionSet.AddPermission(isolatedStorageFilePermission);
|
||||
mediumTrustPermissionSet.AddPermission(new PrintingPermission(PrintingPermissionLevel.DefaultPrinting));
|
||||
SecurityPermissionFlag securityPermissionFlag = SecurityPermissionFlag.Assertion | SecurityPermissionFlag.Execution |
|
||||
SecurityPermissionFlag.ControlThread | SecurityPermissionFlag.ControlPrincipal |
|
||||
SecurityPermissionFlag.RemotingConfiguration;
|
||||
if (allowUnmanagedCode)
|
||||
{
|
||||
securityPermissionFlag |= SecurityPermissionFlag.UnmanagedCode;
|
||||
}
|
||||
mediumTrustPermissionSet.AddPermission(new SecurityPermission(securityPermissionFlag));
|
||||
#if NET_2_0
|
||||
mediumTrustPermissionSet.AddPermission(new System.Net.Mail.SmtpPermission(System.Net.Mail.SmtpAccess.Connect));
|
||||
#endif
|
||||
mediumTrustPermissionSet.AddPermission(new SqlClientPermission(PermissionState.Unrestricted));
|
||||
mediumTrustPermissionSet.AddPermission(new WebPermission());
|
||||
pLevel.AddNamedPermissionSet(mediumTrustPermissionSet);
|
||||
|
||||
// LOWTRUST permissionset (corresponds to ASP.Net permission set in web_mediumtrust.config)
|
||||
NamedPermissionSet lowTrustPermissionSet = new NamedPermissionSet(PERMISSIONSET_LOWTRUST, PermissionState.None);
|
||||
lowTrustPermissionSet.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Low));
|
||||
lowTrustPermissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery,
|
||||
AppDomain.CurrentDomain.BaseDirectory));
|
||||
IsolatedStorageFilePermission isolatedStorageFilePermissionLow = new IsolatedStorageFilePermission(PermissionState.None);
|
||||
isolatedStorageFilePermissionLow.UsageAllowed = IsolatedStorageContainment.AssemblyIsolationByUser;
|
||||
isolatedStorageFilePermissionLow.UserQuota = 1048576;
|
||||
lowTrustPermissionSet.AddPermission(isolatedStorageFilePermissionLow);
|
||||
SecurityPermissionFlag securityPermissionFlagLow = SecurityPermissionFlag.Execution;
|
||||
if (allowUnmanagedCode)
|
||||
{
|
||||
securityPermissionFlagLow |= SecurityPermissionFlag.UnmanagedCode;
|
||||
}
|
||||
lowTrustPermissionSet.AddPermission(new SecurityPermission(securityPermissionFlagLow));
|
||||
pLevel.AddNamedPermissionSet(lowTrustPermissionSet);
|
||||
|
||||
// UnionCodeGroup rootCodeGroup = new UnionCodeGroup(new AllMembershipCondition(), new PolicyStatement(noPermissionSet, PolicyStatementAttribute.Nothing));
|
||||
// pLevel.RootCodeGroup = rootCodeGroup;
|
||||
_domainPolicy = pLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads domain policy from specified file
|
||||
/// </summary>
|
||||
/// <param name="securityConfigurationFile"></param>
|
||||
public SecurityTemplate(FileInfo securityConfigurationFile)
|
||||
{
|
||||
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
_domainPolicy = LoadDomainPolicyFromUri(new Uri(securityConfigurationFile.FullName), appDirectory, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a security tool from the specified domainPolicy
|
||||
/// </summary>
|
||||
public SecurityTemplate(PolicyLevel domainPolicy)
|
||||
{
|
||||
this._domainPolicy = domainPolicy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the given callback using the policy's default
|
||||
/// partial trust permissionset ("ASP.Net" <see cref="PERMISSIONSET_ASPNET"/>).
|
||||
/// </summary>
|
||||
public void PartialTrustInvoke(ThreadStart callback)
|
||||
{
|
||||
string defaultPermissionSetName = PERMISSIONSET_MEDIUMTRUST;
|
||||
if (null != GetNamedPermissionSet(PERMISSIONSET_ASPNET))
|
||||
{
|
||||
defaultPermissionSetName = PERMISSIONSET_ASPNET;
|
||||
}
|
||||
|
||||
PartialTrustInvoke(defaultPermissionSetName, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the given callback using the specified permissionset.
|
||||
/// </summary>
|
||||
// [SecurityTreatAsSafe, SecurityCritical]
|
||||
public void PartialTrustInvoke(string permissionSetName, ThreadStart callback)
|
||||
{
|
||||
PermissionSet ps = null;
|
||||
ps = GetNamedPermissionSet(permissionSetName);
|
||||
if (ps == null && throwOnUnknownPermissionSet)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("permissionSetName", permissionSetName,
|
||||
string.Format("unknown PermissionSet name '{0}'",
|
||||
permissionSetName));
|
||||
}
|
||||
|
||||
if (!IsFullTrust(ps))
|
||||
{
|
||||
ps.PermitOnly();
|
||||
callback();
|
||||
CodeAccessPermission.RevertPermitOnly();
|
||||
}
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
private PermissionSet GetNamedPermissionSet(string name)
|
||||
{
|
||||
if (_domainPolicy != null)
|
||||
{
|
||||
return _domainPolicy.GetNamedPermissionSet(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the policy configuration from app.config configuration section
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// Configuration is identical to web.config:
|
||||
/// <code>
|
||||
/// <configuration>
|
||||
/// <system.web>
|
||||
/// <securityPolicy>
|
||||
/// <trustLevel name="Full" policyFile="internal"/>
|
||||
/// <trustLevel name="High" policyFile="web_hightrust.config"/>
|
||||
/// <trustLevel name="Medium" policyFile="web_mediumtrust.config"/>
|
||||
/// <trustLevel name="Low" policyFile="web_lowtrust.config"/>
|
||||
/// <trustLevel name="Minimal" policyFile="web_minimaltrust.config"/>
|
||||
/// </securityPolicy>
|
||||
/// <trust level="Medium" originUrl=""/>
|
||||
/// </system.web>
|
||||
/// </configuration>
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="throwOnError"></param>
|
||||
/// <returns></returns>
|
||||
public static PolicyLevel LoadDomainPolicyFromAppConfig(bool throwOnError)
|
||||
{
|
||||
TrustSection trustSection = (TrustSection)ConfigurationManager.GetSection("system.web/trust");
|
||||
SecurityPolicySection securityPolicySection = (SecurityPolicySection)ConfigurationManager.GetSection("system.web/securityPolicy");
|
||||
|
||||
if ((trustSection == null) || string.IsNullOrEmpty(trustSection.Level))
|
||||
{
|
||||
if (!throwOnError)
|
||||
return null;
|
||||
throw new ConfigurationErrorsException("Configuration section <system.web/trust> not found ");
|
||||
}
|
||||
|
||||
if (trustSection.Level == "Full")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((securityPolicySection == null) || (securityPolicySection.TrustLevels[trustSection.Level] == null))
|
||||
{
|
||||
if (!throwOnError)
|
||||
return null;
|
||||
throw new ConfigurationErrorsException(string.Format("configuration <system.web/securityPolicy/trustLevel@name='{0}'> not found", trustSection.Level));
|
||||
}
|
||||
|
||||
string policyFileExpanded = GetPolicyFilenameExpanded(securityPolicySection.TrustLevels[trustSection.Level]);
|
||||
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
PolicyLevel domainPolicy = LoadDomainPolicyFromUri(new Uri(policyFileExpanded), appDirectory, trustSection.OriginUrl);
|
||||
return domainPolicy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a policy from a file (<see cref="SecurityManager.LoadPolicyLevelFromFile"/>),
|
||||
/// replacing placeholders
|
||||
/// <list>
|
||||
/// <item>$AppDir$, $AppDirUrl$ => <paramref name="appDirectory"/></item>
|
||||
/// <item>$CodeGen$ => (TODO)</item>
|
||||
/// <item>$OriginHost$ => <paramref name="originUrl"/></item>
|
||||
/// <item>$Gac$ => the current machine's GAC path</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <param name="policyFileLocation"></param>
|
||||
/// <param name="originUrl"></param>
|
||||
/// <param name="appDirectory"></param>
|
||||
/// <returns></returns>
|
||||
public static PolicyLevel LoadDomainPolicyFromUri(Uri policyFileLocation, string appDirectory, string originUrl)
|
||||
{
|
||||
bool foundGacToken = false;
|
||||
PolicyLevel domainPolicy = CreatePolicyLevel(policyFileLocation, appDirectory, appDirectory, originUrl, out foundGacToken);
|
||||
if (foundGacToken)
|
||||
{
|
||||
CodeGroup rootCodeGroup = domainPolicy.RootCodeGroup;
|
||||
bool hasGacMembershipCondition = false;
|
||||
foreach (CodeGroup childCodeGroup in rootCodeGroup.Children)
|
||||
{
|
||||
if (childCodeGroup.MembershipCondition is GacMembershipCondition)
|
||||
{
|
||||
hasGacMembershipCondition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasGacMembershipCondition && (rootCodeGroup is FirstMatchCodeGroup))
|
||||
{
|
||||
FirstMatchCodeGroup firstMatchCodeGroup = (FirstMatchCodeGroup)rootCodeGroup;
|
||||
if ((firstMatchCodeGroup.MembershipCondition is AllMembershipCondition) && (firstMatchCodeGroup.PermissionSetName == PERMISSIONSET_NOTHING))
|
||||
{
|
||||
PermissionSet unrestrictedPermissionSet = new PermissionSet(PermissionState.Unrestricted);
|
||||
CodeGroup gacGroup = new UnionCodeGroup(new GacMembershipCondition(), new PolicyStatement(unrestrictedPermissionSet));
|
||||
CodeGroup rootGroup = new FirstMatchCodeGroup(rootCodeGroup.MembershipCondition, rootCodeGroup.PolicyStatement);
|
||||
foreach (CodeGroup childGroup in rootCodeGroup.Children)
|
||||
{
|
||||
if (((childGroup is UnionCodeGroup) && (childGroup.MembershipCondition is UrlMembershipCondition)) && (childGroup.PolicyStatement.PermissionSet.IsUnrestricted() && (gacGroup != null)))
|
||||
{
|
||||
rootGroup.AddChild(gacGroup);
|
||||
gacGroup = null;
|
||||
}
|
||||
rootGroup.AddChild(childGroup);
|
||||
}
|
||||
domainPolicy.RootCodeGroup = rootGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
return domainPolicy;
|
||||
}
|
||||
|
||||
private static PolicyLevel CreatePolicyLevel(Uri configFile, string appDir, string binDir, string strOriginUrl, out bool foundGacToken)
|
||||
{
|
||||
WebClient webClient = new WebClient();
|
||||
string strXmlPolicy = webClient.DownloadString(configFile);
|
||||
appDir = FileUtil.RemoveTrailingDirectoryBackSlash(appDir);
|
||||
binDir = FileUtil.RemoveTrailingDirectoryBackSlash(binDir);
|
||||
strXmlPolicy = strXmlPolicy.Replace("$AppDir$", appDir).Replace("$AppDirUrl$", MakeFileUrl(appDir)).Replace("$CodeGen$", MakeFileUrl(binDir));
|
||||
if (strOriginUrl == null)
|
||||
{
|
||||
strOriginUrl = string.Empty;
|
||||
}
|
||||
strXmlPolicy = strXmlPolicy.Replace("$OriginHost$", strOriginUrl);
|
||||
if (strXmlPolicy.IndexOf("$Gac$", StringComparison.Ordinal) != -1)
|
||||
{
|
||||
string gacLocation = GetGacLocation();
|
||||
if (gacLocation != null)
|
||||
{
|
||||
gacLocation = MakeFileUrl(gacLocation);
|
||||
}
|
||||
if (gacLocation == null)
|
||||
{
|
||||
gacLocation = string.Empty;
|
||||
}
|
||||
strXmlPolicy = strXmlPolicy.Replace("$Gac$", gacLocation);
|
||||
foundGacToken = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foundGacToken = false;
|
||||
}
|
||||
return SecurityManager.LoadPolicyLevelFromString(strXmlPolicy, PolicyLevelType.AppDomain);
|
||||
}
|
||||
|
||||
private static string GetPolicyFilenameExpanded(TrustLevel trustLevel)
|
||||
{
|
||||
bool isRelative = true;
|
||||
if (trustLevel.PolicyFile.Length > 1)
|
||||
{
|
||||
char ch = trustLevel.PolicyFile[1];
|
||||
char ch2 = trustLevel.PolicyFile[0];
|
||||
if (ch == ':')
|
||||
{
|
||||
isRelative = false;
|
||||
}
|
||||
else if ((ch2 == '\\') && (ch == '\\'))
|
||||
{
|
||||
isRelative = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRelative)
|
||||
{
|
||||
string configurationElementFileSource = trustLevel.ElementInformation.Properties["policyFile"].Source;
|
||||
string path = configurationElementFileSource.Substring(0, configurationElementFileSource.LastIndexOf('\\') + 1);
|
||||
return path + trustLevel.PolicyFile;
|
||||
}
|
||||
return trustLevel.PolicyFile;
|
||||
}
|
||||
|
||||
[DllImport("mscorwks.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern int GetCachePath(int dwCacheFlags, StringBuilder pwzCachePath, ref int pcchPath);
|
||||
|
||||
private static string GetGacLocation()
|
||||
{
|
||||
int capacity = 0x106;
|
||||
StringBuilder pwzCachePath = new StringBuilder(capacity);
|
||||
int pcchPath = capacity - 2;
|
||||
int hRes = GetCachePath(2, pwzCachePath, ref pcchPath);
|
||||
if (hRes < 0)
|
||||
{
|
||||
throw new HttpException("failed obtaining GAC path", hRes);
|
||||
}
|
||||
return pwzCachePath.ToString();
|
||||
}
|
||||
|
||||
private static string MakeFileUrl(string path)
|
||||
{
|
||||
Uri uri = new Uri(path);
|
||||
return uri.ToString();
|
||||
}
|
||||
|
||||
private class FileUtil
|
||||
{
|
||||
internal static string RemoveTrailingDirectoryBackSlash(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int length = path.Length;
|
||||
if ((length > 3) && (path[length - 1] == '\\'))
|
||||
{
|
||||
path = path.Substring(0, length - 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsFullTrust(PermissionSet perms)
|
||||
{
|
||||
if (perms != null)
|
||||
{
|
||||
return perms.IsUnrestricted();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// [SecurityTreatAsSafe, SecurityCritical]
|
||||
// private bool NeedPartialTrustInvoke(string permissionSetName)
|
||||
// {
|
||||
// if (_domainPolicy == null) return false;
|
||||
//
|
||||
// SecurityContext securityContext = null;
|
||||
// if (!securityContextCache.ContainsKey(permissionSetName))
|
||||
// {
|
||||
// NamedPermissionSet permissionSet = _domainPolicy.GetNamedPermissionSet(permissionSetName);
|
||||
// if (permissionSet == null && throwOnUnknownPermissionSet)
|
||||
// {
|
||||
// throw new ArgumentOutOfRangeException("permissionSetName", permissionSetName, "Undefined permission set");
|
||||
// }
|
||||
// if (!IsFullTrust(permissionSet))
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// permissionSet.PermitOnly();
|
||||
// securityContext = CaptureSecurityContextNoIdentityFlow();
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// CodeAccessPermission.RevertPermitOnly();
|
||||
// }
|
||||
// }
|
||||
// securityContextCache[permissionSetName] = securityContext;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// securityContext = securityContextCache[permissionSetName];
|
||||
// }
|
||||
// return (securityContext != null);
|
||||
// }
|
||||
|
||||
|
||||
// [SecurityCritical]
|
||||
// private static SecurityContext CaptureSecurityContextNoIdentityFlow()
|
||||
// {
|
||||
// if (SecurityContext.IsWindowsIdentityFlowSuppressed())
|
||||
// {
|
||||
// return SecurityContext.Capture();
|
||||
// }
|
||||
// using (SecurityContext.SuppressFlowWindowsIdentity())
|
||||
// {
|
||||
// return SecurityContext.Capture();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -656,6 +656,7 @@
|
||||
<Compile Include="Reflection\Dynamic\DynamicPropertyTests.cs" />
|
||||
<Compile Include="Reflection\Dynamic\SafeFieldTests.cs" />
|
||||
<Compile Include="Reflection\Dynamic\SafePropertyTests.cs" />
|
||||
<Compile Include="SecurityTemplate.cs" />
|
||||
<Compile Include="StandardsComplianceTest.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Util
|
||||
@@ -46,9 +50,50 @@ namespace Spring.Util
|
||||
|
||||
ReflectionUtils.MemberwiseCopy(i2, i1);
|
||||
|
||||
Assert.AreEqual(i2, i1);
|
||||
Assert.AreEqual(i1, i2);
|
||||
}
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
[Test]
|
||||
public void MediumTrustAllowsCopyingBetweenTypesFromSameModule()
|
||||
{
|
||||
SampleBaseClass i1 = new SampleDerivedClass("1st config val");
|
||||
SampleBaseClass i2 = new SampleFurtherDerivedClass("2nd config val");
|
||||
|
||||
SecurityTemplate.MediumTrustInvoke(new ThreadStart(new CopyCommand(i2, i1).Execute));
|
||||
Assert.AreEqual(i1, i2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MediumTrustThrowsSecurityExceptionWhenCopyingBetweenTypesFromDifferentModules()
|
||||
{
|
||||
Exception e1 = new Exception("my name is e1");
|
||||
HttpException e2 = new HttpException("my name is e2");
|
||||
// I know, I am a bit paranoid about that basic assumption
|
||||
Assert.AreNotEqual( e1.GetType().Assembly, e2.GetType().Assembly );
|
||||
|
||||
SecurityTemplate.MediumTrustInvoke(new ThreadStart(new CopyCommand(e2, e1).Execute));
|
||||
Assert.AreEqual(e1.Message, e2.Message);
|
||||
}
|
||||
|
||||
class CopyCommand
|
||||
{
|
||||
private object a;
|
||||
private object b;
|
||||
|
||||
public CopyCommand(object a, object b)
|
||||
{
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
ReflectionUtils.MemberwiseCopy(a, b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Test Support Classes
|
||||
|
||||
@@ -57,7 +102,7 @@ namespace Spring.Util
|
||||
private const string MyConstant = "SampleBaseClass.MyConstant";
|
||||
private readonly string _someReadOnlyVal = "SampleBaseClass.SomeReadOnlyVal";
|
||||
protected readonly string _someProtectedReadOnlyVal = "SampleBaseClass.SomeProtectedReadOnlyVal";
|
||||
private string _someConfigVal = "SampleBaseClass.SomeConfigVal";
|
||||
private string _someConfigVal;
|
||||
|
||||
public SampleBaseClass(string someConfigVal)
|
||||
{
|
||||
@@ -76,9 +121,12 @@ namespace Spring.Util
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
SampleBaseClass sampleBaseClass = obj as SampleBaseClass;
|
||||
if (sampleBaseClass == null) return false;
|
||||
if (ReferenceEquals(obj, null) || (!this.GetType().IsAssignableFrom(obj.GetType())))
|
||||
return false;
|
||||
if (ReferenceEquals(this , obj))
|
||||
return true;
|
||||
|
||||
SampleBaseClass sampleBaseClass = (SampleBaseClass) obj;
|
||||
if (!Equals(_someReadOnlyVal, sampleBaseClass._someReadOnlyVal)) return false;
|
||||
if (!Equals(_someProtectedReadOnlyVal, sampleBaseClass._someProtectedReadOnlyVal)) return false;
|
||||
if (!Equals(_someConfigVal, sampleBaseClass._someConfigVal)) return false;
|
||||
@@ -102,11 +150,12 @@ namespace Spring.Util
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
SampleDerivedClass sampleDerivedClass = obj as SampleDerivedClass;
|
||||
if (sampleDerivedClass == null) return false;
|
||||
if (!base.Equals(obj)) return false;
|
||||
if (!Equals(_someConfigVal, sampleDerivedClass._someConfigVal)) return false;
|
||||
if (!base.Equals(obj))
|
||||
return false;
|
||||
|
||||
SampleDerivedClass sampleDerivedClass = (SampleDerivedClass)obj;
|
||||
if (!Equals(_someConfigVal, sampleDerivedClass._someConfigVal))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user