├── README.md ├── src ├── package.devc.xml ├── yui5_repository_load.fugr.lyui5_repository_loadtop.abap ├── yhttp_test.prog.xml ├── yui5_repository_load.fugr.lyui5_repository_loadd01.xml ├── yui5_repository_load.fugr.lyui5_repository_loadp01.xml ├── ygithub_deploy_test.prog.xml ├── ygithub_deploy_ui5_repository.prog.xml ├── yui5_repository_load.fugr.lyui5_repository_loadtop.xml ├── ycl_github_webhook_handler.clas.xml ├── yui5_repository_load.fugr.saplyui5_repository_load.abap ├── ycl_github_deployer.clas.xml ├── ygithub_deploy_ui5_repository.prog.abap ├── ygithub_deploy_test.prog.abap ├── yhttp_test.prog.abap ├── yui5_repository_load.fugr.xml ├── yui5_repository_load.fugr.saplyui5_repository_load.xml ├── ycl_github_webhook_handler.clas.abap ├── yui5_repository_load.fugr.lyui5_repository_loadd01.abap ├── yui5_repository_load.fugr.yui5_repository_load_http.abap ├── ycl_github_deployer.clas.abap └── yui5_repository_load.fugr.lyui5_repository_loadp01.abap └── .abapgit.xml /README.md: -------------------------------------------------------------------------------- 1 | # sapui5-deployer 2 | ABAP deployment of SAPUI5 apps from Githib 3 | 4 | http://yelcho.github.io/sapui5-deployer/ 5 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SAPUI5 Deployer 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadtop.abap: -------------------------------------------------------------------------------- 1 | FUNCTION-POOL YUI5_REPOSITORY_LOAD. "MESSAGE-ID .. 2 | 3 | type-pools abap. 4 | 5 | CONSTANTS: status_success TYPE char1 VALUE 'S', 6 | status_warning TYPE char1 VALUE 'W', 7 | status_error TYPE char1 VALUE 'E'. 8 | INCLUDE LYUI5_REPOSITORY_LOADD01. "for local class definitions 9 | -------------------------------------------------------------------------------- /.abapgit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | E 6 | /src/ 7 | PREFIX 8 | 9 | /.gitignore 10 | /LICENSE 11 | /README.md 12 | /package.json 13 | /.travis.yml 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/yhttp_test.prog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YHTTP_TEST 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | R 15 | HTTP Test 16 | 9 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadd01.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LYUI5_REPOSITORY_LOADD01 7 | I 8 | S 9 | E 10 | X 11 | 12 | 13 | 14 | R 15 | Include /UI5/LUI5_REPOSITORY_LOADD01 16 | 36 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadp01.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LYUI5_REPOSITORY_LOADP01 7 | I 8 | S 9 | E 10 | X 11 | 12 | 13 | 14 | R 15 | Include /UI5/LUI5_REPOSITORY_LOADP01 16 | 36 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ygithub_deploy_test.prog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YGITHUB_DEPLOY_TEST 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | R 15 | Test deployment of SAPUI5 app from GitHub 16 | 41 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ygithub_deploy_ui5_repository.prog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YGITHUB_DEPLOY_UI5_REPOSITORY 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | R 15 | Program YGITHUB_DEPLOY_UI5_REPOSITORY 16 | 37 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadtop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LYUI5_REPOSITORY_LOADTOP 7 | S 8 | D$ 9 | I 10 | S 11 | E 12 | X 13 | D$S 14 | X 15 | 16 | 17 | 18 | R 19 | Include /UI5/LUI5_REPOSITORY_LOADP01 20 | 36 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/ycl_github_webhook_handler.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YCL_GITHUB_WEBHOOK_HANDLER 7 | E 8 | GitHub webhook ICF handler 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | YCL_GITHUB_WEBHOOK_HANDLER 17 | MT_GITHUB_FIELDS 18 | E 19 | HTTP Framework (iHTTP) Table Name/Value Pairs 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.saplyui5_repository_load.abap: -------------------------------------------------------------------------------- 1 | ******************************************************************* 2 | * System-defined Include-files. * 3 | ******************************************************************* 4 | INCLUDE LYUI5_REPOSITORY_LOADTOP. " Global Data 5 | INCLUDE LYUI5_REPOSITORY_LOADUXX. " Function Modules 6 | 7 | ******************************************************************* 8 | * User-defined Include-files (if necessary). * 9 | ******************************************************************* 10 | * INCLUDE /UI5/LUI5_REPOSITORY_LOADF... " Subprograms 11 | * INCLUDE /UI5/LUI5_REPOSITORY_LOADO... " PBO-Modules 12 | * INCLUDE /UI5/LUI5_REPOSITORY_LOADI... " PAI-Modules 13 | 14 | INCLUDE LYUI5_REPOSITORY_LOADP01. 15 | *INCLUDE /UI5/LUI5_REPOSITORY_LOADP01. "for local class implementations 16 | -------------------------------------------------------------------------------- /src/ycl_github_deployer.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YCL_GITHUB_DEPLOYER 7 | E 8 | Deploy SAPUI5 apps from GitHub 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | YCL_GITHUB_DEPLOYER 17 | CSS_MINIFY_PARAMS 18 | E 19 | HTTP Framework (iHTTP) Table Name/Value Pairs 20 | 21 | 22 | YCL_GITHUB_DEPLOYER 23 | JS_MINIFY_PARAMS 24 | E 25 | HTTP Framework (iHTTP) Table Name/Value Pairs 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/ygithub_deploy_ui5_repository.prog.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Report YGITHUB_DEPLOY_UI5_REPOSITORY 3 | *&---------------------------------------------------------------------* 4 | *& 5 | *&---------------------------------------------------------------------* 6 | REPORT ygithub_deploy_ui5_repository line-SIZE 120. 7 | 8 | DATA: exc TYPE REF TO cx_root. 9 | 10 | SELECTION-SCREEN BEGIN OF BLOCK blk_main. 11 | PARAMETERS: 12 | git_repo TYPE string OBLIGATORY LOWER CASE, 13 | branch TYPE string OBLIGATORY LOWER CASE DEFAULT `master`, 14 | username TYPE string VISIBLE LENGTH 15 LOWER CASE, 15 | password TYPE string VISIBLE LENGTH 15 LOWER CASE, 16 | tranport TYPE trkorr, 17 | test TYPE boolean DEFAULT 'X'. 18 | SELECTION-SCREEN END OF BLOCK blk_main. 19 | 20 | START-OF-SELECTION. 21 | 22 | TRY. 23 | ycl_github_deployer=>deploy( 24 | repository = git_repo 25 | branch = branch 26 | github_user = username 27 | password = password 28 | transport = tranport 29 | test_only = test ). 30 | CATCH cx_root INTO exc. 31 | MESSAGE exc TYPE 'I' DISPLAY LIKE 'E'. 32 | ENDTRY. 33 | -------------------------------------------------------------------------------- /src/ygithub_deploy_test.prog.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Report YGITHUB_DEPLOY_TEST 3 | *&---------------------------------------------------------------------* 4 | *& 5 | *&---------------------------------------------------------------------* 6 | REPORT ygithub_deploy_test. 7 | 8 | *--------------------------------------------------------------------* 9 | * This program tests deployment of a GitHub SAPUI5 repository 10 | * 11 | * Check https://github.com/grahamrobbo/demojam to see the repo 12 | * that will be deployted. This is a public repo so no user 13 | * credentials are required. 14 | * 15 | * Note in the .Ui5RepositoryUploadParameters file where the settings 16 | * for this app are defined. 17 | * 18 | * SAPUI5ApplicationName=ZDEMOJAM 19 | * SAPUI5ApplicationPackage=$TMP 20 | * SAPUI5ApplicationDescription=Simple SAPUI5 App 21 | * ExternalCodePage=Cp1252 22 | * AcceptUnixStyleEol=True 23 | * DeltaMode=False 24 | * 25 | * If you want to change these parameters, for example to give the app 26 | * a different name, clone the repo and make changes in your own copy. 27 | *--------------------------------------------------------------------* 28 | 29 | SELECTION-SCREEN BEGIN OF BLOCK blk_main. 30 | PARAMETERS: 31 | user TYPE string LOWER CASE 32 | DEFAULT ``, 33 | password TYPE string LOWER CASE 34 | DEFAULT ``, 35 | repo TYPE string OBLIGATORY LOWER CASE 36 | DEFAULT `grahamrobbo/demojam`, 37 | branch TYPE string OBLIGATORY LOWER CASE 38 | DEFAULT `master`, 39 | test TYPE boolean DEFAULT 'X'. 40 | SELECTION-SCREEN END OF BLOCK blk_main. 41 | 42 | START-OF-SELECTION. 43 | 44 | TRY. 45 | ycl_github_deployer=>deploy( 46 | github_user = user 47 | password = password 48 | repository = repo 49 | branch = branch 50 | test_only = test ). 51 | CATCH cx_root INTO DATA(exc). 52 | MESSAGE exc TYPE 'I' DISPLAY LIKE 'E'. 53 | ENDTRY. 54 | -------------------------------------------------------------------------------- /src/yhttp_test.prog.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Report YHTTP_TEST 3 | *&---------------------------------------------------------------------* 4 | *& 5 | *&---------------------------------------------------------------------* 6 | REPORT yhttp_test. 7 | *--------------------------------------------------------------------* 8 | * Simple test to ensure we can talk to GitHub. 9 | *--------------------------------------------------------------------* 10 | 11 | DATA: lr_client TYPE REF TO if_http_client. 12 | 13 | cl_http_client=>create_by_url( 14 | EXPORTING 15 | url = 'https://github.com/' 16 | ssl_id = 'ANONYM' 17 | IMPORTING 18 | client = lr_client 19 | EXCEPTIONS 20 | argument_not_found = 1 21 | plugin_not_active = 2 22 | internal_error = 3 23 | OTHERS = 4 ). 24 | IF sy-subrc <> 0. 25 | CASE sy-subrc. 26 | WHEN 1. 27 | " make sure: 28 | " a) SSL is setup properly in STRUST 29 | DATA(lv_message) = 'HTTPS ARGUMENT_NOT_FOUND | STRUST/SSL Setup correct?'. "#EC NOTEXT 30 | WHEN OTHERS. 31 | lv_message = 'While creating HTTP Client'. "#EC NOTEXT 32 | 33 | ENDCASE. 34 | WRITE:/, lv_message COLOR COL_NEGATIVE. 35 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 36 | RETURN. 37 | ENDIF. 38 | 39 | lr_client->send( EXCEPTIONS OTHERS = 1 ). 40 | IF sy-subrc <> 0. 41 | lv_message = |http send error|. 42 | WRITE:/, lv_message COLOR COL_NEGATIVE. 43 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 44 | RETURN. 45 | ENDIF. 46 | lr_client->receive( 47 | EXCEPTIONS 48 | http_communication_failure = 1 49 | http_invalid_state = 2 50 | http_processing_failed = 3 51 | OTHERS = 4 ). 52 | IF sy-subrc <> 0. 53 | CASE sy-subrc. 54 | WHEN 1. 55 | " make sure: 56 | " a) SSL is setup properly in STRUST 57 | " b) no firewalls 58 | " check trace file in transaction SMICM 59 | lv_message = 'HTTP Communication Failure'. "#EC NOTEXT 60 | WHEN 2. 61 | lv_message = 'HTTP Invalid State'. "#EC NOTEXT 62 | WHEN 3. 63 | lv_message = 'HTTP Processing failed'. "#EC NOTEXT 64 | WHEN OTHERS. 65 | lv_message = 'Another error occured'. "#EC NOTEXT 66 | ENDCASE. 67 | WRITE:/, lv_message COLOR COL_NEGATIVE. 68 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 69 | RETURN. 70 | ENDIF. 71 | 72 | lr_client->response->get_status( IMPORTING code = DATA(lv_code) ). 73 | 74 | IF lv_code NE 200. 75 | IF lv_message IS INITIAL. 76 | lv_message = |HTTP Return Code is { lv_code }|. "#EC NOTEXT 77 | ENDIF. 78 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 79 | ELSE. 80 | MESSAGE |All okay| TYPE 'I' DISPLAY LIKE 'I'. 81 | ENDIF. 82 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SAPUI5 Repository Load 6 | 7 | LYUI5_REPOSITORY_LOADD01 8 | LYUI5_REPOSITORY_LOADP01 9 | LYUI5_REPOSITORY_LOADTOP 10 | SAPLYUI5_REPOSITORY_LOAD 11 | 12 | 13 | 14 | YUI5_REPOSITORY_LOAD_HTTP 15 | R 16 | SAPUI5 Repository Upload via HTTP Protocoll 17 | 18 | 19 | IV_URL 20 | STRING 21 | 22 | 23 | IV_SAPUI5_APPLICATION_NAME 24 | '' 25 | X 26 | STRING 27 | 28 | 29 | IV_SAPUI5_APPLICATION_DESC 30 | '' 31 | X 32 | STRING 33 | 34 | 35 | IV_PACKAGE 36 | '' 37 | X 38 | DEVCLASS 39 | 40 | 41 | IV_WORKBENCH_REQUEST 42 | '' 43 | X 44 | TRKORR 45 | 46 | 47 | IV_EXTERNAL_CODE_PAGE 48 | '' 49 | X 50 | STRING 51 | 52 | 53 | IV_ACCEPT_UNIX_STYLE_EOL 54 | '-' 55 | X 56 | BOOLEAN 57 | 58 | 59 | IV_DELTA_MODE 60 | '-' 61 | X 62 | BOOLEAN 63 | 64 | 65 | IV_TEST_MODE 66 | '' 67 | X 68 | BOOLEAN 69 | 70 | 71 | IV_ZIP_FILE 72 | X 73 | XSTRING 74 | 75 | 76 | 77 | 78 | EV_SUCCESS 79 | CHAR1 80 | 81 | 82 | EV_LOG_MESSAGES 83 | STRING_TABLE 84 | 85 | 86 | EV_MSG_ID 87 | SY-MSGID 88 | 89 | 90 | EV_MSG_NO 91 | SY-MSGNO 92 | 93 | 94 | 95 | 96 | IV_URL 97 | P 98 | Url to load SAPUI5 application from 99 | 100 | 101 | IV_SAPUI5_APPLICATION_NAME 102 | P 103 | Name of SAPUI5 application to be loaded 104 | 105 | 106 | IV_SAPUI5_APPLICATION_DESC 107 | P 108 | Description of SAPUI5 application 109 | 110 | 111 | IV_PACKAGE 112 | P 113 | Package of SAPUI5 application 114 | 115 | 116 | IV_WORKBENCH_REQUEST 117 | P 118 | ABAP workbench request 119 | 120 | 121 | IV_EXTERNAL_CODE_PAGE 122 | P 123 | External code page name for text files 124 | 125 | 126 | IV_ACCEPT_UNIX_STYLE_EOL 127 | P 128 | Accept unix style line endings in text files 129 | 130 | 131 | IV_DELTA_MODE 132 | P 133 | Upload different files and folders, delete obsolete resources 134 | 135 | 136 | IV_TEST_MODE 137 | P 138 | Activate test mode with detailed messages 139 | 140 | 141 | IV_ZIP_FILE 142 | P 143 | ZIP file 144 | 145 | 146 | EV_SUCCESS 147 | P 148 | Outcome of function call: S=Success, W=Warning, E=error 149 | 150 | 151 | EV_LOG_MESSAGES 152 | P 153 | Outcome of function call: Log Messages 154 | 155 | 156 | EV_MSG_ID 157 | P 158 | Outcome of function call: Message Class 159 | 160 | 161 | EV_MSG_NO 162 | P 163 | Outcome of function call: Message Number 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.saplyui5_repository_load.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SAPLYUI5_REPOSITORY_LOAD 7 | S 8 | D$ 9 | F 10 | S 11 | E 12 | X 13 | D$S 14 | X 15 | 16 | 17 | 18 | I 19 | 001 20 | ***** Upload of SAPUI5 Application from ZIP-Archive into SAPUI5 ABAP Repository ***** 21 | 132 22 | 23 | 24 | I 25 | 002 26 | * Running in test mode: Upload operations are skipped, Detailed Log * 27 | 132 28 | 29 | 30 | I 31 | 003 32 | * Running in regular mode: Brief Log * 33 | 132 34 | 35 | 36 | I 37 | 010 38 | * Upload canceled: Url to Zip File containing SAPUI5 App is missing. * 39 | 132 40 | 41 | 42 | I 43 | 011 44 | * Upload canceled: Unable to access Url "%" to Zip File containing SAPUI5 App. * 45 | 132 46 | 47 | 48 | I 49 | 012 50 | * Connecting to Zip File containing SAPUI5 Application * 51 | 132 52 | 53 | 54 | I 55 | 013 56 | * Upload canceled: Archive could not be read or appears to be empty. * 57 | 132 58 | 59 | 60 | I 61 | 014 62 | . % Files found in Archive. 63 | 132 64 | 65 | 66 | I 67 | 015 68 | * Upload canceled: SAPUI5 Application Name not specified. * 69 | 79 70 | 71 | 72 | I 73 | 016 74 | * Upload canceled: ABAP workbench request for SAPUI5 ABAP Repository not specified. * 75 | 132 76 | 77 | 78 | I 79 | 017 80 | * Upload canceled: Repository Package is not defined. * 81 | 132 82 | 83 | 84 | I 85 | 018 86 | . The external code page name has been set to "%". 87 | 132 88 | 89 | 90 | I 91 | 019 92 | * Parameters * 93 | 132 94 | 95 | 96 | I 97 | 020 98 | . The text files are identified using the standard settings. 99 | 132 100 | 101 | 102 | I 103 | 021 104 | . The file '.Ui5RepositoryTextFiles' is considered to identify text files. 105 | 132 106 | 107 | 108 | I 109 | 022 110 | . The binary files are identified using the standard settings. 111 | 132 112 | 113 | 114 | I 115 | 023 116 | . The file '.Ui5RepositoryBinaryFiles' is considered to identify binary files. 117 | 132 118 | 119 | 120 | I 121 | 024 122 | . The files and folders to be ignored are determined from the built-in standard settings. 123 | 132 124 | 125 | 126 | I 127 | 025 128 | . The files and folders to be ignored are determined from the '.Ui5RepositoryIgnore' file. 129 | 132 130 | 131 | 132 | I 133 | 026 134 | . %1 "%2" has been determined from the '.Ui5RepositoryUploadParameters' file. 135 | 132 136 | 137 | 138 | I 139 | 027 140 | . %1 "%2" has been determined from the corresponding import parameter. 141 | 132 142 | 143 | 144 | I 145 | 028 146 | * Creating new SAPUI5 application % * 147 | 132 148 | 149 | 150 | I 151 | 029 152 | * Updating existing SAPUI5 application % * 153 | 132 154 | 155 | 156 | I 157 | 030 158 | * Upload canceled: SAPUI5 application has not been created (successfully). * 159 | 132 160 | 161 | 162 | I 163 | 032 164 | * Upload canceled: External Code Page is invalid. You may use e.g. 'UTF-8' or 'Cp1252' * 165 | 132 166 | 167 | 168 | I 169 | 033 170 | * Upload canceled: Code Page is invalid. * 171 | 132 172 | 173 | 174 | I 175 | 034 176 | . The delta mode has been turned on. 177 | 132 178 | 179 | 180 | I 181 | 035 182 | . The delta mode has been turned off. 183 | 132 184 | 185 | 186 | I 187 | 036 188 | . The package has been defaulted to "$TMP". 189 | 132 190 | 191 | 192 | I 193 | 037 194 | . Unix style end of line markers in text files get accepted. 195 | 132 196 | 197 | 198 | I 199 | 038 200 | . Unix style end of line markers in text files get rejected. 201 | 132 202 | 203 | 204 | I 205 | 039 206 | . A BAdI implementation for /UI5/BADI_PREVENT_DELETION is active: Repository and app may become out of sync. 207 | 132 208 | 209 | 210 | I 211 | 040 212 | * Operations * 213 | 132 214 | 215 | 216 | I 217 | 041 218 | * Analyzing Archive * 219 | 132 220 | 221 | 222 | I 223 | 043 224 | * Done * 225 | 40 226 | 227 | 228 | I 229 | 050 230 | * Warning: Content of file % could not be read * 231 | 132 232 | 233 | 234 | I 235 | 051 236 | * Warning: Unable to determine MD5 hash for file % * 237 | 120 238 | 239 | 240 | I 241 | 054 242 | * Warning: Folder % has not been created * 243 | 90 244 | 245 | 246 | I 247 | 055 248 | * Warning: Text file % has not been uploaded * 249 | 100 250 | 251 | 252 | I 253 | 056 254 | * Warning: Text file % has unix style line delimeter. It is not uploaded * 255 | 132 256 | 257 | 258 | I 259 | 057 260 | * Error: Unable to convert Unix style text file % * 261 | 132 262 | 263 | 264 | I 265 | 064 266 | * Warning: Binary file % has not been uploaded * 267 | 100 268 | 269 | 270 | I 271 | 065 272 | * Binary file has NOT been deleted in ABAP repository on BAdI request * 273 | 132 274 | 275 | 276 | I 277 | 070 278 | Text 279 | 10 280 | 281 | 282 | I 283 | 071 284 | Binary 285 | 20 286 | 287 | 288 | I 289 | 072 290 | Warning: File type unknown 291 | 132 292 | 293 | 294 | I 295 | 073 296 | Unix style text file 297 | 132 298 | 299 | 300 | I 301 | 074 302 | Already up-to-date 303 | 132 304 | 305 | 306 | I 307 | 075 308 | Folder already exists 309 | 132 310 | 311 | 312 | I 313 | 076 314 | Warning: Unix style text file 315 | 132 316 | 317 | 318 | I 319 | 090 320 | * Upload canceled: Name of SAPUI5 Application appears to be invalid. Same rules as for BSP applications apply. 321 | 132 322 | 323 | 324 | I 325 | 091 326 | * Upload canceled: External code page has not been specified. * 327 | 132 328 | 329 | 330 | I 331 | 092 332 | * Upload canceled: Unable to lock SAPUI5 repository * 333 | 132 334 | 335 | 336 | I 337 | 093 338 | * Upload canceled: A BAdI error has occurred. * 339 | 132 340 | 341 | 342 | I 343 | 100 344 | The name of the SAPUI5 Application 345 | 132 346 | 347 | 348 | I 349 | 101 350 | The description of the SAPUI5 Application 351 | 132 352 | 353 | 354 | I 355 | 102 356 | Warning : Authorization may be missing for 357 | 132 358 | 359 | 360 | I 361 | 103 362 | The package of the SAPUI5 Application 363 | 132 364 | 365 | 366 | I 367 | 104 368 | Workbench Request 369 | 132 370 | 371 | 372 | I 373 | 105 374 | The external Code Page Name 375 | 132 376 | 377 | 378 | I 379 | 106 380 | The acceptance of Unix style end of line markers in text files 381 | 132 382 | 383 | 384 | I 385 | 107 386 | Warning : Authorizations may be missing. 387 | 132 388 | 389 | 390 | I 391 | 108 392 | and 393 | 132 394 | 395 | 396 | I 397 | 109 398 | . HTTP status was %1 / %2 399 | 132 400 | 401 | 402 | I 403 | 110 404 | Application log message : 405 | 132 406 | 407 | 408 | I 409 | 111 410 | * Updating the Application Index * 411 | 132 412 | 413 | 414 | I 415 | 112 416 | . For details see the application log (SLG1) in client 000 for object /UI5/APPIDX . 417 | 132 418 | 419 | 420 | 421 | 422 | 423 | -------------------------------------------------------------------------------- /src/ycl_github_webhook_handler.clas.abap: -------------------------------------------------------------------------------- 1 | class YCL_GITHUB_WEBHOOK_HANDLER definition 2 | public 3 | create public . 4 | 5 | public section. 6 | 7 | interfaces IF_HTTP_EXTENSION . 8 | protected section. 9 | 10 | types: 11 | BEGIN OF user_profile_plan_type, 12 | name TYPE string, 13 | space TYPE string, 14 | collaborators TYPE string, 15 | private_repos TYPE string, 16 | END OF user_profile_plan_type . 17 | types: 18 | BEGIN OF user_profile_type, 19 | login TYPE string, 20 | id TYPE string, 21 | avatar_url TYPE string, 22 | gravatar_id TYPE string, 23 | url TYPE string, 24 | html_url TYPE string, 25 | followers_url TYPE string, 26 | following_url TYPE string, 27 | gists_url TYPE string, 28 | starred_url TYPE string, 29 | subscriptions_url TYPE string, 30 | organizations_url TYPE string, 31 | repos_url TYPE string, 32 | events_url TYPE string, 33 | received_events_url TYPE string, 34 | type TYPE string, 35 | site_admin TYPE string, 36 | name TYPE string, 37 | company TYPE string, 38 | blog TYPE string, 39 | location TYPE string, 40 | email TYPE string, 41 | hireable TYPE string, 42 | bio TYPE string, 43 | public_repos TYPE string, 44 | public_gists TYPE string, 45 | followers TYPE string, 46 | following TYPE string, 47 | created_at TYPE string, 48 | updated_at TYPE string, 49 | private_gists TYPE string, 50 | total_private_repos TYPE string, 51 | owned_private_repos TYPE string, 52 | disk_usage TYPE string, 53 | collaborators TYPE string, 54 | plan TYPE user_profile_plan_type, 55 | END OF user_profile_type . 56 | types: 57 | BEGIN OF github_permissions_type, 58 | admin TYPE boolean, 59 | push TYPE boolean, 60 | pull TYPE boolean, 61 | END OF github_permissions_type . 62 | types: 63 | BEGIN OF github_owner_type, 64 | login TYPE string, 65 | id TYPE i, 66 | avatar_url TYPE string, 67 | gravatar_id TYPE string, 68 | url TYPE string, 69 | html_url TYPE string, 70 | followers_url TYPE string, 71 | following_url TYPE string, 72 | gists_url TYPE string, 73 | starred_url TYPE string, 74 | subscriptions_url TYPE string, 75 | organizations_url TYPE string, 76 | repos_url TYPE string, 77 | events_url TYPE string, 78 | received_events_url TYPE string, 79 | type TYPE string, 80 | site_admin TYPE boolean, 81 | name type string, 82 | email type string, 83 | username type string, 84 | END OF github_owner_type . 85 | types: 86 | BEGIN OF github_organization_type, 87 | login TYPE string, 88 | id TYPE i, 89 | description type string, 90 | avatar_url TYPE string, 91 | url TYPE string, 92 | html_url TYPE string, 93 | members_url type string, 94 | followers_url TYPE string, 95 | following_url TYPE string, 96 | public_members_url type string, 97 | gists_url TYPE string, 98 | starred_url TYPE string, 99 | subscriptions_url TYPE string, 100 | organizations_url TYPE string, 101 | repos_url TYPE string, 102 | events_url TYPE string, 103 | received_events_url TYPE string, 104 | type TYPE string, 105 | site_admin TYPE boolean, 106 | END OF github_organization_type . 107 | types: 108 | BEGIN OF github_repository_type, 109 | id TYPE i, 110 | name TYPE string, 111 | full_name TYPE string, 112 | owner TYPE github_owner_type, 113 | private TYPE boolean, 114 | html_url TYPE string, 115 | description TYPE string, 116 | fork TYPE boolean, 117 | url TYPE string, 118 | forks_url TYPE string, 119 | keys_url TYPE string, 120 | collaborators_url TYPE string, 121 | teams_url TYPE string, 122 | hooks_url TYPE string, 123 | issue_events_url TYPE string, 124 | events_url TYPE string, 125 | assignees_url TYPE string, 126 | branches_url TYPE string, 127 | tags_url TYPE string, 128 | blobs_url TYPE string, 129 | git_tags_url TYPE string, 130 | git_refs_url TYPE string, 131 | trees_url TYPE string, 132 | statuses_url TYPE string, 133 | languages_url TYPE string, 134 | stargazers_url TYPE string, 135 | contributors_url TYPE string, 136 | subscribers_url TYPE string, 137 | subscription_url TYPE string, 138 | commits_url TYPE string, 139 | git_commits_url TYPE string, 140 | comments_url TYPE string, 141 | issue_comment_url TYPE string, 142 | contents_url TYPE string, 143 | compare_url TYPE string, 144 | merges_url TYPE string, 145 | archive_url TYPE string, 146 | downloads_url TYPE string, 147 | issues_url TYPE string, 148 | pulls_url TYPE string, 149 | milestones_url TYPE string, 150 | notifications_url TYPE string, 151 | labels_url TYPE string, 152 | releases_url TYPE string, 153 | created_at TYPE string, 154 | updated_at TYPE string, 155 | pushed_at TYPE string, 156 | git_url TYPE string, 157 | ssh_url TYPE string, 158 | clone_url TYPE string, 159 | svn_url TYPE string, 160 | homepage TYPE string, 161 | size TYPE i, 162 | stargazers_count TYPE i, 163 | watchers_count TYPE i, 164 | language TYPE string, 165 | has_issues TYPE boolean, 166 | has_downloads TYPE boolean, 167 | has_wiki TYPE boolean, 168 | has_pages TYPE boolean, 169 | forks_count TYPE i, 170 | mirror_url TYPE string, 171 | open_issues_count TYPE i, 172 | forks TYPE i, 173 | open_issues TYPE i, 174 | watchers TYPE i, 175 | startgazers type i, 176 | default_branch TYPE string, 177 | master_branch type string, 178 | permissions TYPE github_permissions_type, 179 | organization TYPE github_organization_type, 180 | network_count TYPE i, 181 | subscribers_count TYPE i, 182 | END OF github_repository_type . 183 | types: 184 | github_repository_ttype TYPE TABLE OF github_repository_type . 185 | types: 186 | begin of github_commit_type, 187 | id type string, 188 | distinct type boolean, 189 | message type string, 190 | timestamp type string, 191 | url type string, 192 | author type github_owner_type, 193 | committer type github_owner_type, 194 | added type stringtab, 195 | removed type stringtab, 196 | modified type stringtab, 197 | end of github_commit_type . 198 | types: 199 | github_commit_ttype type table of github_commit_type . 200 | types: 201 | begin of github_push_type, 202 | ref type string, 203 | before type string, 204 | after type string, 205 | created type boolean, 206 | deleted type boolean, 207 | forced type boolean, 208 | base_ref type string, 209 | compare type string, 210 | "commits type table of github_commit_type, 211 | head_commit type github_commit_type, 212 | repository type github_repository_type, 213 | pusher type github_owner_type, 214 | organization type github_organization_type, 215 | sender type github_owner_type, 216 | end of github_push_type . 217 | 218 | data MT_GITHUB_FIELDS type TIHTTPNVP . 219 | 220 | methods READ_GITHUB_FIELDS 221 | importing 222 | !SERVER type ref to IF_HTTP_SERVER . 223 | methods GET_COMMIT_DETAILS 224 | importing 225 | !SERVER type ref to IF_HTTP_SERVER 226 | returning 227 | value(PUSH) type GITHUB_PUSH_TYPE . 228 | private section. 229 | ENDCLASS. 230 | 231 | 232 | 233 | CLASS YCL_GITHUB_WEBHOOK_HANDLER IMPLEMENTATION. 234 | 235 | 236 | METHOD get_commit_details. 237 | DATA(payload) = server->request->get_cdata( ). 238 | "SPLIT payload AT 'payload=' INTO DATA(junk) payload. 239 | 240 | /ui2/cl_json=>deserialize( 241 | EXPORTING json = cl_http_utility=>unescape_url( payload ) 242 | pretty_name = /ui2/cl_json=>pretty_mode-camel_case 243 | CHANGING 244 | data = push ). 245 | 246 | ENDMETHOD. 247 | 248 | 249 | METHOD if_http_extension~handle_request. 250 | 251 | DATA: ls_push TYPE github_push_type, 252 | lt_stringtab TYPE stringtab, 253 | lv_jobnumber TYPE tbtcjob-jobcount, 254 | lv_jobname TYPE tbtcjob-jobname, 255 | lt_params TYPE TABLE OF rsparams, 256 | lr_param TYPE REF TO rsparams. 257 | 258 | ls_push = get_commit_details( server ). 259 | 260 | CHECK ls_push IS NOT INITIAL. 261 | 262 | * We are only interested in deploying the master branch 263 | SPLIT ls_push-ref AT '/' INTO TABLE lt_stringtab. 264 | CHECK lt_stringtab[ lines( lt_stringtab ) ] EQ ls_push-repository-master_branch. 265 | 266 | * Check this is a repo we want to deploy here 267 | CASE ls_push-repository-full_name. 268 | WHEN 'grahamrobbo/demojam'. "Most repos take a while to deploy - so submit a batch job to do the work 269 | 270 | APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 271 | lr_param->selname = 'GIT_REPO'. 272 | lr_param->kind = 'S'. 273 | lr_param->sign = 'I'. 274 | lr_param->option = 'EQ'. 275 | lr_param->low = ls_push-repository-full_name. 276 | 277 | IF ls_push-repository-master_branch IS NOT INITIAL. 278 | APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 279 | lr_param->selname = 'BRANCH'. 280 | lr_param->kind = 'S'. 281 | lr_param->sign = 'I'. 282 | lr_param->option = 'EQ'. 283 | lr_param->low = ls_push-repository-master_branch. 284 | ENDIF. 285 | 286 | * " Note GitHub credentials only required for private repos 287 | * IF github_user IS NOT INITIAL. 288 | * APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 289 | * lr_param->selname = 'USERNAME'. 290 | * lr_param->kind = 'S'. 291 | * lr_param->sign = 'I'. 292 | * lr_param->option = 'EQ'. 293 | * lr_param->low = github_user. 294 | * 295 | * IF password IS NOT INITIAL. 296 | * APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 297 | * lr_param->selname = 'PASSWORD'. 298 | * lr_param->kind = 'S'. 299 | * lr_param->sign = 'I'. 300 | * lr_param->option = 'EQ'. 301 | * lr_param->low = github_password. 302 | * ENDIF. 303 | * ENDIF. 304 | * 305 | * " Note workbench request can be specified in the .Ui5RepositoryUploadParameters file 306 | * IF transport IS NOT INITIAL. 307 | * APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 308 | * lr_param->selname = 'TRANSPORT'. 309 | * lr_param->kind = 'S'. 310 | * lr_param->sign = 'I'. 311 | * lr_param->option = 'EQ'. 312 | * lr_param->low = transport. 313 | * ENDIF. 314 | 315 | APPEND INITIAL LINE TO lt_params REFERENCE INTO lr_param. 316 | lr_param->selname = 'TEST'. 317 | lr_param->kind = 'S'. 318 | lr_param->sign = 'I'. 319 | lr_param->option = 'EQ'. 320 | lr_param->low = abap_false. 321 | 322 | lv_jobname = |Deploy { ls_push-repository-full_name }|. 323 | CALL FUNCTION 'JOB_OPEN' 324 | EXPORTING 325 | jobname = lv_jobname 326 | IMPORTING 327 | jobcount = lv_jobnumber 328 | EXCEPTIONS 329 | cant_create_job = 1 330 | invalid_job_data = 2 331 | jobname_missing = 3 332 | OTHERS = 4. 333 | CHECK sy-subrc = 0. 334 | 335 | SUBMIT ygithub_deploy_ui5_repository 336 | WITH SELECTION-TABLE lt_params 337 | VIA JOB lv_jobname NUMBER lv_jobnumber AND RETURN. 338 | CHECK sy-subrc = 0. 339 | 340 | CALL FUNCTION 'JOB_CLOSE' 341 | EXPORTING 342 | jobcount = lv_jobnumber 343 | jobname = lv_jobname 344 | strtimmed = 'X' 345 | EXCEPTIONS 346 | cant_start_immediate = 1 347 | invalid_startdate = 2 348 | jobname_missing = 3 349 | job_close_failed = 4 350 | job_nosteps = 5 351 | job_notex = 6 352 | lock_failed = 7 353 | OTHERS = 8. 354 | 355 | WHEN OTHERS. 356 | server->response->set_status( code = 404 reason = |Not found| ). 357 | ENDCASE. 358 | 359 | ENDMETHOD. 360 | 361 | 362 | METHOD read_github_fields. 363 | 364 | DATA: lt_fields TYPE tihttpnvp, 365 | ls_fields LIKE LINE OF lt_fields, 366 | lv_json TYPE xstring, 367 | lr_conv TYPE REF TO cl_abap_conv_out_ce. 368 | 369 | * Json Processing variables. 370 | DATA: lr_reader TYPE REF TO if_sxml_reader, 371 | lr_node TYPE REF TO if_sxml_node, 372 | lr_value_node TYPE REF TO if_sxml_value_node, 373 | lr_open_elem TYPE REF TO if_sxml_open_element, 374 | lt_attribs TYPE if_sxml_attribute=>attributes, 375 | ls_attrib LIKE LINE OF lt_attribs. 376 | 377 | DATA: parse_error TYPE REF TO cx_sxml_parse_error. 378 | 379 | server->request->get_form_fields_cs( 380 | * EXPORTING 381 | * formfield_encoding = 0 " CO_FORMFIELD_ENCODING_RAW / _ENCODED 382 | * search_option = 3 " CO_BODY_BEFORE_QUERY_STRING or others 383 | CHANGING 384 | fields = lt_fields ). " Form fields 385 | 386 | READ TABLE lt_fields INTO ls_fields INDEX 1. 387 | * convert to xstring 388 | lr_conv = cl_abap_conv_out_ce=>create( ). 389 | lr_conv->convert( 390 | EXPORTING 391 | data = ls_fields-value " Field to Be Converted 392 | * n = - 1 " Number of Units to Be Converted 393 | IMPORTING 394 | buffer = lv_json " Converted Data 395 | * len = " Number of Converted Units 396 | ). 397 | * CATCH cx_sy_codepage_converter_init. " 398 | * CATCH cx_sy_conversion_codepage. " 399 | * CATCH cx_parameter_invalid_type. " 400 | CLEAR me->mt_github_fields. 401 | 402 | IF lv_json IS INITIAL. 403 | lv_json = server->request->get_data( ). 404 | ENDIF. 405 | * get the reader 406 | lr_reader = cl_sxml_string_reader=>create( lv_json ). 407 | * Parse in a do loop. 408 | TRY. 409 | DO. 410 | CLEAR lr_node. 411 | lr_node = lr_reader->read_next_node( ). 412 | IF lr_node IS INITIAL. 413 | EXIT. 414 | ENDIF. 415 | CASE lr_node->type. 416 | WHEN if_sxml_node=>co_nt_element_open. 417 | CLEAR ls_fields. 418 | lr_open_elem ?= lr_node. 419 | ls_fields-name = lr_open_elem->qname-name. 420 | IF ls_fields-name EQ 'str'. 421 | " read the name attribute for getting the name of the json value 422 | lt_attribs = lr_open_elem->get_attributes( ). 423 | LOOP AT lt_attribs INTO ls_attrib. 424 | IF ls_attrib->qname-name = 'name'. 425 | ls_fields-name = ls_attrib->get_value( ). 426 | ENDIF. 427 | ENDLOOP. 428 | ELSE. 429 | CLEAR ls_fields. 430 | ENDIF. 431 | WHEN if_sxml_node=>co_nt_value. 432 | * node value. 433 | IF ls_fields IS INITIAL. 434 | CONTINUE. 435 | ENDIF. 436 | lr_value_node ?= lr_node. 437 | ls_fields-value = lr_value_node->get_value( ). 438 | APPEND ls_fields TO me->mt_github_fields. 439 | WHEN OTHERS. 440 | ENDCASE. 441 | ENDDO. 442 | CATCH cx_sxml_parse_error INTO parse_error. 443 | ENDTRY. 444 | ENDMETHOD. 445 | ENDCLASS. 446 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadd01.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Include /UI5/LUI5_REPOSITORY_LOADD01 3 | *&---------------------------------------------------------------------* 4 | ************************************************************************ 5 | ************************************************************************ 6 | * * 7 | * Local Classes Definition * 8 | * * 9 | ************************************************************************ 10 | ************************************************************************ 11 | 12 | 13 | ************************************************************************ 14 | * Class LCL_FUNCTION 15 | * 16 | * provides some helper functions. 17 | ************************************************************************ 18 | CLASS lcl_function DEFINITION. 19 | PUBLIC SECTION. 20 | 21 | TYPES: x255_table TYPE STANDARD TABLE OF raw255. 22 | CLASS-METHODS: conv_unix_style_line_endings IMPORTING iv_string TYPE string 23 | RETURNING VALUE(rv_string) TYPE string, 24 | get_md5_hash_for_string IMPORTING iv_string TYPE string 25 | RETURNING VALUE(rv_md5_hash) TYPE md5_fields-hash, 26 | get_hash_for_xstring IMPORTING iv_xstring TYPE xstring 27 | RETURNING VALUE(rv_hash) TYPE string, 28 | max IMPORTING a TYPE i DEFAULT -999999 29 | b TYPE i DEFAULT -999999 30 | c TYPE i DEFAULT -999999 31 | d TYPE i DEFAULT -999999 32 | e TYPE i DEFAULT -999999 33 | f TYPE i DEFAULT -999999 34 | RETURNING VALUE(rv_max) TYPE i, 35 | set_return_msg IMPORTING iv_success TYPE char1 36 | iv_test_mode TYPE abap_bool 37 | CHANGING cv_msg_id LIKE sy-msgid 38 | cv_msg_no LIKE sy-msgno, 39 | string_to_file IMPORTING iv_file_content TYPE string 40 | iv_code_page TYPE string 41 | iv_file_path TYPE string 42 | RETURNING VALUE(rv_success) TYPE abap_bool, 43 | text_matches_pattern IMPORTING iv_text TYPE string 44 | iv_pattern_list TYPE string_table 45 | RETURNING VALUE(rv_text_matches_pattern) TYPE abap_bool, 46 | text_to_abap_bool IMPORTING iv_text TYPE string 47 | RETURNING VALUE(rv_abap_bool) TYPE abap_bool, 48 | xstring_to_file IMPORTING iv_file_content TYPE xstring 49 | iv_file_path TYPE string 50 | RETURNING VALUE(rv_success) TYPE abap_bool, 51 | xstring2xtable IMPORTING iv_xstring TYPE xstring 52 | EXPORTING ev_xtable TYPE x255_table 53 | ev_size TYPE int4. 54 | 55 | ENDCLASS. "lcl_function DEFINITION 56 | 57 | 58 | ************************************************************************ 59 | * Class LCL_OPERATION 60 | * 61 | * represents an upload operation to be performed. 62 | ************************************************************************ 63 | CLASS lcl_operation DEFINITION. 64 | 65 | PUBLIC SECTION. 66 | 67 | DATA: full_path TYPE string, 68 | message TYPE string, 69 | object_type TYPE string, 70 | object_name TYPE string, 71 | operation TYPE string, 72 | relative_path TYPE string, 73 | hash_value TYPE md5_fields-hash, 74 | code_page TYPE string, 75 | eol_conversion TYPE abap_bool, 76 | to_update TYPE abap_bool. 77 | METHODS: create_log_message RETURNING VALUE(rv_message) TYPE string, 78 | get_file_extension RETURNING VALUE(rv_file_extension) TYPE string, 79 | is_binary RETURNING VALUE(rv_is_binary) TYPE abap_bool. 80 | CLASS-DATA: create_folder TYPE string VALUE 'CREATE FOLDER', 81 | delete_folder TYPE string VALUE 'DELETE FOLDER', 82 | delete_file TYPE string VALUE 'DELETE FILE', 83 | ignore_file TYPE string VALUE 'IGNORE_FILE', 84 | ignore_folder TYPE string VALUE 'IGNORE_FOLDER', 85 | upload_file TYPE string VALUE 'UPLOAD FILE', 86 | object_type_none TYPE string VALUE '', 87 | object_type_binary_file TYPE string VALUE 'BINARY_FILE', 88 | object_type_file TYPE string VALUE 'FILE', 89 | object_type_text_file TYPE string VALUE 'TEXT_FILE', 90 | object_type_folder TYPE string VALUE 'FOLDER'. 91 | 92 | ENDCLASS. "LCL_OPERATION 93 | 94 | ************************************************************************ 95 | * Class LCL_BADI 96 | * 97 | ************************************************************************ 98 | CLASS lcl_badi DEFINITION. 99 | 100 | PUBLIC SECTION. 101 | DATA: 102 | implementation TYPE REF TO /ui5/badi_prevent_deletion, 103 | never_delete_mime_resources TYPE abap_bool, 104 | application_name TYPE string, 105 | workbench_request TYPE trkorr, 106 | test_mode TYPE abap_bool, 107 | error_occurred TYPE abap_bool, 108 | error_text TYPE string. 109 | 110 | METHODS: constructor IMPORTING iv_test_mode TYPE abap_bool 111 | iv_sapui5_application_name TYPE string 112 | iv_workbench_request TYPE trkorr, 113 | disable_deletion_for IMPORTING iv_operation TYPE REF TO lcl_operation 114 | RETURNING VALUE(rv_result) TYPE abap_bool. 115 | 116 | ENDCLASS. 117 | 118 | ************************************************************************ 119 | * Class LCL_SAPUI5_ZIP_ARCHIVE 120 | * 121 | * represents a zip file containing a SAPUI5 application 122 | * 123 | * Remarks: 124 | * - Access to log messages is passed as reference to constructor: 125 | * 1) Changing and table parameters are not allowed here; 126 | * 2) Using a field symbol as an input parameter does not work either: 127 | * Write operation is not supported then. 128 | * 129 | ************************************************************************ 130 | CLASS lcl_sapui5_zip_archive DEFINITION FINAL. 131 | 132 | PUBLIC SECTION. 133 | 134 | TYPES: operations TYPE TABLE OF REF TO lcl_operation. 135 | METHODS: constructor IMPORTING iv_url TYPE string 136 | iv_zip_file TYPE xstring OPTIONAL 137 | ir_log_messages TYPE REF TO string_table, 138 | determine_upload_operations IMPORTING iv_delta_mode TYPE abap_bool 139 | iv_accept_unix_style_eol TYPE abap_bool 140 | iv_code_page TYPE string 141 | CHANGING cv_load_operations TYPE operations 142 | cv_success TYPE char1, 143 | is_ok RETURNING VALUE(rv_is_ok) TYPE boolean, 144 | is_binary_file IMPORTING iv_file_path TYPE string 145 | RETURNING VALUE(rv_is_binary_file) TYPE abap_bool, 146 | is_file_to_be_ignored IMPORTING iv_file_path TYPE string 147 | RETURNING VALUE(rv_ignore) TYPE abap_bool, 148 | is_text_file IMPORTING iv_file_path TYPE string 149 | RETURNING VALUE(rv_is_text_file) TYPE abap_bool, 150 | read_file_to_table IMPORTING iv_path TYPE string 151 | iv_code_page TYPE string 152 | RETURNING VALUE(rt_lines) TYPE string_table, 153 | read_file IMPORTING iv_path TYPE string 154 | RETURNING VALUE(rv_content) TYPE xstring, 155 | get_upload_parameter IMPORTING iv_key TYPE string 156 | iv_return_if_not_specified TYPE string DEFAULT '' 157 | RETURNING VALUE(rv_value) TYPE string. 158 | DATA: binary_file_patterns TYPE string_table, 159 | text_file_patterns TYPE string_table, 160 | upload_ignores TYPE string_table, 161 | upload_parameters TYPE slin_key_value_hash. 162 | 163 | PRIVATE SECTION. 164 | 165 | METHODS: add_default_bin_file_patterns CHANGING cv_file_patterns TYPE string_table, 166 | add_default_ignore_patterns CHANGING cv_file_patterns TYPE string_table, 167 | add_default_text_file_patterns CHANGING cv_file_patterns TYPE string_table, 168 | add_import_upload_parameters CHANGING cv_file_patterns TYPE slin_key_value_hash, 169 | create_folders_for_path IMPORTING iv_path TYPE string 170 | CHANGING cv_folders_created TYPE string 171 | cv_load_operations TYPE operations, 172 | determine_binary_file_patterns IMPORTING iv_code_page TYPE string, 173 | determine_text_file_patterns IMPORTING iv_code_page TYPE string, 174 | determine_upload_ignores IMPORTING iv_code_page TYPE string, 175 | determine_upload_parameters IMPORTING iv_code_page TYPE string. 176 | DATA: error_message TYPE string, 177 | http_client TYPE REF TO if_http_client, 178 | log_messages_ref TYPE REF TO string_table, 179 | ok TYPE boolean, 180 | upload_operations TYPE TABLE OF REF TO lcl_operation, 181 | url TYPE string, 182 | zip_archive TYPE REF TO cl_abap_zip. 183 | 184 | ENDCLASS. "lcl_sapui5_zip_archive 185 | 186 | 187 | ************************************************************************ 188 | * Class LCL_EXCEPTION 189 | * 190 | * is the exception to handle errors in this report. 191 | ************************************************************************ 192 | CLASS lcx_exception DEFINITION INHERITING FROM cx_static_check. 193 | ENDCLASS. "lcx_exception DEFINITION 194 | 195 | 196 | ************************************************************************ 197 | * Class LCL_CANCELED 198 | * 199 | * indicates processing has been canceled by the user. 200 | ************************************************************************ 201 | CLASS lcx_canceled DEFINITION INHERITING FROM cx_dynamic_check. 202 | ENDCLASS. "lcx_canceled DEFINITION 203 | 204 | 205 | 206 | ************************************************************************ 207 | * Class lcl_external_code_page 208 | * 209 | * supports conversion of external code page into abap code page. 210 | ************************************************************************ 211 | CLASS lcl_external_code_page DEFINITION. 212 | 213 | PUBLIC SECTION. 214 | 215 | TYPE-POOLS abap. 216 | CLASS-DATA: no_code_page TYPE cpcodepage VALUE '0'. 217 | CLASS-METHODS: create IMPORTING iv_code_page_name TYPE string 218 | RETURNING VALUE(rv_external_code_page) TYPE REF TO lcl_external_code_page 219 | RAISING lcx_exception, 220 | for_sapgui_installation RETURNING VALUE(rv_external_code_page) TYPE REF TO lcl_external_code_page 221 | RAISING lcx_exception. 222 | METHODS: get_abap_encoding RETURNING VALUE(rv_abap_encoding) TYPE cpcodepage 223 | RAISING lcx_exception, 224 | get_java_encoding RETURNING VALUE(rv_java_encoding) TYPE string 225 | RAISING lcx_exception. 226 | DATA: name TYPE string READ-ONLY, 227 | kind TYPE cpattrkind READ-ONLY. 228 | 229 | ENDCLASS. "lcl_external_code_page DEFINITION 230 | 231 | 232 | ************************************************************************ 233 | * Class LCL_UI5_REPOSITORY 234 | * 235 | * represents a UI5 Repository and the UI5 application it contains. 236 | ************************************************************************ 237 | CLASS lcl_ui5_repository DEFINITION FINAL CREATE PRIVATE. 238 | 239 | PUBLIC SECTION. 240 | CLASS-DATA: message TYPE string, 241 | debug_conversions_for_file TYPE string VALUE ''. 242 | TYPES: BEGIN OF upload_parameters, 243 | description TYPE string, 244 | package TYPE devclass, 245 | transport_request TYPE trkorr, 246 | code_page_ui TYPE string, 247 | code_page_abap TYPE cpcodepage, 248 | code_page_java TYPE string, 249 | END OF upload_parameters, 250 | upload_operations TYPE TABLE OF REF TO lcl_operation. 251 | DATA: already_exists TYPE abap_bool, 252 | api TYPE REF TO /ui5/if_ui5_rep_dt, 253 | binary_file_identification_msg TYPE string, 254 | binary_file_patterns TYPE TABLE OF string, 255 | name TYPE string, 256 | text_file_identification_msg TYPE string, 257 | text_file_patterns TYPE TABLE OF string, 258 | ignores TYPE TABLE OF string, 259 | ignores_identification_msg TYPE string. 260 | CLASS-METHODS: class_constructor, 261 | get_instance IMPORTING ir_log_messages TYPE REF TO string_table 262 | RETURNING VALUE(rv_self) TYPE REF TO lcl_ui5_repository, 263 | evaluate_authorization RETURNING VALUE(rv_message) TYPE string. 264 | METHODS: conciliate_upload_operations IMPORTING iv_path TYPE string DEFAULT '' 265 | iv_delta_mode TYPE abap_bool 266 | iv_badi TYPE REF TO lcl_badi 267 | iv_archive TYPE REF TO lcl_sapui5_zip_archive 268 | CHANGING cv_upload_operations TYPE upload_operations, 269 | get_mime_type_for_upload IMPORTING iv_operation TYPE REF TO lcl_operation 270 | RETURNING VALUE(rv_mime_type) TYPE string, 271 | set_name IMPORTING iv_name TYPE string. 272 | 273 | PRIVATE SECTION. 274 | * METHODS: 275 | * is_binary_file IMPORTING iv_file_path TYPE string 276 | * RETURNING value(rv_is_binary_file) TYPE abap_bool, 277 | * is_file_to_be_ignored IMPORTING iv_file_path TYPE string 278 | * RETURNING value(rv_ignore) TYPE abap_bool, 279 | * is_text_file IMPORTING iv_file_path TYPE string 280 | * RETURNING value(rv_is_text_file) TYPE abap_bool. 281 | CLASS-DATA: self TYPE REF TO lcl_ui5_repository. 282 | DATA: log_messages_ref TYPE REF TO string_table. 283 | 284 | ENDCLASS. "lcl_ui5_repository DEFINITION 285 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.yui5_repository_load_http.abap: -------------------------------------------------------------------------------- 1 | FUNCTION yui5_repository_load_http. 2 | *"---------------------------------------------------------------------- 3 | *"*"Local Interface: 4 | *" IMPORTING 5 | *" VALUE(IV_URL) TYPE STRING 6 | *" VALUE(IV_SAPUI5_APPLICATION_NAME) TYPE STRING DEFAULT '' 7 | *" VALUE(IV_SAPUI5_APPLICATION_DESC) TYPE STRING DEFAULT '' 8 | *" VALUE(IV_PACKAGE) TYPE DEVCLASS DEFAULT '' 9 | *" VALUE(IV_WORKBENCH_REQUEST) TYPE TRKORR DEFAULT '' 10 | *" VALUE(IV_EXTERNAL_CODE_PAGE) TYPE STRING DEFAULT '' 11 | *" VALUE(IV_ACCEPT_UNIX_STYLE_EOL) TYPE BOOLEAN DEFAULT '-' 12 | *" VALUE(IV_DELTA_MODE) TYPE BOOLEAN DEFAULT '-' 13 | *" VALUE(IV_TEST_MODE) TYPE BOOLEAN DEFAULT '' 14 | *" VALUE(IV_ZIP_FILE) TYPE XSTRING OPTIONAL 15 | *" EXPORTING 16 | *" VALUE(EV_SUCCESS) TYPE CHAR1 17 | *" VALUE(EV_LOG_MESSAGES) TYPE STRING_TABLE 18 | *" VALUE(EV_MSG_ID) TYPE SY-MSGID 19 | *" VALUE(EV_MSG_NO) TYPE SY-MSGNO 20 | *"---------------------------------------------------------------------- 21 | ************************************************************************ 22 | *--------------------------------------------------------------------* 23 | * This function module is pretty much a copy of SAP provided function 24 | * module /UI5/UI5_REPOSITORY_LOAD_HTTP with minor changes to support 25 | * input of a .zip file as an alternative to a URL. 26 | * 27 | * The doco for /UI5/UI5_REPOSITORY_LOAD_HTTP follows which describes 28 | * the standard input parameters and how this function module works 29 | * and how to use the .Ui5 parameter files to influence the behaviour. 30 | * 31 | *--------------------------------------------------------------------* 32 | * 33 | * The function module /UI5/UI5_REPOSITORY_LOAD_HTTP loads a SAPUI5 34 | * application accessible at IV_URL into a SAPUI5 ABAP repository. 35 | * 36 | * Remarks: 37 | * 38 | * > As a mandatory input parameter the source url (IV_URL) has to be 39 | * passed. It points to a ZIP archive containing the SAPUI5 application 40 | * to be loaded into the SAPUI5 ABAP repository. 41 | * 42 | * > The parameter IV_TEST mode triggers a test run in which no upload 43 | * takes place. The export parameter EV_LOG_MESSAGES holds a detailed 44 | * log then. 45 | * 46 | * Use the test mode to investigate behavior of the function module 47 | * you did not expect. 48 | * 49 | * > Further parameters are taken preferably from the function module's 50 | * import parameters or from the file .Ui5RepositoryUploadParameters 51 | * located in the archive. 52 | * 53 | * As an advantage the function module can be started easily with a 54 | * set of documented standard parameters 55 | * e.g. automatically in the context of a Maven build process. 56 | * 57 | * > If you specify a parameter in the parameter file, you need 58 | * to place ist value in a line having the form 59 | * = 60 | * 61 | * Examples: SAPUI5ApplicationName=UI5_HCM_LR_APV 62 | * AcceptUnixStyleEol=True or X or Yes or 1 63 | * 64 | * > Overview of input parameters: 65 | * 66 | * --------------------------------------------------------------------------------------------------------------------- 67 | * Parameter Name Name Mandatory Default Remark 68 | * for use in in signature 69 | * parameter file of function module 70 | * --------------------------------------------------------------------------------------------------------------------- 71 | * % IV_URL Yes % Url needs to point to valid 72 | * zip archive. 73 | * SAPUI5ApplicationName IV_SAPUI5_APPLICATION_NAME Yes % App may be created or updated 74 | * SAPUI5ApplicationDescription IV_SAPUI5_APPLICATION_DESC No Used when app is to be created 75 | * in the SAPUI5 ABAP repository. 76 | * SAPUI5ApplicationPackage IV_PACKAGE No '$TMP' 77 | * WorkbenchRequest IV_WORKBENCH_REQUEST Depends Needed in case package is not $TMP. 78 | * ExternalCodePage IV_EXTERNAL_CODE_PAGE Depends Codepage Needed in case SAPGUI not installed. 79 | * of SAPGUI E.g. "Cp1252" for Windows Standard 80 | * AcceptUnixStyleEol IV_ACCEPT_UNIX_STYLE_EOL No ABAP_TRUE Triggers automatic conversion 81 | * of unix style text files to the 82 | * Windows format expected by the 83 | * repository. 84 | * DeltaMode IV_DELTA_MODE No ABAP_FALSE Only changes to current state in 85 | * the repository get registered 86 | * in workbench request. 87 | * % IV_TEST_MODE No ABAP_FALSE Upload operation is skipped then. 88 | * --------------------------------------------------------------------------------------------------------------------- 89 | * Legend: '%' means 'None" 90 | * --------------------------------------------------------------------------------------------------------------------- 91 | * 92 | * > Use the export variable EV_SUCCESS to check if the operation 93 | * was successful ('S'), a warning was indicated ('W') or an error 94 | * happened ('E'). 95 | * 96 | * In addition EV_MSG_ID and EV_MSG_NO give access to a message 97 | * with the outcome of the function call. 98 | * 99 | * Have a look into the output EV_LOG_MESSAGES for the details. 100 | * 101 | * > In order to further control the upload operation you may place the 102 | * text files '.Ui5RepositoryIgnore', '.Ui5RepositoryTextFiles' or 103 | * '.Ui5RepositoryTextFiles' in the archive. 104 | * 105 | * Each line in '.Ui5RepositoryIgnore' describes a file pattern 106 | * indicating which files should be ignored during upload. The line 107 | * may contain a substring of the file path or a regular expression 108 | * starting with '^' and ending with '$'. This setting overwrites 109 | * the built-in default. 110 | * 111 | * Create or change the files '.Ui5RepositoryTextFiles' or 112 | * '.Ui5RepositoryTextFiles' used to identify text and binary content 113 | * in addition to the built-in default. 114 | * 115 | * > You may use the reports /UI5/UI5_REPOSITORY_LOAD_HTTP and 116 | * /UI5/UI5_REPOSITORY_LOAD_HTTPN to operate this function module 117 | * interactivly or to schedule its operation. 118 | * 119 | * /UI5/UI5_REPOSITORY_LOAD_HTTP is for the upload of a single app. 120 | * /UI5/UI5_REPOSITORY_LOAD_HTTPN may handle more than one app. 121 | * 122 | * A jenkins plugin which allows integration in a Maven build 123 | * process is being developed. 124 | * 125 | * > In order to up- and download SAPUI5 applications to and from the 126 | * file system you may use the report /UI5/UI5_REPOSITORY_LOAD. 127 | * 128 | * > Find SAP internal information here: 129 | * http://vesapui5.dhcp.wdf.sap.corp:1080/trac/sapui5.tools/wiki/SAPUI5Tools/UI5RepositoryLoadFaq 130 | 131 | ************************************************************************ 132 | * Check inputs 133 | ************************************************************************ 134 | 135 | * Initialize 136 | ev_success = status_success. 137 | * 138 | DATA: message TYPE string, 139 | empty_line TYPE string, 140 | parameter TYPE string. 141 | empty_line = '.'. 142 | APPEND TEXT-001 TO ev_log_messages. "***** Upload of SAPUI5 Application from ZIP-Archive into SAPUI5 ABAP Repository ***** 143 | APPEND empty_line TO ev_log_messages. 144 | 145 | * Debugging conversions for a specific file 146 | * ... In case you would like to debug: 147 | * Specify resource name here - e.g. 'utils.js' 148 | lcl_ui5_repository=>debug_conversions_for_file = ''. 149 | "lcl_ui5_repository=>debug_conversions_for_file = 'utils.js'. 150 | 151 | * Indicate test mode 152 | IF iv_test_mode = abap_true. 153 | APPEND TEXT-002 TO ev_log_messages. "* Running in test mode: Upload operations are skipped, Detailed Log * 154 | APPEND empty_line TO ev_log_messages. 155 | ELSE. 156 | APPEND TEXT-003 TO ev_log_messages. "* Running in regular mode: Brief Log * 157 | APPEND empty_line TO ev_log_messages. 158 | ENDIF. 159 | 160 | * Check Url to SAPUI5 application 161 | 162 | * ... Is not empty 163 | IF iv_url IS INITIAL AND iv_zip_file IS INITIAL. 164 | ev_success = status_error. 165 | APPEND TEXT-010 TO ev_log_messages. "* Upload canceled: Url to Zip File containing SAPUI5 App is missing. * 166 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 167 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 168 | EXIT. 169 | ENDIF. 170 | 171 | * ... Refers to zip file 172 | " IF iv_url NS '.zip'. 173 | " ev_success = abap_false. 174 | " message = text-010. APPEND message TO ev_log_messages. 175 | " EXIT. 176 | " ENDIF. 177 | 178 | * ... Points to valid archive 179 | DATA: sapui5_archive TYPE REF TO lcl_sapui5_zip_archive, 180 | log_messages_ref TYPE REF TO string_table. 181 | GET REFERENCE OF ev_log_messages INTO log_messages_ref. 182 | CREATE OBJECT sapui5_archive 183 | EXPORTING 184 | iv_url = iv_url 185 | iv_zip_file = iv_zip_file 186 | ir_log_messages = log_messages_ref. 187 | IF ( sapui5_archive->is_ok( ) = abap_false ). 188 | ev_success = status_error. 189 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 190 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 191 | EXIT. 192 | ENDIF. 193 | 194 | * Determine and check upload parameters 195 | 196 | * ... Name of SAPUI5 Repositiory 197 | * Take from import parameter or from zip archive file .Ui5RepositoryUploadParameters 198 | * Exit if no name given 199 | DATA: sapui5_application_name TYPE string, 200 | sapui5_application_desc TYPE string. 201 | sapui5_application_name = iv_sapui5_application_name. 202 | IF sapui5_application_name IS INITIAL. 203 | sapui5_application_name = sapui5_archive->get_upload_parameter('SAPUI5ApplicationName'). 204 | message = TEXT-026. ". %1 "%2" has been determined from the '.Ui5RepositoryUploadParameters' file 205 | ELSE. 206 | message = TEXT-027. ". %1 "%2" has been determined from the corresponding import parameter 207 | ENDIF. 208 | REPLACE '%1' IN message WITH TEXT-100. "Name of SAPUI5 Application 209 | REPLACE '%2' IN message WITH sapui5_application_name. 210 | 211 | IF sapui5_application_name IS NOT INITIAL. 212 | APPEND message TO ev_log_messages. 213 | ELSE. 214 | ev_success = status_error. 215 | APPEND TEXT-015 TO ev_log_messages. "Specify SAPUI5 Application Name 216 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 217 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 218 | EXIT. 219 | ENDIF. 220 | 221 | * ... Access SAPUI5 ABAP Repository 222 | DATA: ui5_repository TYPE REF TO lcl_ui5_repository. 223 | ui5_repository = lcl_ui5_repository=>get_instance( ir_log_messages = log_messages_ref ). 224 | ui5_repository->set_name( sapui5_application_name ). 225 | IF ui5_repository->name IS INITIAL. "this indicates an invalid name 226 | ev_success = status_error. 227 | APPEND TEXT-090 TO ev_log_messages. "* Name of SAPUI5 Application appears to be invalid: Same rules as for BSP applications apply 228 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 229 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 230 | EXIT. 231 | ENDIF. 232 | 233 | * ... Description of SAPUI5 repository 234 | * is used if repository does not yet exist. 235 | IF ui5_repository->already_exists = abap_false. 236 | sapui5_application_desc = iv_sapui5_application_desc. 237 | IF sapui5_application_desc IS NOT INITIAL. 238 | message = TEXT-027. 239 | ENDIF. 240 | IF sapui5_application_desc IS INITIAL. 241 | sapui5_application_desc = sapui5_archive->get_upload_parameter('SAPUI5ApplicationDescription'). 242 | IF sapui5_application_desc IS NOT INITIAL. 243 | message = TEXT-026. 244 | ENDIF. 245 | ENDIF. 246 | IF sapui5_application_desc IS NOT INITIAL. 247 | REPLACE '%1' IN message WITH TEXT-101. "Description of SAPUI5 Application 248 | REPLACE '"%2" ' IN message WITH ''. 249 | CONDENSE message. "Remove double spaces 250 | APPEND message TO ev_log_messages. 251 | ENDIF. 252 | ENDIF. 253 | 254 | * ... Package for SAPUI5 application 255 | * is defaulted to $TMP if not specified elsewhere 256 | DATA: application_package TYPE string. 257 | application_package = iv_package. 258 | IF application_package IS NOT INITIAL. 259 | message = TEXT-027. ". %1 "%2" has been determined from the corresponding import parameter. 260 | ENDIF. 261 | IF application_package IS INITIAL. 262 | application_package = sapui5_archive->get_upload_parameter('SAPUI5ApplicationPackage'). 263 | IF application_package IS NOT INITIAL. 264 | message = TEXT-026. ". %1 "%2" has been determined from the '.Ui5RepositoryUploadParameters' file. 265 | ENDIF. 266 | ENDIF. 267 | IF application_package IS NOT INITIAL. 268 | REPLACE '%1' IN message WITH TEXT-103. "Package of SAPUI5 Application 269 | REPLACE '%2' IN message WITH application_package. 270 | APPEND message TO ev_log_messages. 271 | ENDIF. 272 | IF application_package IS INITIAL. 273 | application_package = '$TMP'. 274 | message = TEXT-036. 275 | APPEND message TO ev_log_messages. 276 | ENDIF. 277 | 278 | * Package needs to be specified if repository already exists. 279 | * ... should not happen as package is defaulted 280 | IF ui5_repository->already_exists = abap_false 281 | AND application_package IS INITIAL. 282 | ev_success = status_error. 283 | message = TEXT-017. APPEND message TO ev_log_messages. "* Repository Package is not definded * 284 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 285 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 286 | EXIT. 287 | ENDIF. 288 | 289 | * Workbench request 290 | * ... may be empty if package is $TMP (local) 291 | DATA: repository_workbench_request TYPE string. 292 | repository_workbench_request = iv_workbench_request. 293 | IF repository_workbench_request IS NOT INITIAL. 294 | message = TEXT-027. 295 | ENDIF. 296 | IF repository_workbench_request IS INITIAL. 297 | repository_workbench_request = sapui5_archive->get_upload_parameter('WorkbenchRequest'). 298 | IF repository_workbench_request IS NOT INITIAL. 299 | message = TEXT-026. 300 | ENDIF. 301 | ENDIF. 302 | IF repository_workbench_request IS NOT INITIAL. 303 | REPLACE '%1' IN message WITH TEXT-104. "Workbench Request 304 | REPLACE '%2' IN message WITH repository_workbench_request. 305 | APPEND message TO ev_log_messages. 306 | ELSE. 307 | IF application_package NE '$TMP'. 308 | ev_success = status_error. 309 | message = TEXT-016. "* Upload canceled: ABAP workbench request for SAPUI5 ABAP Repository not specified. * 310 | APPEND message TO ev_log_messages. 311 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 312 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 313 | EXIT. 314 | ENDIF. 315 | ENDIF. 316 | 317 | * External code page of text files in archive 318 | DATA: external_code_page_name TYPE string. 319 | external_code_page_name = iv_external_code_page. 320 | IF external_code_page_name IS NOT INITIAL. 321 | message = TEXT-027. 322 | ENDIF. 323 | IF external_code_page_name IS INITIAL. 324 | external_code_page_name = sapui5_archive->get_upload_parameter('ExternalCodePage'). 325 | IF external_code_page_name IS NOT INITIAL. 326 | message = TEXT-026. 327 | ENDIF. 328 | ENDIF. 329 | IF external_code_page_name IS NOT INITIAL. 330 | REPLACE '%1' IN message WITH TEXT-105. "External Code Page 331 | REPLACE '%2' IN message WITH external_code_page_name. 332 | APPEND message TO ev_log_messages. 333 | ELSE. 334 | DATA: lv_ex TYPE REF TO cx_root. 335 | TRY. 336 | DATA: ecp TYPE REF TO lcl_external_code_page. 337 | ecp = lcl_external_code_page=>for_sapgui_installation( ). 338 | external_code_page_name = ecp->get_java_encoding( ). 339 | message = TEXT-018. "* Code page has been set to % * 340 | REPLACE '%' IN message WITH external_code_page_name. 341 | APPEND message TO ev_log_messages. 342 | CATCH lcx_exception INTO lv_ex. 343 | ev_success = status_error. 344 | message = TEXT-091. "* Upload canceled: External code page has not been specified. * 345 | APPEND message TO ev_log_messages. 346 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 347 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 348 | EXIT. 349 | ENDTRY. 350 | ENDIF. 351 | 352 | * Accept unix style line endings 353 | * ... default to ABAP_TRUE 354 | DATA: accept_unix_style_line_endings TYPE abap_bool. 355 | accept_unix_style_line_endings = iv_accept_unix_style_eol. 356 | IF accept_unix_style_line_endings NE abap_undefined. 357 | message = TEXT-027. ". %1 "%2" has been determined from the corresponding import parameter. 358 | ELSE. 359 | parameter = 360 | sapui5_archive->get_upload_parameter( iv_key = 'AcceptUnixStyleEol' 361 | iv_return_if_not_specified = '-' ). 362 | accept_unix_style_line_endings = lcl_function=>text_to_abap_bool( parameter ). 363 | IF accept_unix_style_line_endings NE abap_undefined. 364 | message = TEXT-026. ". %1 "%2" has been determined from the '.Ui5RepositoryUploadParameters' file. 365 | ENDIF. 366 | ENDIF. 367 | IF accept_unix_style_line_endings NE abap_undefined. 368 | REPLACE '%1' IN message WITH TEXT-106. "Acceptance of Unix style line delimeters in text files 369 | REPLACE '"%2" ' IN message WITH ''. CONDENSE message. 370 | APPEND message TO ev_log_messages. 371 | ELSE. 372 | accept_unix_style_line_endings = abap_true. 373 | ENDIF. 374 | * ... Indicate 375 | IF accept_unix_style_line_endings = abap_true. 376 | message = TEXT-037. "Unix style end of line markers in text files get accepted. 377 | ELSE. 378 | message = TEXT-038. "Unix style end of line markers in text files get rejected. 379 | ENDIF. 380 | APPEND message TO ev_log_messages. 381 | 382 | * Delta mode 383 | DATA: delta_mode TYPE abap_bool. 384 | * ... Determine from function parameter or upload parameter file 385 | delta_mode = iv_delta_mode. 386 | IF delta_mode = abap_undefined. 387 | parameter = 388 | sapui5_archive->get_upload_parameter( iv_key = 'DeltaMode' 389 | iv_return_if_not_specified = '-' ). 390 | delta_mode = lcl_function=>text_to_abap_bool( parameter ). 391 | ENDIF. 392 | * ... Delta-mode off if not specified. 393 | IF delta_mode = abap_undefined. 394 | delta_mode = abap_false. 395 | ENDIF. 396 | * ... Indicate Delta Mode 397 | IF delta_mode = abap_true. 398 | message = TEXT-034. ". The delta mode has been turned on. 399 | ELSE. 400 | message = TEXT-035. ". The delta mode has been turned off. 401 | ENDIF. 402 | APPEND message TO ev_log_messages. 403 | 404 | * ... Indicate if BAdI /UI5/BADI_PREVENT_DELETION to prevent the deletion of mime objects 405 | * has been implemented: This SAP internal BAdI may cause inconsistencies between 406 | * the app beeing uploaded and the SAPUI5 ABAP repository 407 | DATA: badi_to_prevent_deletion TYPE REF TO lcl_badi, 408 | workbench_request TYPE trkorr. 409 | workbench_request = repository_workbench_request. 410 | CREATE OBJECT badi_to_prevent_deletion 411 | EXPORTING 412 | iv_test_mode = iv_test_mode 413 | iv_sapui5_application_name = sapui5_application_name 414 | iv_workbench_request = workbench_request. 415 | IF badi_to_prevent_deletion->implementation IS NOT INITIAL. 416 | APPEND TEXT-039 TO ev_log_messages. ". Attention: A BAdI implementation for /UI5/BADI_PREVENT_DELETION is active 417 | ENDIF. 418 | 419 | * 420 | APPEND empty_line TO ev_log_messages. 421 | 422 | 423 | ************************************************************************ 424 | * Determine upload operations 425 | ************************************************************************ 426 | 427 | "message = text-041. "* Analyzing Archive * 428 | "append message to ev_log_messages. 429 | 430 | TYPES: operations TYPE TABLE OF REF TO lcl_operation. 431 | DATA: load_operations TYPE operations. 432 | sapui5_archive->determine_upload_operations( EXPORTING iv_delta_mode = delta_mode 433 | iv_code_page = external_code_page_name 434 | iv_accept_unix_style_eol = accept_unix_style_line_endings 435 | CHANGING cv_load_operations = load_operations 436 | cv_success = ev_success ). 437 | 438 | ************************************************************************ 439 | * Explore SAPUI5 application to upload and conciliate operations 440 | ************************************************************************ 441 | 442 | * Conciliate 443 | workbench_request = repository_workbench_request. 444 | ui5_repository->conciliate_upload_operations( EXPORTING iv_delta_mode = delta_mode 445 | iv_badi = badi_to_prevent_deletion 446 | iv_archive = sapui5_archive 447 | CHANGING cv_upload_operations = load_operations ). 448 | 449 | * Estimate authorization 450 | DATA: authorization_warning TYPE string. 451 | authorization_warning = ui5_repository->evaluate_authorization( ). 452 | IF authorization_warning IS NOT INITIAL. 453 | APPEND authorization_warning TO ev_log_messages. 454 | APPEND empty_line TO ev_log_messages. 455 | ENDIF. 456 | 457 | * Return if in test mode or in case an error occurred 458 | DATA: upload_operation TYPE REF TO lcl_operation. 459 | IF iv_test_mode = abap_true OR badi_to_prevent_deletion->error_occurred = abap_true. 460 | 461 | * List operations 462 | message = TEXT-040. "* Operations % * 463 | APPEND message TO ev_log_messages. 464 | LOOP AT load_operations INTO upload_operation. 465 | message = upload_operation->create_log_message( ). 466 | IF message IS INITIAL. CONTINUE. ENDIF. 467 | CONCATENATE '. ' message INTO message RESPECTING BLANKS. 468 | APPEND message TO ev_log_messages. 469 | ENDLOOP. 470 | 471 | * Inidicate BAdI error if occurred 472 | IF badi_to_prevent_deletion->error_occurred = abap_true. 473 | ev_success = status_error. 474 | APPEND empty_line TO ev_log_messages. 475 | APPEND TEXT-093 TO ev_log_messages. "* Upload canceled: A BAdI error has occurred. * 476 | CONCATENATE '. ' badi_to_prevent_deletion->error_text INTO message RESPECTING BLANKS. 477 | APPEND message TO ev_log_messages. 478 | ENDIF. 479 | 480 | * Return message 481 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 482 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 483 | EXIT. 484 | ENDIF. 485 | 486 | 487 | ************************************************************************ 488 | * Upload application 489 | ************************************************************************ 490 | 491 | ***** Prepare upload parameters **************************************** 492 | 493 | * Description 494 | DATA: upload_parameters TYPE lcl_ui5_repository=>upload_parameters. 495 | upload_parameters-description = sapui5_application_desc. 496 | 497 | * Package 498 | upload_parameters-package = application_package. 499 | 500 | * Transport_request 501 | upload_parameters-transport_request = repository_workbench_request. 502 | 503 | * Code page 504 | upload_parameters-code_page_ui = external_code_page_name. 505 | TRY. 506 | ecp = lcl_external_code_page=>create( upload_parameters-code_page_ui ). 507 | upload_parameters-code_page_abap = ecp->get_abap_encoding( ). 508 | upload_parameters-code_page_java = ecp->get_java_encoding( ). 509 | 510 | * Confirm valid code page has been entered. 511 | IF upload_parameters-code_page_abap IS INITIAL. 512 | ev_success = status_error. 513 | APPEND TEXT-032 TO ev_log_messages. "* Upload canceled: External Code Page is invalid. You may use e.g. 'Cp1252' * 514 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 515 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 516 | EXIT. 517 | ENDIF. 518 | 519 | CATCH cx_root. 520 | 521 | * General code page problem 522 | ev_success = status_error. 523 | APPEND TEXT-033 TO ev_log_messages. "* Upload canceled: Code Page is invalid. * 524 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 525 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 526 | EXIT. 527 | 528 | ENDTRY. 529 | 530 | ***** Create SAPUI5 ABAP repository if neccessary ********************* 531 | 532 | IF ui5_repository->already_exists = abap_false. 533 | 534 | * Message 535 | message = TEXT-028. "* Creating new SAPUI5 application % * 536 | REPLACE '%' IN message WITH ui5_repository->name. 537 | APPEND message TO ev_log_messages. 538 | 539 | * Delegate ... 540 | DATA: lv_ex_rep_dt TYPE REF TO /ui5/cx_ui5_rep_dt. 541 | TRY. 542 | ui5_repository->api = 543 | /ui5/cl_ui5_rep_dt=>/ui5/if_ui5_rep_dt~create_repository( 544 | iv_name = ui5_repository->name 545 | iv_description = upload_parameters-description 546 | iv_devclass = upload_parameters-package 547 | iv_transport_request = upload_parameters-transport_request 548 | iv_dialog_mode = space ). 549 | 550 | CATCH /ui5/cx_ui5_rep_dt INTO lv_ex_rep_dt. 551 | * Cleanup 552 | IF ui5_repository->api IS NOT INITIAL. CLEAR ui5_repository->api. ENDIF. 553 | 554 | * If any: write error text on log 555 | ev_success = status_error. 556 | DATA: text TYPE string. 557 | text = lv_ex_rep_dt->get_text( ). 558 | IF text IS NOT INITIAL. 559 | CONCATENATE '* ' text ' *' INTO text RESPECTING BLANKS. 560 | APPEND text TO ev_log_messages. 561 | ENDIF. 562 | APPEND TEXT-030 TO ev_log_messages. "* SAPUI5 application has not been created (successfully) * 563 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 564 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 565 | EXIT. 566 | ENDTRY. 567 | ENDIF. 568 | 569 | * Update message if repository does already exist 570 | IF ui5_repository->already_exists = abap_true. 571 | message = TEXT-029. "* Updating existing SAPUI5 application % * 572 | REPLACE '%' IN message WITH ui5_repository->name. 573 | APPEND message TO ev_log_messages. 574 | ENDIF. 575 | 576 | ***** Perform upload *************************************************** 577 | 578 | * Perform upload operation and write log entry 579 | TRY. 580 | ui5_repository->api->lock( ). 581 | CATCH /ui5/cx_ui5_rep_dt. 582 | ev_success = status_error. 583 | APPEND TEXT-092 TO ev_log_messages. "* Upload canceled: Unable to lock SAPUI5 repository * 584 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 585 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 586 | EXIT. 587 | ENDTRY. 588 | 589 | ***** Loop at each operation ***** 590 | * and if requested ... 591 | DATA: lv_message TYPE string. 592 | LOOP AT load_operations INTO upload_operation. 593 | 594 | * Continue if nothing to do 595 | IF delta_mode EQ abap_true 596 | AND upload_operation->to_update NE abap_true. 597 | CONTINUE. 598 | ENDIF. 599 | 600 | CASE upload_operation->operation. 601 | 602 | ***** Create folder ***** 603 | 604 | WHEN lcl_operation=>create_folder. 605 | 606 | TRY. 607 | ui5_repository->api->create_folder( iv_path = upload_operation->relative_path 608 | iv_transport_request = upload_parameters-transport_request ). 609 | CATCH /ui5/cx_ui5_rep_dt. 610 | lv_message = '* Warning: Folder % has not been created *'(054). 611 | REPLACE '%' IN lv_message WITH upload_operation->relative_path. 612 | APPEND lv_message TO ev_log_messages. 613 | ENDTRY. 614 | 615 | ***** Upload text or binary file **** 616 | 617 | WHEN lcl_operation=>upload_file. 618 | IF ( upload_operation->object_type = lcl_operation=>object_type_text_file 619 | OR upload_operation->object_type = lcl_operation=>object_type_binary_file ). 620 | TRY. 621 | 622 | * Read file from archive 623 | DATA: file_content TYPE xstring. 624 | DATA: upload_operation_is_binary TYPE abap_bool. 625 | upload_operation_is_binary = upload_operation->is_binary( ). 626 | file_content = sapui5_archive->read_file( iv_path = upload_operation->full_path ). 627 | "file_content = file_system->read_file( iv_file_path = upload_operation->full_path 628 | " iv_file_is_binary = upload_operation_is_binary 629 | " iv_code_page_abap = upload_parameters-code_page_abap ). 630 | 631 | * Convert line endings of text files from unix to windows format 632 | * ... if needed and requested 633 | IF upload_operation->object_type = lcl_operation=>object_type_text_file 634 | AND upload_operation->eol_conversion = abap_true 635 | AND accept_unix_style_line_endings = abap_true. 636 | DATA: file_content_as_is TYPE string, 637 | file_content_as_string TYPE string, 638 | file_content_as_string_windows TYPE string. 639 | TRY. 640 | file_content_as_is = file_content. 641 | file_content_as_string = 642 | /ui5/cl_ui5_rep_utility=>convert_xstring_2_string( iv_xstring = file_content 643 | iv_code_page = upload_operation->code_page ). 644 | file_content_as_string_windows = 645 | lcl_function=>conv_unix_style_line_endings( iv_string = file_content_as_string ). 646 | file_content = 647 | /ui5/cl_ui5_rep_utility=>convert_string_2_xstring( iv_string = file_content_as_string_windows 648 | iv_code_page = upload_operation->code_page ). 649 | CATCH /ui5/cx_ui5_rep_dt. 650 | CATCH cx_sy_conversion_error. 651 | ev_success = status_error. 652 | file_content = file_content_as_is. 653 | lv_message = '* Error: Unable to convert Unix style text file % *'(057). 654 | REPLACE '%' IN lv_message WITH upload_operation->relative_path. 655 | APPEND lv_message TO ev_log_messages. 656 | ENDTRY. 657 | ENDIF. 658 | 659 | * Upload content into ui5 repository 660 | DATA: mime_type TYPE string. 661 | mime_type = ui5_repository->get_mime_type_for_upload( upload_operation ). 662 | upload_operation_is_binary = upload_operation->is_binary( ). 663 | TRY. 664 | CALL METHOD ui5_repository->api->put_file 665 | EXPORTING 666 | iv_path = upload_operation->relative_path 667 | iv_transport_request = upload_parameters-transport_request 668 | iv_file_content = file_content 669 | iv_mime_type = mime_type "ui5_repository->get_mime_type_for_upload( upload_operation ) 670 | iv_code_page = upload_parameters-code_page_java 671 | iv_is_binary = upload_operation_is_binary. "upload_operation->is_binary( ). 672 | lv_message = upload_operation->create_log_message( ). 673 | APPEND lv_message TO ev_log_messages. 674 | 675 | * Put content of version.json as log message: 676 | * No more than 15 lines with a maximum length of 120 characters 677 | IF upload_operation->full_path CS 'version.json' 678 | AND upload_operation_is_binary = abap_false. "#EC NOTEXT 679 | TRY. 680 | * Convert to windows format 681 | file_content_as_is = file_content. 682 | file_content_as_string = 683 | /ui5/cl_ui5_rep_utility=>convert_xstring_2_string( iv_xstring = file_content 684 | iv_code_page = upload_operation->code_page ). 685 | file_content_as_string_windows = 686 | lcl_function=>conv_unix_style_line_endings( iv_string = file_content_as_string ). 687 | * Retrieve lines 688 | DATA: lines TYPE o2pageline_table. 689 | lines = /ui5/cl_ui5_rep_utility=>code_string_2_code_tab( iv_src_string = file_content_as_string_windows ). 690 | * Prepare and write lines 691 | IF lines( lines ) < 15. 692 | LOOP AT lines INTO lv_message. 693 | "Mini escaping and beautification 694 | REPLACE ALL OCCURRENCES OF '<' IN lv_message WITH '<'. "#EC NOTEXT 695 | REPLACE ALL OCCURRENCES OF '>' IN lv_message WITH '>'. "#EC NOTEXT 696 | REPLACE ALL OCCURRENCES OF '"' IN lv_message WITH ''. "#EC NOTEXT 697 | REPLACE ALL OCCURRENCES OF '"' IN lv_message WITH ''. "#EC NOTEXT 698 | IF strlen( lv_message ) > 120. 699 | lv_message = lv_message(120). 700 | CONCATENATE lv_message ' ...' INTO lv_message RESPECTING BLANKS. "#EC NOTEXT 701 | ENDIF. 702 | CONCATENATE '. ' lv_message INTO lv_message RESPECTING BLANKS. "#EC NOTEXT 703 | APPEND lv_message TO ev_log_messages. 704 | ENDLOOP. 705 | ENDIF. 706 | CATCH cx_root . 707 | ENDTRY. 708 | ENDIF. 709 | 710 | CATCH /ui5/cx_ui5_rep_dt INTO lv_ex_rep_dt. 711 | * Write error message for UI5 repository problems 712 | text = lv_ex_rep_dt->get_text( ). 713 | CONCATENATE '* ' text ' *' INTO lv_message RESPECTING BLANKS. 714 | APPEND lv_message TO ev_log_messages. 715 | RAISE EXCEPTION TYPE lcx_exception. 716 | ENDTRY. 717 | 718 | CATCH lcx_exception. 719 | * Write error message for UI5 repository problems 720 | IF upload_operation->is_binary( ) = abap_true. 721 | lv_message = '* Warning: Text file % has not been uploaded *'(055). 722 | ELSEIF upload_operation->is_binary( ) = abap_false. 723 | lv_message = '* Warning: Binary file % has not been uploaded *'(064). 724 | ENDIF. 725 | REPLACE '%' IN lv_message WITH upload_operation->relative_path. 726 | APPEND lv_message TO ev_log_messages. 727 | IF ev_success = status_success. "Keep status error 728 | ev_success = status_warning. 729 | ENDIF. 730 | ENDTRY. 731 | ENDIF. 732 | 733 | * Delete file/folder in UI5 repository 734 | WHEN lcl_operation=>delete_file OR 735 | lcl_operation=>delete_folder. 736 | TRY. 737 | ui5_repository->api->delete( iv_path = upload_operation->relative_path 738 | iv_transport_request = upload_parameters-transport_request ). 739 | lv_message = upload_operation->create_log_message( ). " 740 | APPEND lv_message TO ev_log_messages. " 741 | CATCH /ui5/cx_ui5_rep_dt INTO lv_ex_rep_dt. 742 | * Write error message for UI5 repository problems 743 | text = lv_ex_rep_dt->get_text( ). 744 | CONCATENATE '* ' text ' *' INTO lv_message RESPECTING BLANKS. 745 | APPEND lv_message TO ev_log_messages. 746 | ENDTRY. 747 | 748 | ***** Indicate files and folders being ignored ***** 749 | 750 | * Ignore file 751 | * Ignore folder 752 | WHEN lcl_operation=>ignore_file OR 753 | lcl_operation=>ignore_folder. 754 | lv_message = upload_operation->create_log_message( ). 755 | APPEND lv_message TO ev_log_messages. 756 | 757 | ENDCASE. 758 | ENDLOOP. 759 | 760 | * Unlock SAPUI5 repository 761 | TRY. 762 | ui5_repository->api->unlock( ). 763 | CATCH /ui5/cx_ui5_rep_dt. 764 | ENDTRY. 765 | 766 | ************* Recalculate application index and write log messages********************************* 767 | 768 | IF iv_test_mode NE abap_true. 769 | 770 | DATA: lr_app_index TYPE REF TO /ui5/cl_ui5_app_index. 771 | DATA: lv_application TYPE o2applname. 772 | DATA: lt_messages TYPE bapiret2_t. 773 | DATA: lv_log_msg TYPE string. 774 | 775 | FIELD-SYMBOLS: TYPE bapiret2. 776 | 777 | lr_app_index = /ui5/cl_ui5_app_index=>get_instance( ). 778 | 779 | lv_application = sapui5_application_name. 780 | 781 | CALL METHOD lr_app_index->recalculate_app 782 | EXPORTING 783 | iv_application = lv_application 784 | IMPORTING 785 | * es_result = 786 | et_messages = lt_messages. 787 | 788 | * 789 | APPEND empty_line TO ev_log_messages. 790 | APPEND TEXT-111 TO ev_log_messages. 791 | 792 | LOOP AT lt_messages ASSIGNING . 793 | CONCATENATE TEXT-110 -message INTO lv_log_msg SEPARATED BY space. 794 | APPEND lv_log_msg TO ev_log_messages. 795 | ENDLOOP. 796 | 797 | IF lt_messages IS NOT INITIAL. 798 | APPEND TEXT-112 TO ev_log_messages. 799 | ENDIF. 800 | 801 | ENDIF. 802 | ******************************************************************************************* 803 | 804 | 805 | * Upload done 806 | APPEND empty_line TO ev_log_messages. 807 | APPEND TEXT-043 TO ev_log_messages. "* Done * 808 | 809 | * Set return message 810 | lcl_function=>set_return_msg( EXPORTING iv_success = ev_success iv_test_mode = iv_test_mode 811 | CHANGING cv_msg_id = ev_msg_id cv_msg_no = ev_msg_no ). 812 | 813 | 814 | ENDFUNCTION. 815 | -------------------------------------------------------------------------------- /src/ycl_github_deployer.clas.abap: -------------------------------------------------------------------------------- 1 | *----------------------------------------------------------------------* 2 | * CLASS YCL_GITHUB_DEPLOYER DEFINITION 3 | *----------------------------------------------------------------------* 4 | * Documentation is at http://yelcho.github.io/sapui5-deployer/ 5 | *----------------------------------------------------------------------* 6 | CLASS ycl_github_deployer DEFINITION 7 | PUBLIC 8 | FINAL 9 | CREATE PRIVATE . 10 | 11 | PUBLIC SECTION. 12 | 13 | CLASS-METHODS deploy 14 | IMPORTING 15 | !repository TYPE string 16 | !branch TYPE string 17 | !github_user TYPE string OPTIONAL 18 | !password TYPE string OPTIONAL 19 | !transport TYPE trkorr OPTIONAL 20 | !test_only TYPE boolean OPTIONAL . 21 | PROTECTED SECTION. 22 | private section. 23 | 24 | types: 25 | BEGIN OF submodule_info_type, 26 | folder TYPE string, 27 | repository TYPE string, 28 | branch TYPE string, 29 | END OF submodule_info_type . 30 | types: 31 | submodule_info_ttype TYPE STANDARD TABLE OF submodule_info_type . 32 | 33 | data REPOSITORY type STRING . 34 | data BRANCH type STRING . 35 | data TRANSPORT type TRKORR . 36 | data TEST_ONLY type BOOLEAN . 37 | data GITHUB_USER type STRING . 38 | data PASSWORD type STRING . 39 | data MINIFY_FILE_COUNT type I . 40 | data MINIFY_BYTE_COUNT type I . 41 | data ENABLE_MINIFY type BOOLEAN value ABAP_TRUE ##NO_TEXT. 42 | data JS_MINIFY_PARAMS type TIHTTPNVP . 43 | data CSS_MINIFY_PARAMS type TIHTTPNVP . 44 | 45 | methods CONSTRUCTOR 46 | importing 47 | !REPOSITORY type STRING 48 | !BRANCH type STRING 49 | !GITHUB_USER type STRING optional 50 | !PASSWORD type STRING optional 51 | !TRANSPORT type TRKORR optional 52 | !TEST_ONLY type BOOLEAN optional 53 | raising 54 | CX_SY_CREATE_DATA_ERROR . 55 | methods ADD_MODULE_TO_ARCHIVE 56 | importing 57 | !INFO type SUBMODULE_INFO_TYPE 58 | value(ARCHIVE) type ref to CL_ABAP_ZIP . 59 | methods CLEANUP_STRINGDATA 60 | importing 61 | !DATA_IN type STRING 62 | !NOGAPS type BOOLEAN optional 63 | returning 64 | value(DATA_OUT) type STRING . 65 | methods CLEANUP_XMLDATA 66 | importing 67 | !DATA_IN type STRING 68 | returning 69 | value(DATA_OUT) type STRING . 70 | methods GET_FILE_TYPE 71 | importing 72 | !IV_FILENAME type STRING 73 | returning 74 | value(RV_FILETYPE) type STRING . 75 | methods GET_CSS_MINIFY_PARAMS 76 | returning 77 | value(RT_PARAMS) type TIHTTPNVP . 78 | methods GET_JS_MINIFY_PARAMS 79 | returning 80 | value(RT_PARAMS) type TIHTTPNVP . 81 | methods GET_MODULE_ARCHIVE 82 | importing 83 | !URL type STRING 84 | returning 85 | value(ARCHIVE) type ref to CL_ABAP_ZIP . 86 | methods GET_SUBMODULE_INFO 87 | importing 88 | !IV_SUBMODULE_DATA type XSTRING 89 | exporting 90 | value(ET_SUBMODULE_INFO) type SUBMODULE_INFO_TTYPE . 91 | methods MINIFY 92 | importing 93 | !DATA_IN type XSTRING 94 | !FILE_TYPE type STRING 95 | returning 96 | value(DATA_OUT) type XSTRING . 97 | methods MINIFY_JS 98 | importing 99 | !DATA_IN type XSTRING 100 | returning 101 | value(DATA_OUT) type XSTRING . 102 | methods MINIFY_CSS 103 | importing 104 | !DATA_IN type XSTRING 105 | returning 106 | value(DATA_OUT) type XSTRING . 107 | methods REMOVE_COVER_FOLDER 108 | importing 109 | !ARCHIVE type ref to CL_ABAP_ZIP 110 | returning 111 | value(NEW_ARCHIVE) type ref to CL_ABAP_ZIP . 112 | methods SAVE_ARCHIVE_FILE 113 | importing 114 | !ARCHIVE type ref to CL_ABAP_ZIP . 115 | methods UPDATE_CACHEBUSTER . 116 | methods UPLOAD_ARCHIVE_INTO_ICF 117 | importing 118 | value(ARCHIVE) type ref to CL_ABAP_ZIP 119 | raising 120 | CX_SY_CREATE_DATA_ERROR . 121 | methods XSTRING_TO_STRING 122 | importing 123 | !IN type XSTRING 124 | returning 125 | value(OUT) type STRING . 126 | methods STRING_TO_XSTRING 127 | importing 128 | !IN type STRING 129 | returning 130 | value(OUT) type XSTRING . 131 | ENDCLASS. 132 | 133 | 134 | 135 | CLASS YCL_GITHUB_DEPLOYER IMPLEMENTATION. 136 | 137 | 138 | METHOD add_module_to_archive. 139 | 140 | DATA: lo_archive TYPE REF TO cl_abap_zip, 141 | ls_file LIKE LINE OF archive->files, 142 | lv_content TYPE xstring, 143 | lv_cdata TYPE string, 144 | lv_preload_namespace TYPE string, 145 | lt_preload_modules TYPE tihttpnvp, 146 | lr_preload_module TYPE REF TO ihttpnvp, 147 | lv_component TYPE string, 148 | lv_junk TYPE string ##needed. 149 | 150 | WRITE:/, `Adding module`, info-repository, info-branch, 'to archive'. 151 | 152 | lo_archive = remove_cover_folder( get_module_archive( |https://github.com/{ info-repository }/zipball/{ info-branch }| ) ). 153 | 154 | IF lo_archive IS NOT BOUND. 155 | WRITE:/, `Error with module`, info-repository, info-branch COLOR COL_NEGATIVE. 156 | RETURN. 157 | ENDIF. 158 | 159 | * Get Component-preload namespace 160 | READ TABLE lo_archive->files INTO ls_file WITH KEY name = 'Component.js'. 161 | IF sy-subrc = 0. 162 | lo_archive->get( 163 | EXPORTING 164 | name = ls_file-name 165 | IMPORTING 166 | content = lv_content 167 | EXCEPTIONS 168 | zip_index_error = 1 169 | zip_decompression_error = 2 170 | OTHERS = 3 ). 171 | IF sy-subrc = 0. 172 | lv_component = xstring_to_string( lv_content ). 173 | SPLIT lv_component AT `.extend(` INTO lv_junk lv_component. 174 | IF sy-subrc = 0. 175 | SHIFT lv_component LEFT DELETING LEADING: `'`, `"`. 176 | SPLIT lv_component AT `.Component` INTO lv_preload_namespace lv_junk. 177 | REPLACE ALL OCCURRENCES OF `.` IN lv_preload_namespace WITH `/`. 178 | WRITE: /, 'Preload component namespace is', lv_preload_namespace. 179 | ENDIF. 180 | ENDIF. 181 | ENDIF. 182 | 183 | LOOP AT lo_archive->files INTO ls_file. 184 | CLEAR lv_content. 185 | lo_archive->get( 186 | EXPORTING 187 | name = ls_file-name 188 | IMPORTING 189 | content = lv_content 190 | EXCEPTIONS 191 | zip_index_error = 1 192 | zip_decompression_error = 2 193 | OTHERS = 3 ). 194 | 195 | IF sy-subrc <> 0. 196 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 197 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 198 | RETURN. 199 | ENDIF. 200 | 201 | * Minification 202 | IF enable_minify = abap_true. 203 | 204 | lv_content = minify( 205 | data_in = lv_content 206 | file_type = get_file_type( ls_file-name ) ). 207 | 208 | * Collect details for Component.preload - not much point doing this unless minification works 209 | IF lv_preload_namespace IS NOT INITIAL. 210 | CASE get_file_type( ls_file-name ). 211 | WHEN 'JS'. 212 | APPEND INITIAL LINE TO lt_preload_modules REFERENCE INTO lr_preload_module. 213 | lr_preload_module->name = |{ lv_preload_namespace }/{ ls_file-name }|. 214 | lr_preload_module->value = xstring_to_string( lv_content ). 215 | WHEN 'XML'. 216 | IF ls_file-name CS '.view.xml'. 217 | APPEND INITIAL LINE TO lt_preload_modules REFERENCE INTO lr_preload_module. 218 | lr_preload_module->name = |{ lv_preload_namespace }/{ ls_file-name }|. 219 | lr_preload_module->value = me->cleanup_xmldata( xstring_to_string( lv_content ) ). 220 | ENDIF. 221 | WHEN 'PROPERTIES'. 222 | APPEND INITIAL LINE TO lt_preload_modules REFERENCE INTO lr_preload_module. 223 | lr_preload_module->name = |{ lv_preload_namespace }/{ ls_file-name }|. 224 | lr_preload_module->value = me->cleanup_xmldata( xstring_to_string( lv_content ) ). 225 | WHEN OTHERS. 226 | ENDCASE. 227 | ENDIF. 228 | ENDIF. 229 | 230 | IF info-folder IS NOT INITIAL. 231 | ls_file-name = |{ info-folder }/{ ls_file-name }|. 232 | ENDIF. 233 | 234 | * Process any Git submodules 235 | DATA: lt_submodule_info TYPE submodule_info_ttype, 236 | lr_submodule_info TYPE REF TO submodule_info_type. 237 | IF ls_file-name = '.gitmodules'. 238 | get_submodule_info( 239 | EXPORTING 240 | iv_submodule_data = lv_content 241 | IMPORTING 242 | et_submodule_info = lt_submodule_info ). 243 | 244 | LOOP AT lt_submodule_info REFERENCE INTO lr_submodule_info. 245 | add_module_to_archive( 246 | info = lr_submodule_info->* 247 | archive = archive ). 248 | ENDLOOP. 249 | ENDIF. 250 | 251 | archive->add( 252 | EXPORTING 253 | name = ls_file-name 254 | content = lv_content ). 255 | ENDLOOP. 256 | 257 | * Build Component.preload and add to archive 258 | IF lv_preload_namespace IS NOT INITIAL AND enable_minify = abap_true. 259 | LOOP AT lt_preload_modules REFERENCE INTO lr_preload_module. 260 | REPLACE ALL OCCURRENCES OF `"` IN lr_preload_module->value WITH `\"`. 261 | IF lv_cdata IS INITIAL. 262 | lv_cdata = |"{ lr_preload_module->name }":"{ lr_preload_module->value }"|. 263 | ELSE. 264 | lv_cdata = |{ lv_cdata },"{ lr_preload_module->name }":"{ lr_preload_module->value }"|. 265 | ENDIF. 266 | ENDLOOP. 267 | lv_cdata = 268 | |jQuery.sap.registerPreloadedModules(\{| && 269 | |"version": "2.0",| && 270 | |"name": "{ lv_preload_namespace }/Component-preload",| && 271 | |"modules": \{| && 272 | lv_cdata && 273 | |\}| && 274 | |\});|. 275 | archive->add( 276 | EXPORTING 277 | name = 'Component-preload.js' 278 | content = string_to_xstring( lv_cdata ) ). 279 | ENDIF. 280 | 281 | ENDMETHOD. "add_module_to_archive 282 | 283 | 284 | METHOD cleanup_stringdata. 285 | 286 | CONSTANTS: lf TYPE x LENGTH 4 VALUE '0A', 287 | cr TYPE x LENGTH 4 VALUE '0D', 288 | tab TYPE x LENGTH 4 VALUE '09', 289 | spc TYPE x LENGTH 4 VALUE '20'. 290 | 291 | FIELD-SYMBOLS: TYPE char1, 292 | TYPE char1, 293 | TYPE char1, 294 | TYPE char1. 295 | 296 | ASSIGN lf TO CASTING. 297 | ASSIGN cr TO CASTING. 298 | ASSIGN tab TO CASTING. 299 | ASSIGN spc TO CASTING. 300 | 301 | data_out = data_in. 302 | 303 | * Remove line feeds 304 | REPLACE ALL OCCURRENCES OF IN data_out WITH ''. 305 | * Remove carriage returns 306 | REPLACE ALL OCCURRENCES OF IN data_out WITH ''. 307 | * Replace tabs with space 308 | REPLACE ALL OCCURRENCES OF IN data_out WITH . 309 | 310 | IF nogaps = abap_true. 311 | CONDENSE data_out NO-GAPS. 312 | ELSE. 313 | CONDENSE data_out. 314 | ENDIF. 315 | 316 | ENDMETHOD. "minify 317 | 318 | 319 | METHOD cleanup_xmldata. 320 | 321 | CONSTANTS: lf TYPE x LENGTH 4 VALUE '0A', 322 | cr TYPE x LENGTH 4 VALUE '0D', 323 | tab TYPE x LENGTH 4 VALUE '09', 324 | spc TYPE x LENGTH 4 VALUE '20'. 325 | 326 | FIELD-SYMBOLS: TYPE char1, 327 | TYPE char1, 328 | TYPE char1, 329 | TYPE char1. 330 | 331 | ASSIGN lf TO CASTING. 332 | ASSIGN cr TO CASTING. 333 | ASSIGN tab TO CASTING. 334 | ASSIGN spc TO CASTING. 335 | 336 | data_out = data_in. 337 | 338 | * Replace tabs with \t 339 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN data_out WITH '\t'. 340 | * Replace newlines with \n 341 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN data_out WITH '\n'. 342 | * Remove all spaces that immediately follow a new line - hope there are none inside XML data ;) 343 | DO. 344 | REPLACE ALL OCCURRENCES OF `\n ` IN data_out WITH `\n`. 345 | IF sy-subrc NE 0 OR sy-index > 500. EXIT. ENDIF. 346 | ENDDO. 347 | 348 | * Remove line feeds - should be none left 349 | REPLACE ALL OCCURRENCES OF IN data_out WITH ''. 350 | * Remove carriage returns 351 | REPLACE ALL OCCURRENCES OF IN data_out WITH ''. 352 | 353 | ENDMETHOD. "minify 354 | 355 | 356 | METHOD constructor. 357 | 358 | me->repository = repository. 359 | me->branch = branch. 360 | me->github_user = github_user. 361 | me->password = password. 362 | me->transport = transport. 363 | me->test_only = test_only. 364 | 365 | DATA: lo_archive TYPE REF TO cl_abap_zip, 366 | ls_module TYPE submodule_info_type. 367 | 368 | ls_module-repository = me->repository. 369 | ls_module-branch = me->branch. 370 | 371 | CREATE OBJECT lo_archive. 372 | 373 | add_module_to_archive( 374 | info = ls_module 375 | archive = lo_archive ). 376 | 377 | save_archive_file( lo_archive ). 378 | 379 | upload_archive_into_icf( lo_archive ). 380 | 381 | update_cachebuster( ). 382 | 383 | ENDMETHOD. "constructor 384 | 385 | 386 | METHOD deploy. 387 | DATA: deployer TYPE REF TO ycl_github_deployer. 388 | 389 | CREATE OBJECT deployer 390 | EXPORTING 391 | repository = repository 392 | branch = branch 393 | github_user = github_user 394 | password = password 395 | transport = transport 396 | test_only = test_only. 397 | 398 | ENDMETHOD. "deploy 399 | 400 | 401 | METHOD get_css_minify_params. 402 | 403 | IF css_minify_params IS INITIAL. 404 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO DATA(lr_param). 405 | lr_param->name = 'type'. 406 | lr_param->value = 'css'. 407 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 408 | lr_param->name = 'options[advanced]'. 409 | lr_param->value = 'true'. 410 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 411 | lr_param->name = 'options[aggressiveMerging]'. 412 | lr_param->value = 'true'. 413 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 414 | lr_param->name = 'options[rebase]'. 415 | lr_param->value = 'true'. 416 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 417 | lr_param->name = 'options[processImport]'. 418 | lr_param->value = 'true'. 419 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 420 | lr_param->name = 'options[benchmark]'. 421 | lr_param->value = 'false'. 422 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 423 | lr_param->name = 'options[compatibility]'. 424 | lr_param->value = 'false'. 425 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 426 | lr_param->name = 'options[keepBreaks]'. 427 | lr_param->value = 'false'. 428 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 429 | lr_param->name = 'options[debug]'. 430 | lr_param->value = 'false'. 431 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 432 | lr_param->name = 'options[inliner]'. 433 | lr_param->value = ''. 434 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 435 | lr_param->name = 'options[relativeTo]'. 436 | lr_param->value = ''. 437 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 438 | lr_param->name = 'options[root]'. 439 | lr_param->value = ''. 440 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 441 | lr_param->name = 'options[target]'. 442 | lr_param->value = ''. 443 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 444 | lr_param->name = 'options[keepSpecialComments]'. 445 | lr_param->value = '*'. 446 | APPEND INITIAL LINE TO css_minify_params REFERENCE INTO lr_param. 447 | lr_param->name = 'options[roundingPrecision]'. 448 | lr_param->value = '2'. 449 | ENDIF. 450 | 451 | rt_params = css_minify_params. 452 | 453 | ENDMETHOD. "get_css_minify_params 454 | 455 | 456 | METHOD get_file_type. 457 | DATA: lt_strings TYPE stringtab, 458 | lr_extension TYPE REF TO string. 459 | 460 | SPLIT iv_filename AT '.' INTO TABLE lt_strings. 461 | 462 | LOOP AT lt_strings REFERENCE INTO lr_extension. ENDLOOP. 463 | CHECK sy-subrc = 0. 464 | 465 | TRANSLATE lr_extension->* TO UPPER CASE. 466 | 467 | rv_filetype = lr_extension->*. 468 | 469 | ENDMETHOD. "GET_FILE_TYPE 470 | 471 | 472 | METHOD get_js_minify_params. 473 | 474 | IF js_minify_params IS INITIAL. 475 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO DATA(lr_param). 476 | lr_param->name = 'type'. 477 | lr_param->value = 'javascript'. 478 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 479 | lr_param->name = 'options[sequences]'. 480 | lr_param->value = 'true'. 481 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 482 | lr_param->name = 'options[properties]'. 483 | lr_param->value = 'true'. 484 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 485 | lr_param->name = 'options[dead_code]'. 486 | lr_param->value = 'true'. 487 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 488 | lr_param->name = 'options[drop_debugger]'. 489 | lr_param->value = 'true'. 490 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 491 | lr_param->name = 'options[conditionals]'. 492 | lr_param->value = 'true'. 493 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 494 | lr_param->name = 'options[comparisons]'. 495 | lr_param->value = 'true'. 496 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 497 | lr_param->name = 'options[evaluate]'. 498 | lr_param->value = 'true'. 499 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 500 | lr_param->name = 'options[booleans]'. 501 | lr_param->value = 'true'. 502 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 503 | lr_param->name = 'options[loops]'. 504 | lr_param->value = 'true'. 505 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 506 | lr_param->name = 'options[unused]'. 507 | lr_param->value = 'true'. 508 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 509 | lr_param->name = 'options[hoist_funs]'. 510 | lr_param->value = 'true'. 511 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 512 | lr_param->name = 'options[if_return]'. 513 | lr_param->value = 'true'. 514 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 515 | lr_param->name = 'options[join_vars]'. 516 | lr_param->value = 'true'. 517 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 518 | lr_param->name = 'options[cascade]'. 519 | lr_param->value = 'true'. 520 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 521 | lr_param->name = 'options[warnings]'. 522 | lr_param->value = 'true'. 523 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 524 | lr_param->name = 'options[negate_iife]'. 525 | lr_param->value = 'true'. 526 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 527 | lr_param->name = 'options[unsafe]'. 528 | lr_param->value = 'false'. 529 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 530 | lr_param->name = 'options[hoist_vars]'. 531 | lr_param->value = 'false'. 532 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 533 | lr_param->name = 'options[pure_getters]'. 534 | lr_param->value = 'false'. 535 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 536 | lr_param->name = 'options[drop_console]'. 537 | lr_param->value = 'false'. 538 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 539 | lr_param->name = 'options[keep_fargs]'. 540 | lr_param->value = 'false'. 541 | APPEND INITIAL LINE TO js_minify_params REFERENCE INTO lr_param. 542 | lr_param->name = 'options[pure_funcs]'. 543 | lr_param->value = ''. 544 | ENDIF. 545 | 546 | rt_params = js_minify_params. 547 | 548 | ENDMETHOD. "GET_JS_MINIFY_PARAMS 549 | 550 | 551 | METHOD get_module_archive. 552 | 553 | DATA: lr_client TYPE REF TO if_http_client, 554 | lv_code TYPE i, 555 | lv_message TYPE string. 556 | 557 | WRITE:/, `Retrieving archive from`, url. 558 | 559 | cl_http_client=>create_by_url( 560 | EXPORTING 561 | url = url 562 | ssl_id = 'ANONYM' 563 | IMPORTING 564 | client = lr_client 565 | EXCEPTIONS 566 | OTHERS = 1 ). 567 | 568 | IF sy-subrc <> 0. 569 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 570 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 571 | RETURN. 572 | ENDIF. 573 | 574 | IF me->github_user IS NOT INITIAL. 575 | lr_client->authenticate( username = me->github_user password = me->password ). 576 | lr_client->propertytype_accept_cookie = if_http_client=>co_enabled. 577 | ENDIF. 578 | 579 | lr_client->send( EXCEPTIONS OTHERS = 1 ). 580 | IF sy-subrc <> 0. 581 | lv_message = |http send error|. 582 | WRITE:/, lv_message COLOR COL_NEGATIVE. 583 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 584 | RETURN. 585 | ENDIF. 586 | lr_client->receive( 587 | EXCEPTIONS 588 | http_communication_failure = 1 589 | http_invalid_state = 2 590 | http_processing_failed = 3 591 | OTHERS = 4 ). 592 | IF sy-subrc <> 0. 593 | CASE sy-subrc. 594 | WHEN 1. 595 | " make sure: 596 | " a) SSL is setup properly in STRUST 597 | " b) no firewalls 598 | " check trace file in transaction SMICM 599 | lv_message = 'HTTP Communication Failure'. "#EC NOTEXT 600 | WHEN 2. 601 | lv_message = 'HTTP Invalid State'. "#EC NOTEXT 602 | WHEN 3. 603 | lv_message = 'HTTP Processing failed'. "#EC NOTEXT 604 | WHEN OTHERS. 605 | lv_message = 'Another error occured'. "#EC NOTEXT 606 | ENDCASE. 607 | WRITE:/, lv_message COLOR COL_NEGATIVE. 608 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 609 | RETURN. 610 | ENDIF. 611 | 612 | lr_client->response->get_status( IMPORTING code = lv_code ). 613 | 614 | IF lv_code NE 200. 615 | IF lv_message IS INITIAL. 616 | lv_message = |HTTP Return Code is { lv_code }|. 617 | ENDIF. 618 | MESSAGE lv_message TYPE 'E' DISPLAY LIKE 'I'. 619 | RETURN. 620 | ENDIF. 621 | 622 | CREATE OBJECT archive. 623 | 624 | archive->load( 625 | EXPORTING 626 | zip = lr_client->response->get_data( ) 627 | EXCEPTIONS 628 | zip_parse_error = 1 629 | OTHERS = 2 ). 630 | 631 | IF sy-subrc <> 0. 632 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 633 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 634 | RETURN. 635 | ENDIF. 636 | 637 | ENDMETHOD. "get_archive 638 | 639 | 640 | METHOD get_submodule_info. 641 | 642 | DATA: lv_gitmodules TYPE string, 643 | lt_gitmodules TYPE stringtab, 644 | lr_string TYPE REF TO string, 645 | lv_junk1 TYPE string ##needed, 646 | lv_junk2 TYPE string ##needed, 647 | lr_url TYPE REF TO string, 648 | lr_path TYPE REF TO string ##needed, 649 | ls_submodule TYPE submodule_info_type. 650 | 651 | CONSTANTS: lf TYPE x LENGTH 4 VALUE '0A00'. 652 | FIELD-SYMBOLS: TYPE char1. 653 | ASSIGN lf TO CASTING. 654 | 655 | lv_gitmodules = xstring_to_string( iv_submodule_data ). 656 | 657 | SPLIT lv_gitmodules AT INTO TABLE lt_gitmodules. 658 | 659 | LOOP AT lt_gitmodules REFERENCE INTO lr_string. 660 | lr_string->* = cleanup_stringdata( data_in = lr_string->* nogaps = abap_true ). 661 | CHECK lr_string->* CS 'submodule'. 662 | CLEAR ls_submodule. 663 | SPLIT lr_string->* AT '"' INTO lv_junk1 ls_submodule-folder lv_junk2. 664 | READ TABLE lt_gitmodules REFERENCE INTO lr_path INDEX ( sy-tabix + 1 ). 665 | CHECK sy-subrc = 0. 666 | ls_submodule-branch = 'master'. "For submodules we always grab master branch 667 | READ TABLE lt_gitmodules REFERENCE INTO lr_url INDEX ( sy-tabix + 1 ). 668 | CHECK sy-subrc = 0. 669 | SPLIT lr_url->* AT `url = https://github.com/` INTO lv_junk1 ls_submodule-repository. 670 | APPEND ls_submodule TO et_submodule_info. 671 | ENDLOOP. 672 | 673 | ENDMETHOD. "GET_SUBMODULE_INFO 674 | 675 | 676 | METHOD minify. 677 | 678 | CASE file_type. 679 | WHEN 'JS'. 680 | data_out = minify_js( data_in ). 681 | WHEN 'CSS'. 682 | data_out = minify_css( data_in ). 683 | WHEN OTHERS. 684 | ENDCASE. 685 | 686 | IF data_out IS INITIAL. "If minification failed just return unchanged data 687 | data_out = data_in. 688 | ENDIF. 689 | 690 | * Increment counters 691 | ADD 1 TO minify_file_count. 692 | minify_byte_count = minify_byte_count + xstrlen( data_in ) - xstrlen( data_out ). 693 | 694 | ENDMETHOD. "minify 695 | 696 | 697 | METHOD minify_css. 698 | 699 | DATA: lr_client TYPE REF TO if_http_client, 700 | lv_code TYPE i, 701 | lt_ffields TYPE tihttpnvp, 702 | lr_ffield TYPE REF TO ihttpnvp. 703 | 704 | DATA: BEGIN OF json_response, 705 | code TYPE string, 706 | map TYPE string, 707 | END OF json_response. 708 | 709 | cl_http_client=>create_by_url( 710 | EXPORTING 711 | url = 'http://refresh-sf.herokuapp.com/css/' "See http://refresh-sf.com/ for details 712 | ssl_id = 'ANONYM' 713 | IMPORTING 714 | client = lr_client 715 | EXCEPTIONS 716 | argument_not_found = 1 717 | plugin_not_active = 2 718 | internal_error = 3 719 | OTHERS = 4 ). 720 | 721 | IF sy-subrc = 0. 722 | lt_ffields = get_css_minify_params( ). 723 | 724 | APPEND INITIAL LINE TO lt_ffields REFERENCE INTO lr_ffield. 725 | lr_ffield->name = 'code'. 726 | lr_ffield->value = xstring_to_string( data_in ). 727 | 728 | lr_client->request->set_form_fields( lt_ffields ). 729 | lr_client->request->set_method( if_http_request=>co_request_method_post ). 730 | 731 | lr_client->send( 732 | EXCEPTIONS 733 | http_communication_failure = 1 734 | http_invalid_state = 2 735 | http_processing_failed = 3 736 | http_invalid_timeout = 4 737 | OTHERS = 5 ). 738 | IF sy-subrc <> 0. 739 | enable_minify = abap_false. 740 | ELSE. 741 | lr_client->receive( 742 | EXCEPTIONS 743 | http_communication_failure = 1 744 | http_invalid_state = 2 745 | http_processing_failed = 3 746 | OTHERS = 4 ). 747 | IF sy-subrc <> 0. 748 | enable_minify = abap_false. 749 | ELSE. 750 | lr_client->response->get_status( IMPORTING code = lv_code ). 751 | ENDIF. 752 | ENDIF. 753 | 754 | IF lv_code EQ 200. 755 | /ui2/cl_json=>deserialize( 756 | EXPORTING json = lr_client->response->get_cdata( ) 757 | pretty_name = /ui2/cl_json=>pretty_mode-camel_case 758 | CHANGING 759 | data = json_response ). 760 | data_out = string_to_xstring( json_response-code ). 761 | ENDIF. 762 | ENDIF. 763 | 764 | ENDMETHOD. "minify 765 | 766 | 767 | METHOD minify_js. 768 | 769 | DATA: lr_client TYPE REF TO if_http_client, 770 | lv_code TYPE i, 771 | lt_ffields TYPE tihttpnvp, 772 | lr_ffield TYPE REF TO ihttpnvp. 773 | 774 | DATA: 775 | BEGIN OF json_response, 776 | code TYPE string, 777 | map TYPE string, 778 | END OF json_response. 779 | 780 | cl_http_client=>create_by_url( 781 | EXPORTING 782 | url = 'http://refresh-sf.herokuapp.com/javascript/' "See http://refresh-sf.com/ for details 783 | ssl_id = 'ANONYM' 784 | IMPORTING 785 | client = lr_client 786 | EXCEPTIONS 787 | argument_not_found = 1 788 | plugin_not_active = 2 789 | internal_error = 3 790 | OTHERS = 4 ). 791 | 792 | IF sy-subrc = 0. 793 | lt_ffields = get_js_minify_params( ). 794 | 795 | APPEND INITIAL LINE TO lt_ffields REFERENCE INTO lr_ffield. 796 | lr_ffield->name = 'code'. 797 | lr_ffield->value = xstring_to_string( data_in ). 798 | 799 | lr_client->request->set_form_fields( lt_ffields ). 800 | lr_client->request->set_method( if_http_request=>co_request_method_post ). 801 | 802 | lr_client->send( 803 | EXCEPTIONS 804 | http_communication_failure = 1 805 | http_invalid_state = 2 806 | http_processing_failed = 3 807 | http_invalid_timeout = 4 808 | OTHERS = 5 ). 809 | IF sy-subrc <> 0. 810 | enable_minify = abap_false. 811 | ELSE. 812 | lr_client->receive( 813 | EXCEPTIONS 814 | http_communication_failure = 1 815 | http_invalid_state = 2 816 | http_processing_failed = 3 817 | OTHERS = 4 ). 818 | IF sy-subrc <> 0. 819 | enable_minify = abap_false. 820 | ELSE. 821 | lr_client->response->get_status( IMPORTING code = lv_code ). 822 | ENDIF. 823 | ENDIF. 824 | 825 | IF lv_code EQ 200. 826 | /ui2/cl_json=>deserialize( 827 | EXPORTING json = lr_client->response->get_cdata( ) 828 | pretty_name = /ui2/cl_json=>pretty_mode-camel_case 829 | CHANGING 830 | data = json_response ). 831 | data_out = string_to_xstring( json_response-code ). 832 | ENDIF. 833 | ENDIF. 834 | 835 | ENDMETHOD. "minify 836 | 837 | 838 | METHOD remove_cover_folder. 839 | 840 | DATA: ls_file LIKE LINE OF archive->files, 841 | lv_content TYPE xstring, 842 | lv_dummy TYPE string ##needed. 843 | 844 | CHECK archive IS BOUND. 845 | 846 | IF lines( archive->files ) = 0. 847 | WRITE:/, 'No files in archive'. 848 | RETURN. 849 | ENDIF. 850 | 851 | CREATE OBJECT new_archive. 852 | 853 | LOOP AT archive->files INTO ls_file. 854 | CLEAR lv_content. 855 | archive->get( 856 | EXPORTING 857 | name = ls_file-name 858 | IMPORTING 859 | content = lv_content 860 | EXCEPTIONS 861 | zip_index_error = 1 862 | zip_decompression_error = 2 863 | OTHERS = 3 ). 864 | 865 | IF sy-subrc <> 0. 866 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 867 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 868 | RETURN. 869 | ENDIF. 870 | 871 | IF ls_file-name CA '/'. 872 | SPLIT ls_file-name AT '/' INTO lv_dummy ls_file-name. 873 | ELSE. 874 | SPLIT ls_file-name AT '\' INTO lv_dummy ls_file-name. 875 | ENDIF. 876 | IF ls_file-name IS INITIAL. 877 | CONTINUE. 878 | ENDIF. 879 | new_archive->add( 880 | EXPORTING 881 | name = ls_file-name 882 | content = lv_content ). 883 | ENDLOOP. 884 | 885 | ENDMETHOD. "remove_cover_folder 886 | 887 | 888 | METHOD save_archive_file. 889 | 890 | DATA: lv_content TYPE xstring, 891 | fullpath TYPE string, 892 | filename TYPE string, 893 | path TYPE string, 894 | user_action TYPE i, 895 | encoding TYPE abap_encoding, 896 | length TYPE i ##needed. 897 | 898 | DATA: BEGIN OF line_bin, 899 | data(1024) TYPE x, 900 | END OF line_bin. 901 | DATA: data_tab_bin LIKE STANDARD TABLE OF line_bin. 902 | 903 | CHECK test_only = abap_true. 904 | 905 | lv_content = archive->save( ). 906 | 907 | * Binary download table 908 | WHILE xstrlen( lv_content ) > 0. 909 | line_bin-data = lv_content. 910 | APPEND line_bin TO data_tab_bin. 911 | SHIFT lv_content LEFT BY 1024 PLACES IN BYTE MODE. 912 | ENDWHILE. 913 | 914 | * Get filename 915 | CALL METHOD cl_gui_frontend_services=>file_save_dialog 916 | EXPORTING 917 | window_title = 'Download Archive' 918 | with_encoding = 'X' 919 | initial_directory = 'C:\' 920 | CHANGING 921 | filename = filename 922 | path = path 923 | fullpath = fullpath 924 | user_action = user_action 925 | file_encoding = encoding 926 | EXCEPTIONS 927 | cntl_error = 1 928 | error_no_gui = 2 929 | not_supported_by_gui = 3 930 | OTHERS = 4. 931 | IF sy-subrc <> 0. 932 | RETURN. 933 | ENDIF. 934 | 935 | IF user_action <> cl_gui_frontend_services=>action_ok. 936 | RETURN. 937 | ENDIF. 938 | 939 | * Binary download 940 | CALL FUNCTION 'GUI_DOWNLOAD' 941 | EXPORTING 942 | filename = fullpath 943 | filetype = 'BIN' 944 | IMPORTING 945 | filelength = length 946 | TABLES 947 | data_tab = data_tab_bin 948 | EXCEPTIONS 949 | file_write_error = 1 950 | no_batch = 2 951 | gui_refuse_filetransfer = 3 952 | invalid_type = 4 953 | no_authority = 5 954 | unknown_error = 6 955 | header_not_allowed = 7 956 | separator_not_allowed = 8 957 | filesize_not_allowed = 9 958 | header_too_long = 10 959 | dp_error_create = 11 960 | dp_error_send = 12 961 | dp_error_write = 13 962 | unknown_dp_error = 14 963 | access_denied = 15 964 | dp_out_of_memory = 16 965 | disk_full = 17 966 | dp_timeout = 18 967 | file_not_found = 19 968 | dataprovider_exception = 20 969 | control_flush_error = 21 970 | OTHERS = 22 ##FM_SUBRC_OK. 971 | 972 | ENDMETHOD. "save_zip_file 973 | 974 | 975 | METHOD string_to_xstring. 976 | 977 | DATA(lv_conv) = cl_abap_conv_out_ce=>create( ). 978 | 979 | CALL METHOD lv_conv->write 980 | EXPORTING 981 | n = -1 982 | data = in 983 | IMPORTING 984 | len = DATA(lv_length). 985 | 986 | 987 | CALL METHOD lv_conv->get_buffer 988 | RECEIVING 989 | buffer = out. 990 | 991 | ENDMETHOD. "STRING_TO_XSTRING 992 | 993 | 994 | METHOD update_cachebuster. 995 | 996 | DATA: lv_jobnumber TYPE tbtcjob-jobcount, 997 | lv_jobname TYPE tbtcjob-jobname VALUE 'UI5_CACHEBUSTER'. 998 | 999 | CHECK test_only NE abap_true. 1000 | 1001 | CALL FUNCTION 'JOB_OPEN' 1002 | EXPORTING 1003 | jobname = lv_jobname 1004 | IMPORTING 1005 | jobcount = lv_jobnumber 1006 | EXCEPTIONS 1007 | cant_create_job = 1 1008 | invalid_job_data = 2 1009 | jobname_missing = 3 1010 | OTHERS = 4. 1011 | 1012 | CHECK sy-subrc = 0. 1013 | 1014 | SUBMIT /ui5/app_index_calculate "/ui5/update_cachebuster 1015 | VIA JOB lv_jobname NUMBER lv_jobnumber AND RETURN. 1016 | 1017 | CHECK sy-subrc = 0. 1018 | 1019 | CALL FUNCTION 'JOB_CLOSE' 1020 | EXPORTING 1021 | jobcount = lv_jobnumber 1022 | jobname = lv_jobname 1023 | strtimmed = 'X' 1024 | EXCEPTIONS 1025 | cant_start_immediate = 1 1026 | invalid_startdate = 2 1027 | jobname_missing = 3 1028 | job_close_failed = 4 1029 | job_nosteps = 5 1030 | job_notex = 6 1031 | lock_failed = 7 1032 | OTHERS = 8 ##FM_SUBRC_OK. 1033 | 1034 | 1035 | ENDMETHOD. 1036 | 1037 | 1038 | METHOD upload_archive_into_icf. 1039 | 1040 | DATA: lv_zip_file TYPE xstring. 1041 | * Messages 1042 | DATA: lv_success TYPE char1, 1043 | lt_log_messages TYPE string_table, 1044 | lv_message TYPE string, 1045 | lv_msg_id TYPE sy-msgid, 1046 | lv_msg_no TYPE sy-msgno. 1047 | 1048 | CHECK archive->files IS NOT INITIAL. 1049 | 1050 | lv_message = |Archive contains { lines( archive->files ) } folders & files|. 1051 | WRITE:/, lv_message. 1052 | IF minify_file_count > 0. 1053 | lv_message = |{ minify_file_count } files minified - { minify_byte_count } bytes removed|. 1054 | WRITE:/, lv_message. 1055 | ENDIF. 1056 | 1057 | WRITE:/, `Loading archive.....`. 1058 | 1059 | lv_zip_file = archive->save( ). 1060 | 1061 | CALL FUNCTION 'YUI5_REPOSITORY_LOAD_HTTP' 1062 | EXPORTING 1063 | iv_url = '' 1064 | * IV_SAPUI5_APPLICATION_NAME = '' 1065 | * IV_SAPUI5_APPLICATION_DESC = '' 1066 | * IV_PACKAGE = '' 1067 | iv_workbench_request = me->transport 1068 | * IV_EXTERNAL_CODE_PAGE = '' 1069 | * IV_ACCEPT_UNIX_STYLE_EOL = 'X' 1070 | * IV_DELTA_MODE = '-' 1071 | iv_test_mode = me->test_only 1072 | iv_zip_file = lv_zip_file 1073 | IMPORTING 1074 | ev_success = lv_success 1075 | ev_log_messages = lt_log_messages 1076 | ev_msg_id = lv_msg_id 1077 | ev_msg_no = lv_msg_no. 1078 | 1079 | MESSAGE ID lv_msg_id TYPE lv_success NUMBER lv_msg_no INTO lv_message. 1080 | LOOP AT lt_log_messages INTO lv_message. 1081 | WRITE:/, lv_message. 1082 | ENDLOOP. 1083 | CASE lv_success. 1084 | WHEN 'S'. 1085 | WRITE:/, 'Success' COLOR COL_POSITIVE, lv_message COLOR COL_POSITIVE. 1086 | WHEN 'W'. 1087 | WRITE:/, 'Warning' COLOR COL_GROUP, lv_message COLOR COL_GROUP. 1088 | WHEN OTHERS. 1089 | WRITE:/, 'Error' COLOR COL_NEGATIVE, lv_message COLOR COL_NEGATIVE. 1090 | RAISE EXCEPTION TYPE cx_sy_create_data_error "Just any old exception to signal failure 1091 | EXPORTING 1092 | textid = cx_sy_create_data_error=>generic_type 1093 | * previous = previous 1094 | * typename = typename 1095 | . 1096 | ENDCASE. 1097 | 1098 | ENDMETHOD. "load_archive 1099 | 1100 | 1101 | METHOD xstring_to_string. 1102 | 1103 | DATA(conv) = cl_abap_conv_in_ce=>create( 1104 | encoding = 'UTF-8' 1105 | endian = 'L' 1106 | ignore_cerr = 'X' 1107 | replacement = '#' 1108 | input = in 1109 | ). 1110 | 1111 | CALL METHOD conv->read 1112 | IMPORTING 1113 | data = out. 1114 | 1115 | ENDMETHOD. "XSTRING_TO_STRING 1116 | ENDCLASS. 1117 | -------------------------------------------------------------------------------- /src/yui5_repository_load.fugr.lyui5_repository_loadp01.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Include /UI5/LUI5_REPOSITORY_LOADP01 3 | *&---------------------------------------------------------------------* 4 | ************************************************************************ 5 | ************************************************************************ 6 | * * 7 | * Local Classes Implementation * 8 | * * 9 | ************************************************************************ 10 | ************************************************************************ 11 | 12 | 13 | ************************************************************************ 14 | * Class LCL_FUNCTION 15 | * 16 | * provides some helper functions. 17 | ************************************************************************ 18 | CLASS lcl_function IMPLEMENTATION. 19 | 20 | METHOD max. 21 | DATA: max TYPE i. 22 | max = a. 23 | IF ( b > a ). max = b . ENDIF. 24 | IF ( c > max ). max = c . ENDIF. 25 | IF ( d > max ). max = d . ENDIF. 26 | IF ( e > max ). max = e . ENDIF. 27 | IF ( f > max ). max = f . ENDIF. 28 | rv_max = max. 29 | ENDMETHOD. "max 30 | 31 | METHOD set_return_msg. 32 | 33 | cv_msg_id = '/UI5/UI5_REP_LOAD'. 34 | 35 | * Test mode off 36 | IF iv_test_mode = abap_false. 37 | IF iv_success = status_success. 38 | cv_msg_no = '001'. 39 | ELSEIF iv_success = status_warning. 40 | cv_msg_no = '002'. 41 | ELSEIF iv_success = status_error. 42 | cv_msg_no = '003'. 43 | ENDIF. 44 | ENDIF. 45 | 46 | * Test mode on 47 | IF iv_test_mode = abap_true. 48 | IF iv_success = status_success. 49 | cv_msg_no = '004'. 50 | ELSEIF iv_success = status_warning. 51 | cv_msg_no = '005'. 52 | ELSEIF iv_success = status_error. 53 | cv_msg_no = '006'. 54 | ENDIF. 55 | ENDIF. 56 | 57 | ENDMETHOD. "set_return_msg 58 | 59 | METHOD text_matches_pattern. 60 | 61 | * Initialize 62 | rv_text_matches_pattern = abap_false. 63 | 64 | * Check if string matches a pattern of the list passed on entry 65 | DATA: pattern TYPE string, 66 | regular_expression_check TYPE abap_bool, 67 | match_count TYPE i. 68 | LOOP AT iv_pattern_list INTO pattern. 69 | 70 | * Skip empty lines 71 | IF strlen( pattern ) = 0. CONTINUE. ENDIF. 72 | 73 | * Determine if pattern to be treated as a regular expression or a substring 74 | DATA: first_char TYPE c, last_char TYPE c, last_char_offset TYPE i. 75 | last_char_offset = strlen( pattern ) - 1. 76 | first_char = pattern(1). 77 | last_char = pattern+last_char_offset(1). 78 | DATA: is_regular_expression TYPE abap_bool. is_regular_expression = abap_false. 79 | IF first_char = '^' AND last_char = '$'. is_regular_expression = abap_true. ENDIF. 80 | 81 | * Check 82 | IF is_regular_expression = abap_true. 83 | TRY. 84 | FIND REGEX pattern IN iv_text IGNORING CASE MATCH COUNT match_count. 85 | CATCH cx_root. 86 | ENDTRY. 87 | ELSE. 88 | FIND pattern IN iv_text IGNORING CASE MATCH COUNT match_count. 89 | ENDIF. 90 | IF match_count > 0. rv_text_matches_pattern = abap_true. RETURN. ENDIF. 91 | ENDLOOP. 92 | 93 | ENDMETHOD. "text_matches_pattern 94 | 95 | * Converts a text into an abap_bool expression 96 | METHOD text_to_abap_bool. 97 | 98 | * Initialize 99 | rv_abap_bool = abap_true. 100 | DATA: text TYPE string. text = iv_text. 101 | CONDENSE text. TRANSLATE text TO LOWER CASE. 102 | 103 | * ABAP_FALSE 104 | IF text IS INITIAL. rv_abap_bool = abap_false. RETURN. ENDIF. 105 | IF text = 'false'. rv_abap_bool = abap_false. RETURN. ENDIF. "#EC NOTEXT 106 | IF text = 'no'. rv_abap_bool = abap_false. RETURN. ENDIF. "#EC NOTEXT 107 | IF text = '0'. rv_abap_bool = abap_false. RETURN. ENDIF. "#EC NOTEXT 108 | 109 | * ABAP_TRUE 110 | IF text = 'x'. rv_abap_bool = abap_true. RETURN. ENDIF. "#EC NOTEXT 111 | IF text = 'true'. rv_abap_bool = abap_true. RETURN. ENDIF. "#EC NOTEXT 112 | IF text = 'yes'. rv_abap_bool = abap_false. RETURN. ENDIF. "#EC NOTEXT 113 | IF text = '1'. rv_abap_bool = abap_true. RETURN. ENDIF. "#EC NOTEXT 114 | 115 | * ABAP_UNDEFINED 116 | IF text = 'undefined'. rv_abap_bool = abap_undefined. RETURN. ENDIF. "#EC NOTEXT 117 | IF text = '-'. rv_abap_bool = abap_undefined. RETURN. ENDIF. "#EC NOTEXT 118 | IF text = '?'. rv_abap_bool = abap_undefined. RETURN. ENDIF. "#EC NOTEXT 119 | 120 | ENDMETHOD. "text_to_abap_bool 121 | 122 | * Converts xstring into table of xstrings 123 | METHOD xstring2xtable. 124 | 125 | * Calculate size 126 | IF ev_size IS SUPPLIED. 127 | ev_size = xstrlen( iv_xstring ). 128 | ENDIF. 129 | 130 | * Split xstring into lines 131 | DATA: xline TYPE x255, 132 | xstring TYPE xstring. 133 | FREE ev_xtable. 134 | xstring = iv_xstring. 135 | WHILE xstring IS NOT INITIAL. 136 | xline = xstring. 137 | APPEND xline TO ev_xtable. 138 | SHIFT xstring LEFT BY 255 PLACES IN BYTE MODE. 139 | ENDWHILE. 140 | 141 | * Clean up 142 | CLEAR xstring. 143 | 144 | ENDMETHOD. "xstring2table 145 | 146 | 147 | * Converts unix style line endings (LF) to windows style (CR LF) 148 | METHOD conv_unix_style_line_endings. 149 | 150 | DATA: string TYPE string, 151 | regular_expression TYPE string, 152 | replace_with TYPE string. 153 | string = iv_string. 154 | regular_expression = '\r\n|\n\r|\n|\r'. 155 | replace_with = '\r\n'. 156 | REPLACE ALL OCCURRENCES OF REGEX regular_expression IN string WITH replace_with. 157 | 158 | rv_string = string. 159 | 160 | ENDMETHOD. "conv_unix_style_line_endings 161 | 162 | * Outputs a sstring to a file 163 | METHOD string_to_file. 164 | 165 | * Initialize 166 | rv_success = abap_true. 167 | 168 | * 169 | DATA: file_content_as_xstring TYPE xstring. 170 | TRY. 171 | file_content_as_xstring = 172 | /ui5/cl_ui5_rep_utility=>convert_string_2_xstring( iv_string = iv_file_content iv_code_page = iv_code_page ). 173 | xstring_to_file( iv_file_content = file_content_as_xstring iv_file_path = iv_file_path ). 174 | CATCH cx_root. 175 | rv_success = abap_false. 176 | ENDTRY. 177 | 178 | ENDMETHOD. "string_to_file 179 | 180 | * Outputs an xstring to a file 181 | METHOD xstring_to_file. 182 | 183 | * Initialize 184 | rv_success = abap_true. 185 | 186 | * Prepare binary data for file download 187 | * ... Content of text files is passed in binary form as well 188 | DATA: file_size TYPE int4, 189 | file_content_lines_bin TYPE lcl_function=>x255_table, 190 | file_length TYPE int4. 191 | lcl_function=>xstring2xtable( EXPORTING iv_xstring = iv_file_content 192 | IMPORTING ev_size = file_size 193 | ev_xtable = file_content_lines_bin ). 194 | * Delegate 195 | CALL METHOD cl_gui_frontend_services=>gui_download 196 | EXPORTING 197 | bin_filesize = file_size 198 | filename = iv_file_path 199 | filetype = 'BIN' 200 | IMPORTING 201 | filelength = file_length "virus_scan_profile = '/SCET/GUI_DOWNLOAD' 202 | CHANGING 203 | data_tab = file_content_lines_bin 204 | EXCEPTIONS 205 | file_write_error = 1 206 | no_batch = 2 207 | gui_refuse_filetransfer = 3 208 | invalid_type = 4 209 | no_authority = 5 210 | unknown_error = 6 211 | header_not_allowed = 7 212 | separator_not_allowed = 8 213 | filesize_not_allowed = 9 214 | header_too_long = 10 215 | dp_error_create = 11 216 | dp_error_send = 12 217 | dp_error_write = 13 218 | unknown_dp_error = 14 219 | access_denied = 15 220 | dp_out_of_memory = 16 221 | disk_full = 17 222 | dp_timeout = 18 223 | file_not_found = 19 224 | dataprovider_exception = 20 225 | control_flush_error = 21 226 | not_supported_by_gui = 22 227 | error_no_gui = 23 228 | OTHERS = 24. 229 | IF sy-subrc <> 0. 230 | rv_success = abap_false. 231 | ENDIF. 232 | 233 | ENDMETHOD. "xstring_to_file 234 | 235 | * Calculates md5 hash value for string 236 | * ... returns intial value in case of error 237 | METHOD get_md5_hash_for_string. 238 | 239 | DATA: string_length TYPE i. string_length = strlen( iv_string ). 240 | CALL FUNCTION 'MD5_CALCULATE_HASH_FOR_CHAR' 241 | EXPORTING 242 | data = iv_string 243 | length = string_length 244 | IMPORTING 245 | hash = rv_md5_hash 246 | EXCEPTIONS 247 | no_data = 1 248 | internal_error = 2 249 | OTHERS = 3. 250 | IF sy-subrc > 0. 251 | CLEAR rv_md5_hash. 252 | ENDIF. 253 | 254 | ENDMETHOD. "get_md5_hash_for_string 255 | 256 | * Calculates md5 hash value for string 257 | * ... returns intial value in case of error 258 | METHOD get_hash_for_xstring. 259 | 260 | DATA: hash TYPE hash160. 261 | CALL FUNCTION 'CALCULATE_HASH_FOR_RAW' 262 | EXPORTING 263 | * ALG = 'SHA1' 264 | data = iv_xstring 265 | * LENGTH = 0 266 | IMPORTING 267 | hash = hash 268 | * HASHLEN = 269 | * HASHX = l_hashx 270 | * HASHXLEN = 271 | * EXCEPTIONS 272 | * UNKNOWN_ALG = 1 273 | * PARAM_ERROR = 2 274 | * INTERNAL_ERROR = 3 275 | * OTHERS = 4 276 | . 277 | 278 | rv_hash = hash. 279 | 280 | IF sy-subrc > 0. 281 | CLEAR rv_hash. 282 | ENDIF. 283 | 284 | ENDMETHOD. "get_md5_hash_for_xstring 285 | 286 | ENDCLASS. "lcl_function IMPLEMENTATION 287 | 288 | 289 | ************************************************************************ 290 | * Class LCL_OPERATION 291 | * 292 | * represents an upload operation to be performed. 293 | ************************************************************************ 294 | CLASS lcl_operation IMPLEMENTATION. 295 | 296 | ***************************************** 297 | METHOD create_log_message. 298 | ***************************************** 299 | 300 | * Operation 301 | DATA: message TYPE string, 302 | operation_(13) TYPE c. 303 | operation_ = me->operation. 304 | IF me->to_update = abap_false 305 | AND me->operation <> me->ignore_file 306 | AND me->operation <> me->ignore_folder. 307 | operation_ = 'NONE'. 308 | ENDIF. 309 | 310 | CONCATENATE operation_ ' : ' INTO message RESPECTING BLANKS. 311 | 312 | * Path 313 | IF me->operation = lcl_operation=>delete_folder 314 | OR me->operation = lcl_operation=>delete_file. 315 | CONCATENATE message me->relative_path INTO message. 316 | ELSE. 317 | CONCATENATE message me->full_path INTO message. 318 | ENDIF. 319 | 320 | * File type 321 | IF me->operation = lcl_operation=>upload_file. 322 | DATA: text_binary TYPE string. 323 | IF me->object_type = lcl_operation=>object_type_text_file. 324 | text_binary = TEXT-070. 325 | CONCATENATE message ' (' text_binary ')' INTO message RESPECTING BLANKS. 326 | ELSEIF me->object_type = lcl_operation=>object_type_binary_file. 327 | text_binary = TEXT-071. 328 | CONCATENATE message ' (' text_binary ')' INTO message RESPECTING BLANKS. 329 | ENDIF. 330 | ENDIF. 331 | IF me->message IS NOT INITIAL. 332 | CONCATENATE message ' (' me->message ')' INTO message RESPECTING BLANKS. 333 | ENDIF. 334 | 335 | rv_message = message. 336 | 337 | ENDMETHOD. "create_log_message 338 | 339 | ***************************************** 340 | METHOD get_file_extension. 341 | ***************************************** 342 | 343 | * Initialize 344 | CLEAR rv_file_extension. 345 | 346 | * Return empty string if object behind is a folder 347 | IF object_type = lcl_operation=>object_type_folder. RETURN. ENDIF. 348 | 349 | * Split path 350 | DATA: parts TYPE TABLE OF string, 351 | part TYPE string, 352 | i TYPE int4, 353 | extension TYPE string. 354 | SPLIT me->relative_path AT '/' INTO TABLE parts. 355 | i = lines( parts ). 356 | READ TABLE parts INTO part INDEX i. 357 | * Get file extension 358 | SPLIT part AT '.' INTO TABLE parts. 359 | i = lines( parts ). 360 | IF i > 1. 361 | READ TABLE parts INTO extension INDEX i. 362 | TRANSLATE extension TO UPPER CASE. "#EC TRANSLANG 363 | ENDIF. 364 | * Return 365 | IF extension IS INITIAL. RETURN. ENDIF. 366 | CONCATENATE '.' extension INTO extension. 367 | rv_file_extension = extension. 368 | 369 | ENDMETHOD. "get_file_extension 370 | 371 | ***************************************** 372 | METHOD is_binary. 373 | ***************************************** 374 | 375 | * Check file type 376 | rv_is_binary = abap_undefined. 377 | IF me->object_type = lcl_operation=>object_type_binary_file. 378 | rv_is_binary = abap_true. 379 | ELSEIF me->object_type = lcl_operation=>object_type_text_file. 380 | rv_is_binary = abap_false. 381 | ENDIF. 382 | 383 | ENDMETHOD. "is_binary 384 | 385 | ENDCLASS. "lcl_operation 386 | 387 | ************************************************************************ 388 | * Class LCL_BADI 389 | * 390 | * represents the Business Add-In /UI5/BADI_PREVENT_DELETION 391 | ************************************************************************ 392 | CLASS lcl_badi IMPLEMENTATION. 393 | 394 | ***************************************** 395 | METHOD constructor. 396 | ***************************************** 397 | 398 | * Access business add-in 399 | TRY. 400 | 401 | * Retrieve BAdI implementation 402 | GET BADI me->implementation. 403 | IF me->implementation IS NOT INITIAL. 404 | IF cl_badi_query=>number_of_implementations( me->implementation ) = 0. 405 | CLEAR me->implementation. 406 | ENDIF. 407 | ENDIF. 408 | 409 | * Check if the deletion of any mime object is to be ommited 410 | me->never_delete_mime_resources = abap_false. 411 | IF me->implementation IS NOT INITIAL. 412 | CALL BADI me->implementation->disable_deletion_for_all 413 | EXPORTING 414 | iv_caller = '/UI5/UI5_REPOSITORY_LOAD_HTTP' 415 | RECEIVING 416 | rv_prevent_deletion = me->never_delete_mime_resources. 417 | ENDIF. 418 | 419 | * Remember 420 | me->application_name = iv_sapui5_application_name. 421 | me->workbench_request = iv_workbench_request. 422 | me->test_mode = iv_test_mode. 423 | 424 | CATCH cx_badi_not_implemented. 425 | 426 | CLEAR me->implementation. 427 | 428 | ENDTRY. 429 | 430 | ENDMETHOD. "constructor 431 | 432 | ***************************************** 433 | METHOD disable_deletion_for. 434 | ***************************************** 435 | 436 | * Initialize 437 | rv_result = abap_false. 438 | 439 | * Return if no operation given 440 | * or if there's no BAdI 441 | IF iv_operation IS INITIAL 442 | OR me->implementation IS INITIAL. 443 | EXIT. 444 | ENDIF. 445 | 446 | * Return if text file or no delete operation 447 | * ... Note: The BAdI may hinder deletion if the file type is unknown 448 | IF iv_operation->object_type = lcl_operation=>object_type_text_file 449 | OR iv_operation->operation <> lcl_operation=>delete_file. 450 | EXIT. 451 | ENDIF. 452 | 453 | * Disable this deletion in case BAdI disables all 454 | IF me->never_delete_mime_resources = abap_true. 455 | rv_result = abap_true. 456 | EXIT. 457 | ENDIF. 458 | 459 | * Build path expression 460 | DATA: path TYPE string. 461 | CONCATENATE me->application_name '/' iv_operation->full_path INTO path. 462 | 463 | * Delegate to BAdI 464 | DATA: _error_occured TYPE abap_bool, 465 | _error_text TYPE string. 466 | _error_occured = abap_false. _error_text = ''. 467 | CALL BADI me->implementation->disable_deletion_for_one 468 | EXPORTING 469 | iv_url = path 470 | iv_rename = abap_undefined 471 | iv_request = me->workbench_request 472 | iv_test = me->test_mode 473 | iv_caller = '/UI5/CL_UI5_UPLOAD_TO_MIME' 474 | IMPORTING 475 | ev_prevent_deletion = rv_result 476 | ev_error = _error_occured 477 | ev_text = _error_text. 478 | 479 | * Remember last error 480 | IF _error_occured = abap_true. 481 | me->error_occurred = abap_true. 482 | me->error_text = _error_text. 483 | ENDIF. 484 | 485 | ENDMETHOD. "disable_deletion_for 486 | 487 | ENDCLASS. "lcl_operation IMPLEMENTATION 488 | 489 | 490 | ************************************************************************ 491 | * Class LCL_SAPUI5_ZIP_ARCHIVE 492 | * 493 | * represents a zip file containing a SAPUI5 application 494 | * 495 | * Remarks: 496 | * - Access to log messages is passed as reference to constructor: 497 | * 1) Changing and table parameters are not allowed here; 498 | * 2) Using a field symbol as an input parameter does not work either: 499 | * Write operation is not supported then. 500 | * 501 | ************************************************************************ 502 | CLASS lcl_sapui5_zip_archive IMPLEMENTATION. 503 | 504 | ***************************************** 505 | METHOD constructor. 506 | ***************************************** 507 | 508 | * Initialize 509 | me->ok = abap_true. 510 | CLEAR me->error_message. 511 | 512 | * Remember 513 | me->url = iv_url. 514 | me->log_messages_ref = ir_log_messages. 515 | 516 | IF iv_zip_file IS NOT SUPPLIED. 517 | * Access zip file via http 518 | 519 | * ... Confirm Url 520 | cl_http_client=>create_by_url( EXPORTING url = me->url 521 | IMPORTING client = me->http_client 522 | EXCEPTIONS argument_not_found = 1 523 | plugin_not_active = 2 524 | internal_error = 3 525 | OTHERS = 4 ). 526 | IF sy-subrc <> 0. 527 | me->ok = abap_false. me->error_message = TEXT-011. 528 | REPLACE '%' IN me->error_message WITH me->url. 529 | APPEND me->error_message TO log_messages_ref->*. 530 | EXIT. 531 | ELSE. 532 | DATA: message TYPE string. 533 | message = TEXT-012. APPEND message TO me->log_messages_ref->*. 534 | CONCATENATE '. ' iv_url INTO message RESPECTING BLANKS. 535 | APPEND message TO log_messages_ref->*. 536 | ENDIF. 537 | 538 | * ... Grep binary content of archive 539 | DATA: return_code TYPE sysubrc. 540 | http_client->send( EXCEPTIONS OTHERS = 1 ). 541 | http_client->receive( EXCEPTIONS OTHERS = 1 ). 542 | 543 | http_client->get_last_error( 544 | IMPORTING 545 | code = return_code 546 | message = message 547 | ). 548 | IF return_code IS NOT INITIAL. 549 | me->ok = abap_false. me->error_message = TEXT-011. 550 | REPLACE '%' IN me->error_message WITH me->url. 551 | APPEND me->error_message TO me->log_messages_ref->*. 552 | EXIT. 553 | ENDIF. 554 | 555 | DATA: xstring TYPE xstring. 556 | xstring = http_client->response->get_data( ). 557 | 558 | ELSE. 559 | xstring = iv_zip_file. 560 | ENDIF. 561 | 562 | * ... Initialize zip access 563 | CREATE OBJECT zip_archive. 564 | zip_archive->load( EXPORTING zip = xstring 565 | EXCEPTIONS OTHERS = 1 ). 566 | * Indicate if archive is empty or http status is not 200 567 | IF sy-subrc IS NOT INITIAL OR zip_archive->files[] IS INITIAL. 568 | 569 | me->ok = abap_false. me->error_message = TEXT-013. 570 | APPEND me->error_message TO me->log_messages_ref->*. 571 | 572 | DATA: http_status_code_response TYPE i, http_status_code_response_ TYPE string, http_status_text_response TYPE string. 573 | http_client->response->get_status( IMPORTING code = http_status_code_response reason = http_status_text_response ). 574 | IF ( http_status_code_response <> 200 ). 575 | me->ok = abap_false. me->error_message = TEXT-109. 576 | http_status_code_response_ = http_status_code_response. CONDENSE http_status_code_response_ NO-GAPS. 577 | REPLACE '%1' IN me->error_message WITH http_status_code_response_. 578 | REPLACE '%2' IN me->error_message WITH http_status_text_response. 579 | APPEND me->error_message TO me->log_messages_ref->*. 580 | ENDIF. 581 | 582 | EXIT. 583 | 584 | ELSE. 585 | 586 | * Calculate number of files in archive 587 | " describe table zip_archive->files[] lines number -> Does not work as files[] is inconsistent 588 | DATA: count TYPE i, number_of_files TYPE string, file LIKE LINE OF zip_archive->files[]. 589 | CLEAR count. 590 | LOOP AT zip_archive->files[] INTO file. 591 | DATA: last_char_offset TYPE i, last_char TYPE c. 592 | last_char_offset = strlen( file-name ) - 1. 593 | last_char = file-name+last_char_offset(1). 594 | IF last_char NE '/'. count = count + 1. ENDIF. 595 | ENDLOOP. 596 | IF count = 0. 597 | me->ok = abap_false. me->error_message = TEXT-013. 598 | APPEND me->error_message TO me->log_messages_ref->*. 599 | EXIT. 600 | ENDIF. 601 | 602 | * Indicate 603 | number_of_files = count. CONDENSE number_of_files NO-GAPS. 604 | message = TEXT-014. ". % Files and Folders found in Archive. 605 | REPLACE '%' IN message WITH number_of_files. 606 | APPEND message TO log_messages_ref->*. 607 | APPEND '.' TO log_messages_ref->*. "Empty line 608 | 609 | ENDIF. 610 | 611 | * Header for Parameter section in log 612 | APPEND TEXT-019 TO log_messages_ref->*. "* Parameters * 613 | 614 | 615 | * Determine text and binary file patterns 616 | * ... encoding is expected to be UTF-8 compatible 617 | DATA: code_page_utf8 TYPE string VALUE 'UTF-8'. 618 | me->determine_text_file_patterns( code_page_utf8 ). 619 | me->determine_binary_file_patterns( code_page_utf8 ). 620 | me->determine_upload_ignores( code_page_utf8 ). 621 | 622 | * Determine upload parameters from file 623 | * ... encoding is expected to be UTF-8 compatible 624 | me->determine_upload_parameters( code_page_utf8 ). 625 | 626 | ENDMETHOD. "constructor 627 | 628 | ***************************************** 629 | METHOD is_ok. 630 | ***************************************** 631 | rv_is_ok = me->ok. 632 | ENDMETHOD. "is_ok 633 | 634 | 635 | ***************************************** 636 | METHOD determine_upload_operations. 637 | ***************************************** 638 | * 639 | * This method determines the operations needed to upload 640 | * the archive content into a the SAPUI5 ABAP repository 641 | * not yet containing the SAPUI5 application. 642 | 643 | * Initialize 644 | CLEAR cv_load_operations. 645 | 646 | * Access files in archive 647 | TYPES: BEGIN OF t_file, 648 | name TYPE string, 649 | date TYPE d, 650 | time TYPE t, 651 | size TYPE i, 652 | END OF t_file . 653 | TYPES: t_files TYPE TABLE OF t_file . 654 | DATA: files TYPE t_files. 655 | files = me->zip_archive->files[]. 656 | SORT files BY name AS TEXT. 657 | 658 | * For each file or folder in archive 659 | DATA: load_operation TYPE REF TO lcl_operation, 660 | archive_entry LIKE LINE OF me->zip_archive->files[], 661 | message TYPE string, 662 | folders_created TYPE string. 663 | LOOP AT files INTO archive_entry. 664 | 665 | * Create load operation 666 | CREATE OBJECT load_operation. 667 | 668 | load_operation->full_path = archive_entry-name. 669 | load_operation->relative_path = load_operation->full_path. 670 | 671 | "if load_operation->full_path cs '.meta/i18n/'. break wegmann. endif. 672 | 673 | * Determine name of file or folder 674 | DATA: path_components TYPE string_table. 675 | SPLIT load_operation->full_path AT '/' INTO TABLE path_components. 676 | DATA: max_index TYPE i. 677 | DESCRIBE TABLE path_components LINES max_index. 678 | READ TABLE path_components INDEX max_index INTO load_operation->object_name. 679 | 680 | * Folder is to be created 681 | FIND REGEX '^.*/$' IN archive_entry-name. 682 | IF sy-subrc = 0. 683 | 684 | * Initialize 685 | load_operation->to_update = abap_true. 686 | 687 | * Set operation and object type 688 | load_operation->operation = lcl_operation=>create_folder. 689 | load_operation->object_type = lcl_operation=>object_type_folder. 690 | 691 | * Decide if folder is to be ignored 692 | DATA: is_folder_to_be_ignored TYPE abap_bool. 693 | is_folder_to_be_ignored = me->is_file_to_be_ignored( load_operation->full_path ). 694 | IF is_folder_to_be_ignored = abap_true. 695 | load_operation->operation = lcl_operation=>ignore_folder. 696 | ENDIF. 697 | 698 | * Build relative path 699 | DATA: first_char TYPE c, last_char TYPE c, last_char_offset TYPE i. 700 | last_char_offset = strlen( load_operation->relative_path ) - 1. 701 | last_char = load_operation->relative_path+last_char_offset(1). 702 | IF last_char EQ '/'. 703 | REPLACE SECTION OFFSET last_char_offset OF load_operation->relative_path WITH ''. 704 | ENDIF. 705 | 706 | * Register folder 707 | CONCATENATE folders_created load_operation->full_path '; ' INTO folders_created RESPECTING BLANKS. 708 | 709 | * File is to be uploaded 710 | ELSE. 711 | 712 | * Initialize 713 | load_operation->to_update = abap_true. 714 | 715 | * Trigger operations to create folders for file 716 | * ... as me->zip_archive->files[] appears to be incomplete 717 | DATA: path TYPE string. 718 | path = load_operation->full_path. 719 | REPLACE load_operation->object_name IN path WITH ''. 720 | create_folders_for_path( EXPORTING iv_path = path 721 | CHANGING cv_folders_created = folders_created 722 | cv_load_operations = cv_load_operations ). 723 | 724 | * Set operation 725 | load_operation->operation = lcl_operation=>upload_file. 726 | 727 | * Check if entry is to be ignored 728 | DATA: is_file_to_be_ignored TYPE abap_bool. 729 | is_file_to_be_ignored = me->is_file_to_be_ignored( load_operation->full_path ). 730 | IF is_file_to_be_ignored = abap_true. 731 | load_operation->operation = lcl_operation=>ignore_file. 732 | ENDIF. 733 | 734 | * Check if binary or text file 735 | load_operation->object_type = lcl_operation=>object_type_file. 736 | IF me->is_text_file( load_operation->full_path ) = abap_true. 737 | load_operation->object_type = lcl_operation=>object_type_text_file. 738 | load_operation->code_page = iv_code_page. 739 | ENDIF. 740 | IF me->is_binary_file( load_operation->full_path ) = abap_true. 741 | load_operation->object_type = lcl_operation=>object_type_binary_file. 742 | CLEAR load_operation->code_page. 743 | ENDIF. 744 | 745 | ENDIF. 746 | 747 | * ... Try to determine from mime type if not clear from previous check 748 | IF load_operation->object_type = lcl_operation=>object_type_file. 749 | DATA: extension TYPE string, 750 | ext TYPE char20, 751 | mimetype TYPE mimetypes-type. 752 | extension = load_operation->get_file_extension( ). ext = extension. 753 | CALL FUNCTION 'SDOK_MIMETYPE_GET' 754 | EXPORTING 755 | extension = ext 756 | IMPORTING 757 | mimetype = mimetype. 758 | IF mimetype = 'image'. 759 | load_operation->object_type = lcl_operation=>object_type_binary_file. 760 | ELSE. 761 | load_operation->operation = lcl_operation=>ignore_file. 762 | load_operation->message = TEXT-072. "File type unknown 763 | cv_success = status_warning. 764 | ENDIF. 765 | ENDIF. 766 | 767 | * Read file and for text files check if end of line line markers are CR+LF (Windows) 768 | IF load_operation->object_type = lcl_operation=>object_type_text_file 769 | OR load_operation->object_type = lcl_operation=>object_type_binary_file. 770 | 771 | TRY. 772 | DATA: file_content TYPE xstring, 773 | file_content_as_string TYPE string. 774 | file_content = me->read_file( iv_path = archive_entry-name ). 775 | file_content_as_string = 776 | /ui5/cl_ui5_rep_utility=>convert_xstring_2_string( iv_xstring = file_content 777 | iv_code_page = iv_code_page ). 778 | load_operation->eol_conversion = abap_false. 779 | 780 | DATA: eol_conversion_needed TYPE abap_bool. eol_conversion_needed = abap_false. 781 | IF load_operation->object_type = lcl_operation=>object_type_text_file. 782 | DATA: file_content_as_string_windows TYPE string. 783 | file_content_as_string_windows = 784 | lcl_function=>conv_unix_style_line_endings( iv_string = file_content_as_string ). 785 | 786 | ***** Debug conversion of Unix style files ***** 787 | IF lcl_ui5_repository=>debug_conversions_for_file IS NOT INITIAL 788 | AND load_operation->object_name EQ lcl_ui5_repository=>debug_conversions_for_file. 789 | 790 | DATA: file_path TYPE string. 791 | CONCATENATE lcl_ui5_repository=>debug_conversions_for_file 792 | '.upload' INTO file_path. "#EC NOTEXT 793 | lcl_function=>xstring_to_file( iv_file_content = file_content 794 | iv_file_path = file_path ). 795 | CONCATENATE lcl_ui5_repository=>debug_conversions_for_file 796 | '.upload.as_string' INTO file_path. "#EC NOTEXT 797 | lcl_function=>string_to_file( iv_file_content = file_content_as_string 798 | iv_code_page = iv_code_page 799 | iv_file_path = file_path ). 800 | CONCATENATE lcl_ui5_repository=>debug_conversions_for_file 801 | '.upload.as_string_windows' INTO file_path. "#EC NOTEXT 802 | lcl_function=>string_to_file( iv_file_content = file_content_as_string_windows 803 | iv_code_page = iv_code_page 804 | iv_file_path = file_path ). 805 | ENDIF. 806 | ************************************************ 807 | 808 | IF file_content_as_string = file_content_as_string_windows. 809 | eol_conversion_needed = abap_false. 810 | load_operation->eol_conversion = abap_false. 811 | ELSE. 812 | eol_conversion_needed = abap_true. 813 | IF iv_accept_unix_style_eol = abap_true. 814 | load_operation->eol_conversion = abap_true. 815 | ELSE. 816 | "message = text-056. "* Warning: Text file % has unix style line delimeter. It is not uploaded * 817 | "replace '%' in message with archive_entry-name. 818 | "append message to me->log_messages_ref->*. 819 | load_operation->operation = lcl_operation=>ignore_file. 820 | load_operation->message = TEXT-076. "Warning: Unix style text file 821 | load_operation->to_update = abap_false. 822 | load_operation->eol_conversion = abap_false. 823 | cv_success = status_warning. 824 | ENDIF. 825 | ENDIF. 826 | ENDIF. 827 | 828 | * Calculate md5 hash for file to compare with that in SAPUI5 ABAP repository 829 | * ... Needed only in delta mode 830 | IF iv_delta_mode EQ abap_true. 831 | TRY. 832 | IF load_operation->eol_conversion = abap_true. 833 | load_operation->hash_value = lcl_function=>get_md5_hash_for_string( file_content_as_string_windows ). 834 | ELSE. 835 | load_operation->hash_value = lcl_function=>get_md5_hash_for_string( file_content_as_string ). 836 | ENDIF. 837 | load_operation->code_page = iv_code_page. 838 | CATCH /ui5/cx_ui5_rep_dt. 839 | message = TEXT-051. "* Warning: Unable to determine MD5 hash for file % * 840 | REPLACE '%' IN message WITH load_operation->full_path . 841 | APPEND message TO me->log_messages_ref->*. 842 | cv_success = status_warning. 843 | ENDTRY. 844 | ENDIF. 845 | 846 | CATCH /ui5/cx_ui5_rep_dt. 847 | message = TEXT-050. "* Warning: Content of file % could not be read * 848 | REPLACE '%' IN message WITH load_operation->full_path . 849 | APPEND message TO me->log_messages_ref->*. 850 | cv_success = status_warning. 851 | 852 | ENDTRY. 853 | 854 | ENDIF. 855 | 856 | 857 | * Register operation 858 | APPEND load_operation TO cv_load_operations. 859 | 860 | ENDLOOP. 861 | 862 | ENDMETHOD. "determine_upload_operations 863 | 864 | ***************************************** 865 | METHOD read_file. 866 | ***************************************** 867 | 868 | * Return if no path given 869 | IF iv_path IS INITIAL. RETURN. ENDIF. 870 | 871 | * Find file in archive 872 | DATA: index TYPE i. 873 | READ TABLE me->zip_archive->files TRANSPORTING NO FIELDS 874 | WITH KEY name = iv_path. 875 | IF sy-subrc <> 0. RETURN. ENDIF. 876 | index = sy-tabix. 877 | 878 | me->zip_archive->get( EXPORTING index = index IMPORTING content = rv_content ). 879 | 880 | ENDMETHOD. "read_file 881 | 882 | ***************************************** 883 | METHOD read_file_to_table. 884 | ***************************************** 885 | * Read as binary and convert to text 886 | DATA: file_content TYPE xstring, 887 | file_content_as_string TYPE string, 888 | lines TYPE string_table. 889 | TRY. 890 | file_content = me->read_file( iv_path = iv_path ). 891 | file_content_as_string = 892 | /ui5/cl_ui5_rep_utility=>convert_xstring_2_string( iv_xstring = file_content 893 | iv_code_page = iv_code_page ). 894 | file_content_as_string = 895 | lcl_function=>conv_unix_style_line_endings( iv_string = file_content_as_string ). 896 | lines = /ui5/cl_ui5_rep_utility=>code_string_2_code_tab( file_content_as_string ). 897 | CATCH /ui5/cx_ui5_rep_dt. 898 | ENDTRY. 899 | 900 | * Prepare response 901 | rt_lines = lines. 902 | 903 | ENDMETHOD. "read_file_to_table 904 | 905 | 906 | ***************************************** 907 | METHOD get_upload_parameter. 908 | ***************************************** 909 | 910 | * Return if no parameter given 911 | IF iv_key IS INITIAL. RETURN. ENDIF. 912 | 913 | * Find paramenter 914 | DATA: index TYPE i, 915 | upload_parameter TYPE slin_key_value. 916 | 917 | READ TABLE me->upload_parameters INTO upload_parameter 918 | WITH KEY key = iv_key. 919 | IF sy-subrc <> 0. 920 | rv_value = iv_return_if_not_specified. RETURN. 921 | ENDIF. 922 | rv_value = upload_parameter-value. 923 | 924 | ENDMETHOD. "get_upload_paramenter 925 | 926 | 927 | ***************************************** 928 | METHOD add_default_bin_file_patterns. 929 | ***************************************** 930 | 931 | * ... Add default binary patterns 932 | DATA: binary_file_pattern TYPE string. 933 | binary_file_pattern = '.zip'. APPEND binary_file_pattern TO cv_file_patterns. 934 | binary_file_pattern = '.war'. APPEND binary_file_pattern TO cv_file_patterns. 935 | binary_file_pattern = '.xpi'. APPEND binary_file_pattern TO cv_file_patterns. 936 | binary_file_pattern = '.jpg'. APPEND binary_file_pattern TO cv_file_patterns. 937 | binary_file_pattern = '.gif'. APPEND binary_file_pattern TO cv_file_patterns. 938 | binary_file_pattern = '.png'. APPEND binary_file_pattern TO cv_file_patterns. 939 | binary_file_pattern = '.ico'. APPEND binary_file_pattern TO cv_file_patterns. 940 | binary_file_pattern = '^.*\.class$'. APPEND binary_file_pattern TO cv_file_patterns. 941 | 942 | ENDMETHOD. "add_default_bin_file_patterns 943 | 944 | 945 | ***************************************** 946 | METHOD add_default_ignore_patterns. 947 | ***************************************** 948 | 949 | * ... Add default binary patterns 950 | DATA: ignore_file_pattern TYPE string. 951 | ignore_file_pattern = '.git'. APPEND ignore_file_pattern TO cv_file_patterns. 952 | ignore_file_pattern = '^.*[/|\\]build([/|\\].*)?$'. 953 | APPEND ignore_file_pattern TO cv_file_patterns. 954 | 955 | ENDMETHOD. "add_default_ignore_patterns 956 | 957 | 958 | ***************************************** 959 | METHOD add_import_upload_parameters. 960 | ***************************************** 961 | * TODO:check if needed or for better solution 962 | * ... Add import parameter 963 | DATA: import_parameter TYPE slin_key_value. 964 | 965 | " import_parameter-key = 'SAPUI5ApplicationName'. 966 | " import_parameter-value = IV_SAPUI5_REPOSITORY. 967 | " append import_parameter to cv_file_patterns. 968 | 969 | " import_parameter-key = 'TransportRequest'. 970 | " import_parameter-value = IV_WORKBENCH_REQUEST. 971 | " append import_parameter to cv_file_patterns. 972 | 973 | ENDMETHOD. "add_import_upload_parameters 974 | 975 | 976 | ***************************************** 977 | METHOD add_default_text_file_patterns. 978 | ***************************************** 979 | 980 | * Add default text file patterns 981 | DATA: text_file_pattern TYPE string. 982 | text_file_pattern = '.txt'. APPEND text_file_pattern TO cv_file_patterns. 983 | text_file_pattern = '.html'. APPEND text_file_pattern TO cv_file_patterns. 984 | text_file_pattern = '.js'. APPEND text_file_pattern TO cv_file_patterns. 985 | text_file_pattern = '.json'. APPEND text_file_pattern TO cv_file_patterns. 986 | text_file_pattern = '.less'. APPEND text_file_pattern TO cv_file_patterns. 987 | text_file_pattern = '.css'. APPEND text_file_pattern TO cv_file_patterns. 988 | text_file_pattern = '.htm'. APPEND text_file_pattern TO cv_file_patterns. 989 | text_file_pattern = '.xml'. APPEND text_file_pattern TO cv_file_patterns. 990 | text_file_pattern = 'manifest.mf'. APPEND text_file_pattern TO cv_file_patterns. 991 | text_file_pattern = '.classpath'. APPEND text_file_pattern TO cv_file_patterns. 992 | text_file_pattern = '.properties'. APPEND text_file_pattern TO cv_file_patterns. 993 | text_file_pattern = '.project'. APPEND text_file_pattern TO cv_file_patterns. 994 | text_file_pattern = '.settings/'. APPEND text_file_pattern TO cv_file_patterns. 995 | text_file_pattern = '^.*\.control$'. APPEND text_file_pattern TO cv_file_patterns. 996 | text_file_pattern = '^.*\.json$'. APPEND text_file_pattern TO cv_file_patterns. 997 | text_file_pattern = '^.*\.less$'. APPEND text_file_pattern TO cv_file_patterns. 998 | text_file_pattern = '^.*\.library$'. APPEND text_file_pattern TO cv_file_patterns. 999 | text_file_pattern = '^.*\.theming$'. APPEND text_file_pattern TO cv_file_patterns. 1000 | text_file_pattern = '.Ui5RepositoryAppSetup'. APPEND text_file_pattern TO cv_file_patterns. 1001 | text_file_pattern = '.Ui5RepositoryIgnore'. APPEND text_file_pattern TO cv_file_patterns. 1002 | text_file_pattern = '.Ui5RepositoryBinaryFiles'. APPEND text_file_pattern TO cv_file_patterns. 1003 | text_file_pattern = '.Ui5RepositoryTextFiles'. APPEND text_file_pattern TO cv_file_patterns. 1004 | text_file_pattern = '.Ui5RepositoryUploadParameters'. APPEND text_file_pattern TO cv_file_patterns. 1005 | 1006 | ENDMETHOD. "add_default_text_file_patterns 1007 | 1008 | ***************************************** 1009 | METHOD create_folders_for_path. 1010 | ***************************************** 1011 | 1012 | * Adds operations to create folders for a path given as input 1013 | * once 1014 | 1015 | * Check inputs 1016 | IF iv_path IS INITIAL. RETURN. ENDIF. 1017 | 1018 | * Return if already done 1019 | DATA: folder TYPE string. 1020 | CONCATENATE iv_path '; ' INTO folder RESPECTING BLANKS. 1021 | IF cv_folders_created CS folder. RETURN. ENDIF. 1022 | 1023 | * Parse path expression 1024 | DATA: path_components TYPE string_table, 1025 | max_index TYPE i. 1026 | SPLIT iv_path AT '/' INTO TABLE path_components. 1027 | DESCRIBE TABLE path_components LINES max_index. 1028 | 1029 | * Create parent folder 1030 | IF max_index > 1. 1031 | DATA: parent_folder TYPE string, 1032 | path_component TYPE string. 1033 | CLEAR parent_folder. 1034 | LOOP AT path_components INTO path_component. 1035 | IF sy-tabix = max_index. CLEAR path_component. ENDIF. 1036 | IF path_component IS NOT INITIAL. 1037 | CONCATENATE parent_folder path_component '/' INTO parent_folder RESPECTING BLANKS. 1038 | ENDIF. 1039 | ENDLOOP. 1040 | create_folders_for_path( EXPORTING iv_path = parent_folder 1041 | CHANGING cv_folders_created = cv_folders_created 1042 | cv_load_operations = cv_load_operations ). 1043 | ENDIF. 1044 | 1045 | * Prepare operation to create folder 1046 | DATA: load_operation_ TYPE REF TO lcl_operation. 1047 | CREATE OBJECT load_operation_. 1048 | 1049 | * ... Determine name of folder 1050 | READ TABLE path_components INDEX max_index INTO load_operation_->object_name. 1051 | load_operation_->full_path = iv_path. 1052 | load_operation_->relative_path = iv_path. 1053 | load_operation_->to_update = abap_true. 1054 | 1055 | * ... Set operation and object type 1056 | load_operation_->operation = lcl_operation=>create_folder. 1057 | load_operation_->object_type = lcl_operation=>object_type_folder. 1058 | 1059 | * ... Decide if folder is to be ignored 1060 | DATA: is_folder_to_be_ignored TYPE abap_bool. 1061 | is_folder_to_be_ignored = me->is_file_to_be_ignored( load_operation_->full_path ). 1062 | IF is_folder_to_be_ignored = abap_true. 1063 | load_operation_->operation = lcl_operation=>ignore_folder. 1064 | ENDIF. 1065 | 1066 | * ... Build relative path 1067 | DATA: last_char_offset TYPE i, 1068 | last_char TYPE c. 1069 | last_char_offset = strlen( load_operation_->relative_path ) - 1. 1070 | last_char = load_operation_->relative_path+last_char_offset(1). 1071 | IF last_char EQ '/'. 1072 | REPLACE SECTION OFFSET last_char_offset OF load_operation_->relative_path WITH ''. 1073 | ENDIF. 1074 | 1075 | * ... Register operation if needed 1076 | CONCATENATE load_operation_->full_path '; ' INTO folder RESPECTING BLANKS. 1077 | IF cv_folders_created NS folder. 1078 | APPEND load_operation_ TO cv_load_operations. 1079 | CONCATENATE cv_folders_created folder INTO cv_folders_created RESPECTING BLANKS. 1080 | ENDIF. 1081 | 1082 | ENDMETHOD. "create_folder_operations 1083 | 1084 | ***************************************** 1085 | METHOD determine_binary_file_patterns. 1086 | ***************************************** 1087 | 1088 | * Build list of patterns identifying binary files 1089 | 1090 | * ... Standard text file patterns 1091 | me->add_default_bin_file_patterns( CHANGING cv_file_patterns = me->binary_file_patterns ). 1092 | 1093 | * ... Patterns from '.Ui5RepositoryBinaryFiles' file 1094 | DATA: line TYPE string, 1095 | lines TYPE string_table. 1096 | lines = me->read_file_to_table( iv_path = '.Ui5RepositoryBinaryFiles' iv_code_page = iv_code_page ). 1097 | LOOP AT lines INTO line. 1098 | APPEND line TO me->binary_file_patterns. 1099 | ENDLOOP. 1100 | 1101 | * ... Message 1102 | IF lines IS INITIAL. 1103 | APPEND TEXT-022 TO me->log_messages_ref->*. "* Binary files have been identified from standard settings * 1104 | ELSE. 1105 | APPEND TEXT-023 TO me->log_messages_ref->*. "* File '.Ui5RepositoryBinaryFiles' has been considered to identify binary files * 1106 | ENDIF. 1107 | 1108 | ENDMETHOD. "determine_binary_file_patterns 1109 | 1110 | 1111 | ***************************************** 1112 | METHOD determine_text_file_patterns. 1113 | ***************************************** 1114 | 1115 | * Build list of patterns identifying text files 1116 | 1117 | * ... Standard text file patterns 1118 | me->add_default_text_file_patterns( CHANGING cv_file_patterns = me->text_file_patterns ). 1119 | 1120 | * ... Patterns from '.Ui5RepositoryTextFiles' file 1121 | DATA: line TYPE string, 1122 | lines TYPE string_table. 1123 | lines = me->read_file_to_table( iv_path = '.Ui5RepositoryTextFiles' iv_code_page = iv_code_page ). 1124 | LOOP AT lines INTO line. 1125 | APPEND line TO me->text_file_patterns. 1126 | ENDLOOP. 1127 | 1128 | * ... Message 1129 | IF lines IS INITIAL. 1130 | APPEND TEXT-020 TO me->log_messages_ref->*. 1131 | ELSE. 1132 | APPEND TEXT-021 TO me->log_messages_ref->*. 1133 | ENDIF. 1134 | 1135 | ENDMETHOD. "determine_text_file_patterns 1136 | 1137 | ***************************************** 1138 | METHOD determine_upload_ignores. 1139 | ***************************************** 1140 | 1141 | * Determines patterns for files to be ignored during the upload of a UI5 application 1142 | * 1143 | * In case a .Ui5RepositoryIgnore file is found in the directory of the UI5 application 1144 | * its content is used to decide if a file is considered in the upload operation. 1145 | * 1146 | * Example content: 1147 | * 1148 | * .c# 1149 | * ^.*\.ttf$ 1150 | * ^.*[/|\\]build([/|\\].*)?$ 1151 | * 1152 | * In this case all files which contain the sub expression ".c#" in their full path 1153 | * string are ignored by the upload operation. Furthermore files with the extension 1154 | * ".ttf" are ignored as well. In this example "^.*\.ttf$" is detected as a regular 1155 | * expression because it starts with a "^" and ends with a "$". 1156 | * Finally the build directory and everything below gets ignored. 1157 | * 1158 | * If a .Ui5RepIgnore file is not found a standard list of ignore patterns is used: 1159 | * So there's no need for a user to think about this topic in a simple case. 1160 | * 1161 | * Remark: In Eclipse the ignore files are specified by a team provider setting. 1162 | 1163 | * Build list of files to ignore during upload 1164 | 1165 | * ... Either patterns from '.Ui5RepositoryIgnore' file 1166 | me->upload_ignores = me->read_file_to_table( iv_path = '.Ui5RepositoryIgnore' iv_code_page = iv_code_page ). 1167 | 1168 | * ... Or standard ignore file patterns 1169 | IF me->upload_ignores IS INITIAL. 1170 | me->add_default_ignore_patterns( CHANGING cv_file_patterns = me->upload_ignores ). 1171 | APPEND TEXT-024 TO me->log_messages_ref->*. 1172 | ELSE. 1173 | APPEND TEXT-025 TO me->log_messages_ref->*. 1174 | ENDIF. 1175 | 1176 | ENDMETHOD. "determine_upload_ignores 1177 | 1178 | ***************************************** 1179 | METHOD determine_upload_parameters. 1180 | ***************************************** 1181 | 1182 | * Determines file with parameters to the upload of a UI5 application in ABAP Repository 1183 | * 1184 | * In case a .Ui5RepositoryUploadParameters file is found in the directory of the UI5 application 1185 | * its content is used to decide which settings are used in the upload operation. 1186 | * 1187 | * Parameters: 1188 | * 1189 | * SAPUI5ApplicationName Mandatory 1190 | * SAPUI5RepositoryDescription Mandatory: Used for creation of SAPUI5 ABAP Repository, otherwise is an info 1191 | * SAPUI5RepositoryPackage Mandatory 1192 | * TransportRequest Mandatory: ABAP-Transportrequest 1193 | * ExternalCodePage Mandatory: Codepage for the files 1194 | * 1195 | 1196 | * If a .Ui5RepositoryUploadParameters file is not found an import parameter of this Function Module is used. 1197 | 1198 | * Build list of of upload paramenter 1199 | 1200 | * ... Upload parameters from '.Ui5RepositoryUploadParameters' file 1201 | DATA: line TYPE string, 1202 | lines TYPE string_table, 1203 | upload_parameter TYPE slin_key_value. 1204 | 1205 | lines = me->read_file_to_table( iv_path = '.Ui5RepositoryUploadParameters' iv_code_page = iv_code_page ). 1206 | LOOP AT lines INTO line. 1207 | SPLIT line AT '=' INTO upload_parameter-key upload_parameter-value. 1208 | INSERT upload_parameter INTO TABLE me->upload_parameters. 1209 | ENDLOOP. 1210 | 1211 | * ... Or from import parameters 1212 | IF me->upload_parameters IS INITIAL. 1213 | " APPEND text-027 TO me->log_messages_ref->*. 1214 | ELSE. 1215 | " APPEND text-026 TO me->log_messages_ref->*. 1216 | ENDIF. 1217 | 1218 | ENDMETHOD. "determine_upload_parameters 1219 | 1220 | METHOD is_binary_file. 1221 | 1222 | rv_is_binary_file = abap_undefined. 1223 | IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->binary_file_patterns ) = abap_true ). 1224 | rv_is_binary_file = abap_true. 1225 | ENDIF. 1226 | 1227 | ENDMETHOD. "is_binary_file 1228 | 1229 | METHOD is_file_to_be_ignored. 1230 | 1231 | rv_ignore = abap_false. 1232 | IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->upload_ignores ) = abap_true ). 1233 | rv_ignore = abap_true. 1234 | ENDIF. 1235 | 1236 | ENDMETHOD. "is_file_to_be_ignored 1237 | 1238 | METHOD is_text_file. 1239 | 1240 | rv_is_text_file = abap_undefined. 1241 | IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->text_file_patterns ) = abap_true ). 1242 | rv_is_text_file = abap_true. 1243 | ENDIF. 1244 | 1245 | ENDMETHOD. "is_text_file 1246 | 1247 | ENDCLASS. "LCL_SAPUI5_ZIP_ARCHIVE 1248 | 1249 | 1250 | 1251 | 1252 | ************************************************************************ 1253 | * Class lcl_external_code_page 1254 | * 1255 | * supports conversion of external code page into abap code page. 1256 | ************************************************************************ 1257 | CLASS lcl_external_code_page IMPLEMENTATION. 1258 | 1259 | METHOD create. 1260 | 1261 | * Exception if no page name given 1262 | IF iv_code_page_name IS INITIAL. 1263 | RAISE EXCEPTION TYPE lcx_exception. 1264 | ENDIF. 1265 | 1266 | * Create external code page instance and take over náme 1267 | CREATE OBJECT rv_external_code_page. 1268 | rv_external_code_page->name = iv_code_page_name. 1269 | 1270 | * Determine code page type from name 1271 | DATA: name(10) TYPE c. 1272 | name = iv_code_page_name. 1273 | TRANSLATE name TO LOWER CASE. 1274 | 1275 | IF name(2) = 'cp'. 1276 | rv_external_code_page->kind = 'J'. 1277 | ELSEIF name(3) = 'iso'. 1278 | rv_external_code_page->kind = 'H'. 1279 | ELSEIF name(8) = 'us-ascii'. 1280 | rv_external_code_page->kind = 'H'. 1281 | ELSEIF name = 'utf-16be' OR 1282 | name = 'utf-16le'. 1283 | rv_external_code_page->kind = 'H'. 1284 | ENDIF. 1285 | 1286 | ENDMETHOD. "create 1287 | METHOD for_sapgui_installation. 1288 | 1289 | * Determine abap code page from sapgui installation 1290 | DATA: code_page_abap TYPE abap_encoding, 1291 | rc TYPE i VALUE 0. 1292 | CALL METHOD cl_gui_frontend_services=>get_saplogon_encoding 1293 | CHANGING 1294 | rc = rc 1295 | file_encoding = code_page_abap 1296 | EXCEPTIONS 1297 | cntl_error = 1 1298 | error_no_gui = 2 1299 | not_supported_by_gui = 3 1300 | cannot_initialize_globalstate = 4 1301 | OTHERS = 5. 1302 | IF sy-subrc <> 0 OR code_page_abap = 0. 1303 | RAISE EXCEPTION TYPE lcx_exception. 1304 | ENDIF. 1305 | 1306 | * Determine corresponding java code page name 1307 | DATA: java_code_page_name TYPE string, 1308 | code_page_abap_ TYPE cpcodepage. 1309 | code_page_abap_ = code_page_abap. 1310 | CALL FUNCTION 'SCP_GET_JAVA_NAME' 1311 | EXPORTING 1312 | sap_codepage = code_page_abap_ 1313 | IMPORTING 1314 | name = java_code_page_name 1315 | EXCEPTIONS 1316 | name_unknown = 1 1317 | invalid_codepage = 2 1318 | OTHERS = 3. 1319 | IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_exception. ENDIF. 1320 | 1321 | * Delegate for create 1322 | rv_external_code_page = lcl_external_code_page=>create( iv_code_page_name = java_code_page_name ). 1323 | 1324 | ENDMETHOD. "create_for_abap_codepage 1325 | 1326 | METHOD get_abap_encoding. 1327 | 1328 | * Delegate ... 1329 | IF me->kind IS NOT INITIAL. 1330 | DATA: abap_encoding TYPE cpcodepage. 1331 | CALL FUNCTION 'SCP_CODEPAGE_BY_EXTERNAL_NAME' 1332 | EXPORTING 1333 | external_name = me->name 1334 | kind = me->kind 1335 | IMPORTING 1336 | sap_codepage = rv_abap_encoding 1337 | EXCEPTIONS 1338 | not_found = 1. 1339 | ELSE. 1340 | "Default value for kind of code page. 1341 | CALL FUNCTION 'SCP_CODEPAGE_BY_EXTERNAL_NAME' 1342 | EXPORTING 1343 | external_name = me->name 1344 | IMPORTING 1345 | sap_codepage = rv_abap_encoding 1346 | EXCEPTIONS 1347 | not_found = 1. 1348 | ENDIF. 1349 | * ... Raise exception if no abap code page found. 1350 | IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_exception. ENDIF. 1351 | 1352 | ENDMETHOD. "get_abap_encoding 1353 | 1354 | METHOD get_java_encoding. 1355 | 1356 | * Get ABAP codepage 1357 | DATA: abap_encoding TYPE cpcodepage. 1358 | abap_encoding = me->get_abap_encoding( ). 1359 | 1360 | * Delegate ... 1361 | CALL FUNCTION 'SCP_GET_JAVA_NAME' 1362 | EXPORTING 1363 | sap_codepage = abap_encoding 1364 | IMPORTING 1365 | name = rv_java_encoding 1366 | EXCEPTIONS 1367 | name_unknown = 1 1368 | invalid_codepage = 2 1369 | OTHERS = 3. 1370 | IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_exception. ENDIF. 1371 | 1372 | ENDMETHOD. "get_java_encoding 1373 | 1374 | ENDCLASS. "lcl_external_code_page 1375 | 1376 | 1377 | 1378 | ************************************************************************ 1379 | * Class LCL_UI5_REPOSITORY 1380 | * 1381 | * represents a UI5 Repository and the UI5 application it contains. 1382 | ************************************************************************ 1383 | CLASS lcl_ui5_repository IMPLEMENTATION. 1384 | 1385 | METHOD class_constructor. 1386 | CREATE OBJECT self. 1387 | ENDMETHOD. "class_constructor 1388 | 1389 | METHOD get_mime_type_for_upload. 1390 | 1391 | * Check input 1392 | CLEAR rv_mime_type. 1393 | IF iv_operation IS INITIAL. RETURN. ENDIF. 1394 | 1395 | * Check if file is known to be text 1396 | IF iv_operation->object_type = lcl_operation=>object_type_text_file. 1397 | rv_mime_type = 'text/plain'. 1398 | RETURN. 1399 | ENDIF. 1400 | 1401 | * Check if file is known to be binary 1402 | IF iv_operation->object_type = lcl_operation=>object_type_binary_file. 1403 | rv_mime_type = 'image'. "Although this is not true neccessarily: This should trigger a binary upload 1404 | RETURN. 1405 | ENDIF. 1406 | 1407 | * Determine file extension 1408 | DATA: extension TYPE string. 1409 | extension = iv_operation->get_file_extension( ). 1410 | 1411 | * Determine mime type using file extension via SDOK_MIMETYPE_GET 1412 | DATA: mimetype TYPE mimetypes-type, 1413 | ext TYPE char20. 1414 | ext = extension. 1415 | CALL FUNCTION 'SDOK_MIMETYPE_GET' 1416 | EXPORTING 1417 | extension = ext 1418 | IMPORTING 1419 | mimetype = mimetype. 1420 | . 1421 | rv_mime_type = mimetype. 1422 | 1423 | ENDMETHOD. "get_mime_type_for_upload 1424 | 1425 | ***************************************** 1426 | METHOD conciliate_upload_operations. 1427 | ***************************************** 1428 | * 1429 | * The method looks into each upload operation and changes it 1430 | * if needed. This depends on the state of the corresponding 1431 | * file in the repository. 1432 | * 1433 | * Example 1: 1434 | * If a file or folder does exist in the repository but is not 1435 | * to be uploaded, then the object in the repository is to be 1436 | * deleted. 1437 | * There are two situations to be considered: 1438 | * a) The object does not exist in the in the archive. 1439 | * b) The object does exist but it is to be ignored 1440 | * as it is in the ignore-list or it is a unix style text file 1441 | * with no automatic conversion active. 1442 | * 1443 | * Example 2: 1444 | * If a file to be uploaded is identical with the one already 1445 | * in the repository, then it is not to be uploaded if 1446 | * delta mode has been activated. 1447 | 1448 | * Nothing to do if repository does not yet exist 1449 | IF me->already_exists = abap_false. RETURN. ENDIF. 1450 | 1451 | * Walk through content of ui5 repository 1452 | DATA: children TYPE string_table, 1453 | child TYPE string. 1454 | TRY. 1455 | children = me->api->get_folder_children( iv_path ). 1456 | CATCH /ui5/cx_ui5_rep_dt. 1457 | ENDTRY. 1458 | LOOP AT children INTO child. 1459 | 1460 | * Debugging 1461 | "if child cs 'meta.properties'. break wegmann. endif. 1462 | 1463 | * Check if child is intended for upload 1464 | * ... and look for corresponding operation 1465 | DATA: child_is_intended_for_upload TYPE abap_bool. child_is_intended_for_upload = abap_false. 1466 | DATA: operation TYPE REF TO lcl_operation. 1467 | CLEAR operation. 1468 | DATA: operation_found TYPE abap_bool. operation_found = abap_false. 1469 | LOOP AT cv_upload_operations INTO operation. 1470 | IF operation->relative_path EQ child. 1471 | operation_found = abap_true. 1472 | IF NOT ( operation->operation = lcl_operation=>ignore_file 1473 | OR operation->operation = lcl_operation=>ignore_folder ). 1474 | child_is_intended_for_upload = abap_true. 1475 | ENDIF. 1476 | EXIT. 1477 | ENDIF. 1478 | ENDLOOP. 1479 | IF operation_found = abap_false. CLEAR operation. ENDIF. 1480 | 1481 | * Check if it is a folder 1482 | DATA: child_is_folder TYPE abap_bool. 1483 | TRY. 1484 | child_is_folder = me->api->check_is_folder( child ). 1485 | CATCH /ui5/cx_ui5_rep_dt. 1486 | ENDTRY. 1487 | 1488 | * Conciliate sub folder 1489 | IF child_is_folder = abap_true. 1490 | * Content 1491 | conciliate_upload_operations( EXPORTING iv_delta_mode = iv_delta_mode 1492 | iv_path = child 1493 | iv_badi = iv_badi 1494 | iv_archive = iv_archive 1495 | CHANGING cv_upload_operations = cv_upload_operations ). 1496 | * Delete folder in repository not intended for upload 1497 | IF child_is_intended_for_upload = abap_false. 1498 | DATA: is_new_operation TYPE abap_bool. 1499 | is_new_operation = abap_false. " There might be an operation of type IGRNORE_FILE already! 1500 | IF operation IS INITIAL. CREATE OBJECT operation. is_new_operation = abap_true. ENDIF. 1501 | operation->to_update = abap_true. 1502 | operation->operation = lcl_operation=>delete_folder. 1503 | operation->relative_path = child. 1504 | operation->object_type = lcl_operation=>object_type_folder. 1505 | IF is_new_operation = abap_true. APPEND operation TO cv_upload_operations. ENDIF. 1506 | ELSE. 1507 | IF iv_delta_mode = abap_true. 1508 | operation->message = TEXT-075. "Folder already exists 1509 | operation->to_update = abap_false. 1510 | ENDIF. 1511 | ENDIF. 1512 | 1513 | * Conciliate file 1514 | ELSE. 1515 | 1516 | * Delete file not intended for upload 1517 | IF child_is_intended_for_upload = abap_false. 1518 | 1519 | * Create operation if there's none yet 1520 | IF operation IS INITIAL. 1521 | CREATE OBJECT operation. 1522 | is_new_operation = abap_true. 1523 | * Determine object type using .Ui5RepositoryTextFiles 1524 | * and .Ui5RepositoryBinaryFiles in the archive 1525 | operation->object_type = lcl_operation=>object_type_file. 1526 | IF iv_archive->is_binary_file( child ) = abap_true. 1527 | operation->object_type = lcl_operation=>object_type_binary_file. 1528 | ELSEIF iv_archive->is_text_file( child ) = abap_true. 1529 | operation->object_type = lcl_operation=>object_type_text_file. 1530 | ENDIF. 1531 | ENDIF. 1532 | operation->to_update = abap_true. 1533 | operation->operation = lcl_operation=>delete_file. 1534 | operation->relative_path = child. 1535 | operation->full_path = child. 1536 | 1537 | * Omit deletion of mime resource if requested via BAdI /UI5/BADI_PREVENT_DELETION 1538 | IF iv_badi->disable_deletion_for( operation ) = abap_true. 1539 | operation->to_update = abap_false. 1540 | operation->operation = lcl_operation=>ignore_file. 1541 | operation->message = TEXT-065. "* Binary file has NOT been deleted in ABAP repository on BAdI request * 1542 | ENDIF. 1543 | * 1544 | operation->object_type = lcl_operation=>object_type_file. 1545 | IF is_new_operation = abap_true. APPEND operation TO cv_upload_operations. ENDIF. 1546 | 1547 | ELSE. 1548 | 1549 | * Skip if nothing to do 1550 | * ... this e.g. is a unix style text file 1551 | IF operation->to_update = abap_false. CONTINUE. ENDIF. 1552 | 1553 | * Consider delta mode 1554 | IF iv_delta_mode EQ abap_true. 1555 | "Try to get a file content, hash of them and compare with a hash form zip 1556 | DATA: lv_file_content TYPE xstring, 1557 | lv_file_content_as_string TYPE string, 1558 | lv_hash TYPE md5_fields-hash. 1559 | TRY. 1560 | CLEAR lv_hash. 1561 | me->api->get_file( EXPORTING iv_path = child 1562 | iv_code_page = operation->code_page 1563 | IMPORTING ev_file_content = lv_file_content ). 1564 | lv_file_content_as_string = 1565 | /ui5/cl_ui5_rep_utility=>convert_xstring_2_string( iv_xstring = lv_file_content 1566 | iv_code_page = operation->code_page ). 1567 | lv_hash = lcl_function=>get_md5_hash_for_string( lv_file_content_as_string ). 1568 | 1569 | ***** Debug conversion of Unix style files ***** 1570 | IF lcl_ui5_repository=>debug_conversions_for_file IS NOT INITIAL 1571 | AND operation->object_name EQ lcl_ui5_repository=>debug_conversions_for_file. 1572 | 1573 | DATA: file_path TYPE string. 1574 | CONCATENATE lcl_ui5_repository=>debug_conversions_for_file 1575 | '.repository' INTO file_path. "#EC NOTEXT 1576 | lcl_function=>xstring_to_file( iv_file_content = lv_file_content 1577 | iv_file_path = file_path ). 1578 | CONCATENATE lcl_ui5_repository=>debug_conversions_for_file 1579 | '.repository.as_string' INTO file_path. "#EC NOTEXT 1580 | lcl_function=>string_to_file( iv_file_content = lv_file_content_as_string 1581 | iv_code_page = operation->code_page 1582 | iv_file_path = file_path ). 1583 | ENDIF. 1584 | ************************************************ 1585 | 1586 | CATCH /ui5/cx_ui5_rep_dt. 1587 | "File does not exist: It is to be uploaded 1588 | ENDTRY. 1589 | * Compare hash value from content of repository and to upload files 1590 | IF operation->hash_value EQ lv_hash. 1591 | operation->message = TEXT-074. "Already up-to-date 1592 | operation->to_update = abap_false. 1593 | ELSE. 1594 | operation->to_update = abap_true. 1595 | ENDIF. 1596 | ENDIF. 1597 | ENDIF. 1598 | ENDIF. 1599 | 1600 | ENDLOOP. 1601 | 1602 | ENDMETHOD. "conciliate_upload_operations 1603 | 1604 | METHOD get_instance. 1605 | self->log_messages_ref = ir_log_messages. 1606 | rv_self = self. 1607 | ENDMETHOD. "get_instance 1608 | 1609 | * Evaluate authorization available 1610 | METHOD evaluate_authorization. 1611 | 1612 | rv_message = ''. 1613 | DATA: may_be_insufficient TYPE abap_bool. may_be_insufficient = abap_false. 1614 | DATA: affected TYPE string. affected = ''. 1615 | 1616 | * S_DEVELOP 1617 | 1618 | AUTHORITY-CHECK OBJECT 'S_DEVELOP' 1619 | ID 'DEVCLASS' DUMMY 1620 | ID 'OBJTYPE' FIELD 'WAPA' 1621 | ID 'OBJNAME' DUMMY 1622 | ID 'P_GROUP' DUMMY 1623 | ID 'ACTVT' FIELD '02'. 1624 | IF sy-subrc > 0. 1625 | may_be_insufficient = abap_true. 1626 | IF affected IS NOT INITIAL. CONCATENATE affected ', ' INTO affected RESPECTING BLANKS. ENDIF. 1627 | CONCATENATE affected 'S_DEVELOP' INTO affected. 1628 | ENDIF. 1629 | 1630 | * S_ICF_ADM 1631 | 1632 | AUTHORITY-CHECK OBJECT 'S_ICF_ADM' 1633 | ID 'ICF_TYPE' FIELD 'NODE' 1634 | ID 'ACTVT' FIELD '02' 1635 | ID 'ICF_HOST' DUMMY 1636 | ID 'ICF_NODE' DUMMY 1637 | . 1638 | IF sy-subrc > 0. 1639 | may_be_insufficient = abap_true. 1640 | IF affected IS NOT INITIAL. CONCATENATE affected ', ' INTO affected RESPECTING BLANKS. ENDIF. 1641 | CONCATENATE affected 'S_ICF_ADM' INTO affected. 1642 | ENDIF. 1643 | 1644 | * S_TRANSPRT 1645 | 1646 | AUTHORITY-CHECK OBJECT 'S_TRANSPRT' 1647 | ID 'TTYPE' FIELD 'TASK' 1648 | ID 'ACTVT' FIELD '02'. 1649 | 1650 | IF sy-subrc > 0. 1651 | may_be_insufficient = abap_true. 1652 | IF affected IS NOT INITIAL. CONCATENATE affected ', ' INTO affected RESPECTING BLANKS. ENDIF. 1653 | CONCATENATE affected 'S_TRANSPRT' INTO affected. 1654 | ENDIF. 1655 | 1656 | 1657 | * S_TCODE 1658 | 1659 | AUTHORITY-CHECK OBJECT 'S_TCODE' 1660 | ID 'TCD' FIELD '*'. 1661 | IF sy-subrc > 4. 1662 | may_be_insufficient = abap_true. 1663 | IF affected IS NOT INITIAL. CONCATENATE affected ', ' INTO affected RESPECTING BLANKS. ENDIF. 1664 | CONCATENATE affected 'S_TCODE' INTO affected. 1665 | ENDIF. 1666 | 1667 | * S_CTS_ADMI 1668 | 1669 | AUTHORITY-CHECK OBJECT 'S_CTS_ADMI' 1670 | ID 'CTS_ADMFCT' FIELD 'TABL'. 1671 | 1672 | IF sy-subrc > 4. 1673 | may_be_insufficient = abap_true. 1674 | IF affected IS NOT INITIAL. CONCATENATE affected ', ' INTO affected RESPECTING BLANKS. ENDIF. 1675 | CONCATENATE affected 'S_CTS_ADMI' INTO affected. 1676 | ENDIF. 1677 | 1678 | * S_CTS_SADM 1679 | IF may_be_insufficient = abap_true. 1680 | AUTHORITY-CHECK OBJECT 'S_CTS_SADM' 1681 | ID 'DOMAIN' DUMMY 1682 | ID 'DESTSYS' DUMMY 1683 | ID 'CTS_ADMFCT' FIELD 'TABL'. 1684 | IF sy-subrc >= 12. 1685 | DATA: and TYPE string. 1686 | and = 'and'(108). CONDENSE and. 1687 | CONCATENATE affected ' ' and ' S_CTS_ADMI' INTO affected RESPECTING BLANKS. 1688 | ENDIF. 1689 | ENDIF. 1690 | 1691 | * Prepare authorization message 1692 | * ... in case authorization appears to be insufficient 1693 | IF may_be_insufficient = abap_true. 1694 | rv_message = 'Warning : Authorization may be missing for'(102). 1695 | CONCATENATE '* ' rv_message ' ' affected ' *' INTO rv_message RESPECTING BLANKS. 1696 | IF strlen( rv_message ) > 120. 1697 | rv_message = 'Warning : Authorizations may be missing.'(107). 1698 | CONCATENATE '* ' rv_message ' *' INTO rv_message RESPECTING BLANKS. 1699 | ENDIF. 1700 | ENDIF. 1701 | 1702 | ENDMETHOD. "evaluate_authorization 1703 | * METHOD is_binary_file. 1704 | * 1705 | * rv_is_binary_file = abap_undefined. 1706 | * IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->binary_file_patterns ) = abap_true ). 1707 | * rv_is_binary_file = abap_true. 1708 | * ENDIF. 1709 | * 1710 | * ENDMETHOD. "is_binary_file 1711 | * 1712 | * METHOD is_file_to_be_ignored. 1713 | * 1714 | * rv_ignore = abap_false. 1715 | * IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->ignores ) = abap_true ). 1716 | * rv_ignore = abap_true. 1717 | * ENDIF. 1718 | * 1719 | * ENDMETHOD. "is_file_to_be_ignored 1720 | * 1721 | * METHOD is_text_file. 1722 | * 1723 | * rv_is_text_file = abap_undefined. 1724 | * IF ( lcl_function=>text_matches_pattern( iv_text = iv_file_path iv_pattern_list = me->text_file_patterns ) = abap_true ). 1725 | * rv_is_text_file = abap_true. 1726 | * ENDIF. 1727 | * 1728 | * ENDMETHOD. "is_text_file 1729 | 1730 | METHOD set_name. 1731 | 1732 | DATA: message TYPE string. 1733 | 1734 | * Remember name 1735 | me->name = iv_name. 1736 | 1737 | * Check if UI5 Repository already exists. If yes retrieve API. 1738 | TRY. 1739 | me->api = /ui5/cl_ui5_rep_dt=>/ui5/if_ui5_rep_dt~get_api( iv_name = me->name ). 1740 | me->already_exists = abap_true. 1741 | message = TEXT-029. 1742 | 1743 | CATCH cx_root. 1744 | CLEAR me->api. 1745 | me->already_exists = abap_false. 1746 | message = TEXT-028. 1747 | ENDTRY. 1748 | CONCATENATE message ' : ' iv_name INTO message. 1749 | " APPEND message TO me->log_messages_ref->*. 1750 | 1751 | * Check that name is valid 1752 | DATA: p_application_name TYPE o2applname, 1753 | p_application_ext TYPE o2applext. 1754 | p_application_name = iv_name. 1755 | p_application_ext = p_application_name. 1756 | CALL METHOD cl_o2_helper=>check_application_name_valid 1757 | EXPORTING 1758 | p_application_name = p_application_name 1759 | p_application_ext = p_application_ext 1760 | EXCEPTIONS 1761 | invalid = 1. 1762 | IF sy-subrc NE 0. 1763 | MESSAGE ID sy-msgid 1764 | TYPE 'S' 1765 | NUMBER sy-msgno 1766 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO message. 1767 | CONCATENATE '* ' message INTO message RESPECTING BLANKS. 1768 | APPEND message TO me->log_messages_ref->*. 1769 | CLEAR me->name. 1770 | EXIT. 1771 | ENDIF. 1772 | 1773 | ENDMETHOD. "set_name 1774 | 1775 | 1776 | ENDCLASS. "lcl_ui5_repository IMPLEMENTATION 1777 | --------------------------------------------------------------------------------