This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new c7f22fe0d6 [MNG-8677] Bump to Resolver 2.0.8 and more (#2158)
c7f22fe0d6 is described below
commit c7f22fe0d66d69eea4631a8663b05b63b85591ac
Author: Tamas Cservenak <[email protected]>
AuthorDate: Sat Apr 12 09:11:25 2025 +0200
[MNG-8677] Bump to Resolver 2.0.8 and more (#2158)
Bump to Resolver 2.0.8, changes:
* updates Maven to Resolver 2.0.8
* implements maven specific validator (new in Resolver 2.0.8)
* applies required changes to suppliers
---
https://issues.apache.org/jira/browse/MNG-8677
---
.../impl/resolver/validator/MavenValidator.java | 93 ++++++++++++++++++++++
.../resolver/validator/MavenValidatorFactory.java | 36 +++++++++
.../impl/standalone/RepositorySystemSupplier.java | 42 +++++++++-
.../testing/stubs/RepositorySystemSupplier.java | 64 ++++++++++++++-
.../.mvn/maven.properties | 2 +
.../mng-5639-import-scope-pom-resolution/pom.xml | 5 --
pom.xml | 2 +-
7 files changed, 232 insertions(+), 12 deletions(-)
diff --git
a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidator.java
b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidator.java
new file mode 100644
index 0000000000..3726a7719f
--- /dev/null
+++
b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidator.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl.resolver.validator;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.spi.validator.Validator;
+
+/**
+ * Simplest Maven specific validator that is meant to prevent un-interpolated
+ * elements enter resolver; if it does, is most likely some bug.
+ */
+public class MavenValidator implements Validator {
+ protected boolean containsPlaceholder(String value) {
+ return value != null && value.contains("${");
+ }
+
+ @Override
+ public void validateArtifact(Artifact artifact) throws
IllegalArgumentException {
+ if (containsPlaceholder(artifact.getGroupId())
+ || containsPlaceholder(artifact.getArtifactId())
+ || containsPlaceholder(artifact.getVersion())
+ || containsPlaceholder(artifact.getClassifier())
+ || containsPlaceholder(artifact.getExtension())) {
+ throw new IllegalArgumentException("Not fully interpolated
artifact " + artifact);
+ }
+ }
+
+ @Override
+ public void validateMetadata(Metadata metadata) throws
IllegalArgumentException {
+ if (containsPlaceholder(metadata.getGroupId())
+ || containsPlaceholder(metadata.getArtifactId())
+ || containsPlaceholder(metadata.getVersion())
+ || containsPlaceholder(metadata.getType())) {
+ throw new IllegalArgumentException("Not fully interpolated
metadata " + metadata);
+ }
+ }
+
+ @Override
+ public void validateDependency(Dependency dependency) throws
IllegalArgumentException {
+ Artifact artifact = dependency.getArtifact();
+ if (containsPlaceholder(artifact.getGroupId())
+ || containsPlaceholder(artifact.getArtifactId())
+ || containsPlaceholder(artifact.getVersion())
+ || containsPlaceholder(artifact.getClassifier())
+ || containsPlaceholder(artifact.getExtension())
+ || containsPlaceholder(dependency.getScope())
+ || dependency.getExclusions().stream()
+ .anyMatch(e -> containsPlaceholder(e.getGroupId())
+ || containsPlaceholder(e.getArtifactId())
+ || containsPlaceholder(e.getClassifier())
+ || containsPlaceholder(e.getExtension()))) {
+ throw new IllegalArgumentException("Not fully interpolated
dependency " + dependency);
+ }
+ }
+
+ @Override
+ public void validateLocalRepository(LocalRepository localRepository)
throws IllegalArgumentException {
+ if (containsPlaceholder(localRepository.getBasePath().toString())
+ || containsPlaceholder(localRepository.getContentType())
+ || containsPlaceholder(localRepository.getId())) {
+ throw new IllegalArgumentException("Not fully interpolated local
repository " + localRepository);
+ }
+ }
+
+ @Override
+ public void validateRemoteRepository(RemoteRepository remoteRepository)
throws IllegalArgumentException {
+ if (containsPlaceholder(remoteRepository.getUrl())
+ || containsPlaceholder(remoteRepository.getContentType())
+ || containsPlaceholder(remoteRepository.getId())) {
+ throw new IllegalArgumentException("Not fully interpolated remote
repository " + remoteRepository);
+ }
+ }
+}
diff --git
a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidatorFactory.java
b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidatorFactory.java
new file mode 100644
index 0000000000..57039f9b23
--- /dev/null
+++
b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/validator/MavenValidatorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl.resolver.validator;
+
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Singleton;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.spi.validator.Validator;
+import org.eclipse.aether.spi.validator.ValidatorFactory;
+
+@Named
+@Singleton
+public class MavenValidatorFactory implements ValidatorFactory {
+ private final MavenValidator instance = new MavenValidator();
+
+ @Override
+ public Validator newInstance(RepositorySystemSession
repositorySystemSession) {
+ return instance;
+ }
+}
diff --git
a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
index 50832df1d6..7089b9fb66 100644
---
a/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
+++
b/impl/maven-impl/src/main/java/org/apache/maven/impl/standalone/RepositorySystemSupplier.java
@@ -18,11 +18,13 @@
*/
package org.apache.maven.impl.standalone;
+import java.util.List;
import java.util.Map;
import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Provides;
+import org.apache.maven.impl.resolver.validator.MavenValidatorFactory;
import org.eclipse.aether.RepositoryListener;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
@@ -40,6 +42,7 @@
import org.eclipse.aether.impl.RepositoryConnectorProvider;
import org.eclipse.aether.impl.RepositoryEventDispatcher;
import org.eclipse.aether.impl.RepositorySystemLifecycle;
+import org.eclipse.aether.impl.RepositorySystemValidator;
import org.eclipse.aether.impl.UpdateCheckManager;
import org.eclipse.aether.impl.UpdatePolicyAnalyzer;
import org.eclipse.aether.impl.VersionRangeResolver;
@@ -62,6 +65,7 @@
import org.eclipse.aether.internal.impl.DefaultRepositoryLayoutProvider;
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
import org.eclipse.aether.internal.impl.DefaultRepositorySystemLifecycle;
+import org.eclipse.aether.internal.impl.DefaultRepositorySystemValidator;
import org.eclipse.aether.internal.impl.DefaultTrackingFileManager;
import org.eclipse.aether.internal.impl.DefaultTransporterProvider;
import org.eclipse.aether.internal.impl.DefaultUpdateCheckManager;
@@ -85,8 +89,10 @@
import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector;
import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector;
import
org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager;
+import
org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory;
import
org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource;
import
org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource;
+import
org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory;
import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory;
import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
@@ -105,6 +111,7 @@
import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory;
import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource;
import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
@@ -121,6 +128,7 @@
import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
import org.eclipse.aether.spi.synccontext.SyncContextFactory;
+import org.eclipse.aether.spi.validator.ValidatorFactory;
/**
* DI Bridge for Maven Resolver
@@ -177,8 +185,8 @@ static UpdatePolicyAnalyzer newUpdatePolicyAnalyzer() {
@Provides
static RepositoryConnectorProvider newRepositoryConnectorProvider(
Map<String, RepositoryConnectorFactory> connectorFactories,
- RemoteRepositoryFilterManager remoteRepositoryFilterManager) {
- return new DefaultRepositoryConnectorProvider(connectorFactories,
remoteRepositoryFilterManager);
+ Map<String, PipelineRepositoryConnectorFactory>
pipelineConnectorFactories) {
+ return new DefaultRepositoryConnectorProvider(connectorFactories,
pipelineConnectorFactories);
}
@Named("basic")
@@ -197,6 +205,20 @@ static BasicRepositoryConnectorFactory
newBasicRepositoryConnectorFactory(
providedChecksumsSources);
}
+ @Named(OfflinePipelineRepositoryConnectorFactory.NAME)
+ @Provides
+ static OfflinePipelineRepositoryConnectorFactory
newOfflinePipelineConnectorFactory(
+ OfflineController offlineController) {
+ return new
OfflinePipelineRepositoryConnectorFactory(offlineController);
+ }
+
+ @Named(FilteringPipelineRepositoryConnectorFactory.NAME)
+ @Provides
+ static FilteringPipelineRepositoryConnectorFactory
newFilteringPipelineConnectorFactory(
+ RemoteRepositoryFilterManager remoteRepositoryFilterManager) {
+ return new
FilteringPipelineRepositoryConnectorFactory(remoteRepositoryFilterManager);
+ }
+
@Provides
static RepositoryLayoutProvider newRepositoryLayoutProvider(Map<String,
RepositoryLayoutFactory> layoutFactories) {
return new DefaultRepositoryLayoutProvider(layoutFactories);
@@ -245,6 +267,16 @@ static PathProcessor newPathProcessor() {
return new DefaultPathProcessor();
}
+ @Provides
+ static List<ValidatorFactory> newValidatorFactories() {
+ return List.of(new MavenValidatorFactory());
+ }
+
+ @Provides
+ static RepositorySystemValidator
newRepositorySystemValidator(List<ValidatorFactory> validatorFactories) {
+ return new DefaultRepositorySystemValidator(validatorFactories);
+ }
+
@Provides
static RepositorySystem newRepositorySystem(
VersionResolver versionResolver,
@@ -259,7 +291,8 @@ static RepositorySystem newRepositorySystem(
SyncContextFactory syncContextFactory,
RemoteRepositoryManager remoteRepositoryManager,
RepositorySystemLifecycle repositorySystemLifecycle,
- @Nullable Map<String, ArtifactDecoratorFactory>
artifactDecoratorFactories) {
+ @Nullable Map<String, ArtifactDecoratorFactory>
artifactDecoratorFactories,
+ RepositorySystemValidator repositorySystemValidator) {
return new DefaultRepositorySystem(
versionResolver,
versionRangeResolver,
@@ -273,7 +306,8 @@ static RepositorySystem newRepositorySystem(
syncContextFactory,
remoteRepositoryManager,
repositorySystemLifecycle,
- artifactDecoratorFactories != null ?
artifactDecoratorFactories : Map.of());
+ artifactDecoratorFactories != null ?
artifactDecoratorFactories : Map.of(),
+ repositorySystemValidator);
}
@Provides
diff --git
a/impl/maven-testing/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java
b/impl/maven-testing/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java
index 5f7246db79..18a48a4b47 100644
---
a/impl/maven-testing/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java
+++
b/impl/maven-testing/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java
@@ -18,6 +18,7 @@
*/
package org.apache.maven.api.plugin.testing.stubs;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -57,6 +58,7 @@
import org.apache.maven.impl.resolver.VersionsMetadataGeneratorFactory;
import
org.apache.maven.impl.resolver.relocation.DistributionManagementArtifactRelocationSource;
import
org.apache.maven.impl.resolver.relocation.UserPropertiesArtifactRelocationSource;
+import org.apache.maven.impl.resolver.validator.MavenValidatorFactory;
import org.eclipse.aether.RepositoryListener;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
@@ -74,6 +76,7 @@
import org.eclipse.aether.impl.RepositoryConnectorProvider;
import org.eclipse.aether.impl.RepositoryEventDispatcher;
import org.eclipse.aether.impl.RepositorySystemLifecycle;
+import org.eclipse.aether.impl.RepositorySystemValidator;
import org.eclipse.aether.impl.UpdateCheckManager;
import org.eclipse.aether.impl.UpdatePolicyAnalyzer;
import org.eclipse.aether.impl.VersionRangeResolver;
@@ -96,6 +99,7 @@
import org.eclipse.aether.internal.impl.DefaultRepositoryLayoutProvider;
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
import org.eclipse.aether.internal.impl.DefaultRepositorySystemLifecycle;
+import org.eclipse.aether.internal.impl.DefaultRepositorySystemValidator;
import org.eclipse.aether.internal.impl.DefaultTrackingFileManager;
import org.eclipse.aether.internal.impl.DefaultTransporterProvider;
import org.eclipse.aether.internal.impl.DefaultUpdateCheckManager;
@@ -119,8 +123,10 @@
import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector;
import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector;
import
org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager;
+import
org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory;
import
org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource;
import
org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource;
+import
org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory;
import
org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor;
import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory;
import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
@@ -141,6 +147,7 @@
import org.eclipse.aether.spi.artifact.transformer.ArtifactTransformer;
import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource;
import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
@@ -157,6 +164,7 @@
import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
import org.eclipse.aether.spi.synccontext.SyncContextFactory;
+import org.eclipse.aether.spi.validator.ValidatorFactory;
import org.eclipse.aether.transport.apache.ApacheTransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.util.version.GenericVersionScheme;
@@ -720,6 +728,27 @@ protected Map<String, RepositoryConnectorFactory>
createRepositoryConnectorFacto
return result;
}
+ private Map<String, PipelineRepositoryConnectorFactory>
pipelineRepositoryConnectorFactories;
+
+ public final Map<String, PipelineRepositoryConnectorFactory>
getPipelineRepositoryConnectorFactories() {
+ checkClosed();
+ if (pipelineRepositoryConnectorFactories == null) {
+ pipelineRepositoryConnectorFactories =
createPipelineRepositoryConnectorFactories();
+ }
+ return pipelineRepositoryConnectorFactories;
+ }
+
+ protected Map<String, PipelineRepositoryConnectorFactory>
createPipelineRepositoryConnectorFactories() {
+ HashMap<String, PipelineRepositoryConnectorFactory> result = new
HashMap<>();
+ result.put(
+ OfflinePipelineRepositoryConnectorFactory.NAME,
+ new
OfflinePipelineRepositoryConnectorFactory(getOfflineController()));
+ result.put(
+ FilteringPipelineRepositoryConnectorFactory.NAME,
+ new
FilteringPipelineRepositoryConnectorFactory(getRemoteRepositoryFilterManager()));
+ return result;
+ }
+
private RepositoryConnectorProvider repositoryConnectorProvider;
public final RepositoryConnectorProvider getRepositoryConnectorProvider() {
@@ -732,7 +761,7 @@ public final RepositoryConnectorProvider
getRepositoryConnectorProvider() {
protected RepositoryConnectorProvider createRepositoryConnectorProvider() {
return new DefaultRepositoryConnectorProvider(
- getRepositoryConnectorFactories(),
getRemoteRepositoryFilterManager());
+ getRepositoryConnectorFactories(),
getPipelineRepositoryConnectorFactories());
}
private Installer installer;
@@ -1081,6 +1110,36 @@ protected ModelBuilder createModelBuilder() {
new DefaultRootLocator());
}
+ private RepositorySystemValidator repositorySystemValidator;
+
+ public RepositorySystemValidator getRepositorySystemValidator() {
+ checkClosed();
+ if (repositorySystemValidator == null) {
+ repositorySystemValidator = createRepositorySystemValidator();
+ }
+ return repositorySystemValidator;
+ }
+
+ protected RepositorySystemValidator createRepositorySystemValidator() {
+ return new DefaultRepositorySystemValidator(getValidatorFactories());
+ }
+
+ private List<ValidatorFactory> validatorFactories;
+
+ public final List<ValidatorFactory> getValidatorFactories() {
+ checkClosed();
+ if (validatorFactories == null) {
+ validatorFactories = createValidatorFactories();
+ }
+ return validatorFactories;
+ }
+
+ protected List<ValidatorFactory> createValidatorFactories() {
+ List<ValidatorFactory> result = new ArrayList<>();
+ result.add(new MavenValidatorFactory());
+ return result;
+ }
+
private RepositorySystem repositorySystem;
public final RepositorySystem getRepositorySystem() {
@@ -1105,7 +1164,8 @@ protected RepositorySystem createRepositorySystem() {
getSyncContextFactory(),
getRemoteRepositoryManager(),
getRepositorySystemLifecycle(),
- getArtifactDecoratorFactories());
+ getArtifactDecoratorFactories(),
+ getRepositorySystemValidator());
}
@Override
diff --git
a/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/.mvn/maven.properties
b/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/.mvn/maven.properties
new file mode 100644
index 0000000000..0344983373
--- /dev/null
+++
b/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/.mvn/maven.properties
@@ -0,0 +1,2 @@
+# Value corresponds to the folder name in this directory
+repository.url.suffix.property = repo-set-by-property
diff --git
a/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/pom.xml
b/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/pom.xml
index ee0ca564cd..c119576f33 100644
---
a/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/pom.xml
+++
b/its/core-it-suite/src/test/resources/mng-5639-import-scope-pom-resolution/pom.xml
@@ -29,11 +29,6 @@ under the License.
<description>Checks that an import POM in the dependencyManagement section
can be successfully
resolved from a repository defining a URL that contains a
property.</description>
- <properties>
- <!-- Value corresponds to the folder name in this directory -->
-
<repository.url.suffix.property>repo-set-by-property</repository.url.suffix.property>
- </properties>
-
<dependencyManagement>
<dependencies>
<dependency>
diff --git a/pom.xml b/pom.xml
index cdaed2b86e..5978a366ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,7 +162,7 @@ under the License.
<plexusInterpolationVersion>1.28</plexusInterpolationVersion>
<plexusTestingVersion>1.5.0</plexusTestingVersion>
<plexusXmlVersion>4.1.0</plexusXmlVersion>
- <resolverVersion>2.0.7</resolverVersion>
+ <resolverVersion>2.0.8</resolverVersion>
<securityDispatcherVersion>4.1.0</securityDispatcherVersion>
<sisuVersion>0.9.0.M3</sisuVersion>
<slf4jVersion>2.0.17</slf4jVersion>