[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 @@ public interface SettingsBuilder extends Service {
@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 @@ import org.apache.maven.api.annotations.Experimental;
*/
@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 @@ public interface SettingsBuilderRequest {
@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 @@ public interface SettingsBuilderRequest {
@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 interface SettingsBuilderRequest {
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 interface SettingsBuilderRequest {
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.Experimental;
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 @@ import org.apache.maven.api.annotations.Experimental;
*/
@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 @@ public interface ToolchainsBuilderRequest {
@NotThreadSafe
class ToolchainsBuilderRequestBuilder {
Session session;
Path globalToolchainsPath;
Source globalToolchainsSource;
Path userToolchainsPath;
Source userToolchainsSource;
public ToolchainsBuilderRequestBuilder session(Session session) {
@ -108,21 +97,11 @@ public interface ToolchainsBuilderRequest {
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 interface ToolchainsBuilderRequest {
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 @@ import org.apache.maven.api.services.MavenException;
@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 @@ import org.apache.maven.api.services.MavenException;
@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.Collection;
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 abstract class AbstractSession implements InternalSession {
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 abstract class AbstractSession implements InternalSession {
}
}
@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 java.util.Map;
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 @@ package org.apache.maven.internal.impl;
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.Files;
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.api.services.xml.XmlWriterRequest;
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 class DefaultModelXmlFactory implements ModelXmlFactory {
}
}
} 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 class DefaultModelXmlFactory implements ModelXmlFactory {
}
}
} 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.api.settings.Settings;
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 class DefaultSettingsXmlFactory implements SettingsXmlFactory {
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 class DefaultSettingsXmlFactory implements SettingsXmlFactory {
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.io.Writer;
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.api.toolchain.PersistedToolchains;
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 class DefaultToolchainsXmlFactory implements ToolchainsXmlFactory {
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 class DefaultToolchainsXmlFactory implements ToolchainsXmlFactory {
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.Files;
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 java.util.stream.Collectors;
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.Dependency;
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 @@ public interface InternalSession extends 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 @@ public interface InternalSession extends Session {
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 @@ public final class SettingsUtilsV4 {
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.execution.ProjectDependencyGraph;
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 @@ public class DefaultMaven implements Maven {
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 java.util.stream.Collectors;
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.Mirror;
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 @@ import static org.apache.maven.internal.impl.Utils.nonNull;
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.api.Session;
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.codehaus.plexus.util.xml.Xpp3Dom;
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.api.services.xml.*;
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 class DefaultPluginXmlFactory implements PluginXmlFactory {
}
}
} 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 class DefaultPluginXmlFactory implements PluginXmlFactory {
}
}
} 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 @@ import static org.apache.maven.internal.impl.Utils.nonNull;
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 class DefaultProjectBuilder implements ProjectBuilder {
@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 @@ import static org.apache.maven.internal.impl.Utils.nonNull;
@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 class DefaultProjectManager implements ProjectManager {
@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 @@ package org.apache.maven.internal.impl;
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.execution.MavenSession;
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 class DefaultSession extends AbstractSession {
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 class DefaultSession extends AbstractSession {
}
}
@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 class DefaultSession extends AbstractSession {
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 class 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 class DefaultToolchainManager implements ToolchainManager {
@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 class DefaultToolchainManager implements ToolchainManager {
@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 class DefaultToolchainManager implements ToolchainManager {
@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 class DefaultToolchainManager implements ToolchainManager {
@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 class EventSpyImpl implements EventSpy {
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.MojoExecutionListener;
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 class DefaultBuildPluginManager implements BuildPluginManager {
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.MojoExecutionScope;
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 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
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 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
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.InvalidArtifactRTException;
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 @@ public class DefaultProjectBuilder implements ProjectBuilder {
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 java.util.zip.ZipEntry;
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 class ExtensionDescriptorBuilder {
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 com.google.inject.AbstractModule;
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 @@ public class SessionScopeModule extends AbstractModule {
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.Path;
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 @@ class DefaultBeanConfiguratorPathTest {
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.File;
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 @@ class DefaultBeanConfiguratorTest {
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 @@ class TestApi {
.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 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
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.ActivationProperty;
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 abstract class Binding<T> {
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 @@ public class InjectorImpl implements Injector {
}
@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 java.util.Optional;
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 @@ public class PluginDescriptorBuilder {
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 class PluginDescriptorBuilder {
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 class PluginDescriptorBuilder {
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 javax.inject.Singleton;
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 @@ import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
@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 @@ public class DefaultSettingsBuilderFactory {
}
protected SettingsValidator newSettingsValidator() {
return new DefaultSettingsValidator();
return new DefaultSettingsValidator(new org.apache.maven.internal.impl.DefaultSettingsBuilder());
}
/**
@ -52,6 +52,8 @@ public class DefaultSettingsBuilderFactory {
* @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 class DefaultSettingsValidator implements SettingsValidator {
@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 @@ public class DefaultSettingsValidator implements SettingsValidator {
// 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 @@ package org.apache.maven.settings.validation;
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.Named;
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 @@ import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
@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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
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 @@ class DefaultToolchainsBuilderTest {
@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 @@ class DefaultToolchainsBuilderTest {
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