/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / fx / src / xsp / System / Web / HttpApplicationFactory.cs / 4 / HttpApplicationFactory.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
* The HttpApplicationFactory class
*
* Copyright (c) 1999 Microsoft Corporation
*/
namespace System.Web {
using System.Text;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Caching;
using System.Web.Util;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.Compilation;
using System.Web.SessionState;
using System.Collections;
using System.Reflection;
using System.IO;
using System.Globalization;
using System.Web.Management;
/*
* Application Factory only has and public static methods to get / recycle
* application instances. The information cached per application
* config file is encapsulated by ApplicationData class.
* Only one static instance of application factory is created.
*/
internal class HttpApplicationFactory {
internal const string applicationFileName = "global.asax";
// the only instance of application factory
private static HttpApplicationFactory _theApplicationFactory = new HttpApplicationFactory();
// flag to indicate that initialization was done
private bool _inited;
// filename for the global.asax
private String _appFilename;
private ICollection _fileDependencies;
// call application on_start only once
private bool _appOnStartCalled = false;
// call application on_end only once
private bool _appOnEndCalled = false;
// dictionary of application state
private HttpApplicationState _state;
// class of the application object
private Type _theApplicationType;
// free list of app objects
private Stack _freeList = new Stack();
private int _numFreeAppInstances = 0;
private const int _maxFreeAppInstances = 100;
private int _minFreeAppInstances = 0;
// free list of special (context-less) app objects
// to be used for global events (App_OnEnd, Session_OnEnd, etc.)
private Stack _specialFreeList = new Stack();
private int _numFreeSpecialAppInstances = 0;
private const int _maxFreeSpecialAppInstances = 20;
// results of the reflection on the app class
private MethodInfo _onStartMethod; // Application_OnStart
private int _onStartParamCount;
private MethodInfo _onEndMethod; // Application_OnEnd
private int _onEndParamCount;
private MethodInfo _sessionOnEndMethod; // Session_OnEnd
private int _sessionOnEndParamCount;
private EventHandler _sessionOnEndEventHandlerAspCompatHelper; // helper for AspCompat
// list of methods suspected as event handlers
private MethodInfo[] _eventHandlerMethods;
internal HttpApplicationFactory() {
_sessionOnEndEventHandlerAspCompatHelper = new EventHandler(this.SessionOnEndEventHandlerAspCompatHelper);
}
//
// Initialization on first request
//
private void Init() {
if (_customApplication != null)
return;
try {
try {
_appFilename = GetApplicationFile();
CompileApplication();
}
finally {
// Always set up global.asax file change notification, even if compilation
// failed. This way, if the problem is fixed, the appdomain will be restarted.
SetupChangesMonitor();
}
}
catch { // Protect against exception filters
throw;
}
}
internal static void SetupFileChangeNotifications() {
// Just call EnsureInited() to make sure global.asax FCN are set up.
// But don't if we never even got to initialize Fusion
if (HttpRuntime.CodegenDirInternal != null)
_theApplicationFactory.EnsureInited();
}
private void EnsureInited() {
if (!_inited) {
lock (this) {
if (!_inited) {
Init();
_inited = true;
}
}
}
}
internal static void EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) {
if (!_theApplicationFactory._appOnStartCalled) {
Exception error = null;
lock (_theApplicationFactory) {
if (!_theApplicationFactory._appOnStartCalled) {
using (new HttpContextWrapper(context)) {
// impersonation could be required (UNC share or app credentials)
WebBaseEvent.RaiseSystemEvent(_theApplicationFactory, WebEventCodes.ApplicationStart);
if (_theApplicationFactory._onStartMethod != null) {
app.ProcessSpecialRequest(context,
_theApplicationFactory._onStartMethod,
_theApplicationFactory._onStartParamCount,
_theApplicationFactory,
EventArgs.Empty,
null);
}
}
}
_theApplicationFactory._appOnStartCalled = true;
error = context.Error;
}
if (error != null) {
throw new HttpException(error.Message, error);
}
}
}
private void EnsureAppStartCalled(HttpContext context) {
if (!_appOnStartCalled) {
lock (this) {
if (!_appOnStartCalled) {
using (new HttpContextWrapper(context)) {
// impersonation could be required (UNC share or app credentials)
WebBaseEvent.RaiseSystemEvent(this, WebEventCodes.ApplicationStart);
// fire outside of impersonation as HttpApplication logic takes
// care of impersonation by itself
FireApplicationOnStart(context);
}
_appOnStartCalled = true;
}
}
}
}
internal static String GetApplicationFile() {
return Path.Combine(HttpRuntime.AppDomainAppPathInternal, applicationFileName);
}
private void CompileApplication() {
// Get the Application Type and AppState from the global file
_theApplicationType = BuildManager.GetGlobalAsaxType();
BuildResultCompiledGlobalAsaxType result = BuildManager.GetGlobalAsaxBuildResult();
if (result != null) {
// Even if global.asax was already compiled, we need to get the collections
// of application and session objects, since they are not persisted when
// global.asax is compiled. Ideally, they would be, but since