Created separate version files for the client and libraries. The libraries have a...
[pithos-ms-client] / trunk / Pithos.Client.WPF / App.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 Pithos.Interfaces;
56 using log4net.Appender;
57 using log4net.Core;
58 using log4net.Repository.Hierarchy;
59 using System.Runtime.InteropServices;
60
61
62 namespace Pithos.Client.WPF
63 {
64     /// <summary>
65     /// Interaction logic for App.xaml
66     /// </summary>
67     public partial class App : Application
68     {
69         private static readonly log4net.ILog Log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
70         
71             ///DLL Import to add restart manager support
72             [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
73             public static extern Int32 RegisterApplicationRestart(String commandLineArgs, UInt32 flags);
74                 
75         public App()
76         {
77
78             //var instanceMutex=new Mutex()
79             InitializeLogging();
80
81             ///Register Application in the Restartmanager service
82             Int32 result = RegisterApplicationRestart(null, 0);
83             Log.ErrorFormat("RM Result: [{0}]", result);
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             ServicePointManager.Expect100Continue = false;
100             InitializeComponent();            
101         }       
102
103
104 /*
105         private void OnUpdateDetected(object sender, UpdateDetectedEventArgs e)
106         {
107             Log.InfoFormat("Update Detected {0}",e.LatestVersion.Version);    
108         }
109 */
110
111         private static void InitializeLogging()
112         {
113             log4net.Config.XmlConfigurator.Configure();
114
115             try
116             {
117                 var pithosDataPath = PithosSettings.PithosDataPath;
118                 if (!Directory.Exists(pithosDataPath))
119                     Directory.CreateDirectory(pithosDataPath);
120
121                 var loggerRepository = (Hierarchy)log4net.LogManager.GetRepository();
122
123                 var appenders = loggerRepository.GetAppenders();
124                 
125
126                 var lossyAppender = appenders.OfType<BufferingForwardingAppender>()
127                     .FirstOrDefault(appender => appender.Name == "LossyFileAppender");
128                 if (lossyAppender!=null)
129                 {
130                     var dumpAppender = lossyAppender.Appenders.OfType<RollingFileAppender>().First();
131                     dumpAppender.File = Path.Combine(pithosDataPath, "errorlog.xml");
132                     dumpAppender.ActivateOptions();
133                 }
134                 
135                 var debugAppender =appenders.OfType<RollingFileAppender>()
136                     .FirstOrDefault(a => a.Name == "DebugFileAppender");
137                 if (debugAppender != null)
138                 {
139                     debugAppender.File = Path.Combine(pithosDataPath, "debuglog.xml");
140                     if (!Settings.Default.DebugLoggingEnabled)
141                         debugAppender.Threshold = Level.Off;
142                     debugAppender.ActivateOptions();
143                 }
144             }
145             catch (Exception exc)
146             {
147                 Log.Error("Dumpl appender initialization failed",exc);                
148             }
149         }
150
151         private Mutex _singleInstanceMutex;
152
153         protected override void OnStartup(StartupEventArgs e)
154         {
155             if (!Settings.Default.StartOnSystemStartup && e.Args.Contains("startup"))
156             {
157                 Shutdown();
158                 return;
159             }
160
161             bool firstInstance;
162             _singleInstanceMutex = new Mutex(false, "PITHOSMUTEX", out firstInstance);
163             if (!firstInstance)
164             {
165                 _singleInstanceMutex.Dispose();
166                 _singleInstanceMutex = null;
167                 Shutdown();
168                 return;
169             }
170
171             //Delay during startup
172             if (e.Args.Contains("startup"))
173             {
174                 if (Settings.Default.StartupDelay>TimeSpan.Zero)
175                     Thread.Sleep(Settings.Default.StartupDelay);
176             }
177
178             var splashScreen = new SplashScreen("images/pithos_logo-title-margin-splash-600-whitebg.png");
179             splashScreen.Show(true);
180             
181             base.OnStartup(e);
182         }
183
184         protected override void OnExit(ExitEventArgs e)
185         {
186             try
187             {
188                 if (_singleInstanceMutex!=null)
189                     _singleInstanceMutex.Dispose();
190                 _singleInstanceMutex = null;
191             }
192             catch { }
193             base.OnExit(e);
194         }
195
196         private void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
197         {
198             Log.Error("Unobserved Task Exception", e.Exception); 
199             
200             var messages = new List<UserMessage>();
201             e.Exception.Handle(exc=>{
202                 messages.Add(new UserMessage
203                 {
204                     Message = "Unexpected Exception",
205                     Details = exc.ToString(),
206                     Severity = Severity.Error
207                 });
208                 return true;
209             });
210
211
212             //Do not display any messages if this is a 304 code
213             var ignoreExceptions = from exc in e.Exception.InnerExceptions.OfType<WebException>()
214                                    where IsAllowedException(exc)
215                                    select exc;
216
217             if (ignoreExceptions.Any())
218             {
219                 e.SetObserved();
220                 return;
221             }
222
223
224            /* var message = String.Format(@"{0}" + Environment.NewLine + "{1}" + Environment.NewLine + "{2}", 
225                 WPF.Properties.Resources.Unexpected_Error,
226                 WPF.Properties.Resources.We_Apologize, 
227                 WPF.Properties.Resources.Please_Submit_Error);
228             ShowMessages("Oops!",message, messages);*/
229             e.SetObserved();            
230         }
231
232         private bool IsAllowedException(Exception exc)
233         {
234             var we = exc as WebException;
235             if (we==null)
236             {
237                 return false;
238             }
239             var response = we.Response as HttpWebResponse;
240             return (response != null && response.StatusCode == HttpStatusCode.NotModified);
241         }
242
243         private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
244         {
245
246             //Do not display any messages if this is a 304 code
247             if (IsAllowedException(e.ExceptionObject as Exception))
248             {
249                 return;
250             }
251
252             Log.Error("Unhandled exception", (Exception)e.ExceptionObject);
253
254             if (!e.IsTerminating)
255                 //Do not display a message unless the application is terminating
256                 return;
257
258             var description = e.IsTerminating
259                               ? WPF.Properties.Resources.Unexpected_Error_Terminating
260                               : WPF.Properties.Resources.Unexpected_Error;
261             var message = String.Format(@"{0}<LineBreak/>{1}<LineBreak/><LineBreak/>{2}",
262                 description,
263                 WPF.Properties.Resources.We_Apologize,
264                 WPF.Properties.Resources.Please_Submit_Error);
265
266             var exc = ((Exception) e.ExceptionObject);
267             var messages = new[]{
268                                    new UserMessage
269                                        {
270                                            Message = exc.Message,
271                                            Details = exc.ToString(),
272                                            Severity = Severity.Error
273                                        }
274                                };
275
276
277             ShowMessages("Oops!", message,messages);
278         }
279
280
281
282         void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
283         {
284             //Do not display any messages if this is a 304 code
285             if (IsAllowedException(e.Exception))
286             {
287                 return;
288             }
289
290             Log.Error("Unhandled Dispatcher exception", e.Exception);
291             
292            /* var messages = new[]{
293                                    new UserMessage
294                                        {
295                                            Message = e.Exception.Message, 
296                                            Details = e.Exception.ToString(),
297                                            Severity = Severity.Error
298                                        }
299                                };
300             ShowMessages(WPF.Properties.Resources.Error_Title, 
301                 WPF.Properties.Resources.Unexpected_Error,
302                 messages);*/
303             e.Handled=true;
304         }
305
306         void ShowMessages(string title,string message,IEnumerable<UserMessage> messages )
307         {
308             var messageList = messages.ToList();
309             LogMessages(messageList);
310             Execute.OnUIThread(()=>{
311                                        var messageView = new MessageView(messageList)
312                                                         {
313                                                             Title = title, 
314                                                             Message = message
315                                                         };
316                                        messageView.ShowDialog();
317             });
318         }
319
320         private void LogMessages(IEnumerable<UserMessage> messages)
321         {
322             var logMessage = CreateMessage(messages);
323
324             Log.Error(logMessage);
325         }
326
327         private static string CreateMessage(IEnumerable<UserMessage> messages)
328         {
329             var messageBuilder = messages.Aggregate(new StringBuilder("Unexpected Error\r\n"),
330                                                     (builder, message) =>
331                                                         {
332                                                             builder.AppendFormat("\r\n[{0}] {1}\r\n{2}\r\n", message.Severity,
333                                                                                  message.Message, message.Details);
334                                                             return builder;
335                                                         });
336             var logMessage = messageBuilder.ToString();
337             return logMessage;
338         }
339     }
340
341 }
342
343     enum RestartFlags
344     {
345         NONE = 0,
346         RESTART_CYCLICAL = 1,
347         RESTART_NOTIFY_SOLUTION = 2,
348         RESTART_NOTIFY_FAULT = 4,
349         RESTART_NO_CRASH = 8,
350         RESTART_NO_HANG = 16,
351         RESTART_NO_PATCH = 32,
352         RESTART_NO_REBOOT = 64
353     }