소스 검색

Add support for App_GlobalResources and App_LocalResources

svn path=/trunk/mcs/; revision=66799
Marek Habersack 19 년 전
부모
커밋
58fca48c17

+ 5 - 0
mcs/class/ChangeLog

@@ -1,3 +1,8 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* Makefile: Change the order of assembly compilation to make it
+	possible to compile the global/local resources compiler.
+
 2006-09-04  Zoltan Varga  <[email protected]>
 
 	* Makefile (BROKEN_SUBDIRS): Fix make dist.

+ 4 - 4
mcs/class/Makefile

@@ -47,6 +47,10 @@ common_dirs := \
 	System.Data			\
 	Mono.Data			\
 	Mono.GetOptions			\
+	$(MONO_SYMBOLWRITER)		\
+	$(MONO_POSIX)			\
+	Accessibility			\
+	Managed.Windows.Forms		\
 	System.Web			\
 	System.Web.Services		\
 	System.Web			\
@@ -54,16 +58,12 @@ common_dirs := \
 	System.Runtime.Remoting		\
 	System.Configuration.Install 	\
 	System.Management		\
-	$(MONO_SYMBOLWRITER)		\
-	$(MONO_POSIX)			\
 	Mono.Data.SqliteClient		\
 	Mono.Data.SybaseClient		\
 	Mono.Data.TdsClient		\
 	System.Data.OracleClient	\
-	Accessibility			\
 	Microsoft.VisualC		\
 	Cscompmgd			\
-	Managed.Windows.Forms		\
 	System.Design			\
 	PEAPI				\
 	Npgsql				\

+ 8 - 0
mcs/class/System.Web/ChangeLog

@@ -1,3 +1,11 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* System.Web.dll.sources: add global/local resources compiler
+	files.
+
+	* Makefile: System.Windows.Forms.dll is needed for global/local
+	resource compiler now.
+
 2006-10-17 Vladimir Krasnov <[email protected]>
 
 	* run-mono-tests.bat: added Derby to tests classpath

+ 1 - 1
mcs/class/System.Web/Makefile

@@ -125,7 +125,7 @@ TEST_RESOURCE_FILES = \
 NUNIT_RESOURCE_FILES = $(TEST_RESOURCE_FILES)
 ifeq (net_2_0, $(PROFILE))
 OTHER_RES += $(RESOURCE_FILES_2)
-OTHER_LIB_MCS_FLAGS = -nowarn:618 -r:System.Configuration.dll
+OTHER_LIB_MCS_FLAGS = -nowarn:618 -r:System.Configuration.dll -r:System.Windows.Forms.dll
 endif
 
 LIB_MCS_FLAGS = \

+ 10 - 0
mcs/class/System.Web/System.Web.Compilation/BaseCompiler.cs

@@ -110,6 +110,16 @@ namespace System.Web.Compilation
 				}
 			}
 
+#if NET_2_0
+			ArrayList al = WebConfigurationManager.ExtraAssemblies;
+			if (al != null && al.Count > 0) {
+				foreach (object o in al) {
+					if (o is string) {
+						unit.ReferencedAssemblies.Add ((string) o);
+					}
+				}
+			}
+#endif
 			// Late-bound generators specifics (as for MonoBASIC/VB.NET)
 			unit.UserData["RequireVariableDeclaration"] = parser.ExplicitOn;
 			unit.UserData["AllowLateBound"] = !parser.StrictOn;

+ 15 - 0
mcs/class/System.Web/System.Web.Compilation/ChangeLog

@@ -1,3 +1,18 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* TemplateControlCompiler.cs: add support for resource
+	expressions in tag attributes.
+
+	* ResourceExpressionBuilder.cs: add support for resource
+	expressions in tag attributes.
+
+	* BaseCompiler.cs: add global/local resource assemblies to
+	compilation references, if present.
+
+	* AppResourcesCompiler.cs: global/local resources compiler.
+
+	* AppResourceFilesCompiler.cs: compiler of resource files.
+
 2006-10-03 Igor Zelmanovich <[email protected]>
 
 	* TemplateControlCompiler.cs: fixed: Bind functions (Data-Binding Syntax).

+ 11 - 6
mcs/class/System.Web/System.Web.Compilation/ResourceExpressionBuilder.cs

@@ -32,6 +32,7 @@
 
 using System;
 using System.CodeDom;
+using System.Web;
 using System.Web.UI;
 
 namespace System.Web.Compilation {
@@ -44,16 +45,20 @@ namespace System.Web.Compilation {
 		{
 		}
 
-		[MonoTODO]
 		public override object EvaluateExpression (object target, BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
 		{
-			throw new NotImplementedException ();
+			ResourceExpressionFields fields = parsedData as ResourceExpressionFields;
+			return HttpContext.GetGlobalResourceObject (fields.ClassKey, fields.ResourceKey);
 		}
 
-		[MonoTODO]
 		public override CodeExpression GetCodeExpression (BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
 		{
-			throw new NotImplementedException ();
+			ResourceExpressionFields fields = parsedData as ResourceExpressionFields;
+			return new CodeMethodInvokeExpression (
+				new CodeThisReferenceExpression (),
+				"GetGlobalResourceObject",
+				new CodeExpression [] { new CodePrimitiveExpression (fields.ClassKey),
+							new CodePrimitiveExpression (fields.ResourceKey) });
 		}
 
 		public static ResourceExpressionFields ParseExpression (string expression)
@@ -66,10 +71,10 @@ namespace System.Web.Compilation {
 								     expression.Substring (comma + 1).Trim ());
 		}
 
-		[MonoTODO]
 		public override object ParseExpression (string expression, Type propertyType, ExpressionBuilderContext context)
 		{
-			throw new NotImplementedException ();
+			//FIXME: not sure what the propertyType should be used for
+			return ParseExpression (expression);
 		}
 
 		public override bool SupportsEvaluate {

+ 226 - 9
mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs

@@ -41,8 +41,10 @@ using System.Web.UI.WebControls;
 using System.Web.Util;
 using System.ComponentModel.Design.Serialization;
 #if NET_2_0
+using System.Configuration;
 using System.Collections.Specialized;
 using System.Text.RegularExpressions;
+using System.Web.Configuration;
 #endif
 
 namespace System.Web.Compilation
@@ -416,15 +418,22 @@ namespace System.Web.Compilation
 			return method.Name;
 		}
 
-		void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, MemberInfo member, bool isDataBound)
+		void AddCodeForPropertyOrField (ControlBuilder builder, Type type, string var_name, string att, MemberInfo member, bool isDataBound, bool isExpression)
 		{
 			CodeMemberMethod method = builder.method;
-			if (isDataBound && IsWritablePropertyOrField (member)) {
+			bool isWritable = IsWritablePropertyOrField (member);
+			if (isDataBound && isWritable) {
 				string dbMethodName = DataBoundProperty (builder, type, var_name, att);
 				AddEventAssign (method, "DataBinding", typeof (EventHandler), dbMethodName);
 				return;
 			}
-
+#if NET_2_0
+			else if (isExpression && isWritable) {
+				AddExpressionAssign (method, member, type, var_name, att);
+				return;
+			}
+#endif
+			
 			CodeAssignStatement assign = new CodeAssignStatement ();
 			assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
 			currentLocation = builder.location;
@@ -443,6 +452,14 @@ namespace System.Web.Compilation
 		}
 
 #if NET_2_0
+		bool IsExpression (string value)
+		{
+			if (value == null || value == "")
+				return false;
+			string str = value.Trim ();
+			return (StrUtils.StartsWith (str, "<%$") && StrUtils.EndsWith (str, "%>"));
+		}		
+
 		void RegisterBindingInfo (ControlBuilder builder, string propName, ref string value)
 		{
 			string str = value.Trim ();
@@ -507,12 +524,16 @@ namespace System.Web.Compilation
 		}
 
 		bool ProcessPropertiesAndFields (ControlBuilder builder, MemberInfo member, string id,
-						string attValue, string prefix)
+						 string attValue, string prefix)
 		{
 			int hyphen = id.IndexOf ('-');
 			bool isPropertyInfo = (member is PropertyInfo);
 			bool isDataBound = IsDataBound (attValue);
-
+#if NET_2_0
+			bool isExpression = !isDataBound && IsExpression (attValue);
+#else
+			bool isExpression = false;
+#endif
 			Type type;
 			if (isPropertyInfo) {
 				type = ((PropertyInfo) member).PropertyType;
@@ -522,12 +543,14 @@ namespace System.Web.Compilation
 
 			if (InvariantCompareNoCase (member.Name, id)) {
 #if NET_2_0
-				if (isDataBound) RegisterBindingInfo (builder, member.Name, ref attValue);
+				if (isDataBound)
+					RegisterBindingInfo (builder, member.Name, ref attValue);
+				
 #endif
 				if (!IsWritablePropertyOrField (member))
 					return false;
 
-				AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound);
+				AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound, isExpression);
 				return true;
 			}
 			
@@ -569,12 +592,198 @@ namespace System.Web.Compilation
 			if (isDataBound) RegisterBindingInfo (builder, prefix + member.Name + "." + subprop.Name, ref attValue);
 #endif
 			AddCodeForPropertyOrField (builder, subprop.PropertyType,
-						prefix + member.Name + "." + subprop.Name,
-						val, subprop, isDataBound);
+						   prefix + member.Name + "." + subprop.Name,
+						   val, subprop, isDataBound, isExpression);
 
 			return true;
 		}
 
+#if NET_2_0
+		void AddExpressionAssign (CodeMemberMethod method, MemberInfo member, Type type, string name, string value)
+		{
+			CodeAssignStatement assign = new CodeAssignStatement ();
+			assign.Left = new CodePropertyReferenceExpression (ctrlVar, name);
+
+			// First let's find the correct expression builder
+			string expr = value.Substring (3, value.Length - 5).Trim ();
+			int colon = expr.IndexOf (':');
+			if (colon == -1)
+				return;
+			string prefix = expr.Substring (0, colon).Trim ();
+			
+			System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration ("");
+			if (config == null)
+				return;
+			CompilationSection cs = (CompilationSection)config.GetSection ("system.web/compilation");
+			if (cs == null)
+				return;
+			if (cs.ExpressionBuilders == null || cs.ExpressionBuilders.Count == 0)
+				return;
+
+			System.Web.Configuration.ExpressionBuilder ceb = cs.ExpressionBuilders[prefix];
+			if (ceb == null)
+				return;
+			string builderType = ceb.Type;
+
+			Type t;
+			try {
+				t = System.Type.GetType (builderType, true);
+			} catch (Exception e) {
+				throw new HttpException (
+					String.Format ("Failed to load expression builder type `{0}'", builderType), e);
+			}
+
+			if (!typeof (System.Web.Compilation.ExpressionBuilder).IsAssignableFrom (t))
+				throw new HttpException (
+					String.Format (
+						"Type {0} is not descendant from System.Web.Compilation.ExpressionBuilder",
+						builderType));
+
+			System.Web.Compilation.ExpressionBuilder eb = null;
+			ResourceExpressionFields fields;
+			ExpressionBuilderContext ctx;
+			
+			try {
+				eb = Activator.CreateInstance (t) as System.Web.Compilation.ExpressionBuilder;
+				ctx = new ExpressionBuilderContext (HttpContext.Current.Request.FilePath);
+				fields = eb.ParseExpression (expr.Substring (colon + 1).Trim (),
+							     type,
+							     ctx) as ResourceExpressionFields;
+			} catch (Exception e) {
+				throw new HttpException (
+					String.Format ("Failed to create an instance of type `{0}'", builderType), e);
+			}
+			// FIXME: create and pass an instance of BoundPropertyEntry
+			CodeMethodInvokeExpression convert = new CodeMethodInvokeExpression ();
+			convert.Method = new CodeMethodReferenceExpression (
+				new CodeTypeReferenceExpression (typeof(Convert)),
+				"ToString");
+			convert.Parameters.Add (eb.GetCodeExpression (null, fields, ctx));
+			convert.Parameters.Add (
+				new CodePropertyReferenceExpression (
+					new CodeTypeReferenceExpression (typeof(Globalization.CultureInfo)),
+					"CurrentCulture"));
+			
+			assign.Right = convert;
+			
+			method.Statements.Add (assign);
+		}
+
+		void AssignPropertyFromResources (CodeMemberMethod method, MemberInfo mi, string attvalue, string varname)
+		{
+			string resname = String.Format ("{0}.{1}", attvalue, mi.Name);
+			bool isProperty = mi.MemberType == MemberTypes.Property;
+			bool isField = !isProperty && (mi.MemberType == MemberTypes.Field);
+
+			if (!isProperty && !isField || !IsWritablePropertyOrField (mi))
+				return;
+			
+			Type member_type = null;
+			if (isProperty) {
+				PropertyInfo pi = mi as PropertyInfo;
+				member_type = pi.PropertyType;
+			} else if (isField) { 
+				FieldInfo fi = mi as FieldInfo;
+				member_type = fi.FieldType;
+			} else // should never happen
+				return;
+
+			// __ctrl.Text = System.Convert.ToString(this.GetLocalResourceObject("ButtonResource1.Text"), System.Globalization.CultureInfo.CurrentCulture);
+			object obj = HttpContext.GetLocalResourceObject (HttpContext.Current.Request.FilePath,
+									 resname);
+			if (obj == null)
+				return;
+			
+			CodeAssignStatement assign = new CodeAssignStatement ();
+			assign.Left = new CodePropertyReferenceExpression (ctrlVar, mi.Name);
+			CodeMethodInvokeExpression getlro = new CodeMethodInvokeExpression (
+				new CodeThisReferenceExpression (),
+				"GetLocalResourceObject",
+				new CodeExpression [] { new CodePrimitiveExpression (resname) });
+			
+			CodeMethodInvokeExpression convert = new CodeMethodInvokeExpression ();
+			convert.Method = new CodeMethodReferenceExpression (
+				new CodeTypeReferenceExpression (typeof(System.Convert)),
+				"ToString");
+			convert.Parameters.Add (getlro);
+			convert.Parameters.Add (
+				new CodePropertyReferenceExpression (
+					new CodeTypeReferenceExpression (typeof(Globalization.CultureInfo)),
+					"CurrentCulture"));
+			assign.Right = convert;
+			
+// 			assign.Left = new CodeVariableReferenceExpression (varname);
+// 			assign.Right = new CodeMethodInvokeExpression (
+// 				new CodeThisReferenceExpression (),
+// 				"GetLocalResourceObject",
+// 				new CodeExpression [] { new CodePrimitiveExpression (resname) });
+// 			method.Statements.Add (assign);
+
+// 			// if (localResourceObject != null && localResourceObject.GetType() == typeof(member_type))
+// 			CodeConditionStatement ccs = new CodeConditionStatement ();
+// 			CodeBinaryOperatorExpression exp1 = new CodeBinaryOperatorExpression (
+// 				new CodeVariableReferenceExpression (varname),
+// 				CodeBinaryOperatorType.IdentityInequality,
+// 				new CodePrimitiveExpression (null));
+			
+// 			CodeBinaryOperatorExpression exp2 = new CodeBinaryOperatorExpression (
+// 				new CodeMethodInvokeExpression (
+// 					new CodeVariableReferenceExpression (varname),
+// 					"GetType",
+// 					new CodeExpression [] {}),
+// 				CodeBinaryOperatorType.IdentityEquality,
+// 				new CodeTypeOfExpression (
+// 					new CodeTypeReference (member_type.ToString ())));
+// 			ccs.Condition = new CodeBinaryOperatorExpression (
+// 				exp1,
+// 				CodeBinaryOperatorType.BooleanAnd,
+// 				exp2);
+			
+// 			//   ctrlVar.Property = (member_type)obj;
+// 			assign = new CodeAssignStatement ();
+// 			assign.Left = new CodePropertyReferenceExpression (ctrlVar, mi.Name);
+// 			assign.Right = new CodeCastExpression (
+// 				member_type.ToString (),
+// 				new CodeVariableReferenceExpression (varname));
+// 			ccs.TrueStatements.Add (assign);
+			method.Statements.Add (assign);
+		}
+		
+		void AssignPropertiesFromResources (ControlBuilder builder, string attvalue)
+		{
+			if (attvalue == null || attvalue.Length == 0)
+				return;
+			
+			Type controlType = builder.ControlType;
+			if (controlType == null)
+				return;
+
+			// object obj = null;
+			
+			// Process all public fields and properties of the control. We don't use GetMembers to make the code
+			// faster
+			FieldInfo [] fields = controlType.GetFields (
+				BindingFlags.Instance | BindingFlags.Static |
+				BindingFlags.Public | BindingFlags.FlattenHierarchy);
+			PropertyInfo [] properties = controlType.GetProperties (
+				BindingFlags.Instance | BindingFlags.Static |
+				BindingFlags.Public | BindingFlags.FlattenHierarchy);
+
+			if (fields.Length > 0 || properties.Length > 0) {
+				CodeVariableDeclarationStatement cvds = new CodeVariableDeclarationStatement (
+					typeof (object),
+					"localResourceObject",
+					new CodePrimitiveExpression (null));
+				builder.method.Statements.Add (cvds);
+			}
+			
+			foreach (FieldInfo fi in fields)
+				AssignPropertyFromResources (builder.method, fi, attvalue, "localResourceObject");
+			foreach (PropertyInfo pi in properties)
+				AssignPropertyFromResources (builder.method, pi, attvalue, "localResourceObject");
+		}
+#endif
+		
 		void AddEventAssign (CodeMemberMethod method, string name, Type type, string value)
 		{
 			//"__ctrl.{0} += new {1} (this.{2});"
@@ -611,6 +820,13 @@ namespace System.Web.Compilation
 
 			}
 
+#if NET_2_0
+			if (id.ToLower () == "meta:resourcekey") {
+				AssignPropertiesFromResources (builder, attvalue);
+				return;
+			}
+#endif
+			
 			int hyphen = id.IndexOf ('-');
 			string alt_id = id;
 			if (hyphen != -1)
@@ -628,6 +844,7 @@ namespace System.Web.Compilation
 			string val;
 			CodeMemberMethod method = builder.method;
 			bool databound = IsDataBound (attvalue);
+
 			if (databound) {
 				val = attvalue.Substring (3);
 				val = val.Substring (0, val.Length - 2);

+ 5 - 0
mcs/class/System.Web/System.Web.Configuration_2.0/ChangeLog

@@ -1,3 +1,8 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* WebConfigurationManager.cs: implement support for extra
+	assemblies to be referenced when compiling a page.
+
 2006-09-06 Gonzalo Paniagua Javier <[email protected]>
 
 	* WebConfigurationManager.cs: add null checks. Patch by Marek Habersack

+ 54 - 45
mcs/class/System.Web/System.Web.Configuration_2.0/WebConfigurationManager.cs

@@ -47,52 +47,61 @@ namespace System.Web.Configuration {
 		static IInternalConfigConfigurationFactory configFactory;
 		static Hashtable configurations = new Hashtable ();
 #else
-        static internal IInternalConfigConfigurationFactory configFactory
-        {
-            get{
-                IInternalConfigConfigurationFactory factory = (IInternalConfigConfigurationFactory)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory");
-                if (factory == null){
-                    lock (AppDomain.CurrentDomain){
-                        object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory.initialized");
-                        if (initialized == null){
-                            PropertyInfo prop = typeof(ConfigurationManager).GetProperty("ConfigurationFactory", BindingFlags.Static | BindingFlags.NonPublic);
-                            if (prop != null){
-                                factory = prop.GetValue(null, null) as IInternalConfigConfigurationFactory;
-                                configFactory = factory;
-                            }
-                        }
-                    }
-                }
-                return factory != null ? factory : configFactory;
-            }
-            set{
-                AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory", value);
-                AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory.initialized", true);
-            }
-        }
-
-        static internal Hashtable configurations
-        {
-            get{
-                Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations");
-                if (table == null){
-                    lock (AppDomain.CurrentDomain){
-                        object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations.initialized");
-                        if (initialized == null){
-                            table = new Hashtable();
-                            configurations = table;
-                        }
-                    }
-                }
-                return table != null ? table : configurations;
-
-            }
-            set{
-                AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations", value);
-                AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations.initialized", true);
-            }
-        }
+		static internal IInternalConfigConfigurationFactory configFactory
+		{
+			get{
+				IInternalConfigConfigurationFactory factory = (IInternalConfigConfigurationFactory)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory");
+				if (factory == null){
+					lock (AppDomain.CurrentDomain){
+						object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configFactory.initialized");
+						if (initialized == null){
+							PropertyInfo prop = typeof(ConfigurationManager).GetProperty("ConfigurationFactory", BindingFlags.Static | BindingFlags.NonPublic);
+							if (prop != null){
+								factory = prop.GetValue(null, null) as IInternalConfigConfigurationFactory;
+								configFactory = factory;
+							}
+						}
+					}
+				}
+				return factory != null ? factory : configFactory;
+			}
+			set{
+				AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory", value);
+				AppDomain.CurrentDomain.SetData("WebConfigurationManager.configFactory.initialized", true);
+			}
+		}
+
+		static internal Hashtable configurations
+		{
+			get{
+				Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations");
+				if (table == null){
+					lock (AppDomain.CurrentDomain){
+						object initialized = AppDomain.CurrentDomain.GetData("WebConfigurationManager.configurations.initialized");
+						if (initialized == null){
+							table = new Hashtable();
+							configurations = table;
+						}
+					}
+				}
+				return table != null ? table : configurations;
+
+			}
+			set{
+				AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations", value);
+				AppDomain.CurrentDomain.SetData("WebConfigurationManager.configurations.initialized", true);
+			}
+		}
 #endif
+
+		static internal ArrayList extra_assemblies = null;
+		static internal ArrayList ExtraAssemblies {
+			get {
+				if (extra_assemblies == null)
+					extra_assemblies = new ArrayList();
+				return extra_assemblies;
+			}
+		}
 		
 		static WebConfigurationManager ()
 		{

+ 8 - 0
mcs/class/System.Web/System.Web.UI/ChangeLog

@@ -1,3 +1,11 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* TemplateParser.cs: reference System.Resources when compiling a
+	control.
+
+	* TemplateControl.cs: implement the GetGlobalResourceObject
+	ASP.NET 2.0 APIs.
+
 2006-10-12 Igor Zelmanovich <[email protected]>
 
 	* Page.cs: fixed: for 2.0 only

+ 25 - 0
mcs/class/System.Web/System.Web.UI/TemplateControl.cs

@@ -251,6 +251,31 @@ namespace System.Web.UI {
 			throw new NotSupportedException ();
 		}
 
+#if NET_2_0
+		protected object GetGlobalResourceObject (string className, string resourceKey)
+		{
+			return HttpContext.GetGlobalResourceObject (className, resourceKey);
+		}
+
+		[MonoTODO]
+		protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
+		{
+			// FIXME: not sure how to implement that one yet
+			throw new NotSupportedException();
+		}
+
+		protected object GetLocalResourceObject (string resourceKey)
+		{
+			return HttpContext.GetLocalResourceObject (Context.Request.CurrentExecutionFilePath, resourceKey);
+		}
+		
+		protected object GetLocalResourceObject (string resourceKey, Type objType, string propName)
+		{
+			// FIXME: not sure how to implement that one yet
+			throw new NotSupportedException();
+		}
+#endif
+		
 		[EditorBrowsable (EditorBrowsableState.Never)]
 		public static object ReadStringResource (Type t)
 		{

+ 1 - 0
mcs/class/System.Web/System.Web.UI/TemplateParser.cs

@@ -85,6 +85,7 @@ namespace System.Web.UI {
 			imports.Add ("System.Text.RegularExpressions");
 			imports.Add ("System.Web");
 			imports.Add ("System.Web.Caching");
+			imports.Add ("System.Resources"); // should perhaps be conditional on App_Global/LocalResources existence?
 			imports.Add ("System.Web.Security");
 			imports.Add ("System.Web.SessionState");
 			imports.Add ("System.Web.UI");

+ 3 - 0
mcs/class/System.Web/System.Web.dll.sources

@@ -16,6 +16,8 @@ System.Web/CapabilitiesLoader.cs
 System.Web/BrowserCapabilities.cs
 System.Web.Compilation/AppSettingsExpressionBuilder.cs
 System.Web.Compilation/AspComponentFoundry.cs
+System.Web.Compilation/AppResourcesCompiler.cs
+System.Web.Compilation/AppResourceFilesCompiler.cs
 System.Web.Compilation/AspGenerator.cs
 System.Web.Compilation/AspParser.cs
 System.Web.Compilation/AspTokenizer.cs
@@ -1088,3 +1090,4 @@ System.Web/WebCategoryAttribute.cs
 System.Web/WebROCollection.cs
 System.Web/WebSysDescriptionAttribute.cs
 System.Web/XmlSiteMapProvider.cs
+

+ 10 - 0
mcs/class/System.Web/System.Web/ChangeLog

@@ -1,3 +1,13 @@
+2006-10-18  Marek Habersack  <[email protected]>
+
+	* HttpRuntime.cs: add support for compilation of local resources
+	at the start of request.
+
+	* HttpContext.cs: implement the GetGlobalResourceObject APIs
+
+	* HttpApplicationFactory.cs: include the bootstrap code for the
+	global/local resources compiler.
+
 2006-10-09  Marek Habersack  <[email protected]>
 
 	* HttpApplication.cs: change the pipeline order for ASP.NET 2.0 to

+ 16 - 1
mcs/class/System.Web/System.Web/HttpApplicationFactory.cs

@@ -40,6 +40,10 @@ using System.Web.Compilation;
 using vmw.common;
 #endif
 
+#if NET_2_0 && !TARGET_J2EE
+using System.CodeDom.Compiler;
+#endif
+
 namespace System.Web {
 	class HttpApplicationFactory {
 		// Initialized in InitType
@@ -379,7 +383,18 @@ namespace System.Web {
 #else
 				WebConfigurationSettings.Init (context);
 #endif
-				
+		
+#if NET_2_0 && !TARGET_J2EE
+				AppGlobalResourcesCompiler agrc = new AppGlobalResourcesCompiler();
+				CompilerResults cr = agrc.Compile();
+				if (cr != null && cr.CompiledAssembly != null)
+					WebConfigurationManager.ExtraAssemblies.Add(cr.PathToAssembly);
+				AppLocalResourcesCompiler alrc  = new AppLocalResourcesCompiler ();
+				cr = alrc.Compile ();
+				if (cr != null && cr.CompiledAssembly != null)
+					WebConfigurationManager.ExtraAssemblies.Add (cr.PathToAssembly);
+#endif
+
 				if (File.Exists (app_file)) {
 #if TARGET_J2EE
 					app_type = System.Web.J2EE.PageMapper.GetObjectType(app_file);

+ 57 - 4
mcs/class/System.Web/System.Web/HttpContext.cs

@@ -42,6 +42,8 @@ using System.Web.SessionState;
 using System.Web.UI;
 using System.Web.Util;
 #if NET_2_0
+using System.Reflection;
+using System.Resources;
 using System.Web.Profile;
 using CustomErrorMode = System.Web.Configuration.CustomErrorsMode;
 #endif
@@ -340,16 +342,67 @@ namespace System.Web {
 		}
 
 #if NET_2_0
-		[MonoTODO]
+		internal static Type GetGLResourceType (string typeName)
+		{
+			Type type = null;
+			Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
+
+			foreach (Assembly ass in assemblies) {
+				type = ass.GetType (typeName);
+				if (type == null)
+					continue;
+
+				return type;
+			}
+
+			throw new MissingManifestResourceException (String.Format ("Missing resource class {0}", typeName));
+		}
+
+		internal static object GetGLResourceObject (Type type, string resourceKey)
+		{
+			object ret = null;
+			try {
+				PropertyInfo pi = type.GetProperty (resourceKey,
+								    BindingFlags.GetProperty |
+								    BindingFlags.Public |
+								    BindingFlags.Static);
+				if (pi == null)
+					return null;
+				ret = pi.GetValue (null, null);
+			} catch {
+			}
+			
+			return ret;
+		}
+
+		internal static void SetGLResourceObjectCulture (Type type, CultureInfo ci)
+		{
+			try {
+				PropertyInfo pi = type.GetProperty ("Culture",
+								    BindingFlags.SetProperty |
+								    BindingFlags.Public |
+								    BindingFlags.Static);
+				if (pi == null)
+					return; // internal error actually...
+				pi.SetValue (null, ci, null);
+			} catch {
+			}
+		}
+		
 		public static object GetGlobalResourceObject (string classKey, string resourceKey)
 		{
-			throw new NotImplementedException ();
+			string className = String.Format ("System.Resources.{0}", classKey);
+			Type type = GetGLResourceType (className);
+			SetGLResourceObjectCulture (type, null);
+			return GetGLResourceObject (type, resourceKey);
 		}
 
-		[MonoTODO]
 		public static object GetGlobalResourceObject (string classKey, string resourceKey, CultureInfo culture)
 		{
-			throw new NotImplementedException ();
+			string className = String.Format ("System.Resources.{0}", classKey);
+			Type type = GetGLResourceType (className);
+			SetGLResourceObjectCulture (type, culture);
+			return GetGLResourceObject (type, resourceKey);
 		}
 
 		[MonoTODO]

+ 14 - 0
mcs/class/System.Web/System.Web/HttpRuntime.cs

@@ -41,6 +41,11 @@ using System.Web.Configuration;
 using System.Web.UI;
 using System.Threading;
 
+#if NET_2_0
+using System.CodeDom.Compiler;
+using System.Web.Compilation;
+#endif
+
 namespace System.Web {
 	
 	// CAS - no InheritanceDemand here as the class is sealed
@@ -255,6 +260,15 @@ namespace System.Web {
 			} else {
 				context.ApplicationInstance = app;
 			
+#if NET_2_0
+				//
+				// Compile the local resources, if any
+				//
+				AppLocalResourcesCompiler alrc = new AppLocalResourcesCompiler();
+				CompilerResults cr = alrc.Compile();
+				if (cr != null && cr.CompiledAssembly != null)
+					WebConfigurationManager.ExtraAssemblies.Add(cr.PathToAssembly);
+#endif			
 				//
 				// Ask application to service the request
 				//