//
// ServiceHostParser.cs
//
// Author:
// Ankit Jain (jankit@novell.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// Copyright (C) 2006 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Configuration;
namespace System.ServiceModel.Channels{
class ServiceHostParser
{
string file;
string url;
string type_name;
string language;
string factory;
bool debug;
bool got_default_directive;
string program; // If program == null, we have to get the requested 'type_name' from the assemblies in bin
ArrayList assemblies;
HttpContext context;
public ServiceHostParser (string file, string url, HttpContext context)
{
this.file = file;
this.url = url;
assemblies = new ArrayList ();
assemblies.Add ("System.ServiceModel");
this.context = context;
CompilationSection section = (CompilationSection) context.GetSection ("system.web/compilation");
language = section.DefaultLanguage;
}
public HttpContext Context {
get { return context; }
}
public string Filename {
get { return file; }
}
public string TypeName {
get { return type_name; }
}
public bool Debug {
get { return debug; }
}
public string Program {
get { return program; }
}
public ArrayList Assemblies {
get { return assemblies; }
}
public string Factory {
get { return factory; }
}
public string Language {
get { return language; }
}
public void Parse ()
{
using (StreamReader reader = new StreamReader (file)) {
string line;
bool directive_found = false;
StringBuilder content = new StringBuilder ();
while ((line = reader.ReadLine ()) != null) {
string trimmed = line.Trim ();
if (!directive_found && trimmed == String.Empty)
continue;
if (trimmed.StartsWith ("<%@")) {
ParseDirective (trimmed);
directive_found = true;
continue;
}
content.Append (line + "\n");
content.Append (reader.ReadToEnd ());
}
if (!got_default_directive)
throw new Exception ("No @ServiceHost directive found");
this.program = content.ToString ().Trim ();
if (this.program.Trim () == "")
this.program = null;
}
if (String.IsNullOrEmpty (Language))
throw new Exception ("Language not specified.");
}
void ParseDirective (string line)
{
StringDictionary attributes = Split (line);
//Directive
if (String.Compare (attributes ["directive"], "ServiceHost", true) == 0) {
got_default_directive = true;
if (!attributes.ContainsKey ("SERVICE"))
throw new Exception ("Service attribute not present in @ServiceHost directive.");
else
type_name = attributes ["SERVICE"];
if (attributes.ContainsKey ("LANGUAGE"))
language = attributes ["LANGUAGE"];
if (attributes.ContainsKey ("FACTORY"))
factory = attributes ["FACTORY"];
if (attributes.ContainsKey ("DEBUG")) {
if (String.Compare (attributes ["DEBUG"], "TRUE", true) == 0)
debug = true;
else if (String.Compare (attributes ["DEBUG"], "FALSE", true) == 0)
debug = false;
else
throw new Exception (String.Format (
"Invalid value for debug attribute : '{0}'", attributes ["DEBUG"]));
}
//FIXME: Other attributes,
return;
}
//FIXME: Other directives? Documentation doesn't mention any other
throw new Exception (String.Format ("Cannot handle directive : '{0}'", attributes ["directive"]));
}
StringDictionary Split (string line)
{
line.Trim ();
int end_pos = line.LastIndexOf ("%>");
if (end_pos < 0)
throw new Exception ("Directive must end with '%>'");
StringDictionary table = new StringDictionary ();
string content = line.Substring (3, end_pos - 3).Trim ();
if (content.Length == 0)
throw new Exception ("No directive found");
int len = content.Length;
int pos = 0;
while (pos < len && content [pos] != ' ')
pos ++;
if (pos >= len) {
table ["directive"] = content;
return table;
}
table ["directive"] = content.Substring (0, pos);
content = content.Substring (pos);
len = content.Length;
pos = 0;
while (pos < len) {
//skip spaces
while (content [pos] == ' ' && pos < len)
pos ++;
int eq_pos = content.IndexOf ('=', pos);
string key = content.Substring (pos, eq_pos - pos).Trim ();
pos = eq_pos + 1;
int start_quote = content.IndexOf ('"', pos);
int end_quote = content.IndexOf ('"', start_quote + 1);
string val = content.Substring (start_quote + 1, end_quote - start_quote - 1).Trim ();
pos = end_quote + 1;
table [key.ToUpper ()] = val;
}
return table;
}
}
}
|