[MNG-8084] Make the v4 api usable outside the Maven runtime (#1441)

This commit is contained in:
Guillaume Nodet 2024-03-25 11:50:01 +01:00 committed by GitHub
parent 52d453caf9
commit 003a5bc06d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 3100 additions and 1633 deletions

View File

@ -0,0 +1,53 @@
/*
* 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.api.services;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
class PathSource implements Source {
private final Path path;
PathSource(Path path) {
this.path = path;
}
@Override
public Path getPath() {
return path;
}
@Override
public InputStream openStream() throws IOException {
return Files.newInputStream(path);
}
@Override
public String getLocation() {
return path.toString();
}
@Override
public Source resolve(String relative) {
return new PathSource(path.resolve(relative));
}
}

View File

@ -19,11 +19,13 @@
package org.apache.maven.api.services;
import java.nio.file.Path;
import java.util.List;
import org.apache.maven.api.Service;
import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.settings.Settings;
/**
* Builds the effective settings from a user settings file and/or a global settings file.
@ -97,4 +99,37 @@ default SettingsBuilderResult build(
@Nonnull Path userSettingsPath) {
return build(SettingsBuilderRequest.build(session, globalSettingsPath, projectSettingsPath, userSettingsPath));
}
/**
* Validate the specified settings.
*
* @param settings The settings to validate, must not be {@code null}.
* @return The list of problems that were encountered, must not be {@code null}.
*/
@Nonnull
default List<BuilderProblem> validate(@Nonnull Settings settings) {
return validate(settings, false);
}
/**
* Validate the specified settings.
*
* @param settings The settings to validate, must not be {@code null}.
* @param isProjectSettings Boolean indicating if the validation is for project settings or user / global settings.
* @return The list of problems that were encountered, must not be {@code null}.
*/
@Nonnull
List<BuilderProblem> validate(@Nonnull Settings settings, boolean isProjectSettings);
/**
* Convert a model profile to a settings profile.
*/
@Nonnull
org.apache.maven.api.settings.Profile convert(@Nonnull org.apache.maven.api.model.Profile profile);
/**
* Convert a settings profile to a model profile.
*/
@Nonnull
org.apache.maven.api.model.Profile convert(@Nonnull org.apache.maven.api.settings.Profile profile);
}

View File

@ -18,6 +18,9 @@
*/
package org.apache.maven.api.services;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.api.annotations.Experimental;
/**
@ -27,13 +30,24 @@
*/
@Experimental
public class SettingsBuilderException extends MavenException {
private final List<BuilderProblem> problems;
/**
* @param message the message to give
* @param e the {@link Exception}
*/
public SettingsBuilderException(String message, Exception e) {
super(message, e);
this.problems = List.of();
}
// TODO: add SettingsBuilderResult
public SettingsBuilderException(String message, List<BuilderProblem> problems) {
super(message + ": " + problems.stream().map(BuilderProblem::toString).collect(Collectors.joining(", ")), null);
this.problems = List.copyOf(problems);
}
public List<BuilderProblem> getProblems() {
return problems;
}
}

View File

@ -18,6 +18,7 @@
*/
package org.apache.maven.api.services;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
@ -40,14 +41,6 @@ public interface SettingsBuilderRequest {
@Nonnull
Session getSession();
/**
* Gets the global settings path.
*
* @return the global settings path or {@code null} if none
*/
@Nonnull
Optional<Path> getGlobalSettingsPath();
/**
* Gets the global settings source.
*
@ -64,22 +57,6 @@ public interface SettingsBuilderRequest {
@Nonnull
Optional<Source> getProjectSettingsSource();
/**
* Gets the project settings path.
*
* @return the project settings path or {@code null} if none
*/
@Nonnull
Optional<Path> getProjectSettingsPath();
/**
* Gets the user settings path.
*
* @return the user settings path or {@code null} if none
*/
@Nonnull
Optional<Path> getUserSettingsPath();
/**
* Gets the user settings source.
*
@ -97,34 +74,43 @@ static SettingsBuilderRequest build(
@Nonnull
static SettingsBuilderRequest build(
@Nonnull Session session, @Nonnull Path globalSettingsPath, @Nonnull Path userSettingsPath) {
return build(session, globalSettingsPath, null, userSettingsPath);
return build(session, Source.fromPath(globalSettingsPath), null, Source.fromPath(userSettingsPath));
}
@Nonnull
static SettingsBuilderRequest build(
@Nonnull Session session,
@Nonnull Source globalSettingsSource,
@Nonnull Source projectSettingsSource,
@Nonnull Source userSettingsSource) {
@Nullable Source globalSettingsSource,
@Nullable Source projectSettingsSource,
@Nullable Source userSettingsSource) {
return builder()
.session(nonNull(session, "session cannot be null"))
.globalSettingsSource(nonNull(globalSettingsSource, "globalSettingsSource cannot be null"))
.projectSettingsSource(nonNull(projectSettingsSource, "projectSettingsSource cannot be null"))
.userSettingsSource(nonNull(userSettingsSource, "userSettingsSource cannot be null"))
.globalSettingsSource(globalSettingsSource)
.projectSettingsSource(projectSettingsSource)
.userSettingsSource(userSettingsSource)
.build();
}
@Nonnull
static SettingsBuilderRequest build(
@Nonnull Session session,
@Nonnull Path globalSettingsPath,
@Nonnull Path projectSettingsPath,
@Nonnull Path userSettingsPath) {
@Nullable Path globalSettingsPath,
@Nullable Path projectSettingsPath,
@Nullable Path userSettingsPath) {
return builder()
.session(nonNull(session, "session cannot be null"))
.globalSettingsPath(nonNull(globalSettingsPath, "globalSettingsPath cannot be null"))
.projectSettingsPath(nonNull(projectSettingsPath, "projectSettingsPath cannot be null"))
.userSettingsPath(nonNull(userSettingsPath, "userSettingsPath cannot be null"))
.globalSettingsSource(
globalSettingsPath != null && Files.exists(globalSettingsPath)
? Source.fromPath(globalSettingsPath)
: null)
.projectSettingsSource(
projectSettingsPath != null && Files.exists(projectSettingsPath)
? Source.fromPath(projectSettingsPath)
: null)
.userSettingsSource(
userSettingsPath != null && Files.exists(userSettingsPath)
? Source.fromPath(userSettingsPath)
: null)
.build();
}
@ -136,11 +122,8 @@ static SettingsBuilderRequestBuilder builder() {
@NotThreadSafe
class SettingsBuilderRequestBuilder {
Session session;
Path globalSettingsPath;
Source globalSettingsSource;
Path projectSettingsPath;
Source projectSettingsSource;
Path userSettingsPath;
Source userSettingsSource;
public SettingsBuilderRequestBuilder session(Session session) {
@ -148,31 +131,16 @@ public SettingsBuilderRequestBuilder session(Session session) {
return this;
}
public SettingsBuilderRequestBuilder globalSettingsPath(Path globalSettingsPath) {
this.globalSettingsPath = globalSettingsPath;
return this;
}
public SettingsBuilderRequestBuilder globalSettingsSource(Source globalSettingsSource) {
this.globalSettingsSource = globalSettingsSource;
return this;
}
public SettingsBuilderRequestBuilder projectSettingsPath(Path projectSettingsPath) {
this.projectSettingsPath = projectSettingsPath;
return this;
}
public SettingsBuilderRequestBuilder projectSettingsSource(Source projectSettingsSource) {
this.projectSettingsSource = projectSettingsSource;
return this;
}
public SettingsBuilderRequestBuilder userSettingsPath(Path userSettingsPath) {
this.userSettingsPath = userSettingsPath;
return this;
}
public SettingsBuilderRequestBuilder userSettingsSource(Source userSettingsSource) {
this.userSettingsSource = userSettingsSource;
return this;
@ -180,71 +148,38 @@ public SettingsBuilderRequestBuilder userSettingsSource(Source userSettingsSourc
public SettingsBuilderRequest build() {
return new DefaultSettingsBuilderRequest(
session,
globalSettingsPath,
globalSettingsSource,
projectSettingsPath,
projectSettingsSource,
userSettingsPath,
userSettingsSource);
session, globalSettingsSource, projectSettingsSource, userSettingsSource);
}
private static class DefaultSettingsBuilderRequest extends BaseRequest implements SettingsBuilderRequest {
private final Path globalSettingsPath;
private final Source globalSettingsSource;
private final Path projectSettingsPath;
private final Source projectSettingsSource;
private final Path userSettingsPath;
private final Source userSettingsSource;
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultSettingsBuilderRequest(
@Nonnull Session session,
@Nullable Path globalSettingsPath,
@Nullable Source globalSettingsSource,
@Nullable Path projectSettingsPath,
@Nullable Source projectSettingsSource,
@Nullable Path userSettingsPath,
@Nullable Source userSettingsSource) {
super(session);
this.globalSettingsPath = globalSettingsPath;
this.globalSettingsSource = globalSettingsSource;
this.projectSettingsPath = projectSettingsPath;
this.projectSettingsSource = projectSettingsSource;
this.userSettingsPath = userSettingsPath;
this.userSettingsSource = userSettingsSource;
}
@Nonnull
@Override
public Optional<Path> getGlobalSettingsPath() {
return Optional.ofNullable(globalSettingsPath);
}
@Nonnull
@Override
public Optional<Source> getGlobalSettingsSource() {
return Optional.ofNullable(globalSettingsSource);
}
@Nonnull
@Override
public Optional<Path> getProjectSettingsPath() {
return Optional.ofNullable(projectSettingsPath);
}
@Nonnull
@Override
public Optional<Source> getProjectSettingsSource() {
return Optional.ofNullable(projectSettingsSource);
}
@Nonnull
@Override
public Optional<Path> getUserSettingsPath() {
return Optional.ofNullable(userSettingsPath);
}
@Nonnull
@Override
public Optional<Source> getUserSettingsSource() {

View File

@ -27,6 +27,8 @@
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
import static org.apache.maven.api.services.BaseRequest.nonNull;
/**
* Provides access to the contents of a source independently of the
* backing store (e.g. file system, database, memory).
@ -86,4 +88,12 @@ public interface Source {
* @return related source or <code>null</code> if no such source
*/
Source resolve(String relative);
/**
* Creates a Source for the following Path
*/
@Nonnull
static Source fromPath(@Nonnull Path path) {
return new PathSource(nonNull(path, "path cannot be null"));
}
}

View File

@ -18,6 +18,9 @@
*/
package org.apache.maven.api.services;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.api.annotations.Experimental;
/**
@ -27,13 +30,24 @@
*/
@Experimental
public class ToolchainsBuilderException extends MavenException {
private final List<BuilderProblem> problems;
/**
* @param message the message to give
* @param e the {@link Exception}
*/
public ToolchainsBuilderException(String message, Exception e) {
super(message, e);
this.problems = List.of();
}
// TODO: add ToolchainsBuilderResult
public ToolchainsBuilderException(String message, List<BuilderProblem> problems) {
super(message + ": " + problems.stream().map(BuilderProblem::toString).collect(Collectors.joining(", ")), null);
this.problems = List.copyOf(problems);
}
public List<BuilderProblem> getProblems() {
return problems;
}
}

View File

@ -18,6 +18,7 @@
*/
package org.apache.maven.api.services;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
@ -38,14 +39,6 @@ public interface ToolchainsBuilderRequest {
@Nonnull
Session getSession();
/**
* Gets the global Toolchains path.
*
* @return the global Toolchains path or {@code null} if none
*/
@Nonnull
Optional<Path> getGlobalToolchainsPath();
/**
* Gets the global Toolchains source.
*
@ -54,14 +47,6 @@ public interface ToolchainsBuilderRequest {
@Nonnull
Optional<Source> getGlobalToolchainsSource();
/**
* Gets the user Toolchains path.
*
* @return the user Toolchains path or {@code null} if none
*/
@Nonnull
Optional<Path> getUserToolchainsPath();
/**
* Gets the user Toolchains source.
*
@ -72,21 +57,27 @@ public interface ToolchainsBuilderRequest {
@Nonnull
static ToolchainsBuilderRequest build(
@Nonnull Session session, @Nonnull Source globalToolchainsSource, @Nonnull Source userToolchainsSource) {
@Nonnull Session session, @Nullable Source globalToolchainsSource, @Nullable Source userToolchainsSource) {
return builder()
.session(nonNull(session, "session cannot be null"))
.globalToolchainsSource(nonNull(globalToolchainsSource, "globalToolchainsSource cannot be null"))
.userToolchainsSource(nonNull(userToolchainsSource, "userToolchainsSource cannot be null"))
.globalToolchainsSource(globalToolchainsSource)
.userToolchainsSource(userToolchainsSource)
.build();
}
@Nonnull
static ToolchainsBuilderRequest build(
@Nonnull Session session, @Nonnull Path globalToolchainsPath, @Nonnull Path userToolchainsPath) {
@Nonnull Session session, @Nullable Path globalToolchainsPath, @Nullable Path userToolchainsPath) {
return builder()
.session(nonNull(session, "session cannot be null"))
.globalToolchainsPath(nonNull(globalToolchainsPath, "globalToolchainsPath cannot be null"))
.userToolchainsPath(nonNull(userToolchainsPath, "userToolchainsPath cannot be null"))
.globalToolchainsSource(
globalToolchainsPath != null && Files.exists(globalToolchainsPath)
? Source.fromPath(globalToolchainsPath)
: null)
.userToolchainsSource(
userToolchainsPath != null && Files.exists(userToolchainsPath)
? Source.fromPath(userToolchainsPath)
: null)
.build();
}
@ -98,9 +89,7 @@ static ToolchainsBuilderRequestBuilder builder() {
@NotThreadSafe
class ToolchainsBuilderRequestBuilder {
Session session;
Path globalToolchainsPath;
Source globalToolchainsSource;
Path userToolchainsPath;
Source userToolchainsSource;
public ToolchainsBuilderRequestBuilder session(Session session) {
@ -108,21 +97,11 @@ public ToolchainsBuilderRequestBuilder session(Session session) {
return this;
}
public ToolchainsBuilderRequestBuilder globalToolchainsPath(Path globalToolchainsPath) {
this.globalToolchainsPath = globalToolchainsPath;
return this;
}
public ToolchainsBuilderRequestBuilder globalToolchainsSource(Source globalToolchainsSource) {
this.globalToolchainsSource = globalToolchainsSource;
return this;
}
public ToolchainsBuilderRequestBuilder userToolchainsPath(Path userToolchainsPath) {
this.userToolchainsPath = userToolchainsPath;
return this;
}
public ToolchainsBuilderRequestBuilder userToolchainsSource(Source userToolchainsSource) {
this.userToolchainsSource = userToolchainsSource;
return this;
@ -130,47 +109,29 @@ public ToolchainsBuilderRequestBuilder userToolchainsSource(Source userToolchain
public ToolchainsBuilderRequest build() {
return new ToolchainsBuilderRequestBuilder.DefaultToolchainsBuilderRequest(
session, globalToolchainsPath, globalToolchainsSource, userToolchainsPath, userToolchainsSource);
session, globalToolchainsSource, userToolchainsSource);
}
private static class DefaultToolchainsBuilderRequest extends BaseRequest implements ToolchainsBuilderRequest {
private final Path globalToolchainsPath;
private final Source globalToolchainsSource;
private final Path userToolchainsPath;
private final Source userToolchainsSource;
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultToolchainsBuilderRequest(
@Nonnull Session session,
@Nullable Path globalToolchainsPath,
@Nullable Source globalToolchainsSource,
@Nullable Path userToolchainsPath,
@Nullable Source userToolchainsSource) {
super(session);
this.globalToolchainsPath = globalToolchainsPath;
this.globalToolchainsSource = globalToolchainsSource;
this.userToolchainsPath = userToolchainsPath;
this.userToolchainsSource = userToolchainsSource;
}
@Nonnull
@Override
public Optional<Path> getGlobalToolchainsPath() {
return Optional.ofNullable(globalToolchainsPath);
}
@Nonnull
@Override
public Optional<Source> getGlobalToolchainsSource() {
return Optional.ofNullable(globalToolchainsSource);
}
@Nonnull
@Override
public Optional<Path> getUserToolchainsPath() {
return Optional.ofNullable(userToolchainsPath);
}
@Nonnull
@Override
public Optional<Source> getUserToolchainsSource() {

View File

@ -0,0 +1,58 @@
/*
* 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.api.services.xml;
public interface Location {
/**
* Return the line number where the current event ends,
* returns -1 if none is available.
* @return the current line number
*/
int getLineNumber();
/**
* Return the column number where the current event ends,
* returns -1 if none is available.
* @return the current column number
*/
int getColumnNumber();
/**
* Return the byte or character offset into the input source this location
* is pointing to. If the input source is a file or a byte stream then
* this is the byte offset into that stream, but if the input source is
* a character media then the offset is the character offset.
* Returns -1 if there is no offset available.
* @return the current offset
*/
int getCharacterOffset();
/**
* Returns the public ID of the XML
* @return the public ID, or null if not available
*/
String getPublicId();
/**
* Returns the system ID of the XML
* @return the system ID, or null if not available
*/
String getSystemId();
}

View File

@ -29,11 +29,18 @@
@Experimental
public class XmlReaderException extends MavenException {
private final Location location;
/**
* @param message the message for the exception
* @param e the exception itself
*/
public XmlReaderException(String message, Exception e) {
public XmlReaderException(String message, Location location, Exception e) {
super(message, e);
this.location = location;
}
public Location getLocation() {
return location;
}
}

View File

@ -29,11 +29,18 @@
@Experimental
public class XmlWriterException extends MavenException {
private final Location location;
/**
* @param message the message for the exception
* @param e the exception itself
*/
public XmlWriterException(String message, Exception e) {
public XmlWriterException(String message, Location location, Exception e) {
super(message, e);
this.location = location;
}
public Location getLocation() {
return location;
}
}

140
maven-api-impl/pom.xml Normal file
View File

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<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>
<parent>
<groupId>org.apache.maven</groupId>
<artifactId>maven</artifactId>
<version>4.0.0-alpha-14-SNAPSHOT</version>
</parent>
<artifactId>maven-api-impl</artifactId>
<name>Maven API Implementation</name>
<description>Provides the implementation classes for the Maven API</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-di</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-supplier</artifactId>
<version>${resolverVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<executions>
<execution>
<id>velocity-settings</id>
<goals>
<goal>velocity</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<version>2.0.0</version>
<basedir>${project.basedir}/../api/maven-api-settings</basedir>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
<models>
<model>src/main/mdo/settings.mdo</model>
</models>
<templates>
<template>merger.vm</template>
<template>transformer.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
<params>
<param>forcedIOModelVersion=1.2.0</param>
<param>packageModelV3=org.apache.maven.settings</param>
<param>packageModelV4=org.apache.maven.api.settings</param>
<param>packageToolV4=org.apache.maven.settings.v4</param>
<param>locationTracking=true</param>
<param>generateLocationClasses=true</param>
</params>
</configuration>
</execution>
<execution>
<id>velocity-toolchains</id>
<goals>
<goal>velocity</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<version>1.1.0</version>
<basedir>${project.basedir}/../api/maven-api-toolchain</basedir>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
<models>
<model>src/main/mdo/toolchains.mdo</model>
</models>
<templates>
<template>merger.vm</template>
<template>transformer.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
<params>
<param>packageModelV3=org.apache.maven.toolchain.model</param>
<param>packageModelV4=org.apache.maven.api.toolchain</param>
<param>packageToolV4=org.apache.maven.toolchain.v4</param>
</params>
</configuration>
</execution>
<execution>
<id>modello-site-docs</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -25,24 +25,55 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.maven.api.*;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.Dependency;
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.DependencyScope;
import org.apache.maven.api.Language;
import org.apache.maven.api.Listener;
import org.apache.maven.api.LocalRepository;
import org.apache.maven.api.Node;
import org.apache.maven.api.Packaging;
import org.apache.maven.api.PathScope;
import org.apache.maven.api.PathType;
import org.apache.maven.api.Project;
import org.apache.maven.api.ProjectScope;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Service;
import org.apache.maven.api.Session;
import org.apache.maven.api.SessionData;
import org.apache.maven.api.Type;
import org.apache.maven.api.Version;
import org.apache.maven.api.VersionConstraint;
import org.apache.maven.api.VersionRange;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.model.Repository;
import org.apache.maven.api.services.*;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import static org.apache.maven.internal.impl.Utils.map;
import static org.apache.maven.internal.impl.Utils.nonNull;
public abstract class AbstractSession implements InternalSession {
protected final RepositorySystemSession session;
protected final RepositorySystem repositorySystem;
protected final List<RemoteRepository> repositories;
protected final Lookup lookup;
private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>();
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes =
Collections.synchronizedMap(new WeakHashMap<>());
@ -50,10 +81,21 @@ public abstract class AbstractSession implements InternalSession {
Collections.synchronizedMap(new WeakHashMap<>());
private final Map<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories =
Collections.synchronizedMap(new WeakHashMap<>());
private final Map<String, Project> allProjects = Collections.synchronizedMap(new WeakHashMap<>());
private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies =
Collections.synchronizedMap(new WeakHashMap<>());
public AbstractSession(
RepositorySystemSession session,
RepositorySystem repositorySystem,
List<RemoteRepository> repositories,
List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories,
Lookup lookup) {
this.session = session;
this.repositorySystem = repositorySystem;
this.repositories = getRepositories(repositories, resolverRepositories);
this.lookup = lookup;
}
@Override
public RemoteRepository getRemoteRepository(org.eclipse.aether.repository.RemoteRepository repository) {
return allRepositories.computeIfAbsent(repository, DefaultRemoteRepository::new);
@ -81,16 +123,6 @@ public Dependency getDependency(@Nonnull org.eclipse.aether.graph.Dependency dep
return allDependencies.computeIfAbsent(dependency, d -> new DefaultDependency(this, d));
}
@Override
public List<Project> getProjects(List<MavenProject> projects) {
return projects == null ? null : map(projects, this::getProject);
}
@Override
public Project getProject(MavenProject project) {
return allProjects.computeIfAbsent(project.getId(), id -> new DefaultProject(this, project));
}
@Override
public List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories) {
return repositories == null ? null : map(repositories, this::toRepository);
@ -116,22 +148,143 @@ public org.eclipse.aether.repository.LocalRepository toRepository(LocalRepositor
}
}
@Override
public List<ArtifactRepository> toArtifactRepositories(List<RemoteRepository> repositories) {
return repositories == null ? null : map(repositories, this::toArtifactRepository);
}
@Override
public abstract ArtifactRepository toArtifactRepository(RemoteRepository repository);
@Override
public List<org.eclipse.aether.graph.Dependency> toDependencies(
Collection<DependencyCoordinate> dependencies, boolean managed) {
return dependencies == null ? null : map(dependencies, d -> toDependency(d, managed));
}
protected List<RemoteRepository> getRepositories(
List<RemoteRepository> repositories,
List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories) {
if (repositories != null) {
return repositories;
} else if (resolverRepositories != null) {
return map(resolverRepositories, this::getRemoteRepository);
} else {
throw new IllegalArgumentException("no remote repositories provided");
}
}
@Nonnull
@Override
public abstract org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency, boolean managed);
public List<RemoteRepository> getRemoteRepositories() {
return Collections.unmodifiableList(repositories);
}
@Nonnull
@Override
public SessionData getData() {
org.eclipse.aether.SessionData data = session.getData();
return new SessionData() {
@Override
public <T> void set(@Nonnull Key<T> key, @Nullable T value) {
data.set(key, value);
}
@Override
public <T> boolean replace(@Nonnull Key<T> key, @Nullable T oldValue, @Nullable T newValue) {
return data.set(key, oldValue, newValue);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public <T> T get(@Nonnull Key<T> key) {
return (T) data.get(key);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public <T> T computeIfAbsent(@Nonnull Key<T> key, @Nonnull Supplier<T> supplier) {
return (T) data.computeIfAbsent(key, (Supplier<Object>) supplier);
}
};
}
@Nonnull
@Override
public LocalRepository getLocalRepository() {
return new DefaultLocalRepository(session.getLocalRepository());
}
@Nonnull
@Override
public Session withLocalRepository(@Nonnull LocalRepository localRepository) {
nonNull(localRepository, "localRepository");
if (session.getLocalRepository() != null
&& Objects.equals(session.getLocalRepository().getBasedir().toPath(), localRepository.getPath())) {
return this;
}
org.eclipse.aether.repository.LocalRepository repository = toRepository(localRepository);
org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager =
repositorySystem.newLocalRepositoryManager(session, repository);
RepositorySystemSession repoSession =
new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
return newSession(repoSession, repositories);
}
@Nonnull
@Override
public Session withRemoteRepositories(@Nonnull List<RemoteRepository> repositories) {
return newSession(session, repositories);
}
protected abstract Session newSession(RepositorySystemSession session, List<RemoteRepository> repositories);
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementException {
T t = (T) services.computeIfAbsent(clazz, this::lookup);
if (t == null) {
throw new NoSuchElementException(clazz.getName());
}
return t;
}
private Service lookup(Class<? extends Service> c) {
try {
return lookup.lookup(c);
} catch (LookupException e) {
NoSuchElementException nsee = new NoSuchElementException(c.getName());
e.initCause(e);
throw nsee;
}
}
@Nonnull
public RepositorySystemSession getSession() {
return session;
}
@Nonnull
public RepositorySystem getRepositorySystem() {
return repositorySystem;
}
public org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency, boolean managed) {
org.eclipse.aether.graph.Dependency dep;
if (dependency instanceof DefaultDependencyCoordinate) {
dep = ((DefaultDependencyCoordinate) dependency).getDependency();
} else {
dep = new org.eclipse.aether.graph.Dependency(
new org.eclipse.aether.artifact.DefaultArtifact(
dependency.getGroupId(),
dependency.getArtifactId(),
dependency.getClassifier(),
dependency.getType().getExtension(),
dependency.getVersion().toString(),
null),
dependency.getScope().id());
}
if (!managed && "".equals(dep.getScope())) {
dep = dep.setScope(DependencyScope.COMPILE.id());
}
return dep;
}
@Override
public List<org.eclipse.aether.artifact.Artifact> toArtifacts(Collection<Artifact> artifacts) {

View File

@ -18,11 +18,10 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactCoordinateFactory;
import org.apache.maven.api.services.ArtifactCoordinateFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType;

View File

@ -18,14 +18,13 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Collection;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactDeployer;
import org.apache.maven.api.services.ArtifactDeployerException;
import org.apache.maven.api.services.ArtifactDeployerRequest;

View File

@ -18,11 +18,10 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactFactory;
import org.apache.maven.api.services.ArtifactFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType;

View File

@ -18,11 +18,10 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactInstaller;
import org.apache.maven.api.services.ArtifactInstallerException;
import org.apache.maven.api.services.ArtifactInstallerRequest;

View File

@ -18,9 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
@ -29,6 +26,8 @@
import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.ArtifactResolver;
import org.apache.maven.api.services.ArtifactResolverException;

View File

@ -0,0 +1,111 @@
/*
* 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.internal.impl;
import org.apache.maven.api.services.BuilderProblem;
/**
* Describes a problem that was encountered during settings building. A problem can either be an exception that was
* thrown or a simple string message. In addition, a problem carries a hint about its source, e.g. the settings file
* that exhibits the problem.
*/
class DefaultBuilderProblem implements BuilderProblem {
final String source;
final int lineNumber;
final int columnNumber;
final Exception exception;
final String message;
final Severity severity;
DefaultBuilderProblem(
String source, int lineNumber, int columnNumber, Exception exception, String message, Severity severity) {
this.source = source;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
this.exception = exception;
this.message = message;
this.severity = severity;
}
@Override
public String getSource() {
return source;
}
@Override
public int getLineNumber() {
return lineNumber;
}
@Override
public int getColumnNumber() {
return columnNumber;
}
@Override
public Exception getException() {
return exception;
}
@Override
public String getMessage() {
return message;
}
@Override
public Severity getSeverity() {
return severity;
}
@Override
public String getLocation() {
StringBuilder buffer = new StringBuilder(256);
if (!getSource().isEmpty()) {
buffer.append(getSource());
}
if (getLineNumber() > 0) {
if (!buffer.isEmpty()) {
buffer.append(", ");
}
buffer.append("line ").append(getLineNumber());
}
if (getColumnNumber() > 0) {
if (!buffer.isEmpty()) {
buffer.append(", ");
}
buffer.append("column ").append(getColumnNumber());
}
return buffer.toString();
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder(128);
buffer.append('[').append(severity).append("]");
String msg = message != null ? message : exception != null ? exception.getMessage() : null;
if (msg != null && !msg.isEmpty()) {
buffer.append(" ").append(msg);
}
String location = getLocation();
if (!location.isEmpty()) {
buffer.append(" @ ").append(location);
}
return buffer.toString();
}
}

View File

@ -18,18 +18,26 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.maven.api.services.*;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ChecksumAlgorithmService;
import org.apache.maven.api.services.ChecksumAlgorithmServiceException;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;

View File

@ -18,15 +18,22 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Collection;
import java.util.List;
import org.apache.maven.api.*;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.Node;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.services.*;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.DependencyCollector;
import org.apache.maven.api.services.DependencyCollectorException;
import org.apache.maven.api.services.DependencyCollectorRequest;
import org.apache.maven.api.services.DependencyCollectorResult;
import org.apache.maven.api.services.ProjectManager;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.collection.CollectRequest;

View File

@ -20,7 +20,11 @@
import java.util.Collection;
import org.apache.maven.api.*;
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.DependencyScope;
import org.apache.maven.api.Exclusion;
import org.apache.maven.api.Type;
import org.apache.maven.api.VersionConstraint;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
import org.eclipse.aether.artifact.ArtifactProperties;

View File

@ -18,12 +18,11 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.Exclusion;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.DependencyCoordinateFactory;
import org.apache.maven.api.services.DependencyCoordinateFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType;

View File

@ -18,8 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import java.nio.file.Path;
import org.apache.maven.api.LocalRepository;
@ -31,7 +29,6 @@ public class DefaultLocalRepository implements LocalRepository {
private final @Nonnull org.eclipse.aether.repository.LocalRepository repository;
@Inject
public DefaultLocalRepository(@Nonnull org.eclipse.aether.repository.LocalRepository repository) {
this.repository = nonNull(repository, "repository");
}

View File

@ -18,15 +18,14 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.LocalRepository;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.LocalRepositoryManager;
@Named

View File

@ -18,15 +18,14 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Priority;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.MessageBuilder;
import org.apache.maven.api.services.MessageBuilderFactory;
import org.eclipse.sisu.Priority;
@Experimental
@Named

View File

@ -18,9 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
@ -30,6 +27,8 @@
import java.nio.file.Path;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.model.InputSource;
import org.apache.maven.api.model.Model;
import org.apache.maven.api.services.xml.ModelXmlFactory;
@ -40,6 +39,8 @@
import org.apache.maven.model.v4.MavenStaxReader;
import org.apache.maven.model.v4.MavenStaxWriter;
import static org.apache.maven.internal.impl.StaxLocation.getLocation;
import static org.apache.maven.internal.impl.StaxLocation.getMessage;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -76,7 +77,7 @@ public Model read(@Nonnull XmlReaderRequest request) throws XmlReaderException {
}
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read model", e);
throw new XmlReaderException("Unable to read model: " + getMessage(e), getLocation(e), e);
}
}
@ -101,7 +102,7 @@ public void write(XmlWriterRequest<Model> request) throws XmlWriterException {
}
}
} catch (Exception e) {
throw new XmlWriterException("Unable to write model", e);
throw new XmlWriterException("Unable to write model: " + getMessage(e), getLocation(e), e);
}
}

View File

@ -18,30 +18,20 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
import org.apache.maven.api.LocalRepository;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.model.Repository;
import org.apache.maven.api.services.RepositoryFactory;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.repository.RepositoryPolicy;
@Named
@Singleton
public class DefaultRepositoryFactory implements RepositoryFactory {
private final RepositorySystem repositorySystem;
@Inject
public DefaultRepositoryFactory(RepositorySystem repositorySystem) {
this.repositorySystem = repositorySystem;
}
@Override
public LocalRepository createLocal(Path path) {
return new DefaultLocalRepository(new org.eclipse.aether.repository.LocalRepository(path.toFile()));

View File

@ -0,0 +1,300 @@
/*
* 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.internal.impl;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.api.services.SettingsBuilderException;
import org.apache.maven.api.services.SettingsBuilderRequest;
import org.apache.maven.api.services.SettingsBuilderResult;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.xml.SettingsXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.RepositoryPolicy;
import org.apache.maven.api.settings.Server;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.v4.SettingsMerger;
import org.apache.maven.settings.v4.SettingsTransformer;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
/**
* Builds the effective settings from a user settings file and/or a global settings file.
*
*/
@Named
public class DefaultSettingsBuilder implements SettingsBuilder {
private final DefaultSettingsValidator settingsValidator = new DefaultSettingsValidator();
private final SettingsMerger settingsMerger = new SettingsMerger();
@Override
public SettingsBuilderResult build(SettingsBuilderRequest request) throws SettingsBuilderException {
List<BuilderProblem> problems = new ArrayList<>();
Source globalSource = request.getGlobalSettingsSource().orElse(null);
Settings global = readSettings(globalSource, false, request, problems);
Source projectSource = request.getProjectSettingsSource().orElse(null);
Settings project = readSettings(projectSource, true, request, problems);
Source userSource = request.getUserSettingsSource().orElse(null);
Settings user = readSettings(userSource, false, request, problems);
Settings effective =
settingsMerger.merge(user, settingsMerger.merge(project, global, false, null), false, null);
// If no repository is defined in the user/global settings,
// it means that we have "old" settings (as those are new in 4.0)
// so add central to the computed settings for backward compatibility.
if (effective.getRepositories().isEmpty()
&& effective.getPluginRepositories().isEmpty()) {
Repository central = Repository.newBuilder()
.id("central")
.name("Central Repository")
.url("https://repo.maven.apache.org/maven2")
.snapshots(RepositoryPolicy.newBuilder().enabled(false).build())
.build();
Repository centralWithNoUpdate = central.withReleases(
RepositoryPolicy.newBuilder().updatePolicy("never").build());
effective = Settings.newBuilder(effective)
.repositories(List.of(central))
.pluginRepositories(List.of(centralWithNoUpdate))
.build();
}
// for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble
String localRepository = effective.getLocalRepository();
if (localRepository != null && !localRepository.isEmpty()) {
Path file = Paths.get(localRepository);
if (!file.isAbsolute() && file.toString().startsWith(File.separator)) {
effective = effective.withLocalRepository(file.toAbsolutePath().toString());
}
}
if (hasErrors(problems)) {
throw new SettingsBuilderException("Error building settings", problems);
}
return new DefaultSettingsBuilderResult(effective, problems);
}
private boolean hasErrors(List<BuilderProblem> problems) {
if (problems != null) {
for (BuilderProblem problem : problems) {
if (BuilderProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
return true;
}
}
}
return false;
}
private Settings readSettings(
Source settingsSource,
boolean isProjectSettings,
SettingsBuilderRequest request,
List<BuilderProblem> problems) {
if (settingsSource == null) {
return Settings.newInstance();
}
Settings settings;
try {
try {
InputStream is = settingsSource.openStream();
if (is == null) {
return Settings.newInstance();
}
settings = request.getSession()
.getService(SettingsXmlFactory.class)
.read(XmlReaderRequest.builder()
.inputStream(is)
.location(settingsSource.getLocation())
.strict(true)
.build());
} catch (XmlReaderException e) {
InputStream is = settingsSource.openStream();
if (is == null) {
return Settings.newInstance();
}
settings = request.getSession()
.getService(SettingsXmlFactory.class)
.read(XmlReaderRequest.builder()
.inputStream(is)
.location(settingsSource.getLocation())
.strict(false)
.build());
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
problems.add(new DefaultBuilderProblem(
settingsSource.getLocation(),
loc != null ? loc.getLineNumber() : -1,
loc != null ? loc.getColumnNumber() : -1,
e,
e.getMessage(),
BuilderProblem.Severity.WARNING));
}
} catch (XmlReaderException e) {
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
problems.add(new DefaultBuilderProblem(
settingsSource.getLocation(),
loc != null ? loc.getLineNumber() : -1,
loc != null ? loc.getColumnNumber() : -1,
e,
"Non-parseable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
BuilderProblem.Severity.FATAL));
return Settings.newInstance();
} catch (IOException e) {
problems.add(new DefaultBuilderProblem(
settingsSource.getLocation(),
-1,
-1,
e,
"Non-readable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
BuilderProblem.Severity.FATAL));
return Settings.newInstance();
}
settings = interpolate(settings, request, problems);
settingsValidator.validate(settings, isProjectSettings, problems);
if (isProjectSettings) {
settings = Settings.newBuilder(settings, true)
.localRepository(null)
.interactiveMode(false)
.offline(false)
.proxies(List.of())
.usePluginRegistry(false)
.servers(settings.getServers().stream()
.map(s -> Server.newBuilder(s, true)
.username(null)
.passphrase(null)
.privateKey(null)
.password(null)
.filePermissions(null)
.directoryPermissions(null)
.build())
.toList())
.build();
}
return settings;
}
private Settings interpolate(Settings settings, SettingsBuilderRequest request, List<BuilderProblem> problems) {
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
interpolator.addValueSource(new MapBasedValueSource(request.getSession().getUserProperties()));
interpolator.addValueSource(new MapBasedValueSource(request.getSession().getSystemProperties()));
try {
interpolator.addValueSource(new EnvarBasedValueSource());
} catch (IOException e) {
problems.add(new DefaultBuilderProblem(
null,
-1,
-1,
e,
"Failed to use environment variables for interpolation: " + e.getMessage(),
BuilderProblem.Severity.WARNING));
}
return new SettingsTransformer(value -> {
try {
return value != null ? interpolator.interpolate(value) : null;
} catch (InterpolationException e) {
problems.add(new DefaultBuilderProblem(
null,
-1,
-1,
e,
"Failed to interpolate settings: " + e.getMessage(),
BuilderProblem.Severity.WARNING));
return value;
}
})
.visit(settings);
}
@Override
public List<BuilderProblem> validate(Settings settings, boolean isProjectSettings) {
ArrayList<BuilderProblem> problems = new ArrayList<>();
settingsValidator.validate(settings, isProjectSettings, problems);
return problems;
}
@Override
public Profile convert(org.apache.maven.api.model.Profile profile) {
return SettingsUtilsV4.convertToSettingsProfile(profile);
}
@Override
public org.apache.maven.api.model.Profile convert(Profile profile) {
return SettingsUtilsV4.convertFromSettingsProfile(profile);
}
/**
* Collects the output of the settings builder.
*
*/
static class DefaultSettingsBuilderResult implements SettingsBuilderResult {
private final Settings effectiveSettings;
private final List<BuilderProblem> problems;
DefaultSettingsBuilderResult(Settings effectiveSettings, List<BuilderProblem> problems) {
this.effectiveSettings = effectiveSettings;
this.problems = (problems != null) ? problems : new ArrayList<>();
}
@Override
public Settings getEffectiveSettings() {
return effectiveSettings;
}
@Override
public List<BuilderProblem> getProblems() {
return problems;
}
}
}

View File

@ -0,0 +1,362 @@
/*
* 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.internal.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.settings.Mirror;
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Proxy;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.Server;
import org.apache.maven.api.settings.Settings;
/**
*/
public class DefaultSettingsValidator {
private static final String ID = "[\\w.-]+";
private static final Pattern ID_REGEX = Pattern.compile(ID);
private static final String ILLEGAL_REPO_ID_CHARS = "\\/:\"<>|?*"; // ILLEGAL_FS_CHARS
public void validate(Settings settings, boolean isProjectSettings, List<BuilderProblem> problems) {
if (isProjectSettings) {
String msgS = "is not supported on project settings.";
String msgP = "are not supported on project settings.";
if (settings.getLocalRepository() != null
&& !settings.getLocalRepository().isEmpty()) {
addViolation(problems, BuilderProblem.Severity.WARNING, "localRepository", null, msgS);
}
if (!settings.isInteractiveMode()) {
addViolation(problems, BuilderProblem.Severity.WARNING, "interactiveMode", null, msgS);
}
if (settings.isOffline()) {
addViolation(problems, BuilderProblem.Severity.WARNING, "offline", null, msgS);
}
if (!settings.getProxies().isEmpty()) {
addViolation(problems, BuilderProblem.Severity.WARNING, "proxies", null, msgP);
}
if (settings.isUsePluginRegistry()) {
addViolation(problems, BuilderProblem.Severity.WARNING, "usePluginRegistry", null, msgS);
}
List<Server> servers = settings.getServers();
for (int i = 0; i < servers.size(); i++) {
Server server = servers.get(i);
String serverField = "servers.server[" + i + "]";
validateStringEmpty(problems, serverField + ".username", server.getUsername(), msgS);
validateStringEmpty(problems, serverField + ".password", server.getPassword(), msgS);
validateStringEmpty(problems, serverField + ".privateKey", server.getPrivateKey(), msgS);
validateStringEmpty(problems, serverField + ".passphrase", server.getPassphrase(), msgS);
validateStringEmpty(problems, serverField + ".filePermissions", server.getFilePermissions(), msgS);
validateStringEmpty(
problems, serverField + ".directoryPermissions", server.getDirectoryPermissions(), msgS);
}
}
if (settings.isUsePluginRegistry()) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
"usePluginRegistry",
null,
"is deprecated and has no effect.");
}
List<String> pluginGroups = settings.getPluginGroups();
if (pluginGroups != null) {
for (int i = 0; i < pluginGroups.size(); i++) {
String pluginGroup = pluginGroups.get(i);
validateStringNotEmpty(problems, "pluginGroups.pluginGroup[" + i + "]", pluginGroup, null);
if (!ID_REGEX.matcher(pluginGroup).matches()) {
addViolation(
problems,
BuilderProblem.Severity.ERROR,
"pluginGroups.pluginGroup[" + i + "]",
null,
"must denote a valid group id and match the pattern " + ID);
}
}
}
List<Server> servers = settings.getServers();
if (servers != null) {
Set<String> serverIds = new HashSet<>();
for (int i = 0; i < servers.size(); i++) {
Server server = servers.get(i);
validateStringNotEmpty(problems, "servers.server[" + i + "].id", server.getId(), null);
if (!serverIds.add(server.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
"servers.server.id",
null,
"must be unique but found duplicate server with id " + server.getId());
}
}
}
List<Mirror> mirrors = settings.getMirrors();
if (mirrors != null) {
for (Mirror mirror : mirrors) {
validateStringNotEmpty(problems, "mirrors.mirror.id", mirror.getId(), mirror.getUrl());
validateBannedCharacters(
problems,
"mirrors.mirror.id",
BuilderProblem.Severity.WARNING,
mirror.getId(),
null,
ILLEGAL_REPO_ID_CHARS);
if ("local".equals(mirror.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
"mirrors.mirror.id",
null,
"must not be 'local'"
+ ", this identifier is reserved for the local repository"
+ ", using it for other repositories will corrupt your repository metadata.");
}
validateStringNotEmpty(problems, "mirrors.mirror.url", mirror.getUrl(), mirror.getId());
validateStringNotEmpty(problems, "mirrors.mirror.mirrorOf", mirror.getMirrorOf(), mirror.getId());
}
}
List<Profile> profiles = settings.getProfiles();
if (profiles != null) {
Set<String> profileIds = new HashSet<>();
for (Profile profile : profiles) {
if (!profileIds.add(profile.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
"profiles.profile.id",
null,
"must be unique but found duplicate profile with id " + profile.getId());
}
String prefix = "profiles.profile[" + profile.getId() + "].";
validateRepositories(problems, profile.getRepositories(), prefix + "repositories.repository");
validateRepositories(
problems, profile.getPluginRepositories(), prefix + "pluginRepositories.pluginRepository");
}
}
List<Proxy> proxies = settings.getProxies();
if (proxies != null) {
Set<String> proxyIds = new HashSet<>();
for (Proxy proxy : proxies) {
if (!proxyIds.add(proxy.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
"proxies.proxy.id",
null,
"must be unique but found duplicate proxy with id " + proxy.getId());
}
validateStringNotEmpty(problems, "proxies.proxy.host", proxy.getHost(), proxy.getId());
try {
Integer.parseInt(proxy.getPortString());
} catch (NumberFormatException e) {
addViolation(
problems,
BuilderProblem.Severity.ERROR,
"proxies.proxy[" + proxy.getId() + "].port",
null,
"must be a valid integer but found '" + proxy.getPortString() + "'");
}
}
}
}
private void validateRepositories(List<BuilderProblem> problems, List<Repository> repositories, String prefix) {
Set<String> repoIds = new HashSet<>();
for (Repository repository : repositories) {
validateStringNotEmpty(problems, prefix + ".id", repository.getId(), repository.getUrl());
validateBannedCharacters(
problems,
prefix + ".id",
BuilderProblem.Severity.WARNING,
repository.getId(),
null,
ILLEGAL_REPO_ID_CHARS);
if ("local".equals(repository.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
prefix + ".id",
null,
"must not be 'local'"
+ ", this identifier is reserved for the local repository"
+ ", using it for other repositories will corrupt your repository metadata.");
}
if (!repoIds.add(repository.getId())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
prefix + ".id",
null,
"must be unique but found duplicate repository with id " + repository.getId());
}
validateStringNotEmpty(problems, prefix + ".url", repository.getUrl(), repository.getId());
if ("legacy".equals(repository.getLayout())) {
addViolation(
problems,
BuilderProblem.Severity.WARNING,
prefix + ".layout",
repository.getId(),
"uses the unsupported value 'legacy', artifact resolution might fail.");
}
}
}
// ----------------------------------------------------------------------
// Field validation
// ----------------------------------------------------------------------
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string.length == null</code>
* <li><code>string.length == 0</code>
* </ul>
*/
private static boolean validateStringEmpty(
List<BuilderProblem> problems, String fieldName, String string, String message) {
if (string == null || string.length() == 0) {
return true;
}
addViolation(problems, BuilderProblem.Severity.WARNING, fieldName, null, message);
return false;
}
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string.length != null</code>
* <li><code>string.length > 0</code>
* </ul>
*/
private static boolean validateStringNotEmpty(
List<BuilderProblem> problems, String fieldName, String string, String sourceHint) {
if (!validateNotNull(problems, fieldName, string, sourceHint)) {
return false;
}
if (!string.isEmpty()) {
return true;
}
addViolation(problems, BuilderProblem.Severity.ERROR, fieldName, sourceHint, "is missing");
return false;
}
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string != null</code>
* </ul>
*/
private static boolean validateNotNull(
List<BuilderProblem> problems, String fieldName, Object object, String sourceHint) {
if (object != null) {
return true;
}
addViolation(problems, BuilderProblem.Severity.ERROR, fieldName, sourceHint, "is missing");
return false;
}
private static boolean validateBannedCharacters(
List<BuilderProblem> problems,
String fieldName,
BuilderProblem.Severity severity,
String string,
String sourceHint,
String banned) {
if (string != null) {
for (int i = string.length() - 1; i >= 0; i--) {
if (banned.indexOf(string.charAt(i)) >= 0) {
addViolation(
problems,
severity,
fieldName,
sourceHint,
"must not contain any of these characters " + banned + " but found " + string.charAt(i));
return false;
}
}
}
return true;
}
private static void addViolation(
List<BuilderProblem> problems,
BuilderProblem.Severity severity,
String fieldName,
String sourceHint,
String message) {
StringBuilder buffer = new StringBuilder(256);
buffer.append('\'').append(fieldName).append('\'');
if (sourceHint != null) {
buffer.append(" for ").append(sourceHint);
}
buffer.append(' ').append(message);
problems.add(new DefaultBuilderProblem(null, -1, -1, null, buffer.toString(), severity));
}
}

View File

@ -18,15 +18,14 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.xml.SettingsXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
@ -37,7 +36,8 @@
import org.apache.maven.settings.v4.SettingsStaxReader;
import org.apache.maven.settings.v4.SettingsStaxWriter;
import static org.apache.maven.internal.impl.Utils.nonNull;
import static org.apache.maven.internal.impl.StaxLocation.getLocation;
import static org.apache.maven.internal.impl.StaxLocation.getMessage;
@Named
@Singleton
@ -63,7 +63,7 @@ public Settings read(@Nonnull XmlReaderRequest request) throws XmlReaderExceptio
return xml.read(inputStream, request.isStrict(), source);
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read settings", e);
throw new XmlReaderException("Unable to read settings: " + getMessage(e), getLocation(e), e);
}
}
@ -83,7 +83,14 @@ public void write(XmlWriterRequest<Settings> request) throws XmlWriterException
new SettingsStaxWriter().write(outputStream, content);
}
} catch (Exception e) {
throw new XmlWriterException("Unable to write settings", e);
throw new XmlWriterException("Unable to write settings: " + getMessage(e), getLocation(e), e);
}
}
static <T> T nonNull(T t, String name) {
if (t == null) {
throw new IllegalArgumentException(name + " cannot be null");
}
return t;
}
}

View File

@ -0,0 +1,218 @@
/*
* 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.internal.impl;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.ToolchainsBuilder;
import org.apache.maven.api.services.ToolchainsBuilderException;
import org.apache.maven.api.services.ToolchainsBuilderRequest;
import org.apache.maven.api.services.ToolchainsBuilderResult;
import org.apache.maven.api.services.xml.ToolchainsXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsMerger;
import org.apache.maven.toolchain.v4.MavenToolchainsTransformer;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
/**
* Builds the effective toolchains from a user toolchains file and/or a global toolchains file.
*
*/
@Named
public class DefaultToolchainsBuilder implements ToolchainsBuilder {
private final MavenToolchainsMerger toolchainsMerger = new MavenToolchainsMerger();
@Override
public ToolchainsBuilderResult build(ToolchainsBuilderRequest request) throws ToolchainsBuilderException {
List<BuilderProblem> problems = new ArrayList<>();
Source globalSource = request.getGlobalToolchainsSource().orElse(null);
PersistedToolchains global = readToolchains(globalSource, request, problems);
Source userSource = request.getUserToolchainsSource().orElse(null);
PersistedToolchains user = readToolchains(userSource, request, problems);
PersistedToolchains effective = toolchainsMerger.merge(user, global, false, null);
if (hasErrors(problems)) {
throw new ToolchainsBuilderException("Error building toolchains", problems);
}
return new DefaultToolchainsBuilderResult(effective, problems);
}
private boolean hasErrors(List<BuilderProblem> problems) {
if (problems != null) {
for (BuilderProblem problem : problems) {
if (BuilderProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
return true;
}
}
}
return false;
}
private PersistedToolchains readToolchains(
Source toolchainsSource, ToolchainsBuilderRequest request, List<BuilderProblem> problems) {
if (toolchainsSource == null) {
return PersistedToolchains.newInstance();
}
PersistedToolchains toolchains;
try {
try {
InputStream is = toolchainsSource.openStream();
if (is == null) {
return PersistedToolchains.newInstance();
}
toolchains = request.getSession()
.getService(ToolchainsXmlFactory.class)
.read(XmlReaderRequest.builder()
.inputStream(is)
.location(toolchainsSource.getLocation())
.strict(true)
.build());
} catch (XmlReaderException e) {
InputStream is = toolchainsSource.openStream();
if (is == null) {
return PersistedToolchains.newInstance();
}
toolchains = request.getSession()
.getService(ToolchainsXmlFactory.class)
.read(XmlReaderRequest.builder()
.inputStream(is)
.location(toolchainsSource.getLocation())
.strict(false)
.build());
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
problems.add(new DefaultBuilderProblem(
toolchainsSource.getLocation(),
loc != null ? loc.getLineNumber() : -1,
loc != null ? loc.getColumnNumber() : -1,
e,
e.getMessage(),
BuilderProblem.Severity.WARNING));
}
} catch (XmlReaderException e) {
Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
problems.add(new DefaultBuilderProblem(
toolchainsSource.getLocation(),
loc != null ? loc.getLineNumber() : -1,
loc != null ? loc.getColumnNumber() : -1,
e,
"Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
BuilderProblem.Severity.FATAL));
return PersistedToolchains.newInstance();
} catch (IOException e) {
problems.add(new DefaultBuilderProblem(
toolchainsSource.getLocation(),
-1,
-1,
e,
"Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
BuilderProblem.Severity.FATAL));
return PersistedToolchains.newInstance();
}
toolchains = interpolate(toolchains, request, problems);
return toolchains;
}
private PersistedToolchains interpolate(
PersistedToolchains toolchains, ToolchainsBuilderRequest request, List<BuilderProblem> problems) {
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
interpolator.addValueSource(new MapBasedValueSource(request.getSession().getUserProperties()));
interpolator.addValueSource(new MapBasedValueSource(request.getSession().getSystemProperties()));
try {
interpolator.addValueSource(new EnvarBasedValueSource());
} catch (IOException e) {
problems.add(new DefaultBuilderProblem(
null,
-1,
-1,
e,
"Failed to use environment variables for interpolation: " + e.getMessage(),
BuilderProblem.Severity.WARNING));
}
return new MavenToolchainsTransformer(value -> {
try {
return value != null ? interpolator.interpolate(value) : null;
} catch (InterpolationException e) {
problems.add(new DefaultBuilderProblem(
null,
-1,
-1,
e,
"Failed to interpolate toolchains: " + e.getMessage(),
BuilderProblem.Severity.WARNING));
return value;
}
})
.visit(toolchains);
}
/**
* Collects the output of the toolchains builder.
*
*/
static class DefaultToolchainsBuilderResult implements ToolchainsBuilderResult {
private final PersistedToolchains effectiveToolchains;
private final List<BuilderProblem> problems;
DefaultToolchainsBuilderResult(PersistedToolchains effectiveToolchains, List<BuilderProblem> problems) {
this.effectiveToolchains = effectiveToolchains;
this.problems = (problems != null) ? problems : new ArrayList<>();
}
@Override
public PersistedToolchains getEffectiveToolchains() {
return effectiveToolchains;
}
@Override
public List<BuilderProblem> getProblems() {
return problems;
}
}
}

View File

@ -18,9 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
@ -28,6 +25,8 @@
import java.util.Objects;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.model.InputSource;
import org.apache.maven.api.services.xml.ToolchainsXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
@ -38,6 +37,8 @@
import org.apache.maven.toolchain.v4.MavenToolchainsStaxReader;
import org.apache.maven.toolchain.v4.MavenToolchainsStaxWriter;
import static org.apache.maven.internal.impl.StaxLocation.getLocation;
import static org.apache.maven.internal.impl.StaxLocation.getMessage;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -64,7 +65,7 @@ public PersistedToolchains read(@Nonnull XmlReaderRequest request) throws XmlRea
return xml.read(inputStream, request.isStrict());
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read toolchains", e);
throw new XmlReaderException("Unable to read toolchains: " + getMessage(e), getLocation(e), e);
}
}
@ -84,7 +85,7 @@ public void write(XmlWriterRequest<PersistedToolchains> request) throws XmlWrite
new MavenToolchainsStaxWriter().write(outputStream, content);
}
} catch (Exception e) {
throw new XmlWriterException("Unable to write toolchains", e);
throw new XmlWriterException("Unable to write toolchains: " + getMessage(e), getLocation(e), e);
}
}
}

View File

@ -18,9 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
@ -29,6 +26,8 @@
import java.nio.file.Path;
import java.util.Optional;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.Transport;
import org.eclipse.aether.spi.connector.transport.GetTask;
import org.eclipse.aether.spi.connector.transport.PutTask;

View File

@ -18,15 +18,14 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.Transport;
import org.apache.maven.api.services.TransportProvider;
import org.apache.maven.api.services.TransportProviderException;

View File

@ -18,13 +18,12 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.api.Version;
import org.apache.maven.api.VersionConstraint;
import org.apache.maven.api.VersionRange;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.VersionParser;
import org.apache.maven.model.version.ModelVersionParser;

View File

@ -18,10 +18,6 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -29,6 +25,9 @@
import org.apache.maven.api.Repository;
import org.apache.maven.api.Version;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.VersionRangeResolver;
import org.apache.maven.api.services.VersionRangeResolverException;
import org.apache.maven.api.services.VersionRangeResolverRequest;

View File

@ -18,15 +18,14 @@
*/
package org.apache.maven.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List;
import java.util.Optional;
import org.apache.maven.api.Repository;
import org.apache.maven.api.Version;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.VersionResolver;
import org.apache.maven.api.services.VersionResolverException;
import org.apache.maven.api.services.VersionResolverRequest;

View File

@ -27,11 +27,9 @@
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.LocalRepository;
import org.apache.maven.api.Node;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.execution.MavenSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
@ -55,21 +53,12 @@ static InternalSession from(Session session) {
@Nonnull
Dependency getDependency(@Nonnull org.eclipse.aether.graph.Dependency dependency);
List<Project> getProjects(List<org.apache.maven.project.MavenProject> projects);
Project getProject(org.apache.maven.project.MavenProject project);
List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories);
org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository);
org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository repository);
List<org.apache.maven.artifact.repository.ArtifactRepository> toArtifactRepositories(
List<RemoteRepository> repositories);
org.apache.maven.artifact.repository.ArtifactRepository toArtifactRepository(RemoteRepository repository);
List<org.eclipse.aether.graph.Dependency> toDependencies(
Collection<DependencyCoordinate> dependencies, boolean managed);
@ -81,8 +70,6 @@ List<org.eclipse.aether.graph.Dependency> toDependencies(
org.eclipse.aether.artifact.Artifact toArtifact(ArtifactCoordinate coord);
MavenSession getMavenSession();
RepositorySystemSession getSession();
RepositorySystem getRepositorySystem();

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.settings;
package org.apache.maven.internal.impl;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@ -311,17 +311,6 @@ private static RepositoryPolicy convertRepositoryPolicy(org.apache.maven.api.mod
return policy;
}
/**
* @param settings could be null
* @return a new instance of settings or null if settings was null.
*/
public static org.apache.maven.settings.Settings copySettings(org.apache.maven.settings.Settings settings) {
if (settings == null) {
return null;
}
return new org.apache.maven.settings.Settings(settings.getDelegate());
}
private static org.apache.maven.api.model.InputLocation toLocation(
org.apache.maven.api.settings.InputLocation location) {
if (location != null) {

View File

@ -0,0 +1,76 @@
/*
* 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.internal.impl;
import javax.xml.stream.XMLStreamException;
import org.apache.maven.api.services.xml.Location;
public class StaxLocation implements Location {
private final javax.xml.stream.Location location;
public static Location getLocation(Exception e) {
return toLocation(e instanceof XMLStreamException xe ? xe.getLocation() : null);
}
public static Location toLocation(javax.xml.stream.Location location) {
return location != null ? new StaxLocation(location) : null;
}
public static String getMessage(Exception e) {
String message = e.getMessage();
if (e instanceof XMLStreamException xe && xe.getLocation() != null) {
int idx = message.indexOf("\nMessage: ");
if (idx >= 0) {
return message.substring(idx + "\nMessage: ".length());
}
}
return message;
}
public StaxLocation(javax.xml.stream.Location location) {
this.location = location;
}
@Override
public int getLineNumber() {
return location.getLineNumber();
}
@Override
public int getColumnNumber() {
return location.getColumnNumber();
}
@Override
public int getCharacterOffset() {
return location.getCharacterOffset();
}
@Override
public String getPublicId() {
return location.getPublicId();
}
@Override
public String getSystemId() {
return location.getSystemId();
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.internal.impl;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.maven.api.Session;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.api.services.SettingsBuilderRequest;
import org.apache.maven.api.services.SettingsBuilderResult;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.xml.SettingsXmlFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
*/
@ExtendWith(MockitoExtension.class)
class DefaultSettingsBuilderFactoryTest {
@Mock
Session session;
@BeforeEach
void setup() {
Map<String, String> map = System.getProperties().entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(), e -> e.getValue().toString()));
// lenient().when(session.getSystemProperties()).thenReturn(map);
// lenient().when(session.getUserProperties()).thenReturn(Collections.emptyMap());
Mockito.lenient()
.when(session.getService(SettingsXmlFactory.class))
.thenReturn(new DefaultSettingsXmlFactory());
}
@Test
void testCompleteWiring() {
SettingsBuilder builder = new DefaultSettingsBuilder();
assertNotNull(builder);
SettingsBuilderRequest request = SettingsBuilderRequest.builder()
.session(session)
.userSettingsSource(Source.fromPath(getSettings("settings-simple")))
.build();
SettingsBuilderResult result = builder.build(request);
assertNotNull(result);
assertNotNull(result.getEffectiveSettings());
}
private Path getSettings(String name) {
return Paths.get("src/test/resources/" + name + ".xml").toAbsolutePath();
}
}

View File

@ -0,0 +1,234 @@
/*
* 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.internal.impl;
import java.util.List;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.Settings;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*/
class DefaultSettingsValidatorTest {
private SettingsBuilder validator;
@BeforeEach
void setUp() throws Exception {
validator = new DefaultSettingsBuilder();
}
@AfterEach
void tearDown() throws Exception {
validator = null;
}
private void assertContains(String msg, String substring) {
assertTrue(msg.contains(substring), "\"" + substring + "\" was not found in: " + msg);
}
@Test
void testValidate() {
Profile prof = Profile.newBuilder().id("xxx").build();
Settings model = Settings.newBuilder().profiles(List.of(prof)).build();
List<BuilderProblem> problems = validator.validate(model);
assertEquals(0, problems.size());
Repository repo = org.apache.maven.api.settings.Repository.newInstance(false);
Settings model2 = Settings.newBuilder()
.profiles(List.of(prof.withRepositories(List.of(repo))))
.build();
problems.clear();
problems = validator.validate(model2);
assertEquals(2, problems.size());
repo = repo.withUrl("http://xxx.xxx.com");
model2 = Settings.newBuilder()
.profiles(List.of(prof.withRepositories(List.of(repo))))
.build();
problems.clear();
problems = validator.validate(model2);
assertEquals(1, problems.size());
repo = repo.withId("xxx");
model2 = Settings.newBuilder()
.profiles(List.of(prof.withRepositories(List.of(repo))))
.build();
problems.clear();
problems = validator.validate(model2);
assertEquals(0, problems.size());
}
/*
@Test
void testValidateMirror() throws Exception {
Settings settings = new Settings();
Mirror mirror = new Mirror();
mirror.setId("local");
settings.addMirror(mirror);
mirror = new Mirror();
mirror.setId("illegal\\:/chars");
mirror.setUrl("http://void");
mirror.setMirrorOf("void");
settings.addMirror(mirror);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(4, problems.messages.size());
assertContains(problems.messages.get(0), "'mirrors.mirror.id' must not be 'local'");
assertContains(problems.messages.get(1), "'mirrors.mirror.url' for local is missing");
assertContains(problems.messages.get(2), "'mirrors.mirror.mirrorOf' for local is missing");
assertContains(problems.messages.get(3), "'mirrors.mirror.id' must not contain any of these characters");
}
@Test
void testValidateRepository() throws Exception {
Profile profile = new Profile();
Repository repo = new Repository();
repo.setId("local");
profile.addRepository(repo);
repo = new Repository();
repo.setId("illegal\\:/chars");
repo.setUrl("http://void");
profile.addRepository(repo);
Settings settings = new Settings();
settings.addProfile(profile);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(3, problems.messages.size());
assertContains(
problems.messages.get(0), "'profiles.profile[default].repositories.repository.id' must not be 'local'");
assertContains(
problems.messages.get(1),
"'profiles.profile[default].repositories.repository.url' for local is missing");
assertContains(
problems.messages.get(2),
"'profiles.profile[default].repositories.repository.id' must not contain any of these characters");
}
@Test
void testValidateUniqueServerId() throws Exception {
Settings settings = new Settings();
Server server1 = new Server();
server1.setId("test");
settings.addServer(server1);
Server server2 = new Server();
server2.setId("test");
settings.addServer(server2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0), "'servers.server.id' must be unique but found duplicate server with id test");
}
@Test
void testValidateUniqueProfileId() throws Exception {
Settings settings = new Settings();
Profile profile1 = new Profile();
profile1.setId("test");
settings.addProfile(profile1);
Profile profile2 = new Profile();
profile2.setId("test");
settings.addProfile(profile2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0),
"'profiles.profile.id' must be unique but found duplicate profile with id test");
}
@Test
void testValidateUniqueRepositoryId() throws Exception {
Settings settings = new Settings();
Profile profile = new Profile();
profile.setId("pro");
settings.addProfile(profile);
Repository repo1 = new Repository();
repo1.setUrl("http://apache.org/");
repo1.setId("test");
profile.addRepository(repo1);
Repository repo2 = new Repository();
repo2.setUrl("http://apache.org/");
repo2.setId("test");
profile.addRepository(repo2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0),
"'profiles.profile[pro].repositories.repository.id' must be unique"
+ " but found duplicate repository with id test");
}
@Test
void testValidateUniqueProxyId() throws Exception {
Settings settings = new Settings();
Proxy proxy = new Proxy();
String id = "foo";
proxy.setId(id);
proxy.setHost("www.example.com");
settings.addProxy(proxy);
settings.addProxy(proxy);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0),
"'proxies.proxy.id' must be unique" + " but found duplicate proxy with id " + id);
}
@Test
void testValidateProxy() throws Exception {
Settings settings = new Settings();
Proxy proxy1 = new Proxy();
settings.addProxy(proxy1);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(problems.messages.get(0), "'proxies.proxy.host' for default is missing");
}
private static class SimpleProblemCollector implements SettingsProblemCollector {
public List<String> messages = new ArrayList<>();
public void add(Severity severity, String message, int line, int column, Exception cause) {
messages.add(message);
}
}
*/
}

View File

@ -0,0 +1,336 @@
/*
* 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.internal.impl.standalone;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.Version;
import org.apache.maven.api.di.Provides;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.Lookup;
import org.apache.maven.api.services.MavenException;
import org.apache.maven.api.services.RepositoryFactory;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.di.Injector;
import org.apache.maven.di.Key;
import org.apache.maven.di.impl.DIException;
import org.apache.maven.internal.impl.AbstractSession;
import org.apache.maven.internal.impl.DefaultArtifactCoordinateFactory;
import org.apache.maven.internal.impl.DefaultArtifactDeployer;
import org.apache.maven.internal.impl.DefaultArtifactFactory;
import org.apache.maven.internal.impl.DefaultArtifactInstaller;
import org.apache.maven.internal.impl.DefaultArtifactResolver;
import org.apache.maven.internal.impl.DefaultChecksumAlgorithmService;
import org.apache.maven.internal.impl.DefaultDependencyCollector;
import org.apache.maven.internal.impl.DefaultDependencyCoordinateFactory;
import org.apache.maven.internal.impl.DefaultLocalRepositoryManager;
import org.apache.maven.internal.impl.DefaultMessageBuilderFactory;
import org.apache.maven.internal.impl.DefaultModelXmlFactory;
import org.apache.maven.internal.impl.DefaultRepositoryFactory;
import org.apache.maven.internal.impl.DefaultSettingsBuilder;
import org.apache.maven.internal.impl.DefaultSettingsXmlFactory;
import org.apache.maven.internal.impl.DefaultToolchainsBuilder;
import org.apache.maven.internal.impl.DefaultToolchainsXmlFactory;
import org.apache.maven.internal.impl.DefaultTransportProvider;
import org.apache.maven.internal.impl.DefaultVersionParser;
import org.apache.maven.internal.impl.DefaultVersionRangeResolver;
import org.apache.maven.internal.impl.DefaultVersionResolver;
import org.apache.maven.model.path.DefaultPathTranslator;
import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
import org.apache.maven.model.profile.DefaultProfileSelector;
import org.apache.maven.model.profile.activation.FileProfileActivator;
import org.apache.maven.model.profile.activation.JdkVersionProfileActivator;
import org.apache.maven.model.profile.activation.OperatingSystemProfileActivator;
import org.apache.maven.model.profile.activation.PropertyProfileActivator;
import org.apache.maven.model.root.DefaultRootLocator;
import org.apache.maven.repository.internal.DefaultModelVersionParser;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.supplier.RepositorySystemSupplier;
import org.eclipse.aether.util.version.GenericVersionScheme;
public class ApiRunner {
/**
* Create a new session.
*/
public static Session createSession() {
Injector injector = Injector.create();
injector.bindInstance(Injector.class, injector);
injector.bindImplicit(ApiRunner.class);
injector.bindImplicit(DefaultArtifactCoordinateFactory.class);
injector.bindImplicit(DefaultArtifactDeployer.class);
injector.bindImplicit(DefaultArtifactFactory.class);
injector.bindImplicit(DefaultArtifactInstaller.class);
injector.bindImplicit(DefaultArtifactResolver.class);
injector.bindImplicit(DefaultChecksumAlgorithmService.class);
injector.bindImplicit(DefaultDependencyCollector.class);
injector.bindImplicit(DefaultDependencyCoordinateFactory.class);
injector.bindImplicit(DefaultLocalRepositoryManager.class);
injector.bindImplicit(DefaultMessageBuilderFactory.class);
injector.bindImplicit(DefaultModelXmlFactory.class);
injector.bindImplicit(DefaultRepositoryFactory.class);
injector.bindImplicit(DefaultSettingsBuilder.class);
injector.bindImplicit(DefaultSettingsXmlFactory.class);
injector.bindImplicit(DefaultToolchainsBuilder.class);
injector.bindImplicit(DefaultToolchainsXmlFactory.class);
injector.bindImplicit(DefaultTransportProvider.class);
injector.bindImplicit(DefaultVersionParser.class);
injector.bindImplicit(DefaultVersionRangeResolver.class);
injector.bindImplicit(DefaultVersionResolver.class);
return injector.getInstance(Session.class);
}
static class DefaultSession extends AbstractSession {
DefaultSession(RepositorySystemSession session, RepositorySystem repositorySystem, Lookup lookup) {
this(session, repositorySystem, Collections.emptyList(), null, lookup);
}
protected DefaultSession(
RepositorySystemSession session,
RepositorySystem repositorySystem,
List<RemoteRepository> repositories,
List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories,
Lookup lookup) {
super(session, repositorySystem, repositories, resolverRepositories, lookup);
}
@Override
protected Session newSession(RepositorySystemSession session, List<RemoteRepository> repositories) {
return new DefaultSession(session, repositorySystem, repositories, null, lookup);
}
@Override
public Settings getSettings() {
return null;
}
@Override
public Map<String, String> getUserProperties() {
return null;
}
@Override
public Map<String, String> getSystemProperties() {
return null;
}
@Override
public Map<String, String> getEffectiveProperties(Project project) {
return null;
}
@Override
public Version getMavenVersion() {
return null;
}
@Override
public int getDegreeOfConcurrency() {
return 0;
}
@Override
public Instant getStartTime() {
return null;
}
@Override
public Path getTopDirectory() {
return null;
}
@Override
public Path getRootDirectory() {
return null;
}
@Override
public List<Project> getProjects() {
return List.of();
}
@Override
public Map<String, Object> getPluginContext(Project project) {
throw new UnsupportedInStandaloneModeException();
}
}
@Provides
static Lookup newLookup(Injector injector) {
return new Lookup() {
@Override
public <T> T lookup(Class<T> type) {
try {
return injector.getInstance(type);
} catch (DIException e) {
throw new MavenException("Unable to locate instance of type " + type, e);
}
}
@Override
public <T> T lookup(Class<T> type, String name) {
try {
return injector.getInstance(Key.of(type, name));
} catch (DIException e) {
throw new MavenException("Unable to locate instance of type " + type, e);
}
}
@Override
public <T> Optional<T> lookupOptional(Class<T> type) {
try {
return Optional.of(injector.getInstance(type));
} catch (DIException e) {
return Optional.empty();
}
}
@Override
public <T> Optional<T> lookupOptional(Class<T> type, String name) {
try {
return Optional.of(injector.getInstance(Key.of(type, name)));
} catch (DIException e) {
return Optional.empty();
}
}
@Override
public <T> List<T> lookupList(Class<T> type) {
return injector.getInstance(new Key<List<T>>() {});
}
@Override
public <T> Map<String, T> lookupMap(Class<T> type) {
return injector.getInstance(new Key<Map<String, T>>() {});
}
};
}
@Provides
static ArtifactManager newArtifactManager() {
return new ArtifactManager() {
private final Map<Artifact, Path> paths = new ConcurrentHashMap<>();
@Override
public Optional<Path> getPath(Artifact artifact) {
return Optional.ofNullable(paths.get(artifact));
}
@Override
public void setPath(Artifact artifact, Path path) {
paths.put(artifact, path);
}
};
}
@Provides
static DefaultModelVersionParser newModelVersionParser() {
return new DefaultModelVersionParser(new GenericVersionScheme());
}
@Provides
static Session newSession(Lookup lookup) {
Map<String, String> properties = new HashMap<>();
// Env variables prefixed with "env."
System.getenv().forEach((k, v) -> properties.put("env." + k, v));
// Java System properties
System.getProperties().forEach((k, v) -> properties.put(k.toString(), v.toString()));
RepositorySystem system = new RepositorySystemSupplier().get();
// SettingsDecrypter settingsDecrypter =
// (SettingsDecrypter)Objects.requireNonNull(this.createSettingsDecrypter(preBoot));
new DefaultProfileSelector(List.of(
new JdkVersionProfileActivator(),
new PropertyProfileActivator(),
new OperatingSystemProfileActivator(),
new FileProfileActivator(new ProfileActivationFilePathInterpolator(
new DefaultPathTranslator(), new DefaultRootLocator()))));
Path userHome = Paths.get(properties.get("user.home"));
Path mavenUserHome = userHome.resolve(".m2");
Path mavenSystemHome = properties.containsKey("maven.home")
? Paths.get(properties.get("maven.home"))
: properties.containsKey("env.MAVEN_HOME") ? Paths.get(properties.get("env.MAVEN_HOME")) : null;
DefaultRepositorySystemSession rsession = new DefaultRepositorySystemSession(h -> false);
rsession.setSystemProperties(properties);
rsession.setConfigProperties(properties);
DefaultSession session = new DefaultSession(
rsession,
system,
List.of(lookup.lookup(RepositoryFactory.class)
.createRemote("central", "https://repo.maven.apache.org/maven2")),
null,
lookup);
Settings settings = session.getService(SettingsBuilder.class)
.build(
session,
mavenSystemHome != null ? mavenSystemHome.resolve("settings.xml") : null,
mavenUserHome.resolve("settings.xml"))
.getEffectiveSettings();
settings.getProfiles();
// local repository
String localRepository = settings.getLocalRepository() != null
? settings.getLocalRepository()
: mavenUserHome.resolve("repository").toString();
LocalRepositoryManager llm = system.newLocalRepositoryManager(rsession, new LocalRepository(localRepository));
rsession.setLocalRepositoryManager(llm);
// active proxies
// TODO
// active profiles
DefaultSession defaultSession = new DefaultSession(
rsession,
system,
List.of(lookup.lookup(RepositoryFactory.class)
.createRemote("central", "https://repo.maven.apache.org/maven2")),
null,
lookup);
// settings.getDelegate().getRepositories().stream()
// .map(r -> SettingsUtilsV4.)
// defaultSession.getService(RepositoryFactory.class).createRemote()
return defaultSession;
}
static class UnsupportedInStandaloneModeException extends MavenException {}
}

View File

@ -0,0 +1,51 @@
/*
* 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.internal.impl.standalone;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.Node;
import org.apache.maven.api.Session;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class TestApiStandalone {
@Test
void testStandalone() {
Session session = ApiRunner.createSession();
ArtifactCoordinate coord = session.createArtifactCoordinate("org.apache.maven:maven-api-core:4.0.0-alpha-13");
Map.Entry<Artifact, Path> res = session.resolveArtifact(coord);
assertNotNull(res);
assertNotNull(res.getValue());
assertTrue(Files.exists(res.getValue()));
Node node = session.collectDependencies(session.createDependencyCoordinate(coord));
assertNotNull(node);
assertEquals(8, node.getChildren().size());
}
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<settings>
<localRepository>${user.home}/.m2/repository</localRepository>
</settings>

View File

@ -87,6 +87,10 @@ under the License.
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>

View File

@ -60,7 +60,7 @@
import org.apache.maven.graph.GraphBuilder;
import org.apache.maven.graph.ProjectSelector;
import org.apache.maven.internal.impl.DefaultSessionFactory;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.InternalMavenSession;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.LifecycleStarter;
@ -218,7 +218,7 @@ private MavenExecutionResult doExecute(MavenExecutionRequest request) {
sessionScope.seed(MavenSession.class, session);
sessionScope.seed(Session.class, session.getSession());
sessionScope.seed(InternalSession.class, InternalSession.from(session.getSession()));
sessionScope.seed(InternalMavenSession.class, InternalMavenSession.from(session.getSession()));
legacySupport.setSession(session);

View File

@ -32,6 +32,7 @@
import org.apache.maven.api.Session;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.RepositoryCache;
import org.apache.maven.internal.impl.SettingsUtilsV4;
import org.apache.maven.model.Profile;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@ -41,7 +42,6 @@
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.SettingsUtilsV4;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.eclipse.aether.RepositorySystemSession;

View File

@ -44,12 +44,12 @@
public class DefaultArtifactManager implements ArtifactManager {
@Nonnull
private final InternalSession session;
private final InternalMavenSession session;
private final Map<String, Path> paths = new ConcurrentHashMap<>();
@Inject
public DefaultArtifactManager(@Nonnull InternalSession session) {
public DefaultArtifactManager(@Nonnull InternalMavenSession session) {
this.session = session;
}

View File

@ -28,10 +28,10 @@
import org.apache.maven.execution.ExecutionEvent;
public class DefaultEvent implements Event {
private final InternalSession session;
private final InternalMavenSession session;
private final ExecutionEvent delegate;
public DefaultEvent(InternalSession session, ExecutionEvent delegate) {
public DefaultEvent(InternalMavenSession session, ExecutionEvent delegate) {
this.session = session;
this.delegate = delegate;
}

View File

@ -41,10 +41,10 @@
import org.eclipse.aether.graph.DependencyNode;
public class DefaultMojoExecution implements MojoExecution {
private final InternalSession session;
private final InternalMavenSession session;
private final org.apache.maven.plugin.MojoExecution delegate;
public DefaultMojoExecution(InternalSession session, org.apache.maven.plugin.MojoExecution delegate) {
public DefaultMojoExecution(InternalMavenSession session, org.apache.maven.plugin.MojoExecution delegate) {
this.session = session;
this.delegate = delegate;
}

View File

@ -35,6 +35,8 @@
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxWriter;
import static org.apache.maven.internal.impl.StaxLocation.getLocation;
import static org.apache.maven.internal.impl.StaxLocation.getMessage;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -67,7 +69,7 @@ public PluginDescriptor read(@Nonnull XmlReaderRequest request) throws XmlReader
}
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read model", e);
throw new XmlReaderException("Unable to read plugin: " + getMessage(e), getLocation(e), e);
}
}
@ -92,7 +94,7 @@ public void write(XmlWriterRequest<PluginDescriptor> request) throws XmlWriterEx
}
}
} catch (Exception e) {
throw new XmlWriterException("Unable to write model", e);
throw new XmlWriterException("Unable to write plugin: " + getMessage(e), getLocation(e), e);
}
}

View File

@ -35,17 +35,17 @@
public class DefaultProject implements Project {
private final InternalSession session;
private final InternalMavenSession session;
private final MavenProject project;
private final Packaging packaging;
public DefaultProject(InternalSession session, MavenProject project) {
public DefaultProject(InternalMavenSession session, MavenProject project) {
this.session = session;
this.project = project;
this.packaging = session.requirePackaging(project.getPackaging());
}
public InternalSession getSession() {
public InternalMavenSession getSession() {
return session;
}

View File

@ -65,7 +65,7 @@ public DefaultProjectBuilder(org.apache.maven.project.ProjectBuilder builder) {
@Override
public ProjectBuilderResult build(ProjectBuilderRequest request)
throws ProjectBuilderException, IllegalArgumentException {
InternalSession session = InternalSession.from(request.getSession());
InternalMavenSession session = InternalMavenSession.from(request.getSession());
try {
List<ArtifactRepository> repositories = session.toArtifactRepositories(session.getRemoteRepositories());
ProjectBuildingRequest req = new DefaultProjectBuildingRequest()

View File

@ -44,11 +44,11 @@
@SessionScoped
public class DefaultProjectManager implements ProjectManager {
private final InternalSession session;
private final InternalMavenSession session;
private final ArtifactManager artifactManager;
@Inject
public DefaultProjectManager(InternalSession session, ArtifactManager artifactManager) {
public DefaultProjectManager(InternalMavenSession session, ArtifactManager artifactManager) {
this.session = session;
this.artifactManager = artifactManager;
}
@ -66,7 +66,7 @@ public Optional<Path> getPath(Project project) {
@Nonnull
@Override
public Collection<Artifact> getAttachedArtifacts(Project project) {
InternalSession session = ((DefaultProject) project).getSession();
InternalMavenSession session = ((DefaultProject) project).getSession();
Collection<Artifact> attached = map(
getMavenProject(project).getAttachedArtifacts(),
a -> session.getArtifact(RepositoryUtils.toArtifact(a)));

View File

@ -21,8 +21,6 @@
import java.nio.file.Path;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.*;
@ -38,43 +36,39 @@
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
import org.apache.maven.rtinfo.RuntimeInformation;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import static org.apache.maven.internal.impl.Utils.map;
import static org.apache.maven.internal.impl.Utils.nonNull;
public class DefaultSession extends AbstractSession {
public class DefaultSession extends AbstractSession implements InternalMavenSession {
private final MavenSession mavenSession;
private final RepositorySystemSession session;
private final RepositorySystem repositorySystem;
private final List<RemoteRepository> repositories;
private final MavenRepositorySystem mavenRepositorySystem;
private final Lookup lookup;
private final RuntimeInformation runtimeInformation;
private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>();
private final Map<String, Project> allProjects = Collections.synchronizedMap(new WeakHashMap<>());
@SuppressWarnings("checkstyle:ParameterNumber")
public DefaultSession(
@Nonnull MavenSession session,
@Nonnull RepositorySystem repositorySystem,
@Nullable List<RemoteRepository> repositories,
@Nullable List<RemoteRepository> remoteRepositories,
@Nonnull MavenRepositorySystem mavenRepositorySystem,
@Nonnull Lookup lookup,
@Nonnull RuntimeInformation runtimeInformation) {
super(
session.getRepositorySession(),
repositorySystem,
remoteRepositories,
remoteRepositories == null
? map(session.getRequest().getRemoteRepositories(), RepositoryUtils::toRepo)
: null,
lookup);
this.mavenSession = nonNull(session);
this.session = mavenSession.getRepositorySession();
this.repositorySystem = nonNull(repositorySystem);
this.repositories = repositories != null
? repositories
: map(
mavenSession.getRequest().getRemoteRepositories(),
r -> getRemoteRepository(RepositoryUtils.toRepo(r)));
this.mavenRepositorySystem = mavenRepositorySystem;
this.lookup = lookup;
this.runtimeInformation = runtimeInformation;
}
@ -82,16 +76,19 @@ public MavenSession getMavenSession() {
return mavenSession;
}
@Nonnull
@Override
public LocalRepository getLocalRepository() {
return new DefaultLocalRepository(session.getLocalRepository());
public List<Project> getProjects(List<MavenProject> projects) {
return projects == null ? null : map(projects, this::getProject);
}
@Nonnull
@Override
public List<RemoteRepository> getRemoteRepositories() {
return Collections.unmodifiableList(repositories);
public Project getProject(MavenProject project) {
return allProjects.computeIfAbsent(project.getId(), id -> new DefaultProject(this, project));
}
@Override
public List<ArtifactRepository> toArtifactRepositories(List<RemoteRepository> repositories) {
return repositories == null ? null : map(repositories, this::toArtifactRepository);
}
@Nonnull
@ -171,92 +168,13 @@ public Map<String, Object> getPluginContext(Project project) {
}
}
@Nonnull
@Override
public SessionData getData() {
org.eclipse.aether.SessionData data = session.getData();
return new SessionData() {
@Override
public <T> void set(@Nonnull Key<T> key, @Nullable T value) {
data.set(key, value);
}
@Override
public <T> boolean replace(@Nonnull Key<T> key, @Nullable T oldValue, @Nullable T newValue) {
return data.set(key, oldValue, newValue);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public <T> T get(@Nonnull Key<T> key) {
return (T) data.get(key);
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public <T> T computeIfAbsent(@Nonnull Key<T> key, @Nonnull Supplier<T> supplier) {
return (T) data.computeIfAbsent(key, (Supplier<Object>) supplier);
}
};
}
@Nonnull
@Override
public Session withLocalRepository(@Nonnull LocalRepository localRepository) {
nonNull(localRepository, "localRepository");
if (session.getLocalRepository() != null
&& Objects.equals(session.getLocalRepository().getBasedir().toPath(), localRepository.getPath())) {
return this;
protected Session newSession(RepositorySystemSession repoSession, List<RemoteRepository> repositories) {
MavenSession ms = this.mavenSession;
if (repoSession != this.getSession()) {
ms = new MavenSession(repoSession, ms.getRequest(), ms.getResult());
}
org.eclipse.aether.repository.LocalRepository repository = toRepository(localRepository);
org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager =
repositorySystem.newLocalRepositoryManager(session, repository);
RepositorySystemSession repoSession =
new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
MavenSession newSession = new MavenSession(repoSession, mavenSession.getRequest(), mavenSession.getResult());
return new DefaultSession(
newSession, repositorySystem, repositories, mavenRepositorySystem, lookup, runtimeInformation);
}
@Nonnull
@Override
public Session withRemoteRepositories(@Nonnull List<RemoteRepository> repositories) {
return new DefaultSession(
mavenSession, repositorySystem, repositories, mavenRepositorySystem, lookup, runtimeInformation);
}
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementException {
T t = (T) services.computeIfAbsent(clazz, this::lookup);
if (t == null) {
throw new NoSuchElementException(clazz.getName());
}
return t;
}
private Service lookup(Class<? extends Service> c) {
try {
return lookup.lookup(c);
} catch (LookupException e) {
NoSuchElementException nsee = new NoSuchElementException(c.getName());
e.initCause(e);
throw nsee;
}
}
@Nonnull
public RepositorySystemSession getSession() {
return session;
}
@Nonnull
public RepositorySystem getRepositorySystem() {
return repositorySystem;
ms, getRepositorySystem(), repositories, mavenRepositorySystem, lookup, runtimeInformation);
}
public ArtifactRepository toArtifactRepository(RemoteRepository repository) {
@ -281,25 +199,4 @@ public ArtifactRepository toArtifactRepository(RemoteRepository repository) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
public org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency, boolean managed) {
org.eclipse.aether.graph.Dependency dep;
if (dependency instanceof DefaultDependencyCoordinate) {
dep = ((DefaultDependencyCoordinate) dependency).getDependency();
} else {
dep = new org.eclipse.aether.graph.Dependency(
new org.eclipse.aether.artifact.DefaultArtifact(
dependency.getGroupId(),
dependency.getArtifactId(),
dependency.getClassifier(),
dependency.getType().getExtension(),
dependency.getVersion().toString(),
null),
dependency.getScope().id());
}
if (!managed && "".equals(dep.getScope())) {
dep = dep.setScope(DependencyScope.COMPILE.id());
}
return dep;
}
}

View File

@ -53,7 +53,7 @@ public DefaultSessionFactory(
public Session getSession(MavenSession mavenSession) {
SessionData data = mavenSession.getRepositorySession().getData();
return (Session) data.computeIfAbsent(InternalSession.class, () -> newSession(mavenSession));
return (Session) data.computeIfAbsent(InternalMavenSession.class, () -> newSession(mavenSession));
}
private Session newSession(MavenSession mavenSession) {

View File

@ -1,162 +0,0 @@
/*
* 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.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.api.services.SettingsBuilderException;
import org.apache.maven.api.services.SettingsBuilderRequest;
import org.apache.maven.api.services.SettingsBuilderResult;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuildingException;
import org.apache.maven.settings.building.SettingsBuildingResult;
import org.apache.maven.settings.building.SettingsProblem;
import org.apache.maven.settings.building.SettingsSource;
@Named
@Singleton
public class DefaultSettingsBuilder implements SettingsBuilder {
private final org.apache.maven.settings.building.SettingsBuilder builder;
@Inject
public DefaultSettingsBuilder(org.apache.maven.settings.building.SettingsBuilder builder) {
this.builder = builder;
}
@Nonnull
@Override
public SettingsBuilderResult build(SettingsBuilderRequest request)
throws SettingsBuilderException, IllegalArgumentException {
InternalSession session = InternalSession.from(request.getSession());
try {
DefaultSettingsBuildingRequest req = new DefaultSettingsBuildingRequest();
req.setUserProperties(toProperties(session.getUserProperties()));
req.setSystemProperties(toProperties(session.getSystemProperties()));
if (request.getGlobalSettingsSource().isPresent()) {
req.setGlobalSettingsSource(new MappedSettingsSource(
request.getGlobalSettingsSource().get()));
}
if (request.getGlobalSettingsPath().isPresent()) {
req.setGlobalSettingsFile(request.getGlobalSettingsPath().get().toFile());
}
if (request.getUserSettingsSource().isPresent()) {
req.setUserSettingsSource(
new MappedSettingsSource(request.getUserSettingsSource().get()));
}
if (request.getUserSettingsPath().isPresent()) {
req.setUserSettingsFile(request.getUserSettingsPath().get().toFile());
}
SettingsBuildingResult result = builder.build(req);
return new SettingsBuilderResult() {
@Override
public Settings getEffectiveSettings() {
return result.getEffectiveSettings().getDelegate();
}
@Override
public List<BuilderProblem> getProblems() {
return new MappedList<>(result.getProblems(), MappedBuilderProblem::new);
}
};
} catch (SettingsBuildingException e) {
throw new SettingsBuilderException("Unable to build settings", e);
}
}
private Properties toProperties(Map<String, String> map) {
Properties properties = new Properties();
properties.putAll(map);
return properties;
}
private static class MappedSettingsSource implements SettingsSource {
private final Source source;
MappedSettingsSource(Source source) {
this.source = source;
}
@Override
public InputStream getInputStream() throws IOException {
return source.openStream();
}
@Override
public String getLocation() {
return source.getLocation();
}
}
private static class MappedBuilderProblem implements BuilderProblem {
private final SettingsProblem problem;
MappedBuilderProblem(SettingsProblem problem) {
this.problem = problem;
}
@Override
public String getSource() {
return problem.getSource();
}
@Override
public int getLineNumber() {
return problem.getLineNumber();
}
@Override
public int getColumnNumber() {
return problem.getColumnNumber();
}
@Override
public String getLocation() {
return problem.getLocation();
}
@Override
public Exception getException() {
return problem.getException();
}
@Override
public String getMessage() {
return problem.getMessage();
}
@Override
public Severity getSeverity() {
return Severity.valueOf(problem.getSeverity().name());
}
}
}

View File

@ -49,7 +49,7 @@ public DefaultToolchainManager(DefaultToolchainManagerPrivate toolchainManagerPr
@Override
public List<Toolchain> getToolchains(Session session, String type, Map<String, String> requirements)
throws ToolchainManagerException {
MavenSession s = InternalSession.from(session).getMavenSession();
MavenSession s = InternalMavenSession.from(session).getMavenSession();
List<org.apache.maven.toolchain.Toolchain> toolchains =
toolchainManagerPrivate.getToolchains(s, type, requirements);
return new MappedList<>(toolchains, this::toToolchain);
@ -58,7 +58,7 @@ public List<Toolchain> getToolchains(Session session, String type, Map<String, S
@Override
public Optional<Toolchain> getToolchainFromBuildContext(Session session, String type)
throws ToolchainManagerException {
MavenSession s = InternalSession.from(session).getMavenSession();
MavenSession s = InternalMavenSession.from(session).getMavenSession();
return Optional.ofNullable(toolchainManagerPrivate.getToolchainFromBuildContext(type, s))
.map(this::toToolchain);
}
@ -66,7 +66,7 @@ public Optional<Toolchain> getToolchainFromBuildContext(Session session, String
@Override
public List<Toolchain> getToolchainsForType(Session session, String type) throws ToolchainManagerException {
try {
MavenSession s = InternalSession.from(session).getMavenSession();
MavenSession s = InternalMavenSession.from(session).getMavenSession();
ToolchainPrivate[] toolchains = toolchainManagerPrivate.getToolchainsForType(type, s);
return new MappedList<>(Arrays.asList(toolchains), this::toToolchain);
} catch (MisconfiguredToolchainException e) {
@ -76,7 +76,7 @@ public List<Toolchain> getToolchainsForType(Session session, String type) throws
@Override
public void storeToolchainToBuildContext(Session session, Toolchain toolchain) throws ToolchainManagerException {
MavenSession s = InternalSession.from(session).getMavenSession();
MavenSession s = InternalMavenSession.from(session).getMavenSession();
org.apache.maven.toolchain.ToolchainPrivate tc =
(org.apache.maven.toolchain.ToolchainPrivate) ((ToolchainWrapper) toolchain).toolchain;
toolchainManagerPrivate.storeToolchainToBuildContext(tc, s);

View File

@ -1,149 +0,0 @@
/*
* 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.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.ToolchainsBuilder;
import org.apache.maven.api.services.ToolchainsBuilderException;
import org.apache.maven.api.services.ToolchainsBuilderRequest;
import org.apache.maven.api.services.ToolchainsBuilderResult;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest;
import org.apache.maven.toolchain.building.ToolchainsBuildingException;
import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
@Named
@Singleton
public class DefaultToolchainsBuilder implements ToolchainsBuilder {
private final org.apache.maven.toolchain.building.ToolchainsBuilder builder;
@Inject
public DefaultToolchainsBuilder(org.apache.maven.toolchain.building.ToolchainsBuilder builder) {
this.builder = builder;
}
@Nonnull
@Override
public ToolchainsBuilderResult build(ToolchainsBuilderRequest request)
throws ToolchainsBuilderException, IllegalArgumentException {
try {
DefaultToolchainsBuildingRequest req = new DefaultToolchainsBuildingRequest();
if (request.getGlobalToolchainsSource().isPresent()) {
req.setGlobalToolchainsSource(new MappedToolchainsSource(
request.getGlobalToolchainsSource().get()));
} else if (request.getGlobalToolchainsPath().isPresent()) {
req.setGlobalToolchainsSource(new org.apache.maven.building.FileSource(
request.getGlobalToolchainsPath().get().toFile()));
}
if (request.getUserToolchainsSource().isPresent()) {
req.setUserToolchainsSource(new MappedToolchainsSource(
request.getUserToolchainsSource().get()));
} else if (request.getUserToolchainsPath().isPresent()) {
req.setUserToolchainsSource(new org.apache.maven.building.FileSource(
request.getUserToolchainsPath().get().toFile()));
}
ToolchainsBuildingResult result = builder.build(req);
return new ToolchainsBuilderResult() {
@Override
public PersistedToolchains getEffectiveToolchains() {
return result.getEffectiveToolchains().getDelegate();
}
@Override
public List<BuilderProblem> getProblems() {
return new MappedList<>(result.getProblems(), MappedBuilderProblem::new);
}
};
} catch (ToolchainsBuildingException e) {
throw new ToolchainsBuilderException("Unable to build Toolchains", e);
}
}
private static class MappedToolchainsSource implements org.apache.maven.building.Source {
private final Source source;
MappedToolchainsSource(Source source) {
this.source = source;
}
@Override
public InputStream getInputStream() throws IOException {
return source.openStream();
}
@Override
public String getLocation() {
return source.getLocation();
}
}
private static class MappedBuilderProblem implements BuilderProblem {
private final org.apache.maven.building.Problem problem;
MappedBuilderProblem(org.apache.maven.building.Problem problem) {
this.problem = problem;
}
@Override
public String getSource() {
return problem.getSource();
}
@Override
public int getLineNumber() {
return problem.getLineNumber();
}
@Override
public int getColumnNumber() {
return problem.getColumnNumber();
}
@Override
public String getLocation() {
return problem.getLocation();
}
@Override
public Exception getException() {
return problem.getException();
}
@Override
public String getMessage() {
return problem.getMessage();
}
@Override
public Severity getSeverity() {
return Severity.valueOf(problem.getSeverity().name());
}
}
}

View File

@ -47,7 +47,7 @@ public void init(Context context) throws Exception {}
public void onEvent(Object arg) throws Exception {
if (arg instanceof ExecutionEvent) {
ExecutionEvent ee = (ExecutionEvent) arg;
InternalSession session = InternalSession.from(sessionFactory.getSession(ee.getSession()));
InternalMavenSession session = InternalMavenSession.from(sessionFactory.getSession(ee.getSession()));
Collection<Listener> listeners = session.getListeners();
if (!listeners.isEmpty()) {
Event event = new DefaultEvent(session, ee);

View File

@ -0,0 +1,46 @@
/*
* 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.internal.impl;
import java.util.List;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.execution.MavenSession;
import static org.apache.maven.internal.impl.Utils.cast;
public interface InternalMavenSession extends InternalSession {
static InternalMavenSession from(Session session) {
return cast(InternalMavenSession.class, session, "session should be an " + InternalMavenSession.class);
}
List<Project> getProjects(List<org.apache.maven.project.MavenProject> projects);
Project getProject(org.apache.maven.project.MavenProject project);
List<org.apache.maven.artifact.repository.ArtifactRepository> toArtifactRepositories(
List<RemoteRepository> repositories);
org.apache.maven.artifact.repository.ArtifactRepository toArtifactRepository(RemoteRepository repository);
MavenSession getMavenSession();
}

View File

@ -0,0 +1,89 @@
/*
* 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.internal.impl;
import javax.inject.Named;
import javax.inject.Provider;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import com.google.inject.AbstractModule;
import org.apache.maven.di.Injector;
import org.apache.maven.di.Key;
import org.apache.maven.di.impl.Binding;
import org.apache.maven.di.impl.InjectorImpl;
import org.codehaus.plexus.PlexusContainer;
@Named
class SisuDiBridgeModule extends AbstractModule {
@Override
protected void configure() {
Provider<PlexusContainer> containerProvider = getProvider(PlexusContainer.class);
Injector injector = new InjectorImpl() {
@Override
protected <T> Set<Binding<T>> getBindings(Key<T> key) {
Set<Binding<T>> bindings = super.getBindings(key);
if (bindings == null && key.getRawType() != List.class && key.getRawType() != Map.class) {
try {
T t = containerProvider.get().lookup(key.getRawType());
bindings = Set.of(new Binding.BindingToInstance<>(t));
} catch (Throwable e) {
// ignore
e.printStackTrace();
}
}
return bindings;
}
};
injector.bindInstance(Injector.class, injector);
bind(Injector.class).toInstance(injector);
Stream.of(
DefaultArtifactCoordinateFactory.class,
DefaultArtifactDeployer.class,
DefaultArtifactFactory.class,
DefaultArtifactInstaller.class,
DefaultArtifactResolver.class,
DefaultChecksumAlgorithmService.class,
DefaultDependencyCollector.class,
DefaultDependencyCoordinateFactory.class,
DefaultLocalRepositoryManager.class,
DefaultMessageBuilderFactory.class,
DefaultModelXmlFactory.class,
DefaultRepositoryFactory.class,
DefaultSettingsBuilder.class,
DefaultSettingsXmlFactory.class,
DefaultToolchainsBuilder.class,
DefaultToolchainsXmlFactory.class,
DefaultTransportProvider.class,
DefaultVersionParser.class,
DefaultVersionRangeResolver.class,
DefaultVersionResolver.class)
.forEach((Class<?> clazz) -> {
injector.bindImplicit(clazz);
Class<Object> itf = (Class) clazz.getInterfaces()[0];
bind(itf).toProvider(() -> injector.getInstance(clazz));
});
}
}

View File

@ -34,7 +34,7 @@
import org.apache.maven.execution.scope.internal.MojoExecutionScope;
import org.apache.maven.internal.impl.DefaultLog;
import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.InternalMavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@ -121,7 +121,7 @@ public void executeMojo(MavenSession session, MojoExecution mojoExecution)
org.apache.maven.api.plugin.Log.class,
new DefaultLog(LoggerFactory.getLogger(
mojoExecution.getMojoDescriptor().getFullGoalName())));
InternalSession sessionV4 = InternalSession.from(session.getSession());
InternalMavenSession sessionV4 = InternalMavenSession.from(session.getSession());
scope.seed(Project.class, sessionV4.getProject(project));
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(sessionV4, mojoExecution));

View File

@ -44,7 +44,7 @@
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
import org.apache.maven.internal.impl.DefaultLog;
import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.InternalMavenSession;
import org.apache.maven.internal.xml.XmlPlexusConfiguration;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.ContextEnabled;
@ -522,12 +522,12 @@ private <T> T loadV4Mojo(
throws PluginContainerException, PluginConfigurationException {
T mojo;
InternalSession sessionV4 = InternalSession.from(session.getSession());
InternalMavenSession sessionV4 = InternalMavenSession.from(session.getSession());
Project project = sessionV4.getProject(session.getCurrentProject());
List<org.apache.maven.api.RemoteRepository> repos =
sessionV4.getService(ProjectManager.class).getRemoteProjectRepositories(project);
sessionV4 = InternalSession.from(sessionV4.withRemoteRepositories(repos));
sessionV4 = InternalMavenSession.from(sessionV4.withRemoteRepositories(repos));
org.apache.maven.api.MojoExecution execution = new DefaultMojoExecution(sessionV4, mojoExecution);
org.apache.maven.api.plugin.Log log = new DefaultLog(
@ -665,7 +665,7 @@ private <T> T loadV3Mojo(
pomConfiguration = XmlPlexusConfiguration.toPlexusConfiguration(dom);
}
InternalSession sessionV4 = InternalSession.from(session.getSession());
InternalMavenSession sessionV4 = InternalMavenSession.from(session.getSession());
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution);
for (MavenPluginConfigurationValidator validator : configurationValidators) {

View File

@ -38,7 +38,7 @@
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.bridge.MavenRepositorySystem;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.InternalMavenSession;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
@ -909,7 +909,8 @@ private ModelBuildingRequest getModelBuildingRequest() {
modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session));
}
modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder);
InternalSession session = (InternalSession) this.session.getData().get(InternalSession.class);
InternalMavenSession session =
(InternalMavenSession) this.session.getData().get(InternalMavenSession.class);
if (session != null) {
try {
modelBuildingRequest.setRootDirectory(session.getRootDirectory());

View File

@ -32,7 +32,7 @@
import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlNodeStaxBuilder;
/**
* Creates an extension descriptor from some XML stream.
@ -89,7 +89,7 @@ public ExtensionDescriptor build(InputStream is) throws IOException {
XmlNode dom;
try {
XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(is);
dom = XmlNodeBuilder.build(reader);
dom = XmlNodeStaxBuilder.build(reader);
} catch (XMLStreamException e) {
throw new IOException(e.getMessage(), e);
}

View File

@ -25,7 +25,7 @@
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Session;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.InternalMavenSession;
/**
* SessionScopeModule
@ -55,8 +55,8 @@ protected void configure() {
bind(Session.class)
.toProvider(SessionScope.seededKeyProvider(Session.class))
.in(scope);
bind(InternalSession.class)
.toProvider(SessionScope.seededKeyProvider(InternalSession.class))
bind(InternalMavenSession.class)
.toProvider(SessionScope.seededKeyProvider(InternalMavenSession.class))
.in(scope);
}
}

View File

@ -18,6 +18,8 @@
*/
package org.apache.maven.settings;
import org.apache.maven.internal.impl.SettingsUtilsV4;
/**
* Several convenience methods to handle settings
*

View File

@ -26,7 +26,7 @@
import java.nio.file.Paths;
import org.apache.maven.configuration.internal.DefaultBeanConfigurator;
import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlNodeStaxBuilder;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -52,9 +52,9 @@ void tearDown() throws Exception {
private Xpp3Dom toConfig(String xml) {
try {
return new Xpp3Dom(XmlNodeBuilder.build(
return new Xpp3Dom(XmlNodeStaxBuilder.build(
new StringReader("<configuration>" + xml + "</configuration>"),
(XmlNodeBuilder.InputLocationBuilderStax) null));
(XmlNodeStaxBuilder.InputLocationBuilderStax) null));
} catch (XMLStreamException e) {
throw new IllegalArgumentException(e);
}

View File

@ -24,7 +24,7 @@
import java.io.StringReader;
import org.apache.maven.configuration.internal.DefaultBeanConfigurator;
import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlNodeStaxBuilder;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -50,9 +50,9 @@ void tearDown() throws Exception {
private Xpp3Dom toConfig(String xml) {
try {
return new Xpp3Dom(XmlNodeBuilder.build(
return new Xpp3Dom(XmlNodeStaxBuilder.build(
new StringReader("<configuration>" + xml + "</configuration>"),
(XmlNodeBuilder.InputLocationBuilderStax) null));
(XmlNodeStaxBuilder.InputLocationBuilderStax) null));
} catch (XMLStreamException e) {
throw new IllegalArgumentException(e);
}

View File

@ -125,7 +125,7 @@ void setup() {
.withRemoteRepositories(Collections.singletonList(remoteRepository));
sessionScope.enter();
sessionScope.seed(InternalSession.class, InternalSession.from(this.session));
sessionScope.seed(InternalMavenSession.class, InternalMavenSession.from(this.session));
}
private Project project(Artifact artifact) {

View File

@ -413,7 +413,8 @@ private MojoExecution newMojoExecution(Session session) {
pd.addComponentDescriptor(md);
return new DefaultMojoExecution((AbstractSession) session, new org.apache.maven.plugin.MojoExecution(md));
return new DefaultMojoExecution(
InternalMavenSession.from(session), new org.apache.maven.plugin.MojoExecution(md));
}
private DefaultSession newSession() throws Exception {

View File

@ -32,6 +32,7 @@
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.internal.impl.SettingsUtilsV4;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

View File

@ -143,7 +143,7 @@ public interface TupleConstructorN<R> {
public static class BindingToInstance<T> extends Binding<T> {
final T instance;
BindingToInstance(T instance) {
public BindingToInstance(T instance) {
super(null, Collections.emptySet());
this.instance = instance;
}

View File

@ -130,7 +130,7 @@ protected <U> Injector bind(Key<U> key, Binding<U> b) {
}
@SuppressWarnings({"unchecked", "rawtypes"})
private <T> Set<Binding<T>> getBindings(Key<T> key) {
protected <T> Set<Binding<T>> getBindings(Key<T> key) {
return (Set) bindings.get(key);
}

View File

@ -32,7 +32,7 @@
import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlNodeStaxBuilder;
import org.apache.maven.internal.xml.XmlPlexusConfiguration;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
import org.codehaus.plexus.component.repository.ComponentDependency;
@ -142,7 +142,7 @@ private PluginDescriptor build(String source, String nsUri, XMLStreamReader xsr)
new PluginDescriptorStaxReader().read(xsr, true);
return new PluginDescriptor(pd);
} else {
XmlNode node = XmlNodeBuilder.build(xsr, true, null);
XmlNode node = XmlNodeStaxBuilder.build(xsr, true, null);
PlexusConfiguration cfg = XmlPlexusConfiguration.toPlexusConfiguration(node);
return build(source, cfg);
}
@ -474,7 +474,7 @@ public MojoDescriptor buildComponentDescriptor(PlexusConfiguration c, PluginDesc
public PlexusConfiguration buildConfiguration(Reader configuration) throws PlexusConfigurationException {
try {
XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(configuration);
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(reader, true, null));
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeStaxBuilder.build(reader, true, null));
} catch (XMLStreamException e) {
throw new PlexusConfigurationException(e.getMessage(), e);
}
@ -483,7 +483,7 @@ public PlexusConfiguration buildConfiguration(Reader configuration) throws Plexu
public PlexusConfiguration buildConfiguration(InputStream configuration) throws PlexusConfigurationException {
try {
XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(configuration);
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(reader, true, null));
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeStaxBuilder.build(reader, true, null));
} catch (XMLStreamException e) {
throw new PlexusConfigurationException(e.getMessage(), e);
}

View File

@ -38,6 +38,10 @@ under the License.
</contributors>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-builder-support</artifactId>
@ -79,6 +83,11 @@ under the License.
<parameter>
<excludes>
<exclude>org.apache.maven.settings.validation.SettingsValidator#validate(org.apache.maven.settings.Settings,boolean,org.apache.maven.settings.building.SettingsProblemCollector):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.settings.building.DefaultSettingsBuilder#setSettingsReader(org.apache.maven.settings.io.SettingsReader):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.settings.building.DefaultSettingsBuilder#setSettingsValidator(org.apache.maven.settings.validation.SettingsValidator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.settings.building.DefaultSettingsBuilder#setSettingsWriter(org.apache.maven.settings.io.SettingsWriter):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.settings.building.DefaultSettingsBuilder#DefaultSettingsBuilder(org.apache.maven.settings.io.SettingsReader,org.apache.maven.settings.io.SettingsWriter,org.apache.maven.settings.validation.SettingsValidator):CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.settings.validation.DefaultSettingsValidator#DefaultSettingsValidator():CONSTRUCTOR_REMOVED</exclude>
</excludes>
</parameter>
</configuration>

View File

@ -24,29 +24,21 @@
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.maven.api.settings.InputSource;
import org.apache.maven.api.Session;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.SettingsBuilderException;
import org.apache.maven.api.services.SettingsBuilderRequest;
import org.apache.maven.api.services.SettingsBuilderResult;
import org.apache.maven.api.services.xml.SettingsXmlFactory;
import org.apache.maven.building.FileSource;
import org.apache.maven.building.Source;
import org.apache.maven.settings.Repository;
import org.apache.maven.settings.RepositoryPolicy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.TrackableBase;
import org.apache.maven.settings.io.SettingsParseException;
import org.apache.maven.settings.io.SettingsReader;
import org.apache.maven.settings.io.SettingsWriter;
import org.apache.maven.settings.merge.MavenSettingsMerger;
import org.apache.maven.settings.v4.SettingsTransformer;
import org.apache.maven.settings.validation.SettingsValidator;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
/**
* Builds the effective settings from a user settings file and/or a global settings file.
@ -56,215 +48,99 @@
@Singleton
public class DefaultSettingsBuilder implements SettingsBuilder {
private SettingsReader settingsReader;
private SettingsWriter settingsWriter;
private SettingsValidator settingsValidator;
private final MavenSettingsMerger settingsMerger = new MavenSettingsMerger();
private final org.apache.maven.internal.impl.DefaultSettingsBuilder builder;
private final org.apache.maven.internal.impl.DefaultSettingsXmlFactory settingsXmlFactory;
@Inject
public DefaultSettingsBuilder(
SettingsReader settingsReader, SettingsWriter settingsWriter, SettingsValidator settingsValidator) {
this.settingsReader = settingsReader;
this.settingsWriter = settingsWriter;
this.settingsValidator = settingsValidator;
}
public DefaultSettingsBuilder setSettingsReader(SettingsReader settingsReader) {
this.settingsReader = settingsReader;
return this;
}
public DefaultSettingsBuilder setSettingsWriter(SettingsWriter settingsWriter) {
this.settingsWriter = settingsWriter;
return this;
}
public DefaultSettingsBuilder setSettingsValidator(SettingsValidator settingsValidator) {
this.settingsValidator = settingsValidator;
return this;
org.apache.maven.internal.impl.DefaultSettingsBuilder builder,
org.apache.maven.internal.impl.DefaultSettingsXmlFactory settingsXmlFactory) {
this.builder = builder;
this.settingsXmlFactory = settingsXmlFactory;
}
@Override
public SettingsBuildingResult build(SettingsBuildingRequest request) throws SettingsBuildingException {
DefaultSettingsProblemCollector problems = new DefaultSettingsProblemCollector(null);
Source globalSettingsSource =
getSettingsSource(request.getGlobalSettingsFile(), request.getGlobalSettingsSource());
Settings globalSettings = readSettings(globalSettingsSource, false, request, problems);
try {
SettingsBuilderResult result = builder.build(SettingsBuilderRequest.builder()
.session((Session) java.lang.reflect.Proxy.newProxyInstance(
Session.class.getClassLoader(),
new Class[] {Session.class},
(Object proxy, Method method, Object[] args) -> {
if ("getSystemProperties".equals(method.getName())) {
return request.getSystemProperties().entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue().toString()));
} else if ("getUserProperties".equals(method.getName())) {
return request.getUserProperties().entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue().toString()));
} else if ("getService".equals(method.getName())) {
if (args[0] == SettingsXmlFactory.class) {
return settingsXmlFactory;
}
}
return null;
}))
.globalSettingsSource(toSource(request.getGlobalSettingsFile(), request.getGlobalSettingsSource()))
.projectSettingsSource(
toSource(request.getProjectSettingsFile(), request.getProjectSettingsSource()))
.userSettingsSource(toSource(request.getUserSettingsFile(), request.getUserSettingsSource()))
.build());
Source projectSettingsSource =
getSettingsSource(request.getProjectSettingsFile(), request.getProjectSettingsSource());
Settings projectSettings = readSettings(projectSettingsSource, true, request, problems);
Source userSettingsSource = getSettingsSource(request.getUserSettingsFile(), request.getUserSettingsSource());
Settings userSettings = readSettings(userSettingsSource, false, request, problems);
settingsMerger.merge(projectSettings, globalSettings, TrackableBase.GLOBAL_LEVEL);
settingsMerger.merge(userSettings, projectSettings, TrackableBase.PROJECT_LEVEL);
// If no repository is defined in the user/global settings,
// it means that we have "old" settings (as those are new in 4.0)
// so add central to the computed settings for backward compatibility.
if (userSettings.getRepositories().isEmpty()
&& userSettings.getPluginRepositories().isEmpty()) {
Repository central = new Repository();
central.setId("central");
central.setName("Central Repository");
central.setUrl("https://repo.maven.apache.org/maven2");
RepositoryPolicy disabledPolicy = new RepositoryPolicy();
disabledPolicy.setEnabled(false);
central.setSnapshots(disabledPolicy);
userSettings.getRepositories().add(central);
central = central.clone();
RepositoryPolicy updateNeverPolicy = new RepositoryPolicy();
disabledPolicy.setUpdatePolicy("never");
central.setReleases(updateNeverPolicy);
userSettings.getPluginRepositories().add(central);
return new DefaultSettingsBuildingResult(
new Settings(result.getEffectiveSettings()), convert(result.getProblems()));
} catch (SettingsBuilderException e) {
throw new SettingsBuildingException(convert(e.getProblems()));
}
problems.setSource("");
// for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble
String localRepository = userSettings.getLocalRepository();
if (localRepository != null && !localRepository.isEmpty()) {
File file = new File(localRepository);
if (!file.isAbsolute() && file.getPath().startsWith(File.separator)) {
userSettings.setLocalRepository(file.getAbsolutePath());
}
}
if (hasErrors(problems.getProblems())) {
throw new SettingsBuildingException(problems.getProblems());
}
return new DefaultSettingsBuildingResult(userSettings, problems.getProblems());
}
private boolean hasErrors(List<SettingsProblem> problems) {
if (problems != null) {
for (SettingsProblem problem : problems) {
if (SettingsProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
return true;
private org.apache.maven.api.services.Source toSource(File file, Source source) {
if (file != null && file.exists()) {
return org.apache.maven.api.services.Source.fromPath(file.toPath());
} else if (source instanceof FileSource fs) {
return org.apache.maven.api.services.Source.fromPath(fs.getPath());
} else if (source != null) {
return new org.apache.maven.api.services.Source() {
@Override
public Path getPath() {
return null;
}
}
}
return false;
@Override
public InputStream openStream() throws IOException {
return source.getInputStream();
}
@Override
public String getLocation() {
return source.getLocation();
}
@Override
public org.apache.maven.api.services.Source resolve(String relative) {
return null;
}
};
} else {
return null;
}
}
private Source getSettingsSource(File settingsFile, Source settingsSource) {
if (settingsSource != null) {
return settingsSource;
} else if (settingsFile != null && settingsFile.exists()) {
return new FileSource(settingsFile);
}
return null;
private List<SettingsProblem> convert(List<BuilderProblem> problems) {
return problems.stream().map(this::convert).toList();
}
private Settings readSettings(
Source settingsSource,
boolean isProjectSettings,
SettingsBuildingRequest request,
DefaultSettingsProblemCollector problems) {
if (settingsSource == null) {
return new Settings();
}
problems.setSource(settingsSource.getLocation());
Settings settings;
try {
Map<String, Object> options = new HashMap<>();
options.put(SettingsReader.IS_STRICT, Boolean.TRUE);
options.put(InputSource.class.getName(), new InputSource(settingsSource.getLocation()));
try {
settings = settingsReader.read(settingsSource.getInputStream(), options);
} catch (SettingsParseException e) {
options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.FALSE);
settings = settingsReader.read(settingsSource.getInputStream(), options);
problems.add(
SettingsProblem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
} catch (SettingsParseException e) {
problems.add(
SettingsProblem.Severity.FATAL,
"Non-parseable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
e.getLineNumber(),
e.getColumnNumber(),
e);
return new Settings();
} catch (IOException e) {
problems.add(
SettingsProblem.Severity.FATAL,
"Non-readable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
-1,
-1,
e);
return new Settings();
}
settings = interpolate(settings, request, problems);
settingsValidator.validate(settings, isProjectSettings, problems);
if (isProjectSettings) {
settings.setLocalRepository(null);
settings.setInteractiveMode(true);
settings.setOffline(false);
settings.setProxies(Collections.emptyList());
settings.setUsePluginRegistry(false);
for (Server server : settings.getServers()) {
server.setUsername(null);
server.setPassword(null);
server.setPrivateKey(null);
server.setPassword(null);
server.setFilePermissions(null);
server.setDirectoryPermissions(null);
}
}
return settings;
}
private Settings interpolate(
Settings settings, SettingsBuildingRequest request, SettingsProblemCollector problems) {
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
interpolator.addValueSource(new PropertiesBasedValueSource(request.getUserProperties()));
interpolator.addValueSource(new PropertiesBasedValueSource(request.getSystemProperties()));
try {
interpolator.addValueSource(new EnvarBasedValueSource());
} catch (IOException e) {
problems.add(
SettingsProblem.Severity.WARNING,
"Failed to use environment variables for interpolation: " + e.getMessage(),
-1,
-1,
e);
}
return new Settings(new SettingsTransformer(value -> {
try {
return value != null ? interpolator.interpolate(value) : null;
} catch (InterpolationException e) {
problems.add(
SettingsProblem.Severity.WARNING,
"Failed to interpolate settings: " + e.getMessage(),
-1,
-1,
e);
return value;
}
})
.visit(settings.getDelegate()));
private SettingsProblem convert(BuilderProblem problem) {
return new DefaultSettingsProblem(
problem.getMessage(),
SettingsProblem.Severity.valueOf(problem.getSeverity().name()),
problem.getSource(),
problem.getLineNumber(),
problem.getColumnNumber(),
problem.getException());
}
}

View File

@ -43,7 +43,7 @@ protected SettingsWriter newSettingsWriter() {
}
protected SettingsValidator newSettingsValidator() {
return new DefaultSettingsValidator();
return new DefaultSettingsValidator(new org.apache.maven.internal.impl.DefaultSettingsBuilder());
}
/**
@ -52,6 +52,8 @@ protected SettingsValidator newSettingsValidator() {
* @return The new settings builder instance, never {@code null}.
*/
public DefaultSettingsBuilder newInstance() {
return new DefaultSettingsBuilder(newSettingsReader(), newSettingsWriter(), newSettingsValidator());
return new DefaultSettingsBuilder(
new org.apache.maven.internal.impl.DefaultSettingsBuilder(),
new org.apache.maven.internal.impl.DefaultSettingsXmlFactory());
}
}

View File

@ -18,19 +18,15 @@
*/
package org.apache.maven.settings.validation;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Profile;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Repository;
import org.apache.maven.settings.Server;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.SettingsBuilder;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.SettingsProblem.Severity;
import org.apache.maven.settings.building.SettingsProblemCollector;
@ -44,7 +40,12 @@ public class DefaultSettingsValidator implements SettingsValidator {
private static final String ID = "[\\w.-]+";
private static final Pattern ID_REGEX = Pattern.compile(ID);
private static final String ILLEGAL_REPO_ID_CHARS = "\\/:\"<>|?*"; // ILLEGAL_FS_CHARS
private final SettingsBuilder settingsBuilder;
@Inject
public DefaultSettingsValidator(SettingsBuilder settingsBuilder) {
this.settingsBuilder = settingsBuilder;
}
@Override
public void validate(Settings settings, SettingsProblemCollector problems) {
@ -53,201 +54,9 @@ public void validate(Settings settings, SettingsProblemCollector problems) {
@Override
public void validate(Settings settings, boolean isProjectSettings, SettingsProblemCollector problems) {
if (isProjectSettings) {
String msgS = "is not supported on project settings.";
String msgP = "are not supported on project settings.";
if (settings.getLocalRepository() != null
&& !settings.getLocalRepository().isEmpty()) {
addViolation(problems, Severity.WARNING, "localRepository", null, msgS);
}
if (settings.getInteractiveMode() != null && !settings.getInteractiveMode()) {
addViolation(problems, Severity.WARNING, "interactiveMode", null, msgS);
}
if (settings.isOffline()) {
addViolation(problems, Severity.WARNING, "offline", null, msgS);
}
if (!settings.getProxies().isEmpty()) {
addViolation(problems, Severity.WARNING, "proxies", null, msgP);
}
if (settings.isUsePluginRegistry()) {
addViolation(problems, Severity.WARNING, "usePluginRegistry", null, msgS);
}
List<Server> servers = settings.getServers();
for (int i = 0; i < servers.size(); i++) {
Server server = servers.get(i);
String serverField = "servers.server[" + i + "]";
validateStringEmpty(problems, serverField + ".username", server.getUsername(), msgS);
validateStringEmpty(problems, serverField + ".password", server.getPassword(), msgS);
validateStringEmpty(problems, serverField + ".privateKey", server.getPrivateKey(), msgS);
validateStringEmpty(problems, serverField + ".passphrase", server.getPassphrase(), msgS);
validateStringEmpty(problems, serverField + ".filePermissions", server.getFilePermissions(), msgS);
validateStringEmpty(
problems, serverField + ".directoryPermissions", server.getDirectoryPermissions(), msgS);
}
}
if (settings.isUsePluginRegistry()) {
addViolation(problems, Severity.WARNING, "usePluginRegistry", null, "is deprecated and has no effect.");
}
List<String> pluginGroups = settings.getPluginGroups();
if (pluginGroups != null) {
for (int i = 0; i < pluginGroups.size(); i++) {
String pluginGroup = pluginGroups.get(i);
validateStringNotEmpty(problems, "pluginGroups.pluginGroup[" + i + "]", pluginGroup, null);
if (!ID_REGEX.matcher(pluginGroup).matches()) {
addViolation(
problems,
Severity.ERROR,
"pluginGroups.pluginGroup[" + i + "]",
null,
"must denote a valid group id and match the pattern " + ID);
}
}
}
List<Server> servers = settings.getServers();
if (servers != null) {
Set<String> serverIds = new HashSet<>();
for (int i = 0; i < servers.size(); i++) {
Server server = servers.get(i);
validateStringNotEmpty(problems, "servers.server[" + i + "].id", server.getId(), null);
if (!serverIds.add(server.getId())) {
addViolation(
problems,
Severity.WARNING,
"servers.server.id",
null,
"must be unique but found duplicate server with id " + server.getId());
}
}
}
List<Mirror> mirrors = settings.getMirrors();
if (mirrors != null) {
for (Mirror mirror : mirrors) {
validateStringNotEmpty(problems, "mirrors.mirror.id", mirror.getId(), mirror.getUrl());
validateBannedCharacters(
problems, "mirrors.mirror.id", Severity.WARNING, mirror.getId(), null, ILLEGAL_REPO_ID_CHARS);
if ("local".equals(mirror.getId())) {
addViolation(
problems,
Severity.WARNING,
"mirrors.mirror.id",
null,
"must not be 'local'"
+ ", this identifier is reserved for the local repository"
+ ", using it for other repositories will corrupt your repository metadata.");
}
validateStringNotEmpty(problems, "mirrors.mirror.url", mirror.getUrl(), mirror.getId());
validateStringNotEmpty(problems, "mirrors.mirror.mirrorOf", mirror.getMirrorOf(), mirror.getId());
}
}
List<Profile> profiles = settings.getProfiles();
if (profiles != null) {
Set<String> profileIds = new HashSet<>();
for (Profile profile : profiles) {
if (!profileIds.add(profile.getId())) {
addViolation(
problems,
Severity.WARNING,
"profiles.profile.id",
null,
"must be unique but found duplicate profile with id " + profile.getId());
}
String prefix = "profiles.profile[" + profile.getId() + "].";
validateRepositories(problems, profile.getRepositories(), prefix + "repositories.repository");
validateRepositories(
problems, profile.getPluginRepositories(), prefix + "pluginRepositories.pluginRepository");
}
}
List<Proxy> proxies = settings.getProxies();
if (proxies != null) {
Set<String> proxyIds = new HashSet<>();
for (Proxy proxy : proxies) {
if (!proxyIds.add(proxy.getId())) {
addViolation(
problems,
Severity.WARNING,
"proxies.proxy.id",
null,
"must be unique but found duplicate proxy with id " + proxy.getId());
}
validateStringNotEmpty(problems, "proxies.proxy.host", proxy.getHost(), proxy.getId());
try {
Integer.parseInt(proxy.getPortString());
} catch (NumberFormatException e) {
addViolation(
problems,
Severity.ERROR,
"proxies.proxy[" + proxy.getId() + "].port",
null,
"must be a valid integer but found '" + proxy.getPortString() + "'");
}
}
}
}
private void validateRepositories(SettingsProblemCollector problems, List<Repository> repositories, String prefix) {
Set<String> repoIds = new HashSet<>();
for (Repository repository : repositories) {
validateStringNotEmpty(problems, prefix + ".id", repository.getId(), repository.getUrl());
validateBannedCharacters(
problems, prefix + ".id", Severity.WARNING, repository.getId(), null, ILLEGAL_REPO_ID_CHARS);
if ("local".equals(repository.getId())) {
addViolation(
problems,
Severity.WARNING,
prefix + ".id",
null,
"must not be 'local'"
+ ", this identifier is reserved for the local repository"
+ ", using it for other repositories will corrupt your repository metadata.");
}
if (!repoIds.add(repository.getId())) {
addViolation(
problems,
Severity.WARNING,
prefix + ".id",
null,
"must be unique but found duplicate repository with id " + repository.getId());
}
validateStringNotEmpty(problems, prefix + ".url", repository.getUrl(), repository.getId());
if ("legacy".equals(repository.getLayout())) {
addViolation(
problems,
Severity.WARNING,
prefix + ".layout",
repository.getId(),
"uses the unsupported value 'legacy', artifact resolution might fail.");
}
List<BuilderProblem> list = settingsBuilder.validate(settings.getDelegate(), isProjectSettings);
for (BuilderProblem problem : list) {
addViolation(problems, Severity.valueOf(problem.getSeverity().name()), problem.getMessage());
}
}
@ -255,101 +64,7 @@ private void validateRepositories(SettingsProblemCollector problems, List<Reposi
// Field validation
// ----------------------------------------------------------------------
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string.length == null</code>
* <li><code>string.length == 0</code>
* </ul>
*/
private static boolean validateStringEmpty(
SettingsProblemCollector problems, String fieldName, String string, String message) {
if (string == null || string.length() == 0) {
return true;
}
addViolation(problems, Severity.WARNING, fieldName, null, message);
return false;
}
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string.length != null</code>
* <li><code>string.length > 0</code>
* </ul>
*/
private static boolean validateStringNotEmpty(
SettingsProblemCollector problems, String fieldName, String string, String sourceHint) {
if (!validateNotNull(problems, fieldName, string, sourceHint)) {
return false;
}
if (!string.isEmpty()) {
return true;
}
addViolation(problems, Severity.ERROR, fieldName, sourceHint, "is missing");
return false;
}
/**
* Asserts:
* <p/>
* <ul>
* <li><code>string != null</code>
* </ul>
*/
private static boolean validateNotNull(
SettingsProblemCollector problems, String fieldName, Object object, String sourceHint) {
if (object != null) {
return true;
}
addViolation(problems, Severity.ERROR, fieldName, sourceHint, "is missing");
return false;
}
private static boolean validateBannedCharacters(
SettingsProblemCollector problems,
String fieldName,
Severity severity,
String string,
String sourceHint,
String banned) {
if (string != null) {
for (int i = string.length() - 1; i >= 0; i--) {
if (banned.indexOf(string.charAt(i)) >= 0) {
addViolation(
problems,
severity,
fieldName,
sourceHint,
"must not contain any of these characters " + banned + " but found " + string.charAt(i));
return false;
}
}
}
return true;
}
private static void addViolation(
SettingsProblemCollector problems, Severity severity, String fieldName, String sourceHint, String message) {
StringBuilder buffer = new StringBuilder(256);
buffer.append('\'').append(fieldName).append('\'');
if (sourceHint != null) {
buffer.append(" for ").append(sourceHint);
}
buffer.append(' ').append(message);
problems.add(severity, buffer.toString(), -1, -1, null);
private static void addViolation(SettingsProblemCollector problems, Severity severity, String message) {
problems.add(severity, message, -1, -1, null);
}
}

View File

@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.internal.impl.DefaultSettingsBuilder;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Profile;
import org.apache.maven.settings.Proxy;
@ -44,7 +45,7 @@ class DefaultSettingsValidatorTest {
@BeforeEach
void setUp() throws Exception {
validator = new DefaultSettingsValidator();
validator = new DefaultSettingsValidator(new DefaultSettingsBuilder());
}
@AfterEach

View File

@ -31,6 +31,10 @@ under the License.
<description>The effective toolchain builder.</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-toolchain-model</artifactId>
@ -53,6 +57,11 @@ under the License.
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -23,25 +23,27 @@
import javax.inject.Singleton;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collections;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.api.Session;
import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.ToolchainsBuilderException;
import org.apache.maven.api.services.ToolchainsBuilderRequest;
import org.apache.maven.api.services.ToolchainsBuilderResult;
import org.apache.maven.api.services.xml.ToolchainsXmlFactory;
import org.apache.maven.building.FileSource;
import org.apache.maven.building.Problem;
import org.apache.maven.building.ProblemCollector;
import org.apache.maven.building.ProblemCollectorFactory;
import org.apache.maven.building.Source;
import org.apache.maven.toolchain.io.ToolchainsParseException;
import org.apache.maven.toolchain.io.ToolchainsReader;
import org.apache.maven.toolchain.io.ToolchainsWriter;
import org.apache.maven.toolchain.merge.MavenToolchainMerger;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.model.TrackableBase;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
/**
*
@ -50,143 +52,88 @@
@Named
@Singleton
public class DefaultToolchainsBuilder implements ToolchainsBuilder {
private final MavenToolchainMerger toolchainsMerger = new MavenToolchainMerger();
private final ToolchainsWriter toolchainsWriter;
private final ToolchainsReader toolchainsReader;
private final org.apache.maven.api.services.ToolchainsBuilder builder;
private final ToolchainsXmlFactory toolchainsXmlFactory;
@Inject
public DefaultToolchainsBuilder(ToolchainsWriter toolchainsWriter, ToolchainsReader toolchainsReader) {
this.toolchainsWriter = toolchainsWriter;
this.toolchainsReader = toolchainsReader;
public DefaultToolchainsBuilder(
org.apache.maven.api.services.ToolchainsBuilder builder, ToolchainsXmlFactory toolchainsXmlFactory) {
this.builder = builder;
this.toolchainsXmlFactory = toolchainsXmlFactory;
}
@Override
public ToolchainsBuildingResult build(ToolchainsBuildingRequest request) throws ToolchainsBuildingException {
ProblemCollector problems = ProblemCollectorFactory.newInstance(null);
try {
ToolchainsBuilderResult result = builder.build(ToolchainsBuilderRequest.builder()
.session((Session) java.lang.reflect.Proxy.newProxyInstance(
Session.class.getClassLoader(),
new Class[] {Session.class},
(Object proxy, Method method, Object[] args) -> {
if ("getSystemProperties".equals(method.getName())) {
Map<String, String> properties = new HashMap<>();
Properties env = OperatingSystemUtils.getSystemEnvVars();
env.stringPropertyNames()
.forEach(k -> properties.put("env." + k, env.getProperty(k)));
return properties;
} else if ("getUserProperties".equals(method.getName())) {
return Map.of();
} else if ("getService".equals(method.getName())) {
if (args[0] == ToolchainsXmlFactory.class) {
return toolchainsXmlFactory;
}
}
return null;
}))
.globalToolchainsSource(convert(request.getGlobalToolchainsSource()))
.userToolchainsSource(convert(request.getUserToolchainsSource()))
.build());
PersistedToolchains globalToolchains = readToolchains(request.getGlobalToolchainsSource(), request, problems);
PersistedToolchains userToolchains = readToolchains(request.getUserToolchainsSource(), request, problems);
toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL);
problems.setSource("");
userToolchains = interpolate(userToolchains, problems);
if (hasErrors(problems.getProblems())) {
throw new ToolchainsBuildingException(problems.getProblems());
return new DefaultToolchainsBuildingResult(
new PersistedToolchains(result.getEffectiveToolchains()), convert(result.getProblems()));
} catch (ToolchainsBuilderException e) {
throw new ToolchainsBuildingException(convert(e.getProblems()));
}
return new DefaultToolchainsBuildingResult(userToolchains, problems.getProblems());
}
private PersistedToolchains interpolate(PersistedToolchains toolchains, ProblemCollector problems) {
StringWriter stringWriter = new StringWriter(1024 * 4);
try {
toolchainsWriter.write(stringWriter, null, toolchains);
} catch (IOException e) {
throw new IllegalStateException("Failed to serialize toolchains to memory", e);
}
String serializedToolchains = stringWriter.toString();
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
try {
interpolator.addValueSource(new EnvarBasedValueSource());
} catch (IOException e) {
problems.add(
Problem.Severity.WARNING,
"Failed to use environment variables for interpolation: " + e.getMessage(),
-1,
-1,
e);
}
interpolator.addPostProcessor((expression, value) -> {
if (value != null) {
// we're going to parse this back in as XML so we need to escape XML markup
value = value.toString()
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;");
return value;
}
return null;
});
try {
serializedToolchains = interpolator.interpolate(serializedToolchains);
} catch (InterpolationException e) {
problems.add(Problem.Severity.ERROR, "Failed to interpolate toolchains: " + e.getMessage(), -1, -1, e);
return toolchains;
}
PersistedToolchains result;
try {
Map<String, ?> options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.FALSE);
result = toolchainsReader.read(new StringReader(serializedToolchains), options);
} catch (IOException e) {
problems.add(Problem.Severity.ERROR, "Failed to interpolate toolchains: " + e.getMessage(), -1, -1, e);
return toolchains;
}
return result;
}
private PersistedToolchains readToolchains(
Source toolchainsSource, ToolchainsBuildingRequest request, ProblemCollector problems) {
if (toolchainsSource == null) {
return new PersistedToolchains();
}
PersistedToolchains toolchains;
try {
Map<String, ?> options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.TRUE);
try {
toolchains = toolchainsReader.read(toolchainsSource.getInputStream(), options);
} catch (ToolchainsParseException e) {
options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.FALSE);
toolchains = toolchainsReader.read(toolchainsSource.getInputStream(), options);
problems.add(Problem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
} catch (ToolchainsParseException e) {
problems.add(
Problem.Severity.FATAL,
"Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
e.getLineNumber(),
e.getColumnNumber(),
e);
return new PersistedToolchains();
} catch (IOException e) {
problems.add(
Problem.Severity.FATAL,
"Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
-1,
-1,
e);
return new PersistedToolchains();
}
return toolchains;
}
private boolean hasErrors(List<Problem> problems) {
if (problems != null) {
for (Problem problem : problems) {
if (Problem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
return true;
private Source convert(org.apache.maven.building.Source source) {
if (source instanceof FileSource fs) {
return Source.fromPath(fs.getPath());
} else if (source != null) {
return new Source() {
@Override
public Path getPath() {
return null;
}
}
}
return false;
@Override
public InputStream openStream() throws IOException {
return source.getInputStream();
}
@Override
public String getLocation() {
return source.getLocation();
}
@Override
public Source resolve(String relative) {
return null;
}
};
} else {
return null;
}
}
private List<Problem> convert(List<BuilderProblem> problems) {
ProblemCollector collector = ProblemCollectorFactory.newInstance(null);
problems.forEach(p -> collector.add(
Problem.Severity.valueOf(p.getSeverity().name()),
p.getMessage(),
p.getLineNumber(),
p.getColumnNumber(),
p.getException()));
return collector.getProblems();
}
}

View File

@ -18,54 +18,61 @@
*/
package org.apache.maven.toolchain.building;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.building.Source;
import org.apache.maven.building.StringSource;
import org.apache.maven.toolchain.io.DefaultToolchainsReader;
import org.apache.maven.toolchain.io.DefaultToolchainsWriter;
import org.apache.maven.toolchain.io.ToolchainsParseException;
import org.apache.maven.internal.impl.DefaultToolchainsXmlFactory;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.model.ToolchainModel;
import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.apache.maven.internal.impl.StaxLocation.getLocation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class DefaultToolchainsBuilderTest {
private static final String LS = System.lineSeparator();
@Spy
private DefaultToolchainsReader toolchainsReader;
@Spy
private DefaultToolchainsWriter toolchainsWriter;
private DefaultToolchainsXmlFactory toolchainsXmlFactory;
@InjectMocks
private DefaultToolchainsBuilder toolchainBuilder;
@BeforeEach
void onSetup() {
MockitoAnnotations.initMocks(this);
// MockitoAnnotations.openMocks(this);
Map<String, String> envVarMap = new HashMap<>();
envVarMap.put("testKey", "testValue");
envVarMap.put("testSpecialCharactersKey", "<test&Value>");
OperatingSystemUtils.setEnvVarSource(new TestEnvVarSource(envVarMap));
toolchainBuilder = new DefaultToolchainsBuilder(
new org.apache.maven.internal.impl.DefaultToolchainsBuilder(), toolchainsXmlFactory);
}
@Test
@ -79,19 +86,17 @@ void testBuildEmptyRequest() throws Exception {
@Test
void testBuildRequestWithUserToolchains() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "user_value");
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains userResult = new PersistedToolchains();
userResult.setToolchains(Collections.singletonList(toolchain));
doReturn(userResult)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
String xml = new DefaultToolchainsXmlFactory().toXmlString(persistedToolchains.getDelegate());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(xml));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
assertNotNull(result.getEffectiveToolchains());
@ -111,19 +116,17 @@ void testBuildRequestWithUserToolchains() throws Exception {
@Test
void testBuildRequestWithGlobalToolchains() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "global_value");
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains globalResult = new PersistedToolchains();
globalResult.setToolchains(Collections.singletonList(toolchain));
doReturn(globalResult)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
String xml = new DefaultToolchainsXmlFactory().toXmlString(persistedToolchains.getDelegate());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource(xml));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
assertNotNull(result.getEffectiveToolchains());
@ -143,10 +146,6 @@ void testBuildRequestWithGlobalToolchains() throws Exception {
@Test
void testBuildRequestWithBothToolchains() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource(""));
request.setUserToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "user_value");
ToolchainModel toolchain = new ToolchainModel();
@ -163,10 +162,11 @@ void testBuildRequestWithBothToolchains() throws Exception {
PersistedToolchains globalResult = new PersistedToolchains();
globalResult.setToolchains(Collections.singletonList(toolchain));
doReturn(globalResult)
.doReturn(userResult)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(
new StringSource(new DefaultToolchainsXmlFactory().toXmlString(userResult.getDelegate())));
request.setGlobalToolchainsSource(
new StringSource(new DefaultToolchainsXmlFactory().toXmlString(globalResult.getDelegate())));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
assertNotNull(result.getEffectiveToolchains());
@ -195,12 +195,15 @@ void testBuildRequestWithBothToolchains() throws Exception {
@Test
void testStrictToolchainsParseException() throws Exception {
Location loc = mock(Location.class);
when(loc.getLineNumber()).thenReturn(4);
when(loc.getColumnNumber()).thenReturn(2);
XMLStreamException parseException = new XMLStreamException("MESSAGE", loc);
doThrow(new XmlReaderException("MESSAGE", getLocation(parseException), parseException))
.when(toolchainsXmlFactory)
.read(any(XmlReaderRequest.class));
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource(""));
ToolchainsParseException parseException = new ToolchainsParseException("MESSAGE", 4, 2);
doThrow(parseException)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
try {
toolchainBuilder.build(request);
@ -214,12 +217,13 @@ void testStrictToolchainsParseException() throws Exception {
@Test
void testIOException() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource("", "LOCATION"));
Source src = mock(Source.class);
IOException ioException = new IOException("MESSAGE");
doThrow(ioException)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
doThrow(ioException).when(src).getInputStream();
doReturn("LOCATION").when(src).getLocation();
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(src);
try {
toolchainBuilder.build(request);
@ -233,9 +237,6 @@ void testIOException() throws Exception {
@Test
void testEnvironmentVariablesAreInterpolated() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "${env.testKey}");
Xpp3Dom configurationChild = new Xpp3Dom("jdkHome");
@ -249,9 +250,9 @@ void testEnvironmentVariablesAreInterpolated() throws Exception {
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
String xml = new DefaultToolchainsXmlFactory().toXmlString(persistedToolchains.getDelegate());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(xml));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
String interpolatedValue = "testValue";
@ -272,9 +273,6 @@ void testEnvironmentVariablesAreInterpolated() throws Exception {
@Test
void testNonExistingEnvironmentVariablesAreNotInterpolated() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "${env.testNonExistingKey}");
ToolchainModel toolchain = new ToolchainModel();
@ -283,9 +281,9 @@ void testNonExistingEnvironmentVariablesAreNotInterpolated() throws Exception {
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
String xml = new DefaultToolchainsXmlFactory().toXmlString(persistedToolchains.getDelegate());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(xml));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
assertEquals(
@ -301,9 +299,6 @@ void testNonExistingEnvironmentVariablesAreNotInterpolated() throws Exception {
@Test
void testEnvironmentVariablesWithSpecialCharactersAreInterpolated() throws Exception {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Properties props = new Properties();
props.put("key", "${env.testSpecialCharactersKey}");
ToolchainModel toolchain = new ToolchainModel();
@ -312,9 +307,9 @@ void testEnvironmentVariablesWithSpecialCharactersAreInterpolated() throws Excep
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
String xml = new DefaultToolchainsXmlFactory().toXmlString(persistedToolchains.getDelegate());
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(xml));
ToolchainsBuildingResult result = toolchainBuilder.build(request);
String interpolatedValue = "<test&Value>";

Some files were not shown because too many files have changed in this diff Show More