From 15ef7db990cd92de2d005a397b61c60188c7f0ef Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Fri, 17 Apr 2026 17:48:22 +0300 Subject: [PATCH 1/1] Initial commit --- .gitignore | 14 + AGENTS.md | 235 +++++ COPYING | 121 +++ TODO.org | 139 +++ Tools/Open with IntelliJ IDEA | 18 + Tools/Update web site | 127 +++ commandline launcher/install | 25 + commandline launcher/javainspect | 7 + doc/JavaInspect full project.png | Bin 0 -> 111609 bytes doc/JavaInspect.dot | 316 +++++++ doc/JavaInspect.png | Bin 0 -> 99339 bytes doc/example-thumbnail.png | Bin 0 -> 22858 bytes doc/example.png | Bin 0 -> 29812 bytes doc/index.org | 237 +++++ doc/legend.png | Bin 0 -> 18350 bytes doc/usage cli.org | 111 +++ pom.xml | 160 ++++ .../inspector/java/RenderJavaInspect.java | 67 ++ .../commandline/CommandlineConfiguration.java | 196 ++++ .../inspector/java/commandline/Main.java | 262 ++++++ .../commandline/TargetImageTypeParameter.java | 84 ++ .../java/commandline/package-info.java | 15 + .../java/structure/ClassDescriptor.java | 836 ++++++++++++++++++ .../inspector/java/structure/ClassGraph.java | 333 +++++++ .../java/structure/FieldDescriptor.java | 249 ++++++ .../java/structure/GraphElement.java | 59 ++ .../java/structure/MethodDescriptor.java | 319 +++++++ .../java/structure/TargetImageType.java | 48 + .../inspector/java/structure/Utils.java | 251 ++++++ .../java/structure/package-info.java | 18 + usage examples/demo project/.gitignore | 4 + usage examples/demo project/pom.xml | 40 + .../example/RenderUsingReflection.java | 27 + .../torender/ObjectReturnedByMethod.java | 5 + .../torender/ObjectVisibleAsClassField.java | 5 + .../example/torender/SampleClass.java | 11 + .../example/torender/SampleClass2.java | 5 + .../example/torender/SampleEnum.java | 7 + .../example/torender/SampleInterface.java | 5 + .../example/torender/SampleSuperClass.java | 10 + .../tools/open with IntelliJ IDEA | 6 + 41 files changed, 4372 insertions(+) create mode 100755 .gitignore create mode 100644 AGENTS.md create mode 100644 COPYING create mode 100644 TODO.org create mode 100755 Tools/Open with IntelliJ IDEA create mode 100755 Tools/Update web site create mode 100755 commandline launcher/install create mode 100755 commandline launcher/javainspect create mode 100644 doc/JavaInspect full project.png create mode 100644 doc/JavaInspect.dot create mode 100644 doc/JavaInspect.png create mode 100644 doc/example-thumbnail.png create mode 100644 doc/example.png create mode 100644 doc/index.org create mode 100644 doc/legend.png create mode 100644 doc/usage cli.org create mode 100644 pom.xml create mode 100755 src/main/java/eu/svjatoslav/inspector/java/RenderJavaInspect.java create mode 100644 src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java create mode 100644 src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java create mode 100644 src/main/java/eu/svjatoslav/inspector/java/commandline/TargetImageTypeParameter.java create mode 100644 src/main/java/eu/svjatoslav/inspector/java/commandline/package-info.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java create mode 100644 src/main/java/eu/svjatoslav/inspector/java/structure/TargetImageType.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java create mode 100755 src/main/java/eu/svjatoslav/inspector/java/structure/package-info.java create mode 100644 usage examples/demo project/.gitignore create mode 100644 usage examples/demo project/pom.xml create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/RenderUsingReflection.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectReturnedByMethod.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectVisibleAsClassField.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass.java create mode 100644 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass2.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleEnum.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleInterface.java create mode 100755 usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleSuperClass.java create mode 100755 usage examples/demo project/tools/open with IntelliJ IDEA diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..0809663 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +/.settings/ +/.project +/.classpath +/target/ +/.idea/ +dependency-reduced-pom.xml +/example/target +/*.iml +/JavaInspect.dot +/JavaInspect.svg +/doc/index.html +/doc/usage\ cli.html +/doc/graphs/ +/doc/apidocs/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..93ead91 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,235 @@ +# JavaInspect - Quick Reference + +Utility to visualize Java software structure through reflection and GraphViz. + +--- + +# Quick Lookup: "I Want To..." + +| Task | Class (path) | Key Method | +|--------------------------------|--------------------------------------------|---------------------------------------------| +| **Create a graph** | `ClassGraph` (`structure/ClassGraph.java`) | `new ClassGraph()` | +| **Add classes to graph** | `ClassGraph` | `.add(object)` or `.add(Class)` | +| **Generate visualization** | `ClassGraph` | `.generateGraph("name")` → produces SVG/PNG | +| **Set output directory** | `ClassGraph` | `.setTargetDirectory(new File(path))` | +| **Keep DOT file** | `ClassGraph` | `.setKeepDotFile(true)` | +| **Filter classes (blacklist)** | `ClassGraph` | `.blacklistClassGlob("java.*")` | +| **Filter classes (whitelist)** | `ClassGraph` | `.whitelistClassGlob("com.myapp.*")` | +| **Hide orphaned classes** | `ClassGraph` | `.hideOrphanedClasses()` | +| **Set output format** | `ClassGraph` | `.setTargetImageType(TargetImageType.SVG)` | +| **Run from command line** | `Main` (`commandline/Main.java`) | `java -jar javainspect.jar -j myapp.jar` | + +--- + +# Code Examples + +## Basic Usage + +```java +import eu.svjatoslav.inspector.java.structure.ClassGraph; + +// Simple one-liner +new ClassGraph().add(myObject, MyClass.class).generateGraph("MyGraph"); + +// With configuration +ClassGraph graph = new ClassGraph(); +graph.add(myObject); // Add object (class detected automatically) +graph.add(MyClass.class); // Add class directly +graph.setKeepDotFile(true); // Keep intermediate DOT file +graph.setTargetDirectory(new File("/tmp")); +graph.generateGraph("MyApp"); // Generates MyApp.svg +``` + +## Filtering with Glob Patterns + +```java +ClassGraph graph = new ClassGraph(); +graph.add(myApp); + +// Hide standard library classes +graph.blacklistClassGlob("java.*"); +graph.blacklistClassGlob("javax.*"); + +// Only show my package +graph.whitelistClassGlob("com.mycompany.*"); + +// Hide test classes +graph.blacklistClassGlob("*Test"); + +// Hide classes with no connections +graph.hideOrphanedClasses(); + +graph.generateGraph("filtered"); +``` + +## Analyzing JAR Files from Command Line + +```bash +# Basic usage +javainspect -j myapp.jar -n MyAppGraph + +# Multiple JARs with classpath +javainspect -j app.jar -j lib.jar -c /path/to/classes -n Combined + +# With filters +javainspect -j myapp.jar -n graph \ + -b "java.*" -b "*Test" \ + -w "com.mycompany.*" \ + -ho # hide orphaned classes + +# Specify output format and directory +javainspect -j myapp.jar -n graph -t png -d /tmp/graphs + +# Keep DOT file for debugging +javainspect -j myapp.jar -n graph -k + +# Debug mode +javainspect -j myapp.jar -n graph --debug +``` + +## Maven Integration + +```xml + + eu.svjatoslav + javainspect + 1.8 + + + + svjatoslav.eu + https://www3.svjatoslav.eu/maven/ + +``` + +--- + +# Class Catalog + +## Core Structure (`structure/`) + +| Class | File | Purpose | Key Methods | +|--------------------|-------------------------|---------------------------------------|----------------------------------------------------------------------------------------------------------| +| `ClassGraph` | `ClassGraph.java` | Main entry point, graph container | `.add()`, `.generateGraph()`, `.blacklistClassGlob()`, `.whitelistClassGlob()`, `.hideOrphanedClasses()` | +| `ClassDescriptor` | `ClassDescriptor.java` | Represents a single class node | `.getDot()`, `.getGraphId()`, `.isVisible()`, `.analyzeClass()` | +| `FieldDescriptor` | `FieldDescriptor.java` | Represents a field within a class | `.getDot()`, `.getEmbeddedDot()`, `.analyzeField()` | +| `MethodDescriptor` | `MethodDescriptor.java` | Represents a method within a class | `.getDot()`, `.getEmbeddedDot()`, `.analyze()` | +| `GraphElement` | `GraphElement.java` | Interface for DOT-renderable elements | `.getDot()`, `.getEmbeddedDot()`, `.getGraphId()`, `.isVisible()` | +| `Utils` | `Utils.java` | Filtering helpers, color palettes | `.isSystemDataType()`, `.isSystemPackage()`, `.isCommonObjectMethod()`, `.getNextDarkColor()` | +| `TargetImageType` | `TargetImageType.java` | Output format enum | `SVG`, `PNG` (field: `.fileExtension`) | + +## Command Line (`commandline/`) + +| Class | File | Purpose | +|----------------------------|---------------------------------|----------------------------------------| +| `Main` | `Main.java` | CLI entry point, JAR processing | +| `CommandlineConfiguration` | `CommandlineConfiguration.java` | Argument parsing, option storage | +| `TargetImageTypeParameter` | `TargetImageTypeParameter.java` | Custom parameter type for image format | + +--- + +# Architecture + +## Graph Building Pipeline + +``` +ClassGraph.add(object/class) + → getOrCreateClassDescriptor(clazz) + → ClassDescriptor.analyzeClass(clazz) + → indexFields() → FieldDescriptor.analyzeField() + → indexMethods() → MethodDescriptor.analyze() + → getOrCreateClassDescriptor(superClass, interfaces) + → (recursive for all referenced types) + +ClassGraph.generateGraph(name) + → getDot() → iterate all ClassDescriptor.getDot() + → write DOT file + → execute GraphViz (dot -Tsvg) + → optionally delete DOT file +``` + +## Visibility Filtering + +Classes are hidden based on: + +1. **System data types**: `void`, `int`, `long`, `boolean`, etc. +2. **System packages**: `java.*`, `javax.*`, `sun.*` +3. **Glob blacklist**: classes matching any blacklist pattern +4. **Glob whitelist**: if defined, only classes matching whitelist shown +5. **Orphan check**: classes with zero incoming/outgoing references + +## DOT Output Structure + +Each visible class generates: + +1. **Node**: HTML-like table with: + - Package name (small font) + - Class name (large font) + - Fields (type + name rows) + - Methods (return type + name rows, red color) + +2. **Edges**: + - Field → type references (solid arrows) + - Method → return type references (dotted arrows) + - Interface → implementation (dotted forward arrows) + - Superclass → subclass (thick forward arrows) + +--- + +# Build & Test + +```bash +# Build +mvn clean package + +# Run tests +mvn test + +# Generate Javadoc +mvn javadoc:javadoc + +# Run self-visualization demo +mvn exec:java -Dexec.mainClass="eu.svjatoslav.inspector.java.RenderJavaInspect" +``` + +--- + +# Command Line Options + +| Option | Aliases | Description | +|---------------|----------------|-------------------------------------| +| JAR files | `-j` | JAR file(s) to analyze | +| Classpath | `-c` | Additional classpath directories | +| Graph name | `-n` | Output file name (default: "graph") | +| Image type | `-t` | svg or png (default: svg) | +| Target dir | `-d` | Output directory (default: current) | +| Keep DOT | `-k` | Keep intermediate DOT file | +| Hide orphaned | `-ho` | Hide classes with no connections | +| Whitelist | `-w` | Glob patterns to include | +| Blacklist | `-b` | Glob patterns to exclude | +| Root classes | `-r` | Specific classes to start from | +| Debug | `--debug` | Show processing details | +| Help | `-h`, `--help` | Show usage | + +--- + +# Tips for AI Agents + +1. **ClassGraph is the entry point**: Always start with `new ClassGraph()` +2. **Method chaining**: `ClassGraph` methods return `this` for chaining +3. **Glob patterns**: Use `*` for any sequence, `?` for single char +4. **Reflection-based**: Classes must be loadable in JVM (classpath required) +5. **GraphViz required**: `dot` binary must be on system PATH +6. **SVG recommended**: Better for large graphs, PNG for small ones +7. **Filter early**: Large applications produce huge graphs - use blacklist/whitelist +8. **Hide orphaned**: Reduces visual noise from disconnected utility classes + +--- + +# Documentation + +| Path | Topic | +|-----------------|-------------------------------------------------------| +| `doc/index.org` | Main documentation, usage examples, Maven integration | +| `doc/apidocs/` | Generated Javadoc | +| `COPYING` | CC0 license full text | \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/TODO.org b/TODO.org new file mode 100644 index 0000000..3606460 --- /dev/null +++ b/TODO.org @@ -0,0 +1,139 @@ +* Bugs +:PROPERTIES: +:CUSTOM_ID: bugs +:END: + +** Reference counting should exclude non-visible classes +:PROPERTIES: +:CUSTOM_ID: ref-count-exclude-nonvisible +:END: +Should not hide references if there are too many of them to classes if +referring classes are not visible anyway because of blacklist/whitelist +rules. Basically reference counting should exclude not visible classes. + +** Orphaned class removal does not work always +:PROPERTIES: +:CUSTOM_ID: orphaned-removal-bugs +:END: +There are many bugs and corner cases to find and fix still. + +** Code readability needs improvement +:PROPERTIES: +:CUSTOM_ID: code-readability +:END: +Document and refactor for better maintainability. + +* Packaging +:PROPERTIES: +:CUSTOM_ID: packaging +:END: + +** Create installable DEB package +:PROPERTIES: +:CUSTOM_ID: create-deb-package +:END: +Submit it to some Debian developer for integration or become Debian +package maintainer. + +* Architecture +:PROPERTIES: +:CUSTOM_ID: architecture +:END: + +** Make modular with central application model +:PROPERTIES: +:CUSTOM_ID: modular-architecture +:END: +Central part, an application model could be standalone and serializable. + +Multiple ways to acquire model: ++ By introspecting application via Java reflections (current mode) ++ By parsing java source (unfinished) + +Multiple ways to manipulate model: ++ Store/load/compare ++ Trim uninteresting parts ++ Highlight important parts + +Multiple ways to render model: ++ PNG/SVG (currently implemented) ++ PlantUML (TODO) ++ Interactive 3D visualization (TODO) + +* Features +:PROPERTIES: +:CUSTOM_ID: features +:END: + +** Implement Java source parser +:PROPERTIES: +:CUSTOM_ID: java-source-parser +:END: +Implement (or integrate existing java parser +https://javaparser.org/) to be able to produce code visualizations +based on source code (in addition to current reflection based approach). + +** Integrate with PlantUML +:PROPERTIES: +:CUSTOM_ID: plantuml-integration +:END: +http://plantuml.com/class-diagram + +** Add dark theme for generated graphs +:PROPERTIES: +:CUSTOM_ID: dark-theme +:END: + +** Sort class fields alphabetically +:PROPERTIES: +:CUSTOM_ID: sort-fields-alphabetically +:END: + +** Visualize concrete field values +:PROPERTIES: +:CUSTOM_ID: visualize-field-values +:END: +Could be used as ultra cool runtime logging/debugging framework. + +** Visualize from JVM snapshot +:PROPERTIES: +:CUSTOM_ID: jvm-snapshot +:END: + +** Attach to remote process via JVM debug port +:PROPERTIES: +:CUSTOM_ID: remote-process-debug +:END: + +** Attach to JVM using JVM agent +:PROPERTIES: +:CUSTOM_ID: jvm-agent +:END: + +** 3D visualization with Sixth 3D engine +:PROPERTIES: +:CUSTOM_ID: 3d-visualization +:END: +https://www3.svjatoslav.eu/projects/sixth-3d/ + +** Add graph query language +:PROPERTIES: +:CUSTOM_ID: graph-query-language +:END: +Select classes/fields/values to be visualized in some graph query +language. For greater flexibility in comparison to currently supported +glob syntax. + +** Add JSON/XML config file support +:PROPERTIES: +:CUSTOM_ID: config-file +:END: +Different graphs for given project could be defined once in plain text +config, possibly with the aid of some interactive utility. Then defined +graphs could be updated as part of project build or release process. + +** Configurable Maven plugin +:PROPERTIES: +:CUSTOM_ID: maven-plugin +:END: +Generate graphs as part of the project build/release process. \ No newline at end of file diff --git a/Tools/Open with IntelliJ IDEA b/Tools/Open with IntelliJ IDEA new file mode 100755 index 0000000..de9bae5 --- /dev/null +++ b/Tools/Open with IntelliJ IDEA @@ -0,0 +1,18 @@ +#!/bin/bash + +# +# This is a helper bash script that starts IntelliJ with the current project. +# Script is written is such a way that you can simply click on it in file +# navigator to run it. +# +# +# Script assumes: +# +# + GNU operating system +# + IntelliJ is installed and commandline launcher "idea" is enabled. +# + +cd "${0%/*}" +cd .. + +setsid idea . &>/dev/null diff --git a/Tools/Update web site b/Tools/Update web site new file mode 100755 index 0000000..86d62a0 --- /dev/null +++ b/Tools/Update web site @@ -0,0 +1,127 @@ +#!/bin/bash +cd "${0%/*}"; if [ "$1" != "T" ]; then gnome-terminal -- "$0" T; exit; fi; + +cd .. + +# Function to export org to html using emacs in batch mode +export_org_to_html() { + local org_file=$1 + local dir=$(dirname "$org_file") + local base=$(basename "$org_file" .org) + ( + cd "$dir" || return 1 + local html_file="${base}.html" + if [ -f "$html_file" ]; then + rm -f "$html_file" + fi + echo "Exporting: $org_file → $dir/$html_file" + emacs --batch -l ~/.emacs --visit="${base}.org" --funcall=org-html-export-to-html --kill + if [ $? -eq 0 ]; then + echo "✓ Successfully exported $org_file" + else + echo "✗ Failed to export $org_file" + return 1 + fi + ) +} + +export_org_files_to_html() { + echo "🔍 Searching for .org files in doc/ ..." + echo "=======================================" + + mapfile -t ORG_FILES < <(find doc -type f -name "*.org" | sort) + + if [ ${#ORG_FILES[@]} -eq 0 ]; then + echo "❌ No .org files found!" + return 1 + fi + + echo "Found ${#ORG_FILES[@]} .org file(s):" + printf '%s\n' "${ORG_FILES[@]}" + echo "=======================================" + + SUCCESS_COUNT=0 + FAILED_COUNT=0 + + for org_file in "${ORG_FILES[@]}"; do + export_org_to_html "$org_file" + if [ $? -eq 0 ]; then + ((SUCCESS_COUNT++)) + else + ((FAILED_COUNT++)) + fi + done + + echo "=======================================" + echo "📊 SUMMARY:" + echo " ✓ Successful: $SUCCESS_COUNT" + echo " ✗ Failed: $FAILED_COUNT" + echo " Total: $((SUCCESS_COUNT + FAILED_COUNT))" + echo "" +} + +build_visualization_graphs() { + echo "🎨 Generating class visualization graphs..." + echo "=======================================" + + rm -rf doc/graphs/ + mkdir -p doc/graphs/ + + # JavaInspect analyzing itself - meta visualization! + javainspect -j target/javainspect.jar -d doc/graphs/ -n "All classes" -t png + javainspect -j target/javainspect.jar -d doc/graphs/ -n "Inspector" -t png -w "eu.svjatoslav.inspector.*" + javainspect -j target/javainspect.jar -d doc/graphs/ -n "Java parser" -t png -w "eu.svjatoslav.inspector.java.*" + + # Generate index page for graphs + meviz index -w doc/graphs/ -t "JavaInspect classes" + + echo "✓ Visualization graphs generated" + echo "" +} + +# Build project jar file and JavaDocs +echo "🔨 Building project..." +echo "=======================================" +mvn clean package + +if [ $? -ne 0 ]; then + echo "✗ Maven build failed!" + echo "" + echo "Press ENTER to close this window." + read + exit 1 +fi + +echo "✓ Maven build completed" +echo "" + +# Put generated JavaDoc HTML files to documentation directory +echo "📚 Copying JavaDocs..." +echo "=======================================" +rm -rf doc/apidocs/ +cp -r target/apidocs/ doc/ + +echo "✓ JavaDocs copied to doc/apidocs/" +echo "" + +# Publish Emacs org-mode files into HTML format +export_org_files_to_html + +# Generate nice looking code visualization diagrams +build_visualization_graphs + +## Upload assembled documentation to server +echo "📤 Uploading to server..." +echo "=======================================" +rsync -avz --delete -e 'ssh -p 10006' doc/ \ + n0@www3.svjatoslav.eu:/mnt/big/projects/javainspect/ + +if [ $? -eq 0 ]; then + echo "✓ Upload completed successfully!" +else + echo "✗ Upload failed!" +fi + +echo "" +echo "Press ENTER to close this window." +read \ No newline at end of file diff --git a/commandline launcher/install b/commandline launcher/install new file mode 100755 index 0000000..b7c7b3e --- /dev/null +++ b/commandline launcher/install @@ -0,0 +1,25 @@ +#!/bin/bash +# +# This script installs JavaInspect into /opt/javainspect/ directory. +# It also enables javainspect command at the commandline. +# + +( + # go to project root directory + cd .. + + # remove old installation (if any) + sudo rm -rf /opt/javainspect/ + + # compile new package + mvn clean package + + # create installation directory + sudo mkdir -p /opt/javainspect/ + + # copy javainspect jar file to opt installation directory + sudo cp target/javainspect.jar /opt/javainspect/ +) + +# deploy launcher script to /usr/local/bin/javainspect +sudo cp javainspect /usr/local/bin/ diff --git a/commandline launcher/javainspect b/commandline launcher/javainspect new file mode 100755 index 0000000..62971e5 --- /dev/null +++ b/commandline launcher/javainspect @@ -0,0 +1,7 @@ +#!/bin/bash +# +# Launcher script for JavaInspect utility: +# https://www3.svjatoslav.eu/projects/javainspect/ +# + +java -jar /opt/javainspect/javainspect.jar "$@" diff --git a/doc/JavaInspect full project.png b/doc/JavaInspect full project.png new file mode 100644 index 0000000000000000000000000000000000000000..4d5ebba6eebe5a16737393105d593bf7ba780dd1 GIT binary patch literal 111609 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 L + + // class descriptor header + eu.svjatoslav.inspector.java.structure
Filter + + // fields: + // blacklistClassPatterns + ListblacklistClassPatterns + // whitelistClassPatterns + ListwhitelistClassPatterns + + // methods: + // blacklistClassPattern + voidblacklistClassPattern + // isClassShown + booleanisClassShown + // whitelistClassPattern + voidwhitelistClassPattern + >, shape="none"]; + + // field references to other classes + + // method references to other classes + +// Class: eu.svjatoslav.inspector.java.structure.FieldDescriptor + class_eu_svjatoslav_inspector_java_structure_FieldDescriptor[label=< + + // class descriptor header + + + // fields: + // name + + // parent + + // type + + // typeArguments + + + // methods: + // getDot + + // getEmbeddedDot + + // getGraphId + + // getOutsideVisibleReferencesCount + + // isVisible + +
eu.svjatoslav.inspector.java.structure
FieldDescriptor
Stringname
ClassDescriptorparent
ClassDescriptortype
ListtypeArguments
StringgetDot
StringgetEmbeddedDot
StringgetGraphId
intgetOutsideVisibleReferencesCount
booleanisVisible
>, shape="none"]; + + // field references to other classes + + // method references to other classes + + // interfaces implemented by class: eu.svjatoslav.inspector.java.structure.FieldDescriptor + class_eu_svjatoslav_inspector_java_structure_GraphElement -> class_eu_svjatoslav_inspector_java_structure_FieldDescriptor[style="dotted, tapered", color="olivedrab2", penwidth=20, dir="forward"]; + +// Class: eu.svjatoslav.inspector.java.structure.MethodDescriptor + class_eu_svjatoslav_inspector_java_structure_MethodDescriptor[label=< + + // class descriptor header + + + // fields: + // name + + // parent + + // returnType + + // typeArguments + + + // methods: + // compareTo + + // compareTo + + // getDot + + // getEmbeddedDot + + // getGraphId + + // getMethodLabel + + // getOutsideVisibleReferencesCount + + // isVisible + +
eu.svjatoslav.inspector.java.structure
MethodDescriptor
Stringname
ClassDescriptorparent
ClassDescriptorreturnType
ListtypeArguments
intcompareTo
intcompareTo
StringgetDot
StringgetEmbeddedDot
StringgetGraphId
StringgetMethodLabel
intgetOutsideVisibleReferencesCount
booleanisVisible
>, shape="none"]; + + // field references to other classes + + // method references to other classes + + // interfaces implemented by class: eu.svjatoslav.inspector.java.structure.MethodDescriptor + class_eu_svjatoslav_inspector_java_structure_GraphElement -> class_eu_svjatoslav_inspector_java_structure_MethodDescriptor[style="dotted, tapered", color="olivedrab2", penwidth=20, dir="forward"]; + +// Class: eu.svjatoslav.inspector.java.structure.Utils + class_eu_svjatoslav_inspector_java_structure_Utils[label=< + + // class descriptor header + + + // fields: + // darkColors + + // enumMethods + + // lastChosenDarkColor + + // lastChosenLightColor + + // lightColors + + // systemDataTypes + + // systemMethods + + // systemPackages + + + // methods: + // getNextDarkColor + + // getNextLightColor + + // initDarkColors + + // initEnumMethods + + // initLightColors + + // initSystemDataTypes + + // initSystemMethods + + // initSystemPackages + + // isEnumMethod + + // isSystemDataType + + // isSystemMethod + + // isSystemPackage + +
eu.svjatoslav.inspector.java.structure
Utils
ListdarkColors
ListenumMethods
intlastChosenDarkColor
intlastChosenLightColor
ListlightColors
ListsystemDataTypes
ListsystemMethods
ListsystemPackages
StringgetNextDarkColor
StringgetNextLightColor
voidinitDarkColors
voidinitEnumMethods
voidinitLightColors
voidinitSystemDataTypes
voidinitSystemMethods
voidinitSystemPackages
booleanisEnumMethod
booleanisSystemDataType
booleanisSystemMethod
booleanisSystemPackage
>, shape="none"]; + + // field references to other classes + + // method references to other classes + +// Class: eu.svjatoslav.inspector.java.structure.GraphElement + class_eu_svjatoslav_inspector_java_structure_GraphElement[label=< + + // class descriptor header + + + // methods: + // getDot + + // getEmbeddedDot + + // getGraphId + + // isVisible + +
eu.svjatoslav.inspector.java.structure
GraphElement
StringgetDot
StringgetEmbeddedDot
StringgetGraphId
booleanisVisible
>, shape="none"]; + + // method references to other classes + +// Class: eu.svjatoslav.inspector.java.structure.ClassGraph + class_eu_svjatoslav_inspector_java_structure_ClassGraph[label=< + + // class descriptor header + + + // fields: + // filter + + // nameToClassMap + + + // methods: + // addClass + + // addObject + + // addProject + + // generateGraph + + // generateGraph + + // hideOrphanedClasses + + // render + +
eu.svjatoslav.inspector.java.structure
ClassGraph
Filterfilter
MapnameToClassMap
ClassDescriptoraddClass
ClassDescriptoraddObject
voidaddProject
voidgenerateGraph
voidgenerateGraph
voidhideOrphanedClasses
voidrender
>, shape="none"]; + + // field references to other classes + class_eu_svjatoslav_inspector_java_structure_ClassGraph:filter -> class_eu_svjatoslav_inspector_java_structure_Filter[label="filter", color="antiquewhite4", style="bold"]; + + // method references to other classes + +// Class: eu.svjatoslav.inspector.java.structure.ClassDescriptor + class_eu_svjatoslav_inspector_java_structure_ClassDescriptor[label=< + + // class descriptor header + + + // fields: + // MAX_REFERECNES_COUNT + + // classGraph + + // distinctiveReferenceColor + + // fullyQualifiedName + + // incomingReferencesCount + + // interfaceColor + + // interfaces + + // isArray + + // isEnum + + // isInterface + + // isShown + + // methods + + // nameToFieldMap + + // superClass + + // superClassColor + + + // methods: + // areReferencesShown + + // enlistFieldReferences + + // enlistFields + + // enlistImplementedInterfaces + + // enlistMethodReferences + + // enlistMethods + + // enlistSuperClass + + // generateDotHeader + + // getAllFields + + // getBackgroundColor + + // getBorderWidth + + // getClassName + + // getColor + + // getDistinctiveColor + + // getDot + + // getEmbeddedDot + + // getGraphId + + // getPackageName + + // getParentClassesName + + // hide + + // hideClassIfNoReferences + + // indexFields + + // isVisible + + // registerReference + + // setDistinctiveColor + +
eu.svjatoslav.inspector.java.structure
ClassDescriptor
intMAX_REFERECNES_COUNT
ClassGraphclassGraph
StringdistinctiveReferenceColor
StringfullyQualifiedName
intincomingReferencesCount
StringinterfaceColor
Listinterfaces
booleanisArray
booleanisEnum
booleanisInterface
booleanisShown
SortedSetmethods
MapnameToFieldMap
ClassDescriptorsuperClass
StringsuperClassColor
booleanareReferencesShown
voidenlistFieldReferences
voidenlistFields
voidenlistImplementedInterfaces
voidenlistMethodReferences
voidenlistMethods
voidenlistSuperClass
voidgenerateDotHeader
ListgetAllFields
StringgetBackgroundColor
StringgetBorderWidth
StringgetClassName
StringgetColor
StringgetDistinctiveColor
StringgetDot
StringgetEmbeddedDot
StringgetGraphId
StringgetPackageName
StringgetParentClassesName
voidhide
booleanhideClassIfNoReferences
voidindexFields
booleanisVisible
voidregisterReference
voidsetDistinctiveColor
>, shape="none"]; + + // field references to other classes + class_eu_svjatoslav_inspector_java_structure_ClassDescriptor:classGraph -> class_eu_svjatoslav_inspector_java_structure_ClassGraph[label="classGraph", color="blueviolet", style="bold"]; + class_eu_svjatoslav_inspector_java_structure_ClassDescriptor:methods -> class_eu_svjatoslav_inspector_java_structure_MethodDescriptor[label="methods", color="brown4", style="bold"]; + class_eu_svjatoslav_inspector_java_structure_ClassDescriptor:nameToFieldMap -> class_eu_svjatoslav_inspector_java_structure_FieldDescriptor[label="nameToFieldMap", color="chartreuse4", style="bold"]; + + // method references to other classes + class_eu_svjatoslav_inspector_java_structure_ClassDescriptor:getAllFields -> class_eu_svjatoslav_inspector_java_structure_FieldDescriptor[label="getAllFields", color="chartreuse4", style="dotted, bold"]; + + // interfaces implemented by class: eu.svjatoslav.inspector.java.structure.ClassDescriptor + class_eu_svjatoslav_inspector_java_structure_GraphElement -> class_eu_svjatoslav_inspector_java_structure_ClassDescriptor[style="dotted, tapered", color="olivedrab2", penwidth=20, dir="forward"]; +} diff --git a/doc/JavaInspect.png b/doc/JavaInspect.png new file mode 100644 index 0000000000000000000000000000000000000000..625a2dad4bf00e9060869e8958d9f6acf238857c GIT binary patch literal 99339 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 L_O4deH1z)fo*oYN literal 0 HcmV?d00001 diff --git a/doc/index.org b/doc/index.org new file mode 100644 index 0000000..145282f --- /dev/null +++ b/doc/index.org @@ -0,0 +1,237 @@ +#+SETUPFILE: ~/.emacs.d/org-styles/html/darksun.theme +#+TITLE: JavaInspect - Utility to visualize java software +#+LANGUAGE: en +#+LATEX_HEADER: \usepackage[margin=1.0in]{geometry} +#+LATEX_HEADER: \usepackage{parskip} +#+LATEX_HEADER: \usepackage[none]{hyphenat} + +#+OPTIONS: H:20 num:20 +#+OPTIONS: author:nil + +* Introduction +:PROPERTIES: +:CUSTOM_ID: overview +:END: + +*JavaInspect* utility simplifies understanding the computer program +code by automatically visualizing its structure. + +[[https://www3.svjatoslav.eu/projects/sixth-3d/graphs/][See example produced graphs]] for [[https://www3.svjatoslav.eu/projects/sixth-3d/][Sixth 3D - 3D engine project]]. + +JavaInspect can be used as a [[id:acf1896a-74b4-4914-acf6-a77075e07f25][standalone commandline utility]] as well as +[[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][java library]]. JavaInspect uses primarily Java built-in reflection to +discover and visualize any part of Java program. + +JavaInspect currently has no graphical user interface, configuration +files, embedded scripting support, direct Maven, Gradle or Ant +integration. See [[id:2ad2889e-6c95-4662-b3f4-2c341fc74522][usage]] to learn how to instuct Javainspect what to do. + +After discovering application structure and optionally filtering out +unimportant parts, JavaInspect produces GraphViz dot file that +describes data to be visualized. Then launches [[https://graphviz.org/][GraphViz]] to generate +bitmap graph in PNG or SVG format. + +Notes: ++ JavaInspect is developed and tested so far only on GNU/Linux. + + +*A very simple example:* + +[[file:example.png][file:example-thumbnail.png]] + +Graph legend: +file:legend.png + + ++ [[https://www3.svjatoslav.eu/projects/sixth-3d/graphs/][See example produced graphs]] for [[https://www3.svjatoslav.eu/projects/sixth-3d/][Sixth 3D - 3D engine project]]. + +** See also +:PROPERTIES: +:CUSTOM_ID: see-also +:END: + +Similar or alternative solutions: ++ http://www.class-visualizer.net/ ++ [[https://github.com/pahen/madge][Madge - similar tool for JavaScript]] + +* Installation +:PROPERTIES: +:CUSTOM_ID: installation +:END: +[[http://www.graphviz.org/][GraphViz]] - shall be installed on the computer. + +On Ubuntu/Debian GraphViz can be installed using: +#+BEGIN_SRC sh +sudo apt-get install graphviz +#+END_SRC + +To use JavaInspect via Java API, no further installation is +needed. JavaInspect will be embedded into your project as dependency. +This is described in [[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][usage via Java API]]. It will expect GraphViz to be +available in the system. + +To use JavaInspect as a commandline tool, JavaInspect source +repository has to be cloned locally. See: [[id:c47ff9a6-d737-4b73-9393-1c63d2ca1101][Getting the source code]]. + +Then study and execute installation script: +#+begin_src sh + cd commandline\ launcher + ./install +#+end_src + +After installation, new commandline tool should be available +: javainspect + +Quick commandline usage help can be viewed by issuing +: javainspect --help + +* Usage +:PROPERTIES: +:ID: 2ad2889e-6c95-4662-b3f4-2c341fc74522 +:CUSTOM_ID: usage +:END: +JavaInspect utility can be used in 2 different ways: ++ [[id:acf1896a-74b4-4914-acf6-a77075e07f25][As standalone commandline utility]] ++ [[id:bbeeffc8-3767-440d-8d93-ec9124dd60ee][As embedded Java library via Java API]] + +** Usage via Java API +:PROPERTIES: +:ID: bbeeffc8-3767-440d-8d93-ec9124dd60ee +:CUSTOM_ID: usage-via-java-api +:END: +Requires that classes to be visualised are available in the classpath. + +To get JavaInspect into same classpath with your projecs I so far came +up with 2 solutions: + +1. Add JavaInspect library in your project as a dependency. + +2. Create new Java project for the purpose visualizing your other + projects and include JavaInspect and your projecs binary artifacts + (Jar's) into new project classpath. Built binary Jar's (with no + source code) are sufficient because JavaInspect operates via + reflection. + +Simple Java based control/configuration code needs to be written for +each project. I usually put such code into directories devoted for +JUnit tests. Because it needs not to be compiled/embedded into final +product or project artifact I'm just willing to visualize. + +Control code in general does the following: +1. Create graph object. +2. Java reflection/classloaders does not provide mechanism for + discovering all classes under given package. Therefore you need to + declare at least some classes to be added to the graph by manually + adding individual classes to the graph. For every class added to + the graph, GraphViz will recursively inspect it and add all + referecned classes to the graph as well. +3. Graphs easilly get very big and complex so optionally we filter + important code using classname [[https://en.wikipedia.org/wiki/Glob_(programming)][glob]] patterns based blacklist and/or + whitelist. +4. Optionally we can tune some rendering parameters like: + + Possibility to remove orphaned classes (classes with no + references) from the graph. + + Specify target directory for generated visualization + files. (Default is current directory) + + Keep intermediate GraphViz dot file for later inspection. +5. Render graph. + + +*** Example 1: individually picked objects +:PROPERTIES: +:CUSTOM_ID: example-1-individually-picked-objects +:END: +This example demonstrates generating of class graph from hand picked +classes and visualizing GraphViz itself. + +#+BEGIN_SRC java + +// Create graph +final ClassGraph graph = new ClassGraph(); + +// Add some random object to the graph. GraphViz will detect Class from +// the object. +graph.add(graph); + +// Also add some random class to the graph. +graph.add(Utils.class); + +// Keep intermediary GraphViz DOT file for reference. +graph.setKeepDotFile(true); + +// Produce bitmap image titled "JavaInspect.png" to the user Desktop +// directory +graph.generateGraph("JavaInspect"); + +#+END_SRC + +Note: if desired, more compact version of the above: +#+BEGIN_SRC java +new ClassGraph().add(randomObject, RandomClass.class) + .setKeepDotFile(true).generateGraph("JavaInspect"); +#+END_SRC + + +Result: + - Generated DOT file: [[file:JavaInspect.dot][JavaInspect.dot]] + - Generated PNG image: [[file:JavaInspect.png][JavaInspect.png]] + +*** Example 2: GraphViz embedded in another project +:PROPERTIES: +:CUSTOM_ID: example-2-graphviz-embedded-in-another-project +:END: +1. Download project Sixth [[https://www2.svjatoslav.eu/gitweb/?p=sixth.git;a=snapshot;h=HEAD;sf=tgz][code snapshot]]. +2. Inspect and run *DataGraph.java*. + +*** Embedding JavaInspect in your Maven project +:PROPERTIES: +:CUSTOM_ID: embedding-javainspect-in-your-maven-project +:END: + +Declare JavaInspect as dependency: +#+BEGIN_SRC xml + + ... + + eu.svjatoslav + javainspect + 1.7 + + ... + +#+END_SRC + + +Add Maven repository to retrieve artifact from: +#+BEGIN_SRC xml + + ... + + svjatoslav.eu + Svjatoslav repository + https://www3.svjatoslav.eu/maven/ + + ... + +#+END_SRC + +* Source code +:PROPERTIES: +:ID: c47ff9a6-d737-4b73-9393-1c63d2ca1101 +:CUSTOM_ID: getting-the-source-code +:END: + +*This program is free software: released under Creative Commons Zero +(CC0) license* + +Program author: +- Svjatoslav Agejenko +- Homepage: https://svjatoslav.eu +- Email: mailto://svjatoslav@svjatoslav.eu +- See also: [[https://www.svjatoslav.eu/projects/][Other software projects hosted at svjatoslav.eu]] + +*Getting the source code:* +- [[https://www2.svjatoslav.eu/gitweb/?p=javainspect.git;a=snapshot;h=HEAD;sf=tgz][Download latest source code snapshot in TAR GZ format]] +- [[https://www2.svjatoslav.eu/gitweb/?p=javainspect.git;a=summary][Browse Git repository online]] +- You can clone Git repository using git: + : git clone https://www3.svjatoslav.eu/git/javainspect.git diff --git a/doc/legend.png b/doc/legend.png new file mode 100644 index 0000000000000000000000000000000000000000..e206b4fb74ec73791a5bdd8b6a2c3f3050ff21fe GIT binary patch literal 18350 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 literal 0 HcmV?d00001 diff --git a/doc/usage cli.org b/doc/usage cli.org new file mode 100644 index 0000000..d77bdef --- /dev/null +++ b/doc/usage cli.org @@ -0,0 +1,111 @@ +:PROPERTIES: +:ID: acf1896a-74b4-4914-acf6-a77075e07f25 +:END: + +#+TITLE: JavaInspect - usage from commandline +#+LANGUAGE: en +#+LATEX_HEADER: \usepackage[margin=1.0in]{geometry} +#+LATEX_HEADER: \usepackage{parskip} +#+LATEX_HEADER: \usepackage[none]{hyphenat} + +#+OPTIONS: H:20 num:20 +#+OPTIONS: author:nil + + +* Available commandline arguments +:PROPERTIES: +:CUSTOM_ID: available-commandline-arguments +:END: + + +- -j (existing files)... :: JAR file(s) to render. + +- -c (existing directories)... :: Classpath directories + +- -n (string) :: Graph name. (default: "graph") + +- --debug :: Show debug info. + +- -h, --help :: Show commandline usage help. + +- -k :: Keep dot file. + +- -ho :: + Hide orphaned classes. + +- -w (one to many strings)... :: Whitelist glob(s). + +- -b (one to many strings)... :: Blacklist glob(s). + +- -r (one to many strings)... :: root class(es). + +- -d (existing directory) :: Target directory. Default is current directory. + +- -t (options: png, svg) :: Target image type. Default is: svg. + +* Specifying classes to render +:PROPERTIES: +:CUSTOM_ID: specifying-classes-to-render +:END: + +Normal Java application has immense complexity. In addition to code +that was directly written by particular project developers, lots of +functionality is typically added as frameworks or libraries to the +project. In addition there is significant Java standard library. + +Because JavaInspect uses reflection, it does not easily distinguish +between those. In normal situation you would rather want to visualize +only code that was developed specifically for your project and leave +frameworks like Spring etc. out. If you visualize all classes that are +possibly reachable from you project, you will easily get huge and +incomprehensible graph. + +JavaInspect can digest compiled Java classes in 2 modes: +1. Provide list of Jar files. Use *-j* option. +2. Provide list of filesystem directories that can be used as + classpath root. Use *-c* option. + +Currently JavaInspect uses following algorithm to add classes to +rendered graph: + +- All classes that were found in Jar files are added to graph by default. +- None of the classes that were found in filesystem directories are + added to the graph by default (unless explicitly referenced). (TODO: + for consistency it would be better to add them too by default) +- If whitelist is specified (*-w* option) everything that is not + matched by whitelist pattern(s) will be removed from the graph. +- If blacklist is specified (*-b* option) everything that is matched + by blacklist pattern(s) will be removed from the graph. +- Root classes can be specified using *-r* option. Root classes will + be added to the graph. JavaInspect will then try to recursively + discover all classes that were referenced by root class and add + those also to the graph. + +* Examples +:PROPERTIES: +:CUSTOM_ID: examples +:END: + +Visualize java Jar file. All classes. Hide orphaned classes: + +#+begin_src sh + javainspect \ + -j target/sixth-3d-*-SNAPSHOT.jar \ + -d doc/graphs/ \ + -n "all classes" \ + -t png -ho +#+end_src + + +Visualize java Jar file. All classes. Hide orphaned classes. Apply +whitelist: + +#+begin_src sh + javainspect \ + -j target/sixth-3d-*-SNAPSHOT.jar \ + -d doc/graphs/ \ + -n "GUI" \ + -t png \ + -w "eu.svjatoslav.sixth.e3d.gui.*" \ + -ho +#+end_src diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e27daad --- /dev/null +++ b/pom.xml @@ -0,0 +1,160 @@ + + 4.0.0 + eu.svjatoslav + javainspect + 1.8-SNAPSHOT + jar + JavaInspect + Utility to visualize Java code + + + 1.8 + 1.8 + 1.8 + UTF-8 + UTF-8 + + + + svjatoslav.eu + http://svjatoslav.eu + + + + javainspect + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + true + UTF-8 + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + + + foo + bar + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.2 + + + org.apache.maven.scm + maven-scm-provider-gitexe + 1.9.4 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + eu.svjatoslav.inspector.java.commandline.Main + + + + + + + + + + + org.apache.maven.wagon + wagon-ssh-external + 2.6 + + + + + + + eu.svjatoslav + svjatoslavcommons + 1.9 + + + eu.svjatoslav + cli-helper + 1.0 + + + + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu:10006/srv/maven + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu:10006/srv/maven + + + + + + svjatoslav.eu + Svjatoslav repository + https://www3.svjatoslav.eu/maven/ + + + + + + scm:git:ssh://n0@svjatoslav.eu:10006/home/n0/git/javainspect.git + scm:git:ssh://n0@svjatoslav.eu:10006/home/n0/git/javainspect.git + HEAD + + + diff --git a/src/main/java/eu/svjatoslav/inspector/java/RenderJavaInspect.java b/src/main/java/eu/svjatoslav/inspector/java/RenderJavaInspect.java new file mode 100755 index 0000000..4d4f39c --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/RenderJavaInspect.java @@ -0,0 +1,67 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java; + +import eu.svjatoslav.inspector.java.structure.ClassGraph; +import eu.svjatoslav.inspector.java.structure.Utils; + +/** + * Demo application that generates a self-visualization of JavaInspect. + * + *

This class demonstrates how to use JavaInspect to analyze and visualize + * its own codebase, producing a class diagram showing the internal structure + * of the tool.

+ * + * @see ClassGraph + */ +public class RenderJavaInspect { + + /** + * Demonstrates generating a class graph from hand-picked classes. + * + *

This method creates a graph visualization of JavaInspect itself, + * including the {@link ClassGraph} and {@link Utils} classes. The output + * files are generated in the project root directory:

+ * + *
    + *
  • JavaInspect.svg - Scalable vector graphics visualization
  • + *
  • JavaInspect.dot - GraphViz DOT source file (kept for reference)
  • + *
+ */ + private static void handpickClassesExample() { + /* + * This example demonstrates generating of class graph from hand picked + * classes and visualizing GraphViz itself. + */ + + // Create graph + final ClassGraph graph = new ClassGraph(); + + // Add some random object to the graph. GraphViz will detect Class from + // the object. + graph.add(graph); + + // Also add some random class to the graph. + graph.add(Utils.class); + + // Keep intermediary GraphViz DOT file for reference. + graph.setKeepDotFile(true); + + // Produce SVG image titled "JavaInspect.svg" to the user Desktop + // directory + graph.generateGraph("JavaInspect"); + } + + /** + * Entry point for the demo application. + * + * @param args command-line arguments (ignored) + */ + public static void main(final String[] args) { + + handpickClassesExample(); + } +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java new file mode 100644 index 0000000..c22f5a7 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/CommandlineConfiguration.java @@ -0,0 +1,196 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.commandline; + + +import eu.svjatoslav.commons.cli_helper.parameter_parser.Parser; +import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.*; + +/** + * Configuration holder for JavaInspect command-line arguments. + * + *

This class parses and stores all command-line options for the + * JavaInspect tool, providing easy access to JAR files, graph settings, + * and filter patterns.

+ * + *

Supported options:

+ *
    + *
  • -j, --jar: JAR files to analyze (required unless -r is specified)
  • + *
  • -c, --classpath: Additional classpath directories
  • + *
  • -n, --name: Graph name for output files
  • + *
  • -t, --type: Output image type (svg or png)
  • + *
  • -d, --directory: Target output directory
  • + *
  • -k, --keep-dot: Keep intermediate DOT file
  • + *
  • -w, --whitelist: Whitelist glob patterns
  • + *
  • -b, --blacklist: Blacklist glob patterns
  • + *
  • -r, --root: Root classes to analyze (instead of all JAR classes)
  • + *
  • -ho, --hide-orphaned: Hide classes with no connections
  • + *
  • --debug: Show debug output
  • + *
  • -h, --help: Show usage help
  • + *
+ * + * @see Main + * @see Parser + */ +public class CommandlineConfiguration { + + /** + * JAR files containing classes to analyze. + */ + public FileParameters jarFiles; + + /** + * Name for the generated graph files. + */ + public StringParameter graphName; + + /** + * Flag to enable debug output during processing. + */ + private NullParameter showDebug; + + /** + * Glob patterns for classes to include in the graph. + */ + public StringParameters whitelistGlob; + + /** + * Glob patterns for classes to exclude from the graph. + */ + public StringParameters blacklistGlob; + + /** + * Specific root classes to analyze (instead of all JAR classes). + */ + public StringParameters rootClasses; + + /** + * Flag to show command-line usage help. + */ + public NullParameter showHelp; + + /** + * Output image type (SVG or PNG). + */ + public TargetImageTypeParameter targetImageType; + + /** + * Flag to keep the intermediate DOT file. + */ + public NullParameter keepDotFile; + + /** + * Directory for output files. + */ + public DirectoryParameter targetDirectory; + + /** + * Additional classpath directories for resolving dependencies. + */ + public DirectoryParameters classPaths; + + /** + * Whether the command-line arguments were parsed successfully. + */ + public final boolean configurationOk; + + /** + * Flag to hide orphaned classes (classes with no connections). + */ + public NullParameter hideOrphanedClasses; + + /** + * The argument parser instance. + */ + Parser parser; + + /** + * Default graph name if not specified on command line. + */ + public static final String DEFAULT_GRAPH_NAME = "graph"; + + /** + * Parses command-line arguments and initializes all configuration options. + * + * @param args the command-line arguments to parse + */ + public CommandlineConfiguration(String[] args) { + parser = buildCommandlineParameterParser(); + configurationOk = parser.parse(args); + } + + /** + * Checks if debug mode is enabled. + * + * @return true if --debug was specified + */ + public boolean isDebug() { + return showDebug.isSpecified(); + } + + /** + * Builds the command-line argument parser with all supported options. + * + *

This method creates a Parser and registers all parameters with + * their descriptions, default values, and aliases.

+ * + * @return the configured Parser instance + */ + public Parser buildCommandlineParameterParser() { + Parser parser = new Parser(); + + jarFiles = parser.add( + new FileParameters("JAR file(s) to render.")) + .mustExist() + .addAliases("-j"); + + classPaths = parser.add( + new DirectoryParameters("Classpath directories")) + .mustExist() + .addAliases("-c"); + + graphName = parser.add( + new StringParameter("Graph name. (default: \"" + DEFAULT_GRAPH_NAME + "\")", DEFAULT_GRAPH_NAME)) + .addAliases("-n"); + + showDebug = parser.add( + new NullParameter("Show debug info.")) + .addAliases("--debug"); + + showHelp = parser.add(new NullParameter("Show commandline usage help.")) + .addAliases("-h", "--help"); + + keepDotFile = parser.add( + new NullParameter("Keep dot file.")) + .addAliases("-k"); + + hideOrphanedClasses = parser.add( + new NullParameter("Hide orphaned classes.")) + .addAliases("-ho"); + + whitelistGlob = parser.add( + new StringParameters("Whitelist glob(s).")) + .addAliases("-w"); + + blacklistGlob = parser.add( + new StringParameters("Blacklist glob(s).")) + .addAliases("-b"); + + rootClasses = parser.add( + new StringParameters("root class(es).")) + .addAliases("-r"); + + + targetDirectory = parser.add(new DirectoryParameter("Target directory. " + + "Default is current directory.").mustExist()) + .addAliases("-d"); + + targetImageType = parser.add(new TargetImageTypeParameter()).addAliases("-t"); + + return parser; + } + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java new file mode 100644 index 0000000..ace1324 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/Main.java @@ -0,0 +1,262 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.commandline; + +import eu.svjatoslav.inspector.java.structure.ClassGraph; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +/** + * Command-line interface entry point for JavaInspect. + * + *

This class provides the main method for running JavaInspect from the + * command line, parsing arguments and generating class visualizations.

+ * + *

Usage:

+ *
+ * java -jar javainspect.jar -j myapp.jar -n MyAppGraph
+ * 
+ * + *

Common options:

+ *
    + *
  • -j: JAR files to analyze
  • + *
  • -n: Graph name for output files
  • + *
  • -t: Output format (svg or png)
  • + *
  • -d: Target directory for output
  • + *
  • -w/-b: Whitelist/blacklist glob patterns
  • + *
+ * + * @see CommandlineConfiguration + * @see ClassGraph + */ +public class Main { + + /** + * Main entry point for the command-line interface. + * + *

Parses command-line arguments, builds the class graph from JAR files, + * and generates the visualization.

+ * + * @param args command-line arguments + * @throws IOException if JAR files cannot be read + * @throws ClassNotFoundException if classes cannot be loaded + */ + public static void main(String[] args) throws IOException, ClassNotFoundException { + CommandlineConfiguration configuration = new CommandlineConfiguration(args); + if (!configuration.configurationOk) { + configuration.parser.showHelp(); + System.exit(1); + } + + if (configuration.showHelp.isSpecified()) configuration.parser.showHelp(); + + getClassGraph(configuration).generateGraph(configuration.graphName.getValue()); + + if (configuration.isDebug()) + System.out.println("Graph ready."); + } + + /** + * Builds and configures the ClassGraph from command-line options. + * + *

This method:

+ *
    + *
  1. Creates a URLClassLoader from the JAR files and classpath
  2. + *
  3. Creates a ClassGraph and configures output options
  4. + *
  5. Loads either specified root classes or all classes from JARs
  6. + *
  7. Applies whitelist/blacklist filters
  8. + *
  9. Hides orphaned classes if requested
  10. + *
+ * + * @param configuration the parsed command-line configuration + * @return the configured ClassGraph ready for generation + * @throws IOException if JAR files cannot be read + * @throws ClassNotFoundException if classes cannot be loaded + */ + private static ClassGraph getClassGraph(CommandlineConfiguration configuration) throws IOException, ClassNotFoundException { + List jarFiles = configuration.jarFiles.getValue(); + + URLClassLoader classLoader = new URLClassLoader( + getClasspathUrls(jarFiles, configuration.classPaths.getValue()), + configuration.getClass().getClassLoader()); + + ClassGraph classGraph = new ClassGraph(); + + if (configuration.targetDirectory.isSpecified()) + classGraph.setTargetDirectory(configuration.targetDirectory.getValue()); + + if (configuration.targetImageType.isSpecified()) + classGraph.setTargetImageType(configuration.targetImageType.getValue()); + + classGraph.setKeepDotFile(configuration.keepDotFile.getValue()); + + if (configuration.rootClasses.isSpecified()) { + // add only selected root classes + for (String rootClass : configuration.rootClasses.getValue()) + attemptClassAdditionByName(classLoader, classGraph, configuration, rootClass); + + } else { + // add all classes in the jar files to graph + for (File jarFile : jarFiles) + addJarToGraph(jarFile, classLoader, classGraph, configuration); + } + configuration.blacklistGlob.getValue().forEach(classGraph::blacklistClassGlob); + configuration.whitelistGlob.getValue().forEach(classGraph::whitelistClassGlob); + + if (configuration.hideOrphanedClasses.getValue()) + classGraph.hideOrphanedClasses(); + + return classGraph; + } + + /** + * Builds an array of URLs for the classpath from JAR files and directories. + * + * @param jarFiles list of JAR files to include + * @param classpathDirectories list of classpath directories to include + * @return array of URLs for the class loader + */ + private static URL[] getClasspathUrls(List jarFiles, List classpathDirectories) { + List urls = new ArrayList<>(); + + classpathDirectories.forEach(classpathDirectory -> { + try { + urls.add(classpathDirectory.toURI().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }); + + jarFiles.forEach((File file) -> { + try { + urls.add(file.toURI().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }); + + return urls.toArray(new URL[urls.size()]); + } + + /** + * Adds all classes from a JAR file to the class graph. + * + *

Iterates through all .class entries in the JAR and attempts to + * load each one into the graph.

+ * + * @param jarFile the JAR file to process + * @param classLoader the URLClassLoader for loading classes + * @param classGraph the graph to add classes to + * @param configuration the command-line configuration for debug output + * @throws IOException if the JAR cannot be read + * @throws ClassNotFoundException if a class cannot be found + */ + private static void addJarToGraph( + File jarFile, URLClassLoader classLoader, ClassGraph classGraph, CommandlineConfiguration configuration) + throws IOException, ClassNotFoundException { + + for (String className : getClassNamesFromJar(jarFile)) + attemptClassAdditionByName(classLoader, classGraph, configuration, className); + } + + /** + * Attempts to load and add a class to the graph by its name. + * + *

This method gracefully handles NoClassDefFoundError, which can occur + * when a class references other classes not present in the JAR.

+ * + * @param classLoader the URLClassLoader for loading classes + * @param classGraph the graph to add the class to + * @param configuration the command-line configuration for debug output + * @param className the fully qualified class name + * @throws ClassNotFoundException if the class cannot be found + */ + private static void attemptClassAdditionByName(URLClassLoader classLoader, ClassGraph classGraph, CommandlineConfiguration configuration, String className) throws ClassNotFoundException { + if (configuration.isDebug()) + System.out.println("Adding class to graph: " + className); + try { + classGraph.add(loadClassByName(classLoader, className)); + } catch (NoClassDefFoundError e) { + if (configuration.isDebug()) + System.out.println("Class definition was not found."); + // Sometimes referenced classes are not found in the same Jar. + // Let's ignore this and proceed with the classes that we have. + } + } + + /** + * Loads a class by its fully qualified name using the class loader. + * + * @param classLoader the URLClassLoader for loading classes + * @param className the fully qualified class name + * @return the loaded Class object + * @throws ClassNotFoundException if the class cannot be found + */ + private static Class loadClassByName(URLClassLoader classLoader, String className) throws ClassNotFoundException { + return Class.forName(className, true, classLoader); + } + + /** + * Extracts all class names from a JAR file. + * + *

Scans the JAR for .class entries and converts their paths to + * fully qualified class names.

+ * + * @param jarFile the JAR file to scan + * @return list of fully qualified class names + * @throws IOException if the JAR cannot be read + */ + public static List getClassNamesFromJar(File jarFile) throws IOException { + List result = new ArrayList<>(); + try ( + JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile)) + ) { + while (true) { + JarEntry jarEntry = jarInputStream.getNextJarEntry(); + if (jarEntry == null) + break; + + if (isClassFile(jarEntry)) + result.add(getClassNameFromFileName(jarEntry)); + } + + return result; + } + } + + /** + * Checks if a JAR entry is a Java class file. + * + * @param jarEntry the JAR entry to check + * @return true if the entry name ends with .class + */ + private static boolean isClassFile(JarEntry jarEntry) { + return jarEntry.getName().endsWith(".class"); + } + + /** + * Converts a JAR entry path to a fully qualified class name. + * + *

Converts path separators (/) to package separators (.) and + * removes the .class extension.

+ * + * @param jarEntry the JAR entry containing the class file path + * @return the fully qualified class name + */ + private static String getClassNameFromFileName(JarEntry jarEntry) { + String result = jarEntry.getName().replaceAll("/", "\\."); + return result.substring(0, result.lastIndexOf('.')); + } +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/TargetImageTypeParameter.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/TargetImageTypeParameter.java new file mode 100644 index 0000000..917be06 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/TargetImageTypeParameter.java @@ -0,0 +1,84 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.commandline; + +import eu.svjatoslav.commons.cli_helper.parameter_parser.Parameter; +import eu.svjatoslav.commons.string.String2; +import eu.svjatoslav.inspector.java.structure.TargetImageType; + +import java.util.Arrays; + +import static eu.svjatoslav.commons.cli_helper.parameter_parser.ArgumentCount.SINGLE; + +/** + * Command-line parameter type for specifying output image format. + * + *

This parameter accepts "svg" or "png" values and converts them + * to the corresponding {@link TargetImageType} enum values.

+ * + * @see TargetImageType + * @see CommandlineConfiguration + */ +public class TargetImageTypeParameter extends Parameter { + + /** + * Creates a target image type parameter with default SVG format. + * + *

The parameter accepts a single argument value: either "svg" or "png".

+ */ + public TargetImageTypeParameter(){ + super("Target image type. Default is: svg.", SINGLE); + } + + /** + * Describes the valid format options for this parameter. + * + *

Returns a comma-separated list of available image types.

+ * + * @return description string like "options: svg, png" + */ + @Override + public String describeFormat() { + String2 result = new String2(""); + + Arrays.stream(TargetImageType.values()) + .forEach(targetImageType -> result.appendWithSeparator(", ", targetImageType.fileExtension)); + + result.prepend("options: "); + + return result.toString(); + } + + /** + * Returns the parsed TargetImageType value from the command-line argument. + * + *

Converts the argument to uppercase and looks up the corresponding + * enum constant.

+ * + * @return the TargetImageType matching the argument value + */ + @Override + public TargetImageType getValue() { + return TargetImageType.valueOf(arguments.get(0).toUpperCase()); + } + + /** + * Validates that a value is a valid image type name. + * + * @param value the value to validate + * @return true if the value is "svg" or "png", false otherwise + */ + @Override + public boolean validate(String value) { + try { + TargetImageType.valueOf(value.toUpperCase()); + } catch (final IllegalArgumentException exception) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/commandline/package-info.java b/src/main/java/eu/svjatoslav/inspector/java/commandline/package-info.java new file mode 100644 index 0000000..a3a051c --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/commandline/package-info.java @@ -0,0 +1,15 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +/** + * Provides the command-line interface for JavaInspect. + * + *

This package contains classes for parsing command-line arguments + * and launching the class graph generation process.

+ * + * @see eu.svjatoslav.inspector.java.commandline.Main + * @see eu.svjatoslav.inspector.java.commandline.CommandlineConfiguration + */ +package eu.svjatoslav.inspector.java.commandline; \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java new file mode 100755 index 0000000..7e40e89 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java @@ -0,0 +1,836 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; + +/** + * Represents a single Java class for visualization in the class graph. + * + *

Class descriptors are the primary nodes in the visualization, capturing + * class metadata, fields, methods, inheritance relationships, and interface + * implementations. Each descriptor generates GraphViz DOT format output + * for rendering as an HTML-like table node with connection edges.

+ * + *

Classes are analyzed using Java reflection to extract:

+ *
    + *
  • Superclass relationships
  • + *
  • Implemented interfaces
  • + *
  • Declared fields and their types
  • + *
  • Methods and their return types
  • + *
  • Generic type information
  • + *
+ * + * @see ClassGraph + * @see FieldDescriptor + * @see MethodDescriptor + * @see GraphElement + */ +public class ClassDescriptor implements GraphElement, Comparable { + + /** + * Maximum number of incoming references to show for a class. + * + *

Classes with more than this number of references are drawn with + * thicker borders to indicate high coupling.

+ */ + private static final int MAX_REFERECNES_COUNT = 10; + + /** + * List of interfaces implemented by this class. + */ + final List interfaces = new ArrayList<>(); + + /** + * Map of field names to their descriptors. + */ + private final Map nameToFieldMap = new TreeMap<>(); + + /** + * Sorted set of method descriptors. + */ + private final SortedSet methods = new TreeSet<>(); + + /** + * The class graph that owns this descriptor. + */ + private final ClassGraph classGraph; + + /** + * Whether this class is an enum. + */ + boolean isEnum; + + /** + * Whether this class is an interface. + */ + boolean isInterface; + + /** + * Whether this class represents an array type. + */ + boolean isArray; + + /** + * The superclass descriptor, or null for Object or primitives. + */ + ClassDescriptor superClass; + + /** + * The fully qualified class name (e.g., "java.lang.String"). + */ + private String fullyQualifiedName; + + /** + * Color for incoming reference arrows to this class. + * + *

Assigned from the dark color palette to distinguish this class's + * incoming edges from others.

+ */ + private String distinctiveReferenceColor; + + /** + * Color for interface implementation arrows. + */ + private String interfaceColor; + + /** + * Color for superclass inheritance arrows. + */ + private String superClassColor; + + /** + * Whether this class should be rendered in the graph. + * + *

Classes can be hidden if they are system types, filtered by glob + * patterns, or have no interesting references.

+ */ + private boolean isShown = true; + + /** + * Count of field and method references pointing to this class. + * + *

Used to determine if the class should show its reference arrows.

+ */ + private int referencesCount = 0; + + /** + * Count of implementations for interface classes. + * + *

Only relevant for interfaces; counts how many classes implement this interface.

+ */ + private int implementationsCount = 0; + + /** + * Count of extensions for this class. + * + *

Counts how many classes extend this class as their superclass.

+ */ + private int extensionsCount = 0; + + /** + * The component type for array classes. + * + *

For example, for String[] this would be the String descriptor.

+ */ + private ClassDescriptor arrayComponent; + + /** + * Creates a class descriptor associated with a class graph. + * + * @param classGraph the graph that will contain this descriptor + */ + public ClassDescriptor(final ClassGraph classGraph) { + this.classGraph = classGraph; + } + + /** + * Analyzes a Java class using reflection to populate this descriptor. + * + *

This method extracts the class name, type information (enum, interface, array), + * declared fields, methods, superclass, and implemented interfaces.

+ * + * @param clazz the Java Class to analyze + */ + protected void analyzeClass(final Class clazz) { + + fullyQualifiedName = clazz.getName(); + + isArray = clazz.isArray(); + + if (isArray) { + final Class componentType = clazz.getComponentType(); + arrayComponent = getClassGraph().getOrCreateClassDescriptor( + componentType); + } + + // System.out.println("class: " + fullyQualifiedName); + + isEnum = clazz.isEnum(); + + isInterface = clazz.isInterface(); + + if (!isVisible()) + return; + + try { + indexFields(clazz.getDeclaredFields()); + indexFields(clazz.getFields()); + } catch (NoClassDefFoundError error) { + // TODO: better logging of this error + System.out.println(error.toString()); + } + + indexMethods(clazz); + + for (final Class interfaceClass : clazz.getInterfaces()) { + final ClassDescriptor interfaceClassDescriptor = getClassGraph() + .getOrCreateClassDescriptor(interfaceClass); + interfaceClassDescriptor.registerImplementation(); + interfaces.add(interfaceClassDescriptor); + } + + superClass = getClassGraph().getOrCreateClassDescriptor( + clazz.getSuperclass()); + if (superClass != null) + superClass.registerExtension(); + + } + + /** + * Determines whether incoming reference arrows should be shown for this class. + * + *

Classes with too many references are visually cluttered if all arrows + * are shown, so this method returns false above the threshold.

+ * + * @return true if reference count is within the display threshold + */ + protected boolean areReferencesShown() { + return referencesCount <= MAX_REFERECNES_COUNT; + } + + /** + * Appends DOT format edges for field references to other classes. + * + * @param result the StringBuffer to append to + */ + private void enlistFieldReferences(final StringBuffer result) { + if (nameToFieldMap.isEmpty()) + return; + + result.append("\n"); + result.append(" // field references to other classes\n"); + nameToFieldMap.forEach((fieldName, field) -> result.append(field.getDot())); + } + + /** + * Appends DOT format HTML rows for fields within the class node. + * + * @param result the StringBuffer to append to + */ + private void enlistFields(final StringBuffer result) { + if (nameToFieldMap.isEmpty()) + return; + + result.append("\n"); + result.append(" // fields:\n"); + + // enlist fields + for (final Map.Entry entry : nameToFieldMap + .entrySet()) + result.append(entry.getValue().getEmbeddedDot()); + } + + /** + * Appends DOT format edges for implemented interface relationships. + * + *

Interface relationships are shown as dotted forward arrows.

+ * + * @param result the StringBuffer to append to + */ + private void enlistImplementedInterfaces(final StringBuffer result) { + if (interfaces.isEmpty()) + return; + + result.append("\n"); + result.append(" // interfaces implemented by class: " + + fullyQualifiedName + "\n"); + + for (final ClassDescriptor interfaceDescriptor : interfaces) { + if (!interfaceDescriptor.isVisible()) + continue; + + if (!interfaceDescriptor.areReferencesShown()) + continue; + + result.append(" " + interfaceDescriptor.getGraphId() + " -> " + + getGraphId() + "[style=\"dotted\", color=\"" + + interfaceDescriptor.getInterfaceColor() + + "\", penwidth=10, dir=\"forward\"];\n"); + } + } + + /** + * Appends DOT format edges for method return type references. + * + * @param result the StringBuffer to append to + */ + private void enlistMethodReferences(final StringBuffer result) { + if (methods.isEmpty()) + return; + + result.append("\n"); + result.append(" // method references to other classes\n"); + for (final MethodDescriptor methodDescriptor : methods) + result.append(methodDescriptor.getDot()); + } + + /** + * Appends DOT format HTML rows for methods within the class node. + * + * @param result the StringBuffer to append to + */ + private void enlistMethods(final StringBuffer result) { + if (methods.isEmpty()) + return; + + result.append("\n"); + result.append(" // methods:\n"); + + // enlist methods + for (final MethodDescriptor methodDescriptor : methods) + result.append(methodDescriptor.getEmbeddedDot()); + } + + /** + * Appends DOT format edge for the superclass relationship. + * + *

Superclass arrows point from parent to child with thick styling.

+ * + * @param result the StringBuffer to append to + */ + private void enlistSuperClass(final StringBuffer result) { + if (superClass == null) + return; + + if (!superClass.isVisible()) + return; + + if (!superClass.areReferencesShown()) + return; + + result.append("\n"); + result.append(" // super class for: " + fullyQualifiedName + "\n"); + + result.append(" " + superClass.getGraphId() + " -> " + getGraphId() + + "[ color=\"" + superClass.getSuperClassColor() + + "\", penwidth=10, dir=\"forward\"];\n"); + } + + /** + * Generates the DOT format header for the class node. + * + *

This creates the HTML table structure with package name, parent class + * name (for nested classes), and the class name itself.

+ * + * @param result the StringBuffer to append to + */ + private void generateDotHeader(final StringBuffer result) { + result.append("\n"); + result.append("// Class: " + fullyQualifiedName + "\n"); + + result.append(" " + getGraphId() + "[label=<\n"); + + result.append("\n"); + result.append(" // class descriptor header\n"); + result.append(" \n"); + } + + /** + * Returns the HTML background color attribute for this class. + * + *

Enums have navajowhite2, interfaces have darkslategray1, + * regular classes have no background color.

+ * + * @return the bgcolor attribute string, or empty string for regular classes + */ + private String getBackgroundColor() { + String bgColor = ""; + + if (isEnum) + bgColor = "bgcolor=\"navajowhite2\""; + + if (isInterface) + bgColor = "bgcolor=\"darkslategray1\""; + + return bgColor; + } + + /** + * Returns the border width for this class node. + * + *

Classes with many references have thicker borders (4) to indicate + * high coupling, normal classes have thin borders (1).

+ * + * @return "4" for highly referenced classes, "1" otherwise + */ + private String getBorderWidth() { + + if (!areReferencesShown()) + return "4"; + return "1"; + } + + /** + * Returns the owning class graph. + * + * @return the ClassGraph instance that created this descriptor + */ + protected ClassGraph getClassGraph() { + return classGraph; + } + + /** + * Returns the simple class name, optionally with array indicator. + * + *

For nested classes, dollar signs are replaced with dots. + * For array classes, the component type name is returned instead.

+ * + * @param differentiateArray if true, append "[]" for array types + * @return the simple class name + */ + protected String getClassName(final boolean differentiateArray) { + // this is needed for nested classes + final String actualClassName = fullyQualifiedName.replace('$', '.'); + + String result; + if (isArray) { + // for arrays use array component instead of array class name + result = arrayComponent.fullyQualifiedName; + if (result.contains(".")) { + final int i = result.lastIndexOf('.'); + result = result.substring(i + 1); + } + } else { + final int i = actualClassName.lastIndexOf('.'); + result = actualClassName.substring(i + 1); + } + + if (differentiateArray) + if (isArray) + result += " []"; + + // this is needed for nested classes + // result = result.replace('$', '.'); + return result; + } + + /** + * Returns the distinctive color for incoming reference arrows. + * + *

Colors are assigned from the dark palette on first access.

+ * + * @return the GraphViz color name for this class's reference edges + */ + protected String getColor() { + if (distinctiveReferenceColor == null) + distinctiveReferenceColor = Utils.getNextDarkColor(); + + return distinctiveReferenceColor; + } + + /** + * Generates the complete DOT format representation for this class. + * + *

This creates the class node (HTML table) and all outgoing edges + * for fields, methods, interfaces, and superclass.

+ * + * @return DOT format string for the class, or empty string if not visible + */ + @Override + public String getDot() { + if (!isVisible()) + return ""; + + if (isArray) + return ""; + + final StringBuffer result = new StringBuffer(); + + generateDotHeader(result); + + enlistFields(result); + + enlistMethods(result); + + result.append("
" + + "" + getPackageName() + + "
"); + + final String parentClassesName = getParentClassesName(); + if (parentClassesName.length() > 0) + result.append("" + parentClassesName + + "
\n"); + + result.append("" + getClassName(false) + + "" + "
>, shape=\"none\"];\n"); + + enlistFieldReferences(result); + + enlistMethodReferences(result); + + enlistImplementedInterfaces(result); + + enlistSuperClass(result); + + return result.toString(); + } + + /** + * Returns null as classes are not embedded within other nodes. + * + *

This method is not applicable for class-level descriptors.

+ * + * @return null + */ + @Override + public String getEmbeddedDot() { + return null; + } + + /** + * Returns a field matching the given name, ignoring case. + * + *

Used to check if getter/setter methods correspond to existing fields.

+ * + * @param fieldToSearch the field name to search for (case insensitive) + * @return the matching FieldDescriptor, or null if not found + */ + protected FieldDescriptor getFieldIgnoreCase(final String fieldToSearch) { + + for (final String fieldName : nameToFieldMap.keySet()) + if (fieldToSearch.equalsIgnoreCase(fieldName)) + return nameToFieldMap.get(fieldName); + + return null; + } + + /** + * Returns the fully qualified class name. + * + * @return the fully qualified name (e.g., "java.lang.String") + */ + protected String getFullyQualifiedName() { + return fullyQualifiedName; + } + + /** + * Returns the GraphViz identifier for this class. + * + *

The ID is derived from the fully qualified name, with dots and + * special characters replaced with underscores.

+ * + * @return unique identifier in format "class_fully_qualified_name" + */ + @Override + public String getGraphId() { + + return "class_" + + fullyQualifiedName + .replace('.', '_') + .replace(";", "") + .replace("[[", "") + .replace("[L", "") + .replace("[[L", "") // array of arrays + .replace("[[[L", "") // array of arrays of arrays + .replace('$', '_'); + } + + /** + * Returns the color for interface implementation arrows. + * + * @return the GraphViz color name from the dark palette + */ + private String getInterfaceColor() { + if (interfaceColor == null) + interfaceColor = Utils.getNextDarkColor(); + + return interfaceColor; + } + + /** + * Creates or retrieves a field descriptor for a reflection Field. + * + *

If a descriptor for the field already exists, it is returned. + * Otherwise, a new descriptor is created, added to the map, and analyzed.

+ * + * @param field the Java reflection Field + * @return the FieldDescriptor for the field + */ + private FieldDescriptor getOrCreateFieldDescriptor(final Field field) { + + final String fieldName = field.getName(); + + if (nameToFieldMap.containsKey(fieldName)) + return nameToFieldMap.get(fieldName); + final FieldDescriptor newFieldDescriptor = new FieldDescriptor(this); + nameToFieldMap.put(fieldName, newFieldDescriptor); + + newFieldDescriptor.analyzeField(field); + + return newFieldDescriptor; + } + + /** + * Counts the total outgoing references from this class. + * + *

Includes method return types, field types, implemented interfaces, + * and superclass.

+ * + * @return the count of visible outgoing references + */ + private int getOutgoingReferencesCount() { + int result = 0; + + // count method references + for (final MethodDescriptor methodDescriptor : methods) + result += methodDescriptor.getOutsideVisibleReferencesCount(); + + // count field references + for (final FieldDescriptor fieldDescriptor : nameToFieldMap.values()) + result += fieldDescriptor.getOutsideVisibleReferencesCount(); + + // count implemented interfaces + for (final ClassDescriptor classDescriptor : interfaces) + if (classDescriptor.isVisible()) + result++; + + // count superclass + if (superClass != null) + if (superClass.isVisible()) + result++; + + return result; + } + + /** + * Returns the package name portion of the fully qualified name. + * + * @return the package name, or empty string for default package + */ + private String getPackageName() { + + final int i = fullyQualifiedName.lastIndexOf('.'); + + if (i == -1) + return ""; + + return fullyQualifiedName.substring(0, i).replace("[L", ""); + } + + /** + * Returns the parent class names for nested classes. + * + *

For nested classes like Outer.Inner, this returns "Outer".

+ * + * @return the parent class path, or empty string for non-nested classes + */ + private String getParentClassesName() { + int i = fullyQualifiedName.lastIndexOf('.'); + final String fullClassName = fullyQualifiedName.substring(i + 1); + + i = fullClassName.lastIndexOf('$'); + if (i == -1) + return ""; + final String parentClassesName = fullClassName.substring(0, i); + return parentClassesName.replace('$', '.'); + } + + /** + * Returns the color for superclass inheritance arrows. + * + * @return the GraphViz color name from the light palette + */ + private String getSuperClassColor() { + if (superClassColor == null) + superClassColor = Utils.getNextLightColor(); + + return superClassColor; + } + + /** + * Checks if this class has a field matching the given name, ignoring case. + * + * @param fieldToSearch the field name to search for (case insensitive) + * @return true if a matching field exists + */ + protected boolean hasFieldIgnoreCase(final String fieldToSearch) { + + for (final String fieldName : nameToFieldMap.keySet()) + if (fieldToSearch.equalsIgnoreCase(fieldName)) + return true; + + return false; + } + + /** + * Marks this class as hidden, excluding it from the graph output. + */ + private void hide() { + isShown = false; + } + + /** + * Hides this class if it has no incoming or outgoing references. + * + *

Orphaned classes with no connections add visual noise without + * providing useful information about relationships.

+ */ + protected void hideClassIfNoReferences() { + if (!isVisible()) + return; + + final int totalReferencesCount = getOutgoingReferencesCount() + + referencesCount + extensionsCount + implementationsCount; + + if (totalReferencesCount == 0) { + hide(); + return; + } + + } + + /** + * Adds all fields from an array to the field map. + * + * @param fields the array of Java reflection Fields to index + */ + private void indexFields(final Field[] fields) { + for (final Field field : fields) + getOrCreateFieldDescriptor(field); + } + + /** + * Analyzes and adds all public methods from a class. + * + * @param clazz the Java Class to extract methods from + */ + private void indexMethods(final Class clazz) { + for (final Method method : clazz.getMethods()) { + final MethodDescriptor methodDescriptor = new MethodDescriptor( + this, method.getName()); + + methods.add(methodDescriptor); + + methodDescriptor.analyze(method); + } + + } + + /** + * Determines whether this class should be included in the graph. + * + *

A class is hidden if it is:

+ *
    + *
  • A primitive or system data type
  • + *
  • In a system package (java.*, javax.*, sun.*)
  • + *
  • Filtered by blacklist/whitelist glob patterns
  • + *
  • An array of primitives
  • + *
  • Explicitly marked as hidden
  • + *
+ * + * @return true if the class should be rendered, false otherwise + */ + @Override + public boolean isVisible() { + + if (Utils.isSystemDataType(fullyQualifiedName)) + return false; + + if (Utils.isSystemPackage(fullyQualifiedName)) + return false; + + if (!getClassGraph().isClassShown(fullyQualifiedName)) + return false; + + if (isArray) + if (arrayComponent != null) + if (Utils.isSystemDataType(arrayComponent.fullyQualifiedName)) + // Do not show references to primitive data types in arrays. + // That is: there is no point to show reference to byte when + // we have class with byte array field. + return false; + + return isShown; + } + + /** + * Registers that another class extends this class. + */ + protected void registerExtension() { + extensionsCount++; + } + + /** + * Registers that another class implements this interface. + */ + protected void registerImplementation() { + implementationsCount++; + } + + /** + * Registers a field or method reference to this class. + */ + protected void registerReference() { + referencesCount++; + } + + /** + * Compares this descriptor to another for equality. + * + *

Equality is based on fully qualified name.

+ * + * @param o the object to compare + * @return true if the objects represent the same class + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ClassDescriptor)) return false; + + ClassDescriptor that = (ClassDescriptor) o; + + return getFullyQualifiedName().equals(that.getFullyQualifiedName()); + + } + + /** + * Returns a hash code based on the fully qualified name. + * + * @return hash code for this descriptor + */ + @Override + public int hashCode() { + return getFullyQualifiedName().hashCode(); + } + + /** + * Compares this descriptor to another for sorting. + * + *

Classes are sorted by fully qualified name.

+ * + * @param o the other descriptor to compare + * @return negative, zero, or positive based on name comparison + */ + @Override + public int compareTo(ClassDescriptor o) { + return fullyQualifiedName.compareTo(o.fullyQualifiedName); + } +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java new file mode 100755 index 0000000..8d2a759 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java @@ -0,0 +1,333 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +import eu.svjatoslav.commons.string.GlobMatcher; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.io.File.separator; +import static java.lang.System.getProperty; + +/** + * Central graph container for collecting and visualizing Java class relationships. + * + *

ClassGraph is the main entry point for JavaInspect. It collects classes + * through reflection, builds a graph of relationships, and generates GraphViz + * DOT format output that can be rendered to SVG or PNG images.

+ * + *

Typical usage:

+ *
+ * ClassGraph graph = new ClassGraph();
+ * graph.add(myObject);
+ * graph.add(MyClass.class);
+ * graph.setKeepDotFile(true);
+ * graph.generateGraph("MyVisualization");
+ * 
+ * + *

The graph can be configured with:

+ *
    + *
  • Target directory for output files
  • + *
  • Image format (SVG or PNG)
  • + *
  • Whitelist/blacklist glob patterns for filtering classes
  • + *
  • Option to hide orphaned classes with no connections
  • + *
+ * + * @see ClassDescriptor + * @see TargetImageType + */ +public class ClassGraph { + + /** + * Maps fully qualified class names to their descriptors. + * + *

This is the primary storage for all analyzed classes in the graph.

+ */ + private final Map fullyQualifiedNameToClassMap = new HashMap<>(); + + /** + * List of glob patterns for classes to exclude from the graph. + */ + private final List blacklistClassGlobs = new ArrayList<>(); + + /** + * List of glob patterns for classes to include in the graph. + * + *

If non-empty, only classes matching a whitelist pattern are shown.

+ */ + private final List whitelistClassGlobs = new ArrayList<>(); + + /** + * The output image format for generated graphs. + * + *

SVG is recommended for large diagrams; PNG for small ones.

+ */ + TargetImageType targetImageType = TargetImageType.SVG; + + /** + * Whether to keep the intermediate DOT file after rendering. + */ + private boolean keepDotFile; + + /** + * Directory where output files will be written. + * + *

Defaults to the current working directory.

+ */ + private File targetDirectory = new File(getProperty("user.dir") + separator); + + /** + * Creates an empty class graph ready to accept classes. + */ + public ClassGraph() { + } + + /** + * Adds objects or classes to the graph for analysis. + * + *

Each object's class is analyzed and added to the graph. + * If a Class object is passed, the class itself is added.

+ * + * @param objects objects or Class instances to add to the graph + * @return this ClassGraph instance for method chaining + */ + public ClassGraph add(final Object... objects) { + + if (objects != null) + for (final Object object : objects) + addObject(object); + + return this; + } + + /** + * Adds a single object's class to the graph. + * + *

If the object is a Class instance, that class is added directly. + * Otherwise, the object's runtime class is added.

+ * + * @param object the object or Class to add + */ + private void addObject(final Object object) { + if (object instanceof Class) + getOrCreateClassDescriptor((Class) object); + else + getOrCreateClassDescriptor(object.getClass()); + } + + /** + * Adds a glob pattern to the blacklist for filtering classes. + * + *

Classes matching any blacklist pattern are excluded from the graph. + * Glob patterns support wildcards: * matches any sequence, ? matches single characters.

+ * + *

Example patterns:

+ *
    + *
  • "java.*" - excludes all java standard library
  • + *
  • "*Test" - excludes all test classes
  • + *
+ * + * @param glob the glob pattern to add to the blacklist + */ + public void blacklistClassGlob(final String glob) { + blacklistClassGlobs.add(glob); + } + + /** + * Sets the output image format for graph rendering. + * + * @param targetImageType the image format (SVG or PNG) + */ + public void setTargetImageType(TargetImageType targetImageType) { + this.targetImageType = targetImageType; + } + + /** + * Generates the graph visualization as an image file. + * + *

This method:

+ *
    + *
  1. Writes the DOT file to the target directory
  2. + *
  3. Executes GraphViz (dot command) to render the image
  4. + *
  5. Deletes the DOT file unless keepDotFile is true
  6. + *
+ * + *

The GraphViz 'dot' executable must be available on the system PATH.

+ * + * @param resultFileName the base name for output files (extension added automatically) + */ + public void generateGraph(final String resultFileName) { + + final File dotFile = new File(targetDirectory, resultFileName + ".dot"); + final File imageFile = new File(targetDirectory, resultFileName + "." + targetImageType.fileExtension); + + try { + // write DOT file to disk + final PrintWriter out = new PrintWriter(dotFile, "UTF-8"); + out.write(getDot()); + out.close(); + + // execute GraphViz to visualize graph + try { + Runtime.getRuntime() + .exec(new String[]{"dot", + "-T" + targetImageType.fileExtension, + dotFile.getAbsolutePath(), + "-o", + imageFile.getAbsolutePath()}).waitFor(); + } catch (final InterruptedException ignored) { + } + + if (!keepDotFile) + // delete dot file + if (!dotFile.delete()) + throw new RuntimeException("Cannot delete file: " + dotFile.getAbsolutePath()); + + } catch (final IOException e) { + throw new RuntimeException("Unable to generate graph: " + e.getMessage(), e); + } + + } + + /** + * Generates the complete DOT format representation of the graph. + * + *

This creates a digraph with all class nodes and their relationships.

+ * + * @return the DOT format string for the entire graph + */ + private String getDot() { + final StringBuilder result = new StringBuilder(); + + result.append("digraph Java {\n"); + result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n"); + + for (final Map.Entry entry : fullyQualifiedNameToClassMap + .entrySet()) + result.append(entry.getValue().getDot()); + + result.append("}\n"); + + return result.toString(); + } + + /** + * Creates or retrieves a class descriptor for a Java class. + * + *

If a descriptor for the class already exists in the graph, it is returned. + * Otherwise, a new descriptor is created, added to the map, and analyzed.

+ * + * @param clazz the Java Class to get a descriptor for + * @return the ClassDescriptor for the class, or null if clazz is null + */ + protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) { + + if (clazz == null) + return null; + + final String classFullyQualifiedName = clazz.getName(); + + // reuse existing instance if possible + if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName)) + return fullyQualifiedNameToClassMap.get(classFullyQualifiedName); + + // create new class descriptor + final ClassDescriptor newClassDescriptor = new ClassDescriptor(this); + fullyQualifiedNameToClassMap.put(classFullyQualifiedName, + newClassDescriptor); + + newClassDescriptor.analyzeClass(clazz); + + return newClassDescriptor; + } + + /** + * Hides classes that have no incoming or outgoing references. + * + *

Orphaned classes add visual clutter without showing meaningful + * relationships. This method removes them from the graph output.

+ * + * @return this ClassGraph instance for method chaining + */ + public ClassGraph hideOrphanedClasses() { + + for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap + .values()) + classDescriptor.hideClassIfNoReferences(); + + return this; + } + + /** + * Checks whether a class should be shown based on filter patterns. + * + *

A class is hidden if it matches any blacklist pattern, or if + * a whitelist exists and it doesn't match any whitelist pattern.

+ * + * @param className the fully qualified class name to check + * @return true if the class passes the filter, false if it should be hidden + */ + protected boolean isClassShown(final String className) { + for (final String pattern : blacklistClassGlobs) + if (GlobMatcher.match(className, pattern)) + return false; + + if (!whitelistClassGlobs.isEmpty()) { + for (final String pattern : whitelistClassGlobs) + if (GlobMatcher.match(className, pattern)) + return true; + return false; + } + + return true; + } + + /** + * Sets whether to keep the intermediate DOT file after rendering. + * + *

Keeping the DOT file is useful for debugging or manual customization.

+ * + * @param keepDotFile true to keep the DOT file, false to delete it + * @return this ClassGraph instance for method chaining + */ + public ClassGraph setKeepDotFile(final boolean keepDotFile) { + this.keepDotFile = keepDotFile; + + return this; + } + + /** + * Sets the target directory for output files. + * + * @param targetDirectory the directory where DOT and image files will be written + * @return this ClassGraph instance for method chaining + */ + public ClassGraph setTargetDirectory(File targetDirectory) { + this.targetDirectory = targetDirectory; + return this; + } + + /** + * Adds a glob pattern to the whitelist for including classes. + * + *

If any whitelist patterns are defined, only classes matching at least + * one pattern will be shown in the graph.

+ * + * @param glob the glob pattern to add to the whitelist + * @return this ClassGraph instance for method chaining + */ + public ClassGraph whitelistClassGlob(final String glob) { + whitelistClassGlobs.add(glob); + return this; + } + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java new file mode 100755 index 0000000..dc1d20e --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java @@ -0,0 +1,249 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a single field within a Java class for visualization purposes. + * + *

Field descriptors capture field names, types, and generic type arguments, + * generating GraphViz DOT format output for both embedded display within class + * nodes and external reference edges.

+ * + * @see ClassDescriptor + * @see GraphElement + */ +public class FieldDescriptor implements GraphElement { + + /** + * The parent class that contains this field. + */ + private final ClassDescriptor parentClassDescriptor; + + /** + * Generic type arguments for parameterized field types. + * + *

For example, a field of type {@code List} would have + * String as a type argument.

+ */ + private final List typeArguments = new ArrayList<>(); + + /** + * The simple name of the field. + */ + private String name; + + /** + * The type descriptor for the field's declared type. + */ + private ClassDescriptor type; + + /** + * Whether this field is inherited from a parent class. + * + *

Inherited fields are typically hidden in visualizations.

+ */ + private boolean isInherited; + + /** + * Creates a field descriptor associated with a parent class. + * + * @param parent the class descriptor that contains this field + */ + public FieldDescriptor(final ClassDescriptor parent) { + parentClassDescriptor = parent; + } + + /** + * Analyzes a Java reflection Field to populate this descriptor. + * + *

This method extracts the field name, type, and generic type arguments, + * registering references with the class graph for later visualization.

+ * + * @param field the Java reflection Field to analyze + */ + public void analyzeField(final Field field) { + + if (!field.getDeclaringClass().getName() + .equals(parentClassDescriptor.getFullyQualifiedName())) + isInherited = true; + + name = field.getName(); + type = parentClassDescriptor.getClassGraph().getOrCreateClassDescriptor( + field.getType()); + type.registerReference(); + + final Type fieldGenericType = field.getGenericType(); + if (fieldGenericType instanceof ParameterizedType) { + final ParameterizedType fieldParameterizedGenericType = (ParameterizedType) fieldGenericType; + for (final Type type : fieldParameterizedGenericType.getActualTypeArguments()) + if (type instanceof Class) { + final Class aClass = (Class) type; + final ClassDescriptor genericTypeDescriptor = parentClassDescriptor + .getClassGraph().getOrCreateClassDescriptor(aClass); + genericTypeDescriptor.registerReference(); + typeArguments.add(genericTypeDescriptor); + } + + } + } + + /** + * Generates DOT format edges showing references from this field to other classes. + * + *

This creates the arrows pointing from the field to its type and + * generic type arguments in the class diagram.

+ * + * @return DOT format string for edges, or empty string if not visible + */ + @Override + public String getDot() { + + if (!isVisible()) + return ""; + + final StringBuilder result = new StringBuilder(); + + // describe associated types + for (final ClassDescriptor classDescriptor : typeArguments) + if (classDescriptor.isVisible()) + if (classDescriptor.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + classDescriptor.getGraphId() + "[label=\"" + name + + "\", color=\"" + classDescriptor.getColor() + + "\", style=\"bold\"];\n"); + + if (type == null) return result.toString(); + if (!type.isVisible()) + return result.toString(); + + // main type + boolean showLink = type.areReferencesShown(); + + if (type == parentClassDescriptor) + showLink = false; + + if (parentClassDescriptor.isEnum) + showLink = false; + + if (showLink) + result.append(" " + getGraphId() + " -> " + type.getGraphId() + + "[label=\"" + name + "\"," + " color=\"" + + type.getColor() + "\", style=\"bold\"];\n"); + + return result.toString(); + } + + /** + * Generates embedded DOT format HTML table row for display within the parent class node. + * + *

This creates a table row showing the field type and name inside + * the class box in the diagram.

+ * + * @return DOT format HTML table row, or empty string if not visible + */ + @Override + public String getEmbeddedDot() { + + if (!isVisible()) + return ""; + + final StringBuilder result = new StringBuilder(); + + result.append(" // " + name + "\n"); + if (parentClassDescriptor.isEnum && (type == parentClassDescriptor)) { + result.append(" "); + result.append(name + "\n"); + } else { + result.append(" "); + result.append(""); + result.append(describeType() + ""); + result.append(""); + result.append(name + "\n"); + } + return result.toString(); + } + + /** + * Returns a human-readable description of the field's type. + * + * @return the type name with array indicator if applicable, or "-null-" if type is null + */ + private String describeType() { + if (type == null) return "-null-"; + return type.getClassName(true); + } + + /** + * Returns the GraphViz identifier for this field. + * + *

The ID combines the parent class ID with the field name, + * allowing precise edge targeting in the diagram.

+ * + * @return unique identifier in format "classId:fieldName" + */ + @Override + public String getGraphId() { + return parentClassDescriptor.getGraphId() + ":" + name; + } + + /** + * Counts visible external references from this field. + * + *

This is used to determine whether a class has enough connections + * to be worth displaying.

+ * + * @return 1 if the field type is visible, 0 otherwise + */ + protected int getOutsideVisibleReferencesCount() { + + if (!isVisible()) + return 0; + + if (type != null) + if (type.isVisible()) + return 1; + + return 0; + } + + /** + * Returns the type descriptor for this field. + * + * @return the ClassDescriptor representing the field's type + */ + protected ClassDescriptor getType() { + return type; + } + + /** + * Determines whether this field should be included in the visualization. + * + *

Fields are hidden if they are inherited, contain dollar signs + * (compiler-generated), or are serialVersionUID constants.

+ * + * @return true if the field should be displayed, false otherwise + */ + @Override + public boolean isVisible() { + if (isInherited) + return false; + + if (name.contains("$")) + return false; + + return !name.equals("serialVersionUID"); + + } + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java b/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java new file mode 100755 index 0000000..b5873d4 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java @@ -0,0 +1,59 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +/** + * Common interface for elements that can be rendered as GraphViz DOT nodes. + * + *

All graph elements (classes, fields, methods) implement this interface + * to provide DOT format output for visualization.

+ * + * @see ClassDescriptor + * @see FieldDescriptor + * @see MethodDescriptor + */ +public interface GraphElement { + + /** + * Generates the DOT format representation for external references. + * + *

This method produces the edges (arrows) connecting this element + * to other elements in the graph.

+ * + * @return DOT format string for edges, or empty string if not visible + */ + String getDot(); + + /** + * Generates the embedded DOT representation for display within a parent node. + * + *

This method produces the HTML-like table cells that appear inside + * the parent class node in the graph.

+ * + * @return DOT format string for embedded content, or empty string if not visible + */ + String getEmbeddedDot(); + + /** + * Returns the unique GraphViz identifier for this element. + * + *

The ID is used to reference this element in edges and node definitions.

+ * + * @return unique identifier string in GraphViz format + */ + String getGraphId(); + + /** + * Determines whether this element should be included in the graph output. + * + *

Visibility is controlled by various factors including system package + * filtering, inheritance status, and reference count thresholds.

+ * + * @return true if the element should be rendered, false otherwise + */ + boolean isVisible(); + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java new file mode 100755 index 0000000..0324469 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java @@ -0,0 +1,319 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a single method within a Java class for visualization purposes. + * + *

Method descriptors capture method names, return types, and generic type + * information, generating GraphViz DOT format output for both embedded display + * within class nodes and external reference edges.

+ * + * @see ClassDescriptor + * @see GraphElement + */ +public class MethodDescriptor implements GraphElement, + Comparable { + + /** + * The simple name of the method. + */ + private final String methodName; + + /** + * The parent class that contains this method. + */ + private final ClassDescriptor parentClass; + + /** + * Type arguments extracted from generic return types. + * + *

For methods returning parameterized types like {@code List}, + * this captures the generic type arguments.

+ */ + private final List argumentTypes = new ArrayList<>(); + + /** + * The type descriptor for the method's return type. + */ + private ClassDescriptor returnType; + + /** + * Whether this method is inherited from a parent class or interface. + * + *

Inherited methods are typically hidden in visualizations to reduce noise.

+ */ + private boolean isInherited; + + /** + * Creates a method descriptor associated with a parent class. + * + * @param parent the class descriptor that contains this method + * @param methodName the simple name of the method + */ + public MethodDescriptor(final ClassDescriptor parent, + final String methodName) { + parentClass = parent; + this.methodName = methodName; + } + + /** + * Analyzes a Java reflection Method to populate this descriptor. + * + *

This method extracts the return type and generic type information, + * registering references with the class graph for later visualization.

+ * + * @param method the Java reflection Method to analyze + */ + public void analyze(final Method method) { + + if (!method.getDeclaringClass().getName() + .equals(parentClass.getFullyQualifiedName())) + isInherited = true; + + returnType = parentClass.getClassGraph().getOrCreateClassDescriptor( + method.getReturnType()); + returnType.registerReference(); + + final Type genericType = method.getGenericReturnType(); + if (genericType instanceof ParameterizedType) { + final ParameterizedType pt = (ParameterizedType) genericType; + for (final Type t : pt.getActualTypeArguments()) + if (t instanceof Class) { + final Class cl = (Class) t; + final ClassDescriptor classDescriptor = parentClass + .getClassGraph().getOrCreateClassDescriptor(cl); + classDescriptor.registerReference(); + argumentTypes.add(classDescriptor); + } + + } + } + + /** + * Compares this method descriptor to another object for equality. + * + *

Equality is based on method name, parent class, and argument types.

+ * + * @param o the object to compare + * @return true if the objects are equal + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MethodDescriptor)) return false; + + MethodDescriptor that = (MethodDescriptor) o; + + if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false; + if (parentClass != null ? !parentClass.equals(that.parentClass) : that.parentClass != null) return false; + return argumentTypes != null ? argumentTypes.equals(that.argumentTypes) : that.argumentTypes == null; + + } + + + /** + * Returns a hash code for this method descriptor. + * + * @return hash code based on method name, parent class, and argument types + */ + @Override + public int hashCode() { + int result = methodName != null ? methodName.hashCode() : 0; + result = 31 * result + (parentClass != null ? parentClass.hashCode() : 0); + result = 31 * result + (argumentTypes != null ? argumentTypes.hashCode() : 0); + return result; + } + + /** + * Generates DOT format edges showing references from this method to other classes. + * + *

This creates dotted arrows pointing from the method to its return type + * and generic type arguments in the class diagram.

+ * + * @return DOT format string for edges, or empty string if not visible + */ + @Override + public String getDot() { + + if (!isVisible()) + return ""; + + final StringBuilder result = new StringBuilder(); + + // describe associated types + for (final ClassDescriptor classDescriptor : argumentTypes) + if (classDescriptor.isVisible()) + if (classDescriptor.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + classDescriptor.getGraphId() + "[label=\"" + + methodName + "\", color=\"" + + classDescriptor.getColor() + + "\", style=\"dotted, bold\"];\n"); + + if (returnType == null) return result.toString(); + if (!returnType.isVisible()) return result.toString(); + + // main type + if (returnType.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + returnType.getGraphId() + "[label=\"" + methodName + + "\"," + " color=\"" + returnType.getColor() + + "\", style=\"dotted, bold\"];\n"); + + return result.toString(); + } + + /** + * Generates embedded DOT format HTML table row for display within the parent class node. + * + *

This creates a table row showing the return type and method name + * inside the class box in the diagram. Method names are displayed in red.

+ * + * @return DOT format HTML table row, or empty string if not visible + */ + @Override + public String getEmbeddedDot() { + if (!isVisible()) + return ""; + + final StringBuilder result = new StringBuilder(); + + result.append(" // " + methodName + "\n"); + + result.append(" " + + "" + describeReturnType() + + "" + "" + + getMethodLabel() + "\n"); + + return result.toString(); + } + + /** + * Returns a human-readable description of the method's return type. + * + * @return the return type name with array indicator if applicable, or "-null-" if null + */ + private String describeReturnType() { + if (returnType == null) return "-null-"; + + return returnType.getClassName(true); + } + + /** + * Returns the GraphViz identifier for this method. + * + *

The ID combines the parent class ID with the method name.

+ * + * @return unique identifier in format "classId:methodName" + */ + @Override + public String getGraphId() { + return parentClass.getGraphId() + ":" + methodName; + } + + /** + * Returns the label used for displaying the method in the diagram. + * + * @return the method name + */ + private String getMethodLabel() { + return methodName; + } + + /** + * Counts visible external references from this method. + * + *

This counts both the return type and any generic type arguments + * that are visible in the graph.

+ * + * @return the number of visible referenced types + */ + protected int getOutsideVisibleReferencesCount() { + int result = 0; + + if (returnType != null) + if (returnType.isVisible()) + result++; + + for (final ClassDescriptor classDescriptor : argumentTypes) + if (classDescriptor.isVisible()) + result++; + + return result; + } + + /** + * Determines whether this method should be included in the visualization. + * + *

Methods are hidden if they are:

+ *
    + *
  • Inherited from parent classes
  • + *
  • Common Object methods (wait, equals, toString, etc.)
  • + *
  • Enum methods (values, valueOf, etc.) for enum classes
  • + *
  • Getter/setter methods that correspond to existing fields
  • + *
+ * + * @return true if the method should be displayed, false otherwise + */ + @Override + public boolean isVisible() { + + // hide inherited methods + if (isInherited) + return false; + + // hide common object methods + if (Utils.isCommonObjectMethod(methodName)) + return false; + + // hide common Enumeration methods + if (parentClass.isEnum && Utils.isEnumMethod(methodName)) + return false; + + // hide get/set methods for the field of the same name + if (methodName.startsWith("get") || methodName.startsWith("set")) + if (parentClass.hasFieldIgnoreCase(methodName.substring(3))) + return false; + + // hide is methods for the boolean field of the same name + if (methodName.startsWith("is")) { + final FieldDescriptor field = parentClass + .getFieldIgnoreCase(methodName.substring(2)); + if (field != null) + if ("boolean".equals(field.getType().getFullyQualifiedName())) + return false; + } + + return true; + + } + + /** + * Compares this method descriptor to another for sorting purposes. + * + *

Methods are sorted primarily by name, then by parent class.

+ * + * @param that the other method descriptor to compare + * @return negative if this comes before that, positive if after, zero if equal + */ + @Override + public int compareTo(MethodDescriptor that) { + if (this == that) return 0; + + int comparisonResult = methodName.compareTo(that.methodName); + if (comparisonResult != 0) return comparisonResult; + + return parentClass.compareTo(that.parentClass); + } +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/TargetImageType.java b/src/main/java/eu/svjatoslav/inspector/java/structure/TargetImageType.java new file mode 100644 index 0000000..80e7fc9 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/TargetImageType.java @@ -0,0 +1,48 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +/** + * Supported output image formats for class graph visualization. + * + *

JavaInspect uses GraphViz to generate visual representations of + * class relationships. This enum defines the available output formats.

+ * + * @see ClassGraph#setTargetImageType(TargetImageType) + */ +public enum TargetImageType { + + /** + * Portable Network Graphics format. + * + *

A raster image format suitable for embedding in documents + * and web pages where scalability is not required.

+ */ + PNG("png"), + + /** + * Scalable Vector Graphics format. + * + *

A vector image format that scales infinitely without quality loss, + * ideal for large class diagrams and high-resolution displays.

+ */ + SVG("svg"); + + /** + * The file extension used for this image format. + */ + public final String fileExtension; + + /** + * Creates a target image type with the specified file extension. + * + * @param fileExtension the file extension without the leading dot + */ + TargetImageType(String fileExtension) { + this.fileExtension = fileExtension; + } + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java b/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java new file mode 100755 index 0000000..0419aa8 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java @@ -0,0 +1,251 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +package eu.svjatoslav.inspector.java.structure; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class providing filtering and styling helpers for class graph generation. + * + *

This class maintains static collections of system data types, common methods, + * system packages, and color palettes used throughout the visualization process.

+ * + *

All methods are static and the class is not intended to be instantiated.

+ * + * @see ClassDescriptor + * @see MethodDescriptor + */ +public class Utils { + + /** + * List of primitive and system data type names to exclude from visualization. + */ + private static final List systemDataTypes = new ArrayList<>(); + + /** + * List of common {@link Object} method names to hide in method listings. + */ + private static final List commonObjectMethods = new ArrayList<>(); + + /** + * List of system package prefixes to exclude from visualization. + */ + private static final List systemPackages = new ArrayList<>(); + + /** + * Palette of dark colors for reference edges (incoming arrows). + */ + private static final List darkColors = new ArrayList<>(); + + /** + * Palette of light colors for inheritance edges (superclass arrows). + */ + private static final List lightColors = new ArrayList<>(); + + /** + * List of enum-specific method names to hide for enum classes. + */ + private static final List enumMethods = new ArrayList<>(); + + /** + * Current index in the dark color palette for cyclic selection. + */ + private static int lastChosenDarkColor = -1; + + /** + * Current index in the light color palette for cyclic selection. + */ + private static int lastChosenLightColor = -1; + + /** + * Static initializer that populates all filter and color lists. + */ + static { + initEnumMethods(); + initSystemDataTypes(); + initDarkColors(); + initLightColors(); + initCommonObjectMethods(); + initSystemPackages(); + } + + /** + * Returns the next color from the dark color palette. + * + *

Colors are selected cyclically, wrapping around to the first color + * after the last one has been used.

+ * + * @return the name of the next dark color for GraphViz styling + */ + protected static String getNextDarkColor() { + lastChosenDarkColor++; + if (lastChosenDarkColor >= darkColors.size()) + lastChosenDarkColor = 0; + + return darkColors.get(lastChosenDarkColor); + } + + /** + * Returns the next color from the light color palette. + * + *

Colors are selected cyclically, wrapping around to the first color + * after the last one has been used.

+ * + * @return the name of the next light color for GraphViz styling + */ + protected static String getNextLightColor() { + lastChosenLightColor++; + if (lastChosenLightColor >= lightColors.size()) + lastChosenLightColor = 0; + + return lightColors.get(lastChosenLightColor); + } + + /** + * Populates the list of common Object methods to filter out. + * + *

These methods (wait, equals, toString, etc.) are inherited by all + * objects and typically add noise to class diagrams.

+ */ + private static void initCommonObjectMethods() { + commonObjectMethods.add("wait"); + commonObjectMethods.add("equals"); + commonObjectMethods.add("toString"); + commonObjectMethods.add("hashCode"); + commonObjectMethods.add("notify"); + commonObjectMethods.add("notifyAll"); + commonObjectMethods.add("getClass"); + } + + /** + * Populates the dark color palette for reference edges. + * + *

Dark colors are used for incoming reference arrows to distinguish + * them from inheritance relationships.

+ */ + protected static void initDarkColors() { + darkColors.add("antiquewhite4"); + darkColors.add("blueviolet"); + darkColors.add("brown4"); + darkColors.add("chartreuse4"); + darkColors.add("cyan4"); + darkColors.add("deeppink1"); + darkColors.add("deepskyblue3"); + darkColors.add("firebrick1"); + darkColors.add("goldenrod3"); + darkColors.add("gray0"); + } + + /** + * Populates the list of enum-specific methods to filter out. + * + *

These methods (values, valueOf, name, etc.) are present in all + * enum classes and are typically not relevant for visualization.

+ */ + private static void initEnumMethods() { + enumMethods.add("values"); + enumMethods.add("valueOf"); + enumMethods.add("name"); + enumMethods.add("compareTo"); + enumMethods.add("valueOf"); + enumMethods.add("getDeclaringClass"); + enumMethods.add("ordinal"); + } + + /** + * Populates the light color palette for inheritance edges. + * + *

Light colors are used for superclass arrows to visually distinguish + * inheritance relationships from field/method references.

+ */ + private static void initLightColors() { + lightColors.add("olivedrab2"); + lightColors.add("peachpuff2"); + lightColors.add("seagreen1"); + lightColors.add("violet"); + lightColors.add("cyan"); + lightColors.add("orange"); + } + + /** + * Populates the list of primitive and system data types to filter out. + * + *

These types (int, long, boolean, etc.) are fundamental and do not + * represent interesting relationships in class diagrams.

+ */ + private static void initSystemDataTypes() { + systemDataTypes.add("void"); + systemDataTypes.add("int"); + systemDataTypes.add("long"); + systemDataTypes.add("float"); + systemDataTypes.add("double"); + systemDataTypes.add("boolean"); + systemDataTypes.add("char"); + systemDataTypes.add("short"); + systemDataTypes.add("byte"); + } + + /** + * Populates the list of system package prefixes to filter out. + * + *

Classes from these packages (java.*, javax.*, sun.*) are standard + * library classes and typically excluded from application diagrams.

+ */ + private static void initSystemPackages() { + systemPackages.add("java."); + systemPackages.add("javax."); + systemPackages.add("sun."); + } + + /** + * Checks if a method name is a common Object method. + * + * @param name the method name to check + * @return true if the method is a common Object method like equals or toString + */ + protected static boolean isCommonObjectMethod(final String name) { + return commonObjectMethods.contains(name); + } + + /** + * Checks if a method name is an enum-specific method. + * + * @param name the method name to check + * @return true if the method is an enum method like values or valueOf + */ + protected static boolean isEnumMethod(final String name) { + return enumMethods.contains(name); + } + + /** + * Checks if a type name is a primitive or system data type. + * + * @param name the fully qualified type name to check + * @return true if the type is a primitive like int, boolean, or void + */ + protected static boolean isSystemDataType(final String name) { + return systemDataTypes.contains(name); + } + + /** + * Checks if a class belongs to a system package. + * + *

System packages include java.*, javax.*, and sun.* prefixes.

+ * + * @param name the fully qualified class name to check + * @return true if the class is from a system package + */ + protected static boolean isSystemPackage(final String name) { + + for (final String packagePrefix : systemPackages) + if (name.startsWith(packagePrefix)) + return true; + + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/package-info.java b/src/main/java/eu/svjatoslav/inspector/java/structure/package-info.java new file mode 100755 index 0000000..6eab749 --- /dev/null +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/package-info.java @@ -0,0 +1,18 @@ +/* + * JavaInspect - Utility to visualize java software. + * This project is released under Creative Commons Zero (CC0) license. + */ + +/** + * Provides classes for inspecting Java application structure through runtime reflection. + * + *

This package contains the core classes that traverse class references, + * extract field and method information, and generate GraphViz DOT format + * visualizations of Java class relationships.

+ * + * @see eu.svjatoslav.inspector.java.structure.ClassGraph + * @see eu.svjatoslav.inspector.java.structure.ClassDescriptor + * @see eu.svjatoslav.inspector.java.structure.FieldDescriptor + * @see eu.svjatoslav.inspector.java.structure.MethodDescriptor + */ +package eu.svjatoslav.inspector.java.structure; \ No newline at end of file diff --git a/usage examples/demo project/.gitignore b/usage examples/demo project/.gitignore new file mode 100644 index 0000000..49ea519 --- /dev/null +++ b/usage examples/demo project/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/target/ +/example.svg +/*.iml \ No newline at end of file diff --git a/usage examples/demo project/pom.xml b/usage examples/demo project/pom.xml new file mode 100644 index 0000000..6a16ce8 --- /dev/null +++ b/usage examples/demo project/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + eu.svjatoslav + javainspect-demo + 1.0-SNAPSHOT + jar + JavaInspect demo + Demonstration project for JavaInspect utility + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + UTF-8 + + + + + + + + eu.svjatoslav + javainspect + 1.7-SNAPSHOT + + + + + + svjatoslav.eu + Svjatoslav repository + http://www2.svjatoslav.eu/maven/ + + + diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/RenderUsingReflection.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/RenderUsingReflection.java new file mode 100755 index 0000000..d471429 --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/RenderUsingReflection.java @@ -0,0 +1,27 @@ +/* + * JavaInspect - Utility to visualize java software + * Copyright (C) 2013-2020, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU Lesser General Public License + * or later as published by the Free Software Foundation. + */ + +package eu.svjatoslav.inspector.java.structure.example; + +import eu.svjatoslav.inspector.java.structure.ClassGraph; +import eu.svjatoslav.inspector.java.structure.example.torender.SampleClass; +import eu.svjatoslav.inspector.java.structure.example.torender.SampleClass2; + +public class RenderUsingReflection { + + /** + * If you run this method using IDE, then example.svg file shall appear in project root directory. + */ + public static void main(final String[] args) { + + new ClassGraph().add(SampleClass.class, SampleClass2.class) + .generateGraph("example"); + } + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectReturnedByMethod.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectReturnedByMethod.java new file mode 100755 index 0000000..143ab77 --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectReturnedByMethod.java @@ -0,0 +1,5 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public class ObjectReturnedByMethod { + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectVisibleAsClassField.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectVisibleAsClassField.java new file mode 100755 index 0000000..db5b5cc --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/ObjectVisibleAsClassField.java @@ -0,0 +1,5 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public class ObjectVisibleAsClassField { + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass.java new file mode 100755 index 0000000..9720c44 --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass.java @@ -0,0 +1,11 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public class SampleClass extends SampleSuperClass { + + ObjectVisibleAsClassField sampleClassField; + + public ObjectReturnedByMethod sampleMethod() { + return new ObjectReturnedByMethod(); + } + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass2.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass2.java new file mode 100644 index 0000000..a2eba71 --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleClass2.java @@ -0,0 +1,5 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public class SampleClass2 extends SampleSuperClass { + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleEnum.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleEnum.java new file mode 100755 index 0000000..ee8bf9e --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleEnum.java @@ -0,0 +1,7 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public enum SampleEnum { + + ONE, TWO, THREE, FOUR + +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleInterface.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleInterface.java new file mode 100755 index 0000000..648327f --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleInterface.java @@ -0,0 +1,5 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public interface SampleInterface { + SampleEnum getSomeValue(); +} diff --git a/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleSuperClass.java b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleSuperClass.java new file mode 100755 index 0000000..9230509 --- /dev/null +++ b/usage examples/demo project/src/main/java/eu/svjatoslav/inspector/java/structure/example/torender/SampleSuperClass.java @@ -0,0 +1,10 @@ +package eu.svjatoslav.inspector.java.structure.example.torender; + +public class SampleSuperClass implements SampleInterface { + + @Override + public SampleEnum getSomeValue() { + return SampleEnum.ONE; + } + +} diff --git a/usage examples/demo project/tools/open with IntelliJ IDEA b/usage examples/demo project/tools/open with IntelliJ IDEA new file mode 100755 index 0000000..1f82875 --- /dev/null +++ b/usage examples/demo project/tools/open with IntelliJ IDEA @@ -0,0 +1,6 @@ +#!/bin/bash + +cd "${0%/*}" + +cd .. +idea . -- 2.20.1