* _______ _______ _______ _______ _______ _______ ______ _______ _______ ______ _______ * | _ | _ | _ | | | _ | || _ | _ | _ | | _ | * | |_| | |_| | |_| | _ | | |_| | _ | |_| | |_| | | || | |_| | * | | | | |_| | | | | | | | | |_||_| | * | | _ || | ___| _| | |_| | | _ || __ | | * | _ | |_| | _ | | | |_| _ | | _ | |_| | | | | _ | * |__| |__|_______|__| |__|___| |_______|__| |__|______||__| |__|_______|___| |_|__| |__| * www.abapcadabra.com * *------------------------------------------------------------------------------------------- * program : ZABAPCADABRA_SERVER_CLEANUP * title : Utility tool to remove server files that are no longer used * functional area : Cross modules * environment : 4.7 * program Function : Through options on the selection screen files that * reside on the server can be cleared (removed). A full log * is maintained on the process. * Documentation : Search for "Delete server files" on AbapcadabrA.com * Previous version : This is the initial version * Developer name : Wim Maasdam * Development date : 29/08/2015 * Version : 0.1 *--------------------------------------------------------------------- * Change list: * Date Description * 29/08/2015 Initial release *--------------------------------------------------------------------- REPORT ZABAPCADABRA_SERVER_CLEANUP. tables: sscrfields. "Selection screen purpose only TYPE-POOLS SABC. constants: co_slg0_object TYPE balobj_d VALUE 'ALERT', co_slg0_subobject TYPE balsubobj VALUE 'PROCESSING'. *--------------------------------------------------------------------- * S E L E C T I O N - S C R E E N *--------------------------------------------------------------------- selection-SCREEN BEGIN OF LINE. selection-SCREEN COMMENT 1(33) lbl_01 FOR FIELD pa_age. PARAMETERS: pa_age TYPE n length 4. selection-SCREEN COMMENT 41(20) lbl_01b. selection-SCREEN END OF LINE. selection-SCREEN BEGIN OF LINE. selection-SCREEN COMMENT 1(33) lbl_02 FOR FIELD pa_fpat. parameter pa_fpat type string LOWER CASE visible length 15 default '*' OBLIGATORY. selection-SCREEN END OF LINE. selection-SCREEN BEGIN OF LINE. PARAMETERS: pa_test AS CHECKBOX DEFAULT 'X'. selection-SCREEN COMMENT 4(30) lbl_03 FOR FIELD pa_test. selection-SCREEN END OF LINE. SELECTION-SCREEN skip. selection-SCREEN BEGIN OF LINE. selection-SCREEN COMMENT 1(10) lbl_10 FOR FIELD pa_fldr1. PARAMETERS: pa_fldr1 TYPE string LOWER CASE visible length 56. selection-SCREEN END OF LINE. define folder_par. selection-SCREEN BEGIN OF LINE. selection-SCREEN POSITION 12. PARAMETERS: pa_fldr&1 TYPE string LOWER CASE visible length 56. selection-SCREEN END OF LINE. end-of-definition. folder_par: 2,3,4,5,6,7,8. selection-SCREEN SKIP. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN PUSHBUTTON 1(16) pushbut2 USER-COMMAND slg1. SELECTION-SCREEN POSITION 20. PARAMETER pa_balsv TYPE c AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 35(14) lbl_15 FOR FIELD pa_balsv. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN POSITION 20. PARAMETER pa_balsx TYPE c AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 35(35) lbl_16 FOR FIELD pa_balsx. SELECTION-SCREEN END OF LINE. selection-SCREEN SKIP. selection-SCREEN BEGIN OF LINE. SELECTION-SCREEN PUSHBUTTON (70) lbl_abca USER-COMMAND ABAPCADABRA VISIBLE LENGTH 5. selection-SCREEN END OF LINE. *--------------------------------------------------------------------- define folder_f4. AT SELECTION-SCREEN ON VALUE-REQUEST FOR pa_fldr&1. CALL FUNCTION '/SAPDMC/LSM_F4_SERVER_FILE' EXPORTING DIRECTORY = pa_fldr&1 FILEMASK = '(no filenames)' "Explicitely supply dummy filemask IMPORTING SERVERFILE = pa_fldr&1 EXCEPTIONS OTHERS = 0. end-of-definition. folder_f4: 1,2,3,4,5,6,7,8. *--------------------------------------------------------------------- AT SELECTION-SCREEN. CASE sscrfields-ucomm. WHEN 'ABAPCADABRA'. CALL FUNCTION 'CALL_BROWSER' EXPORTING URL = 'http://abapcadabra.com/index.php/interfacing/files/548-erasing-files' EXCEPTIONS OTHERS = 0. WHEN 'SLG1'. SET PARAMETER ID 'BALOBJ' FIELD co_slg0_object. SET PARAMETER ID 'BALSUBOBJ' FIELD co_slg0_subobject. CALL TRANSACTION 'SLG1'. ENDCASE. *--------------------------------------------------------------------- * C L A S S D E F I N I T I O N S *--------------------------------------------------------------------- *---------------------------------------------------------------------- * CLASS lcl_logging - the message logging and error logging for this * interface is done in the Business Application Log (trx. SLG0, SLG1). * The log is displayed at the end of the report run. Logs can also * be saved (options on the selection screen are available). *---------------------------------------------------------------------- CLASS lcl_logging DEFINITION. PUBLIC SECTION. CLASS-DATA: go_log TYPE REF TO cl_ishmed_bal, gv_errors_were_logged TYPE boolean VALUE space. CLASS-METHODS: initialize IMPORTING object TYPE balobj_d DEFAULT 'ALERT' subobject TYPE balsubobj DEFAULT 'PROCESSING', set_message IMPORTING message TYPE any OPTIONAL par1 TYPE any DEFAULT space par2 TYPE any DEFAULT space par3 TYPE any DEFAULT space msgty TYPE symsgty DEFAULT 'I' pass_to_joblog type boolean DEFAULT space PREFERRED PARAMETER message, set_subject IMPORTING subject TYPE any, set_error IMPORTING message TYPE any OPTIONAL par1 TYPE any DEFAULT space par2 TYPE any DEFAULT space PREFERRED PARAMETER message, formatter IMPORTING input type any format type any default 'DATE' returning value(result) type char80. ENDCLASS. "lcl_logging DEFINITION CLASS LCL_folder DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF ty_dir_entry, name(75), " name of entry type(15), " type of entry len(4) TYPE p DECIMALS 0, " length in bytes owner(8), " owner of the entry mtime(6) TYPE p DECIMALS 0, "seconds since 1st of Jan 1970 mode(9), " like "rwx-r-x--x": protection mode. mod_time type c length 8, mod_date type d, subrc(4), errno(3), errmsg(40), END OF ty_dir_entry. DATA: gv_folder type string, gv_total_len(9) TYPE p DECIMALS 2, gv_total_cnt type sy-dbcnt, gt_listing type standard table of ty_dir_entry. ENDCLASS. CLASS LCL_controller DEFINITION. PUBLIC SECTION. CLASS-DATA: gt_folder_obj type standard table of ref to LCL_folder, go_folder type ref to lcl_folder, gw_listing_entry type lcl_folder=>ty_dir_entry. CLASS-METHODS: set_folder importing folder type string, variabele_parser changing parse_field type string, compose_targetlist importing pattern type any age type any. ENDCLASS. *---------------------------------------------------------------------- * CLASS lcl_logging IMPLEMENTATION *---------------------------------------------------------------------- CLASS lcl_logging IMPLEMENTATION. METHOD initialize. TRY. CREATE OBJECT go_log EXPORTING i_object = object i_subobject = subobject i_repid = sy-repid. CATCH cx_ishmed_log. "#EC NO_HANDLER * No actual processing here ENDTRY. ENDMETHOD. "initialize METHOD set_message. " importing message type any, par1, par2 DATA: lv_message TYPE c LENGTH 200, lv_par1 type c length 80, lv_par2 type c length 80, lv_par3 type c length 80. lv_message = message. move par1 to lv_par1. shift lv_par1 LEFT DELETING LEADING space. move par2 to lv_par2. shift lv_par2 LEFT DELETING LEADING space. move par3 to lv_par3. shift lv_par3 LEFT DELETING LEADING space. REPLACE '&' WITH lv_par1 INTO lv_message. CONDENSE lv_message. REPLACE '&' WITH lv_par2 INTO lv_message. CONDENSE lv_message. REPLACE '&' WITH lv_par3 INTO lv_message. CONDENSE lv_message. TRY. go_log->add_free_text( EXPORTING i_msg_type = msgty i_text = lv_message ). CATCH cx_ishmed_log. "#EC NO_HANDLER * No actual logic on catch ENDTRY. if pass_to_joblog = abap_true and sy-batch = abap_true. message id 'V1' type 'I' number 899 with lv_message(50) lv_message+50(50). endif. ENDMETHOD. "set_message METHOD set_subject. DATA: lv_subject TYPE c LENGTH 100. lv_subject = subject. * concatenate '==>' lv_subject into lv_subject SEPARATED BY space. TRANSLATE lv_subject TO UPPER CASE. set_message( message = lv_subject msgty = 'W' ). ENDMETHOD. "set_subject METHOD set_error. set_message( message = message par1 = par1 par2 = par2 msgty = 'E' ). lcl_logging=>gv_errors_were_logged = abap_true. ENDMETHOD. "set_error METHOD formatter. case format. when 'DATE'. write input to result DD/MM/YYYY. when 'TIME'. write input to result using EDIT MASK '__:__'. endcase. ENDMETHOD. ENDCLASS. "lcl_logging IMPLEMENTATION CLASS lcl_controller IMPLEMENTATION. METHOD set_folder. data: lo_folder type ref to lcl_folder, lv_directory_prep type string, lv_directory type CHAR128. check not folder is initial and not folder co ' '. lv_directory_prep = folder. variabele_parser( changing parse_field = lv_directory_prep ). lv_directory = lv_directory_prep. shift lv_directory left DELETING LEADING space. CALL FUNCTION 'PFL_CHECK_DIRECTORY' EXPORTING DIRECTORY_LONG = lv_directory EXCEPTIONS PFL_DIR_NOT_EXIST = 1 PFL_PERMISSION_DENIED = 2 PFL_CANT_BUILD_DATASET_NAME = 3 PFL_FILE_NOT_EXIST = 4 OTHERS = 5. IF sy-subrc <> 0. lcl_logging=>set_message( message = 'Folder: &' par1 = folder msgty = 'W' ). lcl_logging=>set_message( message = 'Directory does not exist' msgty = 'W' ). else. create object lo_folder. lo_folder->gv_folder = lv_directory. append lo_folder to gt_folder_obj. endif. ENDMETHOD. METHOD variabele_parser. DATA: lv_system TYPE c LENGTH 15, lv_system_str TYPE string, begin of lw_tokens, t1 type string, t2 type string, t3 type string, t4 type string, t5 type string, end of lw_tokens, lw_sys_parameter type SPFPFLPAR. CONCATENATE sy-sysid sy-mandt INTO lv_system SEPARATED BY '_'. CONDENSE lv_system NO-GAPS. lv_system_str = lv_system. REPLACE ALL OCCURENCES OF '{S}' IN parse_field WITH lv_system_str. REPLACE ALL OCCURENCES OF '{I}' IN parse_field WITH sy-sysid(3). REPLACE ALL OCCURENCES OF '{C}' IN parse_field WITH sy-mandt(3). REPLACE ALL OCCURENCES OF '{Y}' IN parse_field WITH sy-datum(4). REPLACE ALL OCCURENCES OF '{H}' IN parse_field WITH sy-host. * Special processing for parameter references, which will check RSPARAM settings while parse_field cs '{P='. split parse_field at '{P=' into lw_tokens-t1 lw_tokens-t2. "\tmp\{P=INSTANCE_NAME}\more\ to \tmp\ and INSTANCE_NAME}\more\ split lw_tokens-t2 at '}' into lw_tokens-t3 lw_tokens-t4. "INSTANCE_NAME}\more\ to INSTANCE_NAME and \more\ lw_sys_parameter-PARNAME = lw_tokens-t3. CALL FUNCTION 'RSAN_SYSTEM_PARAMETER_READ' EXPORTING I_NAME = lw_sys_parameter-PARNAME IMPORTING E_VALUE = lw_sys_parameter-PVALUE EXCEPTIONS OTHERS = 4. IF SY-SUBRC <> 0. lcl_logging=>set_error( message = 'Invalid parameter {P=&}' par1 = lw_sys_parameter-PARNAME ). concatenate lw_tokens-t1 '#ERROR#' lw_tokens-t4 into parse_field. else. concatenate lw_tokens-t1 lw_sys_parameter-PVALUE lw_tokens-t4 into parse_field. ENDIF. endwhile. ENDMETHOD. METHOD compose_targetlist. * Constants constants: co_1970 type d value '19700101', co_seconds_in_day(6) type p value 86400, " = 24 * 60 * 60 co_seconds_in_hour type p value 3600. " = 60 * 60 DATA: lv_oldest_mtime(6) type p decimals 0, lo_folder type ref to lcl_folder, lw_dir_entry TYPE lcl_folder=>ty_dir_entry, lv_directory TYPE edipo-outputdir, lv_now TYPE t, lv_pattern type string. lv_pattern = pattern. variabele_parser( changing parse_field = lv_pattern ). GET TIME FIELD lv_now. * Calculate the oldest time (new files should be ignored) lv_oldest_mtime = ( ( sy-datum - co_1970 ) * co_seconds_in_day ) + ( lv_now(2) * co_seconds_in_hour ) + ( lv_now+2(2) * 60 ) + ( lv_now+4(2) ). * If age is not set, simply assume "Now", if age is set, assume whole days. Thus * age = 1 means everything that was created yesterday is removed: if age > 0. lv_oldest_mtime = ( ( ( sy-datum - co_1970 ) - age + 1 ) * co_seconds_in_day ). endif. * Fetch the list of files. Supported for Windows and Unix systems: loop at GT_FOLDER_OBJ into lo_folder. CLEAR: lo_folder->gt_listing[], lo_folder->gv_total_cnt, lo_folder->gv_total_len. CALL 'C_DIR_READ_FINISH' ID 'ERRNO' FIELD lw_dir_entry-errno ID 'ERRMSG' FIELD lw_dir_entry-errmsg. lv_directory = lo_folder->gv_folder. * Position the read in the directory we want CALL 'C_DIR_READ_START' ID 'DIR' FIELD lv_directory ID 'FILE' FIELD lv_pattern ID 'ERRNO' FIELD lw_dir_entry-errno ID 'ERRMSG' FIELD lw_dir_entry-errmsg. CHECK sy-subrc = 0. "If this step fails: simply stop processing * Find the files DO. CLEAR lw_dir_entry. CALL 'C_DIR_READ_NEXT' ID 'TYPE' FIELD lw_dir_entry-type ID 'NAME' FIELD lw_dir_entry-name ID 'LEN' FIELD lw_dir_entry-len ID 'OWNER' FIELD lw_dir_entry-owner ID 'MTIME' FIELD lw_dir_entry-mtime ID 'MODE' FIELD lw_dir_entry-mode ID 'ERRNO' FIELD lw_dir_entry-errno ID 'ERRMSG' FIELD lw_dir_entry-errmsg. IF sy-subrc <> 0 AND lw_dir_entry-name IS INITIAL. EXIT. "End of the listing has been reached ELSEIF sy-subrc = 3. "RC=3 File too big to fit in v_file-len CONTINUE. ELSEIF lw_dir_entry-name IS INITIAL. CONTINUE. ELSEIF lw_dir_entry-type <> 'file, regular'. "Files only CONTINUE. ELSEIF lv_oldest_mtime < lw_dir_entry-mtime. CONTINUE. ELSEIF NOT lw_dir_entry-name CP lv_pattern. "< already captured in 'C_DIR_READ_START' CONTINUE. ENDIF. * Copied from an AL11 call: perform p6_to_date_time_tz in program rstr0400 using lw_dir_entry-mtime lw_dir_entry-mod_time lw_dir_entry-mod_date. APPEND lw_dir_entry TO lo_folder->gt_listing. add 1 to lo_folder->gv_total_cnt. add lw_dir_entry-len to lo_folder->gv_total_len. ENDDO. CALL 'C_DIR_READ_FINISH' ID 'ERRNO' FIELD lw_dir_entry-errno ID 'ERRMSG' FIELD lw_dir_entry-errmsg. modify GT_FOLDER_OBJ from lo_folder. endloop. ENDMETHOD. ENDCLASS. *--------------------------------------------------------------------- * I N I T I A L I Z A T I O N *--------------------------------------------------------------------- INITIALIZATION. * All texts for this report have been set up as hard-coded texts (no use * of the report text-pool). Reason: easy copying of report source code. lbl_abca = '@N5\QMore on AbapcadabrA.com@'. lbl_01 = 'Only remove files older than'. lbl_01b = 'days'. lbl_02 = 'Only remove files (pattern)'. lbl_03 = 'Test mode - no deletions'. lbl_10 = 'Folders'. pushbut2 = 'Application log'. lbl_15 = 'Save log'. lbl_16 = '... only if it contains errors'. *--------------------------------------------------------------------- * S T A R T - O F - S E L E C T I O N *--------------------------------------------------------------------- START-OF-SELECTION. lcl_logging=>initialize( ). lcl_logging=>set_subject( 'Server file deletions - remove old files from the server' ). lcl_logging=>set_message( message = 'Files older than & days with pattern & are removed' par1 = pa_age par2 = pa_fpat pass_to_joblog = abap_true ). if pa_test = abap_true. lcl_logging=>set_subject( 'Test mode - no actual files are removed' ). endif. define set_folder. lcl_controller=>set_folder( pa_fldr&1 ). end-OF-DEFINITION. set_folder: 1,2,3,4,5,6,7,8. lcl_controller=>compose_targetlist( pattern = pa_fpat age = pa_age ). loop at lcl_controller=>gt_folder_obj into lcl_controller=>go_folder. lcl_logging=>set_message( message = 'Folder: &' par1 = lcl_controller=>go_folder->gv_folder msgty = 'W' pass_to_joblog = abap_true ). if lcl_controller=>go_folder->gv_total_cnt is initial. lcl_logging=>set_message( message = 'No files to be deleted' msgty = 'W' pass_to_joblog = abap_true ). else. DIVIDE lcl_controller=>go_folder->gv_total_len by 1000000. lcl_logging=>set_message( message = '& files containing &Mb' par1 = lcl_controller=>go_folder->gv_total_cnt par2 = lcl_controller=>go_folder->gv_total_len msgty = 'W' pass_to_joblog = abap_true ). loop at lcl_controller=>go_folder->gt_listing into lcl_controller=>gw_listing_entry. lcl_logging=>set_message( lcl_controller=>gw_listing_entry-name ). data: lv_formatteddate type c length 10. lv_formatteddate = lcl_logging=>formatter( input = lcl_controller=>gw_listing_entry-mod_date ). lcl_logging=>set_message( message = '&bytes, last modified & at &' par1 = lcl_controller=>gw_listing_entry-len par2 = lv_formatteddate par3 = lcl_controller=>gw_listing_entry-mod_time ). * Delete the actual file if pa_test is initial. data: lv_AUTHB_FILENAME type AUTHB-FILENAME, lv_fullfilename type string. *----------------------------------------------------- concatenate lcl_controller=>go_folder->gv_folder lcl_controller=>gw_listing_entry-name into lv_fullfilename. lv_AUTHB_FILENAME = lv_fullfilename. *Check autorisation for dataset deletion CALL FUNCTION 'AUTHORITY_CHECK_DATASET' EXPORTING PROGRAM = SY-REPID ACTIVITY = sabc_act_delete FILENAME = lv_AUTHB_FILENAME EXCEPTIONS NO_AUTHORITY = 1 ACTIVITY_UNKNOWN = 2. if sy-subrc <> 0. lcl_logging=>set_error( 'File delete authorisation missing ' ). else. open DATASET lv_fullfilename FOR INPUT IN TEXT MODE ENCODING DEFAULT. if sy-subrc <> 0. lcl_logging=>set_error( 'File could not be opened. Full filename:' ). lcl_logging=>set_error( lv_fullfilename ). else. close dataset lv_fullfilename. delete dataset lv_fullfilename. if sy-subrc <> 0. lcl_logging=>set_error( 'File could not be deleted. ' ). endif. endif. endif. *----------------------------------------------------- endif. endloop. endif. endloop. if sy-subrc <> 0. lcl_logging=>set_message( 'No (valid) folders specified' ). endif. lcl_logging=>go_log->display( ). if pa_balsv = abap_true. if pa_balsx = abap_true and lcl_logging=>GV_ERRORS_WERE_LOGGED = abap_true. lcl_logging=>go_log->save( ). elseif pa_balsx = abap_false. lcl_logging=>go_log->save( ). endif. endif.