Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / App.xaml.cs @ ac137734

History | View | Annotate | Download (16.7 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.Security.Cryptography;
49
using System.Text;
50
using System.Threading;
51
using System.Threading.Tasks;
52
using System.Windows;
53
using Caliburn.Micro;
54
using Pithos.Client.WPF.Configuration;
55
using Pithos.Client.WPF.Properties;
56
using Pithos.Interfaces;
57
using Pithos.Network;
58
using log4net.Appender;
59
using log4net.Core;
60
using log4net.Repository.Hierarchy;
61
using System.Runtime.InteropServices;
62

    
63

    
64
namespace Pithos.Client.WPF
65
{
66
    /// <summary>
67
    /// Interaction logic for App.xaml
68
    /// </summary>
69
    public partial class App : Application
70
    {
71
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
72
        
73
            //DLL Import to add restart manager support
74
            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
75
            public static extern Int32 RegisterApplicationRestart(String commandLineArgs, UInt32 flags);
76
		
77
        public App()
78
        {            
79
           
80
            //var instanceMutex=new Mutex()
81
            InitializeLogging();
82

    
83
            RegisterOpenSSL();
84

    
85

    
86
            //Detect OS, if Major Version is 6+ use RestartManager
87
            OperatingSystem os = Environment.OSVersion;
88
            Version vs = os.Version;
89

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

    
98
            DispatcherUnhandledException += OnDispatcherUnhandledException;
99
            AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
100
            TaskScheduler.UnobservedTaskException += OnUnobservedException;
101

    
102

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

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

    
116
        private static void RegisterOpenSSL()
117
        {
118

    
119
            //Try to instantiate OpenSSL and hash an empty array
120
            try
121
            {
122
                using(var testHasher=new SHA256OpenSSL())
123
                {
124
                    testHasher.ComputeHash(new byte[0]);
125
                }
126
                CryptoConfig.AddAlgorithm(typeof(SHA256OpenSSL), "SHA256");
127
                Log.InfoFormat("Registered OpenSSL hash provider");
128
            }
129
            catch (Exception exc)
130
            {
131
                Log.WarnFormat("OpenSSL instantiation failed. Falling back to CNG provider.\r\n[{0}]",exc);                
132
            }
133
            //Running on Vista + ?
134
            if (Environment.OSVersion.Version.Major >= 6)
135
            {
136
                CryptoConfig.AddAlgorithm(typeof(SHA256Cng), "SHA256");
137
                Log.InfoFormat("Registered CNG hash provider");
138
            }
139
            else
140
            {
141
                Log.WarnFormat("Running on XP. Falling back to default hash algorithm.");
142
            }
143

    
144
            
145
        }
146

    
147

    
148
/*        private static string[] platformLibraries = {"libeay32.dll","ssleay32.dll"};
149
        private static Assembly CustomResolve(object sender,ResolveEventArgs args)
150
        {
151

    
152
            if (platformLibraries.Contains(args.Name))
153
            {
154
                var platformPath = Path.Combine(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
155
                                                + args.Name);
156
                string fileName = Path.GetFullPath( platformPath);
157

    
158
                if (File.Exists(fileName))
159
                {
160
                    if (Log.IsDebugEnabled)
161
                        Log.DebugFormat("[PLATFORM] Loading {0}", fileName);
162
                    return Assembly.LoadFile(fileName);
163
                }
164
                else
165
                {
166
                    Log.ErrorFormat("Platform specific file [{0}] not found",fileName);
167
                }
168
            }
169
            return null;
170
        }*/
171
/*
172
        private void OnUpdateDetected(object sender, UpdateDetectedEventArgs e)
173
        {
174
            Log.InfoFormat("Update Detected {0}",e.LatestVersion.Version);    
175
        }
176
*/
177

    
178
        private static void InitializeLogging()
179
        {
180
            log4net.Config.XmlConfigurator.Configure();
181

    
182
            try
183
            {
184
                var pithosDataPath = PithosSettings.PithosDataPath;
185
                if (!Directory.Exists(pithosDataPath))
186
                    Directory.CreateDirectory(pithosDataPath);
187

    
188
                var loggerRepository = (Hierarchy)log4net.LogManager.GetRepository();
189

    
190
                var appenders = loggerRepository.GetAppenders();
191
                
192

    
193
/*
194
                var lossyAppender = appenders.OfType<BufferingForwardingAppender>()
195
                    .FirstOrDefault(appender => appender.Name == "LossyFileAppender");
196
                if (lossyAppender!=null)
197
                {
198
                    var dumpAppender = lossyAppender.Appenders.OfType<RollingFileAppender>().First();
199
                    dumpAppender.File = Path.Combine(pithosDataPath, "errorlog.xml");
200
                    dumpAppender.ActivateOptions();
201
                }
202
*/
203
                
204
                var debugAppender =appenders.OfType<RollingFileAppender>()
205
                    .FirstOrDefault(a => a.Name == "DebugFileAppender");
206
                if (debugAppender != null)
207
                {
208
                    //debugAppender.File = Path.Combine(pithosDataPath, "debuglog.xml");
209
                    if (!Settings.Default.DebugLoggingEnabled)
210
                    {
211
                        debugAppender.Threshold = Level.Off;
212
                        debugAppender.ActivateOptions();
213
                    }
214
                }
215
            }
216
            catch (Exception exc)
217
            {
218
                Log.Error("Dumpl appender initialization failed",exc);                
219
            }
220
        }
221

    
222
        private Mutex _singleInstanceMutex;
223

    
224
        protected override void OnStartup(StartupEventArgs e)
225
        {
226
            if (!Settings.Default.StartOnSystemStartup && e.Args.Contains("startup"))
227
            {
228
                Shutdown();
229
                return;
230
            }
231

    
232
            bool firstInstance;
233
            _singleInstanceMutex = new Mutex(false, "PITHOSMUTEX", out firstInstance);
234
            if (!firstInstance)
235
            {
236
                _singleInstanceMutex.Dispose();
237
                _singleInstanceMutex = null;
238
                Log.Warn("An instance of Pithos+ is already running. Terminating.");
239
                Shutdown();
240
                return;
241
            }
242

    
243
            //Delay during startup
244
            if (e.Args.Contains("startup"))
245
            {
246
                if (Settings.Default.StartupDelay>TimeSpan.Zero)
247
                    Thread.Sleep(Settings.Default.StartupDelay);
248
            }
249

    
250
            var splashScreen = new SplashScreen("images/pithos_logo-title-margin-splash-600-whitebg.png");
251
            splashScreen.Show(true);
252
            
253
            base.OnStartup(e);
254
        }
255

    
256
        protected override void OnExit(ExitEventArgs e)
257
        {
258
            try
259
            {
260
                if (_singleInstanceMutex!=null)
261
                    _singleInstanceMutex.Dispose();
262
                _singleInstanceMutex = null;
263
            }
264
            catch { }
265
            base.OnExit(e);
266
        }
267

    
268
        private void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
269
        {
270
            Log.Error("Unobserved Task Exception", e.Exception); 
271
            
272
            var messages = new List<UserMessage>();
273
            e.Exception.Handle(exc=>{
274
                messages.Add(new UserMessage
275
                {
276
                    Message = "Unexpected Exception",
277
                    Details = exc.ToString(),
278
                    Severity = Severity.Error
279
                });
280
                return true;
281
            });
282

    
283

    
284
            //Do not display any messages if this is a 304 code
285
            var ignoreExceptions = from exc in e.Exception.InnerExceptions.OfType<WebException>()
286
                                   where IsAllowedException(exc)
287
                                   select exc;
288

    
289
            if (ignoreExceptions.Any())
290
            {
291
                e.SetObserved();
292
                return;
293
            }
294

    
295

    
296
           /* var message = String.Format(@"{0}" + Environment.NewLine + "{1}" + Environment.NewLine + "{2}", 
297
                WPF.Properties.Resources.Unexpected_Error,
298
                WPF.Properties.Resources.We_Apologize, 
299
                WPF.Properties.Resources.Please_Submit_Error);
300
            ShowMessages("Oops!",message, messages);*/
301
            e.SetObserved();            
302
        }
303

    
304
        private bool IsAllowedException(Exception exc)
305
        {
306
            var we = exc as WebException;
307
            if (we==null)
308
            {
309
                return false;
310
            }
311
            var response = we.Response as HttpWebResponse;
312
            return (response != null && response.StatusCode == HttpStatusCode.NotModified);
313
        }
314

    
315
        private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
316
        {
317

    
318
            //Do not display any messages if this is a 304 code
319
            if (IsAllowedException(e.ExceptionObject as Exception))
320
            {
321
                return;
322
            }
323

    
324
            if (e.ExceptionObject is ReflectionTypeLoadException)
325
            {
326
                var les=(ReflectionTypeLoadException) e.ExceptionObject;
327
                Log.Error("Unhandled exception", les);
328
                foreach (var le in les.LoaderExceptions)
329
                {
330
                    Log.Error("Dll load error", le);    
331
                }
332
            }
333
            else
334
                Log.Error("Unhandled exception", (Exception)e.ExceptionObject);
335

    
336
            if (!e.IsTerminating)
337
                //Do not display a message unless the application is terminating
338
                return;
339

    
340
            var description = e.IsTerminating
341
                              ? WPF.Properties.Resources.Unexpected_Error_Terminating
342
                              : WPF.Properties.Resources.Unexpected_Error;
343
            var message = String.Format(@"{0}<LineBreak/>{1}<LineBreak/><LineBreak/>{2}",
344
                description,
345
                WPF.Properties.Resources.We_Apologize,
346
                WPF.Properties.Resources.Please_Submit_Error);
347

    
348
            var exc = ((Exception) e.ExceptionObject);
349
            var messages = new[]{
350
                                   new UserMessage
351
                                       {
352
                                           Message = exc.Message,
353
                                           Details = exc.ToString(),
354
                                           Severity = Severity.Error
355
                                       }
356
                               };
357

    
358

    
359
            ShowMessages("Oops!", message,messages);
360
        }
361

    
362

    
363

    
364
        void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
365
        {
366
            //Do not display any messages if this is a 304 code
367
            if (IsAllowedException(e.Exception))
368
            {
369
                return;
370
            }
371

    
372
            if (e.Exception is ReflectionTypeLoadException)
373
            {
374
                var les = (ReflectionTypeLoadException)e.Exception;
375
                Log.Error("Unhandled exception", les);
376
                foreach (var le in les.LoaderExceptions)
377
                {
378
                    Log.Error("Dll load error", le);
379
                }
380
            }
381
            else
382
                Log.Error("Unhandled Dispatcher exception", e.Exception);
383
            
384
           /* var messages = new[]{
385
                                   new UserMessage
386
                                       {
387
                                           Message = e.Exception.Message, 
388
                                           Details = e.Exception.ToString(),
389
                                           Severity = Severity.Error
390
                                       }
391
                               };
392
            ShowMessages(WPF.Properties.Resources.Error_Title, 
393
                WPF.Properties.Resources.Unexpected_Error,
394
                messages);*/
395
            e.Handled=true;
396
        }
397

    
398
        void ShowMessages(string title,string message,IEnumerable<UserMessage> messages )
399
        {
400
            var messageList = messages.ToList();
401
            LogMessages(messageList);
402
            Execute.OnUIThread(()=>{
403
                                       var messageView = new MessageView(messageList)
404
                                                        {
405
                                                            Title = title, 
406
                                                            Message = message
407
                                                        };
408
                                       messageView.ShowDialog();
409
            });
410
        }
411

    
412
        private void LogMessages(IEnumerable<UserMessage> messages)
413
        {
414
            var logMessage = CreateMessage(messages);
415

    
416
            Log.Error(logMessage);
417
        }
418

    
419
        private static string CreateMessage(IEnumerable<UserMessage> messages)
420
        {
421
            var messageBuilder = messages.Aggregate(new StringBuilder("Unexpected Error\r\n"),
422
                                                    (builder, message) =>
423
                                                        {
424
                                                            builder.AppendFormat("\r\n[{0}] {1}\r\n{2}\r\n", message.Severity,
425
                                                                                 message.Message, message.Details);
426
                                                            return builder;
427
                                                        });
428
            var logMessage = messageBuilder.ToString();
429
            return logMessage;
430
        }
431
    }
432

    
433
}
434

    
435
    enum RestartFlags
436
    {
437
        NONE = 0,
438
        RESTART_CYCLICAL = 1,
439
        RESTART_NOTIFY_SOLUTION = 2,
440
        RESTART_NOTIFY_FAULT = 4,
441
        RESTART_NO_CRASH = 8,
442
        RESTART_NO_HANG = 16,
443
        RESTART_NO_PATCH = 32,
444
        RESTART_NO_REBOOT = 64
445
    }