Minor changes to improve testability of helpers
[castle.git] / MonoRail / Castle.MonoRail.Framework / Extensions / ExceptionChaining / AbstractExceptionHandler.cs
blob40dbee95902387afeccb96402f760d3504de24ae
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework.Extensions.ExceptionChaining
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.Text;
22 /// <summary>
23 /// Provides a basic implementation of <see cref="IExceptionHandler"/>
24 /// </summary>
25 public abstract class AbstractExceptionHandler : IExceptionHandler
27 private IExceptionHandler nextHandler;
29 /// <summary>
30 /// Implementors should perform any required
31 /// initialization
32 /// </summary>
33 public virtual void Initialize()
37 /// <summary>
38 /// Implementors should perform the action
39 /// on the exception. Note that the exception
40 /// is available in <see cref="IRailsEngineContext.LastException"/>
41 /// </summary>
42 /// <param name="context"></param>
43 public abstract void Process(IRailsEngineContext context);
45 /// <summary>
46 /// The next exception in the sink
47 /// or null if none exists.
48 /// </summary>
49 /// <value></value>
50 public IExceptionHandler Next
52 get { return nextHandler; }
53 set { nextHandler = value; }
56 /// <summary>
57 /// Invokes the next handler.
58 /// </summary>
59 /// <param name="context">The context.</param>
60 protected void InvokeNext(IRailsEngineContext context)
62 if (nextHandler != null)
64 nextHandler.Process(context);
68 /// <summary>
69 /// Builds the standard message.
70 /// </summary>
71 /// <param name="context">The context.</param>
72 /// <returns></returns>
73 protected string BuildStandardMessage(IRailsEngineContext context)
75 StringBuilder sbMessage = new StringBuilder();
77 sbMessage.Append("Controller details\r\n");
78 sbMessage.Append("==================\r\n\r\n");
79 sbMessage.AppendFormat("Url {0}\r\n", context.Url);
80 sbMessage.AppendFormat("Area {0}\r\n", context.UrlInfo.Area);
81 sbMessage.AppendFormat("Controller {0}\r\n", context.UrlInfo.Controller);
82 sbMessage.AppendFormat("Action {0}\r\n", context.UrlInfo.Action);
83 sbMessage.AppendFormat("Extension {0}\r\n\r\n", context.UrlInfo.Extension);
85 sbMessage.Append("Exception details\r\n");
86 sbMessage.Append("=================\r\n\r\n");
87 sbMessage.AppendFormat("Exception occured at {0}\r\n", DateTime.Now);
88 RecursiveDumpException(context.LastException, sbMessage, 0);
90 sbMessage.Append("\r\nEnvironment and params");
91 sbMessage.Append("\r\n======================\r\n\r\n");
92 sbMessage.AppendFormat("ApplicationPath {0}\r\n", context.ApplicationPath);
93 sbMessage.AppendFormat("ApplicationPhysicalPath {0}\r\n", context.ApplicationPhysicalPath);
94 sbMessage.AppendFormat("RequestType {0}\r\n", context.RequestType);
95 sbMessage.AppendFormat("UrlReferrer {0}\r\n", context.UrlReferrer);
97 if (context.CurrentUser != null)
99 sbMessage.AppendFormat("CurrentUser.Name {0}\r\n", context.CurrentUser.Identity.Name);
100 sbMessage.AppendFormat("CurrentUser.AuthenticationType {0}\r\n", context.CurrentUser.Identity.AuthenticationType);
101 sbMessage.AppendFormat("CurrentUser.IsAuthenticated {0}\r\n", context.CurrentUser.Identity.IsAuthenticated);
104 DumpDictionary(context.Flash, "Flash", sbMessage);
106 DumpDictionary(context.Params, "Params", sbMessage);
108 DumpDictionary(context.Session, "Session", sbMessage);
110 return sbMessage.ToString();
113 private void DumpDictionary(IDictionary dict, String title, StringBuilder message)
115 message.AppendFormat("{0}: \r\n", title);
119 foreach(DictionaryEntry entry in dict)
121 message.AppendFormat("\r\n\t{0}:{1}", entry.Key, entry.Value);
124 catch(Exception)
126 // Ignores
130 private void DumpDictionary(NameValueCollection dict, String title, StringBuilder message)
132 message.AppendFormat("{0}: \r\n", title);
136 foreach(String key in dict.Keys)
138 message.AppendFormat("\r\n\t{0}:{1} \r\n", key, dict[key]);
141 catch(Exception)
143 // Ignores
147 private void RecursiveDumpException(Exception exception, StringBuilder message, int nested)
149 if (exception == null) return;
151 char[] spaceBuff = new char[nested * 2];
152 for(int i = 0; i < nested * 2; i++) spaceBuff[i] = ' ';
154 String space = new String(spaceBuff);
156 message.AppendFormat("{0}Exception: {1}\r\n", space, exception.Message);
157 message.AppendFormat("{0}Stack Trace:\r\n{0}{1}\r\n", space, exception.StackTrace);
159 RecursiveDumpException(exception.InnerException, message, nested + 1);