* PageThemeCompiler.cs: let property builders through, stop the
[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 #if NET_2_0
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                 AspxPage = 3,
42                 TopLevelAssembly = 9
43         }
44
45         //
46         // The attributes of the <preserve> element in a .compiled file are described in
47         //
48         // http://msdn.microsoft.com/msdnmag/issues/07/01/cuttingedge/default.aspx?loc=&fig=true#fig4
49         //
50         // and a sample file is shown in
51         //
52         // http://msdn.microsoft.com/msdnmag/issues/07/01/cuttingedge/default.aspx?loc=&fig=true#fig3
53         //
54         internal class PreservationFile
55         {
56                 string _filePath;
57                 string _assembly;
58                 Int32 _fileHash;
59                 Int32 _flags;
60                 Int32 _hash;
61                 BuildResultTypeCode _resultType = BuildResultTypeCode.Unknown;
62                 string _virtualPath;
63                 List <string> _filedeps;
64
65                 public string Assembly {
66                         get { return _assembly; }
67                         set { _assembly = value; }
68                 }
69
70                 public string FilePath {
71                         get { return _filePath; }
72                         set { _filePath = value; }
73                 }
74                 
75                 public Int32 FileHash {
76                         get { return _fileHash; }
77                         set { _fileHash = value; }
78                 }
79
80                 public int Flags {
81                         get { return _flags; }
82                         set { _flags = value; }
83                 }
84
85                 public Int32 Hash {
86                         get { return _hash; }
87                         set { _hash = value; }
88                 }
89
90                 public BuildResultTypeCode ResultType {
91                         get { return _resultType; }
92                         set { _resultType = value; }
93                 }
94
95                 public string VirtualPath {
96                         get { return _virtualPath; }
97                         set { _virtualPath = value; }
98                 }
99
100                 public List <string> FileDeps {
101                         get { return _filedeps; }
102                         set { _filedeps = value; }
103                 }
104
105                 public PreservationFile ()
106                 {
107                 }
108                 
109                 public PreservationFile (string filePath)
110                 {
111                         this._filePath = filePath;
112                         Parse (filePath);
113                 }
114
115                 public void Parse ()
116                 {
117                         if (_filePath == null)
118                                 throw new InvalidOperationException ("File path is not defined");
119                         Parse (_filePath);
120                 }
121
122                 public void Parse (string filePath)
123                 {
124                         if (filePath == null)
125                                 throw new ArgumentNullException ("File path is required", "filePath");
126                         
127                         XmlDocument doc = new XmlDocument ();
128                         doc.Load (filePath);
129                         
130                         XmlNode root = doc.DocumentElement;
131                         if (root.Name != "preserve")
132                                 throw new InvalidOperationException ("Invalid assembly mapping file format");
133                         ParseRecursively (root);
134                 }
135
136                 void ParseRecursively (XmlNode root)
137                 {
138                         _assembly = GetNonEmptyRequiredAttribute (root, "assembly");
139
140                         // The rest of the values is optional for us and since we don't use them
141                         // at all (at least for now) we also ignore all the integer parsing errors
142                         try {
143                                 _virtualPath = GetNonEmptyOptionalAttribute (root, "virtualPath");
144                                 _fileHash = GetNonEmptyOptionalAttributeInt32 (root, "filehash");
145                                 _hash = GetNonEmptyOptionalAttributeInt32 (root, "hash");
146                                 _flags = GetNonEmptyOptionalAttributeInt32 (root, "flags");
147                                 _resultType = (BuildResultTypeCode) GetNonEmptyOptionalAttributeInt32 (root, "resultType");
148
149                                 foreach (XmlNode child in root.ChildNodes) {
150                                         if (child.NodeType != XmlNodeType.Element)
151                                                 continue;
152                                         if (child.Name != "filedeps")
153                                                 continue;
154                                         ReadFileDeps (child);
155                                 }
156                         } catch (Exception) {
157                         }
158                 }
159
160                 void ReadFileDeps (XmlNode node)
161                 {
162                         string tmp;
163                         if (_filedeps == null)
164                                 _filedeps = new List <string> ();
165                         foreach (XmlNode child in node.ChildNodes) {
166                                 if (child.NodeType != XmlNodeType.Element)
167                                         continue;
168                                 if (child.Name != "filedep")
169                                         continue;
170                                 tmp = GetNonEmptyRequiredAttribute (child, "name");
171                                 _filedeps.Add (tmp);
172                         }
173                 }
174                 
175                 public void Save ()
176                 {
177                         if (_filePath == null)
178                                 throw new InvalidOperationException ("File path is not defined");
179                         Save (_filePath);
180                 }
181
182                 public void Save (string filePath)
183                 {
184                         if (filePath == null)
185                                 throw new ArgumentNullException ("File path is required", "filePath");
186
187                         XmlWriterSettings xmlSettings = new XmlWriterSettings ();
188                         xmlSettings.Indent = false;
189                         xmlSettings.OmitXmlDeclaration = false;
190                         xmlSettings.NewLineOnAttributes = false;
191                         
192                         using (XmlWriter xml = XmlWriter.Create (filePath, xmlSettings)) {
193                                 xml.WriteStartElement ("preserve");
194                                 xml.WriteAttributeString ("assembly", _assembly);
195                                 if (!String.IsNullOrEmpty (_virtualPath))
196                                         xml.WriteAttributeString ("virtualPath", _virtualPath);
197                                 if (_fileHash != 0)
198                                         xml.WriteAttributeString ("filehash", _fileHash.ToString ());
199                                 if (_flags != 0)
200                                         xml.WriteAttributeString ("flags", _flags.ToString ());
201                                 if (_hash != 0)
202                                         xml.WriteAttributeString ("hash", _hash.ToString ());
203                                 if (_resultType != BuildResultTypeCode.Unknown)
204                                         xml.WriteAttributeString ("resultType", ((int)_resultType).ToString ());
205                                 if (_filedeps != null && _filedeps.Count > 0) {
206                                         xml.WriteStartElement ("filedeps");
207                                         foreach (string s in _filedeps) {
208                                                 xml.WriteStartElement ("filedep");
209                                                 xml.WriteAttributeString ("name", s);
210                                                 xml.WriteEndElement ();
211                                         }
212                                         xml.WriteEndElement ();
213                                 }
214                                 xml.WriteEndElement ();
215                         }
216                 }
217
218                 string GetNonEmptyOptionalAttribute (XmlNode n, string name)
219                 {
220                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, true);
221                 }
222                 
223                 Int32 GetNonEmptyOptionalAttributeInt32 (XmlNode n, string name)
224                 {
225                         string tmp = GetNonEmptyOptionalAttribute (n, name);
226                         if (tmp != null)
227                                 return Int32.Parse (tmp);
228                         return 0;
229                 }
230
231                 string GetNonEmptyRequiredAttribute (XmlNode n, string name)
232                 {
233                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, false, false);
234                 }
235         }
236 }
237 #endif