#region
/* -----------------------------------------------------------------------
*
*
* Copyright 2011-2012 GRNET S.A. All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and
* documentation are those of the authors and should not be
* interpreted as representing official policies, either expressed
* or implied, of GRNET S.A.
*
* -----------------------------------------------------------------------
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Caliburn.Micro;
using Pithos.Client.WPF.Configuration;
using Pithos.Client.WPF.Properties;
using Pithos.Interfaces;
using log4net.Appender;
using log4net.Core;
using log4net.Repository.Hierarchy;
using System.Runtime.InteropServices;
namespace Pithos.Client.WPF
{
///
/// Interaction logic for App.xaml
///
public partial class App : Application
{
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
///DLL Import to add restart manager support
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern uint RegisterApplicationRestart(string pwzCommandLine, RestartFlags dwFlags);
public App()
{
//var instanceMutex=new Mutex()
InitializeLogging();
///Register Application in the Restartmanager service
RegisterApplicationRestart("Upgrade", RestartFlags.NONE);
DispatcherUnhandledException += OnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedException;
//Fix incorrect proxy settings by switching to default proxy, if the proxy server settings is empty
if (Settings.Default.UseManualProxy && String.IsNullOrWhiteSpace(Settings.Default.ProxyServer))
{
Settings.Default.UseManualProxy = false;
Settings.Default.UseDefaultProxy = true;
}
if (Settings.Default.IgnoreCertificateErrors)
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
InitializeComponent();
}
/*
private void OnUpdateDetected(object sender, UpdateDetectedEventArgs e)
{
Log.InfoFormat("Update Detected {0}",e.LatestVersion.Version);
}
*/
private static void InitializeLogging()
{
log4net.Config.XmlConfigurator.Configure();
try
{
var pithosDataPath = PithosSettings.PithosDataPath;
if (!Directory.Exists(pithosDataPath))
Directory.CreateDirectory(pithosDataPath);
var loggerRepository = (Hierarchy)log4net.LogManager.GetRepository();
var appenders = loggerRepository.GetAppenders();
var lossyAppender = appenders.OfType()
.FirstOrDefault(appender => appender.Name == "LossyFileAppender");
if (lossyAppender!=null)
{
var dumpAppender = lossyAppender.Appenders.OfType().First();
dumpAppender.File = Path.Combine(pithosDataPath, "errorlog.xml");
dumpAppender.ActivateOptions();
}
var debugAppender =appenders.OfType()
.FirstOrDefault(a => a.Name == "DebugFileAppender");
if (debugAppender != null)
{
debugAppender.File = Path.Combine(pithosDataPath, "debuglog.xml");
if (!Settings.Default.DebugLoggingEnabled)
debugAppender.Threshold = Level.Off;
debugAppender.ActivateOptions();
}
}
catch (Exception exc)
{
Log.Error("Dumpl appender initialization failed",exc);
}
}
private Mutex _singleInstanceMutex;
protected override void OnStartup(StartupEventArgs e)
{
if (!Settings.Default.StartOnSystemStartup && e.Args.Contains("startup"))
{
Shutdown();
return;
}
bool firstInstance;
_singleInstanceMutex = new Mutex(false, "PITHOSMUTEX", out firstInstance);
if (!firstInstance)
{
_singleInstanceMutex.Dispose();
_singleInstanceMutex = null;
Shutdown();
return;
}
//Delay during startup
if (e.Args.Contains("startup"))
{
if (Settings.Default.StartupDelay>TimeSpan.Zero)
Thread.Sleep(Settings.Default.StartupDelay);
}
var splashScreen = new SplashScreen("images/pithos_logo-title-margin-splash-600-whitebg.png");
splashScreen.Show(true);
base.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
try
{
if (_singleInstanceMutex!=null)
_singleInstanceMutex.Dispose();
_singleInstanceMutex = null;
}
catch { }
base.OnExit(e);
}
private void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
{
Log.Error("Unobserved Task Exception", e.Exception);
var messages = new List();
e.Exception.Handle(exc=>{
messages.Add(new UserMessage
{
Message = "Unexpected Exception",
Details = exc.ToString(),
Severity = Severity.Error
});
return true;
});
//Do not display any messages if this is a 304 code
var ignoreExceptions = from exc in e.Exception.InnerExceptions.OfType()
where IsAllowedException(exc)
select exc;
if (ignoreExceptions.Any())
{
e.SetObserved();
return;
}
/* var message = String.Format(@"{0}" + Environment.NewLine + "{1}" + Environment.NewLine + "{2}",
WPF.Properties.Resources.Unexpected_Error,
WPF.Properties.Resources.We_Apologize,
WPF.Properties.Resources.Please_Submit_Error);
ShowMessages("Oops!",message, messages);*/
e.SetObserved();
}
private bool IsAllowedException(Exception exc)
{
var we = exc as WebException;
if (we==null)
{
return false;
}
var response = we.Response as HttpWebResponse;
return (response != null && response.StatusCode == HttpStatusCode.NotModified);
}
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//Do not display any messages if this is a 304 code
if (IsAllowedException(e.ExceptionObject as Exception))
{
return;
}
Log.Error("Unhandled exception", (Exception)e.ExceptionObject);
if (!e.IsTerminating)
//Do not display a message unless the application is terminating
return;
var description = e.IsTerminating
? WPF.Properties.Resources.Unexpected_Error_Terminating
: WPF.Properties.Resources.Unexpected_Error;
var message = String.Format(@"{0}{1}{2}",
description,
WPF.Properties.Resources.We_Apologize,
WPF.Properties.Resources.Please_Submit_Error);
var exc = ((Exception) e.ExceptionObject);
var messages = new[]{
new UserMessage
{
Message = exc.Message,
Details = exc.ToString(),
Severity = Severity.Error
}
};
ShowMessages("Oops!", message,messages);
}
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//Do not display any messages if this is a 304 code
if (IsAllowedException(e.Exception))
{
return;
}
Log.Error("Unhandled Dispatcher exception", e.Exception);
/* var messages = new[]{
new UserMessage
{
Message = e.Exception.Message,
Details = e.Exception.ToString(),
Severity = Severity.Error
}
};
ShowMessages(WPF.Properties.Resources.Error_Title,
WPF.Properties.Resources.Unexpected_Error,
messages);*/
e.Handled=true;
}
void ShowMessages(string title,string message,IEnumerable messages )
{
var messageList = messages.ToList();
LogMessages(messageList);
Execute.OnUIThread(()=>{
var messageView = new MessageView(messageList)
{
Title = title,
Message = message
};
messageView.ShowDialog();
});
}
private void LogMessages(IEnumerable messages)
{
var logMessage = CreateMessage(messages);
Log.Error(logMessage);
}
private static string CreateMessage(IEnumerable messages)
{
var messageBuilder = messages.Aggregate(new StringBuilder("Unexpected Error\r\n"),
(builder, message) =>
{
builder.AppendFormat("\r\n[{0}] {1}\r\n{2}\r\n", message.Severity,
message.Message, message.Details);
return builder;
});
var logMessage = messageBuilder.ToString();
return logMessage;
}
}
}
enum RestartFlags
{
NONE = 0,
RESTART_CYCLICAL = 1,
RESTART_NOTIFY_SOLUTION = 2,
RESTART_NOTIFY_FAULT = 4,
RESTART_NO_CRASH = 8,
RESTART_NO_HANG = 16,
RESTART_NO_PATCH = 32,
RESTART_NO_REBOOT = 64
}