retry

in src/zrest/zcl_rest_utility_class.clas.abap [0:0]


  METHOD retry.
*----------------------------------------------------------------------*
*                       Modification History                           *
*----------------------------------------------------------------------*
* Date      | USER ID  |  VSTF  | Transport  | Remarks                 *
*-----------|----------|--------|------------|-------------------------*
* 04|28|2016|V-DEVEER  |2163894 | DGDK903413 | Authorization Check
*----------------------------------------------------------------------*
* 05|05|2016|V-DEVEER  |2163894 | DGDK903444 | SIT Testing issues
*----------------------------------------------------------------------*
* 12|08|2016|V-JAVEDA  |2163894 | MS2K948543 | Enhance delete function
*----------------------------------------------------------------------*
* 12|16|2016|V-JAVEDA  |2163894 | MS2K948920 | Performance improve
*----------------------------------------------------------------------*
*12/20/2016| V-JAVEDA  |2278065  | MS2K948978 |Clearing prog header *
*----------------------------------------------------------------------*

    DATA : lv_string               TYPE string,
           wa_paylod               TYPE zrest_mo_payload,
           lv_text2                TYPE scx_t100key,
           lv_textid               TYPE REF TO zcx_http_client_failed,
           lv_rfc_destination      TYPE zrest_config-destination,
           lv_srtfd                TYPE zadf_con_indx-srtfd,
           lw_indx                 TYPE zadf_con_indx,
           lt_enveloped_data       TYPE TABLE OF ssfbin,
           lv_cert_string          TYPE xstring,
           lt_recipients           TYPE TABLE OF ssfinfo,
           lw_recipient            TYPE ssfinfo,
           lt_input_data           TYPE TABLE OF ssfbin,
           lv_env_data_len         TYPE i,
           lv_env_len_total        TYPE i,
           lv_subject              TYPE string,
           lw_enveloped_data       TYPE ssfbin,
           lv_len_output           TYPE i,
           lv_len_input            TYPE i,
           lv_decoded_str          TYPE string,
           lv_applic               TYPE rfcdisplay-sslapplic,
           lv_psename              TYPE ssfpsename,
           lv_profilename          TYPE localfile,
           lv_profile              TYPE ssfparms-pab,
           lv_current_timestamp    TYPE timestampl,
           lv_date_adf             TYPE datum,
           lv_time_adf             TYPE uzeit,
           lv_seconds_adf          TYPE p,
           lv_input_seconds_adf    TYPE p,
           lv_expiry_time_adf      TYPE string,
           lv_new_expiry_adf       TYPE string,
           lv_format               TYPE i,
           lv_string_to_sign       TYPE string,
           lv_encoded_base_address TYPE string,
           lv_body_xstring         TYPE xstring,
           lv_sign                 TYPE string,
           lv_final_token          TYPE string,
           lv_decoded              TYPE xstring,
           lo_conv                 TYPE REF TO cl_abap_conv_out_ce,
           lv_sas_key              TYPE string,
           lw_zadf_config          TYPE zadf_config,
           lv_zone                 TYPE sy-zonlo,
           lv_baseaddress          TYPE string,
           http_method             TYPE zinterface_method.
    CONSTANTS: lc_i          TYPE c VALUE 'I',
               lc_servicebus TYPE zadf_config-interface_type VALUE 'SERVICEBUS',
               lc_eventhub   TYPE zadf_config-interface_type VALUE 'EVENTHUB',
               lc_auth       TYPE ihttpnvp-name VALUE 'Authorization'.
    CREATE OBJECT lv_textid.
*-----------------------check message id ------------------------------*
    check_messageid( message_id = message_id ).
*-----------------------get db data -----------------------------------*
    get_db_data( message_id = message_id ).
* ------------------------get the latest payloadv----------------------*
*   Sort the retry num , so that latest one is picked for reprocessing
    SORT payload BY retry_num DESCENDING.

*    READ TABLE payload INTO DATA(wa_paylod) INDEX 1. v-jobpau
    CLEAR wa_paylod.  "v-javeda | MS2K948978
    READ TABLE payload INTO wa_paylod INDEX 1.
* ---------------------------------------------------------------------*
    interface_name = wa_paylod-interface_id.
    http_method = wa_paylod-method.
* ---------------------------------------------------------------------*
*   Begin of changes for 2163894 | DGDK903413
    TRY.
*        To be uncommented later - sapurana - 6/24
*        check_authority( ).
*        AUTHORITY-CHECK OBJECT 'ZREST_RETR'
*        ID 'ZBOOLEAN' FIELD 'X'.
*        IF sy-subrc NE 0.
*          lv_textid2-msgid = 'Z_FI_MDG'.
*          lv_textid2-msgno = '057'.
*          RAISE EXCEPTION TYPE zcx_http_client_failed EXPORTING textid = lv_textid2.
*        ENDIF.
* End of changes for 2163894 | DGDK903413

      CATCH zcx_http_client_failed INTO lv_textid.
        lv_text2 = lv_textid->if_t100_message~t100key.
        RAISE EXCEPTION TYPE zcx_http_client_failed
          EXPORTING
            textid = lv_text2.
    ENDTRY.
*   End of changes for 2163894 | DGDK903413
*-----------------------Get the config ------------------------------*
    DATA: wa_config TYPE zrest_srtuct_config.

    wa_config = zcl_rest_utility_class=>get_config_data(
        interface_id = interface_name
        method       = http_method ).



*-----------------------Retry possible ? ------------------------------*
    IF wa_config-max_retry EQ 0.
      MESSAGE 'Retry not possible'(001) TYPE 'I'.   " Added the messsage for VSTF 2163894 / DGDK903444
      EXIT.
    ELSEIF wa_paylod-retry_num EQ wa_config-max_retry AND from_scheduler EQ 'X'. "v-javeda - MS2K948543
      MESSAGE 'Maximum number of retry attempts reached'(002) TYPE 'I'. " Added the message for VSTF 2163894 / DGDK903444
      EXIT.
    ENDIF.
*----------------------------------------------------------------------*
*    begin of change for the exponential retries.
    IF from_scheduler EQ 'X'.
      DATA: wa_global TYPE zrest_global.
      wa_global = zcl_rest_utility_class=>get_global_params( ).

*     3 9 27 81 243 243 243 ...........
      DATA : base       TYPE i VALUE 3,
             next_retry TYPE p DECIMALS 0,
             seconds    TYPE p DECIMALS 0.
*     Get the next retrial
      IF wa_paylod-retry_num EQ space.
        wa_paylod-retry_num = 0.
      ELSE.
      ENDIF.
      next_retry = base ** wa_paylod-retry_num .
*     Check the date and time difference between the first trail and now
      TRY.
          cl_abap_tstmp=>td_subtract(
            EXPORTING
              date1    = sy-datum
              time1    = sy-uzeit
              date2    = monitor-zexedate
              time2    = monitor-zexetime
            IMPORTING
              res_secs = seconds ).
        CATCH cx_parameter_invalid_type .
        CATCH cx_parameter_invalid_range .
      ENDTRY.
*       Check if enough time has elapsed
      next_retry = 60 * next_retry.
*       Set the max. repetitive interval to be retried ( break from exponential ).
      IF next_retry > ( wa_global-linear_retry_duration * 60 * 60 ).
        next_retry = wa_global-linear_retry_duration * 60 * 60.
      ENDIF.
      IF ( seconds < next_retry ).
        EXIT.
      ENDIF.

    ENDIF.
*    end of change.
*------------------------------------- --------------------------------*
    DATA: cx_http_failed    TYPE REF TO zcx_http_client_failed,
          cx_config_missing TYPE REF TO zcx_interace_config_missing.
    CREATE OBJECT: cx_http_failed,
                   cx_config_missing.
    TRY .
        CREATE OBJECT rest_handler
          EXPORTING
            interface_name      = interface_name
            business_identifier = wa_paylod-businessid
            method              = wa_config-method.

      CATCH zcx_http_client_failed INTO cx_http_failed.

        RAISE EXCEPTION cx_http_failed.
      CATCH zcx_interace_config_missing INTO cx_config_missing.
        RAISE EXCEPTION cx_config_missing.
    ENDTRY.
*   Set the format in binary as it's already converted.
    IF wa_paylod-payload IS NOT INITIAL.
      rest_handler->zif_rest_framework~set_binary_body( wa_paylod-payload ).
    ENDIF.
    rest_handler->set_callingmethod( 'RETRY' ).
*   Append the headers to the message
    CLEAR lv_string.
    CALL FUNCTION 'ECATT_CONV_XSTRING_TO_STRING'
      EXPORTING
        im_xstring  = wa_paylod-programheaders
        im_encoding = 'UTF-8'
      IMPORTING
        ex_string   = lv_string.

    DATA:wa_header     TYPE ihttpnvp,
         result_tab    TYPE TABLE OF string,
         wa_result_tab TYPE string.
    SPLIT lv_string AT '|' INTO TABLE result_tab IN CHARACTER MODE.
*****
**Regenerating SAS key token with new expiry time
    CLEAR lw_zadf_config.
    SELECT SINGLE * FROM zadf_config
             INTO lw_zadf_config
             WHERE interface_id EQ interface_name.
    IF sy-subrc EQ 0.
      CASE lw_zadf_config-interface_type.
        WHEN lc_servicebus OR lc_eventhub. "Azure ServiceBus or eventhub
          lv_srtfd = interface_name.
*Import internal table as a cluster from INDX for decoding SAS Primary key
          IMPORT tab  = lt_enveloped_data[]
                 FROM DATABASE zadf_con_indx(zd)
                 TO lw_indx
                 ID lv_srtfd.
          IF NOT lt_enveloped_data[] IS INITIAL.
            CLEAR lv_rfc_destination.
            SELECT SINGLE destination FROM zrest_config
                                      INTO lv_rfc_destination
                                      WHERE interface_id EQ interface_name.
            IF NOT lv_rfc_destination IS INITIAL .
              CALL FUNCTION 'RFC_READ_HTTP_DESTINATION'
                EXPORTING
                  destination             = lv_rfc_destination
                  authority_check         = ' '
                IMPORTING
                  sslapplic               = lv_applic
                EXCEPTIONS
                  authority_not_available = 1
                  destination_not_exist   = 2
                  information_failure     = 3
                  internal_failure        = 4
                  no_http_destination     = 5
                  OTHERS                  = 6.
              IF sy-subrc NE 0.
                MESSAGE TEXT-008 TYPE lc_i.
              ELSE.
                CALL FUNCTION 'SSFPSE_FILENAME'
                  EXPORTING
                    mandt         = sy-mandt
                    context       = 'SSLC'
                    applic        = lv_applic
                  IMPORTING
                    psename       = lv_psename
                  EXCEPTIONS
                    pse_not_found = 1
                    OTHERS        = 2.
                IF NOT lv_psename IS INITIAL.
                  lv_profile = lv_psename.
                  CALL FUNCTION 'SSFC_GET_CERTIFICATE'
                    EXPORTING
                      profile               = lv_profile
                    IMPORTING
                      certificate           = lv_cert_string
                    EXCEPTIONS
                      ssf_krn_error         = 1
                      ssf_krn_nomemory      = 2
                      ssf_krn_nossflib      = 3
                      ssf_krn_invalid_par   = 4
                      ssf_krn_nocertificate = 5
                      OTHERS                = 6.
                  IF sy-subrc NE 0.
**Adding complete profile path for reading certificate instance
                    lv_profile = lv_profilename.
                    CALL FUNCTION 'SSFC_GET_CERTIFICATE'
                      EXPORTING
                        profile               = lv_profile
                      IMPORTING
                        certificate           = lv_cert_string
                      EXCEPTIONS
                        ssf_krn_error         = 1
                        ssf_krn_nomemory      = 2
                        ssf_krn_nossflib      = 3
                        ssf_krn_invalid_par   = 4
                        ssf_krn_nocertificate = 5
                        OTHERS                = 6.
                    IF sy-subrc NE 0.
                      MESSAGE TEXT-007 TYPE lc_i.
                    ENDIF.
                  ELSE.
                    CALL FUNCTION 'SSFC_PARSE_CERTIFICATE'
                      EXPORTING
                        certificate         = lv_cert_string
                      IMPORTING
                        subject             = lv_subject
                      EXCEPTIONS
                        ssf_krn_error       = 1
                        ssf_krn_nomemory    = 2
                        ssf_krn_nossflib    = 3
                        ssf_krn_invalid_par = 4
                        OTHERS              = 5.
                    IF sy-subrc NE 0.
                      MESSAGE TEXT-006 TYPE lc_i.
                    ELSE.
                      lw_recipient-id      = lv_subject.
                      lw_recipient-profile = lv_profile.
                      APPEND lw_recipient TO lt_recipients.
                      LOOP AT lt_enveloped_data INTO lw_enveloped_data.
                        lv_env_data_len = xstrlen( lw_enveloped_data-bindata ).
                        lv_env_len_total = lv_env_len_total + lv_env_data_len.
                        CLEAR lw_enveloped_data.
                      ENDLOOP.
                      CALL FUNCTION 'SSF_KRN_DEVELOPE'
                        EXPORTING
                          ssftoolkit                   = 'SAPSECULIB'
                          str_format                   = 'PKCS7'
                          ostr_enveloped_data_l        = lv_env_len_total
                        IMPORTING
                          ostr_output_data_l           = lv_len_input
                        TABLES
                          ostr_enveloped_data          = lt_enveloped_data
                          recipient                    = lt_recipients
                          ostr_output_data             = lt_input_data
                        EXCEPTIONS
                          ssf_krn_error                = 1
                          ssf_krn_noop                 = 2
                          ssf_krn_nomemory             = 3
                          ssf_krn_opinv                = 4
                          ssf_krn_nossflib             = 5
                          ssf_krn_recipient_error      = 6
                          ssf_krn_input_data_error     = 7
                          ssf_krn_invalid_par          = 8
                          ssf_krn_invalid_parlen       = 9
                          ssf_fb_input_parameter_error = 10
                          OTHERS                       = 11.
                      IF sy-subrc NE 0.
                        MESSAGE TEXT-005 TYPE lc_i.
                      ELSE.
                        IF NOT lt_input_data[] IS INITIAL.
                          CALL FUNCTION 'SCMS_BINARY_TO_STRING'
                            EXPORTING
                              input_length  = lv_len_input
                            IMPORTING
                              text_buffer   = lv_decoded_str
                              output_length = lv_len_output
                            TABLES
                              binary_tab    = lt_input_data
                            EXCEPTIONS
                              failed        = 1
                              OTHERS        = 2.
                          IF lv_decoded_str IS INITIAL.
                            MESSAGE TEXT-004 TYPE lc_i.
                          ELSE.
                            lv_sas_key = lv_decoded_str.
                          ENDIF.
                        ELSE.
                          MESSAGE TEXT-003 TYPE lc_i.
                        ENDIF.
                      ENDIF.
                    ENDIF.
                  ENDIF.
                ENDIF.
              ENDIF.
            ELSE.
              MESSAGE TEXT-002 TYPE lc_i.
            ENDIF.
          ELSE.
            MESSAGE TEXT-001 TYPE lc_i.
          ENDIF.
**Calculating Epoch time for SAS Token
          IF NOT lv_sas_key IS INITIAL.
*Get the current timestamp
            GET TIME STAMP FIELD  lv_current_timestamp .
*Get the time difference
            CONVERT TIME STAMP lv_current_timestamp TIME ZONE lv_zone INTO DATE lv_date_adf TIME lv_time_adf.
            TRY.
                CALL METHOD cl_abap_tstmp=>td_subtract
                  EXPORTING
                    date1    = lv_date_adf
                    time1    = lv_time_adf
                    date2    = '19700101'
                    time2    = '000000'
                  IMPORTING
                    res_secs = lv_seconds_adf.
* Add expiry time in seconds
                lv_input_seconds_adf =  900 . "Setting expiry time as 15 mins
                lv_seconds_adf = lv_seconds_adf + lv_input_seconds_adf.
                lv_expiry_time_adf = lv_seconds_adf.
                CONDENSE lv_expiry_time_adf.
              CATCH cx_parameter_invalid_type.
              CATCH cx_parameter_invalid_range .
            ENDTRY.
**Generating SAS token with new expiry time
            IF NOT lv_expiry_time_adf IS INITIAL.
              lv_baseaddress = lw_zadf_config-uri.
              lv_format = 18.
              lv_encoded_base_address = escape( val = lv_baseaddress format = lv_format  ).
              CONCATENATE lv_encoded_base_address  cl_abap_char_utilities=>newline lv_expiry_time_adf INTO lv_string_to_sign.

              lo_conv = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ).
              lo_conv->convert( EXPORTING data = lv_string_to_sign IMPORTING buffer = lv_body_xstring ).

              lo_conv = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ).
              lo_conv->convert( EXPORTING data = lv_sas_key IMPORTING buffer = lv_decoded ).
              TRY.
                  CALL METHOD cl_abap_hmac=>calculate_hmac_for_raw
                    EXPORTING
                      if_algorithm     = 'sha-256'
                      if_key           = lv_decoded
                      if_data          = lv_body_xstring
                      if_length        = 0
                    IMPORTING
                      ef_hmacb64string = lv_sign.
                CATCH cx_abap_message_digest.
              ENDTRY.
              lv_new_expiry_adf = lv_expiry_time_adf.
              CONDENSE lv_new_expiry_adf.
              IF NOT lv_sign IS INITIAL.
                DATA wa_policy TYPE zadf_ehub_policy.
                SELECT SINGLE * FROM zadf_ehub_policy INTO wa_policy WHERE interface_id EQ interface_name.
                lv_sign = escape( val = lv_sign format = lv_format  ).
                IF lw_zadf_config-interface_type eq lc_servicebus. "Servicebus signature string
                   CONCATENATE 'SharedAccessSignature sig=' lv_encoded_base_address  '&sig=' lv_sign '&se=' lv_new_expiry_adf '&skn='
                   wa_policy-policy INTO lv_final_token.
                ELSEIF lw_zadf_config-interface_type eq lc_eventhub. "Eventhub signature string
                   CONCATENATE 'SharedAccessSignature sr=' lv_encoded_base_address  '&sig=' lv_sign '&se=' lv_new_expiry_adf '&skn='
                   wa_policy-policy INTO lv_final_token.
                ENDIF.
              ENDIF.
            ENDIF.
          ENDIF.
      ENDCASE.
    ENDIF.
    LOOP AT result_tab INTO wa_result_tab.
      SPLIT wa_result_tab AT ':' INTO wa_header-name wa_header-value.
**Replacing Authorization header value with newly generated SAS Token
      IF ( lw_zadf_config-interface_type EQ lc_servicebus OR lw_zadf_config-interface_type EQ lc_eventhub ) AND
         ( wa_header-name EQ lc_auth ) AND
         ( NOT lv_final_token IS INITIAL ).
        rest_handler->set_request_header( iv_name = wa_header-name  iv_value = lv_final_token ).
      ELSE.
        rest_handler->set_request_header( iv_name = wa_header-name  iv_value = wa_header-value  ).
      ENDIF.
    ENDLOOP.
    rest_handler->set_callingprogram( 'ZCL_REST_UTILITY_CLASS' ).
    lv_string = wa_paylod-uri.
    rest_handler->set_uri( lv_string ).
*   Retry
    response = rest_handler->zif_rest_framework~execute( io_entity  = request
                                                         async      = abap_false
                                                         is_retry   = abap_true
                                                         messageid  = message_id
                                                         retry_count = wa_paylod-retry_num ).

    FREE rest_handler.  "v-javeda -    MS2K948920