using System.Collections.Specialized;
using System.Threading;
using vmw.common;
+using System.Reflection;
namespace System.Web.J2EE
{
/// </summary>
public class PageMapper
{
- private static readonly string _fileListName = "/filelist.xml";
+ //private static readonly string _fileListName = "/filelist.xml";
private static readonly object LOCK_GETASSEMBLIESCACHEDDOCUMENT = new object();
- private static readonly object LOCK_GETFROMMAPPATHCACHE = new object();
+ //private static readonly object LOCK_GETFROMMAPPATHCACHE = new object();
+
+
+ static Assembly CurrentDomain_AssemblyResolve (object sender, ResolveEventArgs args)
+ {
+ Assembly resolvedAssembly = null;
+ try
+ {
+ resolvedAssembly = GetCachedAssembly (HttpContext.Current, args.Name);
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ Console.WriteLine (ex.ToString ());
+#endif
+ resolvedAssembly = null;
+ }
+
+ return resolvedAssembly;
+ }
+
+#if UNUSED
public static string GetFromMapPathCache(string key)
{
answer[currentFile]= IAppDomainConfig.WAR_ROOT_SYMBOL + currentFile;
}
AppDomain.CurrentDomain.SetData(J2EEConsts.MAP_PATH_CACHE,answer);
-
}
}
return (string)answer[key];
}
}
-
- private static ICachedXmlDoc GetAssembliesCachedDocument()
+#endif
+ private static ICachedXmlDoc GetAssembliesCachedDocument(HttpContext context)
{
- lock(LOCK_GETASSEMBLIESCACHEDDOCUMENT)
- {
- ICachedXmlDoc doc = (ICachedXmlDoc) AppDomain.CurrentDomain.GetData(J2EEConsts.ASSEMBLIES_FILE);
- if (doc == null)
- {
- doc = CreateDocument();
- if (doc != null)
- AppDomain.CurrentDomain.SetData(J2EEConsts.ASSEMBLIES_FILE, doc);
+ ICachedXmlDoc doc = (ICachedXmlDoc) AppDomain.CurrentDomain.GetData (J2EEConsts.ASSEMBLIES_FILE);
+
+ if (doc == null) {
+ lock (LOCK_GETASSEMBLIESCACHEDDOCUMENT) {
+ doc = (ICachedXmlDoc) AppDomain.CurrentDomain.GetData (J2EEConsts.ASSEMBLIES_FILE);
+ if (doc == null) {
+ doc = CreateDocument ();
+ if (doc != null) {
+ AppDomain.CurrentDomain.SetData (J2EEConsts.ASSEMBLIES_FILE, doc);
+
+ AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler (CurrentDomain_AssemblyResolve);
+ try {
+ //Try to load the global resources
+ HttpContext.AppGlobalResourcesAssembly = GetCachedAssembly (context, context.Request.ApplicationPath + "/app_globalresources");
+ }
+ catch (Exception ex) {
+#if DEBUG
+ Console.WriteLine (ex.ToString ());
+#endif
+ }
+ }
+ }
}
-
- return doc;
}
+
+ return doc;
}
+ private static String NormalizeName(string url)
+ {
+#if NET_2_0
+ url = System.Web.Util.UrlUtils.RemoveDoubleSlashes(url);
+#endif
+ if (url.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
+ url = url.Substring(IAppDomainConfig.WAR_ROOT_SYMBOL.Length);
+ return url;
+ }
private static ICachedXmlDoc CreateDocument()
{
return new CachedDocumentTypeStorage();
}
- public static Type GetObjectType(string url)
+ public static Type GetObjectType (HttpContext context, string url)
{
-#if NET_2_0
- return GetCachedType(System.Web.Util.UrlUtils.RemoveDoubleSlashes(url));
-#else
- return GetCachedType(url);
-#endif
+ return GetCachedType(context, NormalizeName(url), true);
}
- private static Type GetCachedType(string url)
- {
- ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument();
-
- if (url.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
- url = url.Substring(IAppDomainConfig.WAR_ROOT_SYMBOL.Length);
-
- Type t = doc.Get(url);
+ public static Type GetObjectType (HttpContext context, string url, bool throwException) {
+ return GetCachedType (context, NormalizeName (url), throwException);
+ }
- if (t == null)
+ public static Assembly GetObjectAssembly (HttpContext context, string url)
+ {
+ return GetCachedAssembly (context, NormalizeName (url));
+ }
+ public static string GetAssemblyResource (HttpContext context, string url)
+ {
+ return GetCachedResource (context, NormalizeName (url));
+ }
+ private static string GetCachedResource (HttpContext context, string url)
+ {
+ ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument(context);
+ return doc.GetAssemblyResourceName (context, url);
+ }
+ private static Assembly GetCachedAssembly (HttpContext context, string url)
+ {
+ ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument(context);
+ return doc.GetAssembly (context, url);
+ }
+ private static Type GetCachedType (HttpContext context, string url) {
+ return GetCachedType (context, url, true);
+ }
+ private static Type GetCachedType (HttpContext context, string url, bool throwException)
+ {
+ ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument(context);
+ Type t = doc.GetType(context, url);
+ if (t == null && throwException)
throw new HttpException(404,"The requested resource (" + url + ") is not available.");
return t;
#region ICachedXmlDoc interface
interface ICachedXmlDoc
{
- Type Get(string key);
- //bool ContainsKey(object key);
+ Type GetType (HttpContext context, string key);
+ Assembly GetAssembly (HttpContext context, string key);
+ string GetAssemblyResourceName (HttpContext context, string key);
}
#endregion
#region CachedDocumentTypeStorage class
class CachedDocumentTypeStorage : ICachedXmlDoc
{
+ private static readonly object _fuse = new object();
public static readonly ICachedXmlDoc DEFAULT_DOC =
new CachedDocumentTypeStorage(0);
this(DEFAULT_PAGES_NUMBER)
{}
- Type ICachedXmlDoc.Get(string o)
+ string ICachedXmlDoc.GetAssemblyResourceName (HttpContext context, string o)
{
- return GetTypeByURL(o);
+ return GetMetaByURL(context, o).Resource;
+ }
+ Type ICachedXmlDoc.GetType (HttpContext context, string o)
+ {
+ return GetMetaByURL(context, o).Type;
+ }
+ Assembly ICachedXmlDoc.GetAssembly (HttpContext context, string o)
+ {
+ return GetMetaByURL(context, o).Assembly;
}
internal IDictionaryEnumerator GetEnumerator()
return _table.GetEnumerator();
}
- public Type GetTypeByURL(string url)
+ //rewamped for perfomance reasons
+ //It looks like issue is not important in development mode,
+ //but only will became important in production mode when dynamyc compilation will be enabled
+ //Anyway, locking whole table and compiling under lock looks odd
+ //spivak.December 07 2006
+ public MetaProvider GetMetaByURL(HttpContext context, string url)
{
- string lwUrl = url.ToLower();
+
+#if !NO_GLOBAL_LOCK_ON_COMPILE
+ string lwUrl = url.ToLowerInvariant();
lock (_table)
{
object retVal = _table[lwUrl];
if (retVal == null)
{
- PageCompiler compiler = new PageCompiler(url);
- retVal = compiler.GetCachedType();
+ retVal = PageCompiler.GetCompiler(context, url);
_table[lwUrl] = retVal;
}
- return (Type)retVal;
+ return (MetaProvider)retVal;
}
+
+#else
+ string lwUrl = url.ToLower();
+ if (!_table.ContainsKey(lwUrl))
+ {
+ lock (_table.SyncRoot)
+ {
+ if (_table.ContainsKey(lwUrl))
+ goto Fused;
+ _table[lwUrl] = _fuse;
+ }
+ try
+ {
+ MetaProvider meta = PageCompiler.GetCompiler(url);
+ lock (_table.SyncRoot)
+ {
+ return (MetaProvider)(_table[lwUrl] = meta);
+ }
+ }
+ catch(Exception e)
+ {
+ _table.Remove(lwUrl);
+ }
+ }
+ Fused:
+
+ while (_table[lwUrl] == _fuse)
+ Thread.Sleep(10);
+
+ return !_table.ContainsKey(lwUrl)? PageCompiler.Error: (MetaProvider)_table[lwUrl];
+#endif
}
}
- #endregion
+
+ #endregion
}
- public class PageCompiler
+ public interface MetaProvider
+ {
+ Type Type { get;}
+ Assembly Assembly {get;}
+ string Resource { get;}
+ }
+ public class PageCompiler : MetaProvider
{
private static readonly string PAGE_XPATH = "preserve";
private static readonly string ASSEM_ATTRIB_NAME = "assem";
private static string _parser = null;
private Type _type = null;
+ private string _typeName = null;
+ private Assembly _assembly = null;
+ private string _origAssemblyName = null;
private string _xmlDescriptor = null;
private string _url = null;
private string _session = null;
+ readonly private HttpContext _context;
- public PageCompiler(string url)
+ PageCompiler(HttpContext context, string url)
{
_url = url;
+ _context = context;
_xmlDescriptor = GetDescFromUrl();
_session = DateTime.Now.Ticks.ToString();
+ LoadTypeAndAssem();
+ }
+
+ public static PageCompiler GetCompiler(HttpContext context, string url)
+ {
+ return new PageCompiler(context, url);
}
- public Type GetCachedType()
+ Type MetaProvider.Type
{
- if (_type != null)
+ get{
return _type;
-
+ }
+ }
+ Assembly MetaProvider.Assembly
+ {
+ get{
+ return _assembly;
+ }
+ }
+ string MetaProvider.Resource
+ {
+ get
+ {
+ return _origAssemblyName != null ? _origAssemblyName + ".ghres" : "dll.ghres";
+ }
+ }
+ private void LoadTypeAndAssem()
+ {
+ if (_assembly == null)
+ {
+ string typeName = GetCachedTypeName();
+ if (typeName != null)
+ {
+ if ((_type = Type.GetType(typeName)) != null)
+ _assembly = _type.Assembly;
+ else
+ _assembly = Assembly.Load(_origAssemblyName);
+ }
+ }
+ }
+ private bool InternalCompile()
+ {
+ string fileName = VirtualPathUtility.GetFileName (_url);
+
+ string fullFileName = (fileName.ToLower () == "global.asax") ? _url : _context.Request.MapPath (_url);
+#if DEBUG
+ Console.WriteLine("fullFileName=" + fullFileName);
+#endif
+ //type not found - run aspxparser
+ if (File.Exists(fullFileName) || Directory.Exists(fullFileName))
+ {
+ string[] command = GetParserCmd(fileName.ToLower() == "global.asax");
+ if (J2EEUtils.RunProc(command) != 0)
+ throw GetCompilerError();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ //string message = "The requested resource (" + _url + ") is not available.";
+ //throw new HttpException(404, message);
+ }
+ }
+ private string GetDescriptorPath()
+ {
+ return String.Join("/", new string[] { "assemblies", _xmlDescriptor });
+ }
+ private string GetTypeNameFromAppFolder()
+ {
+ try
+ {
+ using (StreamReader sr = new StreamReader(_context.Request.MapPath("~/" + GetDescriptorPath())))
+ {
+ return GetTypeFromDescStream(sr.BaseStream);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ throw ex;
+ }
+ }
+ internal string GetTypeFromResources()
+ {
string typeName = null;
-
+
//if the desciptor exists in the war - get the type
- string descPath = String.Join("/", new string[]{"assemblies", _xmlDescriptor});
+ string descPath = GetDescriptorPath();
try
{
#if DEBUG
Console.WriteLine(descPath);
#endif
- Stream fs = (Stream)IOUtils.getStream("/" + descPath);
- if (fs != null)
+ using (Stream fs = (Stream)IOUtils.getStreamRecursive("/" + descPath))
{
- typeName = GetTypeFromDescStream(fs);
+ if (fs != null)
+ {
+ return GetTypeFromDescStream(fs);
+ }
}
}
catch (Exception ex)
#if DEBUG
Console.WriteLine(ex);
#endif
- //desc not in the war
- typeName = null;
}
-
- if (typeName != null)
+ return null;
+ }
+ internal string GetCachedTypeName()
+ {
+ string typeName = GetTypeFromResources();
+ if (typeName == null)
{
- _type = Type.GetType(typeName);
- return _type;
+ //spawn dynamic compilation and lookup typename from created folder
+ if (InternalCompile())
+ typeName = GetTypeNameFromAppFolder();
}
-
- string fileName = Path.GetFileName(_url);
-
- if (fileName.ToLower() != "defaultwsdlhelpgenerator.aspx")
+ return typeName;
+ }
+ private string GetTypeName()
+ {
+ return String.Format("{0}, {1}", _typeName, _origAssemblyName);
+ }
+ private bool LoadMetaFromXmlStream(Stream fs)
+ {
+ if (fs != null)
{
- string fullFileName = (fileName.ToLower() == "global.asax") ? _url : HttpContext.Current.Request.MapPath(_url);
-#if DEBUG
- Console.WriteLine("fullFileName=" + fullFileName);
-#endif
- if ( File.Exists(fullFileName) || Directory.Exists(fullFileName)) {
- //type not found - run aspxparser
- string[] command = GetParserCmd(fileName.ToLower() == "global.asax");
- if (J2EEUtils.RunProc(command) != 0)
- throw GetCompilerError();
- }
- else {
- string message = "The requested resource (" + _url + ") is not available.";
- throw new HttpException(404, message);
- }
-
- //if the desciptor exists in the real app dir - get the type
- try {
- StreamReader sr = new StreamReader (HttpContext.Current.Request.MapPath ("/" + descPath));
- typeName = GetTypeFromDescStream (sr.BaseStream);
- sr.Close ();
+ try
+ {
+ XmlDocument descXml = new XmlDocument();
+ descXml.Load(fs);
+ _origAssemblyName = descXml.SelectSingleNode(PAGE_XPATH).Attributes[ASSEM_ATTRIB_NAME].Value;
+ _typeName = descXml.SelectSingleNode(PAGE_XPATH).Attributes[TYPE_ATTRIB_NAME].Value;
+ return true;
}
- catch (Exception ex) {
- Console.WriteLine (ex);
- throw ex;
+ catch
+ {
+#if DEBUG
+ Console.WriteLine("Failed to load typename from stream");
+#endif
}
}
- else
- typeName = "ASP.defaultwsdlhelpgenerator_jvm_aspx";
-
- if (typeName != null)
- {
- _type = Type.GetType(typeName);
- return _type;
- }
-
- return null;
+ return false;
}
private string GetTypeFromDescStream(Stream fs)
{
- if (fs != null)
- {
- XmlDocument descXml = new XmlDocument();
- descXml.Load(fs);
- string assem = descXml.SelectSingleNode(PAGE_XPATH).Attributes[ASSEM_ATTRIB_NAME].Value;
- string shortType = descXml.SelectSingleNode(PAGE_XPATH).Attributes[TYPE_ATTRIB_NAME].Value;
- string typeName = String.Format("{0}, {1}",shortType,assem);
- fs.Close();
- return typeName;
- }
-
+ if (LoadMetaFromXmlStream(fs))
+ return GetTypeName();
return null;
}
if (_parser == null)
{
StreamReader sr =
- File.OpenText(HttpContext.Current.Request.MapPath("/AspxParser.params"));
+ File.OpenText (_context.Request.MapPath ("~/AspxParser.params"));
_parser = sr.ReadLine();
sr.Close();
}
private string GetDescFromUrl()
{
- string fileName = Path.GetFileName(_url);
+ string fileName = VirtualPathUtility.GetFileName (_url);
if (fileName.ToLower() == "global.asax")
return "global.asax.xml";
private string GetIdFromUrl(string path)
{
- path = path.Trim('/');
- string fileName = Path.GetFileName(path);
+ string fileName = VirtualPathUtility.GetFileName(path);
string id = string.Empty;
- path = path.Substring (path.IndexOf ("/") + 1);
+ if (VirtualPathUtility.IsAbsolute (path))
+ path = path.Substring (_context.Request.ApplicationPath.Length + 1);
if (path.Length > fileName.Length)
id = "." + path.Substring(0,path.Length - fileName.Length).Replace('/','_');
private Exception GetCompilerError()
{
- string _errFile = HttpContext.Current.Request.MapPath("/" + _session + ".vmwerr");
+ string _errFile = _context.Request.MapPath ("~/" + _session + ".vmwerr");
if (!File.Exists(_errFile))
throw new FileNotFoundException("Internal Error",_errFile);