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.
DTLDependencyScanner.java
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;
    }

}
  1. 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
  scanners:
    - scanner: DTL
      source: com.ibm.dbb.extensions.scanners.dtl.DTLDependencyScanner
      extensions: "dtl, dtljpn"

Further configuration (optional)

Setting 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
  sourceDefaultScanner: DEPENDENCY

Adding and configuring more scanners: The scanners list can also be used 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
  scanners:
    - scanner: COBOL
      extensions: "cbl, cob, cobol"
Table of Names/Hints
Name Hint
COBOL COB
Assembler ASM
C C
C++ CPP
PL/I PLI
REXX REXX
Easytrieve EASY
zUnit zUnit
Dependency Dependency
Dummy Dummy

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

- task: ScannerInit
  excludeFileList:
    - *.txt
    - *.log

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

- task: ScannerInit
  excludeFileList: *.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
  scanners:
    - scanner: DTL
      source: com.ibm.dbb.extensions.scanners.dtl.DTLDependencyScanner
      extensions: "dtl, dtljpn"

Next steps