Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / PreservationFile.cs
1 //
2 // System.Web.Compilation.AppCodeCompiler: A compiler for the App_Code folder
3 //
4 // Authors:
5 //   Marek Habersack (grendello@gmail.com)
6 //
7 // (C) 2006 Marek Habersack
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Collections.Generic;
33 using System.IO;
34 using System.Xml;
35
36 namespace System.Web.Compilation 
37 {
38         enum BuildResultTypeCode
39         {
40                 Unknown = 0,
41                 AppCodeSubFolder = 1,
42                 Handler = 2,
43                 PageOrControl = 3,
44                 AppCode = 6,
45                 Global = 8,
46                 TopLevelAssembly = 9
47         }
48
49         //
50         // The attributes of the <preserve> element in a .compiled file are described in
51         //
52         // http://msdn.microsoft.com/msdnmag/issues/07/01/cuttingedge/default.aspx?loc=&fig=true#fig4
53         //
54         // and a sample file is shown in
55         //
56         // http://msdn.microsoft.com/msdnmag/issues/07/01/cuttingedge/default.aspx?loc=&fig=true#fig3
57         //
58         class PreservationFile
59         {
60                 string _filePath;
61                 string _assembly;
62                 Int32 _fileHash;
63                 Int32 _flags;
64                 Int32 _hash;
65                 BuildResultTypeCode _resultType = BuildResultTypeCode.Unknown;
66                 string _virtualPath;
67                 List <string> _filedeps;
68
69                 public string Assembly {
70                         get { return _assembly; }
71                         set { _assembly = value; }
72                 }
73
74                 public string FilePath {
75                         get { return _filePath; }
76                         set { _filePath = value; }
77                 }
78                 
79                 public Int32 FileHash {
80                         get { return _fileHash; }
81                         set { _fileHash = value; }
82                 }
83
84                 public int Flags {
85                         get { return _flags; }
86                         set { _flags = value; }
87                 }
88
89                 public Int32 Hash {
90                         get { return _hash; }
91                         set { _hash = value; }
92                 }
93
94                 public BuildResultTypeCode ResultType {
95                         get { return _resultType; }
96                         set { _resultType = value; }
97                 }
98
99                 public string VirtualPath {
100                         get { return _virtualPath; }
101                         set { _virtualPath = value; }
102                 }
103
104                 public List <string> FileDeps {
105                         get { return _filedeps; }
106                         set { _filedeps = value; }
107                 }
108
109                 public PreservationFile ()
110                 {
111                 }
112                 
113                 public PreservationFile (string filePath)
114                 {
115                         this._filePath = filePath;
116                         Parse (filePath);
117                 }
118
119                 public void Parse ()
120                 {
121                         if (_filePath == null)
122                                 throw new InvalidOperationException ("File path is not defined");
123                         Parse (_filePath);
124                 }
125
126                 public void Parse (string filePath)
127                 {
128                         if (filePath == null)
129                                 throw new ArgumentNullException ("File path is required", "filePath");
130                         
131                         XmlDocument doc = new XmlDocument ();
132                         doc.Load (filePath);
133                         
134                         XmlNode root = doc.DocumentElement;
135                         if (root.Name != "preserve")
136                                 throw new InvalidOperationException ("Invalid assembly mapping file format");
137                         ParseRecursively (root);
138                 }
139
140                 void ParseRecursively (XmlNode root)
141                 {
142                         _assembly = GetNonEmptyRequiredAttribute (root, "assembly");
143
144                         // The rest of the values is optional for us and since we don't use them
145                         // at all (at least for now) we also ignore all the integer parsing errors
146                         try {
147                                 _virtualPath = GetNonEmptyOptionalAttribute (root, "virtualPath");
148                                 _fileHash = GetNonEmptyOptionalAttributeInt32 (root, "filehash");
149                                 _hash = GetNonEmptyOptionalAttributeInt32 (root, "hash");
150                                 _flags = GetNonEmptyOptionalAttributeInt32 (root, "flags");
151                                 _resultType = (BuildResultTypeCode) GetNonEmptyOptionalAttributeInt32 (root, "resultType");
152
153                                 foreach (XmlNode child in root.ChildNodes) {
154                                         if (child.NodeType != XmlNodeType.Element)
155                                                 continue;
156                                         if (child.Name != "filedeps")
157                                                 continue;
158                                         ReadFileDeps (child);
159                                 }
160                         } catch (Exception) {
161                         }
162                 }
163
164                 void ReadFileDeps (XmlNode node)
165                 {
166                         string tmp;
167                         if (_filedeps == null)
168                                 _filedeps = new List <string> ();
169                         foreach (XmlNode child in node.ChildNodes) {
170                                 if (child.NodeType != XmlNodeType.Element)
171                                         continue;
172                                 if (child.Name != "filedep")
173                                         continue;
174                                 tmp = GetNonEmptyRequiredAttribute (child, "name");
175                                 _filedeps.Add (tmp);
176                         }
177                 }
178                 
179                 public void Save ()
180                 {
181                         if (_filePath == null)
182                                 throw new InvalidOperationException ("File path is not defined");
183                         Save (_filePath);
184                 }
185
186                 public void Save (string filePath)
187                 {
188                         if (filePath == null)
189                                 throw new ArgumentNullException ("File path is required", "filePath");
190
191                         XmlWriterSettings xmlSettings = new XmlWriterSettings ();
192                         xmlSettings.Indent = false;
193                         xmlSettings.OmitXmlDeclaration = false;
194                         xmlSettings.NewLineOnAttributes = false;
195                         
196                         using (XmlWriter xml = XmlWriter.Create (filePath, xmlSettings)) {
197                                 xml.WriteStartElement ("preserve");
198                                 xml.WriteAttributeString ("assembly", _assembly);
199                                 if (!String.IsNullOrEmpty (_virtualPath))
200                                         xml.WriteAttributeString ("virtualPath", _virtualPath);
201                                 if (_fileHash != 0)
202                                         xml.WriteAttributeString ("filehash", _fileHash.ToString ());
203                                 if (_flags != 0)
204                                         xml.WriteAttributeString ("flags", _flags.ToString ());
205                                 if (_hash != 0)
206                                         xml.WriteAttributeString ("hash", _hash.ToString ());
207                                 if (_resultType != BuildResultTypeCode.Unknown)
208                                         xml.WriteAttributeString ("resultType", ((int)_resultType).ToString ());
209                                 if (_filedeps != null && _filedeps.Count > 0) {
210                                         xml.WriteStartElement ("filedeps");
211                                         foreach (string s in _filedeps) {
212                                                 xml.WriteStartElement ("filedep");
213                                                 xml.WriteAttributeString ("name", s);
214                                                 xml.WriteEndElement ();
215                                         }
216                                         xml.WriteEndElement ();
217                                 }
218                                 xml.WriteEndElement ();
219                         }
220                 }
221
222                 string GetNonEmptyOptionalAttribute (XmlNode n, string name)
223                 {
224                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, true);
225                 }
226                 
227                 Int32 GetNonEmptyOptionalAttributeInt32 (XmlNode n, string name)
228                 {
229                         string tmp = GetNonEmptyOptionalAttribute (n, name);
230                         if (tmp != null)
231                                 return Int32.Parse (tmp);
232                         return 0;
233                 }
234
235                 string GetNonEmptyRequiredAttribute (XmlNode n, string name)
236                 {
237                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, false, false);
238                 }
239         }
240 }
241