Esempio n. 1
0
        /// <summary>
        /// Updates the specified storage data.
        /// </summary>
        /// <param name="storageData">The storage data.</param>
        /// <param name="principal">The principal.</param>
        /// <param name="mode">The mode.</param>
        /// <returns>Returns the updated model instance.</returns>
        public TModel Update(TModel storageData, IPrincipal principal, TransactionMode mode)
        {
            if (storageData == null)
            {
                throw new ArgumentNullException(nameof(storageData), "Value cannot be null");
            }

            if (!storageData.Key.HasValue || storageData.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            var preUpdateArgs = new PrePersistenceEventArgs <TModel>(storageData, principal);

            this.Updating?.Invoke(this, preUpdateArgs);

            if (preUpdateArgs.Cancel)
            {
                traceSource.TraceEvent(TraceEventType.Warning, 0, $"Pre-event handler indicates abort update for : {storageData}");
                return(storageData);
            }

            using (var connection = Configuration.Provider.GetWriteConnection())
            {
                connection.Open();

                using (var tx = connection.BeginTransaction())
                {
                    try
                    {
                        this.traceSource.TraceEvent(TraceEventType.Verbose, 0, "UPDATE {0}", storageData);

                        storageData = this.Update(connection, storageData, principal);

                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        this.Updated?.Invoke(this, new PostPersistenceEventArgs <TModel>(storageData, principal)
                        {
                            Mode = mode
                        });

                        return(storageData);
                    }
                    catch (Exception e)
                    {
                        this.traceSource.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e);
                        tx?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Obsoletes the specified object
        /// </summary>
        public TData Obsolete(TData data, IPrincipal principal, TransactionMode mode)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            PrePersistenceEventArgs <TData> preArgs = new PrePersistenceEventArgs <TData>(data);

            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var connection = m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    this.ThrowIfExceeded();

                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            //connection.Connection.Open();

                            this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "OBSOLETE {0}", data);

                            data = this.Obsolete(connection, data, principal);

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                foreach (var itm in connection.CacheOnCommit)
                                {
                                    ApplicationContext.Current.GetService <IDataCachingService>()?.Remove(itm.Key.Value);
                                }
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new PostPersistenceEventArgs <TData>(data, principal)
                            {
                                Mode = mode
                            };

                            this.Obsoleted?.Invoke(this, args);

                            return(data);
                        }
                        catch (Exception e)
                        {
                            this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e);
                            tx?.Rollback();
                            throw new DataPersistenceException(e.Message, e);
                        }
                    finally
                    {
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref m_currentRequests);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Update the specified object
        /// </summary>
        /// <param name="storageData"></param>
        /// <param name="principal"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public TData Update(TData data, IPrincipal principal, TransactionMode mode)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            PrePersistenceEventArgs <TData> preArgs = new PrePersistenceEventArgs <TData>(data, principal);

            this.Updating?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort update for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    this.ThrowIfExceeded();

                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            //connection.Connection.Open();

                            this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "UPDATE {0}", data);

                            data           = this.Update(connection, data, principal);
                            data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                foreach (var itm in connection.CacheOnCommit)
                                {
                                    ApplicationContext.Current.GetService <IDataCachingService>()?.Add(itm);
                                }
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new PostPersistenceEventArgs <TData>(data, principal)
                            {
                                Mode = mode
                            };

                            this.Updated?.Invoke(this, args);

                            return(data);
                        }
                        catch (DbException e)
                        {
#if DEBUG
                            this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                            this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e.Message);
#endif
                            tx?.Rollback();

                            this.TranslateDbException(e);
                            throw;
                        }
                    catch (Exception e)
                    {
#if DEBUG
                        this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                        this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e.Message);
#endif
                        tx?.Rollback();

                        // if the exception is key not found, we want the caller to know
                        // so that a potential insert can take place
                        if (e is KeyNotFoundException)
                        {
                            throw new KeyNotFoundException(e.Message, e);
                        }

                        // if the exception is anything else, we want to throw a data persistence exception
                        throw new DataPersistenceException(e.Message, e);
                    }
                    finally
                    {
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref m_currentRequests);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Inserts the specified data
        /// </summary>
        public TData Insert(TData data, IPrincipal principal, TransactionMode mode)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            PrePersistenceEventArgs <TData> preArgs = new PrePersistenceEventArgs <TData>(data, principal);

            this.Inserting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort insert for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    this.ThrowIfExceeded();

                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            // Disable inserting duplicate classified objects
                            var existing = data.TryGetExisting(connection, principal, true);
                            if (existing != null)
                            {
                                if (m_configuration.AutoUpdateExisting)
                                {
                                    this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", data);
                                    data = this.Update(connection, data, principal);
                                }
                                else
                                {
                                    throw new DuplicateNameException(data.Key?.ToString());
                                }
                            }
                            else
                            {
                                this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "INSERT {0}", data);
                                data = this.Insert(connection, data, principal);
                            }
                            data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                foreach (var itm in connection.CacheOnCommit)
                                {
                                    ApplicationContext.Current.GetService <IDataCachingService>()?.Add(itm);
                                }
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new PostPersistenceEventArgs <TData>(data, principal)
                            {
                                Mode = mode
                            };

                            this.Inserted?.Invoke(this, args);

                            return(data);
                        }
                        catch (DbException e)
                        {
#if DEBUG
                            this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                            this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e.Message);
#endif
                            tx?.Rollback();

                            this.TranslateDbException(e);
                            throw;
                        }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0} -- {1}", e, this.ObjectToString(data));

                        tx?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                    finally
                    {
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref m_currentRequests);
                }
            }
        }
Esempio n. 5
0
        internal void DoPersistResultMessage(object state)
        {
            // Persist a message to the database
            IDbConnection             conn = m_configuration.CreateConnection();
            AdoMessagePersistanceArgs args = state as AdoMessagePersistanceArgs;

            try
            {
                var mpe = new PrePersistenceEventArgs <MessageInfo>(args.MessageInfo);
                this.Persisting?.Invoke(this, mpe);

                if (mpe.Cancel)
                {
                    Trace.TraceInformation("Message persistence event indicates cancel");
                    return;
                }

                conn.Open();

                // Create the database command
                IDbCommand cmd = conn.CreateCommand();

                try
                {
                    // Setup command
                    cmd.CommandType    = CommandType.StoredProcedure;
                    cmd.CommandText    = "reg_msg";
                    cmd.CommandTimeout = 30;

                    // Setup parameter for message id
                    IDataParameter msgIdParm = cmd.CreateParameter();
                    msgIdParm.DbType        = DbType.String;
                    msgIdParm.Value         = args.MessageInfo.Id;
                    msgIdParm.Direction     = ParameterDirection.Input;
                    msgIdParm.ParameterName = "msg_id_in";
                    cmd.Parameters.Add(msgIdParm);

                    // Setup parameter for the message body
                    IDataParameter msgBodyParm = cmd.CreateParameter();
                    msgBodyParm.DbType        = DbType.Binary;
                    msgBodyParm.Value         = args.MessageInfo.Body;
                    msgBodyParm.Direction     = ParameterDirection.Input;
                    msgBodyParm.ParameterName = "msg_body_in";
                    cmd.Parameters.Add(msgBodyParm);


                    // Setup parameter for msg_rsp_in
                    IDataParameter msgRspParm = cmd.CreateParameter();
                    msgRspParm.DbType        = DbType.String;
                    msgRspParm.Value         = String.IsNullOrEmpty(args.MessageInfo.Response) ? DBNull.Value : (object)args.MessageInfo.Response;
                    msgRspParm.Direction     = ParameterDirection.Input;
                    msgRspParm.ParameterName = "msg_rsp_in";
                    cmd.Parameters.Add(msgRspParm);

                    // Setup parameter for msg_rsp_in
                    IDataParameter msgSrcParm = cmd.CreateParameter();
                    msgSrcParm.DbType        = DbType.String;
                    msgSrcParm.Value         = args.MessageInfo.Source == null ? DBNull.Value : (object)args.MessageInfo.Source.ToString();
                    msgSrcParm.Direction     = ParameterDirection.Input;
                    msgSrcParm.ParameterName = "src_in";
                    cmd.Parameters.Add(msgSrcParm);

                    // Setup parameter for msg_rsp_in
                    IDataParameter msgDstParm = cmd.CreateParameter();
                    msgDstParm.DbType        = DbType.String;
                    msgDstParm.Value         = args.MessageInfo.Destination == null ? DBNull.Value : (object)args.MessageInfo.Destination.ToString();
                    msgDstParm.Direction     = ParameterDirection.Input;
                    msgDstParm.ParameterName = "dst_in";
                    cmd.Parameters.Add(msgDstParm);

                    // Execute the query without result
                    cmd.ExecuteNonQuery();

                    this.Persisted?.Invoke(this, new PostPersistenceEventArgs <MessageInfo>(args.MessageInfo));
                }
                finally
                {
                    cmd.Dispose();
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.ToString());
            }
            finally
            {
                conn.Close();
                conn.Dispose();
                args.MessageInfo = null;
                System.GC.Collect();
            }
        }
Esempio n. 6
0
        public DiagnosticReport Insert(DiagnosticReport storageData, IPrincipal principal, TransactionMode mode)
        {
            var persistenceArgs = new PrePersistenceEventArgs <DiagnosticReport>(storageData, principal);

            this.Inserting?.Invoke(this, persistenceArgs);
            if (persistenceArgs.Cancel)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Warning, 0, "Pre-persistence event cancelled the insertion");
                return(persistenceArgs.Data);
            }

            try
            {
                // Send
                var serviceClient = new JiraServiceClient(new RestClient(this.m_configuration));

                serviceClient.Authenticate(new Model.JiraAuthenticationRequest(this.m_configuration.UserName, this.m_configuration.Password));
                var issue = serviceClient.CreateIssue(new Model.JiraIssueRequest()
                {
                    Fields = new Model.JiraIssueFields()
                    {
                        Description = storageData.Note,
                        Summary     = String.Format("OpenIZ-DIAG: Issue from {0}", storageData?.Submitter?.Names?.FirstOrDefault()?.Component?.FirstOrDefault(n => n.ComponentTypeKey == NameComponentKeys.Given)?.Value),
                        IssueType   = new Model.JiraIdentifier("Bug"),
                        Priority    = new Model.JiraIdentifier("High"),
                        Project     = new Model.JiraKey(this.m_configuration.Project),
                        Labels      = new string[] { "OpenIZMobile" }
                    }
                });

                serviceClient.Client.Requesting += (o, e) =>
                {
                    e.AdditionalHeaders.Add("X-Atlassian-Token", "nocheck");
                };
                // Attachments
                List <MultipartAttachment> attachments = new List <MultipartAttachment>();

                foreach (var itm in storageData.Attachments)
                {
                    if (itm is DiagnosticBinaryAttachment)
                    {
                        var bin = itm as DiagnosticBinaryAttachment;
                        attachments.Add(new MultipartAttachment(bin.Content, "application/x-gzip", bin.FileDescription, true));
                    }
                    else
                    {
                        var txt = itm as DiagnosticTextAttachment;
                        attachments.Add(new MultipartAttachment(Encoding.UTF8.GetBytes(txt.Content), "text/plain", txt.FileName, true));
                    }
                }

                // Attach the application information
                using (var ms = new MemoryStream())
                {
                    XmlSerializer xsz = new XmlSerializer(typeof(DiagnosticApplicationInfo));
                    xsz.Serialize(ms, storageData.ApplicationInfo);
                    attachments.Add(new MultipartAttachment(ms.ToArray(), "text/xml", "appinfo.xml", true));
                }
                serviceClient.CreateAttachment(issue, attachments);
                storageData.CorrelationId = issue.Key;
                storageData.Key           = Guid.NewGuid();

                // Invoke
                this.Inserted?.Invoke(this, new PostPersistenceEventArgs <DiagnosticReport>(storageData, principal));

                return(storageData);
            }
            catch (Exception ex)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, ex.HResult, "Error sending to JIRA: {0}", ex);
                throw;
            }
        }
        /// <summary>
        /// Obsoletes the specified object
        /// </summary>
        public TData Obsolete(TData data, IPrincipal principal, TransactionMode mode)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            PrePersistenceEventArgs <TData> preArgs = new PrePersistenceEventArgs <TData>(data);

            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var connection = new ModelDataContext(m_configuration.ReadWriteConnectionString))
            {
                DbTransaction tx = null;
                try
                {
                    connection.Connection.Open();

                    tx = connection.Transaction = connection.Connection.BeginTransaction();

                    // Tracer
                    if (m_configuration.TraceSql)
                    {
                        connection.Log = new LinqTraceWriter();
                    }

                    this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "OBSOLETE {0}", data);

                    data = this.Obsolete(connection, data, principal);
                    connection.SubmitChanges();


                    if (mode == TransactionMode.Commit)
                    {
                        tx.Commit();
                    }
                    else
                    {
                        tx.Rollback();
                    }

                    var args = new PostPersistenceEventArgs <TData>(data, principal)
                    {
                        Mode = mode
                    };

                    this.Obsoleted?.Invoke(this, args);

                    return(data);
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e);
                    tx?.Rollback();
                    throw new DataPersistenceException(e.Message, e);
                }
                finally
                {
                }
            }
        }
        /// <summary>
        /// Inserts the specified data
        /// </summary>
        public TData Insert(TData data, IPrincipal principal, TransactionMode mode)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            PrePersistenceEventArgs <TData> preArgs = new PrePersistenceEventArgs <TData>(data, principal);

            this.Inserting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort insert for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = new ModelDataContext(m_configuration.ReadWriteConnectionString))
            {
                DbTransaction tx = null;
                try
                {
                    connection.Connection.Open();
                    connection.Transaction = tx = connection.Connection.BeginTransaction();

                    if (m_configuration.TraceSql)
                    {
                        connection.Log = new LinqTraceWriter();
                    }

                    // Disable inserting duplicate classified objects
                    var existing = data.TryGetExisting(connection, principal);
                    if (existing != null)
                    {
                        if (m_configuration.AutoUpdateExisting)
                        {
                            this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", data);
                            data = this.Update(connection, data, principal);
                        }
                        else
                        {
                            throw new DuplicateKeyException(data);
                        }
                    }
                    else
                    {
                        this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "INSERT {0}", data);
                        data = this.Insert(connection, data, principal);
                    }

                    connection.SubmitChanges();


                    if (mode == TransactionMode.Commit)
                    {
                        tx.Commit();
                    }
                    else
                    {
                        tx.Rollback();
                    }

                    var args = new PostPersistenceEventArgs <TData>(data, principal)
                    {
                        Mode = mode
                    };

                    this.Inserted?.Invoke(this, args);

                    return(data);
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e);
                    tx?.Rollback();
                    throw new DataPersistenceException(e.Message, e);
                }
                finally
                {
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Inserts the specified storage data.
        /// </summary>
        /// <param name="storageData">The storage data.</param>
        /// <param name="principal">The principal.</param>
        /// <param name="mode">The mode.</param>
        /// <returns>Returns the inserted model instance.</returns>
        public TModel Insert(TModel storageData, IPrincipal principal, TransactionMode mode)
        {
            if (storageData == null)
            {
                throw new ArgumentNullException(nameof(storageData), "Value cannot be null");
            }

            var preInsertArgs = new PrePersistenceEventArgs <TModel>(storageData, principal);

            this.Inserting?.Invoke(this, preInsertArgs);

            if (preInsertArgs.Cancel)
            {
                traceSource.TraceEvent(TraceEventType.Warning, 0, $"Pre-event handler indicates abort insert for : {storageData}");
                return(storageData);
            }

            using (var connection = Configuration.Provider.GetWriteConnection())
            {
                connection.Open();

                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        var existing = this.Get(connection, storageData.Key.Value, principal, false);

                        if (existing != null)
                        {
                            if (Configuration.AutoUpdateExisting)
                            {
                                this.traceSource.TraceEvent(TraceEventType.Warning, 0, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", storageData);
                                storageData = this.Update(connection, storageData, principal);
                            }
                            else
                            {
                                throw new DuplicateNameException(storageData.Key?.ToString());
                            }
                        }
                        else
                        {
                            this.traceSource.TraceEvent(TraceEventType.Verbose, 0, "INSERT {0}", storageData);
                            storageData = this.Insert(connection, storageData, principal);
                        }

                        if (mode == TransactionMode.Commit)
                        {
                            transaction.Commit();
                        }
                        else
                        {
                            transaction.Rollback();
                        }

                        this.Inserted?.Invoke(this, new PostPersistenceEventArgs <TModel>(storageData, principal)
                        {
                            Mode = mode
                        });

                        return(storageData);
                    }
                    catch (Exception e)
                    {
                        this.traceSource.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e);
                        transaction?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                }
            }
        }
Esempio n. 10
0
        public DiagnosticReport Insert(DiagnosticReport storageData, IPrincipal principal, TransactionMode mode)
        {
            var persistenceArgs = new PrePersistenceEventArgs <DiagnosticReport>(storageData, principal);

            this.Inserting?.Invoke(this, persistenceArgs);
            if (persistenceArgs.Cancel)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Warning, 0, "Pre-persistence event cancelled the insertion");
                return(persistenceArgs.Data);
            }

            try
            {
                var issueId = Guid.NewGuid().ToString().Substring(0, 4);
                // Setup message

                MailMessage bugMessage = new MailMessage();
                bugMessage.From = new MailAddress(this.m_configuration.Smtp.From, $"OpenIZ Bug on behalf of {storageData?.Submitter?.Names?.FirstOrDefault()?.Component?.FirstOrDefault(n => n.ComponentTypeKey == NameComponentKeys.Given)?.Value}");
                foreach (var itm in this.m_configuration.Recipients)
                {
                    bugMessage.To.Add(itm);
                }
                bugMessage.Subject = $"ISSUE #{issueId}";
                bugMessage.Body    = $"{storageData.Note} - Username - {storageData.LoadProperty<SecurityUser>("CreatedBy")?.UserName ?? storageData?.Submitter?.LoadProperty<SecurityUser>("SecurityUser")?.UserName}";


                // Add attachments
                foreach (var itm in storageData.Attachments)
                {
                    if (itm is DiagnosticBinaryAttachment)
                    {
                        var bin = itm as DiagnosticBinaryAttachment;
                        bugMessage.Attachments.Add(new Attachment(new MemoryStream(bin.Content), itm.FileDescription ?? itm.FileName, "application/x-gzip"));
                    }
                    else
                    {
                        var txt = itm as DiagnosticTextAttachment;
                        bugMessage.Attachments.Add(new Attachment(new MemoryStream(Encoding.UTF8.GetBytes(txt.Content)), itm.FileDescription ?? itm.FileName, "text/plain"));
                    }
                }

                // Attach the application information
                using (var ms = new MemoryStream())
                {
                    XmlSerializer xsz = new XmlSerializer(typeof(DiagnosticApplicationInfo));
                    xsz.Serialize(ms, storageData.ApplicationInfo);
                    bugMessage.Attachments.Add(new Attachment(new MemoryStream(ms.ToArray()), "appinfo.xml", "text/xml"));
                }

                SmtpClient smtpClient = new SmtpClient(this.m_configuration.Smtp.Server.Host, this.m_configuration.Smtp.Server.Port);
                smtpClient.UseDefaultCredentials = String.IsNullOrEmpty(this.m_configuration.Smtp.Username);
                smtpClient.EnableSsl             = this.m_configuration.Smtp.Ssl;
                if (!(smtpClient.UseDefaultCredentials))
                {
                    smtpClient.Credentials = new NetworkCredential(this.m_configuration.Smtp.Username, this.m_configuration.Smtp.Password);
                }
                smtpClient.SendCompleted += (o, e) =>
                {
                    this.m_traceSource.TraceInformation("Successfully sent message to {0}", bugMessage.To);
                    if (e.Error != null)
                    {
                        this.m_traceSource.TraceEvent(TraceEventType.Error, 0, e.Error.ToString());
                    }
                    (o as IDisposable).Dispose();
                };
                this.m_traceSource.TraceInformation("Sending bug email message to {0}", bugMessage.To);
                smtpClient.Send(bugMessage);

                // Invoke
                this.Inserted?.Invoke(this, new PostPersistenceEventArgs <DiagnosticReport>(storageData, principal));
                storageData.CorrelationId = issueId;
                storageData.Key           = Guid.NewGuid();
                return(storageData);
            }
            catch (Exception ex)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, ex.HResult, "Error sending to JIRA: {0}", ex);
                throw;
            }
        }