GitHubContribute in GitHub: Edit online

Creating a custom dependency scanner (ScannerInit)

With the zBuilder provided task ScannerInit, you can configure and initialize DBB scanners and populate the Dependency Scanner Registry, associating scanners with appropriate filetypes. It can be necessary to use a custom scanner when DBB does not support a particular filetype. This tutorial explains how to write and configure a custom scanner, using a custom Dialog Tag Language Scanner as an example.

Prerequisites

Estimated time

This tutorial takes about 20 minutes to complete.

Steps

  1. All custom scanners must implement IDependencyScanner. For this example you use DTLDependencyScanner, a custom scanner that extends AbstractDependencyScanner. In this case, the createLogicalFile() and runScan() methods are overridden to support scanning Dialog Tag Language (DTL) files. You can compile the class to com.ibm.dbb.extensions.scanners.dtl.DTLDependencyScanner, or convert it to a Groovy script with the .groovy extension.

    Note: For reference, the DTLDependencyScanner.java file contains the following lines:

    package com.ibm.dbb.extensions.scanners.dtl;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.Reader;
    import java.io.UnsupportedEncodingException;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import com.ibm.dbb.dependency.AbstractDependencyScanner;
    import com.ibm.dbb.dependency.LogicalDependency;
    import com.ibm.dbb.dependency.LogicalFile;
    
    public class DTLDependencyScanner extends AbstractDependencyScanner {
    
        @Override
        protected LogicalFile createLogicalFile(String file, Object scanMetadata) {
            return (LogicalFile) scanMetadata;
        }
    
        private static Pattern entityPattern = Pattern.compile("<[:!][eE][nN][tT][iI][tT][yY]\\s%?(?<payload> ?[a-zA-Z0-9\\$@%]*)\\s[sS][yY][sS][tT][eE][mM].*>"); //$NON-NLS-1$
        private static Pattern inclPattern = Pattern.compile("<\\?(?<payload>.*)>"); //$NON-NLS-1$
    
        
        @Override
        protected Object runScan(String file, InputStream inputStream, String encoding) {
    
            LogicalFile lfile = new LogicalFile(createLogicalName(file), file, "DTL", false, false, false, false);
            
            String ext = file.substring(file.lastIndexOf('.')+1);
            
            // Set library type to DTLINC
            String library = "DTLINC";
            
            // Set a different library for Japanese dialogs includes
            if (ext.equals("dtljpn")) {
                library = "DTLINCJ";
            }
            // System.out.println("File is " + file + " ext is " + ext + " library is " + library);
            
    
            // make sure we use the right encoding
            Reader reader;
            try {
                reader = new InputStreamReader(inputStream, encoding);
                
                BufferedReader br = new BufferedReader(reader);
                
                String line;
                while ((line = br.readLine()) != null) {
                    
                    //System.out.println("[DTL Dependency Scanner] reading : " + line);
    
                    Matcher entityMatcher = entityPattern.matcher(line);
                    Matcher inclMatcher = inclPattern.matcher(line);
    
                    // We have found an <entity ... > match
                    if (entityMatcher.find()) {
                        // System.out.println(String.format("Found entity on line: %s\n", line));
                        LogicalDependency logicalDependency = new LogicalDependency(entityMatcher.group("payload").trim().toUpperCase(), library, "COPY");
                        lfile.addLogicalDependency(logicalDependency);
                        
                    }
                    // We have found a <?include> match
                    else if (inclMatcher.find()) {
                        // System.out.println(String.format("Found include on line: %s\n", line));
                        LogicalDependency logicalDependency = new LogicalDependency(inclMatcher.group("payload").trim(), library, "COPY");
                        lfile.addLogicalDependency(logicalDependency);
                    }
                }
                
            } catch (UnsupportedEncodingException e) {
                // logging=
                return lfile;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            return lfile;
        }
    
    }
    
  2. Within your zBuilder yaml configuration, set up a custom task to initialize scanners using the provided ScannerInit class.

version: 1.0.0
tasks:
  - task: ScannerInit
  1. Define a custom scanner within the ScanerInit configuration. The source is the DTL Scanner you created earlier. It can be either the fully qualified class name of the compiled Java class, or the absolute path to a Groovy script. Under extensions, add dtl and dtljpn in a comma separated list, the two file extensions that you want to be associated with the DTL Scanner.
- task: ScannerInit
  variables:
    - name: scanners
      value:
        - scanner: DTL
          source: com.ibm.dbb.extensions.scanners.dtl.DTLDependencyScanner
          extensions: "dtl, dtljpn"

Further configuration (optional)

You can optionally complete the following configuration steps:

  • Set a default scanner.

    You can set the default scanner of the DependencyScannerRegistry to DependencyScanner or DummyScanner. The default scanner will be used when a file that does not have a scanner mapped to it is scanned. Using sourceDefaultScanner, set the default to either DEPENDENCY or DUMMY. By default, ScannerInit initializes the default scanner to DUMMY. DummyScanner is best used for unknown filetypes that do not need to be parsed. When they are scanned, files will be resolved to a logical file with the language ANY.

    - task: ScannerInit
    variables:
      - name: sourceDefaultScanner
        value: DEPENDENCY
    
  • Add and configure more scanners.

    You can also use the scanners list to set a DependencyScanner with file associations and language hints. For example, name a scanner COBOL, and all filetypes associated with that scanner will be scanned with the language hint COB.

    - task: ScannerInit
    variables:
      - name: scanners
        value:
          - scanner: COBOL
            extensions: "cbl, cob, cobol"
    

    For reference, the following table lists the names and hints of the scanners that are included in the ScannerInit task:

    Name Hint
    COBOL COB
    Assembler ASM
    C C
    C++ CPP
    PL/I PLI
    REXX REXX
    Easytrieve EASY
    zUnit zUnit
    Dependency Dependency
    Dummy Dummy
  • Set exclude lists.

    You can set the excludeFileList to exclude matching filepatterns from being scanned.

    - task: ScannerInit
    variables:
      - name: excludeFileList
        value:
          - *.txt
          - *.log
    

    You can also set a comma separated list of patterns in loadModuleExcludeList to exclude files from being scanned by LinkEditScanner.

    - task: ScannerInit
    variables:
      - name: loadModuleExcludeList
        value: *.SUB, *.SUB2
    

Summary

You have now successfully created and configured a custom dependency scanner to scan DTL files using ScannerInit.

version: 1.0.0
tasks:
  - task: ScannerInit
    variables:
    - name: scanners
      value:
        - scanner: DTL
          source: com.ibm.dbb.extensions.scanners.dtl.DTLDependencyScanner
          extensions: "dtl, dtljpn"

Next steps