Bläddra i källkod

2006-02-22 Gonzalo Paniagua Javier <[email protected]>

	* BareApplicationHost.cs: class used as an entry point into each
	application domiain from the ApplicationManager.
	* ApplicationManager.cs: implemented most of the remaining methods.
	* HostingEnvironment.cs: object handling methods are now implemented.


svn path=/trunk/mcs/; revision=57178
Gonzalo Paniagua Javier 20 år sedan
förälder
incheckning
fec2447c21

+ 108 - 10
mcs/class/System.Web/System.Web.Hosting/ApplicationManager.cs

@@ -28,15 +28,22 @@
 //
 #if NET_2_0
 using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Permissions;
+using System.Security.Policy;
 using System.Threading;
 
 namespace System.Web.Hosting {
+	[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
 	public sealed class ApplicationManager : MarshalByRefObject {
 		static ApplicationManager instance = new ApplicationManager ();
 		int users;
+		Dictionary <string, BareApplicationHost> id_to_host;
 
 		private ApplicationManager ()
 		{
+			id_to_host = new Dictionary<string, BareApplicationHost> ();
 		}
 
 		public void Close ()
@@ -51,11 +58,74 @@ namespace System.Web.Hosting {
 			return CreateObject (appId, type, virtualPath, physicalPath, failIfExists, true);
 		}
 
-		[MonoTODO]
 		public IRegisteredObject CreateObject (string appId, Type type, string virtualPath,
 							string physicalPath, bool failIfExists, bool throwOnError)
 		{
-			throw new NotImplementedException ();
+			if (appId == null)
+				throw new ArgumentNullException ("appId");
+
+			if (!VirtualPathUtility.IsAbsolute (virtualPath))
+				throw new ArgumentException ("Relative path no allowed.", "virtualPath");
+
+			if (physicalPath == null || physicalPath == "")
+				throw new ArgumentException ("Cannot be null or empty", "physicalPath");
+
+			// 'type' is not checked. If it's null, we'll throw a NullReferenceException
+			if (!typeof (IRegisteredObject).IsAssignableFrom (type)) {
+				string msg = String.Format ("Type '{0}' does not implement IRegisteredObject.", type.Name);
+				throw new ArgumentException (msg, "type");
+			}
+
+			//
+			// ArgumentException is thrown for the physical path from the internal object created
+			// in the new application domain.
+			BareApplicationHost host = null;
+			if (id_to_host.ContainsKey (appId))
+				host = id_to_host [appId];
+
+			IRegisteredObject ireg = null;
+			if (host != null) {
+				ireg = CheckIfExists (host, type, failIfExists);
+				if (ireg != null)
+					return ireg;
+			}
+
+			try {
+				if (host == null)
+					host = CreateHost (appId, virtualPath, physicalPath);
+				ireg = host.CreateInstance (type);
+			} catch (Exception e) {
+				if (throwOnError)
+					throw;
+			}
+
+			if (ireg != null && host.GetObject (type) == null) // If not registered from ctor...
+				host.RegisterObject (ireg, true);
+
+			return ireg;
+		}
+
+		BareApplicationHost CreateHost (string appId, string vpath, string ppath)
+		{
+			BareApplicationHost host;
+			host = (BareApplicationHost) ApplicationHost.CreateApplicationHost (typeof (BareApplicationHost), vpath, ppath);
+			id_to_host [appId] = host;
+			return host;
+		}
+
+		IRegisteredObject CheckIfExists (BareApplicationHost host, Type type, bool failIfExists)
+		{
+			IRegisteredObject ireg = host.GetObject (type);
+			if (ireg == null)
+				return null;
+
+			if (failIfExists) {
+				string msg = String.Format ("Well known object of type '{0}' already " +
+						"exists in this domain.", type.Name);
+				throw new InvalidOperationException (msg);
+			}
+
+			return ireg;
 		}
 
 		public static ApplicationManager GetApplicationManager ()
@@ -63,16 +133,35 @@ namespace System.Web.Hosting {
 			return instance;
 		}
 
-		[MonoTODO]
 		public IRegisteredObject GetObject (string appId, Type type)
 		{
-			throw new NotImplementedException ();
+			if (appId == null)
+				throw new ArgumentNullException ("appId");
+
+			if (type == null)
+				throw new ArgumentNullException ("type");
+
+			BareApplicationHost host = null;
+			if (!id_to_host.ContainsKey (appId))
+				return null;
+
+			host = id_to_host [appId];
+			return host.GetObject (type);
 		}
 
-		[MonoTODO]
 		public ApplicationInfo [] GetRunningApplications ()
 		{
-			throw new NotImplementedException ();
+			ICollection<string> coll = id_to_host.Keys;
+			string [] keys = new string [coll.Count];
+			coll.CopyTo (keys, 0);
+			ApplicationInfo [] result = new ApplicationInfo [coll.Count];
+			int i = 0;
+			foreach (string str in keys) {
+				BareApplicationHost host = id_to_host [str];
+				result [i++] = new ApplicationInfo (str, host.PhysicalPath, host.VirtualPath);
+			}
+
+			return result;
 		}
 
 		public override object InitializeLifetimeService ()
@@ -96,16 +185,18 @@ namespace System.Web.Hosting {
 			// == HostingEnvironment.InitiateShutdown in all appdomains managed by this instance
 		}
 
-		[MonoTODO]
 		public void ShutdownApplication (string appId)
 		{
 			if (appId == null)
 				throw new ArgumentNullException ("appId");
 
-			throw new NotImplementedException ();
+			BareApplicationHost host = id_to_host [appId];
+			if (host == null)
+				return;
+
+			host.Shutdown ();
 		}
 
-		[MonoTODO]
 		public void StopObject (string appId, Type type)
 		{
 			if (appId == null)
@@ -114,7 +205,14 @@ namespace System.Web.Hosting {
 			if (type == null)
 				throw new ArgumentNullException ("type");
 
-			throw new NotImplementedException ();
+			if (!id_to_host.ContainsKey (appId))
+				return;
+
+			BareApplicationHost host = id_to_host [appId];
+			if (host == null)
+				return;
+
+			host.StopObject (type);
 		}
 	}
 }

+ 127 - 0
mcs/class/System.Web/System.Web.Hosting/BareApplicationHost.cs

@@ -0,0 +1,127 @@
+//
+// System.Web.Hosting.BareApplicationHost
+// 
+// Author:
+//	Gonzalo Paniagua Javier ([email protected])
+//
+//
+// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace System.Web.Hosting {
+	class RegisteredItem {
+		public IRegisteredObject Item;
+		public bool AutoClean;
+		public RegisteredItem (IRegisteredObject item, bool autoclean)
+		{
+			this.Item = item;
+			this.AutoClean = autoclean;
+		}
+	}
+
+	sealed class BareApplicationHost : MarshalByRefObject {
+		string vpath;
+		string phys_path;
+		Dictionary<Type, RegisteredItem> hash;
+
+		public BareApplicationHost (string vpath, string phys_path)
+		{
+			this.vpath = vpath;
+			if (!Path.IsPathRooted (phys_path)) {
+				string msg = String.Format ("Invalid physical path: '{0}'", phys_path);
+				throw new ArgumentException (msg, "phys_path");
+			}
+			this.phys_path = phys_path;
+			hash = new Dictionary<Type, RegisteredItem> ();
+			HostingEnvironment.Host = this;
+			AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
+		}
+
+		public string VirtualPath {
+			get { return vpath; }
+		}
+
+		public string PhysicalPath {
+			get { return phys_path; }
+		}
+
+		public void Shutdown ()
+		{
+			HostingEnvironment.InitiateShutdown ();
+		}
+
+		public void StopObject (Type type)
+		{
+			if (!hash.ContainsKey (type))
+				return;
+
+			RegisteredItem reg = hash [type];
+			reg.Item.Stop (false);
+		}
+
+		public IRegisteredObject CreateInstance (Type type)
+		{
+			return (IRegisteredObject) Activator.CreateInstance (type, null);
+		}
+
+		public void RegisterObject (IRegisteredObject obj, bool auto_clean)
+		{
+			hash [obj.GetType ()] = new RegisteredItem (obj, auto_clean);
+		}
+
+		public bool UnregisterObject (IRegisteredObject obj)
+		{
+			return hash.Remove (obj.GetType ());
+		}
+
+		public IRegisteredObject GetObject (Type type)
+		{
+			if (hash.ContainsKey (type))
+				return hash [type].Item;
+
+			return null;
+		}
+
+		void OnDomainUnload (object sender, EventArgs args)
+		{
+			ICollection<RegisteredItem> values = hash.Values;
+			RegisteredItem [] objects = new RegisteredItem [hash.Count];
+			values.CopyTo (objects, 0);
+
+			foreach (RegisteredItem reg in objects) {
+				try {
+					reg.Item.Stop (true); // Stop should call Unregister. It's ok if not.
+				} catch {
+					// Ignore or throw?
+				}
+			}
+			hash.Clear ();
+		}
+	}
+}
+
+#endif
+

+ 7 - 0
mcs/class/System.Web/System.Web.Hosting/ChangeLog

@@ -1,3 +1,10 @@
+2006-02-22 Gonzalo Paniagua Javier <[email protected]>
+
+	* BareApplicationHost.cs: class used as an entry point into each
+	application domiain from the ApplicationManager.
+	* ApplicationManager.cs: implemented most of the remaining methods.
+	* HostingEnvironment.cs: object handling methods are now implemented.
+
 2006-02-10 Gonzalo Paniagua Javier <[email protected]>
 
 	* DefaultVirtualPathProvider.cs: add some comments/TODO.

+ 15 - 9
mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs

@@ -33,6 +33,7 @@
 
 using System;
 using System.Security.Permissions;
+using System.Threading;
 using System.Web.Caching;
 using System.Web.Util;
 
@@ -45,11 +46,16 @@ namespace System.Web.Hosting {
 		static bool is_hosted;
 		static string site_name;
 		static ApplicationShutdownReason shutdown_reason;
+		internal static BareApplicationHost Host;
 		static VirtualPathProvider vpath_provider = (HttpRuntime.AppDomainAppVirtualPath == null) ? null :
 								new DefaultVirtualPathProvider ();
+		static int busy_count;
 
 		public HostingEnvironment ()
 		{
+			// The documentation says that this is called once per domain by the ApplicationManager and
+			// then it throws InvalidOperationException whenever called.
+			throw new InvalidOperationException ();
 		}
 
 		public static string ApplicationID {
@@ -92,7 +98,7 @@ namespace System.Web.Hosting {
 		[MonoTODO]
 		public static void DecrementBusyCount ()
 		{
-			throw new NotImplementedException ();
+			Interlocked.Decrement (ref busy_count);
 		}
 
 		[MonoTODO]
@@ -113,10 +119,9 @@ namespace System.Web.Hosting {
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public static void IncrementBusyCount ()
 		{
-			throw new NotImplementedException ();
+			Interlocked.Increment (ref busy_count);
 		}
 
 		public override object InitializeLifetimeService ()
@@ -124,10 +129,9 @@ namespace System.Web.Hosting {
 			return null;
 		}
 
-		[MonoTODO]
 		public static void InitiateShutdown ()
 		{
-			throw new NotImplementedException ();
+			HttpRuntime.UnloadAppDomain ();
 		}
 
 		public static string MapPath (string virtualPath)
@@ -147,10 +151,11 @@ namespace System.Web.Hosting {
 			return context.Request.MapPath (virtualPath);
 		}
 
-		[MonoTODO]
 		public static void RegisterObject (IRegisteredObject obj)
 		{
-			throw new NotImplementedException ();
+			if (obj == null)
+				throw new ArgumentNullException ("obj");
+			Host.RegisterObject (obj, false);
 		}
 
 		public static void RegisterVirtualPathProvider (VirtualPathProvider virtualPathProvider)
@@ -177,10 +182,11 @@ namespace System.Web.Hosting {
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public static void UnregisterObject (IRegisteredObject obj)
 		{
-			throw new NotImplementedException ();
+			if (obj == null)
+				throw new ArgumentNullException ("obj");
+			Host.UnregisterObject (obj);
 		}
 	}
 }

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

@@ -229,6 +229,7 @@ System.Web.Hosting/AppManagerAppDomainFactory.cs
 System.Web.Hosting/ApplicationInfo.cs
 System.Web.Hosting/ApplicationHost.cs
 System.Web.Hosting/ApplicationManager.cs
+System.Web.Hosting/BareApplicationHost.cs
 System.Web.Hosting/DefaultVirtualDirectory.cs
 System.Web.Hosting/DefaultVirtualFile.cs
 System.Web.Hosting/DefaultVirtualPathProvider.cs