ares
Used in:
components
- OverviewOverview
- VersionsVersions
- DependentsDependents
- DependenciesDependencies
<dependency>
<groupId>de.tum.cit.ase</groupId>
<artifactId>ares</artifactId>
<version>2.1.5</version>
</dependency><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>de.tum.cit.ase</groupId>
<artifactId>ares</artifactId>
<version>2.1.5</version>
<properties>
<!-- 0. General Project Settings -->
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 1. Testing: 1.1 JUnit -->
<junit-jupiter-version>6.1.3</junit-jupiter-version>
<junit-platform-version>6.1.3</junit-platform-version>
<!-- 1. Testing: 1.2 jqwik -->
<!-- Pinned to 1.9.3 (newest 1.9.x): the jqwik 1.10.x engine is not stable under
Ares here. Running the full suite, its lifecycle store hits a concurrent
modification (ArrayIndexOutOfBoundsException in StoreRepository.streamAllStores)
when Ares executes thread-spawning jqwik properties, failing JqwickTest
deterministically; 1.9.3 is green. The 1.10.x line also moved to
junit-platform 1.14 while this project builds on junit-platform 6.x, which
likely contributes. Revisit once jqwik ships a JUnit 6 compatible release. -->
<jqwik-version>1.9.3</jqwik-version>
<!-- 1. Testing: 1.3 AssertJ -->
<assertj-version>3.27.7</assertj-version>
<!-- 1. Testing: 1.4 Mockito -->
<mockito-version>5.23.0</mockito-version>
<!-- 2. Architecture: 2.1 Archunit -->
<archunit-version>1.5.0</archunit-version>
<!-- 2. Architecture: 2.2 Wala -->
<wala-version>1.8.0</wala-version>
<!-- Test fixture: genuine third-party JAR in the javax.* namespace -->
<javax-activation-version>1.2.0</javax-activation-version>
<!-- 3. AOP: 3.1 AspectJ -->
<!-- aspectjtools (ajc) 1.9.25 / 1.9.25.1 bundle an Eclipse JDT compiler that throws
an internal NullPointerException ("variableDeclaration is null",
SourceTypeBinding.resolveTypeFor) when weaving an anonymous class that declares
fields. The four JavaInstrumentation*PathMethodAdviceTest classes were refactored
to use named nested classes instead of field-declaring anonymous classes, which
sidesteps that ajc crash, so the toolchain runs cleanly on 1.9.25.1. -->
<aspectj-version>1.9.25.1</aspectj-version>
<aspectj-path>
${user.home}${file.separator}.m2${file.separator}repository${file.separator}org${file.separator}aspectj${file.separator}aspectjrt${file.separator}${aspectj-version}${file.separator}aspectjrt-${aspectj-version}.jar
</aspectj-path>
<!-- 3. AOP: 3.2 Byte Buddy -->
<byte-buddy-version>1.18.13</byte-buddy-version>
<byte-buddy-path>
${project.build.directory}${file.separator}${project.artifactId}-${project.version}-agent.jar
</byte-buddy-path>
<!-- 3. AOP: 3.3 JVM module access -->
<!-- The AspectJ aspects (and the Byte Buddy advice) reflectively read fields of
intercepted JDK objects (e.g. ThreadPoolExecutor.ctl, Socket.delegate,
Executors$AutoShutdownDelegatedExecutorService.cleanable). Under JDK 16+ strong
encapsulation these reads require the corresponding java.base packages to be opened.
This mirrors the jvmArgs the runtime Gradle build applies; without it the test JVM
throws InaccessibleObjectException and the security analysis cannot introspect the
intercepted objects. Student attacks remain blocked by Ares's AOP advice and the
architecture rules, which do not depend on JVM strong encapsulation. -->
<jvm.module.access.args>--add-exports java.base/java.lang=ALL-UNNAMED --add-exports java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.nio.channels=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens java.base/java.util.concurrent.locks=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens jdk.unsupported/sun.misc=ALL-UNNAMED</jvm.module.access.args>
<!-- 4. AST: 4.1 JavaParser -->
<java-parser-version>3.28.2</java-parser-version>
<!-- 5. Formats: YAML and XML (JSON handled via Jackson) -->
<yaml-version>2.22.2</yaml-version>
<!-- 6. Large Tooling Libraries -->
<commons-io-version>2.22.0</commons-io-version>
<jaxb-api-version>2.3.1</jaxb-api-version>
<!-- 7. Small Tooling Libraries -->
<jgrapht-core-version>1.5.3</jgrapht-core-version>
<!-- 8. Logging -->
<logback-version>1.6.3</logback-version>
<!-- 8. API -->
<apiguardian-api-version>1.1.2</apiguardian-api-version>
<!-- Others -->
<spotless.version>3.10.2</spotless.version>
<!-- if JaCoCo is not executed -->
<argLine></argLine>
<!-- Isolate test classes so WALA state and test-created threads cannot accumulate
in one long-lived JVM. The signed outcome cache preserves cross-fork reuse. -->
<surefire-reuse-forks>false</surefire-reuse-forks>
<!-- The fork heap, as a property for the same reason `surefire-reuse-forks` is one: a
profile that changes how tests are isolated usually has to change how much heap that
isolation needs, and overriding the whole `argLine` to do so would duplicate the
agent and bootclasspath arguments into every profile that tried. -->
<surefire-max-heap>6g</surefire-max-heap>
<jacoco-version>0.8.15</jacoco-version>
<!-- BUNDLE-level minima, shared by the `coverage` profile (one local full-suite
run) and the `coverage-aggregate` profile (the merged CI runs) so that the two
gates cannot drift apart. -->
<jacoco-line-coverage-minimum>0.55</jacoco-line-coverage-minimum>
<jacoco-branch-coverage-minimum>0.35</jacoco-branch-coverage-minimum>
<jacoco-method-coverage-minimum>0.65</jacoco-method-coverage-minimum>
<!-- full certificate fingerprint: 23E62BB282A473EE4DDA2F8763EFD39363D21A8D -->
<gpg.key.id>23E62BB282A473EE4DDA2F8763EFD39363D21A8D</gpg.key.id>
</properties>
<dependencyManagement>
<dependencies>
<!-- Pin opencsv's transitive commons-lang3 to a current version. opencsv's
bean-mapping transitives (commons-beanutils, commons-text) are excluded on
the opencsv dependency itself since Ares only uses opencsv's raw CSV reader,
not its bean features. commons-lang3 cannot be excluded: opencsv's
CSVReader/CSVParser call it at construction time. -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.20.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 1. Testing: 1.1 JUnit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit-jupiter-version}</version>
<!-- 3 Cases:
src/test/java/de/tum/cit/ase/ares/api/util/LruCacheTest.java
src/test/java/de/tum/cit/ase/ares/api/util/ClassMemberAccessorTest.java
src/test/java/de/tum/cit/ase/ares/integration/testuser/NetworkUser.java
-->
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter-version}</version>
<!-- 1 Case:
src/test/java/de/tum/cit/ase/ares/testutilities/UserBased.java
-->
</dependency>
<!-- JUnit 4 API only (no vintage engine): there are no JUnit 4 tests to run, but
the throwable sanitization compiles against junit.framework.* and
org.junit.* (JUnit 4) types so it can duplicate/sanitize legacy assertion
errors. junit-vintage-engine was removed; this supplies just the API.
2 Cases:
src/main/java/de/tum/cit/ase/ares/api/internal/sanitization/SafeTypeThrowableSanitizer.java
src/main/java/de/tum/cit/ase/ares/api/internal/sanitization/ThrowableSets.java
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-testkit</artifactId>
<version>${junit-platform-version}</version>
<!-- Multiple Cases -->
</dependency>
<!-- Not Required
Included in junit-jupiter-params and junit-jupiter-engine
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter-version}</version>
</dependency>
Included in junit-platform-testkit
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit-platform-version}</version>
</dependency>
-->
<!-- 1. Testing: 1.2 jqwik -->
<dependency>
<groupId>net.jqwik</groupId>
<artifactId>jqwik</artifactId>
<version>${jqwik-version}</version>
<scope>provided</scope>
<!-- Multiple Cases -->
</dependency>
<!-- 1. Testing: 1.3 Mockito -->
<!-- mockito-inline was discontinued after 5.2.0; its inline mock-maker is the
default in mockito-core since 5.x, so we depend on mockito-core directly. -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-version}</version>
<!-- Multiple Cases -->
</dependency>
<!-- 1. Testing: 1.4 AssertJ -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-version}</version>
</dependency>
<!-- 2. Architecture: 2.1 Archunit -->
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<version>${archunit-version}</version>
<!-- 1 Case:
src/main/java/de/tum/cit/ase/ares/api/securitytest/java/specific/PathLocationProvider.java
-->
</dependency>
<!-- Not required
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
<version>${archunit-version}</version>
</dependency>
-->
<!-- 2. Architecture: 2.2 Wala -->
<dependency>
<groupId>com.ibm.wala</groupId>
<artifactId>com.ibm.wala.core</artifactId>
<version>${wala-version}</version>
<!-- Multiple Cases -->
</dependency>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>${javax-activation-version}</version>
<scope>test</scope>
<!-- Regression fixture for origin-based WALA dependency classification -->
</dependency>
<!-- 3. AOP: 3.1 AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj-version}</version>
</dependency>
<!-- Not required
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj-version}</version>
</dependency>
-->
<!-- 3. AOP: 3.2 Byte Buddy -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy-version}</version>
<!-- Multiple Cases -->
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>${byte-buddy-version}</version>
<!-- Multiple Cases -->
</dependency>
<!-- 4. AST: 4.1 JavaParser -->
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-symbol-solver-core</artifactId>
<version>${java-parser-version}</version>
<!-- 1. Case:
src/main/java/de/tum/cit/ase/ares/api/ast/model/RecursionCheck.java
-->
</dependency>
<!-- Not Required
Included in javaparser-symbol-solver-core
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${java-parser-version}</version>
</dependency>
-->
<!-- 5. Formats: YAML, XML and JSON (all via Jackson) -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${yaml-version}</version>
</dependency>
<!-- 6. Large Tooling Libraries -->
<!-- commons-io is NOT used by Ares itself; it is only a security-interception
target so the AspectJ pointcut and instrumentation policy can reference
org.apache.commons.io.FileUtils.forceDelete (a way students could delete
files). It is scoped 'provided' so it stays on the compile/weave/test
classpath (keeping that interception resolvable) without leaking into the
runtime/transitive footprint of Ares consumers. -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io-version}</version>
<scope>provided</scope>
</dependency>
<!-- javax.xml.bind (JAXB) is NOT used by Ares itself; it is only a
security-interception target so the AspectJ pointcut
(JavaAspectJFileSystemPointcutDefinitions.aj) can reference
javax.xml.bind.Marshaller/Unmarshaller (I-086/TD-030 - the JDK removed JAXB
as a standard module from Java 11 onwards, so these pointcuts otherwise
reference types absent from the compile/weave classpath entirely and are
unverifiable). Scoped 'provided' for the same reason as commons-io above:
keep the interception resolvable without leaking into consumers' transitive
footprint. -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api-version}</version>
<scope>provided</scope>
</dependency>
<!-- 7. Small Tooling Libraries -->
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.12.0</version>
<exclusions>
<exclusion>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<version>${jgrapht-core-version}</version>
</dependency>
<!-- 8. Logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-version}</version>
</dependency>
<!-- 8. API -->
<dependency>
<groupId>org.apiguardian</groupId>
<artifactId>apiguardian-api</artifactId>
<version>${apiguardian-api-version}</version>
</dependency>
<!-- Add JSR-305 for javax.annotation.Nonnull/Nullable -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
<resource>
<!-- I-062: shipping .java/.aj source from src/main/java as a resource looks
like incidental packaging bloat at a glance, but it is a genuine, traced
runtime dependency, not incidental: AspectJAJCopyFiles.csv (also under
src/main/java, see the '**/*.csv' include below) lists these exact source
files as copy 'Source' entries, consumed at runtime by JavaCSVFileLoader
via FileTools.resolveFileOnSourceDirectory - the code-generation flow that
assembles a consuming project's woven security test case reads these
shipped .aj/.java files back out of this jar. Narrowing this resource's
includes without also changing that CSV-driven flow would silently break
AOP test-case generation for consumers; do not narrow it in isolation. -->
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.aj</include>
<include>**/*.properties</include>
<include>**/*.yaml</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
<include>**/*.csv</include>
<include>**/*.txt</include>
<include>**/*.md</include>
<include>**/*.cfg</include>
<include>**/*.so</include>
<include>**/*.sh</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<!-- 1. Clean -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.5.0</version>
</plugin>
<!-- 2. Validate -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>enforce-versions</id>
<phase>validate</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>[3.9,)</version>
</requireMavenVersion>
<requireJavaVersion>
<version>[9,)</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
<execution>
<id>enforce-no-student-code-in-trusted-packages</id>
<phase>process-test-classes</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireFilesDontExist>
<files>
<!-- Required for de.tum.cit.ase.ares.api.security.ArtemisSecurityConfigurationTest -->
<!-- <file>${project.build.outputDirectory}/abc/def/</file> -->
<file>${project.build.outputDirectory}/ch/qos/logback/</file>
<file>${project.build.outputDirectory}/com/github/javaparser/</file>
<file>${project.build.outputDirectory}/com/intellij/</file>
<file>${project.build.outputDirectory}/com/sun/</file>
<!-- We cannot fulfill this one because we are building those classes here
<file>${project.build.outputDirectory}/de/tum/cit/ase/ares/api/</file> -->
<file>${project.build.outputDirectory}/de/tum/in/test/api/</file>
<file>${project.build.outputDirectory}/java/</file>
<file>${project.build.outputDirectory}/javax/</file>
<file>${project.build.outputDirectory}/jdk/</file>
<file>${project.build.outputDirectory}/net/jqwik/</file>
<file>${project.build.outputDirectory}/org/apache/</file>
<file>${project.build.outputDirectory}/org/assertj/</file>
<file>${project.build.outputDirectory}/org/eclipse/</file>
<file>${project.build.outputDirectory}/org/jacoco/</file>
<file>${project.build.outputDirectory}/org/json/</file>
<file>${project.build.outputDirectory}/org/junit/</file>
<file>${project.build.outputDirectory}/org/opentest4j/</file>
<file>${project.build.outputDirectory}/sun/</file>
<file>${project.build.outputDirectory}/org/gradle/</file>
<file>${project.build.outputDirectory}/worker/org/gradle/</file>
</files>
</requireFilesDontExist>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<!-- 3. Compile -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.16.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.5.0</version>
</plugin>
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.1</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<!-- Kept in sync with the aspectjrt runtime via the shared property;
see the aspectj-version note for why this is pinned to 1.9.24. -->
<artifactId>aspectjtools</artifactId>
<version>${aspectj-version}</version>
</dependency>
</dependencies>
<configuration>
<forceAjcCompile>true</forceAjcCompile>
<complianceLevel>17</complianceLevel>
<source>17</source>
<target>17</target>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
<executions>
<execution>
<id>weave-test-classes</id>
<phase>process-test-classes</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
<execution>
<id>weave-main-classes</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 4. Test -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<forkCount>1</forkCount>
<!-- Use a fresh fork for every test class. WALA's mutable scope and graph,
instrumentation state and non-daemon threads therefore cannot accumulate
across the complete suite. -->
<reuseForks>${surefire-reuse-forks}</reuseForks>
<!-- Kill (and report) a hung forked JVM rather than letting CI run until
the runner dies. 2400s sits above a legitimate full-suite run yet below
the 45-minute CI job timeout, so a real hang is caught with a report. -->
<forkedProcessTimeoutInSeconds>2400</forkedProcessTimeoutInSeconds>
<argLine>@{argLine} -Xmx${surefire-max-heap} -javaagent:${byte-buddy-path} -Xbootclasspath/a:${aspectj-path} ${jvm.module.access.args}</argLine>
</configuration>
</plugin>
<!-- 5. Package -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>process-classes</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<manifestEntries>
<Sealed>true</Sealed>
<Premain-Class>de.tum.cit.ase.ares.api.aop.java.instrumentation.JavaInstrumentationAgent</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix>
<Boot-Class-Path></Boot-Class-Path>
</manifestEntries>
</archive>
<includes>
<include>**/*.class</include>
<include>**/*.java</include>
<include>**/*.aj</include>
<include>**/*.properties</include>
<include>**/*.yaml</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
<include>**/*.csv</include>
<include>**/*.txt</include>
<include>**/*.md</include>
<include>**/*.cfg</include>
<include>**/*.so</include>
<include>**/*.sh</include>
<include>**/META-INF/**</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.12.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<failOnError>true</failOnError>
<tags>
<tag>
<name>apiNote</name>
<placement>a</placement>
<head>API Note:</head>
</tag>
<tag>
<name>implSpec</name>
<placement>a</placement>
<head>Implementation Requirements:</head>
</tag>
<tag>
<name>implNote</name>
<placement>a</placement>
<head>Implementation Note:</head>
</tag>
<tag>
<name>param</name>
</tag>
<tag>
<name>return</name>
</tag>
<tag>
<name>throws</name>
</tag>
<tag>
<name>since</name>
</tag>
<tag>
<name>version</name>
</tag>
<tag>
<name>serialData</name>
</tag>
<tag>
<name>see</name>
</tag>
</tags>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.4</version>
<executions>
<execution>
<id>install-main-jar</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}${file.separator}${project.build.finalName}.jar</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
</configuration>
</execution>
<execution>
<id>install-pom</id>
<phase>package</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${basedir}${file.separator}pom.xml
</file> <!-- Ensure this is correctly pointing to your POM file -->
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>pom</packaging>
</configuration>
</execution>
<execution>
<id>install-javadoc-jar</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}${file.separator}${project.build.finalName}-javadoc.jar
</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<classifier>javadoc</classifier>
</configuration>
</execution>
<execution>
<id>install-sources-jar</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}${file.separator}${project.build.finalName}-sources.jar
</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<classifier>sources</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.2</version>
<executions>
<!-- Create agent jar before tests so surefire -javaagent path exists -->
<execution>
<id>shade-agent-before-test</id>
<phase>process-classes</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>agent</shadedClassifierName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Premain-Class>
de.tum.cit.ase.ares.api.aop.java.instrumentation.JavaInstrumentationAgent
</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix>
<Boot-Class-Path></Boot-Class-Path>
</manifestEntries>
</transformer>
</transformers>
<artifactSet>
<includes>
<include>de.tum.cit.ase:ares</include>
</includes>
</artifactSet>
<!-- Surefire loads this agent jar via -javaagent, which makes the JVM append it to
the system classpath next to target/classes. Both then carry logback.xml, so logback
reports it "occurs multiple times on the classpath". Dropping the copy from this
test-only agent jar removes the duplicate while leaving the package-time agent jar
(the distributed artifact) byte-for-byte unchanged. -->
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>logback.xml</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
<!-- Keep existing package-time shaded agent -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>agent</shadedClassifierName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Premain-Class>
de.tum.cit.ase.ares.api.aop.java.instrumentation.JavaInstrumentationAgent
</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix>
<Boot-Class-Path></Boot-Class-Path>
</manifestEntries>
</transformer>
</transformers>
<artifactSet>
<includes>
<include>de.tum.cit.ase:ares</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<!-- 6. Verify -->
<!-- 7. Install -->
<!-- 8. Site -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.22.0</version>
</plugin>
<!-- 9. Deploy -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.4</version>
</plugin>
<!-- Manual execution -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.21.0</version>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<formats>
<format>
<!-- This format mixes pom.xml (LF) with files using the CRLF default.
Resolve each file separately because FAST_ALLSAME uses the first file's ending for all. -->
<lineEndings>GIT_ATTRIBUTES</lineEndings>
<includes>
<include>*.xml</include>
<include>*.java</include>
<include>.gitignore</include>
</includes>
<trimTrailingWhitespace/>
<endWithNewline/>
<indent>
<tabs>true</tabs>
<spacesPerTab>4</spacesPerTab>
</indent>
</format>
</formats>
<java>
<removeUnusedImports/>
<importOrder>
<file>${basedir}${file.separator}.settings${file.separator}eclipse-rules.importorder</file>
</importOrder>
<eclipse>
<version>4.17.0</version>
<file>${basedir}${file.separator}.settings${file.separator}eclipse-formatter-rules.xml
</file>
</eclipse>
</java>
</configuration>
</plugin>
<!-- Static analysis: these goals are bound to package, so a local build crosses the
same gate. CI runs it once, in the job named after it, and turns it off elsewhere
with the without-quality-gates profile below.
The rule sets in .settings are trimmed so that no rule contradicts the formatter,
which owns indentation and import order, and none objects to a deliberate security
idiom. What is left fails the build rather than warning. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<configLocation>${basedir}${file.separator}.settings${file.separator}checkstyle-rules.xml</configLocation>
<suppressionsLocation>${basedir}${file.separator}.settings${file.separator}checkstyle-suppressions.xml</suppressionsLocation>
<!-- Test sources carry the harness that decides whether a security violation was
detected. Leaving them out meant the code most able to fail silently was the code
nobody checked. Fixtures and the underscore naming convention are handled in the
suppressions file; see the reasoning there. -->
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<failOnViolation>true</failOnViolation>
<failsOnError>true</failsOnError>
<violationSeverity>error</violationSeverity>
<consoleOutput>true</consoleOutput>
</configuration>
<executions>
<execution>
<id>checkstyle-quality-gate</id>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.28.0</version>
<configuration>
<rulesets>
<ruleset>${basedir}${file.separator}.settings${file.separator}pmd-rules.xml</ruleset>
</rulesets>
<excludeFromFailureFile>${basedir}${file.separator}.settings${file.separator}cpd-allowed-duplications.txt</excludeFromFailureFile>
<!-- Test sources carry the harness that decides whether a security violation was
detected, so leaving them unanalysed left exactly the code whose defects fail silently.
The fixtures are excluded in the ruleset rather than here, because the boundary is
"is this an assertion or is this the thing being asserted about", not "main or test". -->
<includeTests>true</includeTests>
<failOnViolation>true</failOnViolation>
<printFailingErrors>true</printFailingErrors>
</configuration>
<executions>
<execution>
<id>pmd-quality-gate</id>
<phase>package</phase>
<goals>
<goal>check</goal>
<goal>cpd-check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.10.4.1</version>
<configuration>
<excludeFilterFile>${basedir}${file.separator}.settings${file.separator}spotbugs-exclude.xml</excludeFilterFile>
<failOnError>true</failOnError>
</configuration>
<executions>
<execution>
<id>spotbugs-quality-gate</id>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<name>Ares</name>
<description>A JUnit 5 Extension for secure Artemis Java Testing.</description>
<url>https://github.com/ls1intum/Ares2</url>
<inceptionYear>2024</inceptionYear>
<licenses>
<license>
<name>MIT</name>
<url>https://opensource.org/licenses/MIT</url>
<comments>See https://github.com/ls1intum/Ares2/blob/master/LICENSE</comments>
</license>
</licenses>
<organization>
<name>Technical University of Munich, School of Computation, Information and Technology , Research Group Applied
Software Engineering
</name>
<url>https://ase.cit.tum.de/</url>
</organization>
<developers>
<developer>
<id>MarkusPaulsen</id>
<name>Markus Paulsen</name>
<email>markus.paulsen@tum.de</email>
<url>https://ase.cit.tum.de/people/paulsen/</url>
<organization>Technical University of Munich, School of Computation, Information and Technology , Research
Group Applied Software Engineering
</organization>
<organizationUrl>https://ase.cit.tum.de/</organizationUrl>
<roles>
<role>Scientific Researcher</role>
</roles>
<timezone>Europe/Berlin</timezone>
</developer>
<developer>
<id>SarpSahinalp</id>
<name>Sarp Sahinalp</name>
<email>sarp.sahinalp@tum.de</email>
<url>https://ase.cit.tum.de/people/paulsen/</url>
<organization>Technical University of Munich, School of Computation, Information and Technology , Research
Group Applied Software Engineering
</organization>
<organizationUrl>https://ase.cit.tum.de/</organizationUrl>
<roles>
<role>Thesis Student</role>
</roles>
<timezone>Europe/Berlin</timezone>
</developer>
<developer>
<id>AnirudhZaveri</id>
<name>Anirudh Zaveri</name>
<email>anirudh.zaveri@tum.de</email>
<url>https://ase.cit.tum.de/people/paulsen/</url>
<organization>Technical University of Munich, School of Computation, Information and Technology , Research
Group Applied Software Engineering
</organization>
<organizationUrl>https://ase.cit.tum.de/</organizationUrl>
<roles>
<role>Thesis Student</role>
</roles>
<timezone>Europe/Berlin</timezone>
</developer>
</developers>
<contributors>
<contributor>
<name>Christian Femers</name>
<email>christian.femers@tum.de</email>
<organization>Technical University of Munich</organization>
<organizationUrl>https://www.tum.de</organizationUrl>
<roles>
<role>Creator of Ares 1.0</role>
</roles>
<timezone>Europe/Berlin</timezone>
</contributor>
</contributors>
<scm>
<url>https://github.com/ls1intum/Ares2</url>
<connection>scm:git:https://github.com/ls1intum/Ares2.git</connection>
<developerConnection>scm:git:https://github.com/ls1intum/Ares2.git</developerConnection>
</scm>
<profiles>
<!-- Test selection for CI. Architecture tests run separately from functional tests.
The functional AOP integration tests are selected by method name in the CI workflow,
one job for each architecture/AOP mode combination. Neither profile is active by
default, so a plain `mvn test` still runs the whole suite locally and for any
downstream consumer.
The architecture tests are selected by package rather than moved into a directory of
their own: 13 of them sit in the same package as the code they exercise and call its
package-private members, so moving them would mean widening the visibility of the
security internals purely to satisfy a CI layout. -->
<profile>
<id>architecture-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/integration/architecture/**/*Test.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>functional-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/api/architecture/**/*Test.java</exclude>
<exclude>**/integration/architecture/**/*Test.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>unit-core-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<reuseForks>true</reuseForks>
<includes>
<include>**/api/**/*Test.java</include>
<!-- I-111/TD-060: testutilities/** hosts plain unit tests (e.g.
NonDaemonThreadLeakExtensionTest, PublicTestNamingConventionTest)
that need no woven AOP/architecture-mode setup, but sit outside
api/** and integration/**, so no profile ran them before this
include was added. -->
<include>**/testutilities/**/*Test.java</include>
<!-- The same omission a second time: documentation/** holds the tests
that read documentation/docs directly, they need no woven setup
either, and no profile selected them, so the whole suite passed
locally and never ran here. TestProfileCoverageTest now fails the
build when a test class is left out of every profile CI runs. -->
<include>**/documentation/**/*Test.java</include>
</includes>
<excludes>
<exclude>**/api/architecture/**/*Test.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>unit-architecture-tests</id>
<properties>
<!-- One long-lived fork instead of nineteen short ones needs a stated ceiling
rather than the default, because the reason that default exists is the
opposite case. Measured peak resident size of the reused fork at 6g was
3.12 GB and 3.95 GB across two runs, a spread wide enough that the only real
bound was `-Xmx` itself. 3g bounds it deliberately, and three runs at that
ceiling peaked at 1.76, 2.20 and 1.83 GB. -->
<surefire-max-heap>3g</surefire-max-heap>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- These 19 classes share one fork, as `unit-core-tests` and
`integration-core-tests` already do. Without this the profile inherits
`surefire-reuse-forks`, which the `coverage` profile sets to false, and
every class pays a full JVM start: measured at roughly 15.5 s per fork
in CI, against 105 s of actual test time for the whole set.
Whether WALA state survives a shared fork is not settled by argument,
so it was measured: five runs of this profile, all 19 classes and all
188 tests green, peak resident size 1.76 to 2.20 GB at the 3g ceiling.
The integration matrix in maven.yml has run the WALA modes with
`-Dsurefire-reuse-forks=true` all along, which is a related but not
identical case: it selects methods rather than whole classes. If this
profile ever turns flaky, this line is the first thing to revert. -->
<reuseForks>true</reuseForks>
<includes>
<include>**/api/architecture/**/*Test.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>integration-core-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<reuseForks>true</reuseForks>
<includes>
<include>**/integration/**/*Test.java</include>
</includes>
<excludes>
<exclude>**/integration/architecture/**/*Test.java</exclude>
<exclude>**/integration/aop/allowed/**/*Test.java</exclude>
<exclude>**/integration/aop/forbidden/**/*Test.java</exclude>
<!-- Executed by the dedicated jqwik step because it starts a nested jqwik
engine, not because it requires a separate fork. -->
<exclude>**/integration/JqwickTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- For code coverage using JaCoCo -->
<profile>
<id>coverage</id>
<properties>
<!-- Each test class receives a fresh JVM under coverage. JaCoCo appends each
fork's execution data, avoiding the long-lived >5 GB process and preserving
the complete aggregate report. -->
<surefire-reuse-forks>false</surefire-reuse-forks>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-version}</version>
<executions>
<execution>
<id>prepare-coverage-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
<inclBootstrapClasses>true</inclBootstrapClasses>
<!-- `api` is the only package under src/main/java, so this covers
everything the report is generated for, and nothing else. A new
top-level package under src/main/java has to be added here, or it
reports as entirely uncovered. That is the intended direction of
failure: an omission here is loud in the report, whereas the
opposite mistake is not. The wider
`de.tum.cit.ase.ares.*` also instrumented the integration test
subjects, which are the very classes Ares analyses and enforces
against. A second agent rewriting them changes the artefact under
test: three architecture tests of the ArchUnit/AspectJ combination
then observe a different violation than the one they expect.
Instrumenting test code yielded no coverage data in any case, as
only src/main/java is reported on. -->
<includes>
<include>de.tum.cit.ase.ares.api.*</include>
</includes>
</configuration>
</execution>
<execution>
<id>coverage-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>coverage-threshold</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-line-coverage-minimum}</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-branch-coverage-minimum}</minimum>
</limit>
<limit>
<counter>METHOD</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-method-coverage-minimum}</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Merges the per-job JaCoCo execution data collected by the `coverage` profile
into one report. CI splits the suite across seven jobs, each covering a
disjoint slice, so a single job's execution data says nothing about the
BUNDLE-level rule above; only the merged data does. The rule itself is shared
with the `coverage` profile through the threshold properties, so a local
full-suite run and the CI aggregate are measured against the same minima. -->
<profile>
<id>coverage-aggregate</id>
<properties>
<!-- Directory the CI job downloads the per-job execution-data artefacts into.
Each artefact unpacks into a subdirectory of its own, hence the recursive
include below rather than a flat one. -->
<jacoco-exec-directory>${project.build.directory}/jacoco-exec</jacoco-exec-directory>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-version}</version>
<executions>
<!-- The three executions share the verify phase and therefore run in
declaration order: merge, then report, then check. -->
<execution>
<id>merge-coverage-data</id>
<phase>verify</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${jacoco-exec-directory}</directory>
<includes>
<include>**/*.exec</include>
</includes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/jacoco.exec</destFile>
</configuration>
</execution>
<execution>
<id>aggregated-coverage-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
</configuration>
</execution>
<execution>
<id>aggregated-coverage-threshold</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-line-coverage-minimum}</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-branch-coverage-minimum}</minimum>
</limit>
<limit>
<counter>METHOD</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco-method-coverage-minimum}</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Turns the whole quality gate off for a single Maven invocation. Checkstyle, PMD,
CPD and SpotBugs are bound to package above, so every command that reaches that
phase runs them, whether or not checking the code was the point of the command.
CI activates this profile wherever it was not, so the gate is enforced once
rather than in every job that happens to package the project. The profile is not
active by default, so a local build still crosses the gate. -->
<profile>
<id>without-quality-gates</id>
<properties>
<!-- Spotless has no execution of its own and is invoked as a goal by the job that
owns the gate, so this property changes nothing today. It is here so that
binding spotless:check to a phase later cannot put it back into the builds
that opted out, silently and without a second edit. -->
<spotless.skip>true</spotless.skip>
<checkstyle.skip>true</checkstyle.skip>
<pmd.skip>true</pmd.skip>
<cpd.skip>true</cpd.skip>
<spotbugs.skip>true</spotbugs.skip>
</properties>
</profile>
<!-- This is only for GitHub -->
<profile>
<id>github</id>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub LS1TUM Apache Maven Packages</name>
<url>https://maven.pkg.github.com/ls1intum/Ares</url>
</repository>
<!-- GitHub cannot handle snapshots correctly now, so we do nothing -->
<snapshotRepository>
<id>internal</id>
<url>file://${project.build.directory}${file.separator}mvn-repo</url>
</snapshotRepository>
</distributionManagement>
</profile>
<!-- Profile for fast builds and tests (~ 16 s) -->
<profile>
<id>fast</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<forkCount>1</forkCount>
<forkedProcessTimeoutInSeconds>2400</forkedProcessTimeoutInSeconds>
<argLine>@{argLine} -Xmx6g -javaagent:${byte-buddy-path} -Xbootclasspath/a:${aspectj-path} ${jvm.module.access.args}</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- Profile for manually deploying to Maven Central -->
<profile>
<id>ossrh</id>
<build>
<plugins>
<!-- Only sign the plugin if it's built manually for OSSRH -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.8</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<keyname>${gpg.key.id}</keyname>
<passphraseServerId>${gpg.key.id}</passphraseServerId>
<!-- This is to prevent Maven GPG not passing the passphrase correctly -->
<!-- requires GPG version 2.1 or greater -->
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.11.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>