Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / App.xaml.cs @ 5bded227

History | View | Annotate | Download (15.5 kB)

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
            
82

    
83
            //Detect OS, if Major Version is 6+ use RestartManager
84
            OperatingSystem os = Environment.OSVersion;
85
            Version vs = os.Version;
86

    
87
            //Register Application in the Restartmanager service
88
            Log.ErrorFormat("OS: [{0}]", vs.Major);
89
            if (vs.Major > 5)
90
            {
91
                Int32 result = RegisterApplicationRestart(null, 0);
92
                Log.ErrorFormat("RM Result: [{0}]", result);
93
            }
94

    
95
            DispatcherUnhandledException += OnDispatcherUnhandledException;
96
            AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
97
            TaskScheduler.UnobservedTaskException += OnUnobservedException;
98

    
99

    
100
            //Fix incorrect proxy settings by switching to default proxy, if the proxy server settings is empty
101
            if (Settings.Default.UseManualProxy && String.IsNullOrWhiteSpace(Settings.Default.ProxyServer))
102
            {
103
                Settings.Default.UseManualProxy = false;
104
                Settings.Default.UseDefaultProxy = true;
105
            }
106

    
107
            if (Settings.Default.IgnoreCertificateErrors)
108
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
109
            ServicePointManager.Expect100Continue = false;
110
            InitializeComponent();            
111
        }
112

    
113

    
114
/*        private static string[] platformLibraries = {"libeay32.dll","ssleay32.dll"};
115
        private static Assembly CustomResolve(object sender,ResolveEventArgs args)
116
        {
117

    
118
            if (platformLibraries.Contains(args.Name))
119
            {
120
                var platformPath = Path.Combine(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
121
                                                + args.Name);
122
                string fileName = Path.GetFullPath( platformPath);
123

    
124
                if (File.Exists(fileName))
125
                {
126
                    if (Log.IsDebugEnabled)
127
                        Log.DebugFormat("[PLATFORM] Loading {0}", fileName);
128
                    return Assembly.LoadFile(fileName);
129
                }
130
                else
131
                {
132
                    Log.ErrorFormat("Platform specific file [{0}] not found",fileName);
133
                }
134
            }
135
            return null;
136
        }*/
137
/*
138
        private void OnUpdateDetected(object sender, UpdateDetectedEventArgs e)
139
        {
140
            Log.InfoFormat("Update Detected {0}",e.LatestVersion.Version);    
141
        }
142
*/
143

    
144
        private static void InitializeLogging()
145
        {
146
            log4net.Config.XmlConfigurator.Configure();
147

    
148
            try
149
            {
150
                var pithosDataPath = PithosSettings.PithosDataPath;
151
                if (!Directory.Exists(pithosDataPath))
152
                    Directory.CreateDirectory(pithosDataPath);
153

    
154
                var loggerRepository = (Hierarchy)log4net.LogManager.GetRepository();
155

    
156
                var appenders = loggerRepository.GetAppenders();
157
                
158

    
159
                var lossyAppender = appenders.OfType<BufferingForwardingAppender>()
160
                    .FirstOrDefault(appender => appender.Name == "LossyFileAppender");
161
                if (lossyAppender!=null)
162
                {
163
                    var dumpAppender = lossyAppender.Appenders.OfType<RollingFileAppender>().First();
164
                    dumpAppender.File = Path.Combine(pithosDataPath, "errorlog.xml");
165
                    dumpAppender.ActivateOptions();
166
                }
167
                
168
                var debugAppender =appenders.OfType<RollingFileAppender>()
169
                    .FirstOrDefault(a => a.Name == "DebugFileAppender");
170
                if (debugAppender != null)
171
                {
172
                    debugAppender.File = Path.Combine(pithosDataPath, "debuglog.xml");
173
                    if (!Settings.Default.DebugLoggingEnabled)
174
                        debugAppender.Threshold = Level.Off;
175
                    debugAppender.ActivateOptions();
176
                }
177
            }
178
            catch (Exception exc)
179
            {
180
                Log.Error("Dumpl appender initialization failed",exc);                
181
            }
182
        }
183

    
184
        private Mutex _singleInstanceMutex;
185

    
186
        protected override void OnStartup(StartupEventArgs e)
187
        {
188
            if (!Settings.Default.StartOnSystemStartup && e.Args.Contains("startup"))
189
            {
190
                Shutdown();
191
                return;
192
            }
193

    
194
            bool firstInstance;
195
            _singleInstanceMutex = new Mutex(false, "PITHOSMUTEX", out firstInstance);
196
            if (!firstInstance)
197
            {
198
                _singleInstanceMutex.Dispose();
199
                _singleInstanceMutex = null;
200
                Log.Warn("An instance of Pithos+ is already running. Terminating.");
201
                Shutdown();
202
                return;
203
            }
204

    
205
            //Delay during startup
206
            if (e.Args.Contains("startup"))
207
            {
208
                if (Settings.Default.StartupDelay>TimeSpan.Zero)
209
                    Thread.Sleep(Settings.Default.StartupDelay);
210
            }
211

    
212
            var splashScreen = new SplashScreen("images/pithos_logo-title-margin-splash-600-whitebg.png");
213
            splashScreen.Show(true);
214
            
215
            base.OnStartup(e);
216
        }
217

    
218
        protected override void OnExit(ExitEventArgs e)
219
        {
220
            try
221
            {
222
                if (_singleInstanceMutex!=null)
223
                    _singleInstanceMutex.Dispose();
224
                _singleInstanceMutex = null;
225
            }
226
            catch { }
227
            base.OnExit(e);
228
        }
229

    
230
        private void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
231
        {
232
            Log.Error("Unobserved Task Exception", e.Exception); 
233
            
234
            var messages = new List<UserMessage>();
235
            e.Exception.Handle(exc=>{
236
                messages.Add(new UserMessage
237
                {
238
                    Message = "Unexpected Exception",
239
                    Details = exc.ToString(),
240
                    Severity = Severity.Error
241
                });
242
                return true;
243
            });
244

    
245

    
246
            //Do not display any messages if this is a 304 code
247
            var ignoreExceptions = from exc in e.Exception.InnerExceptions.OfType<WebException>()
248
                                   where IsAllowedException(exc)
249
                                   select exc;
250

    
251
            if (ignoreExceptions.Any())
252
            {
253
                e.SetObserved();
254
                return;
255
            }
256

    
257

    
258
           /* var message = String.Format(@"{0}" + Environment.NewLine + "{1}" + Environment.NewLine + "{2}", 
259
                WPF.Properties.Resources.Unexpected_Error,
260
                WPF.Properties.Resources.We_Apologize, 
261
                WPF.Properties.Resources.Please_Submit_Error);
262
            ShowMessages("Oops!",message, messages);*/
263
            e.SetObserved();            
264
        }
265

    
266
        private bool IsAllowedException(Exception exc)
267
        {
268
            var we = exc as WebException;
269
            if (we==null)
270
            {
271
                return false;
272
            }
273
            var response = we.Response as HttpWebResponse;
274
            return (response != null && response.StatusCode == HttpStatusCode.NotModified);
275
        }
276

    
277
        private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
278
        {
279

    
280
            //Do not display any messages if this is a 304 code
281
            if (IsAllowedException(e.ExceptionObject as Exception))
282
            {
283
                return;
284
            }
285

    
286
            if (e.ExceptionObject is ReflectionTypeLoadException)
287
            {
288
                var les=(ReflectionTypeLoadException) e.ExceptionObject;
289
                Log.Error("Unhandled exception", les);
290
                foreach (var le in les.LoaderExceptions)
291
                {
292
                    Log.Error("Dll load error", le);    
293
                }
294
            }
295
            else
296
                Log.Error("Unhandled exception", (Exception)e.ExceptionObject);
297

    
298
            if (!e.IsTerminating)
299
                //Do not display a message unless the application is terminating
300
                return;
301

    
302
            var description = e.IsTerminating
303
                              ? WPF.Properties.Resources.Unexpected_Error_Terminating
304
                              : WPF.Properties.Resources.Unexpected_Error;
305
            var message = String.Format(@"{0}<LineBreak/>{1}<LineBreak/><LineBreak/>{2}",
306
                description,
307
                WPF.Properties.Resources.We_Apologize,
308
                WPF.Properties.Resources.Please_Submit_Error);
309

    
310
            var exc = ((Exception) e.ExceptionObject);
311
            var messages = new[]{
312
                                   new UserMessage
313
                                       {
314
                                           Message = exc.Message,
315
                                           Details = exc.ToString(),
316
                                           Severity = Severity.Error
317
                                       }
318
                               };
319

    
320

    
321
            ShowMessages("Oops!", message,messages);
322
        }
323

    
324

    
325

    
326
        void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
327
        {
328
            //Do not display any messages if this is a 304 code
329
            if (IsAllowedException(e.Exception))
330
            {
331
                return;
332
            }
333

    
334
            if (e.Exception is ReflectionTypeLoadException)
335
            {
336
                var les = (ReflectionTypeLoadException)e.Exception;
337
                Log.Error("Unhandled exception", les);
338
                foreach (var le in les.LoaderExceptions)
339
                {
340
                    Log.Error("Dll load error", le);
341
                }
342
            }
343
            else
344
                Log.Error("Unhandled Dispatcher exception", e.Exception);
345
            
346
           /* var messages = new[]{
347
                                   new UserMessage
348
                                       {
349
                                           Message = e.Exception.Message, 
350
                                           Details = e.Exception.ToString(),
351
                                           Severity = Severity.Error
352
                                       }
353
                               };
354
            ShowMessages(WPF.Properties.Resources.Error_Title, 
355
                WPF.Properties.Resources.Unexpected_Error,
356
                messages);*/
357
            e.Handled=true;
358
        }
359

    
360
        void ShowMessages(string title,string message,IEnumerable<UserMessage> messages )
361
        {
362
            var messageList = messages.ToList();
363
            LogMessages(messageList);
364
            Execute.OnUIThread(()=>{
365
                                       var messageView = new MessageView(messageList)
366
                                                        {
367
                                                            Title = title, 
368
                                                            Message = message
369
                                                        };
370
                                       messageView.ShowDialog();
371
            });
372
        }
373

    
374
        private void LogMessages(IEnumerable<UserMessage> messages)
375
        {
376
            var logMessage = CreateMessage(messages);
377

    
378
            Log.Error(logMessage);
379
        }
380

    
381
        private static string CreateMessage(IEnumerable<UserMessage> messages)
382
        {
383
            var messageBuilder = messages.Aggregate(new StringBuilder("Unexpected Error\r\n"),
384
                                                    (builder, message) =>
385
                                                        {
386
                                                            builder.AppendFormat("\r\n[{0}] {1}\r\n{2}\r\n", message.Severity,
387
                                                                                 message.Message, message.Details);
388
                                                            return builder;
389
                                                        });
390
            var logMessage = messageBuilder.ToString();
391
            return logMessage;
392
        }
393
    }
394

    
395
}
396

    
397
    enum RestartFlags
398
    {
399
        NONE = 0,
400
        RESTART_CYCLICAL = 1,
401
        RESTART_NOTIFY_SOLUTION = 2,
402
        RESTART_NOTIFY_FAULT = 4,
403
        RESTART_NO_CRASH = 8,
404
        RESTART_NO_HANG = 16,
405
        RESTART_NO_PATCH = 32,
406
        RESTART_NO_REBOOT = 64
407
    }