/jModInfGen

Tool for generating a module-info file from existing java sources.

Primary LanguageJava

jModInfGen

Tool for generating a module-info file from existing java sources.

Version 1.0.0.Final Nov 15, 2017

Overview

The jModInfGen project provides a utility to assist in the construction of a JDK 9 module-info.java file for your code. This tool uses the output from the JDK's "Java [static] class dependency analyzer", jdeps[1] utility and any existing module-info file in the project to generate a module-info.java file.

Build

This tool must be built using JDK 8.

Dependencies

jModInfGen requires the presents of classes.dot file(s) that jdeps generates. jdeps can be run manually or with the org.apache.maven.plugins:maven-jdeps-plugin.

Limitations

  • It is likely this tool will not be able to identify all the module names of all the packages reported by jdeps. jModInfGen makes the best effort to identify external module names. It reports unknown packages in the generated module.info file for the user to address.

  • The export directive allows the declared package to be exported only to a set of specifically-named modules, and to no others. This restriction can not be determined by this tool. The generated file may need to be editied by the user.

  • The uses directive allows the programmer to identify a service residing in an external module that is used in this module. This is an element this tool can not detect. The user may need to provide edits to the generated module-info file.

  • The open directive allows all of the non-public elements of the declared package to be accessed by this module. This is an element this tool can not detect. The user may need to provide edits to the generated module-info file.

  • The requires directive has optional qualifiers transitive and static. This is information that can not be detected by this tool and may required user editing of the generated file.

Usage

jModInfGen-maven-plugin

A functioning example of the jModInfGen-maven-plugin is provided on jboss-cxf's code base. See https://github.com/rsearls/jbossws-cxf/blob/jModInfGen-example.

Setup

The setup entailed adding plugins maven-jdeps-plugin and jModInfGen-maven-plugin to the project's root pom.xml file. https://github.com/rsearls/jbossws-cxf/blob/jModInfGen-example/pom.xml#L1369 In order for classes.dot files to be generated by maven-jdeps-plugin the dotOutput configuration element MUST be set (line 1384). jModInfGen-maven-plugin requires the dotOutput directory to be in the project's target directory.

The jModInfGen-maven-plugin (line 1390) declares 3 optional configuration elements. Element report (line 1407) causes the summary report to be written to a file rather than the console. verbose causes detailed information to be written in the summary and in each generated module-info file. propertyFile declares a properties file that contains package-name/module-name mappings that will be added to jModInfGen for reference. File myExternalModMap.properties can be see here, (https://github.com/rsearls/jbossws-cxf/blob/jModInfGen-example/myExternalModMap.properties)

Executing The Project

Three steps are required in generating the module-info files.

  • mvn clean install // jdeps requires compiled code
  • mvn jdeps:jdkinternals // generate the jdeps' *.dot files
  • mvn jModInfGen:generate-module-info // generates generated module-info.java files

Summary Report

A verbose summary report can be see here, https://github.com/rsearls/jbossws-cxf/blob/jModInfGen-example/jModInfGen-Summary-Report.txt

If the verbose element has not been declared the default (short) summary report would look as follows.

  Fri Oct 27 18:31:19 EDT 2017
  jModInfoGet Summary Report

13 root directories processed
0 module-info.java files found
6 classes.dot files found
7 directories without classes.dot files
14 service provider files found
6 generated-module-info.java files written

  *** Duplicate Package Names ***
  1 duplicate package names found in the following modules.
  package: org.jboss.wsf.stack.cxf in modules
	client
	server

Take particular note of any duplicate package names. Action may need to be taken to make the package names unique. The, "State of the Module System" (http://openjdk.java.net/projects/jigsaw/spec/sotms/) section 2.3 states,

"... every module reads at most one module defining a given package, and that modules defining
identically-named packages do not interfere with each other."

or described another way

... two different modules may export the same package if - at build time and at run time - no module
depends on both A and B at the same time and if A and B don't depend on each other. In theory you
could have two modules that export the same package, and use them one at a time with another
depending module.

Generated Files

Here is the list of files generated by maven-jdeps-plugin and jModInfGen-maven-plugin for jboss-cxf. The jdeps plugin generates the classes.dot and summary.dot files. jModInfGen plugin generates the generated-module-info.java files and jModInfGen-Summary-Report.txt. Only the classes.dot files contain information that is useful in generating a generated-module-info.java file. No processing is performed in any project that does not have a `classes.dot file.

These files are in the branch for your perusal

	jModInfGen-Summary-Report.txt

	modules/addons/transports/http/undertow/target/gen-jdeps/classes.dot
	modules/addons/transports/http/undertow/target/gen-jdeps/summary.dot
	modules/addons/transports/http/undertow/target/gen-jdeps/generated-module-info.java

	modules/addons/transports/udp/target/gen-jdeps/classes.dot
	modules/addons/transports/udp/target/gen-jdeps/summary.dot
	modules/addons/transports/udp/target/gen-jdeps/generated-module-info.java

	modules/client/target/gen-jdeps/classes.dot
	modules/client/target/gen-jdeps/summary.dot
	modules/client/target/gen-jdeps/generated-module-info.java

	modules/jaspi/target/gen-jdeps/classes.dot
	modules/jaspi/target/gen-jdeps/summary.dot
	modules/jaspi/target/gen-jdeps/generated-module-info.java

	modules/server/target/gen-jdeps/classes.dot
	modules/server/target/gen-jdeps/summary.dot
	modules/server/target/gen-jdeps/generated-module-info.java

	modules/test-utils/target/gen-jdeps/classes.dot
	modules/test-utils/target/gen-jdeps/summary.dot
	modules/test-utils/target/gen-jdeps/generated-module-info.java

	modules/resources/target/gen-jdeps/summary.dot
	modules/endorsed/target/gen-jdeps/summary.dot

generated-module-info.java Sample

https://github.com/rsearls/jbossws-cxf/blob/jModInfGen-example/modules/test-utils/target/gen-jdeps/generated-module-info.java This file shows what the output looks like when the verbose element is enabled and external packages that this project uses have been defined in the user provided properies file, myExternalModMap.properties.

The header comment lists date of generation and the files used in the analysis and generation of this file. If a pre-existing module-info.java have had been present in the project it would have been listed here.

/**
  Sat Oct 28 12:33:49 EDT 2017
  File generated by jModInfoGet
	Analysis of /home/rsearls/j1/jbws/jbossws-cxf/modules/test-utils
		/home/rsearls/j1/jbws/jbossws-cxf/modules/test-utils/target/gen-jdeps/classes.dot
**/

The (generated) module-name is the name of the project directory. If a module-info.java file had been present, the module-name declared there would have been used instead.

module test-utils {

The single line comments after each requires declarations is identifying which packages residing in the required module that this project is referencing. This is merely debugging information and does not appear when verbose is not active.

Note that the org.jboss.shrinkwrap module mapping provided in the myExternalModMap.properties is referenced here.

requires  java.xml.ws;
		//javax.xml.ws  - package referenced
		//javax.xml.ws.handler  - package referenced
		//javax.xml.ws.soap  - package referenced
requires  org.jboss.shrinkwrap;
		//org.jboss.shrinkwrap.api  - package referenced
		//org.jboss.shrinkwrap.api.exporter  - package referenced
		//org.jboss.shrinkwrap.api.spec  - package referenced

At the end of the file is a comment containing a list of packages this project references but for which jModInfGen does not have a module-name.

/**
	The module names for these packages are unknown.
	User intervention may be needed.
		requires org.jboss.logging;
		requires org.jboss.ws.common;
		requires org.jboss.ws.common.concurrent;
		requires org.jboss.ws.common.io;
		requires sun.net.util;
**/

jModInfGen Executable Jar

An executable jar is provided so that jModInfGen can be run from the command-line. Input options can be see via the --help option.

java -jar analyzer-1.0.0-Final.one-jar.jar --help

jModInfoGen command-line options
  -d --inputDirectory   Path to the directory from which to start analysis.
                        Default directory is the one from which jModInfGen is run.
  -f --file   Path to a java properties file that contains package name to module name mappings.
              The file format is <qualified package name>:<module name>
              (e.g. java.applet:java.desktop
                    javax.jws:java.xml.ws
                    org.omg.CosNaming:java.corba  )
  --help   Print the command-line options
  -r --report   Write the Summary Report to a file rather than the console.
  -v --verbose  The Summary Report will contains a detailed list of files found and processed.

Project Structure

  • Project module, mod-info-parser uses lexical analyzer JFlex and LALR Parser Generator for Java java_cup in extracting data from each module-info.java file. This tool does not process module-info.class files as this would require JDK9.

  • Project module, analyzer processes the data written to classes.dot by utility jdeps and a module-info.java file found in the project directory. It generates a module-info file of the analyzed data.

  • Project maven-plugin provides a plugin to be used on multi-module maven projects. It will identify cross module dependences. This plugin relies on the output from org.apache.maven.plugins:maven-jdeps-plugin. maven-jdeps-plugin must be configured to generate classes.dot files.

Related Tools

Currently there are 2 other known 3rd party projects related to addressing JSR 376: "The Java Platform Module System" in Project Jigsaw[2], maven-jdeps-plugin [3] and moditect [4].

  • The maven-jdeps-plugin uses the JDK's jdeps tool to analyze the classes in each maven module of a project. The plugin can run on each module of a multi-module project but it does not perform dependency analysis across modules. (jModInfGen when pointed to the root directory of a multi-module maven project does perform a cross module analysis of the jdeps analysis files and generates references to the inter-project modules.)

  • Moditect is a maven plugin. It generates a module-info.java file for given artifacts for Maven dependencies or local JAR files in the project. The module directives can be declared within configuration elements of the plugin definition.

moditect and jModInfGen differ in the following ways,

  • moditect requires JDK 9 in order to run. Your app can't make use of this tool to generate module-info files until it can build with JDK 9. jModInfGen will run using JDK 8.
  • moditect allows the project to retain pre-defined module directives in the pom.xml. The focus of jModInfGen is to initially generate the module directives. jModInfGen could be used to generate the initial module information and plug that data into the moditect configuration declarations.

References

  1. https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jdeps.html
  2. http://openjdk.java.net/projects/jigsaw/spec/sotms/
  3. https://maven.apache.org/plugins/maven-jdeps-plugin/
  4. https://github.com/moditect/moditect