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)
137 return GetCachedType(url);
140 private static Type GetCachedType(string url)
142 ICachedXmlDoc doc = PageMapper.GetAssembliesCachedDocument();
144 if (url.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
145 url = url.Substring(IAppDomainConfig.WAR_ROOT_SYMBOL.Length);
147 Type t = doc.Get(url);
150 throw new HttpException(404,"The requested resource (" + url + ") is not available.");
155 #region ICachedXmlDoc interface
156 interface ICachedXmlDoc
158 Type Get(string key);
159 //bool ContainsKey(object key);
163 #region CachedDocumentTypeStorage class
164 class CachedDocumentTypeStorage : ICachedXmlDoc
166 public static readonly ICachedXmlDoc DEFAULT_DOC =
167 new CachedDocumentTypeStorage(0);
169 private static readonly int DEFAULT_PAGES_NUMBER = 25;
171 private Hashtable _table;
173 private CachedDocumentTypeStorage(int initTableSize)
175 _table = Hashtable.Synchronized(new Hashtable(initTableSize));
178 public CachedDocumentTypeStorage() :
179 this(DEFAULT_PAGES_NUMBER)
182 Type ICachedXmlDoc.Get(string o)
184 return GetTypeByURL(o);
187 internal IDictionaryEnumerator GetEnumerator()
189 return _table.GetEnumerator();
192 public Type GetTypeByURL(string url)
194 string lwUrl = url.ToLower();
197 object retVal = _table[lwUrl];
200 PageCompiler compiler = new PageCompiler(url);
201 retVal = compiler.GetCachedType();
202 _table[lwUrl] = retVal;
213 public class PageCompiler
215 private static readonly string PAGE_XPATH = "preserve";
216 private static readonly string ASSEM_ATTRIB_NAME = "assem";
217 private static readonly string TYPE_ATTRIB_NAME = "type";
218 private static string _parser = null;
220 private Type _type = null;
221 private string _xmlDescriptor = null;
222 private string _url = null;
223 private string _session = null;
225 public PageCompiler(string url)
228 _xmlDescriptor = GetDescFromUrl();
229 _session = DateTime.Now.Ticks.ToString();
232 public Type GetCachedType()
237 string typeName = null;
239 //if the desciptor exists in the war - get the type
240 string descPath = String.Join("/", new string[]{"assemblies", _xmlDescriptor});
245 Console.WriteLine(descPath);
247 Stream fs = (Stream)IOUtils.getStream("/" + descPath);
250 typeName = GetTypeFromDescStream(fs);
256 Console.WriteLine(ex);
258 //desc not in the war
262 if (typeName != null)
264 _type = Type.GetType(typeName);
268 string fileName = Path.GetFileName(_url);
269 if (fileName.ToLower() != "global.asax"
270 && fileName.ToLower() != "defaultwsdlhelpgenerator.aspx")
272 string fullFileName = HttpContext.Current.Request.MapPath(_url);
273 if ( File.Exists(fullFileName) ) {
274 //type not found - run aspxparser
275 string[] command = GetParserCmd();
276 if (J2EEUtils.RunProc(command) != 0)
277 throw GetCompilerError();
280 string message = "The requested resource (" + _url + ") is not available.";
281 throw new HttpException(404, message);
284 //if the desciptor exists in the real app dir - get the type
287 StreamReader sr = new StreamReader(HttpContext.Current.Request.MapPath("/" + descPath));
288 typeName = GetTypeFromDescStream(sr.BaseStream);
293 Console.WriteLine(ex);
297 if (typeName != null)
299 _type = Type.GetType(typeName);
306 private string GetTypeFromDescStream(Stream fs)
310 XmlDocument descXml = new XmlDocument();
312 string assem = descXml.SelectSingleNode(PAGE_XPATH).Attributes[ASSEM_ATTRIB_NAME].Value;
313 string shortType = descXml.SelectSingleNode(PAGE_XPATH).Attributes[TYPE_ATTRIB_NAME].Value;
314 string typeName = String.Format("{0}, {1}",shortType,assem);
322 private string[] GetParserCmd()
324 string[] cmd = new string[5];
325 cmd[0] = GetParser();
326 cmd[1] = "/aspxFiles:" + _url.Trim('/').Replace('/','\\');
327 cmd[2] = "/session:" + _session;
328 cmd[3] = "/appDir:" + (string)AppDomain.CurrentDomain.GetData(IAppDomainConfig.APP_PHYS_DIR);
329 cmd[4] = "/compilepages";
333 private string GetParser()
338 File.OpenText(HttpContext.Current.Request.MapPath("/AspxParser.params"));
339 _parser = sr.ReadLine();
346 private string GetDescFromUrl()
348 string fileName = Path.GetFileName(_url);
350 if (fileName.ToLower() == "global.asax")
351 return "global.asax.xml";
353 string id = GetIdFromUrl(_url);
354 string[] descName = new string[3] {fileName, id, ".xml"} ;
355 return string.Concat(descName).ToLower();
358 private string GetIdFromUrl(string path)
360 path = path.Trim('/');
361 string fileName = Path.GetFileName(path);
362 string id = string.Empty;
363 if (path.Length > fileName.Length)
364 id = "." + path.Substring(0,path.Length - fileName.Length).Replace('/','_');
368 private Exception GetCompilerError()
370 string _errFile = HttpContext.Current.Request.MapPath("/" + _session + ".vmwerr");
372 if (!File.Exists(_errFile))
373 throw new FileNotFoundException("Internal Error",_errFile);
375 StreamReader sr = new StreamReader(_errFile);
376 string message = string.Empty, line = null, file = null, lineInFile = "0";
378 while ((line = sr.ReadLine()) != null)
380 if (line.StartsWith("Message: "))
381 message = line.Substring("Message: ".Length);
382 else if (line.StartsWith("File: "))
383 file = line.Substring("File: ".Length);
384 else if (line.StartsWith("Line: "))
385 lineInFile = line.Substring("Line: ".Length);
392 Location loc = new Location(null);
394 loc.BeginLine = int.Parse(lineInFile);
395 return new ParseException(loc,message);
398 if (message.IndexOf(typeof(FileNotFoundException).Name) != -1 &&
399 message.IndexOf(_url.Trim('\\','/').Replace('/','\\')) != -1)
400 message = "The requested resource (" + _url + ") is not available.";
401 return new HttpException(404,(message != null ? message : string.Empty));