--- /dev/null
+//
+// System.Web.Compilation.AspElements
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Text;
+using System.Web.UI;
+using System.Web.UI.HtmlControls;
+using System.Web.UI.WebControls;
+
+namespace System.Web.Compilation
+{
+
+ public enum ElementType
+ {
+ TAG,
+ PLAINTEXT
+ }
+
+ public abstract class Element
+ {
+ private ElementType elementType;
+
+ public Element (ElementType type)
+ {
+ elementType = type;
+ }
+
+ public ElementType GetElementType
+ {
+ get { return elementType; }
+ }
+ } // class Element
+
+ public class PlainText : Element
+ {
+ private StringBuilder text;
+
+ public PlainText () : base (ElementType.PLAINTEXT)
+ {
+ text = new StringBuilder ();
+ }
+
+ public PlainText (StringBuilder text) : base (ElementType.PLAINTEXT)
+ {
+ this.text = text;
+ }
+
+ public PlainText (string text) : this ()
+ {
+ this.text.Append (text);
+ }
+
+ public void Append (string more)
+ {
+ text.Append (more);
+ }
+
+ public string Text
+ {
+ get { return text.ToString (); }
+ }
+
+ public override string ToString ()
+ {
+ return "PlainText: " + Text;
+ }
+ }
+
+ public enum TagType
+ {
+ DIRECTIVE,
+ HTML,
+ HTMLCONTROL,
+ SERVERCONTROL,
+ INLINEVAR,
+ INLINECODE,
+ CLOSING,
+ SERVEROBJECT,
+ PROPERTYTAG,
+ CODERENDER,
+ DATABINDING,
+ NOTYET
+ }
+
+ /*
+ * Attributes and values are stored in a couple of ArrayList in Add ().
+ * When MakeHash () is called, they are converted to a Hashtable. If there are any
+ * attributes duplicated it throws an ArgumentException.
+ *
+ * The [] operator works with the Hashtable if the values are in it, otherwise
+ * it uses the ArrayList's.
+ *
+ * Why? You can have a tag in HTML like <a att="value" att="xxx">, but not in tags
+ * marked runat=server and Hashtable requires the key to be unique.
+ *
+ */
+ public class TagAttributes
+ {
+ private Hashtable atts_hash;
+ private ArrayList keys;
+ private ArrayList values;
+ private bool got_hashed;
+
+ public TagAttributes ()
+ {
+ got_hashed = false;
+ keys = new ArrayList ();
+ values = new ArrayList ();
+ }
+
+ private void MakeHash ()
+ {
+ atts_hash = new Hashtable (new CaseInsensitiveHashCodeProvider (),
+ new CaseInsensitiveComparer ());
+ for (int i = 0; i < keys.Count; i++)
+ atts_hash.Add (keys [i], values [i]);
+ got_hashed = true;
+ keys = null;
+ values = null;
+ }
+
+ public bool IsRunAtServer ()
+ {
+ return got_hashed;
+ }
+
+ public void Add (object key, object value)
+ {
+ if (key != null && value != null &&
+ 0 == String.Compare ((string) key, "runat", true) &&
+ 0 == String.Compare ((string) value, "server", true))
+ MakeHash ();
+
+ if (got_hashed)
+ atts_hash.Add (key, value);
+ else {
+ keys.Add (key);
+ values.Add (value);
+ }
+ }
+
+ public ICollection Keys
+ {
+ get { return (got_hashed ? atts_hash.Keys : keys); }
+ }
+
+ private int CaseInsensitiveSearch (string key)
+ {
+ // Hope not to have many attributes when the tag is not a server tag...
+ for (int i = 0; i < keys.Count; i++){
+ if (0 == String.Compare ((string) keys [i], key, true))
+ return i;
+ }
+ return -1;
+ }
+
+ public object this [object key]
+ {
+ get {
+ if (got_hashed)
+ return atts_hash [key];
+
+ int idx = CaseInsensitiveSearch ((string) key);
+ if (idx == -1)
+ return null;
+
+ return values [idx];
+ }
+
+ set {
+ if (got_hashed)
+ atts_hash [key] = value;
+ else {
+ int idx = CaseInsensitiveSearch ((string) key);
+ keys [idx] = value;
+ }
+ }
+ }
+
+ public int Count
+ {
+ get { return (got_hashed ? atts_hash.Count : keys.Count);}
+ }
+
+ public bool IsDataBound (string att)
+ {
+ if (att == null || !got_hashed)
+ return false;
+
+ return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
+ }
+
+ public override string ToString ()
+ {
+ string ret = "";
+ string value;
+ foreach (string key in Keys){
+ value = (string) this [key];
+ value = value == null ? "" : value;
+ ret += key + "=" + value + " ";
+ }
+
+ return ret;
+ }
+ }
+
+ public class Tag : Element
+ {
+ protected string tag;
+ protected TagType tagType;
+ protected TagAttributes attributes;
+ protected bool self_closing;
+ protected bool hasDefaultID;
+ private static int ctrlNumber = 1;
+
+ internal Tag (Tag other) :
+ this (other.tag, other.attributes, other.self_closing)
+ {
+ this.tagType = other.tagType;
+ }
+
+ public Tag (string tag, TagAttributes attributes, bool self_closing) :
+ base (ElementType.TAG)
+ {
+ if (tag == null)
+ throw new ArgumentNullException ();
+
+ this.tag = tag;
+ this.attributes = attributes;
+ this.tagType = TagType.NOTYET;
+ this.self_closing = self_closing;
+ this.hasDefaultID = false;
+ }
+
+ public string TagID
+ {
+ get { return tag; }
+ }
+
+ public TagType TagType
+ {
+ get { return tagType; }
+ }
+
+ public bool SelfClosing
+ {
+ get { return self_closing; }
+ }
+
+ public TagAttributes Attributes
+ {
+ get { return attributes; }
+ }
+
+ public string PlainHtml
+ {
+ get {
+ StringBuilder plain = new StringBuilder ();
+ plain.Append ('<');
+ if (tagType == TagType.CLOSING)
+ plain.Append ('/');
+ plain.Append (tag);
+ if (attributes != null){
+ plain.Append (' ');
+ foreach (string key in attributes.Keys){
+ plain.Append (key);
+ if (attributes [key] != null){
+ plain.Append ("=\"");
+ plain.Append ((string) attributes [key]);
+ plain.Append ("\" ");
+ }
+ }
+ }
+
+ if (self_closing)
+ plain.Append ('/');
+ plain.Append ('>');
+ return plain.ToString ();
+ }
+ }
+
+ public override string ToString ()
+ {
+ return TagID + " " + Attributes + " " + self_closing;
+ }
+
+ public bool HasDefaultID
+ {
+ get { return hasDefaultID; }
+ }
+
+ protected void SetNewID ()
+ {
+ if (attributes == null)
+ attributes = new TagAttributes ();
+ attributes.Add ("ID", GetDefaultID ());
+ hasDefaultID = true;
+ }
+
+ public static string GetDefaultID ()
+ {
+ return "_control" + ctrlNumber++;
+ }
+ }
+
+ public class CloseTag : Tag
+ {
+ public CloseTag (string tag) : base (tag, null, false)
+ {
+ tagType = TagType.CLOSING;
+ }
+ }
+
+ public class Directive : Tag
+ {
+ private static Hashtable directivesHash;
+ private static string [] page_atts = { "AspCompat", "AutoEventWireup ", "Buffer",
+ "ClassName", "ClientTarget", "CodePage",
+ "CompilerOptions", "ContentType", "Culture", "Debug",
+ "Description", "EnableSessionState", "EnableViewState",
+ "EnableViewStateMac", "ErrorPage", "Explicit",
+ "Inherits", "Language", "LCID", "ResponseEncoding",
+ "Src", "SmartNavigation", "Strict", "Trace",
+ "TraceMode", "Transaction", "UICulture",
+ "WarningLevel" };
+
+ private static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
+ "Debug", "Description", "EnableViewState",
+ "Explicit", "Inherits", "Language", "Strict", "Src",
+ "WarningLevel" };
+
+ private static string [] import_atts = { "namespace" };
+ private static string [] implements_atts = { "interface" };
+ private static string [] assembly_atts = { "name", "src" };
+ private static string [] register_atts = { "tagprefix", "tagname", "Namespace",
+ "Src", "Assembly" };
+
+ private static string [] outputcache_atts = { "Duration", "Location", "VaryByControl",
+ "VaryByCustom", "VaryByHeader", "VaryByParam" };
+ private static string [] reference_atts = { "page", "control" };
+
+ static Directive ()
+ {
+ InitHash ();
+ }
+
+ private static void InitHash ()
+ {
+ CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider ();
+ CaseInsensitiveComparer comparer = new CaseInsensitiveComparer ();
+
+ directivesHash = new Hashtable (provider, comparer);
+
+ // Use Hashtable 'cause is O(1) in Contains (ArrayList is O(n))
+ Hashtable valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in page_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("PAGE", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in control_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("CONTROL", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in import_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("IMPORT", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in implements_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("IMPLEMENTS", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in register_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("REGISTER", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in assembly_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("ASSEMBLY", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in outputcache_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("OUTPUTCACHE", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in reference_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("REFERENCE", valid_attributes);
+ }
+
+ public Directive (string tag, TagAttributes attributes) :
+ base (tag, attributes, true)
+ {
+ CheckAttributes ();
+ tagType = TagType.DIRECTIVE;
+ }
+
+ private void CheckAttributes ()
+ {
+ Hashtable atts;
+ if (!(directivesHash [tag] is Hashtable))
+ throw new ApplicationException ("Unknown directive: " + tag);
+
+ atts = (Hashtable) directivesHash [tag];
+ foreach (string att in attributes.Keys){
+ if (!atts.Contains (att))
+ throw new ApplicationException ("Attribute " + att +
+ " not valid for tag " + tag);
+ }
+ }
+
+ public static bool IsDirectiveID (string id)
+ {
+ return directivesHash.Contains (id);
+ }
+
+ public override string ToString ()
+ {
+ return "Directive: " + tag;
+ }
+ }
+
+ public class ServerObjectTag : Tag
+ {
+ public ServerObjectTag (Tag tag) :
+ base (tag.TagID, tag.Attributes, tag.SelfClosing)
+ {
+ tagType = TagType.SERVEROBJECT;
+ if (!attributes.IsRunAtServer ())
+ throw new ApplicationException ("<object> without runat=server");
+
+ if (attributes.Count != 3 || !SelfClosing || ObjectID == null || ObjectClass == null)
+ throw new ApplicationException ("Incorrect syntax: <object id=\"name\" " +
+ "class=\"full.class.name\" runat=\"server\" />");
+ }
+
+ public string ObjectID
+ {
+ get { return (string) attributes ["id"]; }
+ }
+
+ public string ObjectClass
+ {
+ get { return (string) attributes ["class"]; }
+ }
+ }
+
+ public class HtmlControlTag : Tag
+ {
+ private Type control_type;
+ private bool is_container;
+
+ private static Hashtable controls;
+ private static Hashtable inputTypes;
+
+ private static void InitHash ()
+ {
+ controls = new Hashtable (new CaseInsensitiveHashCodeProvider (),
+ new CaseInsensitiveComparer ());
+
+ controls.Add ("A", typeof (HtmlAnchor));
+ controls.Add ("BUTTON", typeof (HtmlButton));
+ controls.Add ("FORM", typeof (HtmlForm));
+ controls.Add ("IMG", typeof (HtmlImage));
+ controls.Add ("INPUT", "INPUT");
+ controls.Add ("SELECT", typeof (HtmlSelect));
+ controls.Add ("TABLE", typeof (HtmlTable));
+ controls.Add ("TD", typeof (HtmlTableCell));
+ controls.Add ("TH", typeof (HtmlTableCell));
+ controls.Add ("TR", typeof (HtmlTableRow));
+ controls.Add ("TEXTAREA", typeof (HtmlTextArea));
+
+ inputTypes = new Hashtable (new CaseInsensitiveHashCodeProvider (),
+ new CaseInsensitiveComparer ());
+
+ inputTypes.Add ("BUTTON", typeof (HtmlInputButton));
+ inputTypes.Add ("SUBMIT", typeof (HtmlInputButton));
+ inputTypes.Add ("RESET", typeof (HtmlInputButton));
+ inputTypes.Add ("CHECKBOX", typeof (HtmlInputCheckBox));
+ inputTypes.Add ("FILE", typeof (HtmlInputFile));
+ inputTypes.Add ("HIDDEN", typeof (HtmlInputHidden));
+ inputTypes.Add ("IMAGE", typeof (HtmlInputImage));
+ inputTypes.Add ("RADIO", typeof (HtmlInputRadioButton));
+ inputTypes.Add ("TEXT", typeof (HtmlInputText));
+ inputTypes.Add ("PASSWORD", typeof (HtmlInputText));
+ }
+
+ static HtmlControlTag ()
+ {
+ InitHash ();
+ }
+
+ public HtmlControlTag (string tag, TagAttributes attributes, bool self_closing) :
+ base (tag, attributes, self_closing)
+ {
+ SetData ();
+ if (attributes == null || attributes ["ID"] == null)
+ SetNewID ();
+ }
+
+ public HtmlControlTag (Tag source_tag) :
+ this (source_tag.TagID, source_tag.Attributes, source_tag.SelfClosing)
+ {
+ }
+
+ private void SetData ()
+ {
+ tagType = TagType.HTMLCONTROL;
+ if (!(controls [tag] is string)){
+ control_type = (Type) controls [tag];
+ if (control_type == null)
+ control_type = typeof (HtmlGenericControl);
+ is_container = (0 != String.Compare (tag, "img", true));
+ } else {
+ string type_value = (string) attributes ["TYPE"];
+ if (type_value== null)
+ throw new ArgumentException ("INPUT tag without TYPE attribute!!!");
+
+ control_type = (Type) inputTypes [type_value];
+ //TODO: what does MS with this one?
+ if (control_type == null)
+ throw new ArgumentException ("Unknown input type -> " + type_value);
+ is_container = false;
+ self_closing = true; // All <input ...> are self-closing
+ }
+ }
+
+ public Type ControlType
+ {
+ get { return control_type; }
+ }
+
+ public string ControlID
+ {
+ get { return (string) attributes ["ID"]; }
+ }
+
+ public bool IsContainer
+ {
+ get { return is_container; }
+ }
+
+ public override string ToString ()
+ {
+ string ret = "HtmlControlTag: " + tag + " Name: " + ControlID + "Type:" +
+ control_type.ToString () + "\n\tAttributes:\n";
+
+ foreach (string key in attributes.Keys){
+ ret += "\t" + key + "=" + attributes [key];
+ }
+ return ret;
+ }
+ }
+
+ public enum ChildrenKind
+ {
+ NONE,
+ /*
+ * Children must be ASP.NET server controls. Literal text is passed as LiteralControl.
+ * Child controls and text are added using AddParsedSubObject ().
+ */
+ CONTROLS,
+ /*
+ * Children must correspond to properties of the parent control. No literal text allowed.
+ */
+ PROPERTIES,
+ /*
+ * Special case used inside <columns>...</columns>
+ * Only allow DataGridColumn and derived classes.
+ */
+ DBCOLUMNS,
+ /*
+ * Special case for list controls (ListBox, DropDownList...)
+ */
+ LISTITEM,
+ /* For HtmlSelect children. They are <option> tags that must
+ * be treated as ListItem
+ */
+ OPTION
+ }
+
+ // TODO: support for ControlBuilderAttribute that may be used in custom controls
+ public class Component : Tag
+ {
+ private Type type;
+ private string alias;
+ private string control_type;
+ private bool is_close_tag;
+ private bool allow_children;
+ private ChildrenKind children_kind;
+ private string defaultPropertyName;
+
+ private ChildrenKind GuessChildrenKind (Type type)
+ {
+ object [] custom_atts = type.GetCustomAttributes (true);
+ foreach (object custom_att in custom_atts){
+ if (custom_att is ParseChildrenAttribute){
+ /* FIXME
+ * When adding full support for custom controls, we gotta
+ * bear in mind the pca.DefaultProperty value
+ */
+ ParseChildrenAttribute pca = custom_att as ParseChildrenAttribute;
+ defaultPropertyName = pca.DefaultProperty;
+ /* this property will be true for all controls derived from
+ * WebControls. */
+ if (pca.ChildrenAsProperties == false)
+ return ChildrenKind.CONTROLS;
+ else if (defaultPropertyName == "")
+ return ChildrenKind.PROPERTIES;
+ else
+ return ChildrenKind.LISTITEM;
+ }
+ }
+
+ return ChildrenKind.NONE;
+ }
+
+ private static bool GuessAllowChildren (Type type)
+ {
+ PropertyInfo controls = type.GetProperty ("Controls");
+ if (controls == null)
+ return false;
+ MethodInfo getm = controls.GetGetMethod ();
+ object control_instance = Activator.CreateInstance (type);
+ object control_collection = getm.Invoke (control_instance, null);
+ return (!(control_collection is System.Web.UI.EmptyControlCollection));
+ }
+
+ public Component (Tag input_tag, Type type) :
+ base (input_tag)
+ {
+ tagType = TagType.SERVERCONTROL;
+ this.is_close_tag = input_tag is CloseTag;
+ this.type = type;
+ this.defaultPropertyName = "";
+ this.allow_children = GuessAllowChildren (type);
+ if (input_tag.SelfClosing)
+ this.children_kind = ChildrenKind.NONE;
+ else if (type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
+ type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
+ this.children_kind = ChildrenKind.PROPERTIES;
+ else if (type == typeof (System.Web.UI.WebControls.ListItem))
+ this.children_kind = ChildrenKind.CONTROLS;
+ else
+ this.children_kind = GuessChildrenKind (type);
+
+ int pos = input_tag.TagID.IndexOf (':');
+ alias = tag.Substring (0, pos);
+ control_type = tag.Substring (pos + 1);
+ if (attributes == null || attributes ["ID"] == null)
+ SetNewID ();
+ }
+
+ public Type ComponentType
+ {
+ get { return type; }
+ }
+
+ public string ControlID
+ {
+ get { return (string) attributes ["ID"]; }
+ }
+
+ public bool IsCloseTag
+ {
+ get { return is_close_tag; }
+ }
+
+ public bool AllowChildren
+ {
+ get { return allow_children; }
+ }
+
+ public ChildrenKind ChildrenKind
+ {
+ get { return children_kind; }
+ }
+
+ public string DefaultPropertyName
+ {
+ get { return defaultPropertyName; }
+ }
+
+
+ public override string ToString ()
+ {
+ return type.ToString () + " Alias: " + alias + " ID: " + (string) attributes ["id"];
+ }
+ }
+
+ public class PropertyTag : Tag
+ {
+ private Type type;
+ private string name;
+
+ public PropertyTag (Tag tag, Type type, string name)
+ : base (tag)
+ {
+ tagType = TagType.PROPERTYTAG;
+ SetNewID ();
+ this.name = name;
+ this.type = type;
+ }
+
+ public Type PropertyType
+ {
+ get { return type; }
+ }
+
+ public string PropertyID
+ {
+ get { return (string) attributes ["ID"]; }
+ }
+
+ public string PropertyName
+ {
+ get { return name; }
+ }
+ }
+
+ public class CodeRenderTag : Tag
+ {
+ private string code;
+ private bool isVarName;
+
+ public CodeRenderTag (bool isVarName, string code) : base ("", null, false)
+ {
+ tagType = TagType.CODERENDER;
+ this.isVarName = isVarName;
+ this.code = code.Trim ();
+ }
+
+ public string Code
+ {
+ get { return code; }
+ }
+
+ public bool IsVarName
+ {
+ get { return isVarName; }
+ }
+
+ public string AsText
+ {
+ get { return "<%" + (IsVarName ? "=" : "") + Code + "%>"; }
+ }
+ }
+
+ public class DataBindingTag : Tag
+ {
+ private string data;
+
+ public DataBindingTag (string data) : base ("", null, false)
+ {
+ tagType = TagType.DATABINDING;
+ this.data = data.Trim ();
+ }
+
+ public string Data
+ {
+ get { return data; }
+ }
+
+ public string AsText
+ {
+ get { return "<%#" + Data + "%>"; }
+ }
+ }
+}
+
--- /dev/null
+//
+// System.Web.Compilation.AspParser
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+namespace System.Web.Compilation
+{
+ class AspParser {
+ private AspTokenizer tokenizer;
+ private ArrayList elements; // List of processed elements in the HTML page.
+
+ private void error ()
+ {
+ Console.WriteLine ("Error: " + tokenizer.location);
+ Environment.Exit (-1); //FIXME
+ }
+
+ private void error (string msg)
+ {
+ Console.WriteLine ("Error: "+ msg + "\n" + tokenizer.location);
+ Environment.Exit (-1); //FIXME
+ }
+
+ public AspParser (AspTokenizer tokenizer)
+ {
+ this.tokenizer = tokenizer;
+ elements = new ArrayList ();
+ }
+
+ public AspParser (string filename, Stream input) :
+ this (new AspTokenizer (filename, input))
+ {
+ }
+
+ public ArrayList Elements
+ {
+ get { return elements; }
+ }
+
+ private bool Eat (int expected_token)
+ {
+ if (tokenizer.get_token () != expected_token) {
+ tokenizer.put_back ();
+ return false;
+ }
+ return true;
+ }
+
+ private void AddPlainText (string newText)
+ {
+ if (elements.Count > 0){
+ Element element = (Element) elements [elements.Count - 1];
+ if (element is PlainText){
+ ((PlainText) element).Append (newText);
+ return;
+ }
+ }
+ elements.Add (new PlainText (newText));
+ }
+
+ public void Parse ()
+ {
+ int token;
+ Element element;
+ Tag tag_element;
+ string tag = "";
+
+ while ((token = tokenizer.get_token ()) != Token.EOF){
+ if (tokenizer.Verbatim){
+ string end_verbatim = "</" + tag + ">";
+ string verbatim_text = GetVerbatim (token, end_verbatim);
+
+ if (verbatim_text == null)
+ error ("Unexpected EOF processing " + tag);
+
+ AddPlainText (verbatim_text);
+ elements.Add (new CloseTag (tag));
+ tokenizer.Verbatim = false;
+ }
+ else if (token == '<'){
+ element = GetTag ();
+ if (element == null)
+ error ();
+ if (!(element is Tag)){
+ AddPlainText (((PlainText) element).Text);
+ continue;
+ }
+
+ elements.Add (element);
+
+ tag_element = element as Tag;
+ tag = tag_element.TagID.ToUpper ();
+ if (!tag_element.SelfClosing && (tag == "SCRIPT" || tag == "PRE"))
+ tokenizer.Verbatim = true;
+ }
+ else {
+ StringBuilder text = new StringBuilder ();
+ do {
+ text.Append (tokenizer.value);
+ token = tokenizer.get_token ();
+ } while (token != '<' && token != Token.EOF);
+ tokenizer.put_back ();
+ AddPlainText (text.ToString ());
+ }
+ }
+ }
+
+ private Element GetTag ()
+ {
+ int token = tokenizer.get_token ();
+ string id;
+ TagAttributes attributes;
+
+ switch (token){
+ case '%':
+ if (Eat ('@')){
+ id = (Eat (Token.DIRECTIVE) ? tokenizer.value : "Page");
+ attributes = GetAttributes ();
+ if (!Eat ('%') || !Eat ('>'))
+ error ("expecting '%>'");
+
+ return new Directive (id, attributes);
+ }
+
+ bool varname = Eat ('=');
+ bool databinding = !varname && Eat ('#');
+ tokenizer.Verbatim = true;
+ string inside_tags = GetVerbatim (tokenizer.get_token (), "%>");
+ tokenizer.Verbatim = false;
+ if (databinding)
+ return new DataBindingTag (inside_tags);
+ return new CodeRenderTag (varname, inside_tags);
+ case '/':
+ if (!Eat (Token.IDENTIFIER))
+ error ("expecting TAGNAME");
+ id = tokenizer.value;
+ if (!Eat ('>'))
+ error ("expecting '>'");
+ return new CloseTag (id);
+ case '!':
+ bool double_dash = Eat (Token.DOUBLEDASH);
+ if (double_dash)
+ tokenizer.put_back ();
+
+ tokenizer.Verbatim = true;
+ string end = double_dash ? "-->" : ">";
+ string comment = GetVerbatim (tokenizer.get_token (), end);
+ tokenizer.Verbatim = false;
+ if (comment == null)
+ error ("Unfinished HTML comment/DTD");
+
+ return new PlainText ("<!" + comment + end);
+ case Token.IDENTIFIER:
+ id = tokenizer.value;
+ Tag tag = new Tag (id, GetAttributes (), Eat ('/'));
+ if (!Eat ('>'))
+ error ("expecting '>'");
+ return tag;
+ default:
+ return null;
+ }
+ }
+
+ private TagAttributes GetAttributes ()
+ {
+ int token;
+ TagAttributes attributes;
+ string id;
+
+ attributes = new TagAttributes ();
+ while ((token = tokenizer.get_token ()) != Token.EOF){
+ if (token != Token.IDENTIFIER)
+ break;
+ id = tokenizer.value;
+ if (Eat ('=')){
+ if (Eat (Token.ATTVALUE)){
+ attributes.Add (id, tokenizer.value);
+ } else {
+ //TODO: support data binding syntax without quotes
+ error ("expected ATTVALUE");
+ return null;
+ }
+
+ } else {
+ attributes.Add (id, null);
+ }
+ }
+
+ tokenizer.put_back ();
+ if (attributes.Count == 0)
+ return null;
+
+ return attributes;
+ }
+
+ private string GetVerbatim (int token, string end)
+ {
+ StringBuilder vb_text = new StringBuilder ();
+ int i = 0;
+
+ if (tokenizer.value.Length > 1){
+ // May be we have a put_back token that is not a single character
+ vb_text.Append (tokenizer.value);
+ token = tokenizer.get_token ();
+ }
+
+ while (token != Token.EOF){
+ if (Char.ToUpper ((char) token) == end [i]){
+ if (++i >= end.Length)
+ break;
+ token = tokenizer.get_token ();
+ continue;
+ }
+ else {
+ for (int j = 0; j < i; j++)
+ vb_text.Append (end [j]);
+ }
+
+ i = 0;
+ vb_text.Append ((char) token);
+ token = tokenizer.get_token ();
+ }
+
+ if (token == Token.EOF)
+ return null;
+
+ return vb_text.ToString ();
+ }
+ }
+
+}
+
--- /dev/null
+//
+// System.Web.Compilation.AspTokenizer
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+namespace System.Web.Compilation {
+
+ class Token
+ {
+ public const int EOF = 0;
+ public const int IDENTIFIER = 1000;
+ public const int DIRECTIVE = 1001;
+ public const int ATTVALUE = 1002;
+ public const int TEXT = 1003;
+ public const int DOUBLEDASH = 1004;
+ public const int CLOSING = 1005;
+ }
+
+ class AspTokenizer {
+ private StreamReader sr;
+ private int current_token;
+ private StringBuilder sb;
+ private int col, line;
+ private bool inTag;
+ private bool hasPutBack;
+ private bool verbatim;
+ private string filename;
+
+ public AspTokenizer (string filename, Stream stream)
+ {
+ if (filename == null || stream == null)
+ throw new ArgumentNullException ();
+
+ this.sr = new StreamReader (stream);
+ this.filename = filename;
+ sb = new StringBuilder ();
+ col = line = 1;
+ hasPutBack = inTag = false;
+ }
+
+ public bool Verbatim
+ {
+ get { return verbatim; }
+ set { verbatim = value; }
+ }
+
+ public void put_back ()
+ {
+ if (hasPutBack)
+ throw new ApplicationException ("put_back called twice!");
+
+ hasPutBack = true;
+ }
+
+ public int get_token ()
+ {
+ if (hasPutBack){
+ hasPutBack = false;
+ return current_token;
+ }
+
+ current_token = NextToken ();
+ return current_token;
+ }
+
+ bool is_identifier_start_character (char c)
+ {
+ return (Char.IsLetter (c) || c == '_' );
+ }
+
+ bool is_identifier_part_character (char c)
+ {
+ return (Char.IsLetterOrDigit (c) || c == '_' || c == '-');
+ }
+
+ private int read_char ()
+ {
+ int c = sr.Read ();
+
+ if (c == '\r' && sr.Peek () == '\n')
+ c = sr.Read ();
+
+ if (c == '\n'){
+ col = 0;
+ line++;
+ }
+ else if (c != -1)
+ col++;
+
+ return c;
+ }
+
+ private int NextToken ()
+ {
+ int c;
+
+ sb.Length = 0;
+ while ((c = read_char ()) != -1){
+ if (verbatim){
+ inTag = false;
+ sb.Append ((char) c);
+ return c;
+ }
+
+ if (inTag && (c == '"' || c == '\'')){
+ int previous;
+ int start = c;
+
+ previous = 0;
+ while ((c = sr.Peek ()) != -1) {
+ if (c == start && previous != '\\'){
+ read_char ();
+ break;
+ }
+ sb.Append ((char) read_char ());
+ previous = c;
+ }
+
+ return Token.ATTVALUE;
+ }
+
+ if (c == '<'){
+ inTag = true;
+ sb.Append ((char) c);
+ return c;
+ }
+
+ if (c == '>'){
+ inTag = false;
+ sb.Append ((char) c);
+ return c;
+ }
+
+ if (current_token == '<' && "%/!".IndexOf ((char) c) != -1){
+ sb.Append ((char) c);
+ return c;
+ }
+
+ if (inTag && current_token == '%' && "@#=".IndexOf ((char) c) != -1){
+ sb.Append ((char) c);
+ return c;
+ }
+
+ if (inTag && c == '-' && sr.Peek () == '-'){
+ sb.Append ("--");
+ read_char ();
+ return Token.DOUBLEDASH;
+ }
+
+ if (!inTag){
+ sb.Append ((char) c);
+ while ((c = sr.Peek ()) != -1 && c != '<')
+ sb.Append ((char) read_char ());
+
+ return (c != -1 || sb.Length > 0) ? Token.TEXT : Token.EOF;
+ }
+
+ if (inTag && current_token == '=' && !Char.IsWhiteSpace ((char) c)){
+ sb.Append ((char) c);
+ while ((c = sr.Peek ()) != -1) {
+ if (Char.IsWhiteSpace ((char) c) || c == '/' || c == '>')
+ break;
+ sb.Append ((char) read_char ());
+ }
+
+ return Token.ATTVALUE;
+ }
+
+ if (inTag && is_identifier_start_character ((char) c)){
+ sb.Append ((char) c);
+ while ((c = sr.Peek ()) != -1) {
+ if (!is_identifier_part_character ((char) c) && c != ':')
+ break;
+ sb.Append ((char) read_char ());
+ }
+
+ if (current_token == '@' && Directive.IsDirectiveID (sb.ToString ()))
+ return Token.DIRECTIVE;
+
+ return Token.IDENTIFIER;
+ }
+
+ if (!Char.IsWhiteSpace ((char) c))
+ return c;
+ }
+
+ return Token.EOF;
+ }
+
+ public string value
+ {
+ get { return sb.ToString (); }
+ }
+
+ public string location
+ {
+ get {
+ string msg = filename;
+ msg += " (" + line + ", " + col + "): " + sb.ToString ();
+ return msg;
+ }
+ }
+
+ }
+}
+
+2002-08-16 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * AspElements.cs:
+ * AspParser.cs:
+ * AspTokenizer.cs:
+ * ChangeLog:
+ * PageCompiler.cs:
+ * TemplateFactory.cs: first steps to move xsp into System.Web.
+
--- /dev/null
+//
+// System.Web.Compilation.PageCompiler
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.Web.UI;
+
+namespace System.Web.Compilation
+{
+ class PageCompiler
+ {
+ private PageParser pageParser;
+
+ internal PageCompiler (PageParser pageParser)
+ {
+ this.pageParser = pageParser;
+ }
+
+ public static Type CompilePageType (PageParser pageParser)
+ {
+ return TemplateFactory.GetTypeFromSource (pageParser.InputFile);
+ }
+ }
+}
--- /dev/null
+//\r
+// System.Web.Compilation.TemplateFactory\r
+//\r
+// Authors:\r
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
+//\r
+// (C) 2002 Ximian, Inc (http://www.ximian.com)\r
+//\r
+using System;\r
+using System.Collections;\r
+using System.Diagnostics;\r
+using System.IO;\r
+using System.Reflection;\r
+using System.Text;\r
+using System.Web.UI;\r
+\r
+namespace System.Web.Compilation\r
+{\r
+ class TemplateFactory\r
+ {\r
+ internal class PageBuilder\r
+ {\r
+ private StringBuilder cscOptions;\r
+ private string fileName;\r
+ private string csFileName;\r
+ private string className;\r
+ public static char dirSeparator = Path.DirectorySeparatorChar;\r
+ private static Hashtable cachedData = new Hashtable ();\r
+ private static Random rnd_file = new Random ();\r
+\r
+ private PageBuilder ()\r
+ {\r
+ }\r
+\r
+ internal PageBuilder (string fileName)\r
+ {\r
+ this.fileName = fileName;\r
+ csFileName = "xsp_" + Path.GetFileName (fileName).Replace (".aspx", ".cs");\r
+\r
+ cscOptions = new StringBuilder ();\r
+ cscOptions.Append ("--target library ");\r
+ cscOptions.Append ("-L . ");\r
+ AddReference ("corlib");\r
+ AddReference ("System");\r
+ AddReference ("System.Data");\r
+ AddReference ("System.Web");\r
+ AddReference ("System.Drawing");\r
+ }\r
+\r
+ internal Type Build ()\r
+ {\r
+ string dll;\r
+ if (Xsp (fileName, csFileName) == false){\r
+ Console.WriteLine ("Error running xsp. " + \r
+ "Take a look at the output file.");\r
+ return null;\r
+ }\r
+\r
+ StreamReader st_file = new StreamReader (File.OpenRead ("output" +\r
+ dirSeparator +\r
+ csFileName));\r
+ \r
+ StringReader file_content = new StringReader (st_file.ReadToEnd ());\r
+ st_file.Close ();\r
+ if (GetBuildOptions (file_content) == false)\r
+ return null;\r
+\r
+ dll = "output" + dirSeparator;\r
+ dll += rnd_file.Next () + Path.GetFileName (fileName).Replace (".aspx", ".dll");\r
+ if (Compile (csFileName, dll) == true){\r
+ Assembly assembly = Assembly.LoadFrom (dll);\r
+ Type type = assembly.GetType ("ASP." + className);\r
+ return type;\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+ private static bool Xsp (string fileName, string csFileName)\r
+ {\r
+ return RunProcess ("mono", \r
+ "xsp.exe " + fileName, \r
+ GeneratedXspFileName (fileName),\r
+ "output" + dirSeparator + "xsp_" + Path.GetFileName (fileName) + \r
+ ".sh");\r
+ }\r
+\r
+ private static bool RunProcess (string exe, string arguments, string output_file, string script_file)\r
+ {\r
+ Console.WriteLine ("{0} {1}", exe, arguments);\r
+ Console.WriteLine ("Output goes to {0}", output_file);\r
+ Console.WriteLine ("Script file is {0}", script_file);\r
+ Process proc = new Process ();\r
+\r
+ proc.StartInfo.FileName = "redirector.sh";\r
+ proc.StartInfo.Arguments = exe + " " + output_file + " " + arguments;\r
+ proc.Start ();\r
+ proc.WaitForExit ();\r
+ int result = proc.ExitCode;\r
+ proc.Close ();\r
+\r
+ StreamWriter bat_output = new StreamWriter (File.Create (script_file));\r
+ bat_output.Write ("redirector.sh" + " " + exe + " " + output_file + " " + arguments);\r
+ bat_output.Close ();\r
+/*\r
+ * Use this code when redirection works properly\r
+ *\r
+ proc.StartInfo.FileName = exe;\r
+ proc.StartInfo.Arguments = arguments;\r
+ proc.StartInfo.UseShellExecute = false;\r
+ proc.StartInfo.RedirectStandardOutput = true;\r
+ proc.Start ();\r
+ string poutput = proc.StandardOutput.ReadToEnd();\r
+ proc.WaitForExit ();\r
+ int result = proc.ExitCode;\r
+ proc.Close ();\r
+\r
+ StreamWriter cmd_output = new StreamWriter (File.Create (output_file));\r
+ cmd_output.Write (poutput);\r
+ cmd_output.Close ();\r
+ StreamWriter bat_output = new StreamWriter (File.Create (script_file));\r
+ bat_output.Write (exe + " " + arguments);\r
+ bat_output.Close ();\r
+*/\r
+\r
+ return (result == 0);\r
+ }\r
+\r
+ private bool GetBuildOptions (StringReader genCode)\r
+ {\r
+ string line;\r
+ string dll;\r
+\r
+ while ((line = genCode.ReadLine ()) != String.Empty) {\r
+ if (line.StartsWith ("//<class ")){\r
+ className = GetAttributeValue (line, "name");\r
+ } else if (line.StartsWith ("//<compileandreference ")) {\r
+ string src = GetAttributeValue (line, "src");\r
+ dll = src.Replace (".cs", ".dll"); //FIXME\r
+ //File.Delete (dll);\r
+ if (Compile (src, dll) == false){\r
+ Console.WriteLine ("Error compiling {0}. See the output file.", src);\r
+ return false;\r
+ }\r
+ AddReference (dll.Replace (".dll", ""));\r
+ } else if (line.StartsWith ("//<reference ")) {\r
+ dll = GetAttributeValue (line, "dll");\r
+ AddReference (dll);\r
+ } else if (line.StartsWith ("//<compileroptions ")) {\r
+ string options = GetAttributeValue (line, "options");\r
+ cscOptions.Append (" " + options + " ");\r
+ } else {\r
+ Console.WriteLine ("This is the build option line i get:\n" + line);\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ private void AddReference (string reference)\r
+ {\r
+ string arg = String.Format ("/r:{0} ", reference);\r
+ cscOptions.Append (arg);\r
+ }\r
+ \r
+ private string GetAttributeValue (string line, string att)\r
+ {\r
+ string att_start = att + "=\"";\r
+ int begin = line.IndexOf (att_start);\r
+ int end = line.Substring (begin + att_start.Length).IndexOf ('"');\r
+ if (begin == -1 || end == -1)\r
+ throw new ApplicationException ("Error in reference option:\n" + line);\r
+\r
+ return line.Substring (begin + att_start.Length, end);\r
+ }\r
+ \r
+ private bool Compile (string csName, string dllName)\r
+ {\r
+ cscOptions.AppendFormat ("/out:{0} ", dllName);\r
+ cscOptions.Append ("output" + dirSeparator + csName);\r
+\r
+ string cmdline = cscOptions.ToString ();\r
+ string noext = csName.Replace (".cs", "");\r
+ string output_file = "output" + dirSeparator + "output_from_compilation_" + noext + ".txt";\r
+ string bat_file = "output" + dirSeparator + "last_compilation_" + noext + ".bat";\r
+ return RunProcess ("mcs", cmdline, output_file, bat_file);\r
+ }\r
+ }\r
+\r
+ internal static string CompilationOutputFileName (string fileName)\r
+ {\r
+ string name = "xsp_" + Path.GetFileName (fileName).Replace (".aspx", ".txt");\r
+ return "output" + PageBuilder.dirSeparator + "output_from_compilation_" + name;\r
+ }\r
+\r
+ internal static string GeneratedXspFileName (string fileName)\r
+ {\r
+ string name = Path.GetFileName (fileName).Replace (".aspx", ".cs");\r
+ return "output" + PageBuilder.dirSeparator + "xsp_" + name;\r
+ }\r
+\r
+ private TemplateFactory ()\r
+ {\r
+ }\r
+\r
+ internal static Type GetTypeFromSource (string fileName)\r
+ {\r
+ PageBuilder builder = new PageBuilder (fileName);\r
+ return builder.Build ();\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+//
+// System.Web.UI.ApplicationfileParser
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.Web;
+
+namespace System.Web.UI
+{
+ internal sealed class ApplicationFileParser : TemplateParser
+ {
+ [MonoTODO]
+ protected override Type CompileIntoType ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ internal static Type GetCompiledApplicationType (string inputFile,
+ HttpContext context,
+ ref ApplicationFileParser parser)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override Type DefaultBaseType
+ {
+ get {
+ return typeof (HttpApplication);
+ }
+ }
+
+ protected override string DefaultDirectiveName
+ {
+ get {
+ return "application";
+ }
+ }
+ }
+
+}
+
//
// System.Web.UI.BaseParser.cs
//
-// Duncan Mak (duncan@ximian.com)
+// Authors:
+// Duncan Mak (duncan@ximian.com)
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) Ximian, Inc.
+// (C) 2002 Ximian, Inc. (http://www.ximian.com)
//
+using System.IO;
+using System.Web;
-namespace System.Web.UI {
+namespace System.Web.UI
+{
public class BaseParser
{
- // LAMESPEC: We know nothing about this class from the docs.
+ private HttpContext context;
+ private string baseDir;
+ private string baseVDir;
+ private string vPath;
+
+ internal string MapPath (string path)
+ {
+ return MapPath (path, true);
+ }
+
+ internal string MapPath (string path, bool allowCrossAppMapping)
+ {
+ return context.Request.MapPath (path, baseVDir, allowCrossAppMapping);
+ }
+
+ internal string PhysicalPath (string path)
+ {
+ if (Path.DirectorySeparatorChar != '/')
+ path = path.Replace ('/', '\\');
+
+ return Path.GetFullPath (Path.Combine (baseVDir, path));
+ }
+
+ internal HttpContext Context
+ {
+ get {
+ return context;
+ }
+ }
+
+ internal string BaseDir
+ {
+ get {
+ if (baseDir == null)
+ baseDir = MapPath (baseVDir, false);
+
+ return baseDir;
+ }
+ }
+
+ internal string BaseVirtualDir
+ {
+ get {
+ return baseVDir;
+ }
+ }
+
+ internal string CurrentVirtualPath
+ {
+ get {
+ return vPath;
+ }
+ }
}
+
}
+
+2002-08-16 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * System.Web.UI/ApplicationFileParser.cs:
+ * System.Web.UI/BaseParser.cs:
+ * System.Web.UI/PageParser.cs:
+ * System.Web.UI/TemplateControl.cs:
+ * System.Web.UI/TemplateControlParser.cs:
+ * System.Web.UI/TemplateParser.cs: first steps to move xsp into
+ System.Web.
+
2002-07-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* Page.cs: request to render postback script can be after form started
--- /dev/null
+//
+// System.Web.UI.PageParser
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.Web;
+using System.Web.Compilation;
+
+namespace System.Web.UI
+{
+ public sealed class PageParser : TemplateControlParser
+ {
+ public static IHttpHandler GetCompiledPageInstance (string virtualPath,
+ string inputFile,
+ HttpContext context)
+ {
+ PageParser pp = new PageParser ();
+ return (IHttpHandler) pp.GetCompiledInstance (virtualPath, inputFile, context);
+ }
+
+ protected override Type CompileIntoType ()
+ {
+ return PageCompiler.CompilePageType (this);
+ }
+
+ protected override Type DefaultBaseType
+ {
+ get {
+ return typeof (Page);
+ }
+ }
+
+ protected override string DefaultDirectiveName
+ {
+ get {
+ return "page";
+ }
+ }
+ }
+}
+
public abstract class TemplateControl : Control, INamingContainer
{
+ private object abortTransaction = new object ();
+ private object commitTransaction = new object ();
+ private object error = new object ();
+
#region Constructor
protected TemplateControl ()
{
+ Construct ();
}
#endregion
#region Properties
- [MonoTODO]
- protected virtual int AutoHandlers {
- get { return 1; }
+ protected virtual int AutoHandlers
+ {
+ get { return 0; }
set { }
}
- [MonoTODO]
- protected virtual bool SupportAutoEvents {
- get { return false; }
+ protected virtual bool SupportAutoEvents
+ {
+ get { return true; }
}
#endregion
}
[MonoTODO]
- protected virtual LiteralControl CreateResourceBasedLiteralControl (
- int offset, int size, bool fAsciiOnly)
+ protected virtual LiteralControl CreateResourceBasedLiteralControl (int offset,
+ int size,
+ bool fAsciiOnly)
{
return null;
}
- [MonoTODO]
protected virtual void FrameworkInitialize ()
{
}
return null;
}
- [MonoTODO]
protected virtual void OnAbortTransaction (EventArgs e)
{
+ EventHandler eh = (EventHandler) Events [error];
+ if (eh != null)
+ eh.Invoke (this, e);
}
- [MonoTODO]
protected virtual void OnCommitTransaction (EventArgs e)
{
+ EventHandler eh = (EventHandler) Events [commitTransaction];
+ if (eh != null)
+ eh.Invoke (this, e);
}
- [MonoTODO]
protected virtual void OnError (EventArgs e)
{
+ EventHandler eh = (EventHandler) Events [abortTransaction];
+ if (eh != null)
+ eh.Invoke (this, e);
}
[MonoTODO]
#region Events
- public event EventHandler AbortTransaction;
- public event EventHandler CommitTransaction;
- public event EventHandler Error;
+ public event EventHandler AbortTransaction
+ {
+ add {
+ Events.AddHandler (abortTransaction, value);
+ }
+
+ remove {
+ Events.RemoveHandler (abortTransaction, value);
+ }
+ }
+
+ public event EventHandler CommitTransaction
+ {
+ add {
+ Events.AddHandler (commitTransaction, value);
+ }
+
+ remove {
+ Events.RemoveHandler (commitTransaction, value);
+ }
+ }
+
+ public event EventHandler Error
+ {
+ add {
+ Events.AddHandler (error, value);
+ }
+
+ remove {
+ Events.RemoveHandler (error, value);
+ }
+ }
+
#endregion
}
}
--- /dev/null
+//
+// System.Web.UI.TemplateControlParser
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.IO;
+using System.Web.Compilation;
+
+namespace System.Web.UI
+{
+ public abstract class TemplateControlParser : TemplateParser
+ {
+ internal object GetCompiledInstance (string virtualPath, string inputFile, HttpContext context)
+ {
+ InputFile = Path.Combine (MapPath (virtualPath, false), inputFile);
+ Type type = CompileIntoType ();
+ if (type == null)
+ return null;
+
+ return Activator.CreateInstance (type);
+ }
+ }
+}
+
//
-// System.Web.UI.TemplateParser.cs
+// System.Web.UI.TemplateParser
//
-// Duncan Mak (duncan@ximian.com)
+// Authors:
+// Duncan Mak (duncan@ximian.com)
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) Ximian, Inc.
+// (C) 2002 Ximian, Inc. (http://www.ximian.com)
//
-
using System;
+using System.Web;
-namespace System.Web.UI {
-
+namespace System.Web.UI
+{
public abstract class TemplateParser : BaseParser
{
+ private string inputFile;
+ private string text;
+ private Type baseType;
+
protected abstract Type CompileIntoType ();
+
+ protected abstract Type DefaultBaseType { get; }
+
+ protected abstract string DefaultDirectiveName { get; }
+
+ internal string InputFile
+ {
+ get { return inputFile; }
+ set { inputFile = value; }
+ }
+
+ internal string Text
+ {
+ get { return text; }
+ set { text = value; }
+ }
+
+ internal Type BaseType
+ {
+ get { return baseType; }
+ set { baseType = value; }
+ }
}
}
+