// 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.CodeDom;
using System.CodeDom.Compiler;
namespace System.Web.Compilation
{
+ class AssemblyPathResolver
+ {
+ static Dictionary <string, string> assemblyCache;
+
+ static AssemblyPathResolver ()
+ {
+ assemblyCache = new Dictionary <string, string> ();
+ }
+
+ public static string GetAssemblyPath (string assemblyName)
+ {
+ lock (assemblyCache) {
+ if (assemblyCache.ContainsKey (assemblyName))
+ return assemblyCache [assemblyName];
+
+ Assembly asm = null;
+ Exception error = null;
+ if (assemblyName.IndexOf (',') != -1) {
+ try {
+ asm = Assembly.Load (assemblyName);
+ } catch (Exception e) {
+ error = e;
+ }
+ }
+
+ if (asm == null) {
+ try {
+ asm = Assembly.LoadWithPartialName (assemblyName);
+ } catch (Exception e) {
+ error = e;
+ }
+ }
+
+ if (asm == null)
+ throw new HttpException (String.Format ("Unable to find assembly {0}", assemblyName), error);
+
+ assemblyCache.Add (assemblyName, asm.Location);
+ return asm.Location;
+ }
+ }
+ }
+
internal class AppCodeAssembly
{
- private List<string> files;
- private List<CodeCompileUnit> units;
+ List<string> files;
+ List<CodeCompileUnit> units;
- private string name;
- private string path;
- private bool validAssembly;
- private string outputAssemblyName;
+ string name;
+ string path;
+ bool validAssembly;
+ string outputAssemblyName;
public string OutputAssemblyName
{
// First make sure all the files are in the same
// language
- bool known;
+ bool known = false;
foreach (string f in files) {
known = true;
language = null;
extension = Path.GetExtension (f);
- if (!CodeDomProvider.IsDefinedExtension (extension))
+ if (String.IsNullOrEmpty (extension) || !CodeDomProvider.IsDefinedExtension (extension))
known = false;
if (known) {
language = CodeDomProvider.GetLanguageFromExtension(extension);
}
CodeDomProvider provider = null;
- CompilationSection compilationSection = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
+ CompilationSection compilationSection = WebConfigurationManager.GetWebApplicationSection ("system.web/compilation") as CompilationSection;
if (compilerInfo == null) {
if (!CodeDomProvider.IsDefinedLanguage (compilationSection.DefaultLanguage))
throw new HttpException ("Failed to retrieve default source language");
compilerInfo = CodeDomProvider.GetCompilerInfo (compilationSection.DefaultLanguage);
if (compilerInfo == null || !compilerInfo.IsCodeDomProviderTypeValid)
throw new HttpException ("Internal error while initializing application");
- provider = compilerInfo.CreateProvider ();
- if (provider == null)
- throw new HttpException ("A code provider error occurred while initializing application.");
}
provider = compilerInfo.CreateProvider ();
parameters.ReferencedAssemblies.AddRange (binAssemblies);
if (compilationSection != null) {
- AssemblyName asmName;
foreach (AssemblyInfo ai in compilationSection.Assemblies)
if (ai.Assembly != "*") {
try {
- asmName = new AssemblyName (ai.Assembly);
- parameters.ReferencedAssemblies.Add (asmName.Name);
+ parameters.ReferencedAssemblies.Add (
+ AssemblyPathResolver.GetAssemblyPath (ai.Assembly));
} catch (Exception ex) {
throw new HttpException (
String.Format ("Could not find assembly {0}.", ai.Assembly),
bprovider.GenerateCode (abuilder);
}
}
+
+ if (knownfiles.Count == 0 && unknownfiles.Count == 0 && units.Count == 0)
+ return;
outputAssemblyName = (string)FileUtils.CreateTemporaryFile (
AppDomain.CurrentDomain.SetupInformation.DynamicBase,
foreach (Assembly a in BuildManager.TopLevelAssemblies)
parameters.ReferencedAssemblies.Add (a.Location);
CompilerResults results = abuilder.BuildAssembly (parameters);
- if (results.Errors.Count == 0) {
+ if (results == null)
+ return;
+
+ if (results.NativeCompilerReturnValue == 0) {
BuildManager.CodeAssemblies.Add (results.CompiledAssembly);
BuildManager.TopLevelAssemblies.Add (results.CompiledAssembly);
HttpRuntime.WritePreservationFile (results.CompiledAssembly, name);
throw new CompilationException (null, results.Errors, null);
}
}
-
- private string PhysicalToVirtual (string file)
+
+ VirtualPath PhysicalToVirtual (string file)
{
- return file.Replace (HttpRuntime.AppDomainAppPath, "/").Replace (Path.DirectorySeparatorChar, '/');
+ return new VirtualPath (file.Replace (HttpRuntime.AppDomainAppPath, "/").Replace (Path.DirectorySeparatorChar, '/'));
}
- private BuildProvider GetBuildProviderFor (string file, BuildProviderCollection buildProviders)
+ BuildProvider GetBuildProviderFor (string file, BuildProviderCollection buildProviders)
{
if (file == null || file.Length == 0 || buildProviders == null || buildProviders.Count == 0)
return null;
- BuildProvider ret = buildProviders.GetProviderForExtension (Path.GetExtension (file));
+ BuildProvider ret = buildProviders.GetProviderInstanceForExtension (Path.GetExtension (file));
if (ret != null && IsCorrectBuilderType (ret)) {
ret.SetVirtualPath (PhysicalToVirtual (file));
return ret;
return null;
}
- private bool IsCorrectBuilderType (BuildProvider bp)
+ bool IsCorrectBuilderType (BuildProvider bp)
{
if (bp == null)
return false;
internal class AppCodeCompiler
{
- static private bool _alreadyCompiled;
+ static bool _alreadyCompiled;
internal static string DefaultAppCodeAssemblyName;
// A dictionary that contains an entry per an assembly that will
// Files for which exist BuildProviders but which have no
// unambiguous language assigned to them (e.g. .wsdl files), are
// built using the default website compiler.
- private List<AppCodeAssembly> assemblies;
- string _bindir = null;
+ List<AppCodeAssembly> assemblies;
string providerTypeName = null;
public AppCodeCompiler ()
bool ProcessAppCodeDir (string appCode, AppCodeAssembly defasm)
{
// First process the codeSubDirectories
- CompilationSection cs = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
+ CompilationSection cs = (CompilationSection) WebConfigurationManager.GetWebApplicationSection ("system.web/compilation");
if (cs != null) {
string aname;
for (int i = 0; i < cs.CodeSubDirectories.Count; i++) {
- aname = String.Format ("App_SubCode_{0}", cs.CodeSubDirectories[i].DirectoryName);
+ aname = String.Concat ("App_SubCode_", cs.CodeSubDirectories[i].DirectoryName);
assemblies.Add (new AppCodeAssembly (
aname,
Path.Combine (appCode, cs.CodeSubDirectories[i].DirectoryName)));
return new CodeTypeReference (type);
}
- Type GetTypeFromBin (string typeName)
- {
- string bindir = BinDir;
- if (!Directory.Exists (bindir))
- return null;
-
- string [] binDlls = Directory.GetFiles (bindir, "*.dll");
- Type ret = null;
- foreach (string dll in binDlls) {
- try {
- Assembly asm = Assembly.LoadFrom (dll);
- ret = asm.GetType (typeName, false);
- if (ret != null)
- break;
- } catch (Exception) {
- continue;
- }
- }
-
- return ret;
- }
-
string FindProviderTypeName (ProfileSection ps, string providerName)
{
if (ps.Providers == null || ps.Providers.Count == 0)
void GetProfileSettingsSerializeAsAttribute (ProfileSection ps, CodeAttributeDeclarationCollection collection,
SerializationMode mode)
{
- string parameter = String.Format ("SettingsSerializeAs.{0}", mode.ToString ());
+ string parameter = String.Concat ("SettingsSerializeAs.", mode.ToString ());
collection.Add (
new CodeAttributeDeclaration (
"SettingsSerializeAs",
string MakeGroupName (string name)
{
- return String.Format ("ProfileGroup{0}", name);
+ return String.Concat ("ProfileGroup", name);
}
// FIXME: there should be some validation of syntactic correctness of the member/class name
ns.Imports.Add (new CodeNamespaceImport ("System.Web.Profile"));
RootProfilePropertySettingsCollection props = ps.PropertySettings;
- if (props == null || props.Count == 0)
+ if (props == null)
return true;
SortedList<string, string> groupProperties = new SortedList<string, string> ();
}
string baseType = ps.Inherits;
- bool baseIsGlobal = false;
- if (String.IsNullOrEmpty (baseType)) {
+ if (String.IsNullOrEmpty (baseType))
baseType = "System.Web.Profile.ProfileBase";
- baseIsGlobal = true;
+ else {
+ string[] parts = baseType.Split (new char[] {','});
+ if (parts.Length > 1)
+ baseType = parts [0].Trim ();
}
+ bool baseIsGlobal;
+ if (baseType.IndexOf ('.') != -1)
+ baseIsGlobal = true;
+ else
+ baseIsGlobal = false;
+
BuildProfileClass (ps, "ProfileCommon", props, ns, baseType, baseIsGlobal, groupProperties);
return true;
}
// if (pb != null)
// context.Profile = pb;
// }
+
+ public static bool HaveCustomProfile (ProfileSection ps)
+ {
+ if (ps == null || !ps.Enabled)
+ return false;
+
+ RootProfilePropertySettingsCollection props = ps.PropertySettings;
+ ProfileGroupSettingsCollection groups = props != null ? props.GroupSettings : null;
+
+ if (!String.IsNullOrEmpty (ps.Inherits) || (props != null && props.Count > 0) || (groups != null && groups.Count > 0))
+ return true;
+
+ return false;
+ }
public void Compile ()
{
if (_alreadyCompiled)
return;
- _alreadyCompiled = false;
string appCode = Path.Combine (HttpRuntime.AppDomainAppPath, "App_Code");
- ProfileSection ps = WebConfigurationManager.GetSection ("system.web/profile") as ProfileSection;
+ ProfileSection ps = WebConfigurationManager.GetWebApplicationSection ("system.web/profile") as ProfileSection;
bool haveAppCodeDir = Directory.Exists (appCode);
- bool haveCustomProfile = ps != null ? ps.PropertySettings.Count > 0 : false;
+ bool haveCustomProfile = HaveCustomProfile (ps);
if (!haveAppCodeDir && !haveCustomProfile)
return;
if (!haveCode)
return;
-
+
HttpRuntime.EnableAssemblyMapping (true);
- string bindir = BinDir;
- string[] binAssemblies = null;
- if (Directory.Exists (bindir))
- binAssemblies = Directory.GetFiles (bindir, "*.dll");
+ string[] binAssemblies = HttpApplication.BinDirectoryAssemblies;
+
foreach (AppCodeAssembly aca in assemblies)
aca.Build (binAssemblies);
+ _alreadyCompiled = true;
DefaultAppCodeAssemblyName = Path.GetFileNameWithoutExtension (defasm.OutputAssemblyName);
+
+ RunAppInitialize ();
if (haveCustomProfile && providerTypeName != null) {
if (Type.GetType (providerTypeName, false) == null) {
} else
return;
- if (GetTypeFromBin (providerTypeName) == null)
- throw new HttpException (String.Format ("Profile provider type not found: {0}",
- providerTypeName));
+ Exception noTypeException = null;
+ Type ptype = null;
+
+ try {
+ ptype = HttpApplication.LoadTypeFromBin (providerTypeName);
+ } catch (Exception ex) {
+ noTypeException = ex;
+ }
+
+ if (ptype == null)
+ throw new HttpException (String.Format ("Profile provider type not found: {0}", providerTypeName), noTypeException);
}
}
- private bool CollectFiles (string dir, AppCodeAssembly aca)
+ // Documented (sort of...) briefly in:
+ //
+ // http://quickstarts.asp.net/QuickStartv20/aspnet/doc/extensibility.aspx
+ // http://msdn2.microsoft.com/en-us/library/system.web.hosting.virtualpathprovider.aspx
+ void RunAppInitialize ()
+ {
+ MethodInfo mi = null, tmi;
+ Type[] types;
+
+ foreach (Assembly asm in BuildManager.CodeAssemblies) {
+ types = asm.GetExportedTypes ();
+ if (types == null || types.Length == 0)
+ continue;
+
+ foreach (Type type in types) {
+ tmi = type.GetMethod ("AppInitialize",
+ BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase,
+ null,
+ Type.EmptyTypes,
+ null);
+ if (tmi == null)
+ continue;
+
+ if (mi != null)
+ throw new HttpException ("The static AppInitialize method found in more than one type in the App_Code directory.");
+
+ mi = tmi;
+ }
+ }
+
+ if (mi == null)
+ return;
+
+ mi.Invoke (null, null);
+ }
+
+ bool CollectFiles (string dir, AppCodeAssembly aca)
{
bool haveFiles = false;
}
return haveFiles;
}
-
- private string BinDir {
- get {
- if (_bindir != null)
- return _bindir;
- AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
- _bindir = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath);
- return _bindir;
- }
- }
}
}
-#endif
+