// Authors:\r
// Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
//\r
-// (C) 2002 Ximian, Inc (http://www.ximian.com)\r
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)\r
//\r
using System;\r
using System.Collections;\r
foundries = new Hashtable (CaseInsensitiveHashCodeProvider.Default,\r
CaseInsensitiveComparer.Default);\r
\r
- RegisterFoundry ("asp", "System.Web", "System.Web.UI.WebControls");\r
- RegisterFoundry ("", "object", "System.Web", "System.Web.UI", "ObjectTag");\r
- }\r
-\r
- // TODO: don't forget to remove this method...\r
- public AspComponent MakeAspComponent (string foundryName, string componentName, Tag tag)\r
- {\r
- Foundry foundry = foundries [foundryName] as Foundry;\r
- if (foundry == null)\r
- throw new ApplicationException ("Foundry not found: " + foundryName);\r
-\r
- return new AspComponent (tag, foundry.GetType (componentName));\r
+ Assembly sw = typeof (AspComponentFoundry).Assembly;\r
+ RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");\r
+ RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));\r
}\r
\r
public Type GetComponentType (string foundryName, string tag)\r
}\r
\r
public void RegisterFoundry (string foundryName,\r
- string assemblyName,\r
+ Assembly assembly,\r
string nameSpace)\r
{\r
- AssemblyFoundry foundry = new AssemblyFoundry (assemblyName, nameSpace);\r
+ AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);\r
InternalRegister (foundryName, foundry);\r
}\r
\r
public void RegisterFoundry (string foundryName,\r
string tagName,\r
- string assemblyName,\r
- string nameSpace,\r
- string typeName)\r
+ Type type)\r
{\r
- TagNameFoundry foundry = new TagNameFoundry (assemblyName, tagName, nameSpace, typeName);\r
+ TagNameFoundry foundry = new TagNameFoundry (tagName, type);\r
InternalRegister (foundryName, foundry);\r
}\r
\r
abstract class Foundry\r
{\r
public abstract Type GetType (string componentName);\r
-\r
- public Assembly LoadAssembly (string assemblyName)\r
- {\r
- Assembly assembly = null;\r
- try {\r
- assembly = Assembly.LoadFrom (Path.GetFullPath (assemblyName));\r
- } catch {\r
- string partialName = assemblyName;\r
- if (String.Compare (Path.GetExtension (partialName), ".dll", true) == 0)\r
- partialName = Path.GetFileNameWithoutExtension (assemblyName);\r
-\r
- assembly = Assembly.LoadWithPartialName (partialName);\r
- }\r
-\r
- if (assembly == null)\r
- throw new ApplicationException ("Assembly not found:" + assemblyName);\r
-\r
- return assembly;\r
- }\r
}\r
\r
\r
class TagNameFoundry : Foundry\r
{\r
- string assemblyName;\r
string tagName;\r
- string nameSpace;\r
- string typeName;\r
Type type;\r
\r
- public TagNameFoundry (string assemblyName, string tagName, string nameSpace, string typeName)\r
+ public TagNameFoundry (string tagName, Type type)\r
{\r
- this.assemblyName = assemblyName;\r
this.tagName = tagName;\r
- this.nameSpace = nameSpace;\r
- this.typeName = typeName;\r
+ this.type = type;\r
}\r
\r
public override Type GetType (string componentName)\r
{\r
if (0 != String.Compare (componentName, tagName, true))\r
- throw new ArgumentException (componentName + " != " + tagName);\r
+ return null;\r
\r
- if (type != null)\r
- return type;\r
- \r
- Assembly assembly = LoadAssembly (assemblyName);\r
- type = assembly.GetType (nameSpace + "." + typeName, true, true);\r
return type;\r
}\r
\r
class AssemblyFoundry : Foundry\r
{\r
string nameSpace;\r
- string assemblyName;\r
Assembly assembly;\r
\r
- public AssemblyFoundry (string assemblyName, string nameSpace)\r
+ public AssemblyFoundry (Assembly assembly, string nameSpace)\r
{\r
- this.assemblyName = assemblyName;\r
+ this.assembly = assembly;\r
this.nameSpace = nameSpace;\r
- assembly = null;\r
}\r
\r
public override Type GetType (string componentName)\r
{\r
- Assembly ass = EnsureAssembly (componentName);\r
-\r
- return ass.GetType (nameSpace + "." + componentName, true, true);\r
- }\r
- \r
- Assembly EnsureAssembly (string componentName)\r
- {\r
- if (assembly != null)\r
- return assembly;\r
-\r
- assembly = LoadAssembly (assemblyName);\r
- return assembly;\r
+ return assembly.GetType (nameSpace + "." + componentName, true, true);\r
}\r
}\r
\r
+++ /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.IO;
-using System.Reflection;
-using System.Text;
-using System.Web.UI;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
-using System.Web.Util;
-
-namespace System.Web.Compilation
-{
-
- enum ElementType
- {
- TAG,
- PLAINTEXT
- }
-
- abstract class Element
- {
- private ElementType elementType;
-
- public Element (ElementType type)
- {
- elementType = type;
- }
-
- public ElementType GetElementType
- {
- get { return elementType; }
- }
- } // class Element
-
- 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;
- }
- }
-
- enum TagType
- {
- DIRECTIVE,
- HTML,
- HTMLCONTROL,
- SERVERCONTROL,
- INLINEVAR,
- INLINECODE,
- CLOSING,
- SERVEROBJECT,
- PROPERTYTAG,
- CODERENDER,
- DATABINDING,
- SERVERCOMMENT,
- 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.
- *
- */
- 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 (CaseInsensitiveHashCodeProvider.Default,
- CaseInsensitiveComparer.Default);
- 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 ()
- {
- StringBuilder result = new StringBuilder ();
- string value;
- foreach (string key in Keys){
- result.Append (key);
- value = this [key] as string;
- if (value != null)
- result.AppendFormat ("=\"{0}\"", value);
-
- result.Append (' ');
- }
-
- if (result.Length > 0 && result [result.Length - 1] == ' ')
- result.Length--;
-
- return result.ToString ();
- }
- }
-
- class Tag : Element
- {
- protected string tag;
- protected TagType tagType;
- protected TagAttributes attributes;
- protected bool self_closing;
- protected bool hasDefaultID;
- private static int ctrlNumber = 1;
- ArrayList elements;
-
- internal Tag (ElementType etype) : base (etype) { }
-
- 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;
- }
-
- void ParseError (string msg, int line, int col)
- {
- string exc = String.Format ("error parsing attributes: {0}", msg);
- throw new HttpException (exc);
- }
-
- void TagParsed (Tag tag, int line, int col)
- {
- elements.Add (tag);
- }
-
- void TextParsed (string msg, int line, int col)
- {
- elements.Add (new PlainText (msg));
- }
-
- public ArrayList GetElements ()
- {
- string text = this.PlainHtml;
- string inner = text.Substring (1, text.Length - 2);
- byte [] bytes = WebEncoding.Encoding.GetBytes (inner);
- AspTokenizer tok = new AspTokenizer ("@@inner_string", new MemoryStream (bytes));
- AspParser parser = new AspParser (tok);
-
- elements = new ArrayList ();
- parser.Error += new ParseErrorHandler (ParseError);
- parser.TagParsed += new TagParsedHandler (TagParsed);
- parser.TextParsed += new TextParsedHandler (TextParsed);
-
- parser.Parse ();
-
- elements.Insert (0, new PlainText ("<"));
- elements.Add (new PlainText (">"));
-
- return elements;
- }
- 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 (' ');
- plain.Append (attributes.ToString ());
- }
-
- 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 virtual void SetNewID ()
- {
- if (attributes == null)
- attributes = new TagAttributes ();
- attributes.Add ("ID", GetDefaultID ());
- hasDefaultID = true;
- }
-
- public static string GetDefaultID ()
- {
- return "_control" + ctrlNumber++;
- }
- }
-
- class CloseTag : Tag
- {
- public CloseTag (string tag) : base (tag, null, false)
- {
- tagType = TagType.CLOSING;
- }
- }
-
- class Directive : Tag
- {
- // 'codebehind' is just ignored for Page, Application and Control
- 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", "CodeBehind" };
-
- private static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
- "Debug", "Description", "EnableViewState",
- "Explicit", "Inherits", "Language", "Strict", "Src",
- "WarningLevel", "CodeBehind", "TargetSchema" };
-
- 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" };
-
- private static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
-
- private static string [] application_atts = { "description", "inherits", "codebehind" };
-
- 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);
-
- valid_attributes = new Hashtable (provider, comparer);
- foreach (string att in webservice_atts) valid_attributes.Add (att, null);
- directivesHash.Add ("WEBSERVICE", valid_attributes);
-
- valid_attributes = new Hashtable (provider, comparer);
- foreach (string att in application_atts) valid_attributes.Add (att, null);
- directivesHash.Add ("APPLICATION", 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);
-
- if (attributes == null || attributes.Count == 0)
- return;
-
- 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;
- }
- }
-
- 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"]; }
- }
- }
-
- class HtmlControlTag : Tag
- {
- private Type control_type;
- private bool is_container;
- private string parse_children;
- private bool got_parse_children;
-
- 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 string ParseChildren {
- get {
- if (got_parse_children)
- return parse_children;
-
- got_parse_children = true;
- object [] custom_atts = control_type.GetCustomAttributes (true);
- foreach (object att in custom_atts) {
- if (!(att is ParseChildrenAttribute))
- continue;
-
- ParseChildrenAttribute pc = (ParseChildrenAttribute) att;
- if (pc.ChildrenAsProperties == true)
- parse_children = pc.DefaultProperty;
-
- return parse_children;
- }
-
- return parse_children;
- }
- }
-
- 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;
- }
- }
-
- 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,
- /* Childs of HtmlTable */
- HTMLROW,
- /* Childs of HtmlTableRow */
- HTMLCELL
- }
-
- // TODO: support for ControlBuilderAttribute that may be used in custom controls
- class AspComponent : 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 Type defaultPropertyType;
-
- ChildrenKind ChildrenKindFromProperty (Type type, string propertyName)
- {
- PropertyInfo prop = type.GetProperty (propertyName);
- if (prop == null)
- return ChildrenKind.LISTITEM;
-
- defaultPropertyType = prop.PropertyType;
- if (typeof (TableRowCollection).IsAssignableFrom (defaultPropertyType))
- return ChildrenKind.HTMLROW;
-
- if (typeof (TableCellCollection).IsAssignableFrom (defaultPropertyType))
- return ChildrenKind.HTMLCELL;
-
- return ChildrenKind.LISTITEM;
- }
-
- 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 ChildrenKindFromProperty (type, defaultPropertyName);
- }
- }
-
- 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 AspComponent (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 Type DefaultPropertyType
- {
- get { return defaultPropertyType; }
- }
-
- public override string ToString ()
- {
- return type.ToString () + " Alias: " + alias + " ID: " + (string) attributes ["id"];
- }
- }
-
- 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; }
- }
- }
-
- 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 + "%>"; }
- }
- }
-
- 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 + "%>"; }
- }
- }
-
- class ServerComment : Tag
- {
- public ServerComment (string tag)
- : base (ElementType.TAG)
- {
- if (tag == null)
- throw new ArgumentNullException ();
-
- this.tag = tag;
- this.attributes = null;
- this.tagType = TagType.SERVERCOMMENT;
- this.self_closing = true;
- this.hasDefaultID = false;
- }
-
- public override string ToString ()
- {
- return TagID;
- }
-
- protected override void SetNewID ()
- {
- throw new NotSupportedException ();
- }
- }
-}
-
//
using System;
using System.Collections;
-using System.ComponentModel;
-using System.Drawing;
-using System.Diagnostics;
using System.IO;
-using System.Reflection;
using System.Text;
-using System.Text.RegularExpressions;
using System.Web.UI;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
-using System.Web.Util;
namespace System.Web.Compilation
{
-
-class ControlStack
-{
- private Stack controls;
- private ControlStackData top;
- private bool space_between_tags;
- private bool sbt_valid;
-
- class ControlStackData
+ class BuilderLocation
{
- public Type controlType;
- public string controlID;
- public string tagID;
- public ChildrenKind childKind;
- public string defaultPropertyName;
- public int childrenNumber;
- public Type container;
- public StringBuilder dataBindFunction;
- public StringBuilder codeRenderFunction;
- public bool useCodeRender;
- public int codeRenderIndex;
-
- public ControlStackData (Type controlType,
- string controlID,
- string tagID,
- ChildrenKind childKind,
- string defaultPropertyName,
- Type container)
- {
- this.controlType = controlType;
- this.controlID = controlID;
- this.tagID = tagID;
- this.childKind = childKind;
- this.defaultPropertyName = defaultPropertyName;
- this.container = container;
- childrenNumber = 0;
- }
+ public ControlBuilder Builder;
+ public ILocation Location;
- public override string ToString ()
+ public BuilderLocation (ControlBuilder builder, ILocation location)
{
- return controlType + " " + controlID + " " + tagID + " " + childKind + " " + childrenNumber;
+ this.Builder = builder;
+ this.Location = location;
}
}
- public ControlStack ()
+ class BuilderLocationStack : Stack
{
- controls = new Stack ();
- }
+ public override void Push (object o)
+ {
+ if (!(o is BuilderLocation))
+ throw new InvalidOperationException ();
- private Type GetContainerType (Type type)
- {
- if (type != typeof (System.Web.UI.Control) &&
- !type.IsSubclassOf (typeof (System.Web.UI.Control)))
- return null;
+ base.Push (o);
+ }
- Type container_type;
- if (type == typeof (System.Web.UI.WebControls.DataList))
- container_type = typeof (System.Web.UI.WebControls.DataListItem);
- else if (type == typeof (System.Web.UI.WebControls.DataGrid))
- container_type = typeof (System.Web.UI.WebControls.DataGridItem);
- else if (type == typeof (System.Web.UI.WebControls.Repeater))
- container_type = typeof (System.Web.UI.WebControls.RepeaterItem);
- else if (type == typeof (ListControl) || type.IsSubclassOf (typeof (ListControl)))
- container_type = type;
- else
- container_type = Container;
-
- return container_type;
- }
-
- public void Push (object o)
- {
- if (!(o is ControlStackData))
- return;
-
- controls.Push (o);
- top = (ControlStackData) o;
- sbt_valid = false;
- }
-
- public void Push (Type controlType,
- string controlID,
- string tagID,
- ChildrenKind childKind,
- string defaultPropertyName)
- {
- Type container_type = null;
- if (controlType != null){
- AddChild ();
- container_type = GetContainerType (controlType);
- if (container_type == null)
- container_type = this.Container;
+ public virtual void Push (ControlBuilder builder, ILocation location)
+ {
+ BuilderLocation bl = new BuilderLocation (builder, location);
+ Push (bl);
}
- top = new ControlStackData (controlType,
- controlID,
- tagID,
- childKind,
- defaultPropertyName,
- container_type);
- sbt_valid = false;
- controls.Push (top);
- }
-
- public object Pop ()
- {
- object item = controls.Pop ();
- if (controls.Count != 0)
- top = (ControlStackData) controls.Peek ();
- sbt_valid = false;
- return item;
- }
-
- public Type PeekType ()
- {
- return top.controlType;
- }
-
- public string PeekControlID ()
- {
- return top.controlID;
- }
-
- public string PeekTagID ()
- {
- return top.tagID;
- }
-
- public ChildrenKind PeekChildKind ()
- {
- return top.childKind;
- }
-
- public string PeekDefaultPropertyName ()
- {
- return top.defaultPropertyName;
- }
-
- public void AddChild ()
- {
- if (top != null)
- top.childrenNumber++;
- }
-
- public bool HasDataBindFunction ()
- {
- if (top.dataBindFunction == null || top.dataBindFunction.Length == 0)
- return false;
- return true;
- }
-
- public bool UseCodeRender
- {
- get {
- if (top.codeRenderFunction == null || top.codeRenderFunction.Length == 0)
- return false;
- return top.useCodeRender;
+ public new BuilderLocation Peek ()
+ {
+ return (BuilderLocation) base.Peek ();
}
- set { top.useCodeRender= value; }
- }
-
- public bool SpaceBetweenTags
- {
- get {
- if (!sbt_valid){
- sbt_valid = true;
- Type type = top.controlType;
- if (type.Namespace == "System.Web.UI.WebControls")
- space_between_tags = true;
- else if (type.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlSelect))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTable))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableRow))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableCell))
- space_between_tags = true;
- else
- space_between_tags = false;
- }
- return space_between_tags;
- }
- }
-
- public Type Container {
- get {
- if (top == null)
- return null;
-
- return top.container;
- }
- }
-
- public StringBuilder DataBindFunction
- {
- get {
- if (top.dataBindFunction == null)
- top.dataBindFunction = new StringBuilder ();
- return top.dataBindFunction;
+ public new BuilderLocation Pop ()
+ {
+ return (BuilderLocation) base.Pop ();
}
- }
- public int CodeRenderIndex {
- get {
- return top.codeRenderIndex++;
- }
- }
-
- public StringBuilder CodeRenderFunction
- {
- get {
- if (top.codeRenderFunction == null)
- top.codeRenderFunction = new StringBuilder ();
- return top.codeRenderFunction;
+ public ControlBuilder Builder {
+ get { return Peek ().Builder; }
}
}
- public int ChildIndex
- {
- get { return top.childrenNumber - 1; }
- }
-
- public int Count
- {
- get { return controls.Count; }
- }
-
- public override string ToString ()
+ class AspGenerator
{
- return top.ToString () + " " + top.useCodeRender;
- }
-
-}
-
-enum ScriptStatus
-{
- Close,
- Open,
- Text
-}
-
-class AspGenerator
-{
- object [] parts;
- StringBuilder prolog;
- StringBuilder declarations;
- StringBuilder script;
- StringBuilder constructor;
- StringBuilder init_funcs;
- StringBuilder epilog;
- StringBuilder current_function;
- StringBuilder textChunk;
- Stack functions;
- ControlStack controls;
- bool parse_ok;
- bool has_form_tag;
- AspComponentFoundry aspFoundry;
-
- string classDecl;
- string className;
- string interfaces;
- string basetype;
- string parent;
- Type parentType;
- string fullPath;
+ string filename;
+ AspParser parser;
+ BuilderLocationStack stack;
+ TemplateParser tparser;
+ StringBuilder text;
+ RootBuilder rootBuilder;
+ bool inScript;
+ ILocation location;
+ static Hashtable emptyHash = new Hashtable ();
- Hashtable options;
- string privateBinPath;
- string main_directive;
- static string app_file_wrong = "The content in the application file is not valid.";
-
- bool isPage;
- bool isUserControl;
- bool isApplication;
-
- Element current;
- ScriptStatus sstatus = ScriptStatus.Close;
- string waitClosing;
- ArrayList dependencies;
-
- HttpContext context;
-
- SessionState sessionState = SessionState.Enabled;
-
- static Type styleType = typeof (System.Web.UI.WebControls.Style);
- static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
+ public AspGenerator (TemplateParser tparser)
+ {
+ this.tparser = tparser;
+ this.filename = Path.GetFullPath (tparser.InputFile);
+ tparser.AddDependency (tparser.InputFile);
+ text = new StringBuilder ();
+ stack = new BuilderLocationStack ();
+ rootBuilder = new RootBuilder (tparser);
+ stack.Push (rootBuilder, null);
+ tparser.RootBuilder = rootBuilder;
+ }
- enum UserControlResult
- {
- OK = 0,
- FileNotFound = 1,
- CompilationFailed = 2
- }
+ BaseCompiler GetCompilerFromType ()
+ {
+ Type type = tparser.GetType ();
+ if (type == typeof (PageParser))
+ return new PageCompiler ((PageParser) tparser);
- enum SessionState
- {
- Enabled,
- ReadOnly,
- Disabled
- }
-
- public AspGenerator (string pathToFile)
- {
- if (pathToFile == null)
- throw new ArgumentNullException ("pathToFile");
+ if (type == typeof (ApplicationFileParser))
+ return new GlobalAsaxCompiler ((ApplicationFileParser) tparser);
- string filename = Path.GetFileName (pathToFile);
- this.className = filename.Replace ('.', '_'); // Overridden by @ Page classname
- this.className = className.Replace ('-', '_');
- this.className = className.Replace (' ', '_');
- Options ["ClassName"] = this.className;
- this.fullPath = Path.GetFullPath (pathToFile);
+ if (type == typeof (UserControlParser))
+ return new UserControlCompiler ((UserControlParser) tparser);
- this.has_form_tag = false;
- AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
- privateBinPath = setup.PrivateBinPath;
- // This is a hack until we can run stuff in different domains
- if (privateBinPath == null || privateBinPath.Length == 0)
- privateBinPath = "bin";
-
- if (!Path.IsPathRooted (privateBinPath)) {
- string appbase = setup.ApplicationBase;
- if (appbase.StartsWith ("file://")) {
- appbase = appbase.Substring (7);
- if (Path.DirectorySeparatorChar != '/')
- appbase = appbase.Replace ('/', Path.DirectorySeparatorChar);
- }
- privateBinPath = Path.Combine (appbase, privateBinPath);
+ throw new Exception ("Got type: " + type);
}
- Init ();
- }
-
- public string BaseType {
- get { return basetype; }
-
- set {
- if (parent == null)
- parent = value;
-
- basetype = value;
- isUserControl = (basetype == "System.Web.UI.UserControl");
- isPage = (basetype == "System.Web.UI.Page");
- isApplication = (basetype == "System.Web.HttpApplication");
- }
- }
-
- public bool IsUserControl {
- get { return isUserControl; }
- }
-
- public bool IsPage {
- get { return isPage; }
- }
-
- public bool IsApplication {
- get { return isApplication; }
- }
-
- public string Interfaces {
- get { return interfaces; }
- }
+ public Type GetCompiledType ()
+ {
+ //FIXME: use the encoding of the file or the one specified in the machine.config/web.config file.
+ StreamReader reader = new StreamReader (filename, Encoding.Default);
+ parser = new AspParser (filename, reader);
+ parser.Error += new ParseErrorHandler (ParseError);
+ parser.TagParsed += new TagParsedHandler (TagParsed);
+ parser.TextParsed += new TextParsedHandler (TextParsed);
- public Hashtable Options {
- get {
- if (options == null)
- options = new Hashtable ();
+ parser.Parse ();
+ if (text.Length > 0)
+ FlushText ();
- return options;
- }
- }
-
- public ArrayList Dependencies {
- get { return dependencies; }
- }
-
- internal HttpContext Context {
- get { return context; }
- set { context = value; }
- }
-
- bool AddUsing (string nspace)
- {
- string _using = "using " + nspace + ";";
- if (prolog.ToString ().IndexOf (_using) == -1) {
- prolog.AppendFormat ("\t{0}\n", _using);
- return true;
- }
+ if (stack.Count > 1)
+ throw new ParseException (stack.Builder.location,
+ "Expecting </" + stack.Builder.TagName + ">" + stack.Builder);
- return false;
- }
+ BaseCompiler compiler = GetCompilerFromType ();
- void AddInterface (Type type)
- {
- AddInterface (type.ToString ());
- }
-
- public void AddInterface (string iface)
- {
- if (interfaces == null) {
- interfaces = ", " + iface;
- } else {
- string s = ", " + iface;
- if (interfaces.IndexOf (s) == -1)
- interfaces += s;
+ /*
+ IndentedTextWriter tw = new IndentedTextWriter (Console.Out, " ");
+ generator.GenerateCodeFromCompileUnit (unit, tw, new CodeGeneratorOptions());
+ tw.Close ();
+ */
+ return compiler.GetCompiledType ();
}
- }
- private AspComponentFoundry Foundry
- {
- get {
- if (aspFoundry == null)
- aspFoundry = new AspComponentFoundry ();
-
- return aspFoundry;
+ static void PrintLocation (ILocation loc)
+ {
+ Console.WriteLine ("\tFile name: " + loc.Filename);
+ Console.WriteLine ("\tBegin line: " + loc.BeginLine);
+ Console.WriteLine ("\tEnd line: " + loc.EndLine);
+ Console.WriteLine ("\tBegin column: " + loc.BeginColumn);
+ Console.WriteLine ("\tEnd column: " + loc.EndColumn);
+ Console.WriteLine ("\tPlainText: " + loc.PlainText);
+ Console.WriteLine ();
}
- }
-
- private void Init ()
- {
- dependencies = new ArrayList ();
- dependencies.Add (fullPath);
-
- controls = new ControlStack ();
- controls.Push (typeof (System.Web.UI.Control), "Root", null, ChildrenKind.CONTROLS, null);
- prolog = new StringBuilder ();
- declarations = new StringBuilder ();
- script = new StringBuilder ();
- constructor = new StringBuilder ();
- init_funcs = new StringBuilder ();
- epilog = new StringBuilder ();
- textChunk = new StringBuilder ();
-
- current_function = new StringBuilder ();
- functions = new Stack ();
- functions.Push (current_function);
-
- parts = new Object [6];
- parts [0] = prolog;
- parts [1] = declarations;
- parts [2] = script;
- parts [3] = constructor;
- parts [4] = init_funcs;
- parts [5] = epilog;
-
- prolog.Append ("namespace ASP {\n" +
- "\tusing System;\n" +
- "\tusing System.Collections;\n" +
- "\tusing System.Collections.Specialized;\n" +
- "\tusing System.Configuration;\n" +
- "\tusing System.IO;\n" +
- "\tusing System.Text;\n" +
- "\tusing System.Text.RegularExpressions;\n" +
- "\tusing System.Web;\n" +
- "\tusing System.Web.Caching;\n" +
- "\tusing System.Web.Security;\n" +
- "\tusing System.Web.SessionState;\n" +
- "\tusing System.Web.UI;\n" +
- "\tusing System.Web.UI.WebControls;\n" +
- "\tusing System.Web.UI.HtmlControls;\n");
-
- declarations.Append ("\t\tprivate static int __autoHandlers;\n");
-
- current_function.Append ("\t\tprivate void __BuildControlTree (System.Web.UI.Control __ctrl)\n\t\t{\n");
- if (!IsUserControl)
- current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
- "(System.Web.UI.IParserAccessor) __ctrl;\n\n");
- else
- controls.UseCodeRender = true;
- }
-
- public TextReader GetCode ()
- {
- if (!parse_ok)
- throw new InvalidOperationException ("Parsing not done yet! (may be there were errors?)");
-
- StringBuilder code = new StringBuilder ();
- for (int i = 0; i < parts.Length; i++)
- code.Append ((StringBuilder) parts [i]);
- return new StringReader (code.ToString ());
- }
-
- // Regex.Escape () make some illegal escape sequences for a C# source.
- private string Escape (string input)
- {
- if (input == null)
- return String.Empty;
-
- string output = input.Replace ("\\", "\\\\");
- output = output.Replace ("\"", "\\\"");
- output = output.Replace ("\t", "\\t");
- output = output.Replace ("\r", "\\r");
- output = output.Replace ("\n", "\\n");
- output = output.Replace ("\n", "\\n");
- return output;
- }
-
- bool AddProtectedField (Type type, string fieldName)
- {
- if (parentType == null) {
- declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
- return true;
+ void ParseError (ILocation location, string message)
+ {
+ throw new ParseException (location, message);
}
- FieldInfo field = parentType.GetField (fieldName, BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.Static);
-
- if (field == null || (!field.IsPublic && !field.IsFamily)) {
- declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
- return true;
- }
+ void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes)
+ {
+ this.location = location;
+ if (tparser != null)
+ tparser.Location = location;
- if (!field.FieldType.IsAssignableFrom (type)) {
- string message = String.Format ("The base class includes the field '{0}', but its " +
- "type '{1}' is not compatible with {2}",
- fieldName, field.FieldType, type);
+ if (text.Length != 0)
+ FlushText ();
- throw new ApplicationException (message);
- }
+ if (0 == String.Compare (tagid, "script", true)) {
+ if (ProcessScript (tagtype, attributes))
+ return;
+ }
- return false;
- }
-
- private Type LoadParentType (string typeName)
- {
- // First try loaded assemblies, then try assemblies in Bin directory.
- // By now i do this 'by hand' but may be this is a runtime/gac task.
- Type type = null;
- Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
- foreach (Assembly ass in assemblies) {
- type = ass.GetType (typeName);
- if (type != null)
- return type;
- }
+ switch (tagtype) {
+ case TagType.Directive:
+ if (tagid == "")
+ tagid = tparser.DefaultDirectiveName;
- Assembly assembly;
- string [] binDlls = Directory.GetFiles (privateBinPath, "*.dll");
- foreach (string dll in binDlls) {
- string dllPath = Path.Combine (privateBinPath, dll);
- assembly = null;
- try {
- assembly = Assembly.LoadFrom (dllPath);
- type = assembly.GetType (typeName);
- } catch (Exception e) {
- if (assembly != null) {
- Console.WriteLine ("ASP.NET Warning: assembly {0} loaded", dllPath);
- Console.WriteLine ("ASP.NET Warning: but type {0} not found", typeName);
- } else {
- Console.WriteLine ("ASP.NET Warning: unable to load type {0} from {1}",
- typeName, dllPath);
+ tparser.AddDirective (tagid, attributes.GetDictionary (null));
+ break;
+ case TagType.Tag:
+ if (!ProcessTag (tagid, attributes))
+ TextParsed (location, location.PlainText);
+ break;
+ case TagType.Close:
+ if (!CloseControl (tagid))
+ TextParsed (location, location.PlainText);
+ break;
+ case TagType.SelfClosing:
+ int count = stack.Count;
+ if (!ProcessTag (tagid, attributes)) {
+ TextParsed (location, location.PlainText);
+ } else if (stack.Count != count) {
+ CloseControl (tagid);
}
- Console.WriteLine ("ASP.NET Warning: error was: {0}", e.Message);
- }
-
- if (type != null) {
- dependencies.Add (dllPath);
- return type;
+ break;
+ case TagType.DataBinding:
+ goto case TagType.CodeRender;
+ case TagType.CodeRenderExpression:
+ goto case TagType.CodeRender;
+ case TagType.CodeRender:
+ ProcessCode (tagtype, tagid, location);
+ break;
+ default:
+ break;
}
+ //PrintLocation (location);
}
- return null;
- }
-
- private void PageDirective (TagAttributes att)
- {
- if (att ["ClassName"] != null){
- this.className = (string) att ["ClassName"];
- Options ["ClassName"] = className;
- }
-
- if (att ["EnableSessionState"] != null){
- if (!IsPage)
- throw new ApplicationException ("EnableSessionState not allowed here.");
-
- string est = (string) att ["EnableSessionState"];
- if (0 == String.Compare (est, "false", true))
- sessionState = SessionState.Disabled;
- else if (0 == String.Compare (est, "true", true))
- sessionState = SessionState.Enabled;
- else if (0 == String.Compare (est, "readonly", true))
- sessionState = SessionState.ReadOnly;
- else
- throw new ApplicationException ("EnableSessionState in Page directive not set to " +
- "a correct value: " + est);
- }
-
- if (att ["Inherits"] != null) {
- parent = (string) att ["Inherits"];
- parentType = LoadParentType (parent);
- if (parentType == null)
- throw new ApplicationException ("The class " + parent + " cannot be found.");
+ void TextParsed (ILocation location, string text)
+ {
+ this.text.Append (text);
+ //PrintLocation (location);
}
- if (att ["CompilerOptions"] != null)
- Options ["CompilerOptions"] = (string) att ["CompilerOptions"];
-
- if (att ["AutoEventWireup"] != null) {
- if (options ["AutoEventWireup"] != null)
- throw new ApplicationException ("Already have an AutoEventWireup attribute");
-
- bool autoevent = true;
- string v = att ["AutoEventWireup"] as string;
- try {
- autoevent = Convert.ToBoolean (v);
- } catch (Exception) {
- throw new ApplicationException ("'" + v + "' is not a valid value for AutoEventWireup");
+ void FlushText ()
+ {
+ string t = text.ToString ();
+ text.Length = 0;
+ if (inScript) {
+ // TODO: store location
+ tparser.Scripts.Add (t);
+ return;
}
- options ["AutoEventWireup"] = autoevent;
- }
-
- //FIXME: add support for more attributes.
- }
-
- void AddReference (string dll)
- {
- string references = Options ["References"] as string;
- if (references == null)
- references = dll;
- else
- references = references + "|" + dll;
-
- Options ["References"] = references;
- }
- private void RegisterDirective (TagAttributes att)
- {
- string tag_prefix = (string) (att ["tagprefix"] == null ? "" : att ["tagprefix"]);
- string name_space = (string) (att ["namespace"] == null ? "" : att ["namespace"]);
- string assembly_name = (string) (att ["assembly"] == null ? "" : att ["assembly"]);
- string tag_name = (string) (att ["tagname"] == null ? "" : att ["tagname"]);
- string src = (string) (att ["src"] == null ? "" : att ["src"]);
-
- if (tag_prefix != "" && name_space != "" && assembly_name != ""){
- if (tag_name != "" || src != "")
- throw new ApplicationException ("Invalid attributes for @ Register: " +
- att.ToString ());
-
- AddUsing (name_space);
- string dll = Path.Combine (privateBinPath, assembly_name + ".dll");
- // Hack: it should use assembly.load semantics...
- // may be when we don't run mcs as a external program...
- if (!File.Exists (dll))
- dll = assembly_name;
- else
- dependencies.Add (dll);
+ if (tparser.DefaultDirectiveName == "application" && t.Trim () != "")
+ throw new ParseException (location, "Content not valid for application file.");
- Foundry.RegisterFoundry (tag_prefix, dll, name_space);
- AddReference (dll);
- return;
+ stack.Builder.AppendLiteralString (t);
}
- if (tag_prefix != "" && tag_name != "" && src != ""){
- if (name_space != "" && assembly_name != "")
- throw new ApplicationException ("Invalid attributes for @ Register: " +
- att.ToString ());
+ bool ProcessTag (string tagid, TagAttributes atts)
+ {
+ ControlBuilder parent = stack.Builder;
+ ControlBuilder builder = null;
+ BuilderLocation bl = null;
+ Hashtable htable = (atts != null) ? atts.GetDictionary (null) : emptyHash;
+ if (stack.Count > 1)
+ builder = parent.CreateSubBuilder (tagid, htable, null, tparser, location);
+
+ if (builder == null && atts != null && atts.IsRunAtServer ())
+ builder = rootBuilder.CreateSubBuilder (tagid, htable, null, tparser, location);
- if (!src.EndsWith (".ascx"))
- throw new ApplicationException ("Source file extension for controls " +
- "must be .ascx");
-
- UserControlData data = GenerateUserControl (src, Context);
- switch (data.result) {
- case UserControlResult.OK:
- AddUsing ("ASP");
- Foundry.RegisterFoundry (tag_prefix, tag_name, data.assemblyName, "ASP", data.className);
- AddReference (data.assemblyName);
- break;
- case UserControlResult.FileNotFound:
- throw new ApplicationException ("File '" + src + "' not found.");
- case UserControlResult.CompilationFailed:
- //TODO: should say where the generated .cs file is for the server to
- //show the source and the compiler error
- throw new NotImplementedException ();
- }
- return;
- }
-
- throw new ApplicationException ("Invalid combination of attributes in " +
- "@ Register: " + att.ToString ());
- }
-
- private void ProcessDirective ()
- {
- FlushPlainText ();
- Directive directive = (Directive) current;
- TagAttributes att = directive.Attributes;
- if (att == null)
- return;
-
- string value;
- string id = directive.TagID.ToUpper ();
- switch (id){
- case "APPLICATION":
- if (main_directive != null)
- throw new ApplicationException (id + " not allowed after " + main_directive);
-
- if (!IsApplication)
- throw new ApplicationException ("@Application not allowed.");
-
- string inherits = att ["inherits"] as string;
- if (inherits != null) {
- parent = inherits;
- parentType = LoadParentType (parent);
- if (parentType == null)
- throw new ApplicationException ("The class " + parent + " cannot be found.");
- }
-
- main_directive = directive.TagID;
- break;
- case "PAGE":
- case "CONTROL":
- if (main_directive != null)
- throw new ApplicationException (id + " not allowed after " + main_directive);
-
- if (IsUserControl && id != "CONTROL")
- throw new ApplicationException ("@Page not allowed for user controls.");
- else if (IsPage && id != "PAGE")
- throw new ApplicationException ("@Control not allowed here. This is a page!");
-
- PageDirective (att);
- main_directive = directive.TagID;
- break;
- case "IMPORT":
- value = att ["namespace"] as string;
- if (value == null || att.Count > 1)
- throw new ApplicationException ("Wrong syntax in Import directive.");
+ if (builder == null)
+ return false;
- string _using = "using " + value + ";";
- if (AddUsing (value) == true) {
- string imports = Options ["Import"] as string;
- if (imports == null) {
- imports = value;
- } else {
- imports += "," + value;
+ builder.location = location;
+ builder.ID = htable ["id"] as string;
+ if (builder.HasBody ()) {
+ if (builder is TemplateBuilder) {
+ // push the id list
}
-
- Options ["Import"] = imports;
- }
- break;
- case "IMPLEMENTS":
- if (IsApplication)
- throw new ApplicationException ("@ Implements not allowed in an application file.");
-
- string iface = (string) att ["interface"];
- AddInterface (iface);
- break;
- case "REGISTER":
- if (IsApplication)
- throw new ApplicationException ("@ Register not allowed in an application file.");
-
- RegisterDirective (att);
- break;
- case "ASSEMBLY":
- if (att.Count > 1)
- throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
- string name = att ["name"] as string;
- string src = att ["src"] as string;
-
- if (name == null && src == null)
- throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
- if (IsApplication && src != null)
- throw new ApplicationException ("'name' attribute expected.");
-
- value = (name == null) ? src : name;
- string assemblies = Options ["Assembly"] as string;
- if (assemblies == null) {
- assemblies = value;
+ stack.Push (builder, location);
} else {
- assemblies += "," + value;
+ // FIXME:ObjectTags...
+ parent.AppendSubBuilder (builder);
+ builder.CloseControl ();
}
- Options ["Assembly"] = assemblies;
- break;
- }
- }
-
- private void ProcessPlainText ()
- {
- PlainText asis = (PlainText) current;
- string trimmed = asis.Text.Trim ();
- if (trimmed == String.Empty && controls.SpaceBetweenTags == true)
- return;
-
- if (IsApplication) {
- if (trimmed != String.Empty)
- throw new ApplicationException (app_file_wrong);
- return;
- }
-
- if (trimmed != String.Empty && controls.PeekChildKind () != ChildrenKind.CONTROLS){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException ("Literal content not allowed for " + tag_id);
+ return true;
}
-
- string escaped_text = Escape (asis.Text);
- current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject (" +
- "new System.Web.UI.LiteralControl (\"{0}\"));\n",
- escaped_text);
- StringBuilder codeRenderFunction = controls.CodeRenderFunction;
- codeRenderFunction.AppendFormat ("\t\t\t__output.Write (\"{0}\");\n", escaped_text);
- }
-
- private string EnumValueNameToString (Type enum_type, string value_name)
- {
- if (value_name.EndsWith ("*"))
- throw new ApplicationException ("Invalid property value: '" + value_name +
- ". It must be a valid " + enum_type.ToString () + " value.");
- MemberInfo [] nested_types = enum_type.FindMembers (MemberTypes.Field,
- BindingFlags.Public | BindingFlags.Static,
- Type.FilterNameIgnoreCase,
- value_name);
+ bool ProcessScript (TagType tagtype, TagAttributes attributes)
+ {
+ if (tagtype != TagType.Close && attributes != null && attributes.IsRunAtServer ()) {
+ if (tagtype == TagType.Tag) {
+ parser.VerbatimID = "script";
+ inScript = true;
+ } //else if (tagtype == TagType.SelfClosing)
+ // load script file here
- if (nested_types.Length == 0)
- throw new ApplicationException ("Value " + value_name + " not found in enumeration " +
- enum_type.ToString ());
- if (nested_types.Length > 1)
- throw new ApplicationException ("Value " + value_name + " found " +
- nested_types.Length + " in enumeration " +
- enum_type.ToString ());
+ return true;
+ }
- return enum_type.ToString () + "." + nested_types [0].Name;
- }
-
- private void NewControlFunction (string tag_id,
- string control_id,
- Type control_type,
- ChildrenKind children_kind,
- string defaultPropertyName)
- {
- ChildrenKind prev_children_kind = controls.PeekChildKind ();
- if (prev_children_kind == ChildrenKind.NONE ||
- prev_children_kind == ChildrenKind.PROPERTIES){
- string prev_tag_id = controls.PeekTagID ();
- throw new ApplicationException ("Child controls not allowed for " + prev_tag_id);
- }
+ bool result = inScript;
+ inScript = false;
- Type allowed = null;
- if (prev_children_kind == ChildrenKind.DBCOLUMNS &&
- !typeof (DataGridColumn).IsAssignableFrom (control_type)) {
- allowed = typeof (DataGridColumn);
- } else if (prev_children_kind == ChildrenKind.LISTITEM &&
- control_type != typeof (System.Web.UI.WebControls.ListItem)) {
- allowed = typeof (DataGridColumn);
- } else if (prev_children_kind == ChildrenKind.HTMLROW) {
- Type prevType = controls.PeekType ();
- if (prevType == typeof (HtmlTable) && control_type != typeof (HtmlTableRow))
- allowed = typeof (HtmlTableRow);
- else if (prevType == typeof (Table) && control_type != typeof (TableRow))
- allowed = typeof (TableRow);
- } else if (prev_children_kind == ChildrenKind.HTMLCELL) {
- Type prevType = controls.PeekType ();
- if (prevType == typeof (HtmlTableRow) && control_type != typeof (HtmlTableCell))
- allowed = typeof (HtmlTableCell);
- else if (prevType == typeof (TableRow) && control_type != typeof (TableCell))
- allowed = typeof (TableCell);
+ return result;
}
-
- if (allowed != null)
- throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
- allowed + " objects are allowed");
- StringBuilder func_code = new StringBuilder ();
- current_function = func_code;
- if (0 == String.Compare (tag_id, "form", true)){
- if (has_form_tag)
- throw new ApplicationException ("Only one form server tag allowed.");
- has_form_tag = true;
- }
+ bool CloseControl (string tagid)
+ {
+ ControlBuilder current = stack.Builder;
+ string btag = current.TagName;
+ if (0 != String.Compare (tagid, btag, true))
+ return false;
- controls.Push (control_type, control_id, tag_id, children_kind, defaultPropertyName);
- bool is_generic = control_type == typeof (System.Web.UI.HtmlControls.HtmlGenericControl);
- functions.Push (current_function);
- if (control_type != typeof (System.Web.UI.WebControls.ListItem) &&
- prev_children_kind != ChildrenKind.DBCOLUMNS) {
- current_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_" +
- "{0} ()\n\t\t{{\n\t\t\t{1} __ctrl;\n\n\t\t\t__ctrl" +
- " = new {1} ({2});\n\t\t\tthis.{0} = __ctrl;\n",
- control_id, control_type,
- (is_generic? "\"" + tag_id + "\"" : ""));
- } else {
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ()\n\t\t{{" +
- "\n\t\t\t{1} __ctrl;\n\t\t\t__ctrl = new {1} ();" +
- "\n\t\t\tthis.{0} = __ctrl;\n",
- control_id, control_type);
+ // if (current is TemplateBuilder)
+ // pop from the id list
+ current.CloseControl ();
+ stack.Pop ();
+ stack.Builder.AppendSubBuilder (current);
+ return true;
}
- if (children_kind == ChildrenKind.CONTROLS || children_kind == ChildrenKind.OPTION)
- current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
- "(System.Web.UI.IParserAccessor) __ctrl;\n");
- }
-
- private void DataBoundProperty (Type target, string varName, string value)
- {
- if (value == "")
- throw new ApplicationException ("Empty data binding tag.");
+ bool ProcessCode (TagType tagtype, string code, ILocation location)
+ {
+ ControlBuilder b = null;
+ if (tagtype == TagType.CodeRender)
+ b = new CodeRenderBuilder (code, false, location);
+ else if (tagtype == TagType.CodeRenderExpression)
+ b = new CodeRenderBuilder (code, true, location);
+ else if (tagtype == TagType.DataBinding)
+ b = new DataBindingBuilder (code, location);
+ else
+ throw new HttpException ("Should never happen");
- string control_id = controls.PeekControlID ();
- string control_type_string = controls.PeekType ().ToString ();
- StringBuilder db_function = controls.DataBindFunction;
- string container;
- if (controls.Container == null || !typeof (INamingContainer).IsAssignableFrom (controls.Container))
- container = "System.Web.UI.Control";
- else {
- container = controls.Container.ToString ();
+ stack.Builder.AppendSubBuilder (b);
+ return true;
}
- if (db_function.Length == 0)
- db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
- "System.EventArgs e) {{\n" +
- "\t\t\t{1} Container;\n" +
- "\t\t\t{2} target;\n" +
- "\t\t\ttarget = ({2}) sender;\n" +
- "\t\t\tContainer = ({1}) target.BindingContainer;\n",
- control_id, container, control_type_string);
-
- /* Removes '<%#' and '%>' */
- string real_value = value.Remove (0,3);
- real_value = real_value.Remove (real_value.Length - 2, 2);
- real_value = real_value.Trim ();
-
- if (target == typeof (string))
- db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n",
- varName, real_value);
- else
- db_function.AppendFormat ("\t\t\ttarget.{0} = ({1}) ({2});\n",
- varName, target, real_value);
- }
-
- /*
- * Returns true if it generates some code for the specified property
- */
- private void AddCodeForPropertyOrField (Type type, string var_name, string att, bool isDataBound)
- {
- /* FIXME: should i check for this or let the compiler fail?
- * if (!prop.CanWrite)
- * ....
- */
- if (isDataBound) {
- DataBoundProperty (type, var_name, att);
+ public ILocation Location {
+ get { return location; }
}
- else if (type == typeof (string)){
- if (att == null)
- throw new ApplicationException ("null value for attribute " + var_name );
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name,
- Escape (att)); // FIXME: really Escape this?
- }
- else if (type.IsEnum){
- if (att == null)
- throw new ApplicationException ("null value for attribute " + var_name );
-
- string enum_value = EnumValueNameToString (type, att);
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value);
- }
- else if (type == typeof (bool)){
- string value;
- if (att == null)
- value = "true"; //FIXME: is this ok for non Style properties?
- else if (0 == String.Compare (att, "true", true))
- value = "true";
- else if (0 == String.Compare (att, "false", true))
- value = "false";
- else
- throw new ApplicationException ("Value '" + att + "' is not a valid boolean.");
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (System.Web.UI.WebControls.Unit)){
- //FIXME: should use the culture specified in Page
- try {
- Unit value = Unit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
- } catch (Exception) {
- throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
- }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
- "System.Web.UI.WebControls.Unit.Parse (\"{1}\", " +
- "System.Globalization.CultureInfo.InvariantCulture);\n",
- var_name, att);
- }
- else if (type == typeof (System.Web.UI.WebControls.FontUnit)){
- //FIXME: should use the culture specified in Page
- try {
- FontUnit value = FontUnit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
- } catch (Exception) {
- throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
- }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
- "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " +
- "System.Globalization.CultureInfo.InvariantCulture);\n",
- var_name, att);
- }
- else if (type == typeof (Int16) || type == typeof (Int32) || type == typeof (Int64)) {
- long value;
- try {
- value = Int64.Parse (att); //FIXME: should use the culture specified in Page
- } catch (Exception){
- throw new ApplicationException (att + " is not a valid signed number " +
- "or is out of range.");
- }
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (UInt16) || type == typeof (UInt32) || type == typeof (UInt64)) {
- ulong value;
- try {
- value = UInt64.Parse (att); //FIXME: should use the culture specified in Page
- } catch (Exception){
- throw new ApplicationException (att + " is not a valid unsigned number " +
- "or is out of range.");
- }
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (float)) {
- float value;
- try {
- value = Single.Parse (att);
- } catch (Exception){
- throw new ApplicationException (att + " is not avalid float number or " +
- "is out of range.");
- }
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (double)){
- double value;
- try {
- value = Double.Parse (att);
- } catch (Exception){
- throw new ApplicationException (att + " is not avalid double number or " +
- "is out of range.");
- }
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (System.Drawing.Color)){
- Color c;
- try {
- c = (Color) TypeDescriptor.GetConverter (typeof (Color)).ConvertFromString (att);
- } catch (Exception e){
- throw new ApplicationException ("Color " + att + " is not a valid color.", e);
- }
-
- // Should i also test for IsSystemColor?
- // Are KnownColor members in System.Drawing.Color?
- if (c.IsKnownColor){
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
- "{1};\n", var_name, c.Name);
- }
- else {
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
- "FromArgb ({1}, {2}, {3}, {4});\n",
- var_name, c.A, c.R, c.G, c.B);
- }
- }
- else if (type == typeof (string [])) {
- string [] subStrings = att.Split (',');
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = new String [] {{\n", var_name);
- int end = subStrings.Length;
- for (int i = 0; i < end; i++) {
- string s = subStrings [i].Trim ();
- current_function.AppendFormat ("\t\t\t\t\"{0}\"", s);
- if (i == end - 1)
- current_function.Append ("\t\t\t\t};\n");
- else
- current_function.Append (",\n");
- }
- } else {
- throw new ApplicationException ("Unsupported type in property: " +
- type.ToString ());
- }
- }
-
- private bool ProcessPropertiesAndFields (MemberInfo member, string id, TagAttributes att)
- {
- int hyphen = id.IndexOf ('-');
-
- bool isPropertyInfo = (member is PropertyInfo);
-
- bool is_processed = false;
- bool isDataBound = att.IsDataBound ((string) att [id]);
- Type type;
- if (isPropertyInfo) {
- type = ((PropertyInfo) member).PropertyType;
- if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
- return false;
- } else {
- type = ((FieldInfo) member).FieldType;
- }
-
- if (0 == String.Compare (member.Name, id, true)){
- AddCodeForPropertyOrField (type, member.Name, (string) att [id], isDataBound);
- is_processed = true;
- } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
- string prop_field = id.Replace ("-", ".");
- string [] parts = prop_field.Split (new char [] {'.'});
- if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
- return false;
-
- PropertyInfo [] subprops = type.GetProperties ();
- foreach (PropertyInfo subprop in subprops){
- if (0 != String.Compare (subprop.Name, parts [1], true))
- continue;
-
- if (subprop.CanWrite == false)
- return false;
-
- bool is_bool = subprop.PropertyType == typeof (bool);
- if (!is_bool && att [id] == null){
- att [id] = ""; // Font-Size -> Font-Size="" as html
- return false;
- }
-
- string value;
- if (att [id] == null && is_bool)
- value = "true"; // Font-Bold <=> Font-Bold="true"
- else
- value = (string) att [id];
-
- AddCodeForPropertyOrField (subprop.PropertyType,
- member.Name + "." + subprop.Name,
- value, isDataBound);
- is_processed = true;
- }
- }
-
- return is_processed;
- }
-
- private void AddCodeForAttributes (Type type, TagAttributes att)
- {
- EventInfo [] ev_info = type.GetEvents ();
- PropertyInfo [] prop_info = type.GetProperties ();
- FieldInfo [] field_info = type.GetFields ();
- bool is_processed = false;
- ArrayList processed = new ArrayList ();
-
- foreach (string id in att.Keys){
- if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
- continue;
-
- if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
- string id_as_event = id.Substring (2);
- foreach (EventInfo ev in ev_info){
- if (0 == String.Compare (ev.Name, id_as_event, true)){
- current_function.AppendFormat (
- "\t\t\t__ctrl.{0} += " +
- "new {1} (this.{2});\n",
- ev.Name, ev.EventHandlerType, att [id]);
- is_processed = true;
- break;
- }
- }
- if (is_processed){
- is_processed = false;
- continue;
- }
- }
-
- foreach (PropertyInfo prop in prop_info){
- is_processed = ProcessPropertiesAndFields (prop, id, att);
- if (is_processed)
- break;
- }
-
- if (!is_processed) {
- foreach (FieldInfo field in field_info){
- is_processed = ProcessPropertiesAndFields (field, id, att);
- if (is_processed)
- break;
- }
- }
-
- if (is_processed){
- is_processed = false;
- continue;
- }
-
- current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." +
- "SetAttribute (\"{0}\", \"{1}\");\n",
- id, Escape ((string) att [id]));
- }
- }
-
- private void AddCodeRenderControl (StringBuilder function)
- {
- AddCodeRenderControl (function, controls.CodeRenderIndex);
- }
-
- private void AddCodeRenderControl (StringBuilder function, int index)
- {
- function.AppendFormat ("\t\t\tparameterContainer.Controls [{0}]." +
- "RenderControl (__output);\n", index);
- }
-
- private void AddRenderMethodDelegate (StringBuilder function, string control_id)
- {
- function.AppendFormat ("\t\t\t__ctrl.SetRenderMethodDelegate (new System.Web." +
- "UI.RenderMethod (this.__Render_{0}));\n", control_id);
- }
-
- private void AddCodeRenderFunction (string codeRender, string control_id)
- {
- StringBuilder codeRenderFunction = new StringBuilder ();
- codeRenderFunction.AppendFormat ("\t\tprivate void __Render_{0} " +
- "(System.Web.UI.HtmlTextWriter __output, " +
- "System.Web.UI.Control parameterContainer)\n" +
- "\t\t{{\n", control_id);
- codeRenderFunction.Append (codeRender);
- codeRenderFunction.Append ("\t\t}\n\n");
- init_funcs.Append (codeRenderFunction);
- }
-
- private void RemoveLiterals (StringBuilder function)
- {
- string no_literals = Regex.Replace (function.ToString (),
- @"\t\t\t__parser.AddParsedSubObject \(" +
- @"new System.Web.UI.LiteralControl \(.+\);\n", "");
- function.Length = 0;
- function.Append (no_literals);
- }
-
- private bool FinishControlFunction (string tag_id)
- {
- if (functions.Count == 0)
- throw new ApplicationException ("Unbalanced open/close tags");
-
- if (controls.Count == 0)
- return false;
-
- string saved_id = controls.PeekTagID ();
- if (0 != String.Compare (saved_id, tag_id, true))
- return false;
-
- FlushPlainText ();
- StringBuilder old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
-
- string control_id = controls.PeekControlID ();
- Type control_type = controls.PeekType ();
- ChildrenKind child_kind = controls.PeekChildKind ();
-
- bool hasDataBindFunction = controls.HasDataBindFunction ();
- if (hasDataBindFunction)
- old_function.AppendFormat ("\t\t\t__ctrl.DataBinding += new System.EventHandler " +
- "(this.__DataBind_{0});\n", control_id);
-
- bool useCodeRender = controls.UseCodeRender;
- if (useCodeRender)
- AddRenderMethodDelegate (old_function, control_id);
-
- if (control_type == typeof (System.Web.UI.ITemplate)){
- old_function.Append ("\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = new System.Web.UI." +
- "CompiledTemplateBuilder (new System.Web.UI." +
- "BuildTemplateMethod (this.__BuildControl_{1}));\n",
- saved_id, control_id);
- }
- else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumnCollection)){
- old_function.Append ("\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
- control_id, saved_id);
- }
- else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
- control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)) ||
- control_type == typeof (System.Web.UI.WebControls.ListItem)){
- old_function.Append ("\n\t\t}\n\n");
- string parsed = "";
- string ctrl_name = "ctrl";
- Type cont = controls.Container;
- if (cont == null || cont == typeof (System.Web.UI.HtmlControls.HtmlSelect)){
- parsed = "ParsedSubObject";
- ctrl_name = "parser";
- }
-
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
- "\t\t\t__{1}.Add{2} (this.{0});\n\n",
- control_id, ctrl_name, parsed);
- }
- else if (child_kind == ChildrenKind.LISTITEM){
- old_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (old_function); // Closes the BuildList function
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
- "return __ctrl;\n\t\t}}\n\n",
- control_id, controls.PeekDefaultPropertyName ());
-
- controls.Pop ();
- control_id = controls.PeekControlID ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
- } else if (control_type == typeof (HtmlTableCell) || control_type == typeof (TableCell)) {
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- object top = controls.Pop ();
- Type t = controls.PeekType ();
- controls.Push (top);
- string parsed = "";
- string ctrl_name = "ctrl";
- if (!t.IsSubclassOf (typeof (WebControl)) && t != typeof (HtmlTableRow)) {
- parsed = "ParsedSubObject";
- ctrl_name = "parser";
- }
-
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
- "\t\t\t__{1}.Add{2} (this.{0});\n\n",
- control_id, ctrl_name, parsed);
- } else if (child_kind == ChildrenKind.HTMLROW || child_kind == ChildrenKind.HTMLCELL) {
- old_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (old_function);
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
- "return __ctrl;\n\t\t}}\n\n",
- control_id, controls.PeekDefaultPropertyName ());
-
- controls.Pop ();
- control_id = controls.PeekControlID ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n", control_id);
- if (child_kind == ChildrenKind.HTMLROW) {
- current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject ({0});\n",
- control_id);
- } else {
- current_function.AppendFormat ("\t\t\t__ctrl.Add (this.{0});\n", control_id);
- }
- } else {
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
- }
-
- if (useCodeRender)
- RemoveLiterals (old_function);
-
- init_funcs.Append (old_function);
- if (useCodeRender)
- AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), control_id);
-
- if (hasDataBindFunction){
- StringBuilder db_function = controls.DataBindFunction;
- db_function.Append ("\t\t}\n\n");
- init_funcs.Append (db_function);
- }
-
- // Avoid getting empty stacks for unbalanced open/close tags
- if (controls.Count > 1){
- controls.Pop ();
- AddCodeRenderControl (controls.CodeRenderFunction, controls.ChildIndex);
- }
-
- return true;
- }
-
- private void NewTableElementFunction (HtmlControlTag ctrl)
- {
- string control_id = Tag.GetDefaultID ();
- ChildrenKind child_kind;
-
- Type t;
- if (ctrl.ControlType == typeof (HtmlTable)) {
- t = typeof (HtmlTableRowCollection);
- child_kind = ChildrenKind.HTMLROW;
- } else {
- t = typeof (HtmlTableCellCollection);
- child_kind = ChildrenKind.HTMLCELL;
- }
-
- controls.Push (ctrl.ControlType,
- control_id,
- ctrl.TagID,
- child_kind,
- ctrl.ParseChildren);
-
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
- "\t\t{{\n", control_id, t);
- }
-
- private void ProcessHtmlControlTag ()
- {
- FlushPlainText ();
- HtmlControlTag html_ctrl = (HtmlControlTag) current;
- if (html_ctrl.TagID.ToUpper () == "SCRIPT"){
- //FIXME: if the is script is to be read from disk, do it!
- if (html_ctrl.SelfClosing)
- throw new ApplicationException ("Read script from file not supported yet.");
-
- sstatus = ScriptStatus.Open;
- return;
- }
-
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
-
- Type controlType = html_ctrl.ControlType;
- AddProtectedField (controlType, html_ctrl.ControlID);
-
- ChildrenKind children_kind;
- if (0 == String.Compare (html_ctrl.TagID, "table", true))
- children_kind = ChildrenKind.HTMLROW;
- else if (0 == String.Compare (html_ctrl.TagID, "tr", true))
- children_kind = ChildrenKind.HTMLCELL;
- else if (0 != String.Compare (html_ctrl.TagID, "select", true))
- children_kind = html_ctrl.IsContainer ? ChildrenKind.CONTROLS :
- ChildrenKind.NONE;
- else
- children_kind = ChildrenKind.OPTION;
-
- NewControlFunction (html_ctrl.TagID, html_ctrl.ControlID, controlType, children_kind, html_ctrl.ParseChildren);
-
- current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID);
- AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes);
-
- if (children_kind == ChildrenKind.HTMLROW || children_kind == ChildrenKind.HTMLCELL)
- NewTableElementFunction (html_ctrl);
-
- if (html_ctrl.SelfClosing)
- FinishControlFunction (html_ctrl.TagID);
- }
-
- // Closing is performed in FinishControlFunction ()
- private void NewBuildListFunction (AspComponent component)
- {
- string control_id = Tag.GetDefaultID ();
-
- controls.Push (component.ComponentType,
- control_id,
- component.TagID,
- component.ChildrenKind,
- component.DefaultPropertyName);
-
- Type childType = component.DefaultPropertyType;
- if (childType == null)
- childType = typeof (ListItemCollection);
-
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "({1} __ctrl)\n" +
- "\t\t{{\n", control_id, childType);
- }
-
- private void ProcessComponent ()
- {
- FlushPlainText ();
- AspComponent component = (AspComponent) current;
- Type component_type = component.ComponentType;
- AddProtectedField (component_type, component.ControlID);
-
- NewControlFunction (component.TagID, component.ControlID, component_type,
- component.ChildrenKind, component.DefaultPropertyName);
-
- if (component_type == typeof (UserControl) ||
- component_type.IsSubclassOf (typeof (System.Web.UI.UserControl)))
- current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n");
-
- if (component_type == typeof (Control) ||
- component_type.IsSubclassOf (typeof (System.Web.UI.Control)))
- current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", component.ControlID);
-
- AddCodeForAttributes (component.ComponentType, component.Attributes);
- if (component.ChildrenKind == ChildrenKind.LISTITEM || component.DefaultPropertyType != null)
- NewBuildListFunction (component);
-
- if (component.SelfClosing)
- FinishControlFunction (component.TagID);
- }
-
- private void ProcessServerObjectTag ()
- {
- FlushPlainText ();
- ServerObjectTag obj = (ServerObjectTag) current;
- declarations.AppendFormat ("\t\tprivate {0} cached{1};\n", obj.ObjectClass, obj.ObjectID);
- constructor.AppendFormat ("\n\t\tprivate {0} {1}\n\t\t{{\n\t\t\tget {{\n\t\t\t\t" +
- "if (this.cached{1} == null)\n\t\t\t\t\tthis.cached{1} = " +
- "new {0} ();\n\t\t\t\treturn cached{1};\n\t\t\t}}\n\t\t}}\n\n",
- obj.ObjectClass, obj.ObjectID);
- }
-
- // Creates a new function that sets the values of subproperties.
- private void NewStyleFunction (PropertyTag tag)
- {
- current_function = new StringBuilder ();
-
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- // begin function
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
- "\t\t{{\n", prop_id, prop_type);
-
- // Add property initialization code
- PropertyInfo [] subprop_info = prop_type.GetProperties ();
- TagAttributes att = tag.Attributes;
-
- string subprop_name = null;
- foreach (string id in att.Keys){
- if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
- continue;
-
- bool is_processed = false;
- foreach (PropertyInfo subprop in subprop_info){
- is_processed = ProcessPropertiesAndFields (subprop, id, att);
- if (is_processed){
- subprop_name = subprop.Name;
- break;
- }
- }
-
- if (subprop_name == null)
- throw new ApplicationException ("Property " + tag.TagID + " does not have " +
- "a " + id + " subproperty.");
- }
-
- // Finish function
- current_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (current_function);
- current_function = (StringBuilder) functions.Peek ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
- prop_id, tag.PropertyName);
-
- if (!tag.SelfClosing){
- // Next tag should be the closing tag
- controls.Push (null, null, null, ChildrenKind.NONE, null);
- waitClosing = tag.TagID;
- }
- }
-
- // This one just opens the function. Closing is performed in FinishControlFunction ()
- private void NewTemplateFunction (PropertyTag tag)
- {
- /*
- * FIXME
- * This function does almost the same as NewControlFunction.
- * Consider merging.
- */
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
- controls.Push (prop_type, prop_id, tag_id, ChildrenKind.CONTROLS, null);
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "(System.Web.UI.Control __ctrl)\n" +
- "\t\t{{\n" +
- "\t\t\tSystem.Web.UI.IParserAccessor __parser " +
- "= (System.Web.UI.IParserAccessor) __ctrl;\n" , prop_id);
- }
-
- // Closing is performed in FinishControlFunction ()
- private void NewDBColumnFunction (PropertyTag tag)
- {
- /*
- * FIXME
- * This function also does almost the same as NewControlFunction.
- * Consider merging.
- */
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
- controls.Push (prop_type, prop_id, tag_id, ChildrenKind.DBCOLUMNS, null);
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "(System.Web.UI.WebControls.DataGridColumnCollection __ctrl)\n" +
- "\t\t{{\n", prop_id);
- }
-
- private void NewPropertyFunction (PropertyTag tag)
- {
- FlushPlainText ();
- if (tag.PropertyType == typeof (System.Web.UI.WebControls.Style) ||
- tag.PropertyType.IsSubclassOf (typeof (System.Web.UI.WebControls.Style)))
- NewStyleFunction (tag);
- else if (tag.PropertyType == typeof (System.Web.UI.ITemplate))
- NewTemplateFunction (tag);
- else if (tag.PropertyType == typeof (System.Web.UI.WebControls.DataGridColumnCollection))
- NewDBColumnFunction (tag);
- else
- throw new ApplicationException ("Other than Style and ITemplate not supported yet. " +
- tag.PropertyType);
- }
-
- private void ProcessHtmlTag ()
- {
- Tag tag = (Tag) current;
- ChildrenKind child_kind = controls.PeekChildKind ();
- if (child_kind == ChildrenKind.NONE){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException (tag + " not allowed inside " + tag_id);
- }
-
- if (child_kind == ChildrenKind.OPTION){
- if (0 != String.Compare (tag.TagID, "option", true))
- throw new ApplicationException ("Only <option> tags allowed inside <select>.");
-
- string default_id = Tag.GetDefaultID ();
- Type type = typeof (System.Web.UI.WebControls.ListItem);
- AddProtectedField (type, default_id);
- NewControlFunction (tag.TagID, default_id, type, ChildrenKind.CONTROLS, null);
- return;
- }
-
- if (child_kind == ChildrenKind.CONTROLS) {
- ArrayList tag_elements = tag.GetElements ();
- foreach (Element e in tag_elements) {
- if (e is PlainText) {
- current = e;
- textChunk.Append (((PlainText) e).Text);
- } else if (e is CodeRenderTag) {
- current = e;
- ProcessCodeRenderTag ();
- } else if (e is DataBindingTag) {
- current = e;
- ProcessDataBindingLiteral ();
- } else {
- throw new ApplicationException (fullPath + ": unexpected tag type " + e.GetType ());
- }
- }
- return;
- }
-
- if (child_kind == ChildrenKind.HTMLROW) {
- if (0 == String.Compare (tag.TagID, "tr", true)) {
- current = new HtmlControlTag (tag);
- ProcessHtmlControlTag ();
- return;
- }
- }
-
- if (child_kind == ChildrenKind.HTMLCELL) {
- if (0 == String.Compare (tag.TagID, "td", true)) {
- current = new HtmlControlTag (tag);
- ProcessHtmlControlTag ();
- return;
- }
- }
-
- // Now child_kind should be PROPERTIES, so only allow tag_id == property
- Type control_type = controls.PeekType ();
- PropertyInfo [] prop_info = control_type.GetProperties ();
- bool is_processed = false;
- foreach (PropertyInfo prop in prop_info){
- if (0 == String.Compare (prop.Name, tag.TagID, true)){
- PropertyTag prop_tag = new PropertyTag (tag, prop.PropertyType, prop.Name);
- NewPropertyFunction (prop_tag);
- is_processed = true;
- break;
- }
- }
-
- if (!is_processed){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException (tag.TagID + " is not a property of " + control_type);
- }
- }
-
- private Tag Map (Tag tag)
- {
- int pos = tag.TagID.IndexOf (":");
- if (pos == -1) {
- ChildrenKind child_kind = controls.PeekChildKind ();
- if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
- tag.Attributes.Add ("runat", "server");
- return new HtmlControlTag (tag);
- } else if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
- tag.Attributes.Add ("runat", "server");
- return new HtmlControlTag (tag);
- }
- }
-
- if (tag is CloseTag ||
- ((tag.Attributes == null ||
- !tag.Attributes.IsRunAtServer ()) && pos == -1))
- return tag;
-
- if (pos == -1){
- if (0 == String.Compare (tag.TagID, "object", true))
- return new ServerObjectTag (tag);
-
- return new HtmlControlTag (tag);
- }
-
- string foundry_name = tag.TagID.Substring (0, pos);
- string component_name = tag.TagID.Substring (pos + 1);
-
- if (Foundry.LookupFoundry (foundry_name) == false)
- throw new ApplicationException ("Cannot find foundry for alias'" + foundry_name + "'");
-
- AspComponent component = Foundry.MakeAspComponent (foundry_name, component_name, tag);
- if (component == null)
- throw new ApplicationException ("Cannot find component '" + component_name +
- "' for alias '" + foundry_name + "'");
-
- return component;
- }
-
- private void ProcessCloseTag ()
- {
- CloseTag closeTag = (CloseTag) current;
- if (FinishControlFunction (closeTag.TagID))
- return;
-
- textChunk.Append (closeTag.PlainHtml);
- }
-
- private void ProcessDataBindingLiteral ()
- {
- FlushPlainText ();
- DataBindingTag dataBinding = (DataBindingTag) current;
- string actual_value = dataBinding.Data;
- if (actual_value == "")
- throw new ApplicationException ("Empty data binding tag.");
-
- if (controls.PeekChildKind () != ChildrenKind.CONTROLS)
- throw new ApplicationException ("Data bound content not allowed for " +
- controls.PeekTagID ());
-
- StringBuilder db_function = new StringBuilder ();
- string control_id = Tag.GetDefaultID ();
- string control_type_string = "System.Web.UI.DataBoundLiteralControl";
- AddProtectedField (typeof (System.Web.UI.DataBoundLiteralControl), control_id);
- // Build the control
- db_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_{0} ()\n" +
- "\t\t{{\n\t\t\t{1} __ctrl;\n\n" +
- "\t\t\t__ctrl = new {1} (0, 1);\n" +
- "\t\t\tthis.{0} = __ctrl;\n" +
- "\t\t\t__ctrl.DataBinding += new System.EventHandler " +
- "(this.__DataBind_{0});\n" +
- "\t\t\treturn __ctrl;\n"+
- "\t\t}}\n\n",
- control_id, control_type_string);
- // DataBinding handler
- db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
- "System.EventArgs e) {{\n" +
- "\t\t\t{1} Container;\n" +
- "\t\t\t{2} target;\n" +
- "\t\t\ttarget = ({2}) sender;\n" +
- "\t\t\tContainer = ({1}) target.BindingContainer;\n" +
- "\t\t\ttarget.SetDataBoundString (0, System.Convert." +
- "ToString ({3}));\n" +
- "\t\t}}\n\n",
- control_id, controls.Container, control_type_string,
- actual_value);
-
- init_funcs.Append (db_function);
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
-
- AddCodeRenderControl (controls.CodeRenderFunction);
- }
-
- private void ProcessCodeRenderTag ()
- {
- FlushPlainText ();
- CodeRenderTag code_tag = (CodeRenderTag) current;
-
- controls.UseCodeRender = true;
- if (code_tag.IsVarName)
- controls.CodeRenderFunction.AppendFormat ("\t\t\t__output.Write ({0});\n",
- code_tag.Code);
- else
- controls.CodeRenderFunction.AppendFormat ("\t\t\t{0}\n", code_tag.Code);
- }
-
- void FlushPlainText ()
- {
- if (textChunk.Length != 0) {
- Element saved = current;
- current = new PlainText (textChunk.ToString ());
- textChunk.Length = 0;
- ProcessPlainText ();
- current = saved;
- }
- }
-
- void ParseError (string msg, int line, int col)
- {
- throw new ParseException (fullPath, msg, line, col);
- }
-
- void TagParsed (Tag tag, int line, int col)
- {
- if (waitClosing != null) {
- if (!(tag is CloseTag) || tag.TagID.ToUpper () != waitClosing.ToUpper ())
- throw new HttpException ("Tag " + waitClosing + " not properly closed.");
-
- waitClosing = null;
- controls.Pop ();
- return;
- }
-
- if ((sstatus == ScriptStatus.Open || sstatus == ScriptStatus.Text) &&
- tag.TagID.ToUpper () == "SCRIPT" && tag is CloseTag) {
- sstatus = ScriptStatus.Close;
- return;
- }
-
- current = tag;
-
- if (current is Directive) {
- ProcessDirective ();
- return;
- } else if (current is DataBindingTag) {
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
-
- ProcessDataBindingLiteral ();
- return;
- } else if (current is CodeRenderTag) {
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
-
- ProcessCodeRenderTag ();
- return;
- }
-
- current = Map (tag);
-
- if (current is ServerObjectTag) {
- ProcessServerObjectTag ();
- return;
- } else if (current is HtmlControlTag) {
- ProcessHtmlControlTag ();
- return;
- }
-
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
-
- if (current is AspComponent) {
- ProcessComponent ();
- } else if (current is CloseTag) {
- ProcessCloseTag ();
- } else if (current is Tag) {
- ProcessHtmlTag ();
- } else {
- throw new HttpException ("This place should not be reached.");
- }
- }
-
- void TextParsed (string text, int line, int col)
- {
- if (sstatus == ScriptStatus.Open) {
- script.Append (text);
- sstatus = ScriptStatus.Text;
- return;
- }
-
- textChunk.Append (text);
- }
-
- public void ProcessElements ()
- {
- AspParser parser = new AspParser (fullPath, File.OpenRead (fullPath));
-
- parser.Error += new ParseErrorHandler (ParseError);
- parser.TagParsed += new TagParsedHandler (TagParsed);
- parser.TextParsed += new TextParsedHandler (TextParsed);
-
- try {
- parser.Parse ();
- } catch (CompilationException e) {
- throw;
- } catch (ParseException e) {
- throw;
- } catch (Exception e) {
- throw new ParseException (fullPath, e.Message, parser.Line, parser.Column, e);
- }
-
- End ();
- parse_ok = true;
- }
-
- private string GetTemplateDirectory ()
- {
- string templatePath = Path.GetDirectoryName (fullPath);
- string appPath = Path.GetDirectoryName (HttpRuntime.AppDomainAppPath);
-
- if (templatePath == appPath)
- return "/";
-
- templatePath = templatePath.Substring (appPath.Length);
- if (Path.DirectorySeparatorChar != '/')
- templatePath = templatePath.Replace (Path.DirectorySeparatorChar, '/');
-
- return templatePath;
- }
-
- private void End ()
- {
- FlushPlainText ();
-
- if (isPage) {
- if (sessionState == SessionState.Enabled || sessionState == SessionState.ReadOnly)
- AddInterface (typeof (System.Web.SessionState.IRequiresSessionState));
-
- if (sessionState == SessionState.ReadOnly)
- AddInterface (typeof (System.Web.SessionState.IReadOnlySessionState));
- }
-
- classDecl = "\tpublic class " + className + " : " + parent + interfaces + " {\n";
- prolog.Append ("\n" + classDecl);
- declarations.Append ("\t\tprivate static bool __intialized = false;\n\n");
- if (IsPage)
- declarations.Append ("\t\tprivate static ArrayList __fileDependencies;\n\n");
-
- // adds the constructor
- constructor.AppendFormat ("\t\tpublic {0} ()\n\t\t{{\n", className);
- if (!IsApplication)
- constructor.Append ("\t\t\tSystem.Collections.ArrayList dependencies;\n\n");
-
- constructor.AppendFormat ("\t\t\tif (ASP.{0}.__intialized == false){{\n", className);
-
- if (IsPage) {
- constructor.AppendFormat ("\t\t\t\tdependencies = new System.Collections.ArrayList ();\n" +
- "\t\t\t\tdependencies.Add (@\"{1}\");\n" +
- "\t\t\t\tASP.{0}.__fileDependencies = dependencies;\n",
- className, fullPath);
- }
-
- constructor.AppendFormat ("\t\t\t\tASP.{0}.__intialized = true;\n\t\t\t}}\n\t\t}}\n\n",
- className);
-
- if (!IsApplication) {
- //FIXME: add AutoHandlers: don't know what for...yet!
- constructor.AppendFormat (
- "\t\tprotected override int AutoHandlers\n\t\t{{\n" +
- "\t\t\tget {{ return ASP.{0}.__autoHandlers; }}\n" +
- "\t\t\tset {{ ASP.{0}.__autoHandlers = value; }}\n" +
- "\t\t}}\n\n", className);
-
- constructor.Append (
- "\t\tprotected System.Web.HttpApplication ApplicationInstance\n\t\t{\n" +
- "\t\t\tget { return (System.Web.HttpApplication) this.Context.ApplicationInstance; }\n" +
- "\t\t}\n\n");
-
- constructor.AppendFormat (
- "\t\tpublic override string TemplateSourceDirectory\n\t\t{{\n" +
- "\t\t\tget {{ return \"{0}\"; }}\n" +
- "\t\t}}\n\n", GetTemplateDirectory ());
-
- epilog.Append ("\n\t\tprotected override void FrameworkInitialize ()\n\t\t{\n" +
- "\t\t\tthis.__BuildControlTree (this);\n");
-
- if (IsPage) {
- epilog.AppendFormat ("\t\t\tthis.FileDependencies = ASP.{0}.__fileDependencies;\n" +
- "\t\t\tthis.EnableViewStateMac = true;\n", className);
- }
-
- epilog.Append ("\t\t}\n\n");
- }
-
- if (IsPage) {
- Random rnd = new Random ();
- epilog.AppendFormat ("\t\tpublic override int GetTypeHashCode ()\n\t\t{{\n" +
- "\t\t\treturn {0};\n" +
- "\t\t}}\n", rnd.Next ());
- }
-
- epilog.Append ("\t}\n}\n");
-
- // Closes the currently opened tags
- StringBuilder old_function = current_function;
- string control_id;
- while (functions.Count > 1){
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- init_funcs.Append (old_function);
- control_id = controls.PeekControlID ();
- FinishControlFunction (control_id);
- controls.AddChild ();
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- controls.Pop ();
- }
-
- bool useCodeRender = controls.UseCodeRender;
- if (useCodeRender){
- RemoveLiterals (current_function);
- AddRenderMethodDelegate (current_function, controls.PeekControlID ());
- }
-
- current_function.Append ("\t\t}\n\n");
- init_funcs.Append (current_function);
- if (useCodeRender)
- AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), controls.PeekControlID ());
-
- functions.Pop ();
- }
-
- //
- // Functions related to compilation of user controls
- //
-
- private static char dirSeparator = Path.DirectorySeparatorChar;
- struct UserControlData
- {
- public UserControlResult result;
- public string className;
- public string assemblyName;
}
-
- private UserControlData GenerateUserControl (string src, HttpContext context)
- {
- UserControlData data = new UserControlData ();
- data.result = UserControlResult.OK;
-
- UserControlCompiler compiler = new UserControlCompiler (new UserControlParser (src, context));
- Type t = compiler.GetCompiledType ();
- if (t == null) {
- data.result = UserControlResult.CompilationFailed;
- return data;
- }
-
- data.className = t.Name;
- data.assemblyName = compiler.TargetFile;
- dependencies.Add (src);
- foreach (string s in compiler.Dependencies)
- dependencies.Add (s);
-
- return data;
- }
-}
-
}
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
using System.Collections;
namespace System.Web.Compilation
{
- delegate void ParseErrorHandler (string msg, int line, int col);
- delegate void TagParsedHandler (Tag tag, int line, int col);
- delegate void TextParsedHandler (string text, int line, int col);
+ delegate void ParseErrorHandler (ILocation location, string message);
+ delegate void TextParsedHandler (ILocation location, string text);
+ delegate void TagParsedHandler (ILocation location, TagType tagtype, string id, TagAttributes attributes);
+
+ class AspParser : ILocation
+ {
+ AspTokenizer tokenizer;
+ int beginLine, endLine;
+ int beginColumn, endColumn;
+ int beginPosition, endPosition;
+ string filename;
+ string fileText;
+ string verbatimID;
+
+ public AspParser (string filename, StreamReader input)
+ {
+ this.filename = filename;
+ fileText = input.ReadToEnd ();
+ StringReader reader = new StringReader (fileText);
+ tokenizer = new AspTokenizer (reader);
+ }
- class AspParser {
- private AspTokenizer tokenizer;
+ public int BeginLine {
+ get { return beginLine; }
+ }
- public AspParser (AspTokenizer tokenizer)
- {
- this.tokenizer = tokenizer;
+ public int BeginColumn {
+ get { return beginColumn; }
}
- public AspParser (string filename, Stream input) :
- this (new AspTokenizer (filename, input))
- {
+ public int EndLine {
+ get { return endLine; }
}
- public int Line {
- get {return tokenizer.Line; }
+ public int EndColumn {
+ get { return endColumn; }
}
- public int Column {
- get {return tokenizer.Column; }
+ public string PlainText {
+ get {
+ if (beginPosition >= endPosition)
+ return null;
+
+ return fileText.Substring (beginPosition, endPosition - beginPosition);
+ }
}
- private bool Eat (int expected_token)
+ public string Filename {
+ get { return filename; }
+ }
+
+ public string VerbatimID {
+ set {
+ tokenizer.Verbatim = true;
+ verbatimID = value.ToUpper ();
+ }
+ }
+
+ bool Eat (int expected_token)
{
if (tokenizer.get_token () != expected_token) {
tokenizer.put_back ();
return false;
}
+
+ endLine = tokenizer.EndLine;
+ endColumn = tokenizer.EndColumn;
return true;
}
+ void BeginElement ()
+ {
+ beginLine = tokenizer.BeginLine;
+ beginColumn = tokenizer.BeginColumn;
+ beginPosition = tokenizer.Position - 1;
+ }
+
+ void EndElement ()
+ {
+ endLine = tokenizer.EndLine;
+ endColumn = tokenizer.EndColumn;
+ endPosition = tokenizer.Position;
+ }
+
public void Parse ()
{
int token;
- Element element;
- Tag tag_element;
- string tag = "";
+ string id;
+ TagAttributes attributes;
+ TagType tagtype;
+ StringBuilder text = new StringBuilder ();
+
+ while ((token = tokenizer.get_token ()) != Token.EOF) {
+ BeginElement ();
- while ((token = tokenizer.get_token ()) != Token.EOF){
if (tokenizer.Verbatim){
- string end_verbatim = "</" + tag + ">";
+ string end_verbatim = "</" + verbatimID + ">";
string verbatim_text = GetVerbatim (token, end_verbatim);
if (verbatim_text == null)
- OnError ("Unexpected EOF processing " + tag);
+ OnError ("Unexpected EOF processing " + verbatimID);
- OnTextParsed (verbatim_text);
- OnTagParsed (new CloseTag (tag));
tokenizer.Verbatim = false;
- }
- else if (token == '<') {
- element = GetTag ();
- if (element == null)
- OnError ("");
- if (element is ServerComment)
- continue;
-
- if (!(element is Tag)){
- OnTextParsed (((PlainText) element).Text);
+ EndElement ();
+ endPosition -= end_verbatim.Length;
+ OnTextParsed (verbatim_text);
+ beginPosition = endPosition;
+ endPosition += end_verbatim.Length;
+ OnTagParsed (TagType.Close, verbatimID, null);
+ continue;
+ }
+
+ if (token == '<') {
+ GetTag (out tagtype, out id, out attributes);
+ EndElement ();
+ if (tagtype == TagType.ServerComment)
continue;
- }
- OnTagParsed ((Tag) element);
+ if (tagtype == TagType.Text)
+ OnTextParsed (id);
+ else
+ OnTagParsed (tagtype, id, attributes);
- tag_element = (Tag) element;
- //FIXME: move this to the TagParsed handler.
- 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 ();
- OnTextParsed (text.ToString ());
+ continue;
}
+
+ text.Length = 0;
+ do {
+ text.Append (tokenizer.Value);
+ token = tokenizer.get_token ();
+ } while (token != '<' && token != Token.EOF);
+
+ tokenizer.put_back ();
+ EndElement ();
+ OnTextParsed (text.ToString ());
}
}
- private Element GetTag ()
+ void GetTag (out TagType tagtype, out string id, out TagAttributes attributes)
{
int token = tokenizer.get_token ();
- string id;
+ tagtype = TagType.ServerComment;
+ id = null;
+ attributes = null;
switch (token){
case '%':
- return GetServerTag ();
+ GetServerTag (out tagtype, out id, out attributes);
+ break;
case '/':
if (!Eat (Token.IDENTIFIER))
OnError ("expecting TAGNAME");
- id = tokenizer.value;
+ id = tokenizer.Value;
if (!Eat ('>'))
OnError ("expecting '>'");
- return new CloseTag (id);
+ tagtype = TagType.Close;
+ break;
case '!':
bool double_dash = Eat (Token.DOUBLEDASH);
if (double_dash)
if (comment == null)
OnError ("Unfinished HTML comment/DTD");
- return new PlainText ("<!" + comment + end);
+ tagtype = TagType.Text;
+ id = "<!" + comment + end;
+ break;
case Token.IDENTIFIER:
- id = tokenizer.value;
- Tag tag = new Tag (id, GetAttributes (), Eat ('/'));
- if (!Eat ('>'))
+ id = tokenizer.Value;
+ attributes = GetAttributes ();
+ tagtype = TagType.Tag;
+ if (Eat ('/') && Eat ('>'))
+ tagtype = TagType.SelfClosing;
+ else if (!Eat ('>'))
OnError ("expecting '>'");
- return tag;
+
+ break;
default:
- return new PlainText ("<" + tokenizer.value);
+ tagtype = TagType.Text;
+ id = "<" + tokenizer.Value;
+ break;
}
}
- private TagAttributes GetAttributes ()
+ TagAttributes GetAttributes ()
{
int token;
TagAttributes attributes;
while ((token = tokenizer.get_token ()) != Token.EOF){
if (token != Token.IDENTIFIER)
break;
- id = tokenizer.value;
+ id = tokenizer.Value;
if (Eat ('=')){
if (Eat (Token.ATTVALUE)){
- attributes.Add (id, tokenizer.value);
+ attributes.Add (id, tokenizer.Value);
} else {
//TODO: support data binding syntax without quotes
OnError ("expected ATTVALUE");
return attributes;
}
- private string GetVerbatim (int token, string end)
+ string GetVerbatim (int token, string end)
{
StringBuilder vb_text = new StringBuilder ();
int i = 0;
- if (tokenizer.value.Length > 1){
+ if (tokenizer.Value.Length > 1){
// May be we have a put_back token that is not a single character
- vb_text.Append (tokenizer.value);
+ vb_text.Append (tokenizer.Value);
token = tokenizer.get_token ();
}
break;
token = tokenizer.get_token ();
continue;
- }
- else {
+ } else if (i > 0) {
for (int j = 0; j < i; j++)
vb_text.Append (end [j]);
+ i = 0;
}
- i = 0;
vb_text.Append ((char) token);
token = tokenizer.get_token ();
}
- if (token == Token.EOF)
- return null;
-
return RemoveComments (vb_text.ToString ());
}
- private string RemoveComments (string text)
+ string RemoveComments (string text)
{
int end;
int start = text.IndexOf ("<%--");
return text;
}
- private Element GetServerTag ()
+ void GetServerTag (out TagType tagtype, out string id, out TagAttributes attributes)
{
- string id;
string inside_tags;
- TagAttributes attributes;
if (Eat ('@')){
- id = (Eat (Token.DIRECTIVE) ? tokenizer.value : "Page");
+ tagtype = TagType.Directive;
+ id = "";
+ if (Eat (Token.DIRECTIVE))
+ id = tokenizer.Value;
+
attributes = GetAttributes ();
if (!Eat ('%') || !Eat ('>'))
OnError ("expecting '%>'");
- return new Directive (id, attributes);
- } else if (Eat (Token.DOUBLEDASH)) {
+ return;
+ }
+
+ if (Eat (Token.DOUBLEDASH)) {
tokenizer.Verbatim = true;
inside_tags = GetVerbatim (tokenizer.get_token (), "--%>");
tokenizer.Verbatim = false;
- return new ServerComment ("<%--" + inside_tags + "--%>");
+ id = null;
+ attributes = null;
+ tagtype = TagType.ServerComment;
+ return;
}
bool varname;
tokenizer.Verbatim = true;
inside_tags = GetVerbatim (tokenizer.get_token (), "%>");
tokenizer.Verbatim = false;
- if (databinding)
- return new DataBindingTag (inside_tags);
-
- return new CodeRenderTag (varname, inside_tags);
+ id = inside_tags;
+ attributes = null;
+ tagtype = (databinding ? TagType.DataBinding :
+ (varname ? TagType.CodeRenderExpression : TagType.CodeRender));
}
public event ParseErrorHandler Error;
void OnError (string msg)
{
if (Error != null)
- Error (msg, tokenizer.Line, tokenizer.Column);
+ Error (this, msg);
}
- void OnTagParsed (Tag tag)
+ void OnTagParsed (TagType tagtype, string id, TagAttributes attributes)
{
if (TagParsed != null)
- TagParsed (tag, tokenizer.Line, tokenizer.Column);
+ TagParsed (this, tagtype, id, attributes);
}
void OnTextParsed (string text)
{
if (TextParsed != null)
- TextParsed (text, tokenizer.Line, tokenizer.Column);
+ TextParsed (this, text);
}
}
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
using System.IO;
using System.Text;
-namespace System.Web.Compilation {
-
+namespace System.Web.Compilation
+{
class Token
{
public const int EOF = 0;
public const int IDENTIFIER = 1000;
- public const int DIRECTIVE = 1001;
+ 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;
+ class AspTokenizer
+ {
+ TextReader sr;
+ int current_token;
+ StringBuilder sb;
+ int col, line;
+ int begcol, begline;
+ int position;
+ bool inTag;
+ bool hasPutBack;
+ bool verbatim;
+ bool have_value;
+ string val;
- public AspTokenizer (string filename, Stream stream)
+ public AspTokenizer (TextReader reader)
{
- if (filename == null || stream == null)
- throw new ArgumentNullException ();
-
- this.sr = new StreamReader (stream);
- this.filename = filename;
+ this.sr = reader;
sb = new StringBuilder ();
col = line = 1;
hasPutBack = inTag = false;
public void put_back ()
{
if (hasPutBack)
- throw new ApplicationException ("put_back called twice!");
-
+ throw new HttpException ("put_back called twice!");
+
hasPutBack = true;
+ position -= Value.Length;
}
public int get_token ()
{
if (hasPutBack){
hasPutBack = false;
+ position += Value.Length;
return current_token;
}
+ begline = line;
+ begcol = col;
+ have_value = false;
current_token = NextToken ();
return current_token;
}
return (Char.IsLetterOrDigit (c) || c == '_' || c == '-');
}
- private int read_char ()
+ int read_char ()
{
int c = sr.Read ();
- if (c == '\r' && sr.Peek () == '\n')
+ if (c == '\r' && sr.Peek () == '\n') {
c = sr.Read ();
+ position++;
+ }
if (c == '\n'){
- col = 0;
+ col = -1;
line++;
}
- else if (c != -1)
+
+ if (c != -1) {
col++;
+ position++;
+ }
return c;
}
- private int ReadAttValue (int start)
+ int ReadAttValue (int start)
{
int quoteChar = 0;
bool quoted = false;
return Token.ATTVALUE;
}
- private int NextToken ()
+ int NextToken ()
{
int c;
sb.Append ((char) read_char ());
}
- if (current_token == '@' && Directive.IsDirectiveID (sb.ToString ()))
+ if (current_token == '@' && Directive.IsDirective (sb.ToString ()))
return Token.DIRECTIVE;
-
+
return Token.IDENTIFIER;
}
return Token.EOF;
}
- public string value {
- get { return sb.ToString (); }
- }
-
- public int Line {
+ public string Value {
get {
- return line;
+ if (have_value)
+ return val;
+
+ have_value = true;
+ val = sb.ToString ();
+ return val;
}
}
- public int Column {
- get {
- return col;
- }
+ public int BeginLine {
+ get { return begline; }
}
- public string Location {
- get {
- string msg = filename;
- msg += " (" + line + ", " + col + "): " + sb.ToString ();
- return msg;
- }
+ public int BeginColumn {
+ get { return begcol; }
}
+ public int EndLine {
+ get { return line; }
+ }
+
+ public int EndColumn {
+ get { return col; }
+ }
+
+ public int Position {
+ get { return position; }
+ }
}
}
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
using System.Collections;
-using System.IO;
+using System.Reflection;
using System.Text;
+using System.Web.UI;
+//temp:
+using Microsoft.CSharp;
+using System.IO;
namespace System.Web.Compilation
{
abstract class BaseCompiler
{
- //FIXME: configurable?
- static string default_assemblies = "System.Web.dll, System.Data.dll, System.Drawing.dll";
- static Random rnd = new Random ((int) DateTime.Now.Ticks);
- string randomName;
- protected Hashtable options;
- protected ArrayList dependencies;
-
- protected BaseCompiler ()
+ TemplateParser parser;
+ CodeDomProvider provider;
+ ICodeCompiler compiler;
+ CodeCompileUnit unit;
+ CodeNamespace mainNS;
+ CompilerParameters compilerParameters;
+ protected CodeTypeDeclaration mainClass;
+ protected CodeTypeReferenceExpression mainClassExpr;
+ protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
+
+ protected BaseCompiler (TemplateParser parser)
{
+ compilerParameters = new CompilerParameters ();
+ this.parser = parser;
}
- public virtual Type GetCompiledType ()
+ void Init ()
{
- return null;
- }
+ unit = new CodeCompileUnit ();
+ mainNS = new CodeNamespace ("ASP");
+ unit.Namespaces.Add (mainNS);
+ mainClass = new CodeTypeDeclaration (parser.ClassName);
+ mainClass.TypeAttributes = TypeAttributes.Public;
+ mainNS.Types.Add (mainClass);
+ mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName));
+ mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName);
+ foreach (object o in parser.Imports) {
+ if (o is string)
+ mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
+ }
- public virtual string Key {
- get {
- return null;
+ if (parser.Assemblies != null) {
+ foreach (object o in parser.Assemblies) {
+ if (o is string)
+ unit.ReferencedAssemblies.Add ((string) o);
+ }
}
+
+ AddInterfaces ();
+ CreateStaticFields ();
+ AddScripts ();
+ CreateConstructor (null, null);
}
- public virtual string SourceFile {
- get {
- return null;
- }
+ void BuildTree ()
+ {
+ Init ();
+ CreateMethods ();
}
- public virtual string [] Dependencies {
- get {
- if (dependencies == null)
- return new string [0];
+ protected virtual void CreateStaticFields ()
+ {
+ CodeMemberField fld = new CodeMemberField (typeof (bool), "__intialized");
+ fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
+ fld.InitExpression = new CodePrimitiveExpression (false);
+ mainClass.Members.Add (fld);
+ }
- return (string []) dependencies.ToArray (typeof (string));
+ protected virtual void CreateConstructor (CodeStatementCollection localVars, CodeStatementCollection trueStmt)
+ {
+ CodeConstructor ctor = new CodeConstructor ();
+ ctor.Attributes = MemberAttributes.Public;
+ mainClass.Members.Add (ctor);
+
+ if (localVars != null)
+ ctor.Statements.AddRange (localVars);
+
+ CodeTypeReferenceExpression r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
+ CodeFieldReferenceExpression intialized = new CodeFieldReferenceExpression (r, "__intialized");
+
+ CodeBinaryOperatorExpression bin = new CodeBinaryOperatorExpression (intialized,
+ CodeBinaryOperatorType.ValueEquality,
+ new CodePrimitiveExpression (false));
+
+ CodeAssignStatement assign = new CodeAssignStatement (intialized,
+ new CodePrimitiveExpression (true));
+
+ CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
+ if (trueStmt != null)
+ cond.TrueStatements.AddRange (trueStmt);
+
+ ctor.Statements.Add (cond);
+ }
+
+ void AddScripts ()
+ {
+ if (parser.Scripts == null || parser.Scripts.Count == 0)
+ return;
+
+ foreach (object o in parser.Scripts) {
+ if (o is string)
+ mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
}
}
+
+ protected virtual void CreateMethods ()
+ {
+ }
- public virtual void AddDependency (string filename)
+ protected virtual void AddInterfaces ()
{
- if (dependencies == null)
- dependencies = new ArrayList ();
+ if (parser.Interfaces == null)
+ return;
- dependencies.Add (filename);
+ foreach (object o in parser.Interfaces) {
+ if (o is string)
+ mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
+ }
}
-
- public virtual string CompilerOptions {
- get {
- string assemblies = default_assemblies;
- string privatePath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
- string appBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
- //HACK: we should use Uri (appBase).LocalPath once Uri works fine.
- if (appBase.StartsWith ("file://")) {
- appBase = appBase.Substring (7);
- if (Path.DirectorySeparatorChar == '\\')
- appBase = appBase.Replace ('/', '\\');
- }
- privatePath = Path.Combine (appBase, privatePath);
+ protected virtual void ProcessObjectTag (ObjectTagBuilder tag)
+ {
+ }
- if (privatePath != null && Directory.Exists (privatePath)) {
- StringBuilder sb = new StringBuilder (assemblies);
- foreach (string fileName in Directory.GetFiles (privatePath, "*.dll"))
- sb.AppendFormat (", {0}", fileName);
- assemblies = sb.ToString ();
- sb = null;
- }
+ void CheckCompilerErrors (CompilerResults results)
+ {
+ if (results.NativeCompilerReturnValue == 0)
+ return;
+ StringWriter writer = new StringWriter();
+ provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
+ StringBuilder sb = new StringBuilder ();
+ foreach (CompilerError error in results.Errors) {
+ sb.Append (error);
+ sb.Append ('\n');
+ }
- string [] split = assemblies.Split (',');
- StringBuilder result = new StringBuilder ();
- foreach (string assembly in split)
- result.AppendFormat ("/r:\"{0}\" ", assembly.TrimStart ());
-
- if (options == null)
- return result.ToString ();
-
- string compilerOptions = options ["CompilerOptions"] as string;
- if (compilerOptions != null) {
- result.Append (' ');
- result.Append (compilerOptions);
- }
+ throw new CompilationException (parser.InputFile, sb.ToString (), writer.ToString ());
+ }
- string references = options ["References"] as string;
- if (references == null)
- return result.ToString ();
+ public virtual Type GetCompiledType ()
+ {
+ //TODO: get the compiler and default options from system.web/compileroptions
+ provider = new CSharpCodeProvider ();
+ compiler = provider.CreateCompiler ();
- split = references.Split ('|');
- foreach (string s in split)
- result.AppendFormat (" /r:\"{0}\"", s);
+ BuildTree ();
+ CompilerResults results = CachingCompiler.Compile (this);
+ CheckCompilerErrors (results);
- return result.ToString ();
- }
+ return results.CompiledAssembly.GetType (mainClassExpr.Type.BaseType, true);
}
- public virtual string TargetFile {
- get {
- if (randomName == null) {
- randomName = Path.GetTempFileName ();
- try {
- File.Delete (randomName);
- } catch {}
- randomName += ".dll";
- }
+ internal CompilerParameters CompilerParameters {
+ get { return compilerParameters; }
+ }
- return randomName;
- }
+ internal CodeCompileUnit Unit {
+ get { return unit; }
+ }
+
+ internal ICodeCompiler Compiler {
+ get { return compiler; }
+ }
+
+ internal TemplateParser Parser {
+ get { return parser; }
}
}
}
--- /dev/null
+//
+// System.Web.Compilation.CSCompiler
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+using System.Reflection;
+using Microsoft.CSharp;
+
+namespace System.Web.Compilation
+{
+ class CSCompiler
+ {
+ static CodeDomProvider provider;
+ static ICodeCompiler compiler;
+ string filename;
+ ArrayList assemblies;
+ CompilerParameters options;
+
+ static CSCompiler ()
+ {
+ provider = new CSharpCodeProvider ();
+ compiler = provider.CreateCompiler ();
+ }
+
+ private CSCompiler (string filename, ArrayList assemblies)
+ {
+ this.filename = filename;
+ this.assemblies = assemblies;
+ options = new CompilerParameters ();
+ if (assemblies != null) {
+ StringCollection coll = new StringCollection ();
+ foreach (string str in assemblies)
+ coll.Add (str);
+ }
+ }
+
+ public Assembly GetCompiledAssembly ()
+ {
+ CompilerResults results = compiler.CompileAssemblyFromFile (options, filename);
+ if (results.NativeCompilerReturnValue != 0) {
+ StringBuilder errors = new StringBuilder ();
+ foreach (CompilerError error in results.Errors) {
+ errors.Append (error);
+ errors.Append ('\n');
+ }
+
+ throw new HttpException ("Error compiling " + filename + "\n" + errors.ToString ());
+ }
+
+ return results.CompiledAssembly;
+ }
+
+ static public Assembly CompileCSFile (string file, ArrayList assemblies)
+ {
+ CSCompiler compiler = new CSCompiler (file, assemblies);
+ return compiler.GetCompiledAssembly ();
+ }
+
+ static public CodeDomProvider Provider {
+ get { return provider; }
+ }
+
+ static public ICodeCompiler Compiler {
+ get { return compiler; }
+ }
+ }
+}
+
// (C) 2002 Ximian, Inc (http://www.ximian.com)
//
using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
using System.Collections;
-using System.Diagnostics;
using System.IO;
-using System.Text;
using System.Web.UI;
-using System.Web.Util;
namespace System.Web.Compilation
{
//TODO: caching should be done using System.Web.Caching, but that namespace still need some work.
internal class CompilationCacheItem
{
- CompilationResult result;
+ CompilerResults result;
+ ArrayList dependencies;
DateTime reference;
- bool invalidated;
- public CompilationCacheItem (CompilationResult result)
+ public CompilationCacheItem (CompilerResults result, ArrayList dependencies)
{
this.result = result;
- try {
- this.reference = File.GetLastWriteTime (result.OutputFile);
- } catch (FileNotFoundException){
- this.reference = DateTime.Now;
- }
+ this.dependencies = dependencies;
+ this.reference = DateTime.Now;
}
- public bool CheckDependencies ()
+ public bool CheckDependencies (string key)
{
- if (invalidated || result.Dependencies == null)
- return false;
-
- if (!File.Exists (result.OutputFile))
- return false;
+ if (dependencies == null)
+ return true; // Forever young
- foreach (string s in result.Dependencies) {
- if (!File.Exists (s) || File.GetLastWriteTime (s) > reference) {
- invalidated = true;
+ foreach (string s in dependencies) {
+ if (!File.Exists (s) || File.GetLastWriteTime (s) > reference)
return false;
- }
}
return true;
}
- public CompilationResult Result
- {
+ public CompilerResults Result {
get { return result; }
}
}
return instance;
}
- public CompilationCacheItem this [string key]
+ public bool CheckDependencies (CompilationCacheItem item, string key)
{
- get {
- return cache [key] as CompilationCacheItem;
- }
+ bool result = item.CheckDependencies (key);
+ if (result == false)
+ cache.Remove (key);
- set {
- cache [key] = value;
- }
+ return result;
+ }
+
+ public CompilationCacheItem this [string key] {
+ get { return cache [key] as CompilationCacheItem; }
+ set { cache [key] = value; }
}
}
internal class CachingCompiler
{
static CompilationCache cache = CompilationCache.GetInstance ();
- string key;
- BaseCompiler compiler;
- public CachingCompiler (BaseCompiler compiler)
- {
- this.compiler = compiler;
- this.key = compiler.Key;
- }
+ private CachingCompiler () {}
public static CompilationCacheItem GetCached (string key)
{
throw new ArgumentNullException ("key");
CompilationCacheItem item = cache [key];
- if (item != null && item.CheckDependencies ())
+ if (item != null && cache.CheckDependencies (item, key))
return item;
return null;
}
static object compilationLock = new object ();
- public bool Compile (CompilationResult result)
+ public static CompilerResults Compile (BaseCompiler compiler)
{
- if (compiler.SourceFile == null)
- throw new ArgumentException ("No source to compile!");
-
- result.Reset ();
- CompilationCacheItem item;
-
- item = GetCached (key);
- if (item != null) {
- result.CopyFrom (item.Result);
- return true;
- }
+ string key = compiler.Parser.InputFile;
+ CompilationCacheItem item = GetCached (key);
+ if (item != null)
+ return item.Result;
+ CompilerResults results = null;
lock (compilationLock) {
item = GetCached (key);
- if (item != null) {
- result.CopyFrom (item.Result);
- return true;
- }
+ if (item != null)
+ return item.Result;
- RealCompile (result);
- cache [key] = new CompilationCacheItem (result);
+ results = compiler.Compiler.CompileAssemblyFromDom (compiler.CompilerParameters, compiler.Unit);
+ cache [key] = new CompilationCacheItem (results, compiler.Parser.Dependencies);
}
- return (result.ExitCode == 0);
- }
-
- void RealCompile (CompilationResult result)
- {
- StringBuilder options = new StringBuilder ("/target:library ");
- if (compiler.CompilerOptions != null)
- options.Append (compiler.CompilerOptions + ' ');
-
- options.AppendFormat ("/out:\"{0}\" ", compiler.TargetFile);
- options.Append ('"' + compiler.SourceFile + '"');
-
- //Console.WriteLine ("mcs {0}", options);
- Process proc = new Process ();
- if (Path.DirectorySeparatorChar == '\\')
- proc.StartInfo.FileName = "mcs.bat";
- else
- proc.StartInfo.FileName = "mcs";
-
- proc.StartInfo.Arguments = options.ToString ();
- proc.StartInfo.UseShellExecute = false;
- proc.StartInfo.RedirectStandardOutput = true;
-
- WebTrace.WriteLine ("{0} {1}", proc.StartInfo.FileName, options.ToString ());
- try {
- proc.Start ();
- } catch (Exception e) {
- if (Path.DirectorySeparatorChar == '\\') {
- proc.StartInfo.FileName = "mcs";
- proc.Start ();
- } else {
- throw e;
- }
- }
-
- string poutput = proc.StandardOutput.ReadToEnd();
- proc.WaitForExit ();
- result.ExitCode = proc.ExitCode;
- proc.Close ();
- proc = null;
-
- result.CompilerOutput = poutput;
- //Console.WriteLine ("output: {0}\n", poutput);
- result.OutputFile = compiler.TargetFile;
+ return results;
}
}
}
+2003-04-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * AspComponentFoundry.cs: simplified it a lot by using Type and Assembly
+ instead of their names.
+
+ * AspElements.cs: removed. No longer needed.
+
+ * AspGenerator.cs: this file is now in charge of interfacing between
+ the parser and the compiler. It manages the creation of the
+ ControlBuilder tree and the compilation of the CodeDOM tree.
+
+ * AspParser.cs: tag handling is simpler now. Instead of a whole bunch
+ of different Types, tags are just and id and a set of attributes.
+ Implement ILocation interface.
+
+ * AspTokenizer.cs: added a few methods to help the parser implementing
+ ILocation.
+
+ * BaseCompiler.cs: handles the portions of the CodeDOM tree that are
+ common to appliaction, page and user control, including the actual
+ compilation and error handling.
+
+ * CSCompiler.cs: compiles C# files using CodeDOM interfaces.
+
+ * CachingCompiler.cs: simplified to use the new interfaces.
+
+ * CompilationException.cs: it's now using CompilationResult to report
+ errors.
+
+ * CompilationResult.cs: Removed file.
+
+ * Directive.cs: to check for the validity of a directive.
+
+ * GlobalAsaxCompiler.cs: simplified a lot, as most of the work is done
+ in BaseCompiler.
+
+ * ILocation.cs: interface used to now the exact place where a parse
+ error happens.
+
+ * PageCompiler.cs: generates a couple of methods that are only used in
+ pages.
+
+ * ParseException.cs: use the ILocation interface.
+
+ * TagAttributes.cs: handles the attributes of the tags parsed.
+
+ * TagType.cs: an enum for the different kinds of tags.
+
+ * TemplateControlCompiler.cs: this is the one that does most of the
+ conversion from teh ControlBuilder tree into a CodeDOM tree.
+
+ * UserControlCompiler.cs: simplified as most of the work is done in
+ its base classes.
+
+ * WebServiceCompiler.cs: dummy.
+
2003-04-20 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* AspComponentFoundry.cs: added GetComponentType method.
//
using System;
+using System.CodeDom.Compiler;
using System.Web;
-using System.IO;
namespace System.Web.Compilation
{
internal class CompilationException : HtmlizedException
{
- CompilationResult result;
+ string filename;
+ string errors;
+ string file;
- public CompilationException (CompilationResult result)
- : base ("Compilation Error")
+ public CompilationException (string filename, string errors, string file)
{
- this.result = result;
- }
-
- public CompilationException (string msg, CompilationResult result)
- : base (msg)
- {
- this.result = result;
- }
-
- public CompilationException (CompilationCacheItem item)
- {
- this.result = item.Result;
+ this.filename = filename;
+ this.errors = errors;
+ this.file = file;
}
public override string FileName {
- get { return result.FileName; }
+ get { return filename; }
}
public override string Title {
}
public override string ErrorMessage {
- get {
- //FIXME: it should be a one line message.
- return result.CompilerOutput;
- }
+ get { return errors; }
}
- //TODO: get lines from compiler output.
- public override StringReader SourceError { get {return null;}}
- public override int SourceErrorLine { get { return -1; } }
-
- public override TextReader SourceFile {
- get {
- StreamReader input = new StreamReader (File.OpenRead (FileName));
- int sourceErrorLine;
- string result = GetErrorLines (input, 0, out sourceErrorLine);
- input.Close ();
- input = null;
- return new StringReader (result);
- }
+ public string File {
+ get { return file; }
}
}
}
+++ /dev/null
-//
-// System.Web.Compilation.CompilationResult
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
-//
-using System;
-using System.Collections;
-
-namespace System.Web.Compilation
-{
- internal class CompilationResult
- {
- int exitCode;
- string fileName;
- string output;
- string outputFile;
- object data;
- Hashtable options;
- ArrayList dependencies;
-
- public CompilationResult ()
- {
- }
-
- public CompilationResult (string fileName)
- {
- this.fileName = fileName;
- }
-
- public void Reset ()
- {
- exitCode = 0;
- output = null;
- }
-
- public void CopyFrom (CompilationResult other)
- {
- exitCode = other.ExitCode;
- output = other.output;
- outputFile = other.outputFile;
- data = other.data;
- }
-
- public int ExitCode {
- get { return exitCode; }
- set { exitCode = value; }
- }
-
- public string CompilerOutput {
- get { return output; }
- set { output = value; }
- }
-
- public string FileName {
- get { return fileName; }
- }
-
- public string OutputFile {
- get { return outputFile; }
- set { outputFile = value; }
- }
-
- public object Data {
- get { return data; }
- set { data = value; }
- }
-
- public Hashtable Options {
- get { return options; }
- set { options = value; }
- }
-
- public ArrayList Dependencies {
- get { return dependencies; }
- set { dependencies = value; }
- }
-
- public override string ToString ()
- {
- return String.Format ("CompilationResult: {0} {1} {2} {3}", exitCode, output, outputFile, data);
- }
- }
-}
-
--- /dev/null
+//
+// System.Web.Compilation.Directive
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+
+namespace System.Web.Compilation
+{
+ sealed class Directive
+ {
+ static Hashtable directivesHash;
+ 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", "CodeBehind" };
+
+ static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
+ "Debug", "Description", "EnableViewState",
+ "Explicit", "Inherits", "Language", "Strict", "Src",
+ "WarningLevel", "CodeBehind", "TargetSchema" };
+
+ static string [] import_atts = { "namespace" };
+ static string [] implements_atts = { "interface" };
+ static string [] assembly_atts = { "name", "src" };
+ static string [] register_atts = { "tagprefix", "tagname", "Namespace", "Src", "Assembly" };
+
+ static string [] outputcache_atts = { "Duration", "Location", "VaryByControl",
+ "VaryByCustom", "VaryByHeader", "VaryByParam" };
+
+ static string [] reference_atts = { "page", "control" };
+
+ static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
+
+ static string [] application_atts = { "description", "inherits", "codebehind" };
+
+ 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);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in webservice_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("WEBSERVICE", valid_attributes);
+
+ valid_attributes = new Hashtable (provider, comparer);
+ foreach (string att in application_atts) valid_attributes.Add (att, null);
+ directivesHash.Add ("APPLICATION", valid_attributes);
+ }
+
+ private Directive () { }
+
+ public static bool IsDirective (string id)
+ {
+ return directivesHash.Contains (id);
+ }
+ }
+}
+
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
-using System.IO;
-using System.Reflection;
-using System.Text;
-using System.Web;
-using System.Web.Util;
+using System.Web.UI;
namespace System.Web.Compilation
{
class GlobalAsaxCompiler : BaseCompiler
{
- string filename;
- string sourceFile;
- HttpContext context;
+ ApplicationFileParser parser;
- private GlobalAsaxCompiler (string filename)
+ public GlobalAsaxCompiler (ApplicationFileParser parser)
+ : base (parser)
{
- this.filename = filename;
+ this.parser = parser;
}
- public override Type GetCompiledType ()
+ public static Type CompileApplicationType (ApplicationFileParser parser)
{
- sourceFile = GenerateSourceFile ();
-
- CachingCompiler compiler = new CachingCompiler (this);
- CompilationResult result = new CompilationResult (sourceFile);
- result.Options = options;
- if (compiler.Compile (result) == false)
- throw new CompilationException (result);
-
- result.Dependencies = dependencies;
- Assembly assembly = Assembly.LoadFrom (result.OutputFile);
- Type [] types = assembly.GetTypes ();
- foreach (Type t in types) {
- if (t.IsSubclassOf (typeof (HttpApplication))) {
- if (result.Data != null)
- throw new CompilationException ("More that 1 app!!!", result);
- result.Data = t;
- }
- }
-
- return result.Data as Type;
- }
-
- public override string Key {
- get {
- return filename;
- }
- }
-
- public override string SourceFile {
- get {
- return sourceFile;
- }
+ GlobalAsaxCompiler compiler = new GlobalAsaxCompiler (parser);
+ return compiler.GetCompiledType ();
}
- public static Type CompileApplicationType (string filename, HttpContext context)
+ [MonoTODO("Process application scope for object tags")]
+ protected override void ProcessObjectTag (ObjectTagBuilder tag)
{
- CompilationCacheItem item = CachingCompiler.GetCached (filename);
- if (item != null && item.Result != null) {
- if (item.Result != null)
- return item.Result.Data as Type;
-
- throw new CompilationException (item.Result);
- }
-
- GlobalAsaxCompiler gac = new GlobalAsaxCompiler (filename);
- gac.context = context;
- return gac.GetCompiledType ();
- }
-
- string GenerateSourceFile ()
- {
- AspGenerator generator = new AspGenerator (filename);
- generator.Context = context;
- generator.BaseType = typeof (HttpApplication).ToString ();
- generator.ProcessElements ();
- string generated = generator.GetCode ().ReadToEnd ();
- options = generator.Options;
- dependencies = generator.Dependencies;
-
- //FIXME: should get Tmp dir for this application
- string csName = Path.GetTempFileName () + ".cs";
- WebTrace.WriteLine ("Writing {0}", csName);
- StreamWriter output = new StreamWriter (File.OpenWrite (csName));
- output.Write (generated);
- output.Close ();
- return csName;
+ //TODO
}
}
}
--- /dev/null
+//
+// System.Web.Compilation.ILocation
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+namespace System.Web.Compilation
+{
+ interface ILocation
+ {
+ string Filename { get; }
+ int BeginLine { get; }
+ int EndLine { get; }
+ int BeginColumn { get; }
+ int EndColumn { get; }
+ string PlainText { get; }
+ }
+}
+
// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
+using System.CodeDom;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web.UI;
+using System.Web.SessionState;
using System.Web.Util;
namespace System.Web.Compilation
{
- class PageCompiler : BaseCompiler
+ class PageCompiler : TemplateControlCompiler
{
PageParser pageParser;
- string sourceFile;
+ static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
- private PageCompiler (PageParser pageParser)
+ public PageCompiler (PageParser pageParser)
+ : base (pageParser)
{
this.pageParser = pageParser;
}
- public override Type GetCompiledType ()
+ protected override void AddInterfaces ()
{
- string inputFile = pageParser.InputFile;
- sourceFile = GenerateSourceFile ();
+ base.AddInterfaces ();
+ if (pageParser.EnableSessionState)
+ mainClass.BaseTypes.Add (new CodeTypeReference (typeof(IRequiresSessionState)));
- CachingCompiler compiler = new CachingCompiler (this);
- CompilationResult result = new CompilationResult (sourceFile);
- result.Options = options;
- if (compiler.Compile (result) == false)
- throw new CompilationException (result);
-
- result.Dependencies = dependencies;
- if (result.Data is Type)
- return (Type) result.Data;
-
- Assembly assembly = Assembly.LoadFrom (result.OutputFile);
- Type [] types = assembly.GetTypes ();
- foreach (Type t in types) {
- if (t.IsSubclassOf (typeof (Page))) {
- if (result.Data != null)
- throw new CompilationException ("More that 1 page!!!", result);
- result.Data = t;
- }
- }
-
- return result.Data as Type;
+ if (pageParser.ReadOnlySessionState)
+ mainClass.BaseTypes.Add (new CodeTypeReference (typeof (IReadOnlySessionState)));
}
- public override string Key {
- get {
- return pageParser.InputFile;
- }
- }
-
- public override string SourceFile {
- get {
- return sourceFile;
- }
+ void CreateGetTypeHashCode ()
+ {
+ CodeMemberMethod method = new CodeMemberMethod ();
+ method.ReturnType = intRef;
+ method.Name = "GetTypeHashCode";
+ method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
+ Random rnd = new Random (pageParser.InputFile.GetHashCode ());
+ method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
+ mainClass.Members.Add (method);
}
- public static Type CompilePageType (PageParser pageParser)
+ protected override void CreateMethods ()
{
- CompilationCacheItem item = CachingCompiler.GetCached (pageParser.InputFile);
- if (item != null && item.Result != null) {
- if (item.Result != null) {
- pageParser.Options = item.Result.Options;
- return item.Result.Data as Type;
- }
-
- throw new CompilationException (item.Result);
- }
+ base.CreateMethods ();
- PageCompiler pc = new PageCompiler (pageParser);
- return pc.GetCompiledType ();
+ CreateGetTypeHashCode ();
}
- string GenerateSourceFile ()
+ public static Type CompilePageType (PageParser pageParser)
{
- AspGenerator generator = new AspGenerator (pageParser.InputFile);
- generator.Context = pageParser.Context;
- generator.BaseType = pageParser.BaseType.ToString ();
- generator.ProcessElements ();
- pageParser.Text = generator.GetCode ().ReadToEnd ();
- dependencies = generator.Dependencies;
- options = generator.Options;
-
- //FIXME: should get Tmp dir for this application
- string csName = Path.GetTempFileName () + ".cs";
- WebTrace.WriteLine ("Writing {0}", csName);
- StreamWriter output = new StreamWriter (File.OpenWrite (csName));
- output.Write (pageParser.Text);
- output.Close ();
- return csName;
+ PageCompiler compiler = new PageCompiler (pageParser);
+ return compiler.GetCompiledType ();
}
}
}
{
internal class ParseException : HtmlizedException
{
- string fileName;
string message;
- int line;
- int col;
- int sourceErrorLine;
+ ILocation location;
- public ParseException (string fileName, string message, int line, int col)
- : base (message)
+ public ParseException (ILocation location, string message)
{
- this.fileName = fileName;
+ if (location == null)
+ throw new Exception ();
+ this.location = location;
this.message = message;
- this.line = line >= 1 ? line : 1;
- this.col = col;
- }
-
- public ParseException (string fileName, string message, int line, int col, Exception inner)
- : base (message, inner)
- {
- this.fileName = fileName;
- this.message = message;
- this.line = line >= 1 ? line : 1;
- this.col = col;
}
public override string Title {
}
public override string FileName {
- get { return fileName; }
- }
-
- public override StringReader SourceError {
- get {
- StreamReader input = new StreamReader (File.OpenRead (fileName));
- string result = GetErrorLines (input, line - 1, out sourceErrorLine);
- input.Close ();
- input = null;
- return new StringReader (result);
- }
- }
-
- public override int SourceErrorLine {
- get { return sourceErrorLine; }
- }
-
- public override TextReader SourceFile {
- get { return null; }
+ get { return location.Filename; }
}
}
}
--- /dev/null
+//
+// System.Web.Compilation.TagAttributes
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace System.Web.Compilation
+{
+ class TagAttributes
+ {
+ Hashtable atts_hash;
+ Hashtable tmp_hash;
+ ArrayList keys;
+ ArrayList values;
+ bool got_hashed;
+
+ public TagAttributes ()
+ {
+ got_hashed = false;
+ keys = new ArrayList ();
+ values = new ArrayList ();
+ }
+
+ void MakeHash ()
+ {
+ atts_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
+ CaseInsensitiveComparer.Default);
+ 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)) {
+ if (0 == String.Compare ((string) value, "server", true))
+ MakeHash ();
+ else
+ throw new HttpException ("runat attribute must have a 'server' value");
+ }
+
+ if (got_hashed) {
+ atts_hash [key] = value;
+ } else {
+ keys.Add (key);
+ values.Add (value);
+ }
+ }
+
+ public ICollection Keys
+ {
+ get { return (got_hashed ? atts_hash.Keys : keys); }
+ }
+
+ public ICollection Values
+ {
+ get { return (got_hashed ? atts_hash.Values : values); }
+ }
+
+ 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 Hashtable GetDictionary (string key)
+ {
+ if (got_hashed)
+ return atts_hash;
+
+ if (tmp_hash == null)
+ tmp_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
+ CaseInsensitiveComparer.Default);
+
+ tmp_hash.Clear ();
+ for (int i = keys.Count - 1; i >= 0; i--)
+ if (key == null || String.Compare (key, (string) keys [i], true) == 0)
+ tmp_hash [keys [i]] = values [i];
+
+ return tmp_hash;
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder result = new StringBuilder ();
+ string value;
+ foreach (string key in Keys){
+ result.Append (key);
+ value = this [key] as string;
+ if (value != null)
+ result.AppendFormat ("=\"{0}\"", value);
+
+ result.Append (' ');
+ }
+
+ if (result.Length > 0 && result [result.Length - 1] == ' ')
+ result.Length--;
+
+ return result.ToString ();
+ }
+ }
+}
+
--- /dev/null
+//
+// System.Web.Compilation.TagType
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+namespace System.Web.Compilation
+{
+ enum TagType
+ {
+ Text,
+ Tag,
+ Close,
+ SelfClosing,
+ Directive,
+ ServerComment,
+ DataBinding,
+ CodeRender,
+ CodeRenderExpression
+ }
+}
+
--- /dev/null
+//
+// System.Web.Compilation.TemplateControlCompiler
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.CodeDom;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Web.UI;
+
+namespace System.Web.Compilation
+{
+ class TemplateControlCompiler : BaseCompiler
+ {
+ static BindingFlags noCaseFlags = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Instance | BindingFlags.IgnoreCase;
+
+ static Type styleType = typeof (System.Web.UI.WebControls.Style);
+ static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
+
+ TemplateControlParser parser;
+ static TypeConverter colorConverter;
+
+ static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
+ static Type [] arrayString = new Type [] {typeof (string)};
+ static Type [] arrayStringCultureInfo = new Type [] {typeof (string), typeof (CultureInfo)};
+
+ public TemplateControlCompiler (TemplateControlParser parser)
+ : base (parser)
+ {
+ this.parser = parser;
+ }
+
+ void EnsureID (ControlBuilder builder)
+ {
+ if (builder.ID == null || builder.ID.Trim () == "")
+ builder.ID = builder.GetNextID (null);
+ }
+
+ void CreateField (ControlBuilder builder, bool check)
+ {
+ if (check && CheckBaseFieldOrProperty (builder.ID, builder.ControlType))
+ return; // The field or property already exists in a base class and is accesible.
+
+ CodeMemberField field;
+ field = new CodeMemberField (builder.ControlType.FullName, builder.ID);
+ field.Attributes = MemberAttributes.Family;
+ mainClass.Members.Add (field);
+ }
+
+ bool CheckBaseFieldOrProperty (string id, Type type)
+ {
+ FieldInfo fld = parser.BaseType.GetField (id, noCaseFlags);
+
+ Type other = null;
+ if (fld == null || fld.IsPrivate) {
+ PropertyInfo prop = parser.BaseType.GetProperty (id, noCaseFlags);
+ if (prop != null) {
+ MethodInfo setm = prop.GetSetMethod (true);
+ if (setm != null)
+ other = prop.PropertyType;
+ }
+ } else {
+ other = fld.FieldType;
+ }
+
+ if (other == null)
+ return false;
+
+ if (!other.IsAssignableFrom (type)) {
+ string msg = String.Format ("The base class includes the field '{0}', but its " +
+ "type '{1}' is not compatible with {2}",
+ id, other, type);
+ throw new HttpException (msg);
+ }
+
+ return true;
+ }
+
+ void AddParsedSubObjectStmt (ControlBuilder builder, CodeExpression expr)
+ {
+ if (!builder.haveParserVariable) {
+ CodeVariableDeclarationStatement p = new CodeVariableDeclarationStatement();
+ p.Name = "__parser";
+ p.Type = new CodeTypeReference (typeof (IParserAccessor));
+ p.InitExpression = new CodeCastExpression (typeof (IParserAccessor), ctrlVar);
+ builder.method.Statements.Add (p);
+ builder.haveParserVariable = true;
+ }
+
+ CodeVariableReferenceExpression var = new CodeVariableReferenceExpression ("__parser");
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (var, "AddParsedSubObject");
+ invoke.Parameters.Add (expr);
+ builder.method.Statements.Add (invoke);
+ }
+
+ void InitMethod (ControlBuilder builder, bool isTemplate, bool childrenAsProperties)
+ {
+ string tailname = ((builder is RootBuilder) ? "Tree" : ("_" + builder.ID));
+ CodeMemberMethod method = new CodeMemberMethod ();
+ builder.method = method;
+ method.Name = "__BuildControl" + tailname;
+ method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+ Type type = builder.ControlType;
+
+ if (builder.HasAspCode) {
+ CodeMemberMethod renderMethod = new CodeMemberMethod ();
+ builder.renderMethod = renderMethod;
+ renderMethod.Name = "__Render" + tailname;
+ renderMethod.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+ CodeParameterDeclarationExpression arg1 = new CodeParameterDeclarationExpression ();
+ arg1.Type = new CodeTypeReference (typeof (HtmlTextWriter));
+ arg1.Name = "__output";
+ CodeParameterDeclarationExpression arg2 = new CodeParameterDeclarationExpression ();
+ arg2.Type = new CodeTypeReference (typeof (Control));
+ arg2.Name = "parameterContainer";
+ renderMethod.Parameters.Add (arg1);
+ renderMethod.Parameters.Add (arg2);
+ mainClass.Members.Add (renderMethod);
+ }
+
+ if (childrenAsProperties || isTemplate) {
+ string typeString;
+ if (builder.isProperty && !isTemplate)
+ typeString = builder.ControlType.FullName;
+ else
+ typeString = "System.Web.UI.Control";
+
+ method.Parameters.Add (new CodeParameterDeclarationExpression (typeString, "__ctrl"));
+ } else {
+
+ if (typeof (Control).IsAssignableFrom (type))
+ method.ReturnType = new CodeTypeReference (typeof (Control));
+
+ CodeObjectCreateExpression newExpr = new CodeObjectCreateExpression (type);
+
+ object [] atts = type.GetCustomAttributes (typeof (ConstructorNeedsTagAttribute), true);
+ if (atts != null && atts.Length > 0) {
+ ConstructorNeedsTagAttribute att = (ConstructorNeedsTagAttribute) atts [0];
+ if (att.NeedsTag)
+ newExpr.Parameters.Add (new CodePrimitiveExpression (builder.TagName));
+ } else if (builder is DataBindingBuilder) {
+ newExpr.Parameters.Add (new CodePrimitiveExpression (0));
+ newExpr.Parameters.Add (new CodePrimitiveExpression (1));
+ }
+
+ method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ assign.Left = ctrlVar;
+ assign.Right = newExpr;
+ method.Statements.Add (assign);
+
+ CodeFieldReferenceExpression builderID = new CodeFieldReferenceExpression ();
+ builderID.TargetObject = thisRef;
+ builderID.FieldName = builder.ID;
+ assign = new CodeAssignStatement ();
+ assign.Left = builderID;
+ assign.Right = ctrlVar;
+ method.Statements.Add (assign);
+ if (typeof (UserControl).IsAssignableFrom (type)) {
+ CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression ();
+ mref.TargetObject = builderID;
+ mref.MethodName = "InitializeAsUserControl";
+ CodeMethodInvokeExpression initAsControl = new CodeMethodInvokeExpression (mref);
+ initAsControl.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page"));
+ method.Statements.Add (initAsControl);
+ }
+ }
+
+ mainClass.Members.Add (method);
+ }
+
+ void AddLiteralSubObject (ControlBuilder builder, string str)
+ {
+ if (!builder.HasAspCode) {
+ CodeObjectCreateExpression expr;
+ expr = new CodeObjectCreateExpression (typeof (LiteralControl), new CodePrimitiveExpression (str));
+ AddParsedSubObjectStmt (builder, expr);
+ } else {
+ CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression ();
+ methodRef.TargetObject = new CodeArgumentReferenceExpression ("__output");
+ methodRef.MethodName = "Write";
+
+ CodeMethodInvokeExpression expr;
+ expr = new CodeMethodInvokeExpression (methodRef, new CodePrimitiveExpression (str));
+ builder.renderMethod.Statements.Add (expr);
+ }
+ }
+
+ void AddCodeForPropertyOrField (CodeMemberMethod method, Type type, string var_name, string att, bool isDataBound)
+ {
+ if (isDataBound) {
+ //DataBoundProperty (type, var_name, att);
+ return;
+ }
+
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
+ assign.Right = GetExpressionFromString (type, att);
+
+ method.Statements.Add (assign);
+ }
+
+ bool ProcessPropertiesAndFields (CodeMemberMethod method, MemberInfo member, string id, string attValue)
+ {
+ int hyphen = id.IndexOf ('-');
+
+ bool isPropertyInfo = (member is PropertyInfo);
+
+ bool is_processed = false;
+ //FIXME: bool isDataBound = att.IsDataBound ((string) att [id]);
+ bool isDataBound = false;
+ Type type;
+ if (isPropertyInfo) {
+ type = ((PropertyInfo) member).PropertyType;
+ if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
+ return false;
+ } else {
+ type = ((FieldInfo) member).FieldType;
+ }
+
+ if (0 == String.Compare (member.Name, id, true)){
+ AddCodeForPropertyOrField (method, type, member.Name, attValue, isDataBound);
+ is_processed = true;
+ } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
+ //FIXME: x-y should not be limited to style and font
+ string prop_field = id.Replace ("-", ".");
+ string [] parts = prop_field.Split (new char [] {'.'});
+ if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
+ return false;
+
+ PropertyInfo [] subprops = type.GetProperties ();
+ foreach (PropertyInfo subprop in subprops) {
+ if (0 != String.Compare (subprop.Name, parts [1], true))
+ continue;
+
+ if (subprop.CanWrite == false)
+ return false;
+
+ bool is_bool = subprop.PropertyType == typeof (bool);
+ if (!is_bool && attValue == null)
+ return false; // Font-Size -> Font-Size="" as html
+
+ string value;
+ if (attValue == null && is_bool)
+ value = "true"; // Font-Bold <=> Font-Bold="true"
+ else
+ value = attValue;
+
+ AddCodeForPropertyOrField (method, subprop.PropertyType,
+ member.Name + "." + subprop.Name,
+ value, isDataBound);
+ is_processed = true;
+ }
+ }
+
+ return is_processed;
+ }
+
+ void AddEventAssign (CodeMemberMethod method, string name, Type type, string value)
+ {
+ //"__ctrl.{0} += new {1} (this.{2});"
+ CodeEventReferenceExpression evtID = new CodeEventReferenceExpression (ctrlVar, name);
+
+ CodeDelegateCreateExpression create;
+ create = new CodeDelegateCreateExpression (new CodeTypeReference (type), thisRef, value);
+
+ CodeAttachEventStatement attach = new CodeAttachEventStatement (evtID, create);
+ method.Statements.Add (attach);
+ }
+
+ void CreateAssignStatementsFromAttributes (ControlBuilder builder)
+ {
+ IDictionary atts = builder.attribs;
+ if (atts == null || atts.Count == 0)
+ return;
+
+ EventInfo [] ev_info = null;
+ PropertyInfo [] prop_info = null;
+ FieldInfo [] field_info = null;
+ bool is_processed = false;
+ Type type = builder.ControlType;
+
+ foreach (string id in atts.Keys){
+ if (0 == String.Compare (id, "runat", true))
+ continue;
+
+ is_processed = false;
+ if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
+ if (ev_info == null)
+ ev_info = type.GetEvents ();
+
+ string id_as_event = id.Substring (2);
+ foreach (EventInfo ev in ev_info){
+ if (0 == String.Compare (ev.Name, id_as_event, true)){
+ AddEventAssign (builder.method,
+ ev.Name,
+ ev.EventHandlerType,
+ (string) atts [id]);
+
+ is_processed = true;
+ break;
+ }
+ }
+
+ if (is_processed)
+ continue;
+ }
+
+ if (prop_info == null)
+ prop_info = type.GetProperties ();
+
+ foreach (PropertyInfo prop in prop_info) {
+ is_processed = ProcessPropertiesAndFields (builder.method, prop, id, atts [id] as string);
+ if (is_processed)
+ break;
+ }
+
+ if (is_processed)
+ continue;
+
+ if (field_info == null)
+ field_info = type.GetFields ();
+
+ foreach (FieldInfo field in field_info){
+ is_processed = ProcessPropertiesAndFields (builder.method, field, id, atts [id] as string);
+ if (is_processed)
+ break;
+ }
+
+ if (is_processed)
+ continue;
+
+ if (!typeof (IAttributeAccessor).IsAssignableFrom (type))
+ throw new ParseException (builder.location, "Unrecognized attribute: " + id);
+
+
+ CodeCastExpression cast = new CodeCastExpression (typeof (IAttributeAccessor), ctrlVar);
+ CodeMethodReferenceExpression methodExpr;
+ methodExpr = new CodeMethodReferenceExpression (cast, "SetAttribute");
+ CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (methodExpr);
+ expr.Parameters.Add (new CodePrimitiveExpression (id));
+ expr.Parameters.Add (new CodePrimitiveExpression ((string) atts [id]));
+ builder.method.Statements.Add (expr);
+ }
+ }
+
+ void AddRenderControl (ControlBuilder builder)
+ {
+ CodeIndexerExpression indexer = new CodeIndexerExpression ();
+ indexer.TargetObject = new CodePropertyReferenceExpression (
+ new CodeArgumentReferenceExpression ("parameterContainer"),
+ "Controls");
+
+ indexer.Indices.Add (new CodePrimitiveExpression (builder.renderIndex));
+
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (indexer, "RenderControl");
+ invoke.Parameters.Add (new CodeArgumentReferenceExpression ("__output"));
+ builder.renderMethod.Statements.Add (invoke);
+ builder.renderIndex++;
+ }
+
+ void AddChildCall (ControlBuilder parent, ControlBuilder child)
+ {
+ CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (thisRef, child.method.Name);
+ CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (m);
+ if (child.isProperty || parent.FChildrenAsProperties) {
+ expr.Parameters.Add (new CodeFieldReferenceExpression (ctrlVar, child.TagName));
+ parent.method.Statements.Add (expr);
+ return;
+ }
+
+ parent.method.Statements.Add (expr);
+ CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, child.ID);
+ if (parent.ControlType == null || typeof (IParserAccessor).IsAssignableFrom (parent.ControlType)) {
+ AddParsedSubObjectStmt (parent, field);
+ } else {
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (ctrlVar, "Add");
+ invoke.Parameters.Add (field);
+ parent.method.Statements.Add (invoke);
+ }
+
+ if (parent.HasAspCode)
+ AddRenderControl (parent);
+ }
+
+ void AddTemplateInvocation (CodeMemberMethod method, string name, string methodName)
+ {
+ CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
+
+ CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
+ newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+
+ CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledTemplateBuilder));
+ newCompiled.Parameters.Add (newBuild);
+
+ CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
+ method.Statements.Add (assign);
+ }
+
+ void AddCodeRender (ControlBuilder parent, CodeRenderBuilder cr)
+ {
+ if (cr.Code == null || cr.Code.Trim () == "")
+ return;
+
+ if (!cr.IsAssign) {
+ CodeSnippetStatement code = new CodeSnippetStatement (cr.Code);
+ parent.renderMethod.Statements.Add (code);
+ return;
+ }
+
+ CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
+ expr.Method = new CodeMethodReferenceExpression (
+ new CodeArgumentReferenceExpression ("__output"),
+ "Write");
+
+ expr.Parameters.Add (new CodeSnippetExpression (cr.Code));
+ parent.renderMethod.Statements.Add (expr);
+ }
+
+ static Type GetContainerType (ControlBuilder builder)
+ {
+ Type type = builder.NamingContainerType;
+ if (builder.ControlType != null && !typeof (ITemplate).IsAssignableFrom (builder.ControlType))
+ return type;
+
+ PropertyInfo prop = type.GetProperty ("Items", noCaseFlags);
+ if (prop == null)
+ return type;
+
+ Type ptype = prop.PropertyType;
+ if (!typeof (ICollection).IsAssignableFrom (ptype))
+ return type;
+
+ prop = ptype.GetProperty ("Item", noCaseFlags);
+ if (prop == null)
+ return type;
+
+ return prop.PropertyType;
+ }
+
+ void AddDataBindingLiteral (ControlBuilder builder, DataBindingBuilder db)
+ {
+ if (db.Code == null || db.Code.Trim () == "")
+ return;
+
+ EnsureID (db);
+ CreateField (db, false);
+
+ string dbMethodName = "__DataBind_" + db.ID;
+ // Add the method that builds the DataBoundLiteralControl
+ InitMethod (db, false, false);
+ CodeMemberMethod method = db.method;
+ AddEventAssign (method, "DataBinding", typeof (EventHandler), dbMethodName);
+ method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+
+ // Add the DataBind handler
+ CodeTypeReference dbTypeRef = new CodeTypeReference (typeof (DataBoundLiteralControl));
+ CodeTypeReference containerType = new CodeTypeReference (GetContainerType (builder));
+
+ method = new CodeMemberMethod ();
+ method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+ method.Name = dbMethodName;
+ method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object), "sender"));
+ method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (EventArgs), "e"));
+
+ CodeVariableDeclarationStatement decl = new CodeVariableDeclarationStatement();
+ decl.Name = "Container";
+ decl.Type = containerType;
+ method.Statements.Add (decl);
+
+ decl = new CodeVariableDeclarationStatement();
+ decl.Name = "target";
+ decl.Type = dbTypeRef;
+ method.Statements.Add (decl);
+
+ CodeVariableReferenceExpression target = new CodeVariableReferenceExpression ("target");
+ CodeAssignStatement assign = new CodeAssignStatement ();
+ assign.Left = target;
+ assign.Right = new CodeCastExpression (dbTypeRef, new CodeArgumentReferenceExpression ("sender"));
+ method.Statements.Add (assign);
+
+ assign = new CodeAssignStatement ();
+ assign.Left = new CodeVariableReferenceExpression ("Container");
+ assign.Right = new CodeCastExpression (containerType,
+ new CodePropertyReferenceExpression (target, "BindingContainer"));
+ method.Statements.Add (assign);
+
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
+ invoke.Method = new CodeMethodReferenceExpression (target, "SetDataBoundString");
+ invoke.Parameters.Add (new CodePrimitiveExpression (0));
+ CodeMethodInvokeExpression tostring = new CodeMethodInvokeExpression ();
+ tostring.Method = new CodeMethodReferenceExpression (
+ new CodeTypeReferenceExpression (typeof (Convert)),
+ "ToString");
+ tostring.Parameters.Add (new CodeSnippetExpression (db.Code));
+ invoke.Parameters.Add (tostring);
+ method.Statements.Add (invoke);
+
+ mainClass.Members.Add (method);
+
+ AddChildCall (builder, db);
+ }
+
+ void FlushText (ControlBuilder builder, StringBuilder sb)
+ {
+ if (sb.Length > 0) {
+ AddLiteralSubObject (builder, sb.ToString ());
+ sb.Length = 0;
+ }
+ }
+
+ void CreateControlTree (ControlBuilder builder, bool inTemplate, bool childrenAsProperties)
+ {
+ EnsureID (builder);
+ bool isTemplate = (typeof (TemplateBuilder).IsAssignableFrom (builder.GetType ()));
+ if (!isTemplate)
+ CreateField (builder, true);
+
+ InitMethod (builder, isTemplate, childrenAsProperties || isTemplate);
+ CreateAssignStatementsFromAttributes (builder);
+
+ if (builder.Children != null && builder.Children.Count > 0) {
+ ArrayList templates = null;
+
+ StringBuilder sb = new StringBuilder ();
+ foreach (object b in builder.Children) {
+
+ if (b is string) {
+ sb.Append ((string) b);
+ continue;
+ }
+
+ FlushText (builder, sb);
+ if (b is ObjectTagBuilder) {
+ ProcessObjectTag ((ObjectTagBuilder) b);
+ continue;
+ }
+
+ if (b is TemplateBuilder) {
+ if (templates == null)
+ templates = new ArrayList ();
+
+ templates.Add (b);
+ continue;
+ }
+
+ if (b is CodeRenderBuilder) {
+ AddCodeRender (builder, (CodeRenderBuilder) b);
+ continue;
+ }
+
+ if (b is DataBindingBuilder) {
+ AddDataBindingLiteral (builder, (DataBindingBuilder) b);
+ continue;
+ }
+
+ if (b is ControlBuilder) {
+ ControlBuilder child = (ControlBuilder) b;
+ CreateControlTree (child, inTemplate, builder.FChildrenAsProperties);
+ AddChildCall (builder, child);
+ continue;
+ }
+
+ throw new Exception ("???");
+ }
+
+ FlushText (builder, sb);
+
+ if (templates != null) {
+ foreach (ControlBuilder b in templates) {
+ CreateControlTree (b, true, false);
+ AddTemplateInvocation (builder.method, b.TagName, b.method.Name);
+ }
+ }
+
+ }
+
+ if (builder.defaultPropertyBuilder != null) {
+ ControlBuilder b = builder.defaultPropertyBuilder;
+ CreateControlTree (b, false, true);
+ Console.WriteLine ("Aqui");
+ AddChildCall (builder, b);
+ }
+
+ if (builder.HasAspCode) {
+ CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
+ m.TargetObject = thisRef;
+ m.MethodName = builder.renderMethod.Name;
+
+ CodeObjectCreateExpression create = new CodeObjectCreateExpression ();
+ create.CreateType = new CodeTypeReference (typeof (RenderMethod));
+ create.Parameters.Add (m);
+
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
+ invoke.Method = new CodeMethodReferenceExpression (ctrlVar, "SetRenderMethodDelegate");
+ invoke.Parameters.Add (create);
+
+ builder.method.Statements.Add (invoke);
+ }
+
+ if (typeof (Control).IsAssignableFrom (builder.ControlType))
+ builder.method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+ }
+
+ protected override void CreateMethods ()
+ {
+ base.CreateMethods ();
+
+ CreateProperties ();
+ CreateControlTree (parser.RootBuilder, false, false);
+ CreateFrameworkInitializeMethod ();
+ }
+
+ void CreateFrameworkInitializeMethod ()
+ {
+ CodeMemberMethod method = new CodeMemberMethod ();
+ method.Name = "FrameworkInitialize";
+ method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+ AddStatementsToFrameworkInitialize (method);
+ mainClass.Members.Add (method);
+ }
+
+ protected virtual void AddStatementsToFrameworkInitialize (CodeMemberMethod method)
+ {
+ if (!parser.EnableViewState) {
+ CodeAssignStatement stmt = new CodeAssignStatement ();
+ stmt.Left = new CodePropertyReferenceExpression (thisRef, "EnableViewState");
+ stmt.Right = new CodePrimitiveExpression (false);
+ method.Statements.Add (stmt);
+ }
+
+ CodeMethodReferenceExpression methodExpr;
+ methodExpr = new CodeMethodReferenceExpression (thisRef, "__BuildControlTree");
+ CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (methodExpr, thisRef);
+ method.Statements.Add (new CodeExpressionStatement (expr));
+ }
+
+ protected override void ProcessObjectTag (ObjectTagBuilder tag)
+ {
+ string name = tag.ObjectID;
+ string className = tag.ClassName;
+ Type t = null;
+ try {
+ t = parser.LoadType (className);
+ } catch (Exception e) {
+ throw new ParseException (tag.location, "Error loading type " + className);
+ }
+
+ string fieldName = "cached" + name;
+ CodeMemberField f = new CodeMemberField (t, fieldName);
+ f.Attributes = MemberAttributes.Private;
+ mainClass.Members.Add (f);
+
+ CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
+
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ prop.Type = new CodeTypeReference (t);
+ prop.Name = name;
+ prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+
+ CodeConditionStatement stmt = new CodeConditionStatement();
+ stmt.Condition = new CodeBinaryOperatorExpression (field,
+ CodeBinaryOperatorType.IdentityEquality,
+ new CodePrimitiveExpression (null));
+
+ CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type);
+ stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
+ prop.GetStatements.Add (stmt);
+ prop.GetStatements.Add (new CodeMethodReturnStatement (field));
+ mainClass.Members.Add (prop);
+ }
+
+ void CreateProperties ()
+ {
+ if (!parser.AutoEventWireup) {
+ CreateAutoEventWireup ();
+ } else {
+ CreateAutoHandlers ();
+ }
+
+ CreateApplicationInstance ();
+ CreateTemplateSourceDirectory ();
+ }
+
+ void CreateTemplateSourceDirectory ()
+ {
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ prop.Type = new CodeTypeReference (typeof (string));
+ prop.Name = "TemplateSourceDirectory";
+ prop.Attributes = MemberAttributes.Public | MemberAttributes.Override;
+
+ CodePrimitiveExpression expr = new CodePrimitiveExpression (parser.CurrentVirtualPath);
+ prop.GetStatements.Add (new CodeMethodReturnStatement (expr));
+ mainClass.Members.Add (prop);
+ }
+
+ void CreateApplicationInstance ()
+ {
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ Type appType = typeof (HttpApplication);//FIXME: uncomment HttpApplicationFactory.AppType;
+ prop.Type = new CodeTypeReference (appType);
+ prop.Name = "ApplicationInstance";
+ prop.Attributes = MemberAttributes.Family | MemberAttributes.Final;
+
+ CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression (thisRef, "Context");
+
+ propRef = new CodePropertyReferenceExpression (propRef, "ApplicationInstance");
+
+ CodeCastExpression cast = new CodeCastExpression (appType.FullName, propRef);
+ prop.GetStatements.Add (new CodeMethodReturnStatement (cast));
+ mainClass.Members.Add (prop);
+ }
+
+ void CreateAutoHandlers ()
+ {
+ // Create AutoHandlers property
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ prop.Type = new CodeTypeReference (typeof (int));
+ prop.Name = "AutoHandlers";
+ prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+
+ CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
+ CodeFieldReferenceExpression fldRef ;
+ fldRef = new CodeFieldReferenceExpression (mainClassExpr, "__autoHandlers");
+ ret.Expression = fldRef;
+ prop.GetStatements.Add (ret);
+
+ prop.SetStatements.Add (new CodeAssignStatement (fldRef, new CodePropertySetValueReferenceExpression ()));
+
+ mainClass.Members.Add (prop);
+
+ // Add the __autoHandlers field
+ CodeMemberField fld = new CodeMemberField (typeof (int), "__autoHandlers");
+ fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
+ mainClass.Members.Add (fld);
+ }
+
+ void CreateAutoEventWireup ()
+ {
+ // The getter returns false
+ CodeMemberProperty prop = new CodeMemberProperty ();
+ prop.Type = new CodeTypeReference (typeof (int));
+ prop.Name = "AutoEventWireup";
+ prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+ prop.GetStatements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (false)));
+ mainClass.Members.Add (prop);
+ }
+
+ CodeExpression GetExpressionFromString (Type type, string str)
+ {
+ if (type == typeof (string))
+ return new CodePrimitiveExpression (str);
+
+ if (type == typeof (bool)) {
+ if (str == null || str == "" || 0 == String.Compare (str, "true", true))
+ return new CodePrimitiveExpression (true);
+ else if (0 == String.Compare (str, "false", true))
+ return new CodePrimitiveExpression (false);
+ else
+ throw new HttpException ("Value '" + str + "' is not a valid boolean.");
+ }
+
+ if (str == null)
+ return new CodePrimitiveExpression (null);
+
+ if (type.IsPrimitive)
+ return new CodePrimitiveExpression (Convert.ChangeType (str, type));
+
+ if (type.IsEnum) {
+ object val = null;
+ try {
+ val = Enum.Parse (type, str, true);
+ } catch (Exception) {
+ throw new HttpException (str + " is not a valid value for enum '" + type + "'");
+ }
+ CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
+ expr.TargetObject = new CodeTypeReferenceExpression (type);
+ expr.FieldName = val.ToString ();
+ return expr;
+ }
+
+ if (type == typeof (Color)){
+ if (colorConverter == null)
+ colorConverter = TypeDescriptor.GetConverter (typeof (Color));
+
+ Color c;
+ try {
+ c = (Color) colorConverter.ConvertFromString (str);
+ } catch (Exception e){
+ throw new HttpException ("Color " + str + " is not a valid color.", e);
+ }
+
+ if (c.IsKnownColor){
+ CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
+ expr.TargetObject = new CodeTypeReferenceExpression (type);
+ expr.FieldName = c.Name;
+ return expr;
+ } else {
+ CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
+ m.TargetObject = new CodeTypeReferenceExpression (type);
+ m.MethodName = "FromArgb";
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (m);
+ invoke.Parameters.Add (new CodePrimitiveExpression (c.A));
+ invoke.Parameters.Add (new CodePrimitiveExpression (c.R));
+ invoke.Parameters.Add (new CodePrimitiveExpression (c.G));
+ invoke.Parameters.Add (new CodePrimitiveExpression (c.B));
+ return invoke;
+ }
+ }
+
+ bool parms = false;
+ BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
+ MethodInfo parse = type.GetMethod ("Parse", flags, null, arrayStringCultureInfo, null);
+ if (parse != null) {
+ parms = true;
+ } else {
+ parse = type.GetMethod ("Parse", flags, null, arrayString, null);
+ }
+
+ if (parse != null) {
+ object o = null;
+ try {
+ if (parms)
+ o = parse.Invoke (null, new object [] { str, CultureInfo.InvariantCulture });
+ else
+ o = parse.Invoke (null, new object [] { str });
+ } catch (Exception e) {
+ throw new HttpException ("Cannot parse " + str + " as " + type, e);
+ }
+
+ if (o == null)
+ throw new HttpException (str + " as " + type + " is null");
+
+ CodeTypeReferenceExpression exprType = new CodeTypeReferenceExpression (type);
+ CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (exprType, "Parse");
+ //FIXME: may be we gotta ensure roundtrip between o.ToString and Parse
+ invoke.Parameters.Add (new CodePrimitiveExpression (o.ToString ()));
+ if (parms) {
+ CodeTypeReferenceExpression texp = new CodeTypeReferenceExpression (typeof (CultureInfo));
+ CodePropertyReferenceExpression pexp = new CodePropertyReferenceExpression ();
+ pexp.TargetObject = texp;
+ pexp.PropertyName = "InvariantCulture";
+ invoke.Parameters.Add (pexp);
+ }
+ return invoke;
+ }
+
+ // FIXME: Arrays (arrays of string are implemented in old AspGenerator.cs
+ Console.WriteLine ("Unknown type: " + type + " value: " + str);
+
+ return new CodePrimitiveExpression (str);
+ }
+ }
+}
+
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
-using System.IO;
-using System.Reflection;
using System.Web.UI;
-using System.Web.Util;
namespace System.Web.Compilation
{
- class UserControlCompiler : BaseCompiler
+ class UserControlCompiler : TemplateControlCompiler
{
- UserControlParser userControlParser;
- string sourceFile;
- string targetFile;
+ UserControlParser parser;
- internal UserControlCompiler (UserControlParser userControlParser)
+ public UserControlCompiler (UserControlParser parser)
+ : base (parser)
{
- this.userControlParser = userControlParser;
- }
-
- public override Type GetCompiledType ()
- {
- string inputFile = userControlParser.InputFile;
- sourceFile = GenerateSourceFile (userControlParser);
-
- CachingCompiler compiler = new CachingCompiler (this);
- CompilationResult result = new CompilationResult (sourceFile);
- result.Options = options;
- if (compiler.Compile (result) == false)
- throw new CompilationException (result);
-
- result.Dependencies = dependencies;
- if (result.Data is Type) {
- targetFile = result.OutputFile;
- return (Type) result.Data;
- }
-
- Assembly assembly = Assembly.LoadFrom (result.OutputFile);
- Type [] types = assembly.GetTypes ();
- foreach (Type t in types) {
- if (t.IsSubclassOf (typeof (UserControl))) {
- if (result.Data != null)
- throw new CompilationException ("More that 1 user control!!!", result);
- result.Data = t;
- }
- }
-
- return result.Data as Type;
- }
-
- public override string Key {
- get {
- return userControlParser.InputFile;
- }
- }
-
- public override string SourceFile {
- get {
- return sourceFile;
- }
- }
-
- public override string TargetFile {
- get {
- if (targetFile == null)
- targetFile = Path.ChangeExtension (sourceFile, ".dll");
-
- return targetFile;
- }
+ this.parser = parser;
}
public static Type CompileUserControlType (UserControlParser userControlParser)
{
- CompilationCacheItem item = CachingCompiler.GetCached (userControlParser.InputFile);
- if (item != null && item.Result != null) {
- if (item.Result != null) {
- userControlParser.Options = item.Result.Options;
- return item.Result.Data as Type;
- }
-
- throw new CompilationException (item.Result);
- }
-
UserControlCompiler pc = new UserControlCompiler (userControlParser);
return pc.GetCompiledType ();
}
-
- string GenerateSourceFile (UserControlParser userControlParser)
- {
- string inputFile = userControlParser.InputFile;
-
- AspGenerator generator = new AspGenerator (inputFile);
- generator.Context = userControlParser.Context;
- generator.BaseType = userControlParser.BaseType.ToString ();
- generator.ProcessElements ();
- userControlParser.Text = generator.GetCode ().ReadToEnd ();
- options = generator.Options;
- dependencies = generator.Dependencies;
-
- //FIXME: should get Tmp dir for this application
- string csName = Path.GetTempFileName () + ".cs";
- WebTrace.WriteLine ("Writing {0}", csName);
- StreamWriter output = new StreamWriter (File.OpenWrite (csName));
- output.Write (userControlParser.Text);
- output.Close ();
- return csName;
- }
}
}
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
-using System.IO;
-using System.Reflection;
using System.Web.UI;
namespace System.Web.Compilation
class WebServiceCompiler : BaseCompiler
{
SimpleWebHandlerParser wService;
- string sourceFile;
- private WebServiceCompiler (SimpleWebHandlerParser wService)
+ [MonoTODO]
+ public WebServiceCompiler (SimpleWebHandlerParser wService)
+ : base (null)
{
this.wService = wService;
}
+ [MonoTODO]
public static Type CompileIntoType (SimpleWebHandlerParser wService)
{
- CompilationCacheItem item = CachingCompiler.GetCached (wService.PhysicalPath);
- if (item != null && item.Result != null) {
- if (item.Result != null)
- return item.Result.Data as Type;
-
- throw new CompilationException (item.Result);
- }
-
- WebServiceCompiler wsc = new WebServiceCompiler (wService);
- return wsc.GetCompiledType ();
- }
-
- static string GenerateSourceFile (SimpleWebHandlerParser wService)
- {
- //FIXME: should get Tmp dir for this application
- string csName = Path.GetTempFileName ();
- StreamWriter output = new StreamWriter (File.OpenWrite (csName));
- output.Write (wService.Program);
- output.Close ();
- return csName;
- }
-
- public override Type GetCompiledType ()
- {
- sourceFile = GenerateSourceFile (wService);
-
- CachingCompiler compiler = new CachingCompiler (this);
- CompilationResult result = new CompilationResult ();
- if (compiler.Compile (result) == false)
- throw new CompilationException (result);
-
- Assembly assembly = Assembly.LoadFrom (result.OutputFile);
- Type [] types = assembly.GetTypes ();
- Type type = types [0];
- if (type.FullName != wService.ClassName)
- throw new ApplicationException (String.Format (
- "Class={0}, but the class compiled is {1}",
- wService.ClassName,
- type.FullName));
-
- result.Data = type;
- return type;
- }
-
- public override string Key {
- get {
- return wService.PhysicalPath;
- }
- }
-
- public override string SourceFile {
- get {
- return sourceFile;
- }
+ return null;
}
}
}