2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections;
30 using System.Web.Compilation;
31 using System.Collections.Specialized;
32 using System.Threading;
35 namespace System.Web.J2EE
38 /// Class that allows reading assemblies.xml file for getting information about different types.
40 public class PageMapper
42 private static readonly string _fileListName = "/filelist.xml";
43 private static readonly object LOCK_GETASSEMBLIESCACHEDDOCUMENT = new object();
44 private static readonly object LOCK_GETFROMMAPPATHCACHE = new object();
46 public static string GetFromMapPathCache(string key)
48 Hashtable answer = null;
49 lock(LOCK_GETFROMMAPPATHCACHE)
51 answer = (Hashtable) AppDomain.CurrentDomain.GetData(J2EEConsts.MAP_PATH_CACHE);
54 answer = new Hashtable();
55 CachedDocumentTypeStorage storage = (CachedDocumentTypeStorage)GetAssembliesCachedDocument();
56 IDictionaryEnumerator e = storage.GetEnumerator();
60 string currentFile = (string)((DictionaryEntry)e.Current).Key;
61 answer[currentFile]= IAppDomainConfig.WAR_ROOT_SYMBOL + currentFile;
63 AppDomain.CurrentDomain.SetData(J2EEConsts.MAP_PATH_CACHE,answer);
67 return (string)answer[key];
71 //The method was used by runtime to force file names casesensitivity
72 // problem. The filelist.xml file should contain correct file names,
73 // but currently it is unused
74 public static void LoadFileList()
76 Hashtable hashTable = (Hashtable) AppDomain.CurrentDomain.GetData(J2EEConsts.FILE_LIST_FILE);
77 if (hashTable == null)
82 Stream fs = (Stream)IOUtils.getStream(_fileListName);
85 AppDomain.CurrentDomain.SetData(J2EEConsts.FILE_LIST_FILE, new Hashtable());
89 doc = new XmlDocument();
94 // Console.WriteLine("filelist.xml was not found!!!");
95 AppDomain.CurrentDomain.SetData(J2EEConsts.FILE_LIST_FILE, new Hashtable());
98 // Console.WriteLine("filelist.xml was found!!!");
99 if (doc != null && doc.DocumentElement.HasChildNodes)
101 hashTable = CollectionsUtil.CreateCaseInsensitiveHashtable();
102 XmlNodeList nodeList = doc.DocumentElement.ChildNodes;
103 for (int i = 0;i < nodeList.Count ; i++)
105 string fileName = nodeList.Item(i).InnerText;
106 hashTable.Add(fileName,fileName);
108 AppDomain.CurrentDomain.SetData(J2EEConsts.FILE_LIST_FILE, hashTable);
114 private static ICachedXmlDoc GetAssembliesCachedDocument()
116 lock(LOCK_GETASSEMBLIESCACHEDDOCUMENT)
118 ICachedXmlDoc doc = (ICachedXmlDoc) AppDomain.CurrentDomain.GetData(J2EEConsts.ASSEMBLIES_FILE);
121 doc = CreateDocument();
123 AppDomain.CurrentDomain.SetData(J2EEConsts.ASSEMBLIES_FILE, doc);
130 private static ICachedXmlDoc CreateDocument()
132 return new CachedDocumentTypeStorage();
135 public static Type GetObjectType(string url)
138 return GetCachedType(System.Web.Util.UrlUtils.RemoveDoubleSlashes(url));
140 return GetCachedType(url);
144 private static Type GetCachedType(string url)
146 ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument();
148 if (url.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
149 url = url.Substring(IAppDomainConfig.WAR_ROOT_SYMBOL.Length);
151 Type t = doc.Get(url);
154 throw new HttpException(404,"The requested resource (" + url + ") is not available.");
159 #region ICachedXmlDoc interface
160 interface ICachedXmlDoc
162 Type Get(string key);
163 //bool ContainsKey(object key);
167 #region CachedDocumentTypeStorage class
168 class CachedDocumentTypeStorage : ICachedXmlDoc
170 public static readonly ICachedXmlDoc DEFAULT_DOC =
171 new CachedDocumentTypeStorage(0);
173 private static readonly int DEFAULT_PAGES_NUMBER = 25;
175 private Hashtable _table;
177 private CachedDocumentTypeStorage(int initTableSize)
179 _table = Hashtable.Synchronized(new Hashtable(initTableSize));
182 public CachedDocumentTypeStorage() :
183 this(DEFAULT_PAGES_NUMBER)
186 Type ICachedXmlDoc.Get(string o)
188 return GetTypeByURL(o);
191 internal IDictionaryEnumerator GetEnumerator()
193 return _table.GetEnumerator();
196 public Type GetTypeByURL(string url)
198 string lwUrl = url.ToLower();
201 object retVal = _table[lwUrl];
204 PageCompiler compiler = new PageCompiler(url);
205 retVal = compiler.GetCachedType();
206 _table[lwUrl] = retVal;
217 public class PageCompiler
219 private static readonly string PAGE_XPATH = "preserve";
220 private static readonly string ASSEM_ATTRIB_NAME = "assem";
221 private static readonly string TYPE_ATTRIB_NAME = "type";
222 private static string _parser = null;
224 private Type _type = null;
225 private string _xmlDescriptor = null;
226 private string _url = null;
227 private string _session = null;
229 public PageCompiler(string url)
232 _xmlDescriptor = GetDescFromUrl();
233 _session = DateTime.Now.Ticks.ToString();
236 public Type GetCachedType()
241 string typeName = null;
243 //if the desciptor exists in the war - get the type
244 string descPath = String.Join("/", new string[]{"assemblies", _xmlDescriptor});
249 Console.WriteLine(descPath);
251 Stream fs = (Stream)IOUtils.getStream("/" + descPath);
254 typeName = GetTypeFromDescStream(fs);
260 Console.WriteLine(ex);
262 //desc not in the war
266 if (typeName != null)
268 _type = Type.GetType(typeName);
272 string fileName = Path.GetFileName(_url);
274 if (fileName.ToLower() != "defaultwsdlhelpgenerator.aspx")
276 string fullFileName = (fileName.ToLower() == "global.asax") ? _url : HttpContext.Current.Request.MapPath(_url);
278 Console.WriteLine("fullFileName=" + fullFileName);
280 if ( File.Exists(fullFileName) || Directory.Exists(fullFileName)) {
281 //type not found - run aspxparser
282 string[] command = GetParserCmd(fileName.ToLower() == "global.asax");
283 if (J2EEUtils.RunProc(command) != 0)
284 throw GetCompilerError();
287 string message = "The requested resource (" + _url + ") is not available.";
288 throw new HttpException(404, message);
291 //if the desciptor exists in the real app dir - get the type
293 StreamReader sr = new StreamReader (HttpContext.Current.Request.MapPath ("/" + descPath));
294 typeName = GetTypeFromDescStream (sr.BaseStream);
297 catch (Exception ex) {
298 Console.WriteLine (ex);
303 typeName = "ASP.defaultwsdlhelpgenerator_jvm_aspx";
305 if (typeName != null)
307 _type = Type.GetType(typeName);
314 private string GetTypeFromDescStream(Stream fs)
318 XmlDocument descXml = new XmlDocument();
320 string assem = descXml.SelectSingleNode(PAGE_XPATH).Attributes[ASSEM_ATTRIB_NAME].Value;
321 string shortType = descXml.SelectSingleNode(PAGE_XPATH).Attributes[TYPE_ATTRIB_NAME].Value;
322 string typeName = String.Format("{0}, {1}",shortType,assem);
330 private string[] GetParserCmd(bool globalAsax)
336 cmd[3] = "/buildglobalasax";
341 cmd[3] = "/aspxFiles:" + _url;
342 cmd[4] = "/compilepages";
344 cmd[0] = GetParser();
345 cmd[1] = "/session:" + _session;
346 cmd[2] = "/appDir:" + (string)AppDomain.CurrentDomain.GetData(IAppDomainConfig.APP_PHYS_DIR);
350 private string GetParser()
355 File.OpenText(HttpContext.Current.Request.MapPath("/AspxParser.params"));
356 _parser = sr.ReadLine();
363 private string GetDescFromUrl()
365 string fileName = Path.GetFileName(_url);
367 if (fileName.ToLower() == "global.asax")
368 return "global.asax.xml";
370 string id = GetIdFromUrl(_url);
371 string[] descName = new string[3] {fileName, id, ".xml"} ;
372 return string.Concat(descName).ToLower();
375 private string GetIdFromUrl(string path)
377 path = path.Trim('/');
378 string fileName = Path.GetFileName(path);
379 string id = string.Empty;
381 path = path.Substring (path.IndexOf ("/") + 1);
383 if (path.Length > fileName.Length)
384 id = "." + path.Substring(0,path.Length - fileName.Length).Replace('/','_');
388 private Exception GetCompilerError()
390 string _errFile = HttpContext.Current.Request.MapPath("/" + _session + ".vmwerr");
392 if (!File.Exists(_errFile))
393 throw new FileNotFoundException("Internal Error",_errFile);
395 StreamReader sr = new StreamReader(_errFile);
396 string message = string.Empty, line = null, file = null, lineInFile = "0";
398 while ((line = sr.ReadLine()) != null)
400 if (line.StartsWith("Message: "))
401 message = line.Substring("Message: ".Length);
402 else if (line.StartsWith("File: "))
403 file = line.Substring("File: ".Length);
404 else if (line.StartsWith("Line: "))
405 lineInFile = line.Substring("Line: ".Length);
412 Location loc = new Location(null);
414 loc.BeginLine = int.Parse(lineInFile);
415 return new ParseException(loc,message);
418 if (message.IndexOf(typeof(FileNotFoundException).Name) != -1 &&
419 message.IndexOf(_url.Trim('\\','/').Replace('/','\\')) != -1)
420 message = "The requested resource (" + _url + ") is not available.";
421 return new HttpException(404,(message != null ? message : string.Empty));