New tests.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / ServiceHostParser.cs
1 //
2 // ServiceHostParser.cs
3 //
4 // Author:
5 //      Ankit Jain      (jankit@novell.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // Copyright (C) 2006 Novell, Inc.  http://www.novell.com
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.IO;
33 using System.Text;
34 using System.Web;
35 using System.Web.Caching;
36 using System.Web.Configuration;
37
38 namespace System.ServiceModel.Channels {
39
40         class ServiceHostParser
41         {
42                 string file;
43                 string url;
44                 string type_name;
45                 string language;
46                 string factory;
47                 bool debug;
48                 bool got_default_directive;
49                 string program; // If program == null, we have to get the requested 'type_name' from the assemblies in bin
50                 ArrayList assemblies;
51                 HttpContext context;
52
53                 public ServiceHostParser (string file, string url, HttpContext context)
54                 {
55                         this.file = file;
56                         this.url = url;
57                         assemblies = new ArrayList ();
58                         assemblies.Add ("System.ServiceModel");
59                         this.context = context;
60                         CompilationSection section = (CompilationSection) context.GetSection ("system.web/compilation");
61                         language = section.DefaultLanguage;
62                 }
63
64                 public HttpContext Context {
65                         get { return context; }
66                 }
67
68                 public string Filename {
69                         get { return file; }
70                 }
71
72                 public string TypeName {
73                         get { return type_name; }
74                 }
75
76                 public bool Debug {
77                         get { return debug; }
78                 }
79
80                 public string Program {
81                         get { return program; }
82                 }
83
84                 public ArrayList Assemblies {
85                         get { return assemblies; }
86                 }
87
88                 public string Factory {
89                         get { return factory; }
90                 }
91
92                 public string Language {
93                         get { return language; }
94                 }
95
96                 public void Parse ()
97                 {
98                         using (StreamReader reader = new StreamReader (file)) {
99                                 string line;
100                                 bool directive_found = false;
101                                 StringBuilder content = new StringBuilder ();
102                                         
103                                 while ((line = reader.ReadLine ()) != null) {
104                                         string trimmed = line.Trim ();
105                                         if (!directive_found && trimmed == String.Empty)
106                                                 continue;
107                                         
108                                         if (trimmed.StartsWith ("<%@")) {
109                                                 ParseDirective (trimmed);
110                                                 directive_found = true;
111                                                 continue;
112                                         }
113
114                                         content.Append (line + "\n");
115                                         content.Append (reader.ReadToEnd ());
116                                 }
117                                 
118                                 if (!got_default_directive)
119                                         throw new Exception ("No @ServiceHost directive found");
120
121                                 this.program = content.ToString ().Trim ();
122                                 if (this.program.Trim () == "")
123                                         this.program = null;
124                         }
125
126                         if (String.IsNullOrEmpty (Language))
127                                 throw new Exception ("Language not specified.");
128                 }
129
130                 void ParseDirective (string line)
131                 {
132                         StringDictionary attributes = Split (line);
133
134                         //Directive
135                         if (String.Compare (attributes ["directive"], "ServiceHost", true) == 0) {
136                                 got_default_directive = true;
137
138                                 if (!attributes.ContainsKey ("SERVICE"))
139                                         throw new Exception ("Service attribute not present in @ServiceHost directive.");
140                                 else
141                                         type_name = attributes ["SERVICE"];
142
143                                 if (attributes.ContainsKey ("LANGUAGE"))
144                                         language = attributes ["LANGUAGE"];
145
146                                 if (attributes.ContainsKey ("FACTORY"))
147                                         factory = attributes ["FACTORY"];
148
149                                 if (attributes.ContainsKey ("DEBUG")) {
150                                         if (String.Compare (attributes ["DEBUG"], "TRUE", true) == 0)
151                                                 debug = true;
152                                         else if (String.Compare (attributes ["DEBUG"], "FALSE", true) == 0)
153                                                 debug = false;
154                                         else
155                                                 throw new Exception (String.Format (
156                                                         "Invalid value for debug attribute : '{0}'", attributes ["DEBUG"]));
157                                 }
158
159
160                                 //FIXME: Other attributes, 
161                                 return;
162                         }
163                         //FIXME: Other directives? Documentation doesn't mention any other
164
165                         throw new Exception (String.Format ("Cannot handle directive : '{0}'", attributes ["directive"]));
166                 }
167
168                 StringDictionary Split (string line)
169                 {
170                         line.Trim ();
171                         int end_pos = line.LastIndexOf ("%>");
172                         if (end_pos < 0)
173                                 throw new Exception ("Directive must end with '%>'");
174
175                         StringDictionary table = new StringDictionary ();
176                         string content = line.Substring (3, end_pos - 3).Trim ();
177                         if (content.Length == 0)
178                                 throw new Exception ("No directive found");
179
180                         int len = content.Length;
181                         int pos = 0;
182                         
183                         while (pos < len && content [pos] != ' ')
184                                 pos ++;
185
186                         if (pos >= len) {
187                                 table ["directive"] = content;
188                                 return table;
189                         }
190
191                         table ["directive"] = content.Substring (0, pos);
192
193                         content = content.Substring (pos);
194
195                         len = content.Length;
196                         pos = 0;
197                         while (pos < len) {
198                                 //skip spaces   
199                                 while (content [pos] == ' ' && pos < len)
200                                         pos ++;
201
202                                 int eq_pos = content.IndexOf ('=', pos);
203                                 string key = content.Substring (pos, eq_pos - pos).Trim ();
204
205                                 pos = eq_pos + 1;
206                                 int start_quote = content.IndexOf ('"', pos);
207                                 int end_quote = content.IndexOf ('"', start_quote + 1);
208
209                                 string val = content.Substring (start_quote + 1, end_quote - start_quote - 1).Trim ();
210
211                                 pos = end_quote + 1;
212                                 table [key.ToUpper ()] = val;
213                         }
214
215                         return table;
216                 }
217
218         }
219 }