diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4e7b66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,198 @@ +# User-specific stuff +.idea +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# Don't ignore the demo binaries +!etc/demo/jar/*.jar +!etc/demo/ear/*.ear +!etc/demo/war/*.war + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### VisualStudioCode ### +.vscode/* + +!src/test/resources/sample_apps/daytrader8/binaries/daytrader8.jar +src/test/resources/sample_apps/daytrader8/output + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope +.vscode/*.code-snippets + +# Ignore code-workspaces +*.code-workspace + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/intellij,gradle,java,visualstudiocode +.idea +.DS_Store +.vscode +bin/ +etc/ +/src/test/resources/sample_apps/daytrader8/output/ diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..b1f734e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,10 @@ +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index 328540f..8b94cb3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,183 @@ -# codenet-minerva-code-analyzer -Java source code (and/or binary) to JSON based system dependency graph generator. +# + +![logo](./docs/assets/logo.png) + +Native WALA implementation of source code analysis tool for Enterprise Java Applications. + +## 1. Prerequisites + +Before you begin, ensure you have met the following requirements: + +* You have a Linux/MacOS/WSL machine. +* You have installed the latest version of [SDKMan!](sdkman.io/) + +### 1.1. Install SDKMan! +1. Install SDKMan! + Open your terminal and enter the following command: + + ```bash + curl -s "https://get.sdkman.io" | bash + ``` + + Follow the on-screen instructions to complete the installation. + +2. Open a new terminal or source the SDKMan! scripts: + + ```bash + source "$HOME/.sdkman/bin/sdkman-init.sh" + ``` + +## 2. Building `codeanalyzer` + +### 2.1. Install Java 11 or above + +1. You can list all available GraalVM versions with: + + ```bash + sdk list java | grep sem + ``` + You should see the following: + ``` + Semeru | | 21.0.2 | sem | | 21.0.2-sem + | | 21.0.1 | sem | | 21.0.1-sem + | | 17.0.10 | sem | | 17.0.10-sem + | | 17.0.9 | sem | | 17.0.9-sem + | | 11.0.22 | sem | installed | 11.0.22-sem + | | 11.0.21 | sem | | 11.0.21-sem + ``` + +2. Install Java 11 or above (we'll go with 17.0.10-sem): + + ```bash + sdk install java 17.0.10-sem + ``` + +3. Set Java 17 as the current Java version: + + ```bash + sdk use java 17.0.10-sem + ``` + +### 2.2. Build `codeanalyzer` + +Clone the repository (if you haven't already) and navigate into the cloned directory. + +Run the Gradle wrapper script to build the project. This will compile the project using GraalVM native image. + +```bash +./gradlew fatJar +``` + +### 2.3. Using `codeanalyzer` + +The jar will be built at `build/libs/codeanalyzer-1.0.jar`. It may be used as follows: + +```help +Usage: java -jar /path/to/codeanalyzer-1.0.jar [-hqV] [-d=] [-e=] -i= + -o= +Convert java binary (*.jar, *.ear, *.war) to a neo4j graph. + -d, --app-deps= Path to the application dependencies. + -e, --extra-libs= + Path to the extra libraries. + -h, --help Show this help message and exit. + -i, --input= Path to the input jar(s). + -o, --output= Destination directory to save the output graphs. + -q, --quiet Don't print logs to console. + -V, --version Print version information and exit. +``` + + +## 3. Installing `codeanalyzer` as a native binary (once built, no JVM will be required for running `codeanalyzer`) + +To install `codeanalyzer`, follow these steps: + +### 3.1. Install GraalVM using SDKMan + +1. You can list all available GraalVM versions with: + + ```bash + sdk list java | grep graal + ``` + +2. Install GraalVM 17 or above (we'll go with 21.0.2-graalce): + + ```bash + sdk install java 21.0.2-graalce + ``` + +3. Set GraalVM 21 as the current Java version: + + ```bash + sdk use java 21.0.2-graalce + ``` + +### 3.2. Build the Project + +Clone the repository (if you haven't already) and navigate into the cloned directory. + +Run the Gradle wrapper script to build the project. This will compile the project using GraalVM native image. + +```bash +./gradlew nativeCompile -PbinDir=$HOME/.local/bin +``` + +**Note: `-PbinDir` is optional. If not provided, this command places the binaries in `build/bin`.** + +### 3.3. Using `codeanalyzer` + +Assuming the path you provided in `-PbinDir` (in my case `$HOME/.local/bin`) is in your `$PATH`, after installation, you can use `codeanalyzer` by following the below format: + + ```help + Usage: codeanalyzer [-hqV] [-d=] [-e=] -i= + -o= + Convert java binary (*.jar, *.ear, *.war) to a neo4j graph. + -d, --app-deps= Path to the application dependencies. + -e, --extra-libs= + Path to the extra libraries. + -h, --help Show this help message and exit. + -i, --input= Path to the input jar(s). + -o, --output= Destination directory to save the output graphs. + -q, --quiet Don't print logs to console. + -V, --version Print version information and exit. + ``` + +There is a sample application in `src/test/resources/sample_apps/daytrader8/binaries/`. You can use this to test the tool. + + ```sh + codeanalyzer -i src/test/resources/sample_apps/daytrader8/binaries/ + ``` + +This will produce print the SDG on the console. Explore other flags to save the output to a JSON. + +## FAQ + +1. After making a few code changes, my native binary gives random exceptions. But, my code works perfectly with `java -jar`. + + The `reflect-config.json` is most likely out of date. Plese follow the below instructions: + + a. Build the fatjar using `./gradlew fatJar` + + b. Run the following + + ```sh + java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image-config -jar build/libs/codeanalyzer-1.0.jar -i src/test/resources/sample.applications/daytrader8/source -a 2 -v + ``` + + c. Then build using the instructions in [§3.3](./README.md#33-build-the-project). + + The problem should be resolved. + +## LICENSE + +```LICENSE +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..262b070 --- /dev/null +++ b/build.gradle @@ -0,0 +1,203 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + id 'eclipse' + id 'application' + id 'org.graalvm.buildtools.native' version '0.9.28' +} + +version = 'latest' + +repositories { + mavenCentral() + mavenLocal() +} + + +if (project.hasProperty('mainClass')) { + mainClassName = project.getProperty('mainClass') +} else { + // use a default + mainClassName =("com.ibm.northstar.CodeAnalyzer") +} + +sourceSets { + main { + java { + srcDirs = ["src/main/java"] + } + resources { + srcDirs = ["src/main/resources"] + } + } + test { + java { + srcDirs = ['src/test/java'] + } + resources { + srcDirs= ["src/test/resources"] + } + } +} + +// Remove that nagging bin folder vscode seems to generate every single time +clean.doFirst { + delete "${rootDir}/bin" +} + +dependencies { + // PICOCLI for handling commandline interface + implementation 'info.picocli:picocli:4.1.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' + annotationProcessor 'info.picocli:picocli-codegen:4.1.0' + + implementation 'org.apache.commons:commons-lang3:3.14.0' + + implementation group: 'commons-cli', name: 'commons-cli', version: '1.4' + + implementation 'commons-io:commons-io:2.8.0' + + implementation 'org.apache.logging.log4j:log4j-api:2.18.0' + implementation 'org.apache.logging.log4j:log4j-core:2.18.0' + def walaVersion = '1.6.3' + + compileOnly 'org.projectlombok:lombok:1.18.30' + annotationProcessor 'org.projectlombok:lombok:1.18.30' + + implementation "com.ibm.wala:com.ibm.wala.shrike:${walaVersion}" + implementation "com.ibm.wala:com.ibm.wala.util:${walaVersion}" + implementation "com.ibm.wala:com.ibm.wala.core:${walaVersion}" + implementation "com.ibm.wala:com.ibm.wala.cast:${walaVersion}" + implementation "com.ibm.wala:com.ibm.wala.cast.java:${walaVersion}" + implementation "com.ibm.wala:com.ibm.wala.cast.java.ecj:${walaVersion}" + + compileOnly 'org.projectlombok:lombok:1.18.30' + annotationProcessor 'org.projectlombok:lombok:1.18.30' + + implementation 'com.google.guava:guava:33.0.0-jre' + + implementation("commons-io:commons-io:2.15.1") + implementation("org.ow2.asm:asm:9.6") + implementation("org.eclipse.jdt:org.eclipse.jdt.core:3.21.0") + implementation("org.eclipse.platform:org.eclipse.core.commands:3.9.700") + implementation("org.eclipse.platform:org.eclipse.core.contenttype:3.7.1000") + implementation("org.eclipse.platform:org.eclipse.core.expressions:3.7.100") + implementation("org.eclipse.platform:org.eclipse.core.filesystem:1.9.0") + implementation("org.eclipse.platform:org.eclipse.core.jobs:3.11.0") + implementation('org.eclipse.platform:org.eclipse.core.resources:3.20.0') + implementation("org.eclipse.platform:org.eclipse.core.runtime:3.17.100") + implementation("org.eclipse.platform:org.eclipse.equinox.app:1.5.100") + implementation("org.eclipse.platform:org.eclipse.equinox.common:3.14.100") + implementation("org.eclipse.platform:org.eclipse.equinox.preferences:3.8.200") + implementation("org.eclipse.platform:org.eclipse.equinox.registry:3.10.200") + implementation("org.eclipse.platform:org.eclipse.osgi:3.16.300") + implementation("org.eclipse.platform:org.eclipse.text:3.11.0") + + implementation('org.json:json:20231013') + implementation('com.google.code.gson:gson:2.10.1') + implementation('org.jgrapht:jgrapht-core:1.5.2') + implementation('org.jgrapht:jgrapht-io:1.5.2') + implementation('org.jgrapht:jgrapht-ext:1.5.2') + implementation('com.github.javaparser:javaparser-symbol-solver-core:3.25.9') + + testImplementation group: 'junit', name: 'junit', version: '4.13.2' +} + +task fatjar(type: Jar) { + archiveBaseName = 'codeanalyzer' + archiveFileName = 'codeanalyzer.jar' + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes 'Implementation-Title': 'Northstar Codeanalyzer', + 'Implementation-Version': archiveVersion, + 'Main-Class': 'com.ibm.northstar.CodeAnalyzer' + } + from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } } + with jar +} + +run { + if (project.hasProperty('args')) { + args = project.args.split(',') + } +} + +graalvmNative { + binaries { + main { + imageName = "codeanalyzer" + mainClass = "com.ibm.northstar.CodeAnalyzer" + buildArgs.add("-Ob") + buildArgs.add("-march=compatibility") + buildArgs.add("--no-fallback") + buildArgs.add("--no-server") + buildArgs.add("-H:ReflectionConfigurationFiles=$projectDir/src/main/resources/META-INF/native-image-config/reflect-config.json") + buildArgs.add("-H:ResourceConfigurationFiles=$projectDir/src/main/resources/META-INF/native-image-config/resource-config.json") + buildArgs.add("-H:JNIConfigurationFiles=$projectDir/src/main/resources/META-INF/native-image-config/jni-config.json") + buildArgs.add("-H:DynamicProxyConfigurationFiles=$projectDir/src/main/resources/META-INF/native-image-config/proxy-config.json") + } + test { + buildArgs.add("-O0") + } + } + binaries.configureEach { + buildArgs.add("--verbose") + } +} + +// Define a property for the output directory +def binDir = project.hasProperty('binDir') ? project.property('binDir') : "$projectDir/artifacts/bin" + + +// Task to copy the native executable to the specified directory +task copyNativeExecutable(type: Copy) { + dependsOn nativeCompile // Ensure this runs after the native image is built + + from "${buildDir}/native/nativeCompile/codeanalyzer" + into binDir + + fileMode = 0755 +} + +task createRelease { + doLast { + def releaseTitle = 'latest' + def hostName = 'git@github.ibm.com' + def repo = 'northstar/codeanalyzer' + + // Command to create release + def delete = "gh release delete latest --cleanup-tag --yes -R ${hostName}:${repo}"// + // Execute command + def proc = delete.execute() + proc.in.eachLine { line -> println line } // Print output + proc.err.eachLine { line -> println "Error: $line" } // Print error + proc.waitFor() // Wait for process to complete + def command = "gh release create latest $projectDir/build/libs/codeanalyzer.jar -t ${releaseTitle} -R ${hostName}:${repo}" + try { + def release = command.execute() + release.in.eachLine { line -> println line } // Print output + release.err.eachLine { line -> println "Error: $line" } // Print error + release.waitFor() // Wait for process to complete + } catch (Exception e) { + throw new GradleException("Error executing gh command: ${e.message}") + } + } + +} + +nativeCompile.finalizedBy copyNativeExecutable diff --git a/docs/assets/Artboard 1.png b/docs/assets/Artboard 1.png new file mode 100644 index 0000000..11244fa Binary files /dev/null and b/docs/assets/Artboard 1.png differ diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000..93cab6b Binary files /dev/null and b/docs/assets/logo.png differ diff --git a/docs/assets/ns.png b/docs/assets/ns.png new file mode 100644 index 0000000..b998bf9 Binary files /dev/null and b/docs/assets/ns.png differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d64cd49 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a80b22c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..7101f8e --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..2d7bdb7 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,12 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/CodeAnalyzer.java b/src/main/java/com/ibm/northstar/CodeAnalyzer.java new file mode 100644 index 0000000..a14ccf3 --- /dev/null +++ b/src/main/java/com/ibm/northstar/CodeAnalyzer.java @@ -0,0 +1,157 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar; + + +import com.github.javaparser.Problem; +import com.google.gson.*; +import com.ibm.northstar.entities.JavaCompilationUnit; +import com.ibm.northstar.utils.BuildProject; +import com.ibm.northstar.utils.Log; +import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException; +import com.ibm.wala.ipa.cha.ClassHierarchyException; +import org.apache.commons.lang3.tuple.Pair; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPOutputStream; + +/** + * The type Code analyzer. + */ +@Command(name = "codeanalyzer", mixinStandardHelpOptions = true, sortOptions = false, version = "codeanalyzer v1.1", description = "Convert java binary (*.jar, *.ear, *.war) into a comprehensive system dependency graph.") +public class CodeAnalyzer implements Runnable { + + @Option(names = {"-i", "--input"}, required = true, description = "Path to the project root directory.") + private static String input; + + @Option(names = {"-a", "--analysis-level"}, description = "[Optional] Level of analysis to perform. Options: 1 (for just symbol table) or 2 (for full analysis including the system depenedency graph). Default: 1") + private static int analysisLevel = 1; + + @Option(names = {"-o", "--output"}, description = "[Optional] Destination directory to save the output graphs. By default, the SDG formatted as a JSON will be printed to the console.") + private static String output; + + @Option(names = {"-d", "--dependencies"}, description = "[Optional] Path to the application 3rd party dependencies that may be helpful in analyzing the application.") + private static String dependencies; + + @Option(names = {"-s", "--source-analysis"}, description = "[Experimental] Analyze the source code instead directly of the binary. Warning: This option is experimental and may not work as expected.") + private static boolean analyzeSource = false; + + @Option(names = {"-v", "--verbose"}, description = "Print logs to console.") + private static boolean verbose = false; + + + public static Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .setPrettyPrinting() + .disableHtmlEscaping() + .create(); + /** + * The entry point of application. + * + * @param args the input arguments + */ + public static void main(String[] args) { + int exitCode = new CommandLine(new CodeAnalyzer()).execute(args); + System.exit(exitCode); + } + + @Override + public void run() { + // Set log level based on quiet option + Log.setVerbosity(verbose); + try { + analyze(); + } catch (IOException | CallGraphBuilderCancelException | ClassHierarchyException e) { + throw new RuntimeException(e); + } + } + + private static void analyze() throws IOException, ClassHierarchyException, CallGraphBuilderCancelException { + + // download library dependencies of project for type resolution + if (!BuildProject.downloadLibraryDependencies(input)) { + Log.warn("Failed to download library dependencies of project"); + } + // construct symbol table for project, write parse problems to file in output directory if specified + Pair, Map>> symbolTableExtractionResult = + SymbolTable.extractAll(Paths.get(input)); + Map symbolTable = symbolTableExtractionResult.getLeft(); + if (output != null) { + Path outputPath = Paths.get(output); + if (!Files.exists(outputPath)) { + Files.createDirectories(outputPath); + } + gson.toJson(symbolTableExtractionResult.getRight(), new FileWriter(new File(outputPath.toString(), "parse_errors.json"))); + } + + // Convert the JavaCompilationUnit to JSON + String symbolTableJSONString = gson.toJson(symbolTable); + JsonElement symbolTableJSON = gson.fromJson(symbolTableJSONString, JsonElement.class); + + JsonObject combinedJsonObject = new JsonObject(); + combinedJsonObject.add("symbol_table", symbolTableJSON); + if (analysisLevel > 1) { + // Save SDG, IPCFG, and Call graph as JSON + String sdgAsJSONString = SystemDependencyGraph.construct(input, dependencies, analyzeSource); + JsonElement sdgAsJSONElement = gson.fromJson(sdgAsJSONString, JsonElement.class); + JsonObject sdgAsJSONObject = sdgAsJSONElement.getAsJsonObject(); + + // We don't really need these fields, so we'll remove it. + sdgAsJSONObject.remove("nodes"); + sdgAsJSONObject.remove("creator"); + sdgAsJSONObject.remove("version"); + + // Remove the 'edges' element and move the list of edges up one level + JsonElement edges = sdgAsJSONObject.get("edges"); + combinedJsonObject.add("system_dependency_graph", edges); + + } + String consolidatedJSONString = gson.toJson(combinedJsonObject); + emit(consolidatedJSONString); + } + + private static void emit(String consolidatedJSONString) throws IOException { + if (output == null) { + byte[] bytes = consolidatedJSONString.getBytes(StandardCharsets.UTF_8); + // Create the GZIPOutputStream, using System.out + GZIPOutputStream gzipOS = new GZIPOutputStream(System.out); + // Write the byte array to the GZIPOutputStream + gzipOS.write(bytes); + // Flush the GZIPOutputStream + gzipOS.flush(); + // Close the GZIPOutputStream + gzipOS.close(); + } else { + // If output is not null, export to a file + File file = new File(output, "analysis.json"); + try (FileWriter fileWriter = new FileWriter(file)) { + fileWriter.write(consolidatedJSONString); + Log.done("Analysis output saved at " + output); + } catch (IOException e) { + Log.error("Error writing to file: " + e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/SymbolTable.java b/src/main/java/com/ibm/northstar/SymbolTable.java new file mode 100644 index 0000000..4e4af8f --- /dev/null +++ b/src/main/java/com/ibm/northstar/SymbolTable.java @@ -0,0 +1,486 @@ +package com.ibm.northstar; + +import com.github.javaparser.ParseResult; +import com.github.javaparser.Problem; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.body.*; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.FieldAccessExpr; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithName; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.type.Type; +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.JavaSymbolSolver; +import com.github.javaparser.symbolsolver.utils.SymbolSolverCollectionStrategy; +import com.github.javaparser.utils.ProjectRoot; +import com.github.javaparser.utils.SourceRoot; +import com.google.common.collect.Table; +import com.google.common.collect.Tables; +import com.ibm.northstar.entities.Enum; +import com.ibm.northstar.entities.*; +import com.ibm.northstar.utils.Log; +import org.apache.commons.lang3.tuple.Pair; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +@SuppressWarnings("rawtypes") +public class SymbolTable { + + private static JavaSymbolSolver javaSymbolSolver; + + /** + * Processes the given compilation unit to extract information about classes and + * interfaces + * declared in the unit and returns a JSON object containing the extracted + * information. + * + * @param parseResult compilation unit to be processed + * @return JSON object containing extracted information + */ + + // Let's store the known callables here for future use. + public static Table declaredMethodsAndConstructors = Tables.newCustomTable(new HashMap<>(), () -> new HashMap<>() { + @Override + public Callable get(Object key) { + if (key instanceof String) { + Optional> matchingEntry = this.entrySet().stream().filter(entry -> isMethodSignatureMatch((String) key, entry.getKey())).findFirst(); + if (matchingEntry.isPresent()) { + return matchingEntry.get().getValue(); + } + } + return super.get(key); + } + + private boolean isMethodSignatureMatch(String fullSignature, String searchSignature) { + String methodName = fullSignature.split("\\(")[0]; + String searchMethodName = searchSignature.split("\\(")[0]; + + // Check method name match + if (!methodName.equals(searchMethodName)) { + return false; + } + + // Extract parameters, split by comma, and trim + String[] fullParams = fullSignature.substring(fullSignature.indexOf("(") + 1, fullSignature.lastIndexOf(")")).split(","); + String[] searchParams = searchSignature.substring(searchSignature.indexOf("(") + 1, searchSignature.lastIndexOf(")")).split(","); + + // Allow matching with fewer search parameters + if (searchParams.length != fullParams.length) { + return false; + } + + return IntStream.range(0, searchParams.length).allMatch(i -> { + String fullParamTrimmed = fullParams[i].trim(); + String searchParamTrimmed = searchParams[i].trim(); + return fullParamTrimmed.endsWith(searchParamTrimmed); + }); + } + }); + + private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseResult) { + JavaCompilationUnit cUnit = new JavaCompilationUnit(); + + cUnit.setFilePath(parseResult.getStorage().get().getFileName()); + + // Add the comment field to the compilation unit + cUnit.setComment(parseResult.getComment().isPresent() ? parseResult.getComment().get().asString() : ""); + + // Add imports + cUnit.setImports(parseResult.getImports().stream().map(NodeWithName::getNameAsString).collect(Collectors.toList())); + + // create array node for type declarations + cUnit.setTypeDeclarations(parseResult.findAll(TypeDeclaration.class) + .stream().filter(typeDecl -> typeDecl.getFullyQualifiedName().isPresent()) + .map(typeDecl -> { + // get type name and initialize the type object + String typeName = typeDecl.getFullyQualifiedName().get().toString(); + com.ibm.northstar.entities.Type typeNode = null; + + if (typeDecl instanceof ClassOrInterfaceDeclaration) { + typeNode = new ClassOrInterface(); + ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration)typeDecl; + + // Add interfaces implemented by class + typeNode.setImplementsList(classDecl.getImplementedTypes().stream().map(SymbolTable::resolveType) + .collect(Collectors.toList())); + + // Add class modifiers + typeNode.setModifiers(classDecl.getModifiers().stream().map(m -> m.toString().strip()) + .collect(Collectors.toList())); + + // Add class annotations + typeNode.setAnnotations(classDecl.getAnnotations().stream().map(a -> a.toString().strip()) + .collect(Collectors.toList())); + + // add booleans indicating interfaces and inner/local classes + ((ClassOrInterface)typeNode).setInterface(classDecl.isInterface()); + ((ClassOrInterface)typeNode).setInnerClass(classDecl.isInnerClass()); + ((ClassOrInterface)typeNode).setLocalClass(classDecl.isLocalClassDeclaration()); + + // Add extends + ((ClassOrInterface)typeNode).setExtendsList(classDecl.getExtendedTypes().stream() + .map(SymbolTable::resolveType) + .collect(Collectors.toList())); + + } else if (typeDecl instanceof EnumDeclaration) { + typeNode = new Enum(); + EnumDeclaration enumDecl = (EnumDeclaration)typeDecl; + + // Add interfaces implemented by enum + typeNode.setImplementsList(enumDecl.getImplementedTypes().stream().map(SymbolTable::resolveType) + .collect(Collectors.toList())); + + // Add enum modifiers + typeNode.setModifiers(enumDecl.getModifiers().stream().map(m -> m.toString().strip()) + .collect(Collectors.toList())); + + // Add enum annotations + typeNode.setAnnotations(enumDecl.getAnnotations().stream().map(a -> a.toString().strip()) + .collect(Collectors.toList())); + + // Add enum constants + ((Enum)typeNode).setEnumConstants(enumDecl.getEntries().stream() + .map(SymbolTable::processEnumConstantDeclaration).collect(Collectors.toList())); + + } else { + // TODO: handle AnnotationDeclaration, RecordDeclaration + // set the common type attributes only + Log.warn("Found unsupported type declaration: "+typeDecl.toString()); + typeNode = new com.ibm.northstar.entities.Type(); + } + + /* set common attributes of types that available in type declarations: + is nested type, is class or interface declaration, is enum declaration, + comments, parent class, callable declarations, field declarations */ + + // Set fields indicating nested, class/interface, enum, annotation, and record types + typeNode.setNestedType(typeDecl.isNestedType()); + typeNode.setClassOrInterfaceDeclaration(typeDecl.isClassOrInterfaceDeclaration()); + typeNode.setEnumDeclaration(typeDecl.isEnumDeclaration()); + typeNode.setAnnotationDeclaration(typeDecl.isAnnotationDeclaration()); + typeNode.setRecordDeclaration(typeDecl.isRecordDeclaration()); + + // Add class comment + typeNode.setComment(typeDecl.getComment().isPresent() ? typeDecl.getComment().get().asString() : ""); + + // add parent class (for nested type declarations) + typeNode.setParentType(typeDecl.getParentNode().get() instanceof TypeDeclaration ? + ((TypeDeclaration>)typeDecl.getParentNode().get()).getFullyQualifiedName().get() : ""); + + typeNode.setNestedTypeDeclarations(typeDecl.findAll(TypeDeclaration.class).stream() + .filter(typ -> typ.isClassOrInterfaceDeclaration() || typ.isEnumDeclaration()) + .filter(typ -> typ.getParentNode().isPresent() && typ.getParentNode().get() == typeDecl) + .map(typ -> typ.getFullyQualifiedName().get().toString()).collect(Collectors.toList())); + + // Add information about declared fields (filtering to fields declared in the + // type, not in a nested type) + typeNode.setFieldDeclarations(typeDecl.findAll(FieldDeclaration.class).stream() + .filter(f -> f.getParentNode().isPresent() && f.getParentNode().get() == typeDecl) + .map(SymbolTable::processFieldDeclaration).collect(Collectors.toList())); + List fieldNames = new ArrayList<>(); + typeNode.getFieldDeclarations().stream().map(fd -> fd.getVariables()).forEach(fieldNames::addAll); + + // Add information about declared methods (filtering to methods declared in the class, not in a nested class) + typeNode.setCallableDeclarations(typeDecl.findAll(CallableDeclaration.class).stream() + .filter(c -> c.getParentNode().isPresent() && c.getParentNode().get() == typeDecl) + .map(meth -> { + Pair callableDeclaration = processCallableDeclaration(meth, fieldNames, typeName); + declaredMethodsAndConstructors.put(typeName, callableDeclaration.getLeft(), callableDeclaration.getRight()); + return callableDeclaration; + }).collect(Collectors.toMap(p -> p.getLeft(), p -> p.getRight()))); + + return Pair.of(typeName, typeNode); + }).collect(Collectors.toMap(p -> p.getLeft(), p -> p.getRight()))); + + return cUnit; + } + + /** + * Process enum constant declaration. + * + * @param enumConstDecl enum constant declaration to be processed + * @return EnumConstant object containing extracted information + */ + private static EnumConstant processEnumConstantDeclaration(EnumConstantDeclaration enumConstDecl) { + EnumConstant enumConstant = new EnumConstant(); + + // add enum constant name + enumConstant.setName(enumConstDecl.getNameAsString()); + + // add enum constant arguments + enumConstant.setArguments(enumConstDecl.getArguments().stream().map(a -> a.toString()) + .collect(Collectors.toList())); + + return enumConstant; + } + + + /** + * Process parameter declarations on callables. + * + * @param paramDecl parameter declaration to be processed + */ + private static ParameterInCallable processParameterDeclaration(Parameter paramDecl) { + ParameterInCallable parameter = new ParameterInCallable(); + + parameter.setType(resolveType(paramDecl.getType())); + parameter.setName(paramDecl.getName().toString()); + parameter.setAnnotations(paramDecl.getAnnotations().stream().map(a -> a.toString().strip()).collect(Collectors.toList())); + parameter.setModifiers(paramDecl.getModifiers().stream().map(a -> a.toString().strip()).collect(Collectors.toList())); + return parameter; + } + + /** + * Processes the given callable declaration to extract information about the + * declared method or + * constructor and returns a JSON object containing the extracted information. + * + * @param callableDecl callable (method or constructor) to be processed + * @return Callable object containing extracted information + */ + @SuppressWarnings("unchecked") + private static Pair processCallableDeclaration(CallableDeclaration callableDecl, + List classFields, String typeName) { + Callable callableNode = new Callable(); + + // add comment associated with method/constructor + callableNode.setComment(callableDecl.getComment().isPresent() ? callableDecl.getComment().get().asString() : ""); + + // add annotations on method/constructor + callableNode.setAnnotations((List) callableDecl.getAnnotations().stream().map(mod -> mod.toString().strip()).collect(Collectors.toList())); + + // add method or constructor modifiers + callableNode.setModifiers((List) callableDecl.getModifiers().stream().map(mod -> mod.toString().strip()).collect(Collectors.toList())); + + // add the complete declaration string, including modifiers, throws, and + // parameter names + callableNode.setDeclaration(callableDecl.getDeclarationAsString(true, true, true).strip()); + + // add information about callable parameters: for each parameter, type, name, + // annotations, + // modifiers + callableNode.setParameters((List) callableDecl.getParameters().stream().map(param -> processParameterDeclaration((Parameter) param)).collect(Collectors.toList())); + + // A method declaration may not have a body if it is an abstract method. A + // constructor always + // has a body. So, we need to check if the body is present before processing it + // and capture it + // using the Optional type. + Optional body = (callableDecl instanceof MethodDeclaration) ? ((MethodDeclaration) callableDecl).getBody() : Optional.ofNullable(((ConstructorDeclaration) callableDecl).getBody()); + + // Same as above, a constructor declaration may not have a return type + // and method declaration always has a return type. + callableNode.setReturnType((callableDecl instanceof MethodDeclaration) ? + resolveType(((MethodDeclaration)callableDecl).getType()) : null); + + callableNode.setConstructor(callableDecl instanceof ConstructorDeclaration); + callableNode.setStartLine(callableDecl.getRange().isPresent() ? callableDecl.getRange().get().begin.line : -1); + callableNode.setEndLine(callableDecl.getRange().isPresent() ? callableDecl.getRange().get().end.line : -1); + callableNode.setReferencedTypes(getReferencedTypes(body)); + callableNode.setCode(body.isPresent() ? body.get().toString() : ""); + + callableNode.setCalledMethodDeclaringTypes(getCalledMethodDeclaringTypes(body)); + callableNode.setAccessedFields(getAccessedFields(body, classFields, typeName)); + + String callableSignature = (callableDecl instanceof MethodDeclaration) ? callableDecl.getSignature().asString() : callableDecl.getSignature().asString().replace(callableDecl.getSignature().getName(), ""); + return Pair.of(callableSignature, callableNode); + } + + /** + * Processes the given field declaration to extract information about the + * declared field and + * returns a JSON object containing the extracted information. + * + * @param fieldDecl field declaration to be processed + * @return Field object containing extracted information + */ + private static Field processFieldDeclaration(FieldDeclaration fieldDecl) { + Field field = new Field(); + + // add comment associated with field + field.setComment(fieldDecl.getComment().isPresent() ? fieldDecl.getComment().get().asString() : ""); + + // add annotations on field + field.setAnnotations(fieldDecl.getAnnotations().stream().map(a -> a.toString().strip()).collect(Collectors.toList())); + + // add variable names + field.setVariables(fieldDecl.getVariables().stream().map(v -> v.getName().asString()).collect(Collectors.toList())); + + // add field modifiers + field.setModifiers(fieldDecl.getModifiers().stream().map(m -> m.toString().strip()).collect(Collectors.toList())); + + // add field type + field.setType(resolveType(fieldDecl.getCommonType())); + + // add field start and end lines + field.setStartLine(fieldDecl.getRange().isPresent() ? fieldDecl.getRange().get().begin.line : null); + + field.setEndLine(fieldDecl.getRange().get().end.line); + + return field; + } + + /** + * Computes and returns the set of types references in a block of statement + * (method or constructor + * body). + * + * @param blockStmt Block statement to compute referenced types for + * @return List of types referenced in the block statement + */ + private static List getReferencedTypes(Optional blockStmt) { + Set referencedTypes = new HashSet<>(); + blockStmt.ifPresent(bs -> bs.findAll(VariableDeclarator.class) + .stream() + .filter(vd -> vd.getType().isClassOrInterfaceType()) + .map(vd -> resolveType(vd.getType())) + .forEach(referencedTypes::add)); + return new ArrayList<>(referencedTypes); + } + + /** + * Computes and returns the list if fields accessed in the given callable body. The returned values contain + * field names qualified by names of the declaring types. + * + * @param callableBody Callable body to compute accessed fields for + * @return List of fully qualified field names + */ + private static List getAccessedFields(Optional callableBody, List classFields, + String typeName) { + Set accessedFields = new HashSet<>(); + + // process field access expressions in the callable + callableBody.ifPresent(cb -> cb.findAll(FieldAccessExpr.class) + .stream() + .map(faExpr -> { + String fieldDeclaringType = resolveExpression(faExpr.getScope()); + if (!fieldDeclaringType.isEmpty()) { + return fieldDeclaringType + "." + faExpr.getNameAsString(); + } else { + return faExpr.getNameAsString(); + } + }) + .forEach(accessedFields::add) + ); + + // process all names expressions in callable and match against names of declared fields + // in class TODO: handle local variable declarations with the same name + if (callableBody.isPresent()) { + for (NameExpr nameExpr : callableBody.get().findAll(NameExpr.class)) { + for (String fieldName : classFields) { + if (nameExpr.getNameAsString().equals(fieldName)) { + accessedFields.add(typeName + "." + nameExpr.getNameAsString()); + } + } + } + } + + return new ArrayList<>(accessedFields); + } + + /** + * For method calls occurring in the given callable, computes the set of declaring types and returns + * their qualified names. + * + * @param callableBody Callable to compute declaring types for called methods + * @return List of qualified type names for method calls + */ + private static List getCalledMethodDeclaringTypes(Optional callableBody) { + Set calledMethodDeclaringTypes = new HashSet<>(); + callableBody.ifPresent(cb -> cb.findAll(MethodCallExpr.class) + .stream() + .map(expr -> { + String resolvedExpr = ""; + if (expr.getScope().isPresent()) { + resolvedExpr = resolveExpression(expr.getScope().get()); + if (resolvedExpr.contains(" | ")) { + return resolvedExpr.split(" \\| "); + } + } + return new String[]{resolvedExpr}; + }) + .flatMap(type -> Arrays.stream(type)) + .filter(type -> !type.isEmpty()) + .forEach(calledMethodDeclaringTypes::add) + ); + return new ArrayList<>(calledMethodDeclaringTypes); + } + + /** + * Calculates type for the given expression and returns the resolved type name, or empty string if + * exception occurs during type resolution. + * + * @param expression Expression to be resolved + * @return Resolved type name or empty string if type resolution fails + */ + private static String resolveExpression(Expression expression) { + try { + ResolvedType resolvedType = javaSymbolSolver.calculateType(expression); + if (resolvedType.isReferenceType() || resolvedType.isUnionType()) { + return resolvedType.describe(); + } + } catch (UnsolvedSymbolException use) { + Log.warn("Could not resolve expression: "+expression+"\n"+use.getMessage()); + } + return ""; + } + + /** + * Resolves the given type and returns string representation of the resolved type. If type resolution + * fails, returns string representation (name) of the type. + * @param type Type to be resolved + * @return Resolved (qualified) type name + */ + private static String resolveType(Type type) { + try { + return type.resolve().describe(); + } catch (UnsolvedSymbolException | IllegalStateException e) { + Log.warn("Could not resolve "+type.asString()+": "+e.getMessage()); + return type.asString(); + } + } + + /** + * Collects all source roots (e.g., "src/main/java", "src/test/java") under the given project root path + * using the symbol solver collection strategy. Parses all source files under each source root and + * returns the complete symbol table as map of file path and java compilation unit pairs. + * + * @param projectRootPath root path of the project to be analyzed + * @return Pair of extracted symbol table map and parse problems map for project + * @throws IOException + */ + public static Pair, Map>> extractAll(Path projectRootPath) throws IOException { + SymbolSolverCollectionStrategy symbolSolverCollectionStrategy = new SymbolSolverCollectionStrategy(); + ProjectRoot projectRoot = symbolSolverCollectionStrategy.collect(projectRootPath); + javaSymbolSolver = (JavaSymbolSolver)symbolSolverCollectionStrategy.getParserConfiguration().getSymbolResolver().get(); + Map symbolTable = new LinkedHashMap(); + Map parseProblems = new HashMap>(); + for (SourceRoot sourceRoot : projectRoot.getSourceRoots()) { + for (ParseResult parseResult : sourceRoot.tryToParse()) { + if (parseResult.isSuccessful()) { + CompilationUnit compilationUnit = parseResult.getResult().get(); + symbolTable.put( + compilationUnit.getStorage().get().getPath().toString(), + processCompilationUnit(compilationUnit) + ); + } else { + parseProblems.put(sourceRoot.getRoot().toString(), parseResult.getProblems()); + } + } + } + return Pair.of(symbolTable, parseProblems); + } + + public static void main(String[] args) throws IOException { + extractAll(Paths.get(args[0])); + } + +} diff --git a/src/main/java/com/ibm/northstar/SystemDependencyGraph.java b/src/main/java/com/ibm/northstar/SystemDependencyGraph.java new file mode 100644 index 0000000..29f1e69 --- /dev/null +++ b/src/main/java/com/ibm/northstar/SystemDependencyGraph.java @@ -0,0 +1,287 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar; + +import com.ibm.northstar.utils.AnalysisUtils; +import com.ibm.northstar.utils.Log; +import com.ibm.northstar.entities.*; +import com.ibm.northstar.utils.ScopeUtils; +import com.ibm.wala.cast.ir.ssa.AstIRFactory; +import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory; +import com.ibm.wala.cast.java.translator.jdt.ecj.ECJClassLoaderFactory; +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.ipa.callgraph.*; +import com.ibm.wala.ipa.callgraph.AnalysisOptions.ReflectionOptions; +import com.ibm.wala.ipa.callgraph.impl.Util; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.cha.ClassHierarchyException; +import com.ibm.wala.ipa.cha.ClassHierarchyFactory; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.ipa.modref.ModRef; +import com.ibm.wala.ipa.slicer.MethodEntryStatement; +import com.ibm.wala.ipa.slicer.SDG; +import com.ibm.wala.ipa.slicer.Slicer; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.types.ClassLoaderReference; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.graph.Graph; +import com.ibm.wala.util.graph.GraphSlicer; +import com.ibm.wala.util.graph.traverse.DFS; +import org.apache.commons.io.output.NullOutputStream; +import org.apache.commons.lang3.tuple.Pair; +import org.jgrapht.graph.DefaultDirectedGraph; +import org.jgrapht.nio.json.JSONExporter; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.StringWriter; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +import static com.ibm.northstar.CodeAnalyzer.gson; +import static com.ibm.northstar.utils.AnalysisUtils.getCallableFromSymbolTable; +import static com.ibm.northstar.utils.AnalysisUtils.createAndPutNewCallableInSymbolTable; + +/** + * The type Sdg 2 json. + */ +public class SystemDependencyGraph { + + /** + * Get a JGraphT graph exporter to save graph as JSON. + * + * @return the graph exporter + */ + + + private static JSONExporter, AbstractGraphEdge> getGraphExporter() { + JSONExporter, AbstractGraphEdge> exporter = new JSONExporter<>( + pair -> { + Map vertex = new HashMap<>(); + vertex.put("class_interface_declarations", pair.getLeft()); + vertex.put("callable", gson.toJson(pair.getRight())); + return gson.toJson(vertex); + } + ); +// exporter.setVertexAttributeProvider(v -> v.getRight().getAttributes()); + exporter.setEdgeAttributeProvider(AbstractGraphEdge::getAttributes); + return exporter; + } + + /** + * Convert SDG to a formal Graph representation. + * + * @param entryPoints + * @param sdg + * @param callGraph + * @param edgeLabels + * @return + */ + private static org.jgrapht.Graph, AbstractGraphEdge> buildGraph( + Supplier> entryPoints, + Graph sdg, CallGraph callGraph, + BiFunction edgeLabels) { + + org.jgrapht.Graph, AbstractGraphEdge> graph = new DefaultDirectedGraph<>( + AbstractGraphEdge.class); + + // We'll use forward and backward search on the DFS to identify which CFG nodes + // are dominant + // This is a forward DFS search (or exit time first search) + int dfsNumber = 0; + Map dfsFinish = HashMapFactory.make(); + Iterator search = DFS.iterateFinishTime(sdg, entryPoints.get()); + + while (search.hasNext()) { + dfsFinish.put(search.next(), dfsNumber++); + } + + // This is a reverse DFS search (or entry time first search) + int reverseDfsNumber = 0; + Map dfsStart = HashMapFactory.make(); + Iterator reverseSearch = DFS.iterateDiscoverTime(sdg, entryPoints.get()); + + while (reverseSearch.hasNext()) { + dfsStart.put(reverseSearch.next(), reverseDfsNumber++); + } + + // Populate graph + sdg.stream() + .filter(dfsFinish::containsKey) + .sorted(Comparator.comparingInt(dfsFinish::get)) + .forEach(p -> sdg.getSuccNodes(p).forEachRemaining(s -> { + if (dfsFinish.containsKey(s) + && dfsStart.get(p) != null && dfsStart.get(s) != null + && !((dfsStart.get(p) >= dfsStart.get(s)) + && (dfsFinish.get(p) <= dfsFinish.get(s))) + && !p.getNode().getMethod().equals(s.getNode().getMethod())) { + + // Add the source nodes to the graph as vertices + Pair source = Optional.ofNullable(getCallableFromSymbolTable(p.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getNode().getMethod())); + graph.addVertex(source); + + // Add the target nodes to the graph as vertices + Pair target = Optional.ofNullable(getCallableFromSymbolTable(s.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(s.getNode().getMethod())); + graph.addVertex(target); + + + String edgeType = edgeLabels.apply(p, s); + SystemDepEdge graphEdge = new SystemDepEdge(p, s, edgeType); + SystemDepEdge cgEdge = (SystemDepEdge) graph.getEdge(source, target); + if (source.getRight() != null && target.getRight() != null) { + if (cgEdge == null || !cgEdge.equals(graphEdge)) { + graph.addEdge( + source, + target, + graphEdge); + } else { + graphEdge.incrementWeight(); + } + } + } + })); + + callGraph.getEntrypointNodes() + .forEach(p -> { + // Get call statements that may execute in a given method + Iterator outGoingCalls = p.iterateCallSites(); + outGoingCalls.forEachRemaining(n -> { + callGraph.getPossibleTargets(p, n).stream() + .filter(o -> AnalysisUtils.isApplicationClass(o.getMethod().getDeclaringClass())) + .forEach(o -> { + + // Add the source nodes to the graph as vertices + Pair source = Optional.ofNullable(getCallableFromSymbolTable(p.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getMethod())); + graph.addVertex(source); + + // Add the target nodes to the graph as vertices + Pair target = Optional.ofNullable(getCallableFromSymbolTable(o.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(o.getMethod())); + graph.addVertex(target); + + if (!source.equals(target) && source.getRight() != null && target.getRight() != null) { + + // Get the edge between the source and the target + AbstractGraphEdge cgEdge = graph.getEdge(source, target); + + if (cgEdge == null) { + graph.addEdge(source, target, new CallEdge()); + } + // If edge exists, then increment the weight + else { + cgEdge.incrementWeight(); + } + } + }); + }); + }); + + return graph; + } + + /** + * Construct a System Dependency Graph from a given input. + * + * @param input the input + * @param dependencies the dependencies + * @param experimental the experimental + * @return A List of triples containing the source, destination, and edge type + * @throws IOException the io exception + * @throws ClassHierarchyException the class hierarchy exception + * @throws IllegalArgumentException the illegal argument exception + * @throws CallGraphBuilderCancelException the call graph builder cancel + * exception + */ + public static String construct( + String input, String dependencies, boolean experimental) + throws IOException, ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException { + + // Initialize scope + AnalysisScope scope; + if (dependencies == null) { + scope = ScopeUtils.createScope(input, experimental); + } else { + scope = ScopeUtils.createScope(input, dependencies, experimental); + } + IClassHierarchy cha = ClassHierarchyFactory.makeWithRoot(scope, + new ECJClassLoaderFactory(scope.getExclusions())); + Log.done("There were a total of " + cha.getNumberOfClasses() + " classes of which " + + AnalysisUtils.getNumberOfApplicationClasses(cha) + " are application classes."); + + // Initialize analysis options + AnalysisOptions options = new AnalysisOptions(); + Iterable entryPoints = AnalysisUtils.getEntryPoints(cha); + options.setEntrypoints(entryPoints); + options.getSSAOptions().setDefaultValues(com.ibm.wala.ssa.SymbolTable::getDefaultValue); + options.setReflectionOptions(ReflectionOptions.NONE); + IAnalysisCacheView cache = new AnalysisCacheImpl(AstIRFactory.makeDefaultFactory(), + options.getSSAOptions()); + + // Build call graph + Log.info("Building call graph."); + + // Some fu to remove WALA's console out... + PrintStream originalOut = System.out; + PrintStream originalErr = System.err; + long start_time = System.currentTimeMillis(); + CallGraph callGraph; + CallGraphBuilder builder; + try { + System.setOut(new PrintStream(new NullOutputStream())); + System.setErr(new PrintStream(new NullOutputStream())); + builder = Util.makeRTABuilder(options, cache, cha); + callGraph = builder.makeCallGraph(options, null); + } finally { + System.setOut(originalOut); + System.setErr(originalErr); + } + + Log.done("Finished construction of call graph. Took " + + Math.ceil((double) (System.currentTimeMillis() - start_time) / 1000) + " seconds."); + + // Build SDG graph + Log.info("Building System Dependency Graph."); + SDG sdg = new SDG<>( + callGraph, + builder.getPointerAnalysis(), + new ModRef<>(), + Slicer.DataDependenceOptions.NO_HEAP_NO_EXCEPTIONS, + Slicer.ControlDependenceOptions.NO_EXCEPTIONAL_EDGES); + + // Prune the Graph to keep only application classes. + Graph prunedGraph = GraphSlicer.prune(sdg, + statement -> (statement.getNode() + .getMethod() + .getDeclaringClass() + .getClassLoader() + .getReference() + .equals(ClassLoaderReference.Application))); + + // A supplier to get entries + Supplier> sdgEntryPointsSupplier = () -> callGraph.getEntrypointNodes().stream() + .map(n -> (Statement) new MethodEntryStatement(n)).iterator(); + + org.jgrapht.Graph, AbstractGraphEdge> sdgGraph = buildGraph( + sdgEntryPointsSupplier, + prunedGraph, callGraph, + (p, s) -> String.valueOf(sdg.getEdgeLabels(p, s).iterator().next())); + + JSONExporter, AbstractGraphEdge> graphExporter = getGraphExporter(); + + StringWriter sdgWriter = new StringWriter(); + graphExporter.exportGraph(sdgGraph, sdgWriter); + + return sdgWriter.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/entities/AbstractGraphEdge.java b/src/main/java/com/ibm/northstar/entities/AbstractGraphEdge.java new file mode 100644 index 0000000..b4ee79d --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/AbstractGraphEdge.java @@ -0,0 +1,121 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.entities; + +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.shrike.shrikeCT.InvalidClassFileException; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.SSAInstruction; +import org.jgrapht.nio.Attribute; + +import java.io.Serializable; +import java.util.Map; + +/** + * The type Abstract graph edge. + */ +public abstract class AbstractGraphEdge implements Serializable { + /** + * The Context. + */ + public final String context; + /** + * The Weight. + */ + public Integer weight = 1; + + /** + * Instantiates a new Abstract graph edge. + */ + protected AbstractGraphEdge() { + this(null); + } + + /** + * Instantiates a new Abstract graph edge. + * + * @param context the context + */ + protected AbstractGraphEdge(String context) { + this.context = context; + } + + /** + * Increment weight. + */ + public void incrementWeight() { + this.weight += 1; + } + + /** + * Gets context. + * + * @return the context + */ + public String getContext() { + return this.context; + } + + /** + * Gets id. + * + * @return the id + */ + public Integer getId() { + return this.hashCode(); + } + + /** + * Gets weight. + * + * @return the weight + */ + public Integer getWeight() { + return this.weight; + } + + /** + * Gets statement position. + * + * @param statement the statement + * @return the statement position + */ + Integer getStatementPosition(Statement statement) { + CGNode statementNode = statement.getNode(); + IR statementIR = statementNode.getIR(); + Integer pos = null; + // TODO: check this assumption: the same source instruction maps to several + // SSAInstructions, + // therefore it is sufficient to return the position of the first statement. + for (SSAInstruction inst : statementNode.getIR().getInstructions()) { + try { + pos = statementIR.getMethod().getSourcePosition(inst.iIndex()).getLastLine(); + return pos; + } catch (InvalidClassFileException e) { + throw new RuntimeException(e); + } catch (NullPointerException npe) { + return -1; + } + } + return pos; + } + + /** + * Gets attributes. + * + * @return the attributes + */ + public abstract Map getAttributes(); +} diff --git a/src/main/java/com/ibm/northstar/entities/CallEdge.java b/src/main/java/com/ibm/northstar/entities/CallEdge.java new file mode 100644 index 0000000..5d30ec0 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/CallEdge.java @@ -0,0 +1,69 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.entities; + +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * The type Call edge. + */ +public class CallEdge extends AbstractGraphEdge { + /** + * The constant serialVersionUID. + */ + public static final long serialVersionUID = -8284030936836318929L; + /** + * The Type. + */ + public final String type; + + /** + * Instantiates a new Call edge. + */ + public CallEdge() { + super(); + this.type = toString(); + } + + /** + * Instantiates a new Call edge. + * + * @param context the context + */ + public CallEdge(String context) { + super(context); + this.type = toString(); + } + + @Override + public String toString() { + return "CALL_DEP"; + } + + @Override + public boolean equals(Object o) { + return (o instanceof CallEdge) && (toString().equals(o.toString())); + } + + public Map getAttributes() { + Map map = new LinkedHashMap<>(); + map.put("type", DefaultAttribute.createAttribute(toString())); + map.put("weight", DefaultAttribute.createAttribute(String.valueOf(getWeight()))); + return map; + } +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/entities/Callable.java b/src/main/java/com/ibm/northstar/entities/Callable.java new file mode 100644 index 0000000..0e841c2 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/Callable.java @@ -0,0 +1,23 @@ +package com.ibm.northstar.entities; + +import lombok.Data; + +import java.util.List; + +@Data +public class Callable { + private String comment; + private List annotations; + private List modifiers; + private String declaration; + private List parameters; + private String code; + private int startLine; + private int endLine; + private String returnType = null; + private boolean isImplicit = false; + private boolean isConstructor = false; + private List referencedTypes; + private List accessedFields; + private List calledMethodDeclaringTypes; +} diff --git a/src/main/java/com/ibm/northstar/entities/ClassOrInterface.java b/src/main/java/com/ibm/northstar/entities/ClassOrInterface.java new file mode 100644 index 0000000..d36fba8 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/ClassOrInterface.java @@ -0,0 +1,15 @@ +package com.ibm.northstar.entities; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ClassOrInterface extends Type { + private boolean isInterface; + private boolean isInnerClass; + private boolean isLocalClass; + private List extendsList; +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/entities/Enum.java b/src/main/java/com/ibm/northstar/entities/Enum.java new file mode 100644 index 0000000..5eb397b --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/Enum.java @@ -0,0 +1,12 @@ +package com.ibm.northstar.entities; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper=false) +public class Enum extends Type { + private List enumConstants; +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/entities/EnumConstant.java b/src/main/java/com/ibm/northstar/entities/EnumConstant.java new file mode 100644 index 0000000..d39d0ff --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/EnumConstant.java @@ -0,0 +1,11 @@ +package com.ibm.northstar.entities; + +import lombok.Data; + +import java.util.List; + +@Data +public class EnumConstant { + private String name; + private List arguments; +} diff --git a/src/main/java/com/ibm/northstar/entities/Field.java b/src/main/java/com/ibm/northstar/entities/Field.java new file mode 100644 index 0000000..ce10091 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/Field.java @@ -0,0 +1,16 @@ +package com.ibm.northstar.entities; + +import lombok.Data; +import java.util.List; + +@Data +public class Field { + private String comment; + private String name; + private String type; + private Integer startLine; + private Integer endLine; + private List variables; + private List modifiers; + private List annotations; +} diff --git a/src/main/java/com/ibm/northstar/entities/JavaCompilationUnit.java b/src/main/java/com/ibm/northstar/entities/JavaCompilationUnit.java new file mode 100644 index 0000000..3eb3f9d --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/JavaCompilationUnit.java @@ -0,0 +1,13 @@ +package com.ibm.northstar.entities; + +import lombok.Data; +import java.util.List; +import java.util.Map; + +@Data +public class JavaCompilationUnit { + private String filePath; + private String comment; + private List imports; + private Map typeDeclarations; +} diff --git a/src/main/java/com/ibm/northstar/entities/ParameterInCallable.java b/src/main/java/com/ibm/northstar/entities/ParameterInCallable.java new file mode 100644 index 0000000..cb2ea52 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/ParameterInCallable.java @@ -0,0 +1,17 @@ +package com.ibm.northstar.entities; + +import lombok.Data; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +public class ParameterInCallable { + private String type; + private String name; + private List annotations; + private List modifiers; +} diff --git a/src/main/java/com/ibm/northstar/entities/SystemDepEdge.java b/src/main/java/com/ibm/northstar/entities/SystemDepEdge.java new file mode 100644 index 0000000..6c30326 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/SystemDepEdge.java @@ -0,0 +1,105 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.entities; + +import com.ibm.wala.ipa.slicer.Statement; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.DefaultAttribute; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * The type System dep edge. + */ +public class SystemDepEdge extends AbstractGraphEdge { + /** + * The constant serialVersionUID. + */ + public static final long serialVersionUID = -8284030936836318929L; + /** + * The Source pos. + */ + public final Integer sourcePos; + /** + * The Destination pos. + */ + public final Integer destinationPos; + /** + * The Type. + */ + public final String type; + + /** + * Instantiates a new System dep edge. + * + * @param sourceStatement the source statement + * @param destinationStatement the destination statement + * @param type the type + */ + public SystemDepEdge(Statement sourceStatement, Statement destinationStatement, String type) { + super(); + this.type = type; + this.sourcePos = getStatementPosition(sourceStatement); + this.destinationPos = getStatementPosition(destinationStatement); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(sourcePos).append(destinationPos).append(context).append(type) + .build(); + } + + @Override + public boolean equals(Object o) { + return (o instanceof SystemDepEdge) && (this.toString().equals(o.toString())) + && Integer.valueOf(this.hashCode()).equals(o.hashCode()) + && this.type.equals(((SystemDepEdge) o).getType()); + } + + /** + * Gets type. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * Gets source pos. + * + * @return the source pos + */ + public Integer getSourcePos() { + return sourcePos; + } + + /** + * Gets destination pos. + * + * @return the destination pos + */ + public Integer getDestinationPos() { + return destinationPos; + } + + public Map getAttributes() { + Map map = new LinkedHashMap<>(); + map.put("type", DefaultAttribute.createAttribute(getType())); + map.put("weight", DefaultAttribute.createAttribute(String.valueOf(getWeight()))); + return map; + } +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/entities/Type.java b/src/main/java/com/ibm/northstar/entities/Type.java new file mode 100644 index 0000000..1f77347 --- /dev/null +++ b/src/main/java/com/ibm/northstar/entities/Type.java @@ -0,0 +1,23 @@ +package com.ibm.northstar.entities; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class Type { + private boolean isNestedType; + private boolean isClassOrInterfaceDeclaration; + private boolean isEnumDeclaration; + private boolean isAnnotationDeclaration; + private boolean isRecordDeclaration; + private String comment; + private List implementsList; + private List modifiers; + private List annotations; + private String parentType; + private List nestedTypeDeclarations; + private Map callableDeclarations; + private List fieldDeclarations; +} \ No newline at end of file diff --git a/src/main/java/com/ibm/northstar/utils/AnalysisUtils.java b/src/main/java/com/ibm/northstar/utils/AnalysisUtils.java new file mode 100644 index 0000000..4535cfd --- /dev/null +++ b/src/main/java/com/ibm/northstar/utils/AnalysisUtils.java @@ -0,0 +1,134 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.utils; + +import static com.ibm.northstar.SymbolTable.declaredMethodsAndConstructors; + +import com.ibm.northstar.entities.Callable; +import com.ibm.northstar.entities.ParameterInCallable; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.Entrypoint; +import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.types.ClassLoaderReference; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.apache.commons.lang3.tuple.Pair; +import org.objectweb.asm.Type; + +/** + * The type Analysis utils. + */ +public class AnalysisUtils { + + /** + * The constant classAttr. + */ + public static Pair createAndPutNewCallableInSymbolTable(IMethod method) { + // Get the class name, with a . representation. + String declaringClassSignature = method.getDeclaringClass().getName().toString().substring(1).replace("/", ".").replace("$", "."); + + // Get the method arguments, use a . notation for types. + List arguments = Arrays.stream(Type.getMethodType(method.getDescriptor().toString()).getArgumentTypes()).map(Type::getClassName).collect(Collectors.toList()); + + String methodName = method.getName().toString(); + + // Get the method signature. + String methodSignature = String.join("", methodName, "(", String.join(", ", Optional.of(arguments).orElseGet(Collections::emptyList)), ")"); + + Callable newCallable = new Callable(); + newCallable.setImplicit(true); + newCallable.setConstructor(methodName.contains("")); + newCallable.setComment(""); + newCallable.setModifiers(Stream.of(method.isPublic() ? "public" : null, method.isProtected() ? "protected" : null, method.isPrivate() ? "private" : null, method.isAbstract() ? "abstract" : null, method.isStatic() ? "static" : null, method.isFinal() ? "final" : null, method.isSynchronized() ? "synchronized" : null, method.isNative() ? "native" : null, method.isSynthetic() ? "synthetic" : null, method.isBridge() ? "bridge" : null).filter(Objects::nonNull).collect(Collectors.toList())); + newCallable.setCode(""); + newCallable.setDeclaration(methodSignature); + newCallable.setEndLine(-1); + newCallable.setStartLine(-1); + newCallable.setParameters(Arrays.stream(Type.getMethodType(method.getDescriptor().toString()).getArgumentTypes()).map(param -> { + ParameterInCallable parameter = new ParameterInCallable(); + parameter.setType(param.getClassName()); + parameter.setName(null); + parameter.setModifiers(Collections.emptyList()); + parameter.setAnnotations(Collections.emptyList()); + return parameter; + }).collect(Collectors.toList())); + newCallable.setReferencedTypes(Collections.emptyList()); + newCallable.setAnnotations(method.getAnnotations().stream().map(annotation -> annotation.toString().replace("[", "(").replace("]", ")").replace("Annotation type ", "@")).collect(Collectors.toList())); + + declaredMethodsAndConstructors.put(declaringClassSignature, methodSignature, newCallable); + + return Pair.of(declaringClassSignature, newCallable); + } + + public static Pair getCallableFromSymbolTable(IMethod method) { + + // Get the class name, with a . representation. + String declaringClassSignature = method.getDeclaringClass().getName().toString().substring(1).replace("/", ".").replace("$", "."); + + // Get the method arguments, use a . notation for types. + List arguments = Arrays.stream(Type.getMethodType(method.getDescriptor().toString()).getArgumentTypes()).map(Type::getClassName).collect(Collectors.toList()); + + // Get the method signature. + String methodSignature = String.join("", method.getName().toString(), "(", String.join(", ", Optional.of(arguments).orElseGet(Collections::emptyList)), ")"); + + return Pair.of(declaringClassSignature, declaredMethodsAndConstructors.get(declaringClassSignature, methodSignature)); + } + + /** + * Verfy if a class is an application class. + * + * @param _class the class + * @return Boolean boolean + */ + public static Boolean isApplicationClass(IClass _class) { + return _class.getClassLoader().getReference().equals(ClassLoaderReference.Application); + } + + /** + * Gets number of application classes. + * + * @param cha the cha + * @return the number of application classes + */ + public static long getNumberOfApplicationClasses(IClassHierarchy cha) { + return StreamSupport.stream(cha.spliterator(), false).filter(AnalysisUtils::isApplicationClass).count(); + } + + /** + * Use all public methods of all application classes as entrypoints. + * + * @param cha the cha + * @return Iterable entry points + */ + public static Iterable getEntryPoints(IClassHierarchy cha) { + List entrypoints = StreamSupport.stream(cha.spliterator(), true).filter(AnalysisUtils::isApplicationClass).flatMap(c -> { + try { + return c.getDeclaredMethods().stream(); + } catch (NullPointerException nullPointerException) { + Log.error(c.getSourceFileName()); + System.exit(1); + return Stream.empty(); + } + }).filter(method -> method.isPublic() || method.isPrivate() || method.isProtected() || method.isStatic()).map(method -> new DefaultEntrypoint(method, cha)).collect(Collectors.toList()); + + Log.info("Registered " + entrypoints.size() + " entrypoints."); + return entrypoints; + } +} diff --git a/src/main/java/com/ibm/northstar/utils/BuildProject.java b/src/main/java/com/ibm/northstar/utils/BuildProject.java new file mode 100644 index 0000000..1942c83 --- /dev/null +++ b/src/main/java/com/ibm/northstar/utils/BuildProject.java @@ -0,0 +1,142 @@ +package com.ibm.northstar.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import static com.ibm.northstar.utils.ProjectDirectoryScanner.classFilesStream; + +public class BuildProject { + + private static final String LIB_DEPS_DOWNLOAD_DIR = "_libdeps"; + + private static boolean buildWithTool(String[] buildCommand) { + Log.info("Building the project using " + buildCommand[0] + "."); + ProcessBuilder processBuilder = new ProcessBuilder(buildCommand); + + try { + Process process = processBuilder.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.info(line); + } + int exitCode = process.waitFor(); + Log.info(buildCommand[0].toUpperCase() + " build exited with code " + exitCode); + return exitCode == 0; + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + return false; + } + } + + /** + * Checks if Maven is installed in the system. + * + * @return true if Maven is installed, false otherwise. + */ + private static boolean isMavenInstalled() { + ProcessBuilder processBuilder = new ProcessBuilder("mvn", "--version"); + try { + Process process = processBuilder.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line = reader.readLine(); // Read the first line of the output + if (line != null && line.contains("Apache Maven")) { + Log.info("Maven is installed: " + line); + return true; + } + } catch (IOException e) { + Log.error("An error occurred while checking if Maven is installed: " + e.getMessage()); + } + Log.error("Maven is not installed or not properly configured in the system's PATH."); + return false; + } + + /** + * Initiates a maven build process for the given project path. + * + * @param projectPath is the path to the project to be built. + * @return true if the build was successful, false otherwise. + */ + private static boolean mavenBuild(String projectPath) { + Log.info("Building the project using Maven."); + if (!isMavenInstalled()) { + Log.info("Checking if Maven is installed."); + return false; + } + String[] mavenCommand = { + "mvn", "clean", "package", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", + "-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip", + "-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true", + "-Drat.skip=true", "-Dspotless.check.skip=true" }; + + return buildWithTool(mavenCommand); + } + + public static boolean gradleBuild(String projectPath) { + // Adjust Gradle command as needed + String gradleWrapper = projectPath + "/gradlew"; + String[] gradleCommand = { gradleWrapper, "clean", "compileJava", "-p", projectPath }; + return buildWithTool(gradleCommand); + } + + private static boolean buildProject(String projectPath) { + File pomFile = new File(projectPath, "pom.xml"); + if (pomFile.exists()) { + Log.info("Found pom.xml in the project directory. Using Maven to build the project."); + return mavenBuild(projectPath); // Use Maven if pom.xml exists + } else { + Log.info("Did not find a pom.xml in the project directory. Using Gradle to build the project."); + return gradleBuild(projectPath); // Otherwise, use Gradle + } + } + + /** + * Streams the files in the given project path. + * + * @param projectPath is the path to the project to be streamed. + * @return true if the streaming was successful, false otherwise. + */ + public static List buildProjectAndStreamClassFiles(String projectPath) throws IOException { + return buildProject(projectPath) ? classFilesStream(projectPath) : null; + } + + /** + * Downloads library dependency jars of the given project so that the jars can be used + * for type resolution during symbol table creation. + * + * @param projectPath Path to the project under analysis + * @return true if dependency download succeeds; false otherwise + */ + public static boolean downloadLibraryDependencies(String projectPath) { + // created download dir if it does not exist + Path libDownloadPath = Paths.get(projectPath, LIB_DEPS_DOWNLOAD_DIR); + if (!Files.exists(libDownloadPath)) { + try { + Files.createDirectory(libDownloadPath); + } catch (IOException e) { + Log.error("Error creating library dependency directory for " + projectPath + ": " +e.getMessage()); + return false; + } + } + File pomFile = new File(projectPath, "pom.xml"); + if (pomFile.exists()) { + Log.info("Found pom.xml in the project directory. Using Maven to download dependencies."); + String[] mavenCommand = { + "mvn", "--no-transfer-progress", "-f", + Paths.get(projectPath, "pom.xml").toString(), + "dependency:copy-dependencies", + "-DoutputDirectory=" + libDownloadPath.toString() + }; + return buildWithTool(mavenCommand); + } else { + // TODO: implement for gradle + return false; + } + } +} diff --git a/src/main/java/com/ibm/northstar/utils/Log.java b/src/main/java/com/ibm/northstar/utils/Log.java new file mode 100644 index 0000000..d534893 --- /dev/null +++ b/src/main/java/com/ibm/northstar/utils/Log.java @@ -0,0 +1,135 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.utils; + +import java.time.LocalDateTime; + +/** + * The type Log. + */ +public class Log { + /** + * The constant ANSI_RESET. + */ + public static final String ANSI_RESET = "\u001B[0m"; + /** + * The constant ANSI_BLACK. + */ + public static final String ANSI_BLACK = "\u001B[30m"; + /** + * The constant ANSI_RED. + */ + public static final String ANSI_RED = "\u001B[31m"; + /** + * The constant ANSI_GREEN. + */ + public static final String ANSI_GREEN = "\u001B[32m"; + /** + * The constant ANSI_YELLOW. + */ + public static final String ANSI_YELLOW = "\u001B[33m"; + /** + * The constant ANSI_BLUE. + */ + public static final String ANSI_BLUE = "\u001B[34m"; + /** + * The constant ANSI_PURPLE. + */ + public static final String ANSI_PURPLE = "\u001B[35m"; + /** + * The constant ANSI_CYAN. + */ + public static final String ANSI_CYAN = "\u001B[36m"; + /** + * The constant ANSI_WHITE. + */ + public static final String ANSI_WHITE = "\u001B[37m"; + private static boolean verbose = true; + + /** + * Set verbose setting to on or off. + * + * @param val True or false. + */ + public static final void setVerbosity(boolean val) { + verbose = val; + } + + /** + * Is verbosity turned on/off + * + * @return Boolean boolean + */ + public static final boolean isVerbose() { + return verbose; + } + + /** + * Info. + * + * @param msg the msg + */ + public static final void info(String msg) { + toConsole(msg, ANSI_PURPLE, "INFO"); + } + + /** + * Done. + * + * @param msg the msg + */ + public static final void done(String msg) { + toConsole(msg, ANSI_GREEN, "DONE"); + } + + /** + * Debug. + * + * @param msg the msg + */ + public static final void debug(String msg) { + toConsole(msg, ANSI_YELLOW, "DEBUG"); + } + + /** + * Warn. + * + * @param msg the msg + */ + public static final void warn(String msg) { + toConsole(msg, ANSI_YELLOW, "WARN"); + } + + /** + * Error. + * + * @param msg the msg + */ + public static final void error(String msg) { + toConsole(msg, ANSI_RED, "ERROR"); + } + + /** + * Print log message to console + * + * @param msg to print to console + */ + private static void toConsole(String msg, String ansi_color, String Level) { + if (isVerbose()) { + LocalDateTime localDateTime = LocalDateTime.now(); + System.out.println( + ANSI_CYAN + localDateTime + ANSI_RESET + ansi_color + "\t[" + Level + "]\t" + ANSI_RESET + msg); + } + } +} diff --git a/src/main/java/com/ibm/northstar/utils/ProjectDirectoryScanner.java b/src/main/java/com/ibm/northstar/utils/ProjectDirectoryScanner.java new file mode 100644 index 0000000..e2835f9 --- /dev/null +++ b/src/main/java/com/ibm/northstar/utils/ProjectDirectoryScanner.java @@ -0,0 +1,58 @@ +package com.ibm.northstar.utils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ProjectDirectoryScanner { + public static List classFilesStream(String projectPath) throws IOException { + Path projectDir = Paths.get(projectPath); + Log.info("Finding *.class files in " + projectDir); + if (Files.exists(projectDir)) { + try (Stream paths = Files.walk(projectDir)) { + return paths + .filter(file -> !Files.isDirectory(file) && file.toString().endsWith(".class")) + .filter(file -> !file.toAbsolutePath().toString().contains("test/resources/")) + .filter(file -> !file.toAbsolutePath().toString().contains("main/resources/")) + .collect(Collectors.toList()); + } + } + return null; + } + + public static List jarFilesStream(String projectPath) throws IOException { + Path projectDir = Paths.get(projectPath); + Log.info("Finding *.jar files in " + projectDir); + if (Files.exists(projectDir)) { + try (Stream paths = Files.walk(projectDir)) { + return paths + .filter(file -> !Files.isDirectory(file) && file.toString().endsWith(".jar")) + .collect(Collectors.toList()); + } + } + return null; + } + + public static List sourceFilesStream(String projectPath) throws IOException { + Path projectDir = Paths.get(projectPath); + Log.info("Finding *.java files in " + projectDir); + if (Files.exists(projectDir)) { + try (Stream paths = Files.walk(projectDir)) { + return paths + .filter(file -> !Files.isDirectory(file)) + .filter(file -> file.toString().endsWith(".java")) + .filter(file -> !file.toAbsolutePath().toString().contains("build/")) + .filter(file -> !file.toAbsolutePath().toString().contains("target/")) + .filter(file -> !file.toAbsolutePath().toString().contains("main/resources/")) + .filter(file -> !file.toAbsolutePath().toString().contains("test/resources/")) + .collect(Collectors.toList()); + } + } + return null; + } + +} diff --git a/src/main/java/com/ibm/northstar/utils/ScopeUtils.java b/src/main/java/com/ibm/northstar/utils/ScopeUtils.java new file mode 100644 index 0000000..ac96a23 --- /dev/null +++ b/src/main/java/com/ibm/northstar/utils/ScopeUtils.java @@ -0,0 +1,139 @@ +/* +Copyright IBM Corporation 2023, 2024 + +Licensed under the Apache Public License 2.0, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.ibm.northstar.utils; + +import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope; +import com.ibm.wala.ipa.callgraph.AnalysisScope; +import com.ibm.wala.shrike.shrikeCT.InvalidClassFileException; +import com.ibm.wala.types.ClassLoaderReference; +import com.ibm.wala.util.config.FileOfClasses; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Struct; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.jar.JarFile; + +import org.apache.commons.io.FileUtils; + +import static com.ibm.northstar.utils.ProjectDirectoryScanner.jarFilesStream; + +public class ScopeUtils { + + private static final String EXCLUSIONS = ""; + + /** + * The Std libs. + */ + public static String[] stdLibs; + + /** + * Create an analysis scope base on the input + * + * @param projectPath The root directory of the project to be analyzed. + * @return scope The created analysis scope + * @throws IOException the io exception + */ + public static AnalysisScope createScope(String projectPath, boolean experimental) + throws IOException { + return createScope(projectPath, null, experimental); + } + + /** + * Create an analysis scope base on the input + * + * @param projectPath The root directory of the project to be analyzed. + * @param applicationDeps the application deps + * @return scope The created analysis scope + * @throws IOException the io exception + */ + public static AnalysisScope createScope(String projectPath, String applicationDeps, boolean experimental) + throws IOException { + Log.info("Create analysis scope."); + AnalysisScope scope = new JavaSourceAnalysisScope(); + addDefaultExclusions(scope); + + Log.info("Loading Java SE standard libs."); + String[] stdlibs = Files.walk(Paths.get(System.getenv("JAVA_HOME"), "jmods")) + .filter(path -> path.toString().endsWith(".jmod")) + .map(path -> path.toAbsolutePath().toString()) + .toArray(String[]::new); + + for (String stdlib : stdlibs) { + scope.addToScope(ClassLoaderReference.Primordial, new JarFile(stdlib)); + } + setStdLibs(stdlibs); + + // ------------------------------------- + // Add extra user provided JARS to scope + // ------------------------------------- + if (!(applicationDeps == null)) { + Log.info("Loading user specified extra libs."); + Objects.requireNonNull(jarFilesStream(applicationDeps)).stream() + .forEach( + extraLibJar -> { + Log.info("-> Adding dependency " + extraLibJar + " to analysis scope."); + try { + scope.addToScope(ClassLoaderReference.Extension, new JarFile(extraLibJar.toAbsolutePath().toFile())); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } else { + Log.warn("No extra libraries to process."); + } + + Path path = Paths.get(FileUtils.getTempDirectory().getAbsolutePath(), UUID.randomUUID().toString()); + String tmpDirString = Files.createDirectories(path).toFile().getAbsolutePath(); + Path workDir = Paths.get(tmpDirString); + FileUtils.cleanDirectory(workDir.toFile()); + + List applicationClassFiles = BuildProject.buildProjectAndStreamClassFiles(projectPath); + Log.debug("Application class files: " + String.valueOf(applicationClassFiles.size())); + if (applicationClassFiles == null) { + Log.error("No application classes found."); + throw new RuntimeException("No application classes found."); + } + Log.info("Adding application classes to scope."); + applicationClassFiles.forEach( + applicationClassFile -> { + try { + scope.addClassFileToScope( + ClassLoaderReference.Application, applicationClassFile.toFile()); + } catch (InvalidClassFileException e) { + throw new RuntimeException(e); + } + }); + + return scope; + } + + private static AnalysisScope addDefaultExclusions(AnalysisScope scope) + throws IOException { + Log.info("Add exclusions to scope."); + scope.setExclusions(new FileOfClasses(new ByteArrayInputStream(EXCLUSIONS.getBytes(StandardCharsets.UTF_8)))); + return scope; + } + + private static void setStdLibs(String[] stdlibs) { + stdLibs = stdlibs; + } +} diff --git a/src/main/resources/META-INF/native-image-config/jni-config.json b/src/main/resources/META-INF/native-image-config/jni-config.json new file mode 100644 index 0000000..8b4e417 --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/jni-config.json @@ -0,0 +1,6 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +} +] diff --git a/src/main/resources/META-INF/native-image-config/predefined-classes-config.json b/src/main/resources/META-INF/native-image-config/predefined-classes-config.json new file mode 100644 index 0000000..0e79b2c --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/src/main/resources/META-INF/native-image-config/proxy-config.json b/src/main/resources/META-INF/native-image-config/proxy-config.json new file mode 100644 index 0000000..0d4f101 --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/src/main/resources/META-INF/native-image-config/reflect-config.json b/src/main/resources/META-INF/native-image-config/reflect-config.json new file mode 100644 index 0000000..2c027f5 --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/reflect-config.json @@ -0,0 +1,240 @@ +[ +{ + "name":"[B" +}, +{ + "name":"[Ljava.lang.String;" +}, +{ + "name":"[Lsun.security.pkcs.SignerInfo;" +}, +{ + "name":"com.ibm.northstar.CodeAnalyzer", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.ibm.northstar.entities.Callable", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.ibm.northstar.entities.ClassOrInterface", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.ibm.northstar.entities.Field", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.ibm.northstar.entities.JavaCompilationUnit", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.ibm.northstar.entities.ParameterInCallable", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.ibm.northstar.entities.Type", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"getRecordComponents","parameterTypes":[] }, {"name":"isRecord","parameterTypes":[] }] +}, +{ + "name":"java.lang.Object", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.reflect.RecordComponent", + "methods":[{"name":"getName","parameterTypes":[] }, {"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.nio.file.Path" +}, +{ + "name":"java.nio.file.Paths", + "methods":[{"name":"get","parameterTypes":["java.lang.String","java.lang.String[]"] }] +}, +{ + "name":"java.security.interfaces.RSAPrivateKey" +}, +{ + "name":"java.security.interfaces.RSAPublicKey" +}, +{ + "name":"java.sql.Connection" +}, +{ + "name":"java.sql.Date" +}, +{ + "name":"java.sql.Driver" +}, +{ + "name":"java.sql.DriverManager", + "methods":[{"name":"getConnection","parameterTypes":["java.lang.String"] }, {"name":"getDriver","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.sql.Time", + "methods":[{"name":"","parameterTypes":["long"] }] +}, +{ + "name":"java.sql.Timestamp", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.Duration", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Instant", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalDate", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.MonthDay", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.OffsetDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.OffsetTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Period", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Year", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.YearMonth", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.ZoneId", + "methods":[{"name":"of","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.ZoneOffset", + "methods":[{"name":"of","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.ZonedDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.util.Date" +}, +{ + "name":"java.util.HashMap", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.util.LinkedHashMap", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"picocli.CommandLine$AutoHelpMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSASignature$SHA256withRSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.util.ObjectIdentifier" +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificateExtensions" +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/src/main/resources/META-INF/native-image-config/resource-config.json b/src/main/resources/META-INF/native-image-config/resource-config.json new file mode 100644 index 0000000..271f2e6 --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt67b/nfkc.nrm\\E" + }]}, + "bundles":[] +} diff --git a/src/main/resources/META-INF/native-image-config/serialization-config.json b/src/main/resources/META-INF/native-image-config/serialization-config.json new file mode 100644 index 0000000..f3d7e06 --- /dev/null +++ b/src/main/resources/META-INF/native-image-config/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} diff --git a/src/main/resources/java-std-libs/java11/java.base.jmod b/src/main/resources/java-std-libs/java11/java.base.jmod new file mode 100644 index 0000000..f6c8e6f Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.base.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.compiler.jmod b/src/main/resources/java-std-libs/java11/java.compiler.jmod new file mode 100644 index 0000000..32959ed Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.datatransfer.jmod b/src/main/resources/java-std-libs/java11/java.datatransfer.jmod new file mode 100644 index 0000000..778c864 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.datatransfer.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.desktop.jmod b/src/main/resources/java-std-libs/java11/java.desktop.jmod new file mode 100644 index 0000000..7d1168e Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.instrument.jmod b/src/main/resources/java-std-libs/java11/java.instrument.jmod new file mode 100644 index 0000000..b85edf1 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.instrument.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.logging.jmod b/src/main/resources/java-std-libs/java11/java.logging.jmod new file mode 100644 index 0000000..8125361 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.logging.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.management.jmod b/src/main/resources/java-std-libs/java11/java.management.jmod new file mode 100644 index 0000000..ea12fed Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.management.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.management.rmi.jmod b/src/main/resources/java-std-libs/java11/java.management.rmi.jmod new file mode 100644 index 0000000..4a514dc Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.management.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.naming.jmod b/src/main/resources/java-std-libs/java11/java.naming.jmod new file mode 100644 index 0000000..945141e Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.naming.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.net.http.jmod b/src/main/resources/java-std-libs/java11/java.net.http.jmod new file mode 100644 index 0000000..7379ede Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.net.http.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.prefs.jmod b/src/main/resources/java-std-libs/java11/java.prefs.jmod new file mode 100644 index 0000000..eec3509 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.prefs.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.rmi.jmod b/src/main/resources/java-std-libs/java11/java.rmi.jmod new file mode 100644 index 0000000..04fc108 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.scripting.jmod b/src/main/resources/java-std-libs/java11/java.scripting.jmod new file mode 100644 index 0000000..cf6f812 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.scripting.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.se.jmod b/src/main/resources/java-std-libs/java11/java.se.jmod new file mode 100644 index 0000000..1390826 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.se.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.security.jgss.jmod b/src/main/resources/java-std-libs/java11/java.security.jgss.jmod new file mode 100644 index 0000000..2205352 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.security.sasl.jmod b/src/main/resources/java-std-libs/java11/java.security.sasl.jmod new file mode 100644 index 0000000..57a7f3f Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.security.sasl.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.smartcardio.jmod b/src/main/resources/java-std-libs/java11/java.smartcardio.jmod new file mode 100644 index 0000000..8a6ada4 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.smartcardio.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.sql.jmod b/src/main/resources/java-std-libs/java11/java.sql.jmod new file mode 100644 index 0000000..5914026 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.sql.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.sql.rowset.jmod b/src/main/resources/java-std-libs/java11/java.sql.rowset.jmod new file mode 100644 index 0000000..d0460ff Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.sql.rowset.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.transaction.xa.jmod b/src/main/resources/java-std-libs/java11/java.transaction.xa.jmod new file mode 100644 index 0000000..223d616 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.transaction.xa.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.xml.crypto.jmod b/src/main/resources/java-std-libs/java11/java.xml.crypto.jmod new file mode 100644 index 0000000..ec01a89 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.xml.crypto.jmod differ diff --git a/src/main/resources/java-std-libs/java11/java.xml.jmod b/src/main/resources/java-std-libs/java11/java.xml.jmod new file mode 100644 index 0000000..c1e58bc Binary files /dev/null and b/src/main/resources/java-std-libs/java11/java.xml.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.accessibility.jmod b/src/main/resources/java-std-libs/java11/jdk.accessibility.jmod new file mode 100644 index 0000000..19317aa Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.accessibility.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.attach.jmod b/src/main/resources/java-std-libs/java11/jdk.attach.jmod new file mode 100644 index 0000000..2a472f8 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.attach.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.charsets.jmod b/src/main/resources/java-std-libs/java11/jdk.charsets.jmod new file mode 100644 index 0000000..6dda23b Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.charsets.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.compiler.jmod b/src/main/resources/java-std-libs/java11/jdk.compiler.jmod new file mode 100644 index 0000000..d3bf0fe Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.crypto.cryptoki.jmod b/src/main/resources/java-std-libs/java11/jdk.crypto.cryptoki.jmod new file mode 100644 index 0000000..cb5d8e7 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.crypto.cryptoki.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.crypto.ec.jmod b/src/main/resources/java-std-libs/java11/jdk.crypto.ec.jmod new file mode 100644 index 0000000..ace2334 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.crypto.ec.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.dynalink.jmod b/src/main/resources/java-std-libs/java11/jdk.dynalink.jmod new file mode 100644 index 0000000..4f48a15 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.dynalink.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.editpad.jmod b/src/main/resources/java-std-libs/java11/jdk.editpad.jmod new file mode 100644 index 0000000..31a043c Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.editpad.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.httpserver.jmod b/src/main/resources/java-std-libs/java11/jdk.httpserver.jmod new file mode 100644 index 0000000..7837ae5 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.httpserver.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.internal.ed.jmod b/src/main/resources/java-std-libs/java11/jdk.internal.ed.jmod new file mode 100644 index 0000000..61256a0 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.internal.ed.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.internal.jvmstat.jmod b/src/main/resources/java-std-libs/java11/jdk.internal.jvmstat.jmod new file mode 100644 index 0000000..11e3d41 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.internal.jvmstat.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.internal.le.jmod b/src/main/resources/java-std-libs/java11/jdk.internal.le.jmod new file mode 100644 index 0000000..ba3e1a0 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.internal.le.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.internal.opt.jmod b/src/main/resources/java-std-libs/java11/jdk.internal.opt.jmod new file mode 100644 index 0000000..e6f85e1 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.internal.opt.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jartool.jmod b/src/main/resources/java-std-libs/java11/jdk.jartool.jmod new file mode 100644 index 0000000..18fded4 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jartool.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.javadoc.jmod b/src/main/resources/java-std-libs/java11/jdk.javadoc.jmod new file mode 100644 index 0000000..a5dd48f Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.javadoc.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jcmd.jmod b/src/main/resources/java-std-libs/java11/jdk.jcmd.jmod new file mode 100644 index 0000000..51404bb Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jcmd.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jconsole.jmod b/src/main/resources/java-std-libs/java11/jdk.jconsole.jmod new file mode 100644 index 0000000..c86e029 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jconsole.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jdeps.jmod b/src/main/resources/java-std-libs/java11/jdk.jdeps.jmod new file mode 100644 index 0000000..f886af1 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jdeps.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jdi.jmod b/src/main/resources/java-std-libs/java11/jdk.jdi.jmod new file mode 100644 index 0000000..a845cc8 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jdi.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jdwp.agent.jmod b/src/main/resources/java-std-libs/java11/jdk.jdwp.agent.jmod new file mode 100644 index 0000000..7b94732 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jdwp.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jlink.jmod b/src/main/resources/java-std-libs/java11/jdk.jlink.jmod new file mode 100644 index 0000000..dc93064 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jlink.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jshell.jmod b/src/main/resources/java-std-libs/java11/jdk.jshell.jmod new file mode 100644 index 0000000..fe6559c Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jshell.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.jsobject.jmod b/src/main/resources/java-std-libs/java11/jdk.jsobject.jmod new file mode 100644 index 0000000..a668994 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.jsobject.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.localedata.jmod b/src/main/resources/java-std-libs/java11/jdk.localedata.jmod new file mode 100644 index 0000000..338b571 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.localedata.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.management.agent.jmod b/src/main/resources/java-std-libs/java11/jdk.management.agent.jmod new file mode 100644 index 0000000..59b540c Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.management.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.management.jmod b/src/main/resources/java-std-libs/java11/jdk.management.jmod new file mode 100644 index 0000000..ebf9751 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.management.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.naming.dns.jmod b/src/main/resources/java-std-libs/java11/jdk.naming.dns.jmod new file mode 100644 index 0000000..d9ff5a5 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.naming.dns.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.naming.ldap.jmod b/src/main/resources/java-std-libs/java11/jdk.naming.ldap.jmod new file mode 100644 index 0000000..f6ccb18 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.naming.ldap.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.naming.rmi.jmod b/src/main/resources/java-std-libs/java11/jdk.naming.rmi.jmod new file mode 100644 index 0000000..80eccb2 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.naming.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.net.jmod b/src/main/resources/java-std-libs/java11/jdk.net.jmod new file mode 100644 index 0000000..a5f3370 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.net.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.pack.jmod b/src/main/resources/java-std-libs/java11/jdk.pack.jmod new file mode 100644 index 0000000..0f9ff7a Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.pack.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.rmic.jmod b/src/main/resources/java-std-libs/java11/jdk.rmic.jmod new file mode 100644 index 0000000..5f860d2 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.rmic.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.jmod b/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.jmod new file mode 100644 index 0000000..cbabc25 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.shell.jmod b/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.shell.jmod new file mode 100644 index 0000000..93f1c1f Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.scripting.nashorn.shell.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.sctp.jmod b/src/main/resources/java-std-libs/java11/jdk.sctp.jmod new file mode 100644 index 0000000..9e82e42 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.sctp.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.security.auth.jmod b/src/main/resources/java-std-libs/java11/jdk.security.auth.jmod new file mode 100644 index 0000000..de38e90 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.security.auth.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.security.jgss.jmod b/src/main/resources/java-std-libs/java11/jdk.security.jgss.jmod new file mode 100644 index 0000000..2a7f934 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.unsupported.desktop.jmod b/src/main/resources/java-std-libs/java11/jdk.unsupported.desktop.jmod new file mode 100644 index 0000000..6d355f3 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.unsupported.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.unsupported.jmod b/src/main/resources/java-std-libs/java11/jdk.unsupported.jmod new file mode 100644 index 0000000..197c6ce Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.unsupported.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.xml.dom.jmod b/src/main/resources/java-std-libs/java11/jdk.xml.dom.jmod new file mode 100644 index 0000000..48040af Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.xml.dom.jmod differ diff --git a/src/main/resources/java-std-libs/java11/jdk.zipfs.jmod b/src/main/resources/java-std-libs/java11/jdk.zipfs.jmod new file mode 100644 index 0000000..d0fd512 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/jdk.zipfs.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.cuda.jmod b/src/main/resources/java-std-libs/java11/openj9.cuda.jmod new file mode 100644 index 0000000..c5b4347 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.cuda.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.dataaccess.jmod b/src/main/resources/java-std-libs/java11/openj9.dataaccess.jmod new file mode 100644 index 0000000..4dc53b3 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.dataaccess.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.dtfj.jmod b/src/main/resources/java-std-libs/java11/openj9.dtfj.jmod new file mode 100644 index 0000000..97f2c4e Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.dtfj.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.dtfjview.jmod b/src/main/resources/java-std-libs/java11/openj9.dtfjview.jmod new file mode 100644 index 0000000..b2f5286 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.dtfjview.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.gpu.jmod b/src/main/resources/java-std-libs/java11/openj9.gpu.jmod new file mode 100644 index 0000000..66c33ba Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.gpu.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.jvm.jmod b/src/main/resources/java-std-libs/java11/openj9.jvm.jmod new file mode 100644 index 0000000..11915f8 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.jvm.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.sharedclasses.jmod b/src/main/resources/java-std-libs/java11/openj9.sharedclasses.jmod new file mode 100644 index 0000000..e7f2e93 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.sharedclasses.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.traceformat.jmod b/src/main/resources/java-std-libs/java11/openj9.traceformat.jmod new file mode 100644 index 0000000..463ac1c Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.traceformat.jmod differ diff --git a/src/main/resources/java-std-libs/java11/openj9.zosconditionhandling.jmod b/src/main/resources/java-std-libs/java11/openj9.zosconditionhandling.jmod new file mode 100644 index 0000000..78db4b1 Binary files /dev/null and b/src/main/resources/java-std-libs/java11/openj9.zosconditionhandling.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.base.jmod b/src/main/resources/java-std-libs/java17/java.base.jmod new file mode 100644 index 0000000..5b8d9a5 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.base.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.compiler.jmod b/src/main/resources/java-std-libs/java17/java.compiler.jmod new file mode 100644 index 0000000..d41cc2f Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.datatransfer.jmod b/src/main/resources/java-std-libs/java17/java.datatransfer.jmod new file mode 100644 index 0000000..5d8fc8d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.datatransfer.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.desktop.jmod b/src/main/resources/java-std-libs/java17/java.desktop.jmod new file mode 100644 index 0000000..0dd7dfa Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.instrument.jmod b/src/main/resources/java-std-libs/java17/java.instrument.jmod new file mode 100644 index 0000000..7f9fff8 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.instrument.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.logging.jmod b/src/main/resources/java-std-libs/java17/java.logging.jmod new file mode 100644 index 0000000..5979c1d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.logging.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.management.jmod b/src/main/resources/java-std-libs/java17/java.management.jmod new file mode 100644 index 0000000..f9410ef Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.management.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.management.rmi.jmod b/src/main/resources/java-std-libs/java17/java.management.rmi.jmod new file mode 100644 index 0000000..a0329e6 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.management.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.naming.jmod b/src/main/resources/java-std-libs/java17/java.naming.jmod new file mode 100644 index 0000000..289f553 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.naming.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.net.http.jmod b/src/main/resources/java-std-libs/java17/java.net.http.jmod new file mode 100644 index 0000000..9126fd7 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.net.http.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.prefs.jmod b/src/main/resources/java-std-libs/java17/java.prefs.jmod new file mode 100644 index 0000000..f667ac9 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.prefs.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.rmi.jmod b/src/main/resources/java-std-libs/java17/java.rmi.jmod new file mode 100644 index 0000000..68e19e0 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.scripting.jmod b/src/main/resources/java-std-libs/java17/java.scripting.jmod new file mode 100644 index 0000000..7fde76a Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.scripting.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.se.jmod b/src/main/resources/java-std-libs/java17/java.se.jmod new file mode 100644 index 0000000..b60b359 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.se.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.security.jgss.jmod b/src/main/resources/java-std-libs/java17/java.security.jgss.jmod new file mode 100644 index 0000000..c3b50c5 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.security.sasl.jmod b/src/main/resources/java-std-libs/java17/java.security.sasl.jmod new file mode 100644 index 0000000..49f5404 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.security.sasl.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.smartcardio.jmod b/src/main/resources/java-std-libs/java17/java.smartcardio.jmod new file mode 100644 index 0000000..3ac5ef2 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.smartcardio.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.sql.jmod b/src/main/resources/java-std-libs/java17/java.sql.jmod new file mode 100644 index 0000000..6edfbe8 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.sql.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.sql.rowset.jmod b/src/main/resources/java-std-libs/java17/java.sql.rowset.jmod new file mode 100644 index 0000000..ec42e9e Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.sql.rowset.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.transaction.xa.jmod b/src/main/resources/java-std-libs/java17/java.transaction.xa.jmod new file mode 100644 index 0000000..e98444d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.transaction.xa.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.xml.crypto.jmod b/src/main/resources/java-std-libs/java17/java.xml.crypto.jmod new file mode 100644 index 0000000..dbba9f8 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.xml.crypto.jmod differ diff --git a/src/main/resources/java-std-libs/java17/java.xml.jmod b/src/main/resources/java-std-libs/java17/java.xml.jmod new file mode 100644 index 0000000..1bd7cda Binary files /dev/null and b/src/main/resources/java-std-libs/java17/java.xml.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.accessibility.jmod b/src/main/resources/java-std-libs/java17/jdk.accessibility.jmod new file mode 100644 index 0000000..dbc7063 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.accessibility.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.attach.jmod b/src/main/resources/java-std-libs/java17/jdk.attach.jmod new file mode 100644 index 0000000..1a8483b Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.attach.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.charsets.jmod b/src/main/resources/java-std-libs/java17/jdk.charsets.jmod new file mode 100644 index 0000000..bb9caff Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.charsets.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.compiler.jmod b/src/main/resources/java-std-libs/java17/jdk.compiler.jmod new file mode 100644 index 0000000..803feb2 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.crypto.cryptoki.jmod b/src/main/resources/java-std-libs/java17/jdk.crypto.cryptoki.jmod new file mode 100644 index 0000000..b4c9091 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.crypto.cryptoki.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.crypto.ec.jmod b/src/main/resources/java-std-libs/java17/jdk.crypto.ec.jmod new file mode 100644 index 0000000..de727a5 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.crypto.ec.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.dynalink.jmod b/src/main/resources/java-std-libs/java17/jdk.dynalink.jmod new file mode 100644 index 0000000..2d7dc3a Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.dynalink.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.editpad.jmod b/src/main/resources/java-std-libs/java17/jdk.editpad.jmod new file mode 100644 index 0000000..cfb71ab Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.editpad.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.hotspot.agent.jmod b/src/main/resources/java-std-libs/java17/jdk.hotspot.agent.jmod new file mode 100644 index 0000000..d7f3bb3 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.hotspot.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.httpserver.jmod b/src/main/resources/java-std-libs/java17/jdk.httpserver.jmod new file mode 100644 index 0000000..76bade7 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.httpserver.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.incubator.foreign.jmod b/src/main/resources/java-std-libs/java17/jdk.incubator.foreign.jmod new file mode 100644 index 0000000..c81caae Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.incubator.foreign.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.incubator.vector.jmod b/src/main/resources/java-std-libs/java17/jdk.incubator.vector.jmod new file mode 100644 index 0000000..598bd52 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.incubator.vector.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.ed.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.ed.jmod new file mode 100644 index 0000000..53da525 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.ed.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.jvmstat.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.jvmstat.jmod new file mode 100644 index 0000000..47bcfc3 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.jvmstat.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.le.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.le.jmod new file mode 100644 index 0000000..d7675c1 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.le.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.opt.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.opt.jmod new file mode 100644 index 0000000..e7de43d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.opt.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.vm.ci.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.vm.ci.jmod new file mode 100644 index 0000000..34ec234 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.vm.ci.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.jmod new file mode 100644 index 0000000..a1737e6 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.management.jmod b/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.management.jmod new file mode 100644 index 0000000..4cac96a Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.internal.vm.compiler.management.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jartool.jmod b/src/main/resources/java-std-libs/java17/jdk.jartool.jmod new file mode 100644 index 0000000..24535c5 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jartool.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.javadoc.jmod b/src/main/resources/java-std-libs/java17/jdk.javadoc.jmod new file mode 100644 index 0000000..a64c986 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.javadoc.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jcmd.jmod b/src/main/resources/java-std-libs/java17/jdk.jcmd.jmod new file mode 100644 index 0000000..a7dfa2d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jcmd.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jconsole.jmod b/src/main/resources/java-std-libs/java17/jdk.jconsole.jmod new file mode 100644 index 0000000..4127720 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jconsole.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jdeps.jmod b/src/main/resources/java-std-libs/java17/jdk.jdeps.jmod new file mode 100644 index 0000000..4cf6bab Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jdeps.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jdi.jmod b/src/main/resources/java-std-libs/java17/jdk.jdi.jmod new file mode 100644 index 0000000..52c168a Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jdi.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jdwp.agent.jmod b/src/main/resources/java-std-libs/java17/jdk.jdwp.agent.jmod new file mode 100644 index 0000000..cb7c46f Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jdwp.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jfr.jmod b/src/main/resources/java-std-libs/java17/jdk.jfr.jmod new file mode 100644 index 0000000..152a853 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jfr.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jlink.jmod b/src/main/resources/java-std-libs/java17/jdk.jlink.jmod new file mode 100644 index 0000000..8a2eb8b Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jlink.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jpackage.jmod b/src/main/resources/java-std-libs/java17/jdk.jpackage.jmod new file mode 100644 index 0000000..60a4caa Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jpackage.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jshell.jmod b/src/main/resources/java-std-libs/java17/jdk.jshell.jmod new file mode 100644 index 0000000..b71bd77 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jshell.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jsobject.jmod b/src/main/resources/java-std-libs/java17/jdk.jsobject.jmod new file mode 100644 index 0000000..fbad11a Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jsobject.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.jstatd.jmod b/src/main/resources/java-std-libs/java17/jdk.jstatd.jmod new file mode 100644 index 0000000..8f9b983 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.jstatd.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.localedata.jmod b/src/main/resources/java-std-libs/java17/jdk.localedata.jmod new file mode 100644 index 0000000..74038c2 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.localedata.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.management.agent.jmod b/src/main/resources/java-std-libs/java17/jdk.management.agent.jmod new file mode 100644 index 0000000..8e672a6 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.management.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.management.jfr.jmod b/src/main/resources/java-std-libs/java17/jdk.management.jfr.jmod new file mode 100644 index 0000000..df4e75f Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.management.jfr.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.management.jmod b/src/main/resources/java-std-libs/java17/jdk.management.jmod new file mode 100644 index 0000000..4c37061 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.management.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.naming.dns.jmod b/src/main/resources/java-std-libs/java17/jdk.naming.dns.jmod new file mode 100644 index 0000000..9c95870 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.naming.dns.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.naming.rmi.jmod b/src/main/resources/java-std-libs/java17/jdk.naming.rmi.jmod new file mode 100644 index 0000000..201bc09 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.naming.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.net.jmod b/src/main/resources/java-std-libs/java17/jdk.net.jmod new file mode 100644 index 0000000..d0b79d0 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.net.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.nio.mapmode.jmod b/src/main/resources/java-std-libs/java17/jdk.nio.mapmode.jmod new file mode 100644 index 0000000..cdbbbd8 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.nio.mapmode.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.random.jmod b/src/main/resources/java-std-libs/java17/jdk.random.jmod new file mode 100644 index 0000000..c948e36 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.random.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.sctp.jmod b/src/main/resources/java-std-libs/java17/jdk.sctp.jmod new file mode 100644 index 0000000..d39d7cb Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.sctp.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.security.auth.jmod b/src/main/resources/java-std-libs/java17/jdk.security.auth.jmod new file mode 100644 index 0000000..0dbf42d Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.security.auth.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.security.jgss.jmod b/src/main/resources/java-std-libs/java17/jdk.security.jgss.jmod new file mode 100644 index 0000000..f976084 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.unsupported.desktop.jmod b/src/main/resources/java-std-libs/java17/jdk.unsupported.desktop.jmod new file mode 100644 index 0000000..5fd2070 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.unsupported.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.unsupported.jmod b/src/main/resources/java-std-libs/java17/jdk.unsupported.jmod new file mode 100644 index 0000000..799e0f2 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.unsupported.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.xml.dom.jmod b/src/main/resources/java-std-libs/java17/jdk.xml.dom.jmod new file mode 100644 index 0000000..4c425d7 Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.xml.dom.jmod differ diff --git a/src/main/resources/java-std-libs/java17/jdk.zipfs.jmod b/src/main/resources/java-std-libs/java17/jdk.zipfs.jmod new file mode 100644 index 0000000..06dbdfb Binary files /dev/null and b/src/main/resources/java-std-libs/java17/jdk.zipfs.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.base.jmod b/src/main/resources/java-std-libs/java21/java.base.jmod new file mode 100644 index 0000000..a3b2a58 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.base.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.compiler.jmod b/src/main/resources/java-std-libs/java21/java.compiler.jmod new file mode 100644 index 0000000..87f43cb Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.datatransfer.jmod b/src/main/resources/java-std-libs/java21/java.datatransfer.jmod new file mode 100644 index 0000000..1a3349e Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.datatransfer.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.desktop.jmod b/src/main/resources/java-std-libs/java21/java.desktop.jmod new file mode 100644 index 0000000..b69e4f7 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.instrument.jmod b/src/main/resources/java-std-libs/java21/java.instrument.jmod new file mode 100644 index 0000000..4f9cc92 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.instrument.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.logging.jmod b/src/main/resources/java-std-libs/java21/java.logging.jmod new file mode 100644 index 0000000..54c536b Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.logging.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.management.jmod b/src/main/resources/java-std-libs/java21/java.management.jmod new file mode 100644 index 0000000..99fa532 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.management.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.management.rmi.jmod b/src/main/resources/java-std-libs/java21/java.management.rmi.jmod new file mode 100644 index 0000000..af4e196 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.management.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.naming.jmod b/src/main/resources/java-std-libs/java21/java.naming.jmod new file mode 100644 index 0000000..b872886 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.naming.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.net.http.jmod b/src/main/resources/java-std-libs/java21/java.net.http.jmod new file mode 100644 index 0000000..84b9e6a Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.net.http.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.prefs.jmod b/src/main/resources/java-std-libs/java21/java.prefs.jmod new file mode 100644 index 0000000..de71f63 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.prefs.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.rmi.jmod b/src/main/resources/java-std-libs/java21/java.rmi.jmod new file mode 100644 index 0000000..ad67c3f Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.scripting.jmod b/src/main/resources/java-std-libs/java21/java.scripting.jmod new file mode 100644 index 0000000..d3a1bfb Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.scripting.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.se.jmod b/src/main/resources/java-std-libs/java21/java.se.jmod new file mode 100644 index 0000000..e570a28 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.se.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.security.jgss.jmod b/src/main/resources/java-std-libs/java21/java.security.jgss.jmod new file mode 100644 index 0000000..0025219 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.security.sasl.jmod b/src/main/resources/java-std-libs/java21/java.security.sasl.jmod new file mode 100644 index 0000000..1d3002b Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.security.sasl.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.smartcardio.jmod b/src/main/resources/java-std-libs/java21/java.smartcardio.jmod new file mode 100644 index 0000000..b7dc61f Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.smartcardio.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.sql.jmod b/src/main/resources/java-std-libs/java21/java.sql.jmod new file mode 100644 index 0000000..11b02fd Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.sql.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.sql.rowset.jmod b/src/main/resources/java-std-libs/java21/java.sql.rowset.jmod new file mode 100644 index 0000000..8a314aa Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.sql.rowset.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.transaction.xa.jmod b/src/main/resources/java-std-libs/java21/java.transaction.xa.jmod new file mode 100644 index 0000000..97cea22 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.transaction.xa.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.xml.crypto.jmod b/src/main/resources/java-std-libs/java21/java.xml.crypto.jmod new file mode 100644 index 0000000..b0b7a38 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.xml.crypto.jmod differ diff --git a/src/main/resources/java-std-libs/java21/java.xml.jmod b/src/main/resources/java-std-libs/java21/java.xml.jmod new file mode 100644 index 0000000..7f82e08 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/java.xml.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.accessibility.jmod b/src/main/resources/java-std-libs/java21/jdk.accessibility.jmod new file mode 100644 index 0000000..daa31ad Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.accessibility.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.attach.jmod b/src/main/resources/java-std-libs/java21/jdk.attach.jmod new file mode 100644 index 0000000..9b31c93 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.attach.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.charsets.jmod b/src/main/resources/java-std-libs/java21/jdk.charsets.jmod new file mode 100644 index 0000000..d8f2dc9 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.charsets.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.compiler.jmod b/src/main/resources/java-std-libs/java21/jdk.compiler.jmod new file mode 100644 index 0000000..226cc14 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.crypto.cryptoki.jmod b/src/main/resources/java-std-libs/java21/jdk.crypto.cryptoki.jmod new file mode 100644 index 0000000..fd37789 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.crypto.cryptoki.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.crypto.ec.jmod b/src/main/resources/java-std-libs/java21/jdk.crypto.ec.jmod new file mode 100644 index 0000000..e15557c Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.crypto.ec.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.dynalink.jmod b/src/main/resources/java-std-libs/java21/jdk.dynalink.jmod new file mode 100644 index 0000000..127cb6e Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.dynalink.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.editpad.jmod b/src/main/resources/java-std-libs/java21/jdk.editpad.jmod new file mode 100644 index 0000000..f63d351 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.editpad.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.hotspot.agent.jmod b/src/main/resources/java-std-libs/java21/jdk.hotspot.agent.jmod new file mode 100644 index 0000000..f395c53 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.hotspot.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.httpserver.jmod b/src/main/resources/java-std-libs/java21/jdk.httpserver.jmod new file mode 100644 index 0000000..f5aa4dc Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.httpserver.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.incubator.vector.jmod b/src/main/resources/java-std-libs/java21/jdk.incubator.vector.jmod new file mode 100644 index 0000000..af53e64 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.incubator.vector.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.ed.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.ed.jmod new file mode 100644 index 0000000..cf0f75d Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.ed.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.jvmstat.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.jvmstat.jmod new file mode 100644 index 0000000..c146652 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.jvmstat.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.le.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.le.jmod new file mode 100644 index 0000000..4aa6aa3 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.le.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.opt.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.opt.jmod new file mode 100644 index 0000000..4e08318 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.opt.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.vm.ci.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.vm.ci.jmod new file mode 100644 index 0000000..081f424 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.vm.ci.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.jmod new file mode 100644 index 0000000..d94a877 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.management.jmod b/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.management.jmod new file mode 100644 index 0000000..66c5fbc Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.internal.vm.compiler.management.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jartool.jmod b/src/main/resources/java-std-libs/java21/jdk.jartool.jmod new file mode 100644 index 0000000..f3ab8f3 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jartool.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.javadoc.jmod b/src/main/resources/java-std-libs/java21/jdk.javadoc.jmod new file mode 100644 index 0000000..ff58396 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.javadoc.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jcmd.jmod b/src/main/resources/java-std-libs/java21/jdk.jcmd.jmod new file mode 100644 index 0000000..0936eeb Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jcmd.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jconsole.jmod b/src/main/resources/java-std-libs/java21/jdk.jconsole.jmod new file mode 100644 index 0000000..940dfd0 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jconsole.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jdeps.jmod b/src/main/resources/java-std-libs/java21/jdk.jdeps.jmod new file mode 100644 index 0000000..758c7c8 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jdeps.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jdi.jmod b/src/main/resources/java-std-libs/java21/jdk.jdi.jmod new file mode 100644 index 0000000..64fd5a4 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jdi.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jdwp.agent.jmod b/src/main/resources/java-std-libs/java21/jdk.jdwp.agent.jmod new file mode 100644 index 0000000..07cd75b Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jdwp.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jfr.jmod b/src/main/resources/java-std-libs/java21/jdk.jfr.jmod new file mode 100644 index 0000000..d09a702 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jfr.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jlink.jmod b/src/main/resources/java-std-libs/java21/jdk.jlink.jmod new file mode 100644 index 0000000..2de2127 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jlink.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jpackage.jmod b/src/main/resources/java-std-libs/java21/jdk.jpackage.jmod new file mode 100644 index 0000000..c81f77a Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jpackage.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jshell.jmod b/src/main/resources/java-std-libs/java21/jdk.jshell.jmod new file mode 100644 index 0000000..82a6d15 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jshell.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jsobject.jmod b/src/main/resources/java-std-libs/java21/jdk.jsobject.jmod new file mode 100644 index 0000000..cc37288 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jsobject.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.jstatd.jmod b/src/main/resources/java-std-libs/java21/jdk.jstatd.jmod new file mode 100644 index 0000000..268710c Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.jstatd.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.localedata.jmod b/src/main/resources/java-std-libs/java21/jdk.localedata.jmod new file mode 100644 index 0000000..d98a90b Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.localedata.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.management.agent.jmod b/src/main/resources/java-std-libs/java21/jdk.management.agent.jmod new file mode 100644 index 0000000..a8daf79 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.management.agent.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.management.jfr.jmod b/src/main/resources/java-std-libs/java21/jdk.management.jfr.jmod new file mode 100644 index 0000000..95707b9 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.management.jfr.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.management.jmod b/src/main/resources/java-std-libs/java21/jdk.management.jmod new file mode 100644 index 0000000..a842323 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.management.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.naming.dns.jmod b/src/main/resources/java-std-libs/java21/jdk.naming.dns.jmod new file mode 100644 index 0000000..0c0b619 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.naming.dns.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.naming.rmi.jmod b/src/main/resources/java-std-libs/java21/jdk.naming.rmi.jmod new file mode 100644 index 0000000..9bb81bf Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.naming.rmi.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.net.jmod b/src/main/resources/java-std-libs/java21/jdk.net.jmod new file mode 100644 index 0000000..12d0512 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.net.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.nio.mapmode.jmod b/src/main/resources/java-std-libs/java21/jdk.nio.mapmode.jmod new file mode 100644 index 0000000..85d9dbc Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.nio.mapmode.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.random.jmod b/src/main/resources/java-std-libs/java21/jdk.random.jmod new file mode 100644 index 0000000..a11eec4 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.random.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.sctp.jmod b/src/main/resources/java-std-libs/java21/jdk.sctp.jmod new file mode 100644 index 0000000..f074c57 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.sctp.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.security.auth.jmod b/src/main/resources/java-std-libs/java21/jdk.security.auth.jmod new file mode 100644 index 0000000..c354b7f Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.security.auth.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.security.jgss.jmod b/src/main/resources/java-std-libs/java21/jdk.security.jgss.jmod new file mode 100644 index 0000000..58e4d88 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.security.jgss.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.unsupported.desktop.jmod b/src/main/resources/java-std-libs/java21/jdk.unsupported.desktop.jmod new file mode 100644 index 0000000..304e009 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.unsupported.desktop.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.unsupported.jmod b/src/main/resources/java-std-libs/java21/jdk.unsupported.jmod new file mode 100644 index 0000000..49caae3 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.unsupported.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.xml.dom.jmod b/src/main/resources/java-std-libs/java21/jdk.xml.dom.jmod new file mode 100644 index 0000000..7081a1c Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.xml.dom.jmod differ diff --git a/src/main/resources/java-std-libs/java21/jdk.zipfs.jmod b/src/main/resources/java-std-libs/java21/jdk.zipfs.jmod new file mode 100644 index 0000000..aba56b5 Binary files /dev/null and b/src/main/resources/java-std-libs/java21/jdk.zipfs.jmod differ diff --git a/src/main/resources/java-std-libs/javaee/get_libs.sh b/src/main/resources/java-std-libs/javaee/get_libs.sh new file mode 100755 index 0000000..203c5bb --- /dev/null +++ b/src/main/resources/java-std-libs/javaee/get_libs.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Download Java EE libraries +JPA_VERSION=2.2 +JTA_VERSION=1.3 +JAVAEE7_VERSION=7.0 +JAVAEE8_VERSION=8.0 +JAX_RS_VERSION=2.1.6 +JSON_P_VERSION=1.1.4 +WEBSOCKET_VERSION=1.1 +SERVLET_VERSION=4.0.1 +JAVAMAIL_VERSION=1.5.7 +DERBY_VERSION=10.16.2.1 +SPRING_BOOT_VERSION=2.7.3 +VALIDATION_API_VERSION=2.0.1.Final + +echo "Downloading JAX-RS libraries..." +wget https://repo1.maven.org/maven2/javax/ws/rs/javax.ws.rs-api/${JAX_RS_VERSION}/javax.ws.rs-api-${JAX_RS_VERSION}.jar + +echo "Downloading JSON-P libraries..." +wget https://repo1.maven.org/maven2/javax/json/javax.json-api/${JSON_P_VERSION}/javax.json-api-${JSON_P_VERSION}.jar + +echo "Downloading Java WebSocket libraries..." +wget https://repo1.maven.org/maven2/javax/websocket/javax.websocket-api/${WEBSOCKET_VERSION}/javax.websocket-api-${WEBSOCKET_VERSION}.jar + +echo "Downloading JavaMail libraries..." +wget https://repo1.maven.org/maven2/com/sun/mail/javax.mail/${JAVAMAIL_VERSION}/javax.mail-${JAVAMAIL_VERSION}.jar + +echo "Downloading Bean Validation API libraries..." +wget https://repo1.maven.org/maven2/javax/validation/validation-api/${VALIDATION_API_VERSION}/validation-api-${VALIDATION_API_VERSION}.jar + +echo "Downloading Java Persistence API (JPA) libraries..." +wget https://repo1.maven.org/maven2/javax/persistence/javax.persistence-api/${JPA_VERSION}/javax.persistence-api-${JPA_VERSION}.jar + +echo "Downloading Java Transaction API (JTA) libraries..." +wget https://repo1.maven.org/maven2/javax/transaction/javax.transaction-api/${JTA_VERSION}/javax.transaction-api-${JTA_VERSION}.jar + +echo "Downloading Servlet API libraries..." +wget https://repo1.maven.org/maven2/javax/servlet/jstl/${SERVLET_VERSION}/jstl-${SERVLET_VERSION}.jar + +echo "Downloading Java EE API (version 7.0) libraries..." +wget https://repo1.maven.org/maven2/javax/javaee-api/${JAVAEE7_VERSION}/javaee-api-${JAVAEE7_VERSION}.jar + +echo "Downloading Java EE API (version 8.0) libraries..." +wget https://repo1.maven.org/maven2/javax/javaee-api/${JAVAEE8_VERSION}/javaee-api-${JAVAEE8_VERSION}.jar + +echo "Downloading Spring Boot libraries..." +wget https://repo1.maven.org/maven2/org/springframework/boot/${SPRING_BOOT_VERSION}/spring-boot-${SPRING_BOOT_VERSION}.jar + +echo "Downloading Apache Derby libraries..." +wget https://repo1.maven.org/maven2/org/apache/derby/${DERBY_VERSION}/derby-${DERBY_VERSION}.jar diff --git a/src/test/java/com/ibm/northstar/CodeAnalyzerTest.java b/src/test/java/com/ibm/northstar/CodeAnalyzerTest.java new file mode 100644 index 0000000..c4ec4e6 --- /dev/null +++ b/src/test/java/com/ibm/northstar/CodeAnalyzerTest.java @@ -0,0 +1,26 @@ +package com.ibm.northstar; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CodeAnalyzerTest { + + @BeforeEach + void setUp() { + } + + @AfterEach + void tearDown() { + } + + @Test + void main() { + } + + @Test + void run() { + } +} \ No newline at end of file