| Requirement | Version | Notes |
|---|---|---|
| Java (JDK) | 21+ | OpenJDK/Temurin recommended |
| Gradle | 8.6+ | Wrapper included (./gradlew) |
| Git | Any recent | For source control |
| IDE (recommended) | IntelliJ IDEA or Eclipse | Java 21 support required |
# Clone repository
git clone https://github.com/Denomas/freemind-ce.git
cd freemind-ce
# Build and run using Make (recommended)
make build # Compile + test
make run # Run FreeMind CE
make help # Show all available targetsThe project includes a cross-platform Makefile that auto-detects JAVA_HOME and wraps Gradle with the correct flags. It supports macOS (Homebrew/MacPorts), Linux (apt/dnf/SDKMAN), and Windows (WSL/Git Bash). Use make help to see all targets:
| Target | Description |
|---|---|
| Development | |
make build |
Build the project (compile + test) |
make run |
Run FreeMind CE |
make debug |
Run in debug mode (attach debugger on port 5005) |
make test |
Run tests only |
make coverage |
Run tests with JaCoCo coverage report |
make check |
Build + all quality checks |
make clean |
Clean all build artifacts |
make jaxb |
Regenerate JAXB classes from XSD schema |
make javadoc |
Generate API documentation |
| Packaging | |
make package |
Build native package for current OS (auto-detect) |
make package-mac |
Build macOS DMG package |
make package-win |
Build Windows EXE installer |
make package-linux |
Build Linux DEB package |
make dist-zip |
Create distribution ZIP archive |
make install-dist |
Create local distribution layout |
| General | |
make info |
Show detected Java and system info |
make help |
Show this help message |
To override Java detection: JAVA_HOME=/path/to/jdk make build
For cases where you need direct Gradle access (CI, IDE integration, advanced options):
| Command | Purpose |
|---|---|
./gradlew build |
Full compilation, testing, packaging |
./gradlew :freemind:run |
Run application with JVM args |
./gradlew test |
Run all unit tests |
./gradlew :freemind:generateJaxb |
Generate JAXB classes from XSD |
./gradlew :freemind:jar |
Build main JAR |
./gradlew :freemind:installDist |
Create distribution layout |
./gradlew :freemind:distZip |
Create distribution ZIP |
./gradlew :freemind:jpackageMac |
Create macOS .dmg |
./gradlew :freemind:jpackageWin |
Create Windows .exe |
./gradlew :freemind:jpackageLinux |
Create Linux .deb |
./gradlew :freemind:prepareMacDist |
Prepare macOS key mappings |
./gradlew javadoc |
Generate API documentation |
Important: Always use
--no-configuration-cacheflag with raw Gradle commands. The Makefile handles this automatically.
-Xms64m -Xmx512m -Xss8M
-Dapple.laf.useScreenMenuBar=true
--add-opens=java.desktop/java.awt=ALL-UNNAMED
--add-opens=java.desktop/java.awt.event=ALL-UNNAMED
--add-opens=java.desktop/javax.swing=ALL-UNNAMED
--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
:freemind → Main application
:freemind:plugins:svg → SVG/PDF export
:freemind:plugins:script → Groovy scripting
:freemind:plugins:map → OpenStreetMap viewer
:freemind:plugins:search → Full-text search
:freemind:plugins:help → Help system
:freemind:plugins:contextgraph → Context graph export
:freemind:plugins:collaboration:socket → Real-time collaboration
freemind/
├── freemind/ → Main Java sources (3 srcDirs)
│ ├── freemind/ → Core application packages
│ ├── accessories/ → Accessory/utility classes
│ └── de/ → German-specific classes
├── tests/ → Test sources (JUnit + jqwik)
├── images/ → Icons and images (resources)
└── doc/ → Template .mm files (resources)
| File | Purpose | Location |
|---|---|---|
freemind.properties |
Default application settings | freemind/ |
auto.properties |
User overrides | ~/.freemind/ |
patterns.xml |
Node styling patterns | freemind/ |
mindmap_menus.xml |
Menu structure definition | freemind/ |
freemind.xsd |
Mind map file format schema | freemind/ |
freemind_actions.xsd |
Action (undo/redo) schema | freemind/ (root) |
Resources_*.properties |
Language resource bundles | freemind/freemind/ |
# Using Make (recommended)
make test # Unit tests only
make test-gui # GUI tests only
make coverage # Tests + JaCoCo coverage report
# Using Gradle directly
./gradlew test --no-configuration-cache # Unit tests
./gradlew testGui --no-configuration-cache # GUI tests
./gradlew test --no-configuration-cache --info # Verbose output- JUnit 4 test classes (
extends TestCase) running on JUnit 5 vintage engine - GUI tests: AssertJ Swing with
GuiTestBasebase class,@Tag("gui"), automatic screenshots - Property-based: jqwik (sample size 1000, tries 100, seed 12345 — reproducible)
- Test base:
FreeMindTestBaseprovides headless FreeMind context viaHeadlessFreeMind
| Directory/File | Purpose |
|---|---|
tests/freemind/gui/ |
22 GUI test classes (AssertJ Swing) |
tests/freemind/property/ |
Property-based tests (jqwik) |
tests/freemind/fuzz/ |
Fuzz tests |
tests/freemind/findreplace/ |
Search/replace tests |
tests/freemind/unicode/ |
Unicode handling tests |
FreeMindTestBase.java |
Unit test base class |
GuiTestBase.java |
GUI test base class (robot, screenshots) |
MarshallerTests.java |
JAXB XML serialization |
LayoutTests.java |
UI layout verification |
TransformTest.java |
XSLT transformation |
CollaborationTests.java |
Collaboration module |
ExportTests.java |
Export functionality |
ContextGraphExportTest.java |
Context graph plugin |
HtmlConversionTests.java |
HTML export |
StandaloneMapTests.java |
Standalone map operations |
Dependency vulnerability scanning catches known CVEs in project dependencies before they reach production.
# Quick scan — Grype (requires: mise install grype)
make audit # ~30 seconds, fails on High+ with known fix
# Full report — OWASP Dependency-Check (Gradle plugin)
make audit-full # ~5 minutes, HTML report
open freemind/build/reports/dependency-check-report.html| Source | Examples |
|---|---|
| Gradle dependencies | jsoup, Batik, FOP, Lucene, Logback, JUnit |
Tracked JARs (lib/) |
jortho.jar, SimplyHTML.jar, bindings.jar |
Plugin JARs (plugins/*/) |
JMapViewer.jar, jhall.jar, groovy-all.jar |
| Build tools (non-runtime) | PMD, SpotBugs, JaCoCo |
No external API dependency for security tooling. If a tool runs as a local CLI, we use the CLI — not cloud dashboards or paid services. All scanning runs offline after initial database download.
Weekly security-scan.yml runs Grype + Trivy + OWASP on GitHub Actions with SARIF upload to the Security tab. This catches anything missed locally and provides audit trail.
Full documentation: CONTRIBUTING.md — Security Audit
Static analysis tools (PMD + SpotBugs), configuration, reports, and the early detection chain are documented in one place:
CONTRIBUTING.md — Static Analysis — Tools, config files, report locations, viewing commands, early detection chain.
| Remote | URL | Purpose |
|---|---|---|
origin |
https://github.com/Denomas/freemind-ce.git |
Primary repository (push/pull) |
upstream |
git://git.code.sf.net/p/freemind/code |
Original FreeMind on SourceForge (read-only) |
- Branch:
main— trunk-based development, all work here - Tracking:
maintracksorigin/main - Releases: Tag
v*.*.*onmaintriggers GitHub Actions release workflow
CI pipeline details, path filtering, test matrix, workflows, and packaging are documented in one place:
docs/contributor-workflows.md — Section 6 — CI flow diagrams, path filtering, doc-only detection, release gating.
docs/merge-release-safety.md — Merge protocol, release checklist, dependency updates.
The original Ant build system (freemind/build.xml) is preserved for reference but Gradle is the primary build system:
- Ant build targets Java 21 (
java_source_version=21) - Contains macOS
.appbundle creation scripts - Plugin builds:
build_svg.xml,build_map.xml, etc.
Note: Ant build references JiBX (legacy XML binding). The Gradle build uses JAXB 2.3.9 instead. Use Gradle for all development.
Dependencies are managed in freemind/build.gradle.kts with version variables:
jaxbImplVersion = "2.3.9"/jaxbApiVersion = "2.3.1"batikVersion = "1.19"fopVersion = "2.11"flatlafVersion = "3.7"jgoodiesFormsVersion = "1.8.0"/jgoodiesCommonVersion = "1.8.1"junitVersion = "4.13.2"
Repositories: Maven Central + JitPack
The project includes Serena configuration for LSP-powered semantic code analysis. The config file .serena/project.yml is versioned in the repository.
Prerequisites: uv (Python package manager)
# Add Serena MCP server to Claude Code
claude mcp add serena -- uvx --from git+https://github.com/oraios/serena \
serena start-mcp-server --context=claude-code --project-from-cwd
# Index the codebase (creates LSP cache for fast symbol lookup)
uvx --from git+https://github.com/oraios/serena serena project index .
# Verify everything works
uvx --from git+https://github.com/oraios/serena serena project health-check .| File | Purpose | Versioned |
|---|---|---|
.serena/project.yml |
Project config (language, encoding, ignored paths) | Yes |
.serena/project.local.yml |
Local overrides (developer-specific) | No (.gitignore) |
~/.serena/serena_config.yml |
Global Serena config (backend, dashboard, timeouts) | No |
.serena/memories/ |
Project-specific AI memories | No (.gitignore) |
For Java 21 support, add to ~/.serena/serena_config.yml:
ls_specific_settings:
java:
gradle_java_home: "/path/to/your/java-21-home"On macOS with Homebrew: /opt/homebrew/Cellar/openjdk@21/21.0.10/libexec/openjdk.jdk/Contents/Home
Re-index after major codebase changes (new files, moved packages, renamed classes):
uvx --from git+https://github.com/oraios/serena serena project index .- Create directory under
freemind/plugins/<name>/ - Create
build.gradle.ktswithcompileOnly(project(":freemind"))dependency - Add
include(":freemind:plugins:<name>")tosettings.gradle.kts - Create plugin registration XML file
- Implement hook class extending appropriate adapter
Edit freemind/mindmap_menus.xml - declarative menu hierarchy.
- Create Actor class in
freemind/modes/mindmapmode/actions/ - Define XML element in
freemind_actions.xsd - Register in
MindMapController
Create/edit Resources_<locale>.properties in freemind/freemind/