f18643c54325eb8d77ada48f61cc51cc9e3fff75
[pithos-ms-client] / trunk%2FPithos.Client.WPF%2FApp.xaml.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="App.xaml.cs" company="GRNet">
4  * 
5  * Copyright 2011-2012 GRNET S.A. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  *   1. Redistributions of source code must retain the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer.
14  *
15  *   2. Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials
18  *      provided with the distribution.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and
35  * documentation are those of the authors and should not be
36  * interpreted as representing official policies, either expressed
37  * or implied, of GRNET S.A.
38  * </copyright>
39  * -----------------------------------------------------------------------
40  */
41 #endregion
42 using System;
43 using System.Collections.Generic;
44 using System.IO;
45 using System.Linq;
46 using System.Net;
47 using System.Reflection;
48 using System.Text;
49 using System.Threading;
50 using System.Threading.Tasks;
51 using System.Windows;
52 using Caliburn.Micro;
53 using Pithos.Client.WPF.Configuration;
54 using Pithos.Client.WPF.Properties;
55 using log4net.Appender;
56 using log4net.Core;
57 using log4net.Repository.Hierarchy;
58 using System.Runtime.InteropServices;
59
60
61 namespace Pithos.Client.WPF
62 {
63     /// <summary>
64     /// Interaction logic for App.xaml
65     /// </summary>
66     public partial class App : Application
67     {
68         private static readonly log4net.ILog Log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
69         
70             ///DLL Import to add restart manager support
71             [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
72             static extern uint RegisterApplicationRestart(string pwzCommandLine, RestartFlags dwFlags);
73                 
74         public App()
75         {
76
77             //var instanceMutex=new Mutex()
78
79             InitializeLogging();
80
81             ///Register Application in the Restartmanager service
82             RegisterApplicationRestart("Upgrade", RestartFlags.NONE);
83
84
85             DispatcherUnhandledException += OnDispatcherUnhandledException;
86             AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
87             TaskScheduler.UnobservedTaskException += OnUnobservedException;
88
89
90             //Fix incorrect proxy settings by switching to default proxy, if the proxy server settings is empty
91             if (Settings.Default.UseManualProxy && String.IsNullOrWhiteSpace(Settings.Default.ProxyServer))
92             {
93                 Settings.Default.UseManualProxy = false;
94                 Settings.Default.UseDefaultProxy = true;
95             }
96
97             if (Settings.Default.IgnoreCertificateErrors)
98                 ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
99
100
101             InitializeComponent();            
102         }       
103
104
105 /*
106         private void OnUpdateDetected(object sender, UpdateDetectedEventArgs e)
107         {
108             Log.InfoFormat("Update Detected {0}",e.LatestVersion.Version);    
109         }
110 */
111
112         private static void InitializeLogging()
113         {
114             log4net.Config.XmlConfigurator.Configure();
115
116             try
117             {
118                 var pithosDataPath = PithosSettings.PithosDataPath;
119                 if (!Directory.Exists(pithosDataPath))
120                     Directory.CreateDirectory(pithosDataPath);
121
122                 var loggerRepository = (Hierarchy)log4net.LogManager.GetRepository();
123
124                 var appenders = loggerRepository.GetAppenders();
125                 
126
127                 var lossyAppender = appenders.OfType<BufferingForwardingAppender>()
128                     .FirstOrDefault(appender => appender.Name == "LossyFileAppender");
129                 if (lossyAppender!=null)
130                 {
131                     var dumpAppender = lossyAppender.Appenders.OfType<RollingFileAppender>().First();
132                     dumpAppender.File = Path.Combine(pithosDataPath, "errorlog.xml");
133                     dumpAppender.ActivateOptions();
134                 }
135                 
136                 var debugAppender =appenders.OfType<RollingFileAppender>()
137                     .FirstOrDefault(a => a.Name == "DebugFileAppender");
138                 if (debugAppender != null)
139                 {
140                     debugAppender.File = Path.Combine(pithosDataPath, "debuglog.xml");
141                     if (!Settings.Default.DebugLoggingEnabled)
142                         debugAppender.Threshold = Level.Off;
143                     debugAppender.ActivateOptions();
144                 }
145             }
146             catch (Exception exc)
147             {
148                 Log.Error("Dumpl appender initialization failed",exc);                
149             }
150         }
151
152         private Mutex _singleInstanceMutex;
153
154         protected override void OnStartup(StartupEventArgs e)
155         {
156             if (!Settings.Default.StartOnSystemStartup && e.Args.Contains("startup"))
157             {
158                 Shutdown();
159                 return;
160             }
161
162             bool firstInstance;
163             _singleInstanceMutex = new Mutex(false, "PITHOSMUTEX", out firstInstance);
164             if (!firstInstance)
165             {
166                 _singleInstanceMutex.Dispose();
167                 _singleInstanceMutex = null;
168                 Shutdown();
169                 return;
170             }
171
172             //Delay during startup
173             if (e.Args.Contains("startup"))
174             {
175                 if (Settings.Default.StartupDelay>TimeSpan.Zero)
176                     Thread.Sleep(Settings.Default.StartupDelay);
177             }
178
179             var splashScreen = new SplashScreen("images/pithos_logo-title-margin-splash-600-whitebg.png");
180             splashScreen.Show(true);
181             
182             base.OnStartup(e);
183         }
184
185         protected override void OnExit(ExitEventArgs e)
186         {
187             try
188             {
189                 if (_singleInstanceMutex!=null)
190                     _singleInstanceMutex.Dispose();
191                 _singleInstanceMutex = null;
192             }
193             catch { }
194             base.OnExit(e);
195         }
196
197         private void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
198         {
199             Log.Error("Unobserved Task Exception", e.Exception); 
200             
201             var messages = new List<UserMessage>();
202             e.Exception.Handle(exc=>{
203                 messages.Add(new UserMessage
204                 {
205                     Message = "Unexpected Exception",
206                     Details = exc.ToString(),
207                     Severity = Severity.Error
208                 });
209                 return true;
210             });
211
212
213             var message = String.Format(@"{0}" + Environment.NewLine + "{1}" + Environment.NewLine + "{2}", 
214                 WPF.Properties.Resources.Unexpected_Error,
215                 WPF.Properties.Resources.We_Apologize, 
216                 WPF.Properties.Resources.Please_Submit_Error);
217             ShowMessages("Oops!",message, messages);
218             e.SetObserved();            
219         }
220
221         private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
222         {
223             Log.Error("Unhandled exception", (Exception)e.ExceptionObject);
224
225             var description = e.IsTerminating
226                               ? WPF.Properties.Resources.Unexpected_Error_Terminating
227                               : WPF.Properties.Resources.Unexpected_Error;
228             var message = String.Format(@"{0}<LineBreak/>{1}<LineBreak/><LineBreak/>{2}",
229                 description,
230                 WPF.Properties.Resources.We_Apologize,
231                 WPF.Properties.Resources.Please_Submit_Error);
232
233
234             var exc = ((Exception) e.ExceptionObject);
235             var messages = new[]{
236                                    new UserMessage
237                                        {
238                                            Message = exc.Message,
239                                            Details = exc.ToString(),
240                                            Severity = Severity.Error
241                                        }
242                                };
243
244
245             ShowMessages("Oops!", message,messages);
246         }
247
248         void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
249         {
250             Log.Error("Unhandled Dispatcher exception", e.Exception);
251             
252             var messages = new[]{
253                                    new UserMessage
254                                        {
255                                            Message = e.Exception.Message, 
256                                            Details = e.Exception.ToString(),
257                                            Severity = Severity.Error
258                                        }
259                                };
260             ShowMessages(WPF.Properties.Resources.Error_Title, 
261                 WPF.Properties.Resources.Unexpected_Error,
262                 messages);
263             e.Handled=true;
264         }
265
266         void ShowMessages(string title,string message,IEnumerable<UserMessage> messages )
267         {
268             var messageList = messages.ToList();
269             LogMessages(messageList);
270             Execute.OnUIThread(()=>{
271                                        var messageView = new MessageView(messageList)
272                                                         {
273                                                             Title = title, 
274                                                             Message = message
275                                                         };
276                                        messageView.ShowDialog();
277             });
278         }
279
280         private void LogMessages(IEnumerable<UserMessage> messages)
281         {
282             var logMessage = CreateMessage(messages);
283
284             Log.Error(logMessage);
285         }
286
287         private static string CreateMessage(IEnumerable<UserMessage> messages)
288         {
289             var messageBuilder = messages.Aggregate(new StringBuilder("Unexpected Error\r\n"),
290                                                     (builder, message) =>
291                                                         {
292                                                             builder.AppendFormat("\r\n[{0}] {1}\r\n{2}\r\n", message.Severity,
293                                                                                  message.Message, message.Details);
294                                                             return builder;
295                                                         });
296             var logMessage = messageBuilder.ToString();
297             return logMessage;
298         }
299     }
300
301 }
302
303     enum RestartFlags
304     {
305         NONE = 0,
306         RESTART_CYCLICAL = 1,
307         RESTART_NOTIFY_SOLUTION = 2,
308         RESTART_NOTIFY_FAULT = 4,
309         RESTART_NO_CRASH = 8,
310         RESTART_NO_HANG = 16,
311         RESTART_NO_PATCH = 32,
312         RESTART_NO_REBOOT = 64
313     }