Call SetEndOfSendNotification
[mono.git] / mcs / class / System.Web / System.Web / HttpException.cs
index ffa3a3aca6767338173853a1006bbedc68db2c55..006da9ed8320b33e8b84c2a83c7b9d06366bc775 100644 (file)
@@ -7,7 +7,7 @@
 //
 // (c) 2002 Patrik Torstensson
 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -36,6 +36,7 @@ using System.Security.Permissions;
 using System.Text;
 using System.Web.Util;
 using System.Web.Compilation;
+using System.Web.Management;
 using System.Collections.Specialized;
 
 namespace System.Web
@@ -43,19 +44,28 @@ namespace System.Web
        // CAS
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
-#if NET_2_0
        [Serializable]
-#endif
        public class HttpException : ExternalException
        {
                const string DEFAULT_DESCRIPTION_TEXT = "Error processing request.";
                const string ERROR_404_DESCRIPTION = "The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.";
-               
+
+               int webEventCode = WebEventCodes.UndefinedEventCode;
                int http_code = 500;
                string resource_name;
                string description;
                
                const string errorStyleFonts = "\"Verdana\",\"DejaVu Sans\",sans-serif";
+
+#if NET_4_0
+               public
+#else
+               internal
+#endif
+               int WebEventCode 
+               {
+                       get { return webEventCode; }
+               }
                
                public HttpException ()
                {
@@ -86,11 +96,11 @@ namespace System.Web
                        this.description = description;
                }
                
-#if NET_2_0
                protected HttpException (SerializationInfo info, StreamingContext context)
                        : base (info, context)
                {
                        http_code = info.GetInt32 ("_httpCode");
+                       webEventCode = info.GetInt32 ("_webEventCode");
                }
 
                [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
@@ -98,8 +108,8 @@ namespace System.Web
                {
                        base.GetObjectData (info, context);
                        info.AddValue ("_httpCode", http_code);
+                       info.AddValue ("_webEventCode", webEventCode);
                }
-#endif
 
                public HttpException (int httpCode, string message, int hr) 
                        : base (message, hr)
@@ -118,7 +128,7 @@ namespace System.Web
                        http_code = httpCode;
                }
 
-               public HttpException (int httpCode, string message, Exception innerException, string resourceName)
+               internal HttpException (int httpCode, string message, Exception innerException, string resourceName)
                        : this (httpCode, message, innerException)
                {
                        resource_name = resourceName;
@@ -127,13 +137,23 @@ namespace System.Web
                public string GetHtmlErrorMessage ()
                {
                        try {
-                               if (HttpContext.Current.IsCustomErrorEnabled)
-                                       return GetCustomErrorDefaultMessage ();
+                               HttpContext ctx = HttpContext.Current;
+                               if (ctx != null && ctx.IsCustomErrorEnabled) {
+                                       if (http_code != 404 && http_code != 403)
+                                               return GetCustomErrorDefaultMessage ();
+                                       else
+                                               return GetDefaultErrorMessage (false, null);
+                               }
                                
-                               if (!(this.InnerException is HtmlizedException))
-                                       return GetDefaultErrorMessage ();
+                               Exception ex = GetBaseException ();
+                               if (ex == null)
+                                       ex = this;
                                
-                               return GetHtmlizedErrorMessage ();
+                               HtmlizedException htmlException = ex  as HtmlizedException;
+                               if (htmlException == null)
+                                       return GetDefaultErrorMessage (true, ex);
+                               
+                               return GetHtmlizedErrorMessage (htmlException);
                        } catch (Exception ex) {
                                Console.WriteLine (ex);
                                
@@ -160,8 +180,78 @@ namespace System.Web
                        }
                }
 
+               internal static HttpException NewWithCode (string message, int webEventCode)
+               {
+                       var ret = new HttpException (message);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+
+               internal static HttpException NewWithCode (string message, Exception innerException, int webEventCode)
+               {
+                       var ret = new HttpException (message, innerException);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+
+               internal static HttpException NewWithCode (int httpCode, string message, int webEventCode)
+               {
+                       var ret = new HttpException (httpCode, message);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+               
+               internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, string resourceName, int webEventCode)
+               {
+                       var ret = new HttpException (httpCode, message, innerException, resourceName);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+
+               internal static HttpException NewWithCode (int httpCode, string message, string resourceName, int webEventCode)
+               {
+                       var ret = new HttpException (httpCode, message, resourceName);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+
+               internal static HttpException NewWithCode (int httpCode, string message, Exception innerException, int webEventCode)
+               {
+                       var ret = new HttpException (httpCode, message, innerException);
+                       ret.SetWebEventCode (webEventCode);
+
+                       return ret;
+               }
+               
+               internal void SetWebEventCode (int webEventCode)
+               {
+                       this.webEventCode = webEventCode;
+               }
+               
                void WriteFileTop (StringBuilder builder, string title)
                {
+#if TARGET_J2EE
+                       builder.AppendFormat ("<html><head><title>{0}</title><style type=\"text/css\">", title);
+                       builder.AppendFormat (
+                               @"body {{font-family:{0};font-weight:normal;font-size: 9pt;color:black;background-color: white}}
+p {{font-family:{0};font-weight:normal;color:black;margin-top: -5px}}
+b {{font-family:{0};font-weight:bold;color:black;margin-top: -5px}}
+h1 {{ font-family:{0};font-weight:normal;font-size:18pt;color:red }}
+h2 {{ font-family:{0};font-weight:normal;font-size:14pt;color:maroon }}
+pre {{font-family:""Lucida Console"",""DejaVu Sans Mono"",monospace;font-size: 10pt}}
+div.bodyText {{font-family: {0}}}
+table.sampleCode {{width: 100%; background-color: #ffffcc; }}
+.errorText {{color: red; font-weight: bold}}
+.marker {{font-weight: bold; color: black;text-decoration: none;}}
+.version {{color: gray;}}
+.error {{margin-bottom: 10px;}}
+.expandable {{ text-decoration:underline; font-weight:bold; color:navy; cursor:pointer; }}", errorStyleFonts);
+#else
                        builder.Append ("<?xml version=\"1.0\" ?>\n");
                        builder.Append ("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
                        builder.AppendFormat ("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>{0}</title><style type=\"text/css\">", title);
@@ -171,7 +261,7 @@ p {{font-family:{0};font-weight:normal;color:black;margin-top: -5px}}
 b {{font-family:{0};font-weight:bold;color:black;margin-top: -5px}}
 h1 {{ font-family:{0};font-weight:normal;font-size:18pt;color:red }}
 h2 {{ font-family:{0};font-weight:normal;font-size:14pt;color:maroon }}
-pre {{font-family:""Lucida Console"",""DejaVu Sans Mono"",monospace;font-size: 0.9em}}
+pre,code {{font-family:""Lucida Console"",""DejaVu Sans Mono"",monospace;font-size: 0.9em,white-space: pre-line}}
 div.bodyText {{font-family: {0}}}
 table.sampleCode {{width: 100%; background-color: #ffffcc; }}
 .errorText {{color: red; font-weight: bold}}
@@ -179,39 +269,45 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
 .version {{color: gray;}}
 .error {{margin-bottom: 10px;}}
 .expandable {{ text-decoration:underline; font-weight:bold; color:navy; cursor:pointer; }}", errorStyleFonts);
+#endif
 
                        builder.AppendFormat (
                                "</style></head><body><h1>Server Error in '{0}' Application</h1><hr style=\"color: silver\"/>",
                                HtmlEncode (HttpRuntime.AppDomainAppVirtualPath));
                }
                
-               void WriteFileBottom (StringBuilder builder)
+               void WriteFileBottom (StringBuilder builder, bool showTrace)
                {
-                       builder.Append ("<hr style=\"color: silver\"/>");
-                       builder.AppendFormat ("<strong>Version information: </strong> Mono Version: {0}; ASP.NET Version: {0}</body></html>\r\n<!--", Environment.Version);
-                       
-                       string trace, message;
-                       bool haveTrace;
-                       Exception ex = this;
+                       if (showTrace) {
+                               builder.Append ("<hr style=\"color: silver\"/>");
+                               builder.AppendFormat ("<strong>Version information: </strong> Mono Runtime Version: <tt>{0}</tt>; ASP.NET Version: <tt>{1}</tt></body></html>\r\n",
+                                                     RuntimeHelpers.MonoVersion, Environment.Version);
                        
-                       while (ex != null) {
-                               trace = ex.StackTrace;
-                               message = ex.Message;
-                               haveTrace = (trace != null && trace.Length > 0);
+                               string trace, message;
+                               bool haveTrace;
+                               Exception ex = this;
+
+                               builder.Append ("\r\n<!--");
+                               while (ex != null) {
+                                       trace = ex.StackTrace;
+                                       message = ex.Message;
+                                       haveTrace = (trace != null && trace.Length > 0);
                                
-                               if (!haveTrace && (message == null || message.Length == 0)) {
-                                       ex = ex.InnerException;
-                                       continue;
-                               }
+                                       if (!haveTrace && (message == null || message.Length == 0)) {
+                                               ex = ex.InnerException;
+                                               continue;
+                                       }
 
-                               builder.Append ("\r\n[" + ex.GetType () + "]: " + HtmlEncode (message) + "\r\n");
-                               if (haveTrace)
-                                       builder.Append (ex.StackTrace);
+                                       builder.Append ("\r\n[" + ex.GetType () + "]: " + HtmlEncode (message) + "\r\n");
+                                       if (haveTrace)
+                                               builder.Append (ex.StackTrace);
                                
-                               ex = ex.InnerException;
-                       }
+                                       ex = ex.InnerException;
+                               }
                        
-                       builder.Append ("\r\n-->");
+                               builder.Append ("\r\n-->");
+                       } else
+                               builder.Append ("</body></html>\r\n");
                }
 
                string GetCustomErrorDefaultMessage ()
@@ -262,14 +358,14 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
 
     &lt;/system.web&gt;
 &lt;/configuration&gt;</pre></td></tr></table>");
-                       WriteFileBottom (builder);
+                       WriteFileBottom (builder, false);
                        return builder.ToString ();
                }
                
-               string GetDefaultErrorMessage ()
+               string GetDefaultErrorMessage (bool showTrace, Exception baseEx)
                {
-                       Exception ex, baseEx;
-                       ex = baseEx = GetBaseException ();
+                       Exception ex;
+                       ex = baseEx;
                        if (ex == null)
                                ex = this;
 
@@ -279,7 +375,7 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                        if (http_code == 404)
                                builder.Append ("The resource cannot be found.");
                        else
-                               builder.AppendFormat (HtmlEncode (ex.Message));
+                               builder.Append (HtmlEncode (ex.Message));
                        builder.Append ("</em></h2>\r\n<p><strong>Description: </strong>");
                        
                        if (http_code != 0)
@@ -288,15 +384,15 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                        builder.Append ("</p>\r\n");
 
                        if (resource_name != null && resource_name.Length > 0)
-                               builder.AppendFormat ("<p><strong>Resource URL: </strong>{0}</p>\r\n", resource_name);
+                               builder.AppendFormat ("<p><strong>Requested URL: </strong>{0}</p>\r\n", resource_name);
                        
-                       if (baseEx != null && http_code != 404) {
+                       if (showTrace && baseEx != null && http_code != 404 && http_code != 403) {
                                builder.Append ("<p><strong>Stack Trace: </strong></p>");
                                builder.Append ("<table summary=\"Stack Trace\" class=\"sampleCode\">\r\n<tr><td>");
                                WriteTextAsCode (builder, baseEx.ToString ());
                                builder.Append ("</td></tr>\r\n</table>\r\n");
                        }
-                       WriteFileBottom (builder);
+                       WriteFileBottom (builder, showTrace);
                        
                        return builder.ToString ();
                }
@@ -310,17 +406,32 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                        return res.Replace ("\r\n", "<br />");
                }
 
-               string GetHtmlizedErrorMessage ()
+               string FormatSourceFile (string filename)
+               {
+                       if (filename == null || filename.Length == 0)
+                               return String.Empty;
+
+                       if (filename.StartsWith ("@@"))
+                               return "[internal] <!-- " + filename + " -->";
+
+                       return filename;
+               }
+               
+               string GetHtmlizedErrorMessage (HtmlizedException exc)
                {
                        StringBuilder builder = new StringBuilder ();
-                       HtmlizedException exc = (HtmlizedException) this.InnerException;
+#if TARGET_J2EE
+                       bool isParseException = false;
+                       bool isCompileException = false;
+#else
                        bool isParseException = exc is ParseException;
                        bool isCompileException = (!isParseException && exc is CompilationException);
+#endif
                        
                        WriteFileTop (builder, exc.Title);
                        builder.AppendFormat ("<h2><em>{0}</em></h2>\r\n", exc.Title);
                        builder.AppendFormat ("<p><strong>Description: </strong>{0}\r\n</p>\r\n", HtmlEncode (exc.Description));
-                       string errorMessage = HtmlEncode (exc.ErrorMessage).Replace ("\n", "<br/>");
+                       string errorMessage = HtmlEncode (exc.ErrorMessage);
                        
                        builder.Append ("<p><strong>");
                        if (isParseException)
@@ -328,7 +439,8 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                        else if (isCompileException)
                                builder.Append ("Compiler ");
                        
-                       builder.AppendFormat ("Error Message: </strong>{0}</p>", errorMessage);
+                       builder.Append ("Error Message: </strong>");
+                       builder.AppendFormat ("<code>{0}</code></p>", errorMessage);
 
                        StringBuilder longCodeVersion = null;
                        
@@ -349,13 +461,21 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
 
                                builder.Append ("<br/><p><strong>Source File: </strong>");
                                if (exc.SourceFile != exc.FileName)
-                                       builder.Append (exc.SourceFile);
+                                       builder.Append (FormatSourceFile (exc.SourceFile));
                                else
-                                       builder.Append (exc.FileName);
-                               
+                                       builder.Append (FormatSourceFile (exc.FileName));
+
                                if (isParseException || isCompileException) {
-                                       builder.Append ("&nbsp;&nbsp;<strong>Line: </strong>");
-                                       builder.Append (exc.ErrorLines [0]);
+                                       int[] errorLines = exc.ErrorLines;
+                                       int numErrors = errorLines != null ? errorLines.Length : 0;
+                                       if (numErrors > 0) {
+                                               builder.AppendFormat ("&nbsp;&nbsp;<strong>Line{0}: </strong>", numErrors > 1 ? "s" : String.Empty);
+                                               for (int i = 0; i < numErrors; i++) {
+                                                       if (i > 0)
+                                                               builder.Append (", ");
+                                                       builder.Append (exc.ErrorLines [i]);
+                                               }
+                                       }
                                }
                                builder.Append ("</p>");
                        } else if (exc.FileName != null)
@@ -363,6 +483,7 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
 
                        bool needToggleJS = false;
                        
+#if !TARGET_J2EE
                        if (isCompileException) {
                                CompilationException cex = exc as CompilationException;
                                StringCollection output = cex.CompilerOutput;
@@ -372,12 +493,13 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                                        StringBuilder sb = new StringBuilder ();
                                        foreach (string s in output)
                                                sb.Append (s + "\r\n");
-                                       WriteExpandableBlock (builder, "Show Detailed Compiler Output", sb.ToString ());
+                                       WriteExpandableBlock (builder, "compilerOutput", "Show Detailed Compiler Output", sb.ToString ());
                                }
                        }
+#endif
                        
                        if (longCodeVersion != null && longCodeVersion.Length > 0) {
-                               WriteExpandableBlock (builder, "Show Complete Compilation Source", longCodeVersion.ToString ());
+                               WriteExpandableBlock (builder, "fullCode", "Show Complete Compilation Source", longCodeVersion.ToString ());
                                needToggleJS = true;
                        }
 
@@ -395,16 +517,16 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                                                "}\r\n" +
                                                "</script>\r\n");
                        
-                       WriteFileBottom (builder);
+                       WriteFileBottom (builder, true);
                        
                        return builder.ToString ();
                }
 
-               static void WriteExpandableBlock (StringBuilder builder, string title, string contents)
+               static void WriteExpandableBlock (StringBuilder builder, string id, string title, string contents)
                {
-                       builder.AppendFormat ("<br><div class=\"expandable\" onclick=\"ToggleVisible ('fullCode')\">{0}:</div><br/>" +
-                                             "<div id=\"fullCode\" style=\"display: none\"><table summary=\"Details\" class=\"sampleCode\"><tr><td>" +
-                                             "<code><pre>\r\n", title);
+                       builder.AppendFormat ("<br><div class=\"expandable\" onclick=\"ToggleVisible ('{1}')\">{0}:</div><br/>" +
+                                             "<div id=\"{1}\" style=\"display: none\"><table summary=\"Details\" class=\"sampleCode\"><tr><td>" +
+                                             "<code><pre>\r\n", title, id);
                        builder.Append (contents);
                        builder.Append ("</pre></code></td></tr></table></div>");
                }
@@ -418,7 +540,7 @@ table.sampleCode {{width: 100%; background-color: #ffffcc; }}
                static void WriteSource (StringBuilder builder, StringBuilder longVersion, HtmlizedException e)
                {
                        builder.Append ("<code><pre>");
-                       WritePageSource (builder, longVersion, e);
+                       WritePageSource (builder, e);
                        builder.Append ("</code></pre>\r\n");
                }