<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ch.sbb.polarion.extensions</groupId>
    <artifactId>ch.sbb.polarion.extension.generic</artifactId>
    <version>16.1.0</version>
    <packaging>pom</packaging>

    <name>Versatile extension for developing additional extensions within Polarion ALM: parent POM</name>
    <description>This is a Polarion extension which provides common part to other extensions reducing code duplication</description>
    <url>https://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic</url>

    <licenses>
        <license>
            <name>The SBB License, Version 1.0</name>
            <url>https://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic/blob/main/LICENSES/SBB.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <name>SBB Polarion Team</name>
            <email>polarion-opensource@sbb.ch</email>
            <organization>SBB AG</organization>
            <organizationUrl>https://www.sbb.ch</organizationUrl>
        </developer>
    </developers>

    <scm>
        <connection>scm:git:git://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic.git</connection>
        <developerConnection>scm:git:ssh://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic.git</developerConnection>
        <url>https://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic/tree/main</url>
    </scm>

    <issueManagement>
        <system>GitHub</system>
        <url>https://github.com/SchweizerischeBundesbahnen/ch.sbb.polarion.extension.generic/issues</url>
    </issueManagement>

    <distributionManagement>
        <snapshotRepository>
            <id>sonatype-central</id>
            <url>https://central.sonatype.com/</url>
        </snapshotRepository>
        <repository>
            <id>sonatype-central</id>
            <url>https://central.sonatype.com/</url>
        </repository>
    </distributionManagement>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>

        <polarion.version>2606</polarion.version>

        <!-- Maven plugins -->
        <maven-clean-plugin.version>3.5.0</maven-clean-plugin.version>
        <maven-compiler-plugin.version>3.15.0</maven-compiler-plugin.version>
        <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version>
        <maven-install-plugin.version>3.1.4</maven-install-plugin.version>
        <maven-jar-plugin.version>3.5.1</maven-jar-plugin.version>
        <maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>
        <maven-resources-plugin.version>3.5.0</maven-resources-plugin.version>
        <maven-source-plugin.version>3.4.0</maven-source-plugin.version>
        <maven-surefire-plugin.version>3.5.6</maven-surefire-plugin.version>
        <maven-dependency-plugin.version>3.11.0</maven-dependency-plugin.version>
        <pre-commit-run-maven-plugin.version>1.0.0</pre-commit-run-maven-plugin.version>
        <polarion-compatibility-maven-plugin.version>0.1.2</polarion-compatibility-maven-plugin.version>
        <swagger-maven-plugin.version>2.2.55</swagger-maven-plugin.version>
        <sonar-maven-plugin.version>5.7.0.6970</sonar-maven-plugin.version>

        <!-- Test dependencies -->
        <junit.version>6.1.3</junit.version>
        <mockito.version>5.23.0</mockito.version>
        <assertj-core.version>3.27.7</assertj-core.version>
        <jaxb.impl.version>4.0.9</jaxb.impl.version>
        <istack.version>4.2.0</istack.version>
        <log4j.version>2.26.1</log4j.version>
        <jackson.annotations.version>2.22.2</jackson.annotations.version>
        <jakarta.transaction-api.version>2.0.1</jakarta.transaction-api.version>

        <!-- Sonar and JaCoCo -->
        <jacoco.version>0.8.15</jacoco.version>
        <sonar.projectKey>SchweizerischeBundesbahnen_${project.artifactId}</sonar.projectKey>
        <sonar.organization>schweizerischebundesbahnen</sonar.organization>
        <sonar.projectName>${project.artifactId}</sonar.projectName>
        <sonar.host.url>https://sonarcloud.io</sonar.host.url>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
        <sonar.language>java</sonar.language>
        <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
        <sonar.verbose>true</sonar.verbose>
        <sonar.qualitygate.wait>true</sonar.qualitygate.wait>

        <!-- Others -->
        <lombok.version>1.18.30</lombok.version>
        <jetbrains.api.version>24.0.1</jetbrains.api.version>
        <gwt-servlet.version>2.9.0</gwt-servlet.version>
        <jersey.version>3.1.12</jersey.version>
        <re2j.version>1.8</re2j.version>
        <classgraph.version>4.8.194</classgraph.version>
        <org.osgi.framework.version>1.10.0</org.osgi.framework.version>
        <swagger.version>2.2.55</swagger.version>
        <jakarta.ws.rs-api.version>3.1.0</jakarta.ws.rs-api.version>
        <commons-logging.version>1.3.6</commons-logging.version>

        <!-- Manifest entries -->
        <maven-jar-plugin.Manifest-Version>1.0</maven-jar-plugin.Manifest-Version>
        <maven-jar-plugin.Bundle-ManifestVersion>2</maven-jar-plugin.Bundle-ManifestVersion>
        <maven-jar-plugin.Bundle-Build-Timestamp>${maven.build.timestamp}</maven-jar-plugin.Bundle-Build-Timestamp>
        <maven-jar-plugin.Automatic-Module-Name>${project.artifactId}</maven-jar-plugin.Automatic-Module-Name>
        <maven-jar-plugin.Bundle-SymbolicName>${project.artifactId};singleton:=true</maven-jar-plugin.Bundle-SymbolicName>
        <maven-jar-plugin.Bundle-Vendor>SBB AG</maven-jar-plugin.Bundle-Vendor>
        <!--suppress UnresolvedMavenProperty -->
        <maven-jar-plugin.Bundle-Version>${project.artifact.selectedVersion.majorVersion}.${project.artifact.selectedVersion.minorVersion}.${project.artifact.selectedVersion.incrementalVersion}</maven-jar-plugin.Bundle-Version>
        <maven-jar-plugin.Extension-Context/>
        <maven-jar-plugin.Discover-Base-Package>${project.artifactId}</maven-jar-plugin.Discover-Base-Package>
        <maven-jar-plugin.Configuration-Properties-Prefix/>
        <maven-jar-plugin.Project-URL>${project.scm.url}</maven-jar-plugin.Project-URL>
        <maven-jar-plugin.Support-Email>polarion-opensource@sbb.ch</maven-jar-plugin.Support-Email>
        <maven-jar-plugin.Bundle-ActivationPolicy>lazy</maven-jar-plugin.Bundle-ActivationPolicy>
        <!-- Extension-specific OSGi imports. An extension may override this property wholesale. -->
        <maven-jar-plugin.Import-Package>org.osgi.framework</maven-jar-plugin.Import-Package>
        <!-- Appended to Import-Package for every extension and NOT meant to be overridden.
             jakarta.annotation used to arrive from TWO bundles: com.polarion.portal.tomcat (Tomcat 11 embeds
             the annotation API) and jakarta.annotation-api. Both export it unversioned, so only the exporting
             bundle told them apart, and Require-Bundle listed the Tomcat one first - which bound our classes
             to Tomcat's copy while Jersey requires jakarta.annotation-api;bundle-version="3.0.0" and binds to
             the other one. Two distinct jakarta.annotation.Priority classes then made Jersey's
             `annotation instanceof Priority` check in ComponentBag.modelFor() fail, so @Priority never reached
             the provider model: every filter fell back to Priorities.USER, ranks tied, and RankedComparator
             (which never returns 0) left the filters in HashSet iteration order - a different
             authentication/authorization order per JVM start.
             The Tomcat bundle is gone from Require-Bundle now, so only one exporter is left. The pin stays as
             the guard: Import-Package is searched BEFORE Require-Bundle, so it keeps us on Jersey's class no
             matter what a future Require-Bundle entry drags in. -->
        <maven-jar-plugin.Import-Package.required>jakarta.annotation;bundle-symbolic-name="jakarta.annotation-api"</maven-jar-plugin.Import-Package.required>
        <!-- Common Require-Bundle:
            jakarta.servlet-api
            com.polarion.alm.ui
            jakarta.inject-api
            jakarta.annotation-api
            jakarta.ws.rs-api
            jakarta.xml.bind-api
            jakarta.activation-api
            org.glassfish.jersey
            com.fasterxml.jackson.core
            com.fasterxml.jackson.databind
            com.fasterxml.jackson.annotations
            com.fasterxml.jackson.module.jakarta.xmlbind.annotations
            org.apache.commons.logging
            commons-io
            slf4j.api
            org.springframework.spring-core
            org.springframework.spring-web
            com.polarion.alm.tracker
            com.polarion.platform.guice
        -->
        <maven-jar-plugin.Require-Bundle.common>jakarta.servlet-api,com.polarion.alm.ui,jakarta.inject-api,jakarta.annotation-api,jakarta.ws.rs-api,jakarta.xml.bind-api,jakarta.activation-api,org.glassfish.jersey,com.fasterxml.jackson.core,com.fasterxml.jackson.databind,com.fasterxml.jackson.annotations,com.fasterxml.jackson.module.jakarta.xmlbind.annotations,org.apache.commons.logging,commons-io,slf4j.api,org.springframework.spring-core,org.springframework.spring-web,com.polarion.alm.tracker,com.polarion.platform.guice</maven-jar-plugin.Require-Bundle.common>
        <maven-jar-plugin.Require-Bundle.extension/>
        <maven-jar-plugin.Require-Bundle>${maven-jar-plugin.Require-Bundle.common}</maven-jar-plugin.Require-Bundle>

        <central-publishing-maven-plugin.version>0.11.0</central-publishing-maven-plugin.version>
        <central-publishing-maven-plugin.autoPublish>true</central-publishing-maven-plugin.autoPublish>

        <markdown2html-maven-plugin.version>1.7.1</markdown2html-maven-plugin.version>
        <markdown2html-maven-plugin.inputFile>${project.basedir}/README.md</markdown2html-maven-plugin.inputFile>
        <!-- The property name is historical: it predates the React apps and is kept so downstream poms
             that reference it keep working. The path mirrors ExtensionInfoInternalController.readHtmlFile,
             which composes `/webapp/` + the Extension-Context manifest attribute + `-app/html/` and reads
             nowhere else. Spelled out rather than derived from ui.destination.root, so relocating the
             React bundle does not silently move the help articles out of the one directory the reader
             looks in (a missing article yields an empty About page, not an error). -->
        <markdown2html-maven-plugin.extensionContextAdminHtml>${project.basedir}/src/main/resources/webapp/${maven-jar-plugin.Extension-Context}-app/html</markdown2html-maven-plugin.extensionContextAdminHtml>
        <markdown2html-maven-plugin.outputFileName>about.html</markdown2html-maven-plugin.outputFileName>
        <markdown2html-maven-plugin.outputFile>${markdown2html-maven-plugin.extensionContextAdminHtml}/${markdown2html-maven-plugin.outputFileName}</markdown2html-maven-plugin.outputFile>
        <!-- A broken README.md -> about.html conversion fails the build instead of shipping an empty
             About page. The default was lenient while the conversion called the GitHub API and failed
             without a token; markdown2html renders locally since 1.7.x, so strictness costs nothing. -->
        <markdown2html-maven-plugin.failOnError>true</markdown2html-maven-plugin.failOnError>
        <markdown2html-maven-plugin.generateHeadingIds>true</markdown2html-maven-plugin.generateHeadingIds>

        <!-- exclude rest controllers from coverage report -->
        <sonar.coverage.exclusions>**/rest/controller/**</sonar.coverage.exclusions>

        <frontend-maven-plugin.version>2.0.2</frontend-maven-plugin.version>
        <!-- Used by the `ui-build-react-app` profile below, which every extension with a
             `ui/package.json` inherits. Generic itself no longer builds any JavaScript. -->
        <frontend-maven-plugin.nodeVersion>v24.18.0</frontend-maven-plugin.nodeVersion>
        <frontend-maven-plugin.npmVersion>12.0.1</frontend-maven-plugin.npmVersion>

        <!-- ==== React/Vite administration app (the `ui-*` profiles below) ========================
             An extension gets the whole build by having a `ui/package.json`; there is nothing to
             declare in its own pom. Override any of these to deviate.

             The names follow the rule recorded in CLAUDE.md: a property is `ui.<subject>.<action>`
             and the profile it activates is `ui-<what it does>`, so a flag and its profile read as
             a pair. Deprecated spellings of the same properties are kept at the end of this block. -->
        <!-- Webapp context that receives a copy of generic.app.jar in its WEB-INF/lib (see the
             maven-dependency-plugin `copy-generic-app-to-ui-webapp` execution). `-app` is the only
             context an extension serves, so the copy lands where something reads it; a wrong value
             here is 350+ KB of dead weight in every jar rather than a build failure. Based on
             web.app.name to match the other WEB-INF/lib paths below, which every extension defines as
             ${maven-jar-plugin.Extension-Context} — keep the two in step if you override either. -->
        <ui.webapp.name>${generic.app.ui.webapp}</ui.webapp.name>

        <ui.sources.root>${vite.sources.root}</ui.sources.root>
        <ui.destination.root>${vite.destination.root}</ui.destination.root>
        <!-- Set -DskipJsTests to skip the ui/ Vitest run (and the Playwright install) that otherwise
             happens in the `test` phase alongside the Java tests. The name breaks the ui.* scheme of
             this block on purpose: 15 downstream workflows pass it on the command line, and Maven
             does not warn on an unrecognised -D, so renaming it here would silently start running
             the suite in the deploy jobs that mean to skip it. -->
        <skipJsTests>false</skipJsTests>
        <!-- The npm invocation for the ui/ tests, run as
             `npm ${ui.tests.npmCommand} ${ui.tests.npmExtraArgs}`. Two independent pieces so that
             setting one never clobbers the other:
               ui.tests.npmCommand   - defaults to the dockerized full suite WITH the coverage gate;
                                       -Dui.tests.withoutDocker switches it to the native equivalent.
                                       (The plain test:docker variant would run the suite but never
                                       evaluate the istanbul thresholds.)
               ui.tests.npmExtraArgs - extra arguments forwarded to Vitest, none by default. Only
                                       takes effect on the non-docker command, because the
                                       test:docker wrapper forwards no extra arguments. Pass a
                                       Vitest exclude of the *.visual.test.tsx files here, together
                                       with -Dui.tests.withoutDocker, to drop the visual-regression
                                       tests on a host that still loads them. They already skip
                                       themselves outside the reference image. -->
        <ui.tests.npmCommand>run test:coverage:docker</ui.tests.npmCommand>
        <ui.tests.npmExtraArgs> </ui.tests.npmExtraArgs>
        <!-- The Playwright browser install, see the `ui-install-playwright-browser` profile below.
             Empty means the browser binary alone. Playwright's own with-deps flag adds its OS
             libraries and needs a Debian/Ubuntu host with apt-get and root. -->
        <ui.playwright.installArgs> </ui.playwright.installArgs>

        <!-- Deprecated spellings, kept so a downstream pom that still reads or sets one keeps
             working. An unknown property in ${...} resolves to its own literal text instead of
             failing, so dropping these outright would break such a pom without any error at all.
             Remove in the next major, moving the three values below back up to the new names.

             The first three hold the value and the new name derives from it, which is what makes an
             override work from either side: a pom that sets the old name feeds the new one through
             the reference, and a pom that sets the new name simply replaces its definition here.

             The last two are read-only aliases. Their value belongs to the new name, because
             ui-tests-run-without-docker overrides ui.tests.npmCommand and a reversed alias would go
             stale inside that profile. Nothing reads or sets either one downstream. -->
        <generic.app.ui.webapp>${web.app.name}-app</generic.app.ui.webapp>
        <vite.sources.root>${project.basedir}/ui</vite.sources.root>
        <vite.destination.root>${project.basedir}/src/main/resources/webapp/${maven-jar-plugin.Extension-Context}-app</vite.destination.root>
        <jsTestCommand>${ui.tests.npmCommand}</jsTestCommand>
        <jsTestExtraArgs>${ui.tests.npmExtraArgs}</jsTestExtraArgs>
    </properties>

    <profiles>
        <!-- Build the extension and drop the jar into the Polarion installation named by
             $POLARION_HOME, replacing whatever copy is there. Developer machines only. -->
        <profile>
            <id>local-install-into-polarion</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-clean-plugin</artifactId>
                        <version>${maven-clean-plugin.version}</version>
                        <executions>
                            <execution>
                                <id>delete-installed-extension-from-polarion</id>
                                <phase>clean</phase>
                                <goals>
                                    <goal>clean</goal>
                                </goals>
                                <configuration>
                                    <filesets>
                                        <fileset>
                                            <directory>${env.POLARION_HOME}/polarion/extensions/${project.artifactId}/eclipse/plugins</directory>
                                            <includes>
                                                <include>${project.artifactId}*.jar</include>
                                            </includes>
                                            <followSymlinks>false</followSymlinks>
                                        </fileset>
                                    </filesets>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <version>${maven-dependency-plugin.version}</version>
                        <executions>
                            <execution>
                                <id>copy-to-local-polarion</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>copy</goal>
                                </goals>
                                <configuration>
                                    <artifactItems>
                                        <artifactItem>
                                            <groupId>${project.groupId}</groupId>
                                            <artifactId>${project.artifactId}</artifactId>
                                            <version>${project.version}</version>
                                            <type>${project.packaging}</type>
                                        </artifactItem>
                                    </artifactItems>
                                    <outputDirectory>${env.POLARION_HOME}/polarion/extensions/${project.artifactId}/eclipse/plugins</outputDirectory>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>gpg-sign</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>central-publishing</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.sonatype.central</groupId>
                        <artifactId>central-publishing-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <!-- ==== React/Vite administration app ======================================================
             The whole build for an extension whose admin UI is a Vite/React app on
             react-sbb-polarion: install node+npm, `npm ci`, `npm run build`, copy the bundle into the
             extension's `<ext>-app` webapp resources, run the JS suite in the `test` phase, and clean
             the generated bundle.

             Activated by the presence of `ui/package.json`, NOT by a flag or a plugin declaration:
               - an extension with a React app needs nothing in its own pom;
               - an extension without one is completely unaffected;
               - generic's own `app` module has no `ui/`, so its build stays pure Java.
             File activation is also immune to the `activeByDefault` rule that switches default profiles
             off as soon as any -P profile is named. -->
        <profile>
            <id>ui-build-react-app</id>
            <activation>
                <file>
                    <exists>${project.basedir}/ui/package.json</exists>
                </file>
            </activation>
            <properties>
                <!-- markdown2html-maven-plugin.extensionContextAdminHtml and ui.webapp.name both
                     already default to the `-app` webapp, so this profile no longer has to override
                     them. -->
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-clean-plugin</artifactId>
                        <configuration>
                            <!-- combine.children="append" is required, not decoration: without it Maven
                                 merges this fileset element-wise into the managed one (which deletes the
                                 generated about.html), so the directory below would inherit that
                                 <includes> and clean nothing - while also disabling that cleanup. -->
                            <filesets combine.children="append">
                                <fileset>
                                    <directory>${ui.destination.root}/app</directory>
                                    <followSymlinks>false</followSymlinks>
                                </fileset>
                            </filesets>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>com.github.eirslett</groupId>
                        <artifactId>frontend-maven-plugin</artifactId>
                        <version>${frontend-maven-plugin.version}</version>
                        <configuration>
                            <workingDirectory>${ui.sources.root}</workingDirectory>
                        </configuration>
                        <executions>
                            <execution>
                                <id>vite-install-node-and-npm</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>install-node-and-npm</goal>
                                </goals>
                                <configuration>
                                    <nodeVersion>${frontend-maven-plugin.nodeVersion}</nodeVersion>
                                    <npmVersion>${frontend-maven-plugin.npmVersion}</npmVersion>
                                </configuration>
                            </execution>
                            <!-- `ci`, not the plugin default `install`: the shipped bundle must come from
                                 the committed package-lock.json, the same graph the dockerized tests run
                                 against (they `npm ci` too). With `install` the caret ranges could resolve
                                 differently here than in the tests, so we would ship something we never
                                 ran; it also turns a package.json/lock mismatch into a failed build
                                 instead of a silent repair. -->
                            <execution>
                                <id>vite-npm-ci</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>npm</goal>
                                </goals>
                                <configuration>
                                    <arguments>ci</arguments>
                                </configuration>
                            </execution>
                            <execution>
                                <id>vite-npm-build</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>npm</goal>
                                </goals>
                                <configuration>
                                    <arguments>run build</arguments>
                                </configuration>
                            </execution>
                            <!-- The JS suite runs in the `test` phase next to the Java tests. By default
                                 that is the full suite (behavior + visual regression) plus the coverage
                                 gate inside the pinned Playwright Docker image, so the screenshots match
                                 their committed references. On a host without Docker use
                                 -Dui.tests.withoutDocker; to skip it entirely, -DskipJsTests. -->
                            <execution>
                                <id>vite-npm-test</id>
                                <phase>test</phase>
                                <goals>
                                    <goal>npm</goal>
                                </goals>
                                <configuration>
                                    <arguments>${ui.tests.npmCommand} ${ui.tests.npmExtraArgs}</arguments>
                                    <skip>${skipJsTests}</skip>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Copy the Vite bundle (ui/dist) into the <ext>-app webapp resources so it is
                         packaged into the jar and served by the extension's app servlet. -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-resources-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>copy-vite-build</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>copy-resources</goal>
                                </goals>
                                <configuration>
                                    <outputDirectory>${ui.destination.root}</outputDirectory>
                                    <resources>
                                        <resource>
                                            <directory>${ui.sources.root}/dist</directory>
                                            <filtering>false</filtering>
                                            <includes>
                                                <include>**/*</include>
                                            </includes>
                                        </resource>
                                    </resources>
                                    <overwrite>true</overwrite>
                                    <includeEmptyDirs>true</includeEmptyDirs>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <!-- Activate with -Dui.npm.ignoreUserConfig to run npm with an empty user config.
             For CI agents whose npm configuration the build cannot fix and must not inherit: the ESTA
             agents still carry the npm 6-era `email` and `always-auth` keys, which npm 12 rejects
             outright (ERR_INVALID_AUTH) before it fetches anything, and each agent is a container
             recreated per run, so there is nothing to repair in place.

             Nothing is lost by ignoring it: every lockfile entry resolves from the public registry,
             which is also what npm falls back to with no configuration, so no token and no scope
             mapping applies. Never make this the default - on a developer machine it would silently
             discard their own registry, proxy and auth settings. -->
        <profile>
            <id>ui-npm-ignore-user-config</id>
            <activation>
                <property>
                    <name>ui.npm.ignoreUserConfig</name>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.github.eirslett</groupId>
                        <artifactId>frontend-maven-plugin</artifactId>
                        <configuration>
                            <!-- On the plugin, not on one execution: every npm invocation validates the
                                 user config, not just the ones that fetch. Set here rather than in the
                                 base configuration so that a build without the flag does not touch the
                                 environment at all - an NPM_CONFIG_USERCONFIG set outside Maven keeps
                                 working, which an unconditional override would silently discard. -->
                            <environmentVariables>
                                <NPM_CONFIG_USERCONFIG>/dev/null</NPM_CONFIG_USERCONFIG>
                            </environmentVariables>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <!-- Run the ui/ tests natively instead of in the pinned Playwright Docker image. Needed where
             Docker is unavailable - notably the ESTA build agents, which have no docker-in-docker. The
             Vitest suite runs in Playwright browser mode, so the browser must be present: add
             -Dui.playwright.install (below). The visual suites detect they are not in the reference
             image and skip themselves, so no pixel assertion runs. Sets only ui.tests.npmCommand, so
             it composes with -Dui.tests.npmExtraArgs. -->
        <profile>
            <id>ui-tests-run-without-docker</id>
            <activation>
                <property>
                    <name>ui.tests.withoutDocker</name>
                </property>
            </activation>
            <properties>
                <ui.tests.npmCommand>run test:coverage:full</ui.tests.npmCommand>
            </properties>
        </profile>

        <!-- The Chromium build Vitest browser mode needs, installed before the tests run. Kept separate
             from -Dui.tests.withoutDocker so a host with the browser already cached can skip it. Not
             needed for the dockerized path - the pinned Playwright image ships the browser.

             -Dui.playwright.install alone fetches the browser binary only, which is what a host
             without apt-get or root can take; that host must already provide Chromium's system
             libraries. Set ui.playwright.installArgs to Playwright's own with-deps flag on a
             Debian/Ubuntu host with root to have it install those libraries too. -->
        <profile>
            <id>ui-install-playwright-browser</id>
            <activation>
                <property>
                    <name>ui.playwright.install</name>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.github.eirslett</groupId>
                        <artifactId>frontend-maven-plugin</artifactId>
                        <version>${frontend-maven-plugin.version}</version>
                        <configuration>
                            <workingDirectory>${ui.sources.root}</workingDirectory>
                        </configuration>
                        <executions>
                            <execution>
                                <id>ui-playwright-install-chromium</id>
                                <phase>process-test-resources</phase>
                                <goals>
                                    <goal>npx</goal>
                                </goals>
                                <configuration>
                                    <arguments>playwright install ${ui.playwright.installArgs} chromium</arguments>
                                    <skip>${skipJsTests}</skip>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

    <dependencyManagement>
        <dependencies>
            <!-- commons-logging carries ServletContextCleaner, which references javax.servlet.* and is
                 rejected by Polarion 2606's JakartaCompatibilityChecker. Extensions pull it transitively
                 (pdfbox, docx4j, fop, …), often in several versions. Manage it to `provided` here so every
                 extension that pulls it gets it demoted out of WEB-INF/lib (and out of Bundle-ClassPath —
                 both driven by includeScope=runtime) without each extension repeating the override; this is
                 a no-op for extensions that don't pull it. The runtime API is supplied by Polarion's OSGi
                 bundle org.apache.commons.logging_1.2.0, declared in `Require-Bundle.common` above — keep
                 these two in sync: removing org.apache.commons.logging from Require-Bundle would break
                 logging resolution at runtime for every extension relying on this `provided` demotion.
                 The version here is required only to satisfy Sonatype Central's POM validation (every
                 dependencyManagement entry must carry a version) and is build/test-classpath only — it
                 need NOT match the runtime OSGi bundle 1.2.0, since the artifact is `provided` and never
                 reaches WEB-INF/lib; renovate keeps it on the latest commons-logging release. -->
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${commons-logging.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Polarion artifacts -->
        <dependency>
            <groupId>com.polarion.alm.projects</groupId>
            <artifactId>projects</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.alm.tracker</groupId>
            <artifactId>tracker</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.alm.ui</groupId>
            <artifactId>ui</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.platform</groupId>
            <artifactId>platform</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.platform.persistence</groupId>
            <artifactId>platform-persistence</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.platform.jobs</groupId>
            <artifactId>jobs</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.platform.repository</groupId>
            <artifactId>platform-repository</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.core.util</groupId>
            <artifactId>util</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.platform.guice</groupId>
            <artifactId>platform-guice</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.subterra.base</groupId>
            <artifactId>subterra-base-core</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.subterra.base</groupId>
            <artifactId>subterra-base-data</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.core.boot</groupId>
            <artifactId>boot</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Polarion OSGi bundles -->
        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>org.glassfish.jersey_3.1.8</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>com.fasterxml.jackson.core_2.19.0</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>com.fasterxml.jackson.databind_2.19.0</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>com.fasterxml.jackson.annotations_2.19.0</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>${jakarta.ws.rs-api.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jakarta.inject</groupId>
            <artifactId>jakarta.inject-api</artifactId>
            <version>2.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-annotations</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
                <!-- Polarion 2606 ships jakarta.xml.bind-api_4.0.0 and
                     jakarta.activation-api_2.1.4 as OSGi bundles; resolved at
                     runtime via Require-Bundle. The transitive activation-api
                     2.1.x jar contains a "javax.activation.debug" string
                     literal (legacy sysprop) which trips Polarion 2606's
                     JakartaCompatibilityChecker via visitLdcInsn — so it
                     must NOT be bundled into downstream extensions. -->
                <exclusion>
                    <groupId>jakarta.xml.bind</groupId>
                    <artifactId>jakarta.xml.bind-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>jakarta.activation</groupId>
                    <artifactId>jakarta.activation-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Compile-time only; source uses jakarta.xml.bind.* (e.g. JAXBUtils).
             At runtime resolved via Require-Bundle from Polarion's own bundles. -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>4.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.activation</groupId>
            <artifactId>jakarta.activation-api</artifactId>
            <version>2.1.3</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-entity-filtering</artifactId>
            <version>${jersey.version}</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>${jersey.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-annotations-jakarta</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-integration-jakarta</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-annotations</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-jaxrs2-jakarta</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>slf4j.api_1.7.36</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>commons-io_2.20.0</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>jakarta.servlet-api_6.1.0</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>org.glassfish.jaxb-core_4.0.1</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>org.springframework.spring-web_6.2.14</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.thirdparty</groupId>
            <artifactId>org.springframework.spring-core_6.2.14</artifactId>
            <version>${polarion.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>${jersey.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Test dependencies -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>${mockito.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>${mockito.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>${assertj-core.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>${jaxb.impl.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.istack</groupId>
            <artifactId>istack-commons-runtime</artifactId>
            <version>${istack.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-jaxb-annotations</artifactId>
            <version>${jackson.annotations.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-annotations</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>jakarta.activation</groupId>
                    <artifactId>jakarta.activation-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>jakarta.transaction</groupId>
            <artifactId>jakarta.transaction-api</artifactId>
            <version>${jakarta.transaction-api.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- required for mocking InternalReadOnlyTransaction -->
        <dependency>
            <groupId>com.polarion.alm.builder</groupId>
            <artifactId>builder</artifactId>
            <version>${polarion.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.siemens.polarion.integration.ci</groupId>
            <artifactId>integrationci</artifactId>
            <version>${polarion.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.polarion.alm.oslc</groupId>
            <artifactId>oslc</artifactId>
            <version>${polarion.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Others -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>${jetbrains.api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.framework</artifactId>
            <version>${org.osgi.framework.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Will be packaged to final extensions jars -->
        <dependency>
            <groupId>com.google.re2j</groupId>
            <artifactId>re2j</artifactId>
            <version>${re2j.version}</version>
        </dependency>
        <!-- Classpath scanning used by ContextUtils. ClassGraph replaces
             org.reflections, whose 0.10.2 bytecode references javax.servlet
             and is rejected by Polarion 2606's JakartaCompatibilityChecker. -->
        <dependency>
            <groupId>io.github.classgraph</groupId>
            <artifactId>classgraph</artifactId>
            <version>${classgraph.version}</version>
        </dependency>

        <!-- Polarion UI dependency -->
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-servlet</artifactId>
            <version>${gwt-servlet.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>ch.sbb.maven.plugins</groupId>
                    <artifactId>markdown2html-maven-plugin</artifactId>
                    <version>${markdown2html-maven-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>readme.md-to-about.html</id>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>convert</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <inputFile>${markdown2html-maven-plugin.inputFile}</inputFile>
                        <outputFile>${markdown2html-maven-plugin.outputFile}</outputFile>
                        <failOnError>${markdown2html-maven-plugin.failOnError}</failOnError>
                        <generateHeadingIds>${markdown2html-maven-plugin.generateHeadingIds}</generateHeadingIds>
                        <excludeChapters>
                            <excludeChapter>## Build</excludeChapter>
                            <excludeChapter>## Installation to Polarion</excludeChapter>
                            <excludeChapter>## Changelog</excludeChapter>
                        </excludeChapters>
                        <relativeLinkPrefix>${project.scm.url}</relativeLinkPrefix>
                        <openExternalLinksInNewTab>true</openExternalLinksInNewTab>
                        <removeLinesWithStrings>
                            <removeLinesWithString>https://sonarcloud.io/api/project_badges/</removeLinesWithString>
                        </removeLinesWithStrings>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>io.swagger.core.v3</groupId>
                    <artifactId>swagger-maven-plugin-jakarta</artifactId>
                    <version>${swagger-maven-plugin.version}</version>
                    <configuration>
                        <outputFileName>openapi</outputFileName>
                        <outputPath>${project.basedir}/docs</outputPath>
                        <outputFormat>JSONANDYAML</outputFormat>
                        <prettyPrint>true</prettyPrint>
                        <sortOutput>true</sortOutput>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>compile</phase>
                            <goals>
                                <goal>resolve</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.glassfish.jersey.core</groupId>
                            <artifactId>jersey-common</artifactId>
                            <version>${jersey.version}</version>
                            <scope>runtime</scope>
                        </dependency>
                    </dependencies>
                </plugin>

                <plugin>
                    <groupId>io.github.grigoriev</groupId>
                    <artifactId>pre-commit-run-maven-plugin</artifactId>
                    <version>${pre-commit-run-maven-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>format-openapi-json</id>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <hooks>
                                    <hook>pretty-format-openapi-json</hook>
                                    <hook>mixed-line-ending-openapi-json</hook>
                                </hooks>
                                <files>
                                    <file>docs/openapi.json</file>
                                </files>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

                <!-- Fails the build when the assembled bundle, or a jar nested inside it, refers to a
                     package Polarion 2606 rejects. Declared here only; an extension opts in by naming
                     the plugin in its own build section. -->
                <plugin>
                    <groupId>com.intechcore</groupId>
                    <artifactId>polarion-compatibility-maven-plugin</artifactId>
                    <version>${polarion-compatibility-maven-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>polarion-compatibility-check</id>
                            <goals>
                                <goal>check</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>${maven-dependency-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>build-bundle-classpath</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>build-classpath</goal>
                            </goals>
                            <configuration>
                                <prefix>webapp/${web.app.name}/WEB-INF/lib</prefix>
                                <pathSeparator>,</pathSeparator>
                                <fileSeparator>/</fileSeparator>
                                <outputProperty>maven-jar-plugin.Bundle-ClassPath</outputProperty>
                                <includeScope>runtime</includeScope>
                            </configuration>
                        </execution>

                        <execution>
                            <id>copy-dependencies</id>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>copy-dependencies</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>${basedir}/target/classes/webapp/${web.app.name}/WEB-INF/lib</outputDirectory>
                                <includeScope>runtime</includeScope>
                            </configuration>
                        </execution>

                        <execution>
                            <id>copy-generic-app-to-ui-webapp</id>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>copy</goal>
                            </goals>
                            <configuration>
                                <artifactItems>
                                    <artifactItem>
                                        <groupId>ch.sbb.polarion.extensions</groupId>
                                        <artifactId>ch.sbb.polarion.extension.generic.app</artifactId>
                                        <version>${project.parent.version}</version>
                                        <type>jar</type>
                                    </artifactItem>
                                </artifactItems>
                                <outputDirectory>${basedir}/target/classes/webapp/${ui.webapp.name}/WEB-INF/lib</outputDirectory>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>${maven-jar-plugin.version}</version>
                    <configuration>
                        <archive>
                            <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
                            <manifestEntries>
                                <Manifest-Version>${maven-jar-plugin.Manifest-Version}</Manifest-Version>
                                <Bundle-ManifestVersion>${maven-jar-plugin.Bundle-ManifestVersion}</Bundle-ManifestVersion>
                                <Bundle-Vendor>${maven-jar-plugin.Bundle-Vendor}</Bundle-Vendor>
                                <Automatic-Module-Name>${maven-jar-plugin.Automatic-Module-Name}</Automatic-Module-Name>
                                <Bundle-SymbolicName>${maven-jar-plugin.Bundle-SymbolicName}</Bundle-SymbolicName>
                                <Bundle-Version>${maven-jar-plugin.Bundle-Version}</Bundle-Version>
                                <Bundle-Build-Timestamp>${maven-jar-plugin.Bundle-Build-Timestamp}</Bundle-Build-Timestamp>
                                <Bundle-ClassPath>.,${maven-jar-plugin.Bundle-ClassPath}</Bundle-ClassPath>
                                <Extension-Context>${maven-jar-plugin.Extension-Context}</Extension-Context>
                                <Discover-Base-Package>${maven-jar-plugin.Discover-Base-Package}</Discover-Base-Package>
                                <Configuration-Properties-Prefix>${maven-jar-plugin.Configuration-Properties-Prefix}</Configuration-Properties-Prefix>
                                <Project-URL>${maven-jar-plugin.Project-URL}</Project-URL>
                                <Support-Email>${maven-jar-plugin.Support-Email}</Support-Email>
                                <Bundle-ActivationPolicy>${maven-jar-plugin.Bundle-ActivationPolicy}</Bundle-ActivationPolicy>
                                <!-- The jakarta.annotation pin is appended here rather than kept in the
                                     property, because an extension that needs its own import overrides
                                     maven-jar-plugin.Import-Package wholesale (interceptor-manager already
                                     does) and would silently drop it - bringing the filter-ordering bug
                                     back. See the property's comment for what the pin is for. -->
                                <Import-Package>${maven-jar-plugin.Import-Package},${maven-jar-plugin.Import-Package.required}</Import-Package>
                                <Require-Bundle>${maven-jar-plugin.Require-Bundle}</Require-Bundle>
                            </manifestEntries>
                        </archive>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven-surefire-plugin.version}</version>
                    <configuration>
                        <!-- hide unwanted exceptions logging -->
                        <redirectTestOutputToFile>true</redirectTestOutputToFile>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${jacoco.version}</version>
                    <configuration>
                        <excludes>**/*.jar</excludes>
                    </configuration>
                    <executions>
                        <execution>
                            <id>prepare-agent</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>report</id>
                            <phase>package</phase>
                            <goals>
                                <goal>report</goal>
                            </goals>
                            <configuration>
                                <formats>
                                    <format>XML</format>
                                </formats>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

                <plugin>
                    <groupId>org.sonarsource.scanner.maven</groupId>
                    <artifactId>sonar-maven-plugin</artifactId>
                    <version>${sonar-maven-plugin.version}</version>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>${maven-source-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <version>${maven-javadoc-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>attach-javadocs</id>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <sourcepath>${basedir}/src/main/java</sourcepath>
                        <doclint>none</doclint>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>${maven-clean-plugin.version}</version>
                    <configuration>
                        <filesets>
                            <fileset>
                                <directory>${markdown2html-maven-plugin.extensionContextAdminHtml}</directory>
                                <includes>
                                    <include>${markdown2html-maven-plugin.outputFileName}</include>
                                </includes>
                                <followSymlinks>false</followSymlinks>
                            </fileset>
                        </filesets>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                        <compilerArgs>
                            <arg>-Alog4j.graalvm.groupId=org.apache.logging.log4j</arg>
                            <arg>-Alog4j.graalvm.artifactId=log4j-core</arg>
                        </compilerArgs>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.sonatype.central</groupId>
                    <artifactId>central-publishing-maven-plugin</artifactId>
                    <version>${central-publishing-maven-plugin.version}</version>
                    <extensions>true</extensions>
                    <configuration>
                        <publishingServerId>sonatype-central</publishingServerId>
                        <autoPublish>${central-publishing-maven-plugin.autoPublish}</autoPublish>
                        <waitUntil>published</waitUntil>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-gpg-plugin</artifactId>
                    <version>${maven-gpg-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>sign-artifacts</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>sign</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>${maven-install-plugin.version}</version>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>${maven-resources-plugin.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>false</filtering>
            </resource>
            <resource> <!-- Below is a way to replace polarion version in generic.properties by version from a profile -->
                <directory>src/main/resources-filtered</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <modules>
        <module>app</module>
    </modules>
</project>
