Get-Message.ps1

function Get-Message {
<#
.SYNOPSIS
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory.
 
.DESCRIPTION
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory.
 
.OUTPUTS
This Cmdlet returns the Messaging Factory message object. In case of failure is trying '-Retry' times, otherwise returns $null.
 
.INPUTS
See PARAMETER section for a description of input parameters.
 
.EXAMPLE
Retrieves a message from ServiceBus. The message is immediately removed from the facility after receipt.
 
PS > Get-Message;
CorrelationId :
SessionId :
ReplyToSessionId :
DeliveryCount : 1
ExpiresAtUtc : 31.12.9999 23:59:59
LockedUntilUtc :
LockToken :
MessageId : e6dc938213264de790e53ace7949f610
ContentType :
Label :
Properties : {}
ReplyTo :
EnqueuedTimeUtc : 24.12.2015 21:00:00
ScheduledEnqueueTimeUtc : 01.01.0001 00:00:00
SequenceNumber : 1
EnqueuedSequenceNumber : 0
Size : 6
State : Active
TimeToLive : 10675199.02:48:05.4775807
To :
IsBodyConsumed : False
 
.EXAMPLE
Retrieves a message from ServiceBus and save the message contents (body) to a variable. The message is immediately removed from the facility after receipt.
 
PS > $message = Get-Message -BodyAsProperty;
PS > write-host $message.Properties['Body']
I am a message body from ServiceBus with an arbitrary content.
 
.EXAMPLE
Similar to the previous example, but message is explicitly removed from the facility (in case the module default configuration is set to 'PeekLock').
 
PS > $message = Get-Message -ReceiveAndDelete -BodyAsProperty;
PS > write-host $message.Properties['Body']
I am a message body from ServiceBus with an arbitrary content.
 
.EXAMPLE
This example receives a message from the service bus. The message will be kept in the queue until it is explicity marked as 'Complete'
 
PS > $message = Get-Message -Receivemode 'PeekLock';
PS > # do something with the message before you acknowledge receipt
PS > $message.Complete();
 
.EXAMPLE
This example retrieves a message from the ServiceBus facility 'Topics-Newsletter'. The facility will be created if it does not exist.
 
PS > $message = Get-Message -Facility 'Topic-Newsletter' -EnsureFacility;
 
.EXAMPLE
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory against server defined within module configuration xml file.
 
PS > $receiver = Get-MessageReceiver -Facility 'MyQueue1';
PS > $message = Get-Message -Client $receiver;
 
#>

[CmdletBinding(
    HelpURI = 'http://dfch.biz/biz/dfch/PS/AzureServiceBus/Client/'
)]
[OutputType([Microsoft.ServiceBus.Messaging.BrokeredMessage])]
Param 
(
    # [Optional] The WaitTimeOutSec such as '3' Seconds for receiving a message before it times out. If you do not specify this
    # value it is taken from the default value = 3 sec.
    [Parameter(Mandatory = $false, Position = 0)]
    [ValidateNotNullorEmpty()]
    [int] $WaitTimeoutSec = [int]::MaxValue
    , 
    # [Optional] The Receivemode such as 'PeekLock'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 1)]
    [ValidateSet('PeekLock', 'ReceiveAndDelete')]
    [string] $Receivemode = 'ReceiveAndDelete'
    ,
    # [Optional] ReceiveAndDelete same as Receivemode 'ReceiveAndDelete'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 2)]
    [switch] $ReceiveAndDelete = $false
    ,
    # [Optional] ReceiveAndComplete same as Receivemode 'PeekLock' and $Message.Complete(). If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 3)]
    [switch] $ReceiveAndComplete = $false
    ,
    # [Optional] ReceiveAndAbandon same as Receivemode 'PeekLock' and $Message.Abandon(). If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 4)]
    [switch] $ReceiveAndAbandon = $false
    ,
    # [Optional] BodyAsProperty writes the Message Body to Property 'Body'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 5)]
    [switch] $BodyAsProperty = $false
    ,
    # [Optional] The Facility such as 'MyQueue'. If you do not specify this
    # value it is taken from the module configuration file.
    [Parameter(Mandatory = $false, Position = 6)]
    [ValidateNotNullorEmpty()]
    [alias("queue")]
    [alias("subscription")]
    [alias("QueueName")]
    [string] $Facility = (Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).ReceiveFacility
    , 
    # [Optional] Specifies if the facility will be created if it does not exist
    [Parameter(Mandatory = $false, Position = 7)]
    [alias("ensure")]
    [alias("broadcast")]
    [alias("checkfacility")]
    [switch]$EnsureFacility = $false
    ,
    # [Optional] Messaging Client (instance of the MessagingFactory)
    [Parameter(Mandatory = $false, Position = 8)]
    [alias("MessageClient")]
    $Client
    ,
    # [Optional] Skip retrying
    [Parameter(Mandatory = $false, Position = 9)]
    [switch]$NoRetry = $false
    ,
    # [Optional] The Retry. If you do not specify this
    # value it is taken from the module configuration file.
    [Parameter(Mandatory=$false, Position = 10)]
    [int]$Retry = (Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).CommandRetry
    ,
    # [Optional] The RetryInterval. If you do not specify this
    # value it is taken from the module configuration file.
    [Parameter(Mandatory=$false, Position = 11)]
    [int]$RetryInterval = (Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).CommandRetryInterval
)

BEGIN 
{
    $datBegin = [datetime]::Now;
    [string] $fn = $MyInvocation.MyCommand.Name;
    Log-Debug $fn ("CALL. Facility '{0}'" -f $Facility ) -fac 1;
    
    # Factory validation
    if((Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).Factory -isnot [Microsoft.ServiceBus.Messaging.MessagingFactory]) {
        $msg = "Factory: Factory validation FAILED. Connect to the server before using the Cmdlet.";
        $e = New-CustomErrorRecord -m $msg -cat InvalidData -o (Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).Factory;
        $PSCmdlet.ThrowTerminatingError($e);
    } # if

}
# BEGIN

PROCESS 
{

    [boolean] $fReturn = $false;

    # Get all parameters
    $Params = @{};
    $ParamsList = (Get-Command -Name $MyInvocation.InvocationName).Parameters;
    foreach ($key in $ParamsList.keys)
    {
        $var = Get-Variable -Name $key -ErrorAction SilentlyContinue;
        if($var)
        {
            if ( @('Retry', 'RetryInterval', 'NoRetry') -notcontains $($var.name) -and $var.value -ne $null -and $($var.value) -ne '' )  
            {
                $Params.Add($($var.name), $var.value);
            }
        }
    }
    #Log-Debug $fn ("Operation [{0}] arguments: {1}" -f ($fn -replace 'Worker', ''), ($Params | Out-String));
    
    # Retry handling
    for($c = 1; $c -le ($Retry+1); $c++)
    {
        try
        {
            $OutputParameter = Get-MessageWorker @Params;
            break;
        }
        catch
        {
            # Throw last execption
            if ( $NoRetry -or 
                $c -gt $Retry -or 
                $_.Exception.Message -match 'Connect to the message factory before using the Cmdlet.' -or
                $_.Exception.Message -match 'The message body cannot be read multiple times.'
                )
            {
                if ($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) 
                {
                    throw;
                }
                else
                {
                    break;
                }    
            }
            Log-Debug $fn ("[{0}/{1}] Retrying operation [{2}]" -f $c, $Retry, ($fn -replace 'Worker', ''));
            Start-Sleep -Seconds $RetryInterval;
            $RetryInterval *= 2;
            continue;
        }
    }
    return $OutputParameter;
    $fReturn = $true;

}
# PROCESS

END 
{
    $datEnd = [datetime]::Now;
    Log-Debug -fn $fn -msg ("RET. fReturn: [{0}]. Execution time: [{1}]ms. Started: [{2}]." -f $fReturn, ($datEnd - $datBegin).TotalMilliseconds, $datBegin.ToString('yyyy-MM-dd HH:mm:ss.fffzzz')) -fac 2;
}
# END

} # function
if($MyInvocation.ScriptName) { Export-ModuleMember -Function Get-Message; } 

function Get-MessageWorker {
<#
.SYNOPSIS
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory.
 
.DESCRIPTION
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory.
 
.OUTPUTS
This Cmdlet returns the MessageId from the Messaging Factory message object. On failure it returns $null.
 
.INPUTS
See PARAMETER section for a description of input parameters.
 
.EXAMPLE
$message = Get-MessageWorker;
 
Receives a message from a receiver client, which is based on the Service Bus Messaging Factory.
#>

[CmdletBinding(
    HelpURI = 'http://dfch.biz/biz/dfch/PS/AzureServiceBus/Client/'
)]
[OutputType([Microsoft.ServiceBus.Messaging.BrokeredMessage])]
Param 
(
    # [Optional] The WaitTimeOutSec such as '3' Seconds for receiving a message before it times out. If you do not specify this
    # value it is taken from the default value = 3 sec.
    [Parameter(Mandatory = $false, Position = 0)]
    [ValidateNotNullorEmpty()]
    [int] $WaitTimeoutSec = [int]::MaxValue
    , 
    # [Optional] The Receivemode such as 'PeekLock'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 1)]
    [ValidateSet('PeekLock', 'ReceiveAndDelete')]
    [string] $Receivemode = 'ReceiveAndDelete'
    ,
    # [Optional] ReceiveAndDelete same as Receivemode 'ReceiveAndDelete'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 2)]
    [switch] $ReceiveAndDelete = $false
    ,
    # [Optional] ReceiveAndComplete same as Receivemode 'PeekLock' and $Message.Complete(). If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 3)]
    [switch] $ReceiveAndComplete = $false
    ,
    # [Optional] ReceiveAndAbandon same as Receivemode 'PeekLock' and $Message.Abandon(). If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 4)]
    [switch] $ReceiveAndAbandon = $false
    ,
    # [Optional] BodyAsProperty writes the Message Body to Property 'Body'. If you do not specify this
    # value it is taken from the default parameter.
    [Parameter(Mandatory = $false, Position = 5)]
    [switch] $BodyAsProperty = $false
    ,
    # [Optional] The Facility such as 'MyQueue'. If you do not specify this
    # value it is taken from the module configuration file.
    [Parameter(Mandatory = $false, Position = 6)]
    [ValidateNotNullorEmpty()]
    [alias("queue")]
    [alias("subscription")]
    [alias("QueueName")]
    [string] $Facility = (Get-Variable -Name $MyInvocation.MyCommand.Module.PrivateData.MODULEVAR -ValueOnly).ReceiveFacility
    , 
    # [Optional] Checks if facility existing
    [Parameter(Mandatory = $false, Position = 7)]
    [alias("ensure")]
    [alias("broadcast")]
    [alias("CreateIfNotExist")]
    [switch] $EnsureFacility = $false
    ,
    # [Optional] Messaging Client (instance of the MessagingFactory)
    [Parameter(Mandatory = $false, Position = 8)]
    [alias("MessageClient")]
    $Client
)

BEGIN 
{
    $datBegin = [datetime]::Now;
    [string] $fn = $MyInvocation.MyCommand.Name;
    Log-Debug $fn ("CALL. Facility '{0}'" -f $Facility ) -fac 1;

}
# BEGIN

PROCESS 
{

[boolean] $fReturn = $false;

try 
{
    # Parameter validation
    if ( $ReceiveAndDelete ) 
    {
        $Receivemode = 'ReceiveAndDelete';
    }
    
    # Check facility
    if ( $EnsureFacility ) 
    {
        $Path = ($Facility -Split "\\Subscriptions\\")[0];
        $SubscriptionName = "RECV-{0}" -f (get-wmiobject Win32_ComputerSystemProduct  | Select-Object -ExpandProperty UUID).toString();
        if ( $Facility -match "\\Subscriptions\\" )
        {
            $SubscriptionName = ($Facility -Split "\\Subscriptions\\")[1];
        }
        try 
        {
            $FacilitiyExists = New-MessageFacility -Path $Path -Name $SubscriptionName;
            $Facility = '{0}\Subscriptions\{1}' -f $Path, $SubscriptionName;
        } 
        catch 
        {
            $msg = $_.Exception.Message;
            Log-Error -msg $msg;
            $e = New-CustomErrorRecord -m $msg -cat InvalidData -o $Facility;
            $PSCmdlet.ThrowTerminatingError($e);
        }
    }
    
    # Create Client
    if ( !$PSBoundParameters.ContainsKey('Client') ) 
    {
        try 
        {
            $Client = Get-MessageReceiver -Facility $Facility -Receivemode $Receivemode;
        } 
        catch 
        {
            $msg = $_.Exception.Message;
            $e = New-CustomErrorRecord -m $msg -cat InvalidData -o $Client;
            Log-Error $fn -msg $msg;
            $PSCmdlet.ThrowTerminatingError($e);
        }
    }
    
    # Get Message
    try 
    {
        # DFTODO - is this really an AMQP message when we are using the BrokeredMessage class?, see #5
        [Microsoft.ServiceBus.Messaging.BrokeredMessage] $BrokeredMessage = $Client.Receive((New-TimeSpan -Seconds $WaitTimeoutSec));
    } catch {
        $msg = $_.Exception.Message;
        $e = New-CustomErrorRecord -m $msg -cat InvalidData -o $BrokeredMessage;
        Log-Error $fn -msg $msg;
        $PSCmdlet.ThrowTerminatingError($e);
    }
    
    # Process Message
    if ( $BrokeredMessage -ne $null ) 
    {
        if ( $ReceiveAndAbandon -and $Receivemode -ne 'ReceiveAndDelete' ) 
        {
            $BrokeredMessage.Abandon();
        }
        
        if ( $ReceiveAndComplete -and $Receivemode -ne 'ReceiveAndDelete' ) 
        {
            $BrokeredMessage.Complete();
        }
        
        if ( $BodyAsProperty ) 
        {
            $PropertyName = 'Body';
            $PropertyValue = Get-MessageBody -Message $BrokeredMessage;
            if ( $BrokeredMessage.Properties.ContainsKey($PropertyName) -and $BrokeredMessage.Properties[$PropertyName].toString() -ne $PropertyValue.toString() ) 
            {
                [int] $PropertyCount = 1;
                $PropertyName = ("Body{0}" -f $PropertyCount);
                while( $BrokeredMessage.Properties.ContainsKey($PropertyName) )
                {
                    $PropertyCount += 1;
                    $PropertyName = ("Body{0}" -f $PropertyCount);
                }
            }
            $BrokeredMessage.Properties[$PropertyName] = $PropertyValue;
        }
    }
    
    $OutputParameter = $BrokeredMessage;
    $fReturn = $true;
}
catch 
{
    if($gotoSuccess -eq $_.Exception.Message) 
    {
            $fReturn = $true;
    } 
    else 
    {
        [string] $ErrorText = "catch [$($_.FullyQualifiedErrorId)]";
        $ErrorText += (($_ | fl * -Force) | Out-String);
        $ErrorText += (($_.Exception | fl * -Force) | Out-String);
        $ErrorText += (Get-PSCallStack | Out-String);
        
        if($_.Exception -is [System.Net.WebException]) 
        {
            Log-Critical $fn "Login to Uri '$Uri' with Username '$Username' FAILED [$_].";
            Log-Debug $fn $ErrorText -fac 3;
        }
        else 
        {
            Log-Error $fn $ErrorText -fac 3;
            if($gotoError -eq $_.Exception.Message) 
            {
                Log-Error $fn $e.Exception.Message;
                $PSCmdlet.ThrowTerminatingError($e);
            } 
            elseif($gotoFailure -ne $_.Exception.Message) 
            { 
                Write-Verbose ("$fn`n$ErrorText"); 
            } 
            else 
            {
                # N/A
            }
        }
        $fReturn = $false;
        $OutputParameter = $null;
    }
}
finally 
{
    # Clean up
    # N/A
}
return $OutputParameter;

}
# PROCESS

END 
{
    $datEnd = [datetime]::Now;
    Log-Debug -fn $fn -msg ("RET. fReturn: [{0}]. Execution time: [{1}]ms. Started: [{2}]." -f $fReturn, ($datEnd - $datBegin).TotalMilliseconds, $datBegin.ToString('yyyy-MM-dd HH:mm:ss.fffzzz')) -fac 2;
}
# END

} # function

#
# Copyright 2014-2015 d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# SIG # Begin signature block
# MIIXDwYJKoZIhvcNAQcCoIIXADCCFvwCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU4JbjYuQxuwIHDgWCo7jZIyje
# VvCgghHCMIIEFDCCAvygAwIBAgILBAAAAAABL07hUtcwDQYJKoZIhvcNAQEFBQAw
# VzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNV
# BAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0
# MTMxMDAwMDBaFw0yODAxMjgxMjAwMDBaMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQK
# ExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9HbG9iYWxTaWduIFRpbWVzdGFt
# cGluZyBDQSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlO9l
# +LVXn6BTDTQG6wkft0cYasvwW+T/J6U00feJGr+esc0SQW5m1IGghYtkWkYvmaCN
# d7HivFzdItdqZ9C76Mp03otPDbBS5ZBb60cO8eefnAuQZT4XljBFcm05oRc2yrmg
# jBtPCBn2gTGtYRakYua0QJ7D/PuV9vu1LpWBmODvxevYAll4d/eq41JrUJEpxfz3
# zZNl0mBhIvIG+zLdFlH6Dv2KMPAXCae78wSuq5DnbN96qfTvxGInX2+ZbTh0qhGL
# 2t/HFEzphbLswn1KJo/nVrqm4M+SU4B09APsaLJgvIQgAIMboe60dAXBKY5i0Eex
# +vBTzBj5Ljv5cH60JQIDAQABo4HlMIHiMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB
# Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTBHBgNV
# HSAEQDA+MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFs
# c2lnbi5jb20vcmVwb3NpdG9yeS8wMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny
# bC5nbG9iYWxzaWduLm5ldC9yb290LmNybDAfBgNVHSMEGDAWgBRge2YaRQ2XyolQ
# L30EzTSo//z9SzANBgkqhkiG9w0BAQUFAAOCAQEATl5WkB5GtNlJMfO7FzkoG8IW
# 3f1B3AkFBJtvsqKa1pkuQJkAVbXqP6UgdtOGNNQXzFU6x4Lu76i6vNgGnxVQ380W
# e1I6AtcZGv2v8Hhc4EvFGN86JB7arLipWAQCBzDbsBJe/jG+8ARI9PBw+DpeVoPP
# PfsNvPTF7ZedudTbpSeE4zibi6c1hkQgpDttpGoLoYP9KOva7yj2zIhd+wo7AKvg
# IeviLzVsD440RZfroveZMzV+y5qKu0VN5z+fwtmK+mWybsd+Zf/okuEsMaL3sCc2
# SI8mbzvuTXYfecPlf5Y1vC0OzAGwjn//UYCAp5LUs0RGZIyHTxZjBzFLY7Df8zCC
# BCkwggMRoAMCAQICCwQAAAAAATGJxjfoMA0GCSqGSIb3DQEBCwUAMEwxIDAeBgNV
# BAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWdu
# MRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTExMDgwMjEwMDAwMFoXDTE5MDgwMjEw
# MDAwMFowWjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
# MDAuBgNVBAMTJ0dsb2JhbFNpZ24gQ29kZVNpZ25pbmcgQ0EgLSBTSEEyNTYgLSBH
# MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKPv0Z8p6djTgnY8YqDS
# SdYWHvHP8NC6SEMDLacd8gE0SaQQ6WIT9BP0FoO11VdCSIYrlViH6igEdMtyEQ9h
# JuH6HGEVxyibTQuCDyYrkDqW7aTQaymc9WGI5qRXb+70cNCNF97mZnZfdB5eDFM4
# XZD03zAtGxPReZhUGks4BPQHxCMD05LL94BdqpxWBkQtQUxItC3sNZKaxpXX9c6Q
# MeJ2s2G48XVXQqw7zivIkEnotybPuwyJy9DDo2qhydXjnFMrVyb+Vpp2/WFGomDs
# KUZH8s3ggmLGBFrn7U5AXEgGfZ1f53TJnoRlDVve3NMkHLQUEeurv8QfpLqZ0BdY
# Nc0CAwEAAaOB/TCB+jAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB
# ADAdBgNVHQ4EFgQUGUq4WuRNMaUU5V7sL6Mc+oCMMmswRwYDVR0gBEAwPjA8BgRV
# HSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3Jl
# cG9zaXRvcnkvMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2ln
# bi5uZXQvcm9vdC1yMy5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgw
# FoAUj/BLf6guRSSuTVD6Y5qL3uLdG7wwDQYJKoZIhvcNAQELBQADggEBAHmwaTTi
# BYf2/tRgLC+GeTQD4LEHkwyEXPnk3GzPbrXsCly6C9BoMS4/ZL0Pgmtmd4F/ximl
# F9jwiU2DJBH2bv6d4UgKKKDieySApOzCmgDXsG1szYjVFXjPE/mIpXNNwTYr3MvO
# 23580ovvL72zT006rbtibiiTxAzL2ebK4BEClAOwvT+UKFaQHlPCJ9XJPM0aYx6C
# WRW2QMqngarDVa8z0bV16AnqRwhIIvtdG/Mseml+xddaXlYzPK1X6JMlQsPSXnE7
# ShxU7alVrCgFx8RsXdw8k/ZpPIJRzhoVPV4Bc/9Aouq0rtOO+u5dbEfHQfXUVlfy
# GDcy1tTMS/Zx4HYwggSfMIIDh6ADAgECAhIRIQaggdM/2HrlgkzBa1IJTgMwDQYJ
# KoZIhvcNAQEFBQAwUjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24g
# bnYtc2ExKDAmBgNVBAMTH0dsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gRzIw
# HhcNMTUwMjAzMDAwMDAwWhcNMjYwMzAzMDAwMDAwWjBgMQswCQYDVQQGEwJTRzEf
# MB0GA1UEChMWR01PIEdsb2JhbFNpZ24gUHRlIEx0ZDEwMC4GA1UEAxMnR2xvYmFs
# U2lnbiBUU0EgZm9yIE1TIEF1dGhlbnRpY29kZSAtIEcyMIIBIjANBgkqhkiG9w0B
# AQEFAAOCAQ8AMIIBCgKCAQEAsBeuotO2BDBWHlgPse1VpNZUy9j2czrsXV6rJf02
# pfqEw2FAxUa1WVI7QqIuXxNiEKlb5nPWkiWxfSPjBrOHOg5D8NcAiVOiETFSKG5d
# QHI88gl3p0mSl9RskKB2p/243LOd8gdgLE9YmABr0xVU4Prd/4AsXximmP/Uq+yh
# RVmyLm9iXeDZGayLV5yoJivZF6UQ0kcIGnAsM4t/aIAqtaFda92NAgIpA6p8N7u7
# KU49U5OzpvqP0liTFUy5LauAo6Ml+6/3CGSwekQPXBDXX2E3qk5r09JTJZ2Cc/os
# +XKwqRk5KlD6qdA8OsroW+/1X1H0+QrZlzXeaoXmIwRCrwIDAQABo4IBXzCCAVsw
# DgYDVR0PAQH/BAQDAgeAMEwGA1UdIARFMEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYB
# BQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAkG
# A1UdEwQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQgYDVR0fBDswOTA3oDWg
# M4YxaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3RpbWVzdGFtcGluZ2cy
# LmNybDBUBggrBgEFBQcBAQRIMEYwRAYIKwYBBQUHMAKGOGh0dHA6Ly9zZWN1cmUu
# Z2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzdGltZXN0YW1waW5nZzIuY3J0MB0GA1Ud
# DgQWBBTUooRKOFoYf7pPMFC9ndV6h9YJ9zAfBgNVHSMEGDAWgBRG2D7/3OO+/4Pm
# 9IWbsN1q1hSpwTANBgkqhkiG9w0BAQUFAAOCAQEAgDLcB40coJydPCroPSGLWaFN
# fsxEzgO+fqq8xOZ7c7tL8YjakE51Nyg4Y7nXKw9UqVbOdzmXMHPNm9nZBUUcjaS4
# A11P2RwumODpiObs1wV+Vip79xZbo62PlyUShBuyXGNKCtLvEFRHgoQ1aSicDOQf
# FBYk+nXcdHJuTsrjakOvz302SNG96QaRLC+myHH9z73YnSGY/K/b3iKMr6fzd++d
# 3KNwS0Qa8HiFHvKljDm13IgcN+2tFPUHCya9vm0CXrG4sFhshToN9v9aJwzF3lPn
# VDxWTMlOTDD28lz7GozCgr6tWZH2G01Ve89bAdz9etNvI1wyR5sB88FRFEaKmzCC
# BNYwggO+oAMCAQICEhEhDRayW4wRltP+V8mGEea62TANBgkqhkiG9w0BAQsFADBa
# MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEwMC4GA1UE
# AxMnR2xvYmFsU2lnbiBDb2RlU2lnbmluZyBDQSAtIFNIQTI1NiAtIEcyMB4XDTE1
# MDUwNDE2NDMyMVoXDTE4MDUwNDE2NDMyMVowVTELMAkGA1UEBhMCQ0gxDDAKBgNV
# BAgTA1p1ZzEMMAoGA1UEBxMDWnVnMRQwEgYDVQQKEwtkLWZlbnMgR21iSDEUMBIG
# A1UEAxMLZC1mZW5zIEdtYkgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDNPSzSNPylU9jFM78Q/GjzB7N+VNqikf/use7p8mpnBZ4cf5b4qV3rqQd62rJH
# RlAsxgouCSNQrl8xxfg6/t/I02kPvrzsR4xnDgMiVCqVRAeQsWebafWdTvWmONBS
# lxJejPP8TSgXMKFaDa+2HleTycTBYSoErAZSWpQ0NqF9zBadjsJRVatQuPkTDrwL
# eWibiyOipK9fcNoQpl5ll5H9EG668YJR3fqX9o0TQTkOmxXIL3IJ0UxdpyDpLEkt
# tBG6Y5wAdpF2dQX2phrfFNVY54JOGtuBkNGMSiLFzTkBA1fOlA6ICMYjB8xIFxVv
# rN1tYojCrqYkKMOjwWQz5X8zAgMBAAGjggGZMIIBlTAOBgNVHQ8BAf8EBAMCB4Aw
# TAYDVR0gBEUwQzBBBgkrBgEEAaAyATIwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93
# d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wCQYDVR0TBAIwADATBgNVHSUE
# DDAKBggrBgEFBQcDAzBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsLmdsb2Jh
# bHNpZ24uY29tL2dzL2dzY29kZXNpZ25zaGEyZzIuY3JsMIGQBggrBgEFBQcBAQSB
# gzCBgDBEBggrBgEFBQcwAoY4aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9j
# YWNlcnQvZ3Njb2Rlc2lnbnNoYTJnMi5jcnQwOAYIKwYBBQUHMAGGLGh0dHA6Ly9v
# Y3NwMi5nbG9iYWxzaWduLmNvbS9nc2NvZGVzaWduc2hhMmcyMB0GA1UdDgQWBBTN
# GDddiIYZy9p3Z84iSIMd27rtUDAfBgNVHSMEGDAWgBQZSrha5E0xpRTlXuwvoxz6
# gIwyazANBgkqhkiG9w0BAQsFAAOCAQEAAApsOzSX1alF00fTeijB/aIthO3UB0ks
# 1Gg3xoKQC1iEQmFG/qlFLiufs52kRPN7L0a7ClNH3iQpaH5IEaUENT9cNEXdKTBG
# 8OrJS8lrDJXImgNEgtSwz0B40h7bM2Z+0DvXDvpmfyM2NwHF/nNVj7NzmczrLRqN
# 9de3tV0pgRqnIYordVcmb24CZl3bzpwzbQQy14Iz+P5Z2cnw+QaYzAuweTZxEUcJ
# bFwpM49c1LMPFJTuOKkUgY90JJ3gVTpyQxfkc7DNBnx74PlRzjFmeGC/hxQt0hvo
# eaAiBdjo/1uuCTToigVnyRH+c0T2AezTeoFb7ne3I538hWeTdU5q9jGCBLcwggSz
# AgEBMHAwWjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
# MDAuBgNVBAMTJ0dsb2JhbFNpZ24gQ29kZVNpZ25pbmcgQ0EgLSBTSEEyNTYgLSBH
# MgISESENFrJbjBGW0/5XyYYR5rrZMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEM
# MQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQB
# gjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBQAnM8vxrJAqFbH
# 1dns9HDB0ZtnLTANBgkqhkiG9w0BAQEFAASCAQBLwsIiygSKqpXNWcfriE7cAOz7
# lrx1uZq0RJw2XxOvrjkxY+gASbH2bMWYvL1NrxC/DJe4DthebzKnWdFrdP5q7lAv
# J4wymoLrcZ51qaV1j4D5F8ubLJugfFgQY5DsymqXHySVcZ01EgRwI+5oLAW/y8LQ
# XHANyI+fW0uWKZtHSxNPnVBDisWvwm2HN9uMv+sCUEealGn69WF4uXrILhiBLtBT
# M/l+CNZ3u7B+CgP/IhKsO1r+1P915j1sxg/aOoIqDDKpYLfc9eBBxB1ODWVKb0V/
# A7TL9g4Swz9Ygfv2P/xsHNg5BpXTKw0qTU5hoaF4aNHColY3AweFEhX4CMdFoYIC
# ojCCAp4GCSqGSIb3DQEJBjGCAo8wggKLAgEBMGgwUjELMAkGA1UEBhMCQkUxGTAX
# BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKDAmBgNVBAMTH0dsb2JhbFNpZ24gVGlt
# ZXN0YW1waW5nIENBIC0gRzICEhEhBqCB0z/YeuWCTMFrUglOAzAJBgUrDgMCGgUA
# oIH9MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE1
# MTExNjEwNTg1OVowIwYJKoZIhvcNAQkEMRYEFLgKFeFdaf6OfXFrx5CpNPEeuy0z
# MIGdBgsqhkiG9w0BCRACDDGBjTCBijCBhzCBhAQUs2MItNTN7U/PvWa5Vfrjv7Es
# KeYwbDBWpFQwUjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt
# c2ExKDAmBgNVBAMTH0dsb2JhbFNpZ24gVGltZXN0YW1waW5nIENBIC0gRzICEhEh
# BqCB0z/YeuWCTMFrUglOAzANBgkqhkiG9w0BAQEFAASCAQA2tIJNK1wr5qvgXCvV
# 9z73Sqz+Svvlbh344YKEOaJvHkbuHSBErQhXoM5XCAD8i3qKSdpDo2Y0pN8ugBKB
# Ok2Ir52nsSbnBwzAMxrdElaF6jDpbqiPw+aOf7h0jQlVpUr1OswB3xYLbV6/f+74
# fzuW28hSP0GaGcU4zBZw6C/rUq4qR5tRDUfZtYXflhEuWrN601vqnxybxE8IlSey
# PCaA+/tEakzeTwVwnBVuZX0XfjrZb2+bpvoiWI6K8ZkLe5bhiOIYD6WQdST5IOHc
# kJHFo/cuiMaGZypt+5+PuiI4zjGcXG3+EYLpGrG392bzYnrp9go4zSDccwU2MXUy
# nSmD
# SIG # End signature block