ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


System Administration with ooRexx
Pages: 1, 2, 3

Script Structure

All ooRexx scripts have a similar structure. Executable code starts the program. As this template shows, this code ends with an exit instruction:




/**************************************************************************/
/*  TEMPLATE -- shows how ooRexx programs are structured                  */
/**************************************************************************/

/*  Executable code goes here...                                          */

exit

::requires 'oodwin32.cls'     /* The OODialog Classes- comes w/ ooRexx    */
::requires 'folderbrowse.cls' /* Download from www.sahananda.fwbo.net/rexx*/

::class LargeFileClass subclass userdialog inherit advancedcontrols

::method Init

     /* method code goes here */

/* other Methods for the class follow . . .                               */

/* other Classes and their Methods fellow . . .                           */

Any ::requires directives follow the executable code. These statements provide access to any external classes the program needs. The previous example uses the oodwin32.cls class, which defines OODialog, the ooRexx GUI that comes with ooRexx for Windows. The second ::requires directive includes the folderbrowse class you downloaded earlier for managing the user's interaction for drive and folder selection in the program.

After the ::requires directives appear any class definitions. This program has but one:

::class LargeFileClass subclass userdialog inherit advancedcontrols

LargeFileClass extends OODialog's userdialog class. It inherits additional behaviors from OODialog's advancedcontrols class. ooRexx supports multiple inheritance to give you maximum power in reusing classes and their methods.

Any methods in the class follow the class definition. As the Template shows, the ::method directive identifies each. The code that implements the method immediately follows the ::method directive. The Template shows a single method, Init, which ooRexx runs automatically when creating a new instance of an object. Of course, a program can define any number of classes and methods.

The Script

Now that you know the structure of ooRexx scripts, you can consider the example program. Here is the script in its entirety:


/* =======================================================================*/
/* Large Files -- Find the large files on your disk to delete.            */
/* Jon Wolfers May 2005 -- freely distributable code example.             */
/* =======================================================================*/

arg No_of_files .               /* Look for arguments                     */

if  \No_of_files~datatype('w') then No_of_files=50  /* Use default if none*/

MyDialog=.LargeFileClass~new(no_of_files)
MyDialog~Execute('ShowTop')     /* Create, show & run the Windows Object  */
MyDialog~DeInstall              /* Clear Up                               */

exit


::requires 'oodwin32.cls'     /* The OODialog Classes- comes w/ ooRexx    */
::requires 'folderbrowse.cls' /* Download from www.sahananda.fwbo.net/rexx*/


::class LargeFileClass subclass userdialog inherit advancedcontrols


::method Init
/* -----------------------------------------------------------------------*/
/* Init initializes when a LargeFilesClass object is created              */ 
/* -----------------------------------------------------------------------*/
expose NoOfFiles              /* Give this variable scope of the Object   */
use arg NoOfFiles

  self~Init:super             /* We call the Super Class (userdialog)     */
                              /* Now we create the Windows Object         */
  rc=self~CreateCenter(400,200,NoOfFiles 'Largest Files on Disk',,,,
                                    'MS Sans Serif',8)
  self~InitCode=(rc=0)



::method DefineDialog
/* -----------------------------------------------------------------------*/
/* DefineDialog initializes for the user dialog                           */
/* -----------------------------------------------------------------------*/
   self~DefineDialog:super   /* We call the Super Class (userdialog)      */

   self~AddButton(1,self~SizeX-60,self~SizeY-20,50,15,'Leave','Ok','DEFAULT')
   self~AddButton(10,self~SizeX-120,self~SizeY-20,50,15,'Delete','Delete')
   self~AddListControl(11,,10,40,self~SizeX-20,self~SizeY-70,'REPORTSINGLESEL')
   self~AddText(10,self~SizeY-20,self~SizeX-140, 10,' ','CENTER',12)
   self~AddProgressBar(13,10,20,self~sizeX-20,10,'SMOOTH')
   self~AddText(10,10,self~sizeX-20,10,' ','CENTER',14)



::method run
/* -----------------------------------------------------------------------*/
/* Run gets the drive or folder to display files for, retrieves files,    */
/* sorts them, and displays them to the user.                             */
/* -----------------------------------------------------------------------*/
Expose NoOfFiles drive

FBrowser=.BrowseForFolder~new('Select root to find large files in',,,,,0)
FBrowser~Execute('ShowTop')
folder=FBrowser~folder
FBrowser~DeInstall

if folder=''
then self~cancel              /* Call the superclass cancel method to exit*/
else do
   Self~GetProgressBar(13)~SetRange(1,100) /* For Drive Info              */
   disp=Self~GetStaticControl(12)

   drive=filespec('drive',folder)          /* Get drive letter from folder*/
   Self~SetTitle(NoOfFiles 'Largest Files in' folder)       /* Dialog Title  */

   disp~SetTitle('PLEASE WAIT  ... Exploring 'folder '...')
   call sysfiletree folder||'*.*','files','FSL' /* file info-> files. stem*/
   disp~SetTitle('PLEASE WAIT  ... Sorting files ...')
                          /* files.0 holds number of files in files. stem */
   if files.0 > 1 then call SysStemSort 'files.','D',,,,20  /* Largest 1st*/
   disp~SetTitle(' ')

   list=Self~GetListControl(11)        /* Set up & populate list control  */
   if list\=.nil
   then do
      list~insertColumn(0,'Size',35,'RIGHT')
      list~insertColumn(1,'Filename',80,'LEFT')
      list~insertColumn(2,'Date',35,'LEFT')
      list~insertColumn(3,'Time',35,'LEFT')
      list~insertColumn(4,'Path',200,'LEFT')
      added=0 ; i=0
      do forever
         i=i+1                               /* Move on to next file      */
         if     i > files.0   then leave     /* No more data, so go ->    */
         if added > NoOfFiles then leave     /* Reached our target, go -> */
         parse var files.i date time size attr file     /* Get file info  */
         fn=filespec('name',file)            /* Parse out filename        */
         path=file~left(file~length - fn~length)
         if attr~right(1) = 'S' then iterate /* Ignore system files       */

         list~addrow(,,Size,fn,date,time,path)      /* Pop it in the list */
         added=added+1
      end /* DO */
   end /* DO */

   Self~SetTitle(Added 'Largest Files in' folder)   /* Update Dialog Title*/
   self~ShowDriveInfo(drive)
end /* DO */

self~Run:Super                  /* We call the Super Class (userdialog)   */



::method Delete
/* -----------------------------------------------------------------------*/
/* Delete deletes a file the user selects for deletion                    */
/* -----------------------------------------------------------------------*/
expose drive

List=Self~GetListControl(11)
item=list~Selected
if item=-1
then call errormessage 'No File is selected to delete'
else if yesnoMessage('Delete' list~itemtext(item,1) 'from' list~itemtext(item,4))
     then do                                    /* Delete the file       */
        target_file=list~itemtext(item,4)||list~itemtext(item,1)
        target_file=target_file~strip
        rc=sysfiledelete(target_file)
        if rc=0
        then do
           list~Delete(item)                    /* Remove item from list */
           self~ShowDriveInfo(drive)            /* Update drive info     */
        end /* DO */
        else call RXMessageBox 'Delete failed with RC' rc 'for' target_file
     end /* DO */



::method ShowDriveInfo
/* ----------------------------------------------------------------------*/
/* ShowDriveInfo displays the drive with its amount of free space        */
/* ----------------------------------------------------------------------*/
arg drive .
   parse value sysdriveInfo(drive) with . free total label . /* Drive info*/
   pc=(free/total)*100
   self~GetStaticControl(14)~SetTitle(drive '('||label||') -' ,
       format(pc,,2)||'% free')
   Self~GetProgressBar(13)~SetPos(pc~trunc)
return

The executable code starts the program and consists of six lines. The arg instruction reads a command-line argument that tells how many of the largest files to list in the dialog box. The if instruction sets a default value of 50.

The next three lines create a new instance of the LargeFilesClass, run the object, and clean up when done. The executable code terminates with the exit instruction. That's all there is to it. Like most OO scripts, the real work occurs in the methods and the code that defines them.

As mentioned in the Template discussion, any ::requires directives come next. The two that appear in this script refer to two external classes, oodwin32.cls and folderbrowse.cls. The ::requires directives make these classes available for the use of this script. These class files must reside in the class library or folder referenced in the Windows PATH environment variable.

The oodwin32 class is part of OODialog and installs with ooRexx. The folderbrowse class is our own; download it from Sahananda's Rexx web site for the script to run.

Any class code internal to this program comes next. This script has a single class, LargeFileClass. It extends OODialog's userdialog class and also inherits methods and attributes from its advancedcontrols class:

  ::class LargeFileClass subclass userdialog inherit advancedcontrols

The five methods in LargeFileClass follow; the ::method directives identify each one. The code that implements each method immediately follows its ::method directive.

Wherever the tilde symbol (~, which we call the twiddle) is used, the message on its right is sent to the object on its left. This runs the method, as identified by the message name, on the object. The special reference Self refers to the object in which the code itself resides.

In reviewing the code, first up is the Init method. This line in the executable code section runs the Init method when it creates the new LargeFileClass object:

    MyDialog=.LargeFileClass~new(no_of_files)

In the Init method, the expose instruction makes a method's variable accessible to the object. expose implements variable scoping in ooRexx. The use arg instruction reads in this variable. In this case, the method accesses and reads the number of files to list to the screen

  expose NoOfFiles /* Give this variable scope of the Object   */

  use arg NoOfFiles

The next three lines in the method set up the user dialog by calling its superclass, creating the Windows object, and exiting the Init method with a valid return code:

  self~Init:super /* We call the Super Class (userdialog) */

                              /* Now we create the Windows Object */

  rc=self~CreateCenter(400,200,NoOfFiles 'Largest Files on Disk',,,,
                                    'MS Sans Serif',8)
  self~InitCode=(rc=0)

The method DefineDialog appears next. This method calls the superclass (userdialog), and then adds the widgets to the dialog. It also connects the buttons to the methods that run when a user presses them. Like Init, this method is background work for the user interface.

The run method does most of the work in this program. The superclass calls it when the dialog becomes visible but does not yet handle messages (in this case, button presses). It starts with an expose instruction to make visible the number of files to list to the user and the drive involved:

  Expose NoOfFiles drive

The next several statements create and execute an object to browse the files in a folder. This code builds upon the downloaded folderbrowse class:

  FBrowser=.BrowseForFolder~new('Select root to find large files in',,,,,0) 
  FBrowser~Execute('ShowTop')
  folder=FBrowser~folder
  FBrowser~DeInstall

You can examine the code that runs the folderbrowse class. It is also a subclass of userdialog.

Next up is the code that retrieves the files in a folder. It uses the sysfiletree function, one of more than 80 functions provided with ooRexx in its included RexxUtil package. RexxUtil functions allow scripts to perform operating system functions in an OS-independent manner:

  disp~SetTitle('PLEASE WAIT  ... Exploring 'folder '...')
  call sysfiletree folder||'*.*','files','FSL' /* file info-> files. stem*/

  disp~SetTitle('PLEASE WAIT  ... Sorting files ...')

                         /* files.0 holds number of files in files. stem */

  if files.0 > 1 then call SysStemSort 'files.','D',,,,20  /* Largest 1st*/

The sysfiletree function returns a set of filenames in an array. Rexx denotes arrays by compound variables: variable names that contain one or more embedded periods. The call to sysfiletree returns filenames into the files array. Refer to elements in the array as files.1, files.2, and so on. By convention, element files.0 contains the number of items in the array, so the final line in the previous example checks files.0 to verify that the array contains more than one element. If so, it invokes the RexxUtil SysStemSort function to sort the array elements by descending file size (referring to column 20 onward). Because ooRexx is a not a case-sensitive language, you can refer to the function as sysstemsort, SYSSTEMSORT, SysStemSort, or however you feel is most clear.

After retrieving and sorting the filenames, the next code block sets them up for display in a scrollable list box. The script uses the GetListControl method to get the list object and the advancedcontrol class methods InsertColumn and AddRow to populate it.

The last line in the run method invokes the method ShowDriveInfo. This method uses the RexxUtil sysdriveInfo function to retrieve space usage information. The method displays that information along with a graphical bar that shows remaining free space.

The last method to discuss is Delete. It uses the GetListControl method of userdialog to get the list object and then other userdialog methods to manage the user's selection of files to delete. It calls the RexxUtil sysfiledelete function to delete files. After a deletion, it runs the ShowDriveInfo method to update the user's display.

Pages: 1, 2, 3

Next Pagearrow





Sponsored by: