From 953f01a19c2f5bd8d2c487e4cf09e693baa70cf1 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Thu, 12 Nov 2026 07:18:59 +0100 Subject: [PATCH] Bootstrap Neitzel FX Designer repository foundation --- .gitattributes | 6 + .gitignore | 14 ++ .mvn/wrapper/maven-wrapper.properties | 5 + AGENTS.md | 9 + README.md | 36 ++++ THIRD-PARTY-NOTICES.md | 5 + docs/initial-project-contract.md | 131 ++++++++++++ docs/provenance.md | 11 + docs/repository-bootstrap-plan.md | 81 +++++++ mvnw | 295 ++++++++++++++++++++++++++ mvnw.cmd | 189 +++++++++++++++++ pom.xml | 50 +++++ scripts/check-bootstrap.py | 23 ++ 13 files changed, 855 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 AGENTS.md create mode 100644 README.md create mode 100644 THIRD-PARTY-NOTICES.md create mode 100644 docs/initial-project-contract.md create mode 100644 docs/provenance.md create mode 100644 docs/repository-bootstrap-plan.md create mode 100755 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 scripts/check-bootstrap.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ba049f8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +* text=auto +*.sh text eol=lf +mvnw text eol=lf +mvnw.cmd text eol=crlf +*.md text eol=lf +*.py text eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37e1326 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Build output and local designer state +**/target/ +**/build/ +.gradle/ +.neitzel-fx-designer/ +# IDE and machine-local settings +.idea/ +*.iml +.DS_Store +.env +.env.* +!.env.example +__pycache__/ +*.py[cod] diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..e02115f --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,5 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip + +distributionSha256Sum=0d7125e8c91097b36edb990ea5934e6c68b4440eef4ea96510a0f6815e7eeadb diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..73cd745 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,9 @@ +# NeitzelFXDesigner + +Read [README.md](README.md) before changes. For architecture, configuration, build snapshots, preview API or worker work, read [the initial contract](docs/initial-project-contract.md). For sequencing and acceptance, read [the bootstrap plan](docs/repository-bootstrap-plan.md). Decision history is indexed in [provenance](docs/provenance.md). + +This is an independent repository. Confirm its Git root before staging or committing. After the initial main bootstrap, use short-lived `feature/*` branches; follow the enclosing workspace catalog's landing policy. Preserve unrelated workspace and NeitzelLib changes. + +Run `python3 scripts/check-bootstrap.py` for the current repository foundation. As implementation appears, add relevant build/regression checks and document them in README. Treat POM-only success as foundation validation, not application or plugin qualification. + +Keep Kit/IntelliJ dependencies out of application-facing contracts and the preview API. Run application code only in target workers. Establish Java bytecode baselines per module instead of inheriting the host runtime accidentally. Public APIs and release compatibility require evidence from real fixtures. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ab87369 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Neitzel FX Designer + +Shared Scene Builder Kit designer for NeitzelLib FX, with planned standalone and IntelliJ hosts. + +## Current state + +This initial repository contains the accepted contracts, bootstrap plan, project instructions and a pinned Maven build foundation (`de.neitzel.fxdesigner:neitzel-fx-designer:0.1.0-SNAPSHOT`). It currently has **no application sources, implemented modules, runnable designer or packaged IntelliJ plugin**. The root POM validates the build environment; it does not yet build a UI. The module layout in the contract is planned work. + +The corrected NeitzelLib dependency is not yet pinned: its Component builder fix must be integrated separately and the first containing release verified. NeitzelLib sources and prototype implementations are not copied here. + +## Validate the foundation + +Requirements: JDK 21 or newer, Python 3.10 or newer, and network access on the first Maven/dependency download. Select the intended JDK through `JAVA_HOME`. + +```sh +python3 scripts/check-bootstrap.py +``` + +This runs Maven's clean/verify lifecycle through the pinned wrapper and validates local documentation links and illustrative JSON. Maven is pinned to **3.9.11** using Apache Maven Wrapper **3.3.4**. No system Maven installation is needed for this command. On Windows the check invokes `mvnw.cmd`; validation has initially been performed on macOS only. + +For just the Maven foundation: + +```sh +./mvnw --batch-mode --no-transfer-progress clean verify +``` + +The JDK requirement above is for the bootstrap, not a declaration that all future modules or JavaFX 26 hosts run on Java 21. Target/host and bytecode baselines are established independently in the implementation plan. + +## Implementation references + +- [Initial project contract](docs/initial-project-contract.md): module responsibilities, configuration, snapshots, runtimes, preview sessions and communication. +- [Repository bootstrap plan](docs/repository-bootstrap-plan.md): ordered work packages and acceptance gates. Next: isolate and validate the NeitzelLib runtime fix, then implement module/host boundaries. +- [Decision provenance](docs/provenance.md): workspace planning and captured prototype evidence. +- [Third-party notices](THIRD-PARTY-NOTICES.md): Maven wrapper provenance. + +The canonical checkout is `/Volumes/PlanckSSD/KI/java/NeitzelFXDesigner`. Its Git remote is `ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git` and its default branch is `main`. diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md new file mode 100644 index 0000000..68eed62 --- /dev/null +++ b/THIRD-PARTY-NOTICES.md @@ -0,0 +1,5 @@ +# Third-party notices + +`mvnw`, `mvnw.cmd` and `.mvn/wrapper/maven-wrapper.properties` are generated using Apache Maven Wrapper Plugin 3.3.4 (only-script distribution). The wrapper scripts retain their Apache Software Foundation copyright/license headers. See the [Apache Maven Wrapper documentation](https://maven.apache.org/tools/wrapper/) and [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). + +No Scene Builder Kit, IntelliJ, JavaFX, NeitzelLib or prototype source/binary is included in this bootstrap. Track provenance and required notices when dependencies or patches are introduced; this notice does not assign a license to original NeitzelFXDesigner code. diff --git a/docs/initial-project-contract.md b/docs/initial-project-contract.md new file mode 100644 index 0000000..f7dd563 --- /dev/null +++ b/docs/initial-project-contract.md @@ -0,0 +1,131 @@ +# NeitzelFXDesigner initial project contract + +Status: accepted architecture consolidated from decision rounds Q1–Q15 on 2026-11-12. Module and JSON field spellings below are proposed implementation names; public Java signatures and numerical protocol limits must pass their bootstrap validation before publication. This document refines roadmap stage 1, not the complete product specification. + +Decision provenance: [accepted workspace decisions](provenance.md). Execution order: [repository bootstrap plan](repository-bootstrap-plan.md). Existing authoring, preview, binding, generation and host requirements remain in the [broader roadmap context](provenance.md#broader-roadmap). + +## Project and scope + +- Repository: **NeitzelFXDesigner**; application name: **Neitzel FX Designer**. +- Remote: `ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git`. +- Canonical independent checkout: `/Volumes/PlanckSSD/KI/java/NeitzelFXDesigner`, alongside NeitzelLib in the canonical Java workspace. The research worktree is not its permanent checkout. +- Initial default branch: `main`. The initial repository bootstrap establishes this branch; the earlier consolidation found no advertised remote refs. +- The Component builder fix belongs to NeitzelLib. Designer/tooling code belongs to NeitzelFXDesigner. Application fixtures depend on library artifacts, never copied NeitzelLib sources. +- First milestone: one real Component and sample Model through Build and Refresh, successful-build capture, metadata discovery and target-runtime rendering in both minimal hosts. Include classpath and module-path fixtures and failure diagnostics. +- Full binding/generation UI, general projection editing, production handoff, packaging and wider qualification retain their later roadmap gates. Minimal hosts are not feature-complete releases. + +## Modules and dependency direction + +Names are proposed, while the responsibility boundaries are accepted. + +| Module/directory | Responsibility | Boundary | +| --- | --- | --- | +| `designer-contracts` | Configuration types/schema, wire envelopes, metadata DTOs and capability definitions | No Kit, IntelliJ or application classes; schema/protocol versions are independently tracked | +| `designer-core` | Application contexts, build/snapshot orchestration, validation, document edit intents and worker sessions | Depends on contracts; obtains host services through interfaces, not host implementations | +| `designer-kit-ui` | Shared canvas, hierarchy, inspector and later binding/generation panels | Depends on core and pinned Kit/JavaFX; no IntelliJ API | +| `designer-standalone` | Native application entry point, documents/undo, menus, navigation and lifecycle | Adapts core/UI to standalone services | +| `designer-intellij` | FXML editor, IDE Documents/commands, project/build/navigation integration and focus | Adapts the same core/UI; qualify build and packaging against the selected IDE SDK | +| `designer-preview-api` | Typed example descriptors and fresh preview-session lifecycle | Small project-facing artifact; no Kit or IntelliJ dependency | +| `designer-target-tools` | Discovery and NeitzelLib loading/rendering adapter in the application runtime | Uses contracts/preview API and target-compatible library dependencies; never execute application classes in a host | +| `integration-fixtures/` | Real classpath and module-path Maven applications, examples and failure cases | Same scenarios consumed by both hosts; normal artifact dependencies | + +Shared contracts may be Java artifacts without implying identical JDK/JavaFX versions in hosts and workers. Select bytecode/API baselines per module from the supported target fixtures; verify that application-facing artifacts load on the oldest initial target before publishing them. The IntelliJ packaging toolchain must be pinned and tested; a Maven reactor for shared artifacts does not assume that ordinary Maven JAR packaging produces a supported plugin. + +```mermaid +flowchart LR + S[Standalone adapter] --> U[Shared Kit UI] + I[IntelliJ adapter] --> U + U --> C[Shared designer core] + S --> C + I --> C + C --> K[Configuration / protocol / metadata contracts] + C -->|Dedicated local IPC| W[Target-runtime tooling] + W --> K + W --> P[Preview API] + A[Application examples] --> P + W --> N[NeitzelLib and application runtime] +``` + +Each host owns its own engine/UI instances. The authoritative document and undo history belong to the active host. Kit remains a projection. This diagram describes dependencies and process boundaries, not shared mutable state across hosts. + +## Shared application configuration + +`neitzel-fx-designer.json` lives at the application's Maven reactor root. It contains a schema version and named application contexts. A context selects an application module, Maven profiles, classpath/module-path launch mode, preview sources/module and examples. Relative paths resolve from the configuration location, never the process working directory. Validate modules and paths against the selected reactor. Obtain dependency graphs and ordinary source/resource roots from Maven rather than maintaining competing lists. + +Illustrative shape for the first schema (field names are a concrete draft, not a released schema): + +```json +{ + "schemaVersion": "1.0", + "contexts": { + "desktop": { + "applicationModule": "app", + "mavenProfiles": ["designer-preview"], + "launchMode": "classpath", + "buildRuntime": "build-java", + "targetRuntime": "application-java", + "preview": { + "sourceSet": "module", + "module": "preview", + "provider": "example.preview.PersonExamples", + "defaultExample": "person.standard" + } + } + } +} +``` + +The schema must also cover `test` preview sources in the application module, module-path entry/access settings and runtime requirements. Example IDs belong to provider descriptors; configuration selects a default and may select/filter descriptors rather than duplicating their metadata. A provider class name identifies a typed implementation, not an arbitrary reflective factory method. Provider registration/descriptor extraction must be validated against the library before the public API is frozen. + +Select the context automatically when exactly one matches. Otherwise ask, show the active context and remember the choice locally. Opening a Component from a parent inherits that context. Shared source documents retain one host-owned draft even when usable in multiple contexts. + +Local settings hold installed JDK mappings, absolute machine paths and remembered context/UI preferences. Shared runtime names refer to required build and target runtimes; resolve, display and validate those roles separately. Application JavaFX comes from Maven. A missing/incompatible target requests setup; never silently substitute the designer's or IDE's JVM. No automatic configuration migration. Unsupported schema/capabilities disable the affected tool with diagnostics while ordinary source editing remains available. + +## Build and snapshot contract + +1. Resolve the selected context and required reactor dependencies, including configured preview sources. Prefer the Maven wrapper; expose the plan, command/output and cancellation. Avoid unrelated applications unless dependency resolution requires them. +2. Identify known unsaved Java, Maven and designer-configuration inputs affecting the build. Offer **Save affected files and build** or **Cancel**, listing the affected files. Do not implicitly build older disk versions. Account for IDE autosave; another process's unsaved buffers are not observable. +3. Capture the relevant input identity/revision manifest and execute the build with the selected build runtime. FXML-only draft edits have separate revisions and need not trigger Java compilation. +4. After success, stage a consistent snapshot of compiled outputs, generated metadata, resources and resolved dependency content/identities into an ignored designer cache. Do not hand workers mutable `target` paths or mutable dependency outputs. Copy or content-address artifacts; a snapshot must not change if later builds overwrite their inputs. +5. Verify inputs/output capture remained consistent throughout the operation. A fingerprint at only one instant is insufficient. Detected changes, capture failures, cancellation or failed builds prevent activation. Publish a complete manifest/snapshot atomically, never a partially populated directory. +6. Activate the successful snapshot, refresh discovery and restart affected preview sessions. A manifest identifies context, build inputs, artifacts/digests, runtime requirements and tool contracts. Discovery and rendering use the same build identity. +7. Retain the last usable successful snapshot after failure, mark retained derived results outdated, and require explicit **Preview with last successful build**. An outdated build is not silently promoted to current. + +Cache contents are local, ignored and reconstructible. Active workers retain their snapshots until stopped; eviction must not remove in-use artifacts. Numerical retention limits are operational defaults, not a new authoring decision. + +FXML previews overlay the owning host's current parent and open Component drafts onto the selected build snapshot. Document revisions and snapshot identity remain distinct; source edits must not silently change a worker's captured input. Reject obsolete results using host-owned revision ordering, not numeric assumptions about IDE modification stamps. Resources outside the supported draft-overlay mechanism remain part of explicit resource/build freshness validation. + +## Discovery and preview API + +Metadata listing must not construct Models or invoke Controller methods. Separate example descriptors (stable IDs, display labels, compatible Model/View information and declared capabilities) from runtime construction. Generated descriptor metadata or equivalent non-constructing discovery must be tested; calling arbitrary provider initialization merely to list examples does not satisfy this boundary. + +Selecting an example creates a fresh owned preview session with its Model graph and explicitly configured services. Provide readiness and cleanup hooks. Ordinary examples become ready after load/CSS/layout; asynchronous examples signal readiness subject to cancellation/timeout. Construction, services, Controller actions and cleanup execute only in the target JVM. Verify the adapter against NeitzelLib's actual injection/loading lifecycle before publishing Java signatures. + +A parent rendering snapshot shares its Model graph across embedded Components; standalone Component preview selects its own example. Interactive preview has its own JVM/session. Bounded graceful cleanup precedes forced worker termination when necessary; cleanup callbacks cannot be guaranteed after process death, so host-side lifecycle ownership remains required. + +## Versions and communication + +Track configuration schema, wire/metadata contracts and preview API compatibility independently from product releases. Major changes represent breaking contracts; additive features use declared optional capabilities. Equal product versions alone are not proof of compatibility. Verify discovery and rendering independently so one unavailable capability does not unnecessarily disable the other. + +Use a dedicated loopback-only socket with a per-launch random token and version/capability handshake for worker messages. Standard output/error remain captured application logs and cannot carry protocol framing. Do not log tokens. Bind the session to the launched worker and reject messages before authentication/negotiation. Use explicit bounded framing, validate lengths and resource limits before allocation, correlate requests/replies and define cancellation/error outcomes. Exact encoding and limits are bootstrap protocol-specification tasks, not facts established by the prototype. + +Every applicable request/result identifies its worker session, request, context and build snapshot; rendering also identifies document revisions and requested size. Obsolete results cannot mutate current document/UI state. Diagnostics identify operation and available source origin while preserving editing. + +Keep the proven reserved owner-lifetime channel for worker cleanup independent of FX responsiveness. The independently owning standalone editor must survive IDE death; it does not use the preview-worker death rule. Production host-to-host handoff remains a separate protocol/gate; choosing a worker socket does not silently choose its production transport. + +## Library prerequisite and acceptance + +Integrate and test the Component builder fix separately in NeitzelLib, preserve unrelated work, and establish the first released artifact containing it. Declare the resulting supported minimum/capability in designer metadata. Older unsupported versions receive diagnostics, not a hidden adapter. Until release, development fixtures may pin a clearly identified installed snapshot; a SNAPSHOT name alone does not establish fix provenance. The inspected source currently declares `de.neitzel.lib:fx:1.0-SNAPSHOT` with Java 21 / JavaFX 21.0.7, and the fix remains uncommitted. No corrected minimum released version is asserted; see the bootstrap plan for provenance and test-run caveats. + +Accept the first milestone only when both minimal hosts use the same core/UI/fixtures and demonstrate: + +- Constructor-only Components accept custom/inherited FXML attributes after initialization; invalid values fail; Model identity/write-back survive without an adapter. +- Classpath and module-path applications build, discover and render through their selected runtimes; missing module access is diagnosed rather than repaired with silent broad opens. +- Build scope and explicit save choices are observable; failed/cancelled/stale builds preserve documents and do not publish a current snapshot. +- Subsequent builds cannot mutate a running worker's snapshot; active snapshot cleanup is safe. +- FXML draft updates render without Java recompilation and stale responses are ignored. +- Missing/incompatible runtime/schema/protocol/capability failures are actionable and limited to affected tools. +- Listing examples performs no Model/Controller construction; selecting an example produces fresh state and honors readiness/cleanup. +- Console output cannot corrupt worker messages; owner death, cancellation and timeout terminate workers. + +These are acceptance requirements, not newly passed tests. Broader product behavior remains governed by the existing roadmap. diff --git a/docs/provenance.md b/docs/provenance.md new file mode 100644 index 0000000..4b80a9d --- /dev/null +++ b/docs/provenance.md @@ -0,0 +1,11 @@ +# Decision provenance + +The architecture and bootstrap plan were accepted by Konrad through the Java workspace Wayfinder effort **NeitzelLib FX support in Scene Builder**, culminating in **Choose the initial implementation project and contracts** (Q1–Q15, consolidated 2026-11-12). + +The authoritative implementation documents now live here: [initial contract](initial-project-contract.md) and [bootstrap plan](repository-bootstrap-plan.md). Workspace documents retain links here. The original discussion record remains at `docs/issues/neitzellib-scene-builder/issues/23-choose-initial-project-contract.md` in the Java workspace. On the development workstation that workspace is `/Volumes/PlanckSSD/KI/java`. + +## Broader roadmap + +The wider authoring/generation and delivery plan remains at `docs/issues/neitzellib-scene-builder/integration-roadmap.md` in the Java workspace. It covers later binding/generation UI, projection, handoff and packaging gates; this repository's initial contract deliberately covers only its first implementation stage. The selected host architecture shares Kit UI, keeps authoritative documents in their hosts, and isolates application execution in target workers. VoiceOver qualification and remote IDE development remain outside the agreed initial scope. + +The throwaway experiments remain in the workspace repository, not in this production foundation. Their captured evidence includes the [shared Kit/standalone result](https://gitea.neitzel.de/konrad/workspace-java/src/commit/65ffa56215ed666dec5db12746346e8a1f2baa08/docs/issues/neitzellib-scene-builder/prototypes/PROTOTYPE-intellij/STANDALONE-RESULTS.md) and [coordinated handoff result](https://gitea.neitzel.de/konrad/workspace-java/src/commit/327311a4f88061324357a13f76295bf191d4cc70/docs/issues/neitzellib-scene-builder/prototypes/PROTOTYPE-intellij/HANDOFF-RESULTS.md). Their bounded test results are not qualification of this new repository. diff --git a/docs/repository-bootstrap-plan.md b/docs/repository-bootstrap-plan.md new file mode 100644 index 0000000..da94e6f --- /dev/null +++ b/docs/repository-bootstrap-plan.md @@ -0,0 +1,81 @@ +# NeitzelFXDesigner repository bootstrap plan + +Status: repository foundation implemented by the initial commit; work packages 2–7 remain planned. Consolidated 2026-11-12. Scope is the ordered implementation start for the [accepted initial contract](initial-project-contract.md); the initial commit creates the foundation only and does not publish a library release. + +## Starting-point evidence before bootstrap + +- `git ls-remote ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git` succeeded and advertised no refs. Recheck before bootstrapping; do not overwrite work created meanwhile. +- Canonical workspace is `/Volumes/PlanckSSD/KI/java`. Its catalog requires independent project checkouts and currently has no NeitzelFXDesigner row. +- Workspace sync clones a named catalog branch. Create/push initial `main` before expecting ordinary catalog sync to clone it. +- NeitzelLib has existing local changes, including the Component builder work and unrelated tray changes. Integrate only reviewed Component changes; never sweep the working tree into a release commit. +- Current library coordinates: `de.neitzel.lib:fx:1.0-SNAPSHOT`, parent `de.neitzel.lib:neitzellib:1.0-SNAPSHOT`. The parent POM declares Java 21, JavaFX 21.0.7 and Maven minimum 3.8.6; wrapper scripts exist. +- Inspected library HEAD: `23ad65062f629f2b41fe481c5fe9a541f6da405f` on `feature/native-tray-quit`. The Component builder fix in `fx/src/main/java/de/neitzel/fx/view/Components.java` and its regression fixtures are uncommitted. Existing local tray changes must remain intact. Recheck this state before implementation. +- No local tags or corrected released artifact were established. Remote release publication was not audited. Exact corrected minimum version remains unset; local source/prototype success does not prove publication. +- The parent POM sets Surefire `testFailureIgnore=true`. Override it where effective and inspect test reports; Maven exit success alone is not acceptance evidence. +- No source `module-info.java` was found in the inspected library tree. Qualify the actual automatic/named-module behavior and access requirements in the module-path fixture; do not assume a declared named-module contract. + +## Ordered work packages + +Work package 1 supplies this repository, documentation, pinned wrapper and `python3 scripts/check-bootstrap.py`. Its remote-main and workspace-registration checks are verified during publication. The remaining packages below are not implemented. + +### 1. Bootstrap the independent repository and workspace registration + +Recheck remote refs and destination. Reuse an existing correct checkout if one has appeared; otherwise create the independent checkout at `/Volumes/PlanckSSD/KI/java/NeitzelFXDesigner`. Do not create it inside NeitzelLib or commit its files into the workspace repository. + +Create initial `main` with project README, ignore rules, concise project instructions, build entry points and the accepted contract/plan (move their authoritative implementation home into the new repository and leave workspace links). Preserve third-party attribution obligations when bringing over code; do not copy an entire throwaway prototype. Pin actual build-tool versions when verified. Suggested initial project version: `0.1.0-SNAPSHOT`; artifact/group/module spellings are implementation defaults, not previously published coordinates. + +The bootstrap must have a reproducible validation command and a truthful README stating which modules are scaffolded versus runnable. Only advertise working commands. Verify the independent Git root and remote, inspect the initial diff, create/push initial main, and verify it exists remotely. Use the workspace-prescribed feature-branch and landing policy for subsequent work. + +Then register the checkout in the canonical workspace catalog and retain its root ignore boundary. Proposed row: + +| name | kind | remote | branch | language | merge | notes | +| --- | --- | --- | --- | --- | --- | --- | +| NeitzelFXDesigner | app | ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git | main | java | merge-delete | Shared Kit designer, standalone application and IntelliJ host | + +Update the catalog's project count and validate catalog parsing without unnecessarily pulling unrelated checkouts. This plan does not edit the live catalog before the checkout/branch exists. + +**Exit:** independent clean checkout, remote main, valid catalog/ignore boundary, documented reproducible bootstrap check. + +### 2. Integrate and identify the corrected NeitzelLib artifact + +Read the library's current instructions/POM and inspect only the Component builder diff, regression fixtures/tests and related documentation. Preserve unrelated local changes. Run relevant library tests and the direct adapter-free smoke scenario. Verify actual test results despite the parent POM's failure-ignore setting. Capture an isolated library change through its normal feature/landing workflow. + +Establish the first release containing the fix through actual artifact/source evidence. Do not invent a minimum version. Until then, fixtures may use a locally installed snapshot with documented source revision, any required patch digest, and build/artifact identity. Record the release/capability prerequisite in compatibility metadata when verified. + +**Exit:** isolated validated library change, identifiable usable development artifact and a clear release prerequisite; publication is a separate action, not implied by the plan. + +### 3. Establish buildable module and host-service boundaries + +Create the contract's shared artifacts and two host adapters. Define interfaces for document drafts/edit transactions/undo, build execution/output/cancellation, navigation, diagnostics, runtime resolution and lifecycle. Keep UI and IDE dependencies out of contracts/preview artifacts. Verify dependency rules with build checks. + +Build shared libraries/fixtures using the Maven structure; verify and pin the actual IntelliJ SDK packaging toolchain, using a separate adapter build if required. Provide one documented orchestration entry point. Retain independent standalone/plugin packaging gates. Select per-artifact Java bytecode baselines from real target requirements rather than propagating the host JDK into every artifact. + +**Exit:** reproducible clean build, dependency boundary checks, minimal host service adapters; no unsupported public API baseline claims. + +### 4. Make configuration and compatibility executable + +Implement JSON schema, context resolution and local runtime mappings. Turn the illustrative fields into a versioned v1 schema and fixtures. Check invalid paths/modules, missing runtimes, unknown schema versions/capabilities, multiple matching contexts and parent-to-Component context inheritance. Define protocol framing, bounded message/image payloads and negotiation/error fixtures before worker implementation depends on them. + +**Exit:** common configuration tests pass in both host adapters; incompatible setup leaves source editing available; protocol specification is testable and independently versioned. + +### 5. Implement Build and Refresh with immutable snapshots + +Resolve scoped Maven builds, preview source arrangements, explicit save/cancel and runtime choices. Capture successful outputs/resources/dependencies with an input/output manifest. Validate consistency and publish atomically; pin active snapshots against eviction. Provide explicit last-successful-build selection and stale diagnostics. + +**Exit:** success, cancellation, failed build, input edits during build/capture, mutable output replacement, and snapshot-lifetime tests pass. Known unsaved build inputs cannot silently fall back to disk. + +### 6. Validate the preview API and target adapter against real fixtures + +Add classpath/module-path Maven fixture applications using NeitzelLib artifacts. Implement non-constructing descriptor discovery and typed provider/session lifecycle against the real library. Test fresh Models/services, readiness, cleanup, invalid attributes and write-back. Freeze public Java signatures only after these tests establish the adapter contract. + +**Exit:** standalone target-side tests pass without Kit/IntelliJ dependencies leaking into application-facing artifacts; both preview source arrangements are represented. + +### 7. Complete the first workflow in both minimal hosts + +Connect shared core/UI to the worker protocol and fixtures. Exercise Build and Refresh, discovery, parent/Component draft overlays and target-runtime render in standalone and IntelliJ. Use the qualified exclusive JavaFX 26 host setup; keep application runtime execution outside each host. Carry only the verified narrow Kit patch where still needed, with provenance and regression coverage. + +**Exit:** all initial-contract acceptance requirements pass in both hosts with logs/artifact identities and explicit limitations. Then proceed to roadmap stage 2 and later feature stages. Full handoff, binding/generation UI, broader projection/control support and product packaging are not silently included in this first milestone. + +## Delivery discipline + +Do not label these packages as additional unresolved Wayfinder decisions: the architecture is accepted. They are concrete implementation work with validation gates. Reopen a focused design question only if implementation evidence exposes a real incompatibility or missing seam. Bootstrap, library integration and designer implementation remain separately reviewable changes. diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..bd8896b --- /dev/null +++ b/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..92450f9 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a819627 --- /dev/null +++ b/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + de.neitzel.fxdesigner + neitzel-fx-designer + 0.1.0-SNAPSHOT + pom + Neitzel FX Designer + Repository foundation for the shared Kit designer and its standalone and IntelliJ hosts. + https://gitea.neitzel.de/konrad/NeitzelFXDesigner + + UTF-8 + false + + + scm:git:ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git + scm:git:ssh://git@gitea.neitzel.de:2222/konrad/NeitzelFXDesigner.git + https://gitea.neitzel.de/konrad/NeitzelFXDesigner + HEAD + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.6.2 + + + bootstrap-toolchain + enforce + + + [3.9.11,3.9.12) + [21,) + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.4.1 + + + + diff --git a/scripts/check-bootstrap.py b/scripts/check-bootstrap.py new file mode 100644 index 0000000..c5e4296 --- /dev/null +++ b/scripts/check-bootstrap.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Validate the current POM-only foundation and portable local documentation.""" +from pathlib import Path +import json +import os +import re +import subprocess +import sys + +ROOT = Path(__file__).resolve().parent.parent +wrapper = ROOT / ("mvnw.cmd" if os.name == "nt" else "mvnw") +subprocess.run([str(wrapper), "--batch-mode", "--no-transfer-progress", "clean", "verify"], cwd=ROOT, check=True) +for document in [ROOT / "README.md", ROOT / "AGENTS.md", ROOT / "THIRD-PARTY-NOTICES.md", *sorted((ROOT / "docs").glob("*.md"))]: + content = document.read_text(encoding="utf-8") + for example in re.findall(r"```json\n(.*?)\n```", content, re.S): + json.loads(example) + for target in re.findall(r"\]\(([^)]+)\)", content): + if "://" in target or target.startswith("#"): + continue + local = document.parent / target.split("#", 1)[0] + if not local.exists(): + sys.exit(f"Broken local link in {document.relative_to(ROOT)}: {target}") +print("PASS Maven foundation, local document links and JSON examples (no application tests yet)")