From 1151377f0f832ed4ab90febe015257d08e194a4f Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Sun, 9 Oct 2022 20:35:47 +0200 Subject: [PATCH] [MNG-7580] Introduce new SettingsBuilder and ToolchainsBuilder services --- ...uilderProblem.java => BuilderProblem.java} | 41 +++- .../maven/api/services/ProjectBuilder.java | 4 +- .../api/services/ProjectBuilderRequest.java | 14 +- .../api/services/ProjectBuilderResult.java | 2 +- .../maven/api/services/SettingsBuilder.java | 71 ++++++ ...ity.java => SettingsBuilderException.java} | 20 +- .../api/services/SettingsBuilderRequest.java | 204 ++++++++++++++++++ .../api/services/SettingsBuilderResult.java | 48 +++++ ...{ProjectBuilderSource.java => Source.java} | 2 +- .../services/ToolchainManagerException.java | 4 +- .../maven/api/services/ToolchainsBuilder.java | 42 ++++ .../services/ToolchainsBuilderException.java | 43 ++++ .../services/ToolchainsBuilderRequest.java | 196 +++++++++++++++++ .../api/services/ToolchainsBuilderResult.java | 47 ++++ .../internal/impl/DefaultProjectBuilder.java | 17 +- .../internal/impl/DefaultSettingsBuilder.java | 188 ++++++++++++++++ .../impl/DefaultToolchainsBuilder.java | 187 ++++++++++++++++ .../apache/maven/internal/impl/TestApi.java | 7 + 18 files changed, 1099 insertions(+), 38 deletions(-) rename api/maven-api-core/src/main/java/org/apache/maven/api/services/{ProjectBuilderProblem.java => BuilderProblem.java} (70%) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilder.java rename api/maven-api-core/src/main/java/org/apache/maven/api/services/{ProjectBuilderProblemSeverity.java => SettingsBuilderException.java} (68%) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java rename api/maven-api-core/src/main/java/org/apache/maven/api/services/{ProjectBuilderSource.java => Source.java} (96%) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilder.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsBuilder.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsBuilder.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BuilderProblem.java similarity index 70% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/BuilderProblem.java index fef6ceae0dd4..d1bcf501b50f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BuilderProblem.java @@ -20,6 +20,9 @@ */ import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; /** * Describes a problem that was encountered during project building. A problem can either be an exception that was @@ -28,7 +31,8 @@ * @since 4.0 */ @Experimental -public interface ProjectBuilderProblem +@Immutable +public interface BuilderProblem { /** @@ -37,15 +41,16 @@ public interface ProjectBuilderProblem * track the problem back to its origin. A concrete example for such a source hint can be the file path or URL from * which the settings were read. * - * @return The hint about the source of the problem or an empty string if unknown, never {@code null}. + * @return the hint about the source of the problem or an empty string if unknown, never {@code null} */ + @Nonnull String getSource(); /** * Gets the one-based index of the line containing the problem. The line number should refer to some text file that * is given by {@link #getSource()}. * - * @return The one-based index of the line containing the problem or a non-positive value if unknown. + * @return the one-based index of the line containing the problem or a non-positive value if unknown */ int getLineNumber(); @@ -53,7 +58,7 @@ public interface ProjectBuilderProblem * Gets the one-based index of the column containing the problem. The column number should refer to some text file * that is given by {@link #getSource()}. * - * @return The one-based index of the column containing the problem or non-positive value if unknown. + * @return the one-based index of the column containing the problem or non-positive value if unknown */ int getColumnNumber(); @@ -62,29 +67,47 @@ public interface ProjectBuilderProblem * {@link #getSource()}, {@link #getLineNumber()} and {@link #getColumnNumber()}. The exact syntax of the returned * value is undefined. * - * @return The location of the problem, never {@code null}. + * @return the location of the problem, never {@code null} */ + @Nonnull String getLocation(); /** * Gets the exception that caused this problem (if any). * - * @return The exception that caused this problem or {@code null} if not applicable. + * @return the exception that caused this problem or {@code null} if not applicable */ + @Nullable Exception getException(); /** * Gets the message that describes this problem. * - * @return The message describing this problem, never {@code null}. + * @return the message describing this problem, never {@code null} */ + @Nonnull String getMessage(); /** * Gets the severity level of this problem. * - * @return The severity level of this problem, never {@code null}. + * @return the severity level of this problem, never {@code null} */ - ProjectBuilderProblemSeverity getSeverity(); + @Nonnull + Severity getSeverity(); + /** + * The different severity levels for a problem, in decreasing order. + * + * @since 4.0 + */ + @Experimental + enum Severity + { + + FATAL, // + ERROR, // + WARNING // + + } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index 85b9efeeea58..303cdb342b52 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -51,13 +51,13 @@ public interface ProjectBuilder extends Service * Creates a {@link org.apache.maven.api.Project} from a POM file. * * @param session the {@link Session}, must not be {@code null} - * @param source the {@link ProjectBuilderSource}, must not be {@code null} + * @param source The {@link Source}, must not be {@code null} * @throws ProjectBuilderException if the project cannot be created * @throws IllegalArgumentException if an argument is {@code null} or invalid * @see #build(ProjectBuilderRequest) */ @Nonnull - default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Source source ) { return build( ProjectBuilderRequest.build( session, source ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index 2e259091a3ae..174bcadbd967 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -52,7 +52,7 @@ public interface ProjectBuilderRequest Optional getPath(); @Nonnull - Optional getSource(); + Optional getSource(); @Nonnull Optional getArtifact(); @@ -69,7 +69,7 @@ public interface ProjectBuilderRequest boolean isResolveDependencies(); @Nonnull - static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Source source ) { return builder() .session( nonNull( session, "session cannot be null" ) ) @@ -115,7 +115,7 @@ class ProjectBuilderRequestBuilder { Session session; Path path; - ProjectBuilderSource source; + Source source; Artifact artifact; ArtifactCoordinate coordinate; boolean allowStubModel; @@ -139,7 +139,7 @@ public ProjectBuilderRequestBuilder path( Path path ) return this; } - public ProjectBuilderRequestBuilder source( ProjectBuilderSource source ) + public ProjectBuilderRequestBuilder source( Source source ) { this.source = source; return this; @@ -179,7 +179,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest implements ProjectBuilderRequest { private final Path path; - private final ProjectBuilderSource source; + private final Source source; private final Artifact artifact; private final ArtifactCoordinate coordinate; private final boolean allowStubModel; @@ -190,7 +190,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest @SuppressWarnings( "checkstyle:ParameterNumber" ) DefaultProjectBuilderRequest( @Nonnull Session session, @Nullable Path path, - @Nullable ProjectBuilderSource source, + @Nullable Source source, @Nullable Artifact artifact, @Nullable ArtifactCoordinate coordinate, boolean allowStubModel, @@ -218,7 +218,7 @@ public Optional getPath() @Nonnull @Override - public Optional getSource() + public Optional getSource() { return Optional.ofNullable( source ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java index 7664da7a1b6c..0019b66aacda 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -70,7 +70,7 @@ public interface ProjectBuilderResult * @return the problems that were encountered during the project building, can be empty but never {@code null} */ @Nonnull - Collection getProblems(); + Collection getProblems(); /** * Gets the result of the dependency resolution for the project. diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilder.java new file mode 100644 index 000000000000..624a74f91125 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilder.java @@ -0,0 +1,71 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Builds the effective settings from a user settings file and/or a global settings file. + */ +public interface SettingsBuilder extends Service +{ + + /** + * Builds the effective settings of the specified settings files. + * + * @param request the settings building request that holds the parameters, must not be {@code null} + * @return the result of the settings building, never {@code null} + * @throws SettingsBuilderException if the effective settings could not be built + */ + @Nonnull + SettingsBuilderResult build( @Nonnull SettingsBuilderRequest request ); + + /** + * Builds the effective settings of the specified settings sources. + * + * @return the result of the settings building, never {@code null} + * @throws SettingsBuilderException if the effective settings could not be built + */ + @Nonnull + default SettingsBuilderResult build( @Nonnull Session session, + @Nonnull Source globalSettingsSource, + @Nonnull Source userSettingsSource ) + { + return build( SettingsBuilderRequest.build( session, globalSettingsSource, userSettingsSource ) ); + } + + /** + * Builds the effective settings of the specified settings paths. + * + * @return the result of the settings building, never {@code null} + * @throws SettingsBuilderException if the effective settings could not be built + */ + @Nonnull + default SettingsBuilderResult build( @Nonnull Session session, + @Nonnull Path globalSettingsPath, + @Nonnull Path userSettingsPath ) + { + return build( SettingsBuilderRequest.build( session, globalSettingsPath, userSettingsPath ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java similarity index 68% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java index 6af0257098fc..665b9086eb59 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java @@ -9,7 +9,7 @@ * "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 + * 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 @@ -22,16 +22,22 @@ import org.apache.maven.api.annotations.Experimental; /** - * The different severity levels for a problem, in decreasing order. + * The Exception class throw by the {@link SettingsBuilder}. * * @since 4.0 */ @Experimental -public enum ProjectBuilderProblemSeverity +public class SettingsBuilderException + extends MavenException { + /** + * @param message the message to give + * @param e the {@link Exception} + */ + public SettingsBuilderException( String message, Exception e ) + { + super( message, e ); + } - FATAL, // - ERROR, // - WARNING // - + // TODO: add SettingsBuilderResult } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java new file mode 100644 index 000000000000..0523f4d2320c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java @@ -0,0 +1,204 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.util.Optional; + +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import static org.apache.maven.api.services.BaseRequest.nonNull; + +/** + * Collects settings that control the building of effective settings. + */ +@Experimental +@Immutable +public interface SettingsBuilderRequest +{ + + @Nonnull + Session getSession(); + + /** + * Gets the global settings path. + * + * @return the global settings path or {@code null} if none + */ + @Nonnull + Optional getGlobalSettingsPath(); + + /** + * Gets the global settings source. + * + * @return the global settings source or {@code null} if none + */ + @Nonnull + Optional getGlobalSettingsSource(); + + /** + * Gets the user settings path. + * + * @return the user settings path or {@code null} if none + */ + @Nonnull + Optional getUserSettingsPath(); + + /** + * Gets the user settings source. + * + * @return the user settings source or {@code null} if none + */ + @Nonnull + Optional getUserSettingsSource(); + + @Nonnull + static SettingsBuilderRequest build( @Nonnull Session session, + @Nonnull Source globalSettingsSource, + @Nonnull Source userSettingsSource ) + { + return builder() + .session( nonNull( session, "session cannot be null" ) ) + .globalSettingsSource( nonNull( globalSettingsSource, "globalSettingsSource cannot be null" ) ) + .userSettingsSource( nonNull( userSettingsSource, "userSettingsSource cannot be null" ) ) + .build(); + } + + @Nonnull + static SettingsBuilderRequest build( @Nonnull Session session, + @Nonnull Path globalSettingsPath, + @Nonnull Path userSettingsPath ) + { + return builder() + .session( nonNull( session, "session cannot be null" ) ) + .globalSettingsPath( nonNull( globalSettingsPath, "globalSettingsPath cannot be null" ) ) + .userSettingsPath( nonNull( userSettingsPath, "userSettingsPath cannot be null" ) ) + .build(); + } + + @Nonnull + static SettingsBuilderRequestBuilder builder() + { + return new SettingsBuilderRequestBuilder(); + } + + @NotThreadSafe + class SettingsBuilderRequestBuilder + { + Session session; + Path globalSettingsPath; + Source globalSettingsSource; + Path userSettingsPath; + Source userSettingsSource; + + public SettingsBuilderRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public SettingsBuilderRequestBuilder globalSettingsPath( Path globalSettingsPath ) + { + this.globalSettingsPath = globalSettingsPath; + return this; + } + + public SettingsBuilderRequestBuilder globalSettingsSource( Source globalSettingsSource ) + { + this.globalSettingsSource = globalSettingsSource; + return this; + } + + public SettingsBuilderRequestBuilder userSettingsPath( Path userSettingsPath ) + { + this.userSettingsPath = userSettingsPath; + return this; + } + + public SettingsBuilderRequestBuilder userSettingsSource( Source userSettingsSource ) + { + this.userSettingsSource = userSettingsSource; + return this; + } + + public SettingsBuilderRequest build() + { + return new DefaultSettingsBuilderRequest( session, + globalSettingsPath, globalSettingsSource, + userSettingsPath, userSettingsSource ); + } + + private static class DefaultSettingsBuilderRequest extends BaseRequest + implements SettingsBuilderRequest + { + private final Path globalSettingsPath; + private final Source globalSettingsSource; + private final Path userSettingsPath; + private final Source userSettingsSource; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + DefaultSettingsBuilderRequest( @Nonnull Session session, + @Nullable Path globalSettingsPath, + @Nullable Source globalSettingsSource, + @Nullable Path userSettingsPath, + @Nullable Source userSettingsSource ) + { + super( session ); + this.globalSettingsPath = globalSettingsPath; + this.globalSettingsSource = globalSettingsSource; + this.userSettingsPath = userSettingsPath; + this.userSettingsSource = userSettingsSource; + } + + @Nonnull + @Override + public Optional getGlobalSettingsPath() + { + return Optional.ofNullable( globalSettingsPath ); + } + + @Nonnull + @Override + public Optional getGlobalSettingsSource() + { + return Optional.ofNullable( globalSettingsSource ); + } + + @Nonnull + @Override + public Optional getUserSettingsPath() + { + return Optional.ofNullable( userSettingsPath ); + } + + @Nonnull + @Override + public Optional getUserSettingsSource() + { + return Optional.ofNullable( userSettingsSource ); + } + } + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java new file mode 100644 index 000000000000..8cd1fc5757ad --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java @@ -0,0 +1,48 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.settings.Settings; + +public interface SettingsBuilderResult +{ + + /** + * Gets the assembled settings. + * + * @return the assembled settings, never {@code null} + */ + @Nonnull + Settings getEffectiveSettings(); + + /** + * Gets the problems that were encountered during the settings building. Note that only problems of severity + * {@link BuilderProblem.Severity#WARNING} and below are reported here. Problems with a higher severity level cause + * the settings builder to fail with a {@link SettingsBuilderException}. + * + * @return the problems that were encountered during the settings building, can be empty but never {@code null} + */ + @Nonnull + List getProblems(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Source.java similarity index 96% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/Source.java index 1add18cb12fb..08eea48c300d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Source.java @@ -30,7 +30,7 @@ * @since 4.0 */ @Experimental -public interface ProjectBuilderSource +public interface Source { InputStream getInputStream() throws IOException; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java index 2c8a2bd8fe59..eb543818041c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java @@ -31,8 +31,8 @@ public class ToolchainManagerException extends MavenException { /** - * @param message The message to give. - * @param e The {@link Exception}. + * @param message the message to give + * @param e the {@link Exception} */ public ToolchainManagerException( String message, Exception e ) { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilder.java new file mode 100644 index 000000000000..5e57291cf26e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilder.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; + +/** + * Builds the effective toolchains from a user toolchains file and/or a global toolchains file. + */ +@Experimental + +public interface ToolchainsBuilder extends Service +{ + + /** + * Builds the effective toolchains of the specified toolchains files. + * + * @param request the toolchains building request that holds the parameters, must not be {@code null} + * @return the result of the toolchains building, never {@code null} + * @throws ToolchainsBuilderException if the effective toolchains could not be built + */ + ToolchainsBuilderResult build( ToolchainsBuilderRequest request ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java new file mode 100644 index 000000000000..19bd724ed86f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java @@ -0,0 +1,43 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link ToolchainsBuilder}. + * + * @since 4.0 + */ +@Experimental +public class ToolchainsBuilderException + extends MavenException +{ + /** + * @param message the message to give + * @param e the {@link Exception} + */ + public ToolchainsBuilderException( String message, Exception e ) + { + super( message, e ); + } + + // TODO: add ToolchainsBuilderResult +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java new file mode 100644 index 000000000000..085950b2ffa9 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java @@ -0,0 +1,196 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.util.Optional; + +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import static org.apache.maven.api.services.BaseRequest.nonNull; + +public interface ToolchainsBuilderRequest +{ + @Nonnull + Session getSession(); + + /** + * Gets the global Toolchains path. + * + * @return the global Toolchains path or {@code null} if none + */ + @Nonnull + Optional getGlobalToolchainsPath(); + + /** + * Gets the global Toolchains source. + * + * @return the global Toolchains source or {@code null} if none + */ + @Nonnull + Optional getGlobalToolchainsSource(); + + /** + * Gets the user Toolchains path. + * + * @return the user Toolchains path or {@code null} if none + */ + @Nonnull + Optional getUserToolchainsPath(); + + /** + * Gets the user Toolchains source. + * + * @return the user Toolchains source or {@code null} if none + */ + @Nonnull + Optional getUserToolchainsSource(); + + @Nonnull + static ToolchainsBuilderRequest build( @Nonnull Session session, + @Nonnull Source globalToolchainsSource, + @Nonnull 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" ) ) + .build(); + } + + @Nonnull + static ToolchainsBuilderRequest build( @Nonnull Session session, + @Nonnull Path globalToolchainsPath, + @Nonnull 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" ) ) + .build(); + } + + @Nonnull + static ToolchainsBuilderRequestBuilder builder() + { + return new ToolchainsBuilderRequestBuilder(); + } + + @NotThreadSafe + class ToolchainsBuilderRequestBuilder + { + Session session; + Path globalToolchainsPath; + Source globalToolchainsSource; + Path userToolchainsPath; + Source userToolchainsSource; + + public ToolchainsBuilderRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ToolchainsBuilderRequestBuilder globalToolchainsPath( Path globalToolchainsPath ) + { + this.globalToolchainsPath = globalToolchainsPath; + return this; + } + + public ToolchainsBuilderRequestBuilder globalToolchainsSource( Source globalToolchainsSource ) + { + this.globalToolchainsSource = globalToolchainsSource; + return this; + } + + public ToolchainsBuilderRequestBuilder userToolchainsPath( Path userToolchainsPath ) + { + this.userToolchainsPath = userToolchainsPath; + return this; + } + + public ToolchainsBuilderRequestBuilder userToolchainsSource( Source userToolchainsSource ) + { + this.userToolchainsSource = userToolchainsSource; + return this; + } + + public ToolchainsBuilderRequest build() + { + return new ToolchainsBuilderRequestBuilder.DefaultToolchainsBuilderRequest( session, + globalToolchainsPath, globalToolchainsSource, + userToolchainsPath, 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 getGlobalToolchainsPath() + { + return Optional.ofNullable( globalToolchainsPath ); + } + + @Nonnull + @Override + public Optional getGlobalToolchainsSource() + { + return Optional.ofNullable( globalToolchainsSource ); + } + + @Nonnull + @Override + public Optional getUserToolchainsPath() + { + return Optional.ofNullable( userToolchainsPath ); + } + + @Nonnull + @Override + public Optional getUserToolchainsSource() + { + return Optional.ofNullable( userToolchainsSource ); + } + } + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java new file mode 100644 index 000000000000..5be2cea19b05 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.toolchain.PersistedToolchains; + +public interface ToolchainsBuilderResult +{ + /** + * Gets the assembled toolchains. + * + * @return the assembled toolchains, never {@code null} + */ + @Nonnull + PersistedToolchains getEffectiveToolchains(); + + /** + * Gets the problems that were encountered during the settings building. Note that only problems of severity + * {@link BuilderProblem.Severity#WARNING} and below are reported here. Problems with a higher severity level cause + * the settings builder to fail with a {@link ToolchainsBuilderException}. + * + * @return the problems that were encountered during the settings building, can be empty but never {@code null} + */ + @Nonnull + List getProblems(); + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java index 959f8fc69823..4944df1354b6 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -40,11 +40,10 @@ import org.apache.maven.api.services.DependencyCollectorResult; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectBuilderException; -import org.apache.maven.api.services.ProjectBuilderProblem; -import org.apache.maven.api.services.ProjectBuilderProblemSeverity; +import org.apache.maven.api.services.BuilderProblem; import org.apache.maven.api.services.ProjectBuilderRequest; import org.apache.maven.api.services.ProjectBuilderResult; -import org.apache.maven.api.services.ProjectBuilderSource; +import org.apache.maven.api.services.Source; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.building.ModelProblem; @@ -91,7 +90,7 @@ public ProjectBuilderResult build( ProjectBuilderRequest request ) } else if ( request.getSource().isPresent() ) { - ProjectBuilderSource source = request.getSource().get(); + Source source = request.getSource().get(); ModelSource modelSource = new ModelSource() { @Override @@ -153,14 +152,14 @@ public Optional getProject() @Nonnull @Override - public Collection getProblems() + public Collection getProblems() { return new MappedCollection<>( res.getProblems(), this::toProblem ); } - private ProjectBuilderProblem toProblem( ModelProblem problem ) + private BuilderProblem toProblem( ModelProblem problem ) { - return new ProjectBuilderProblem() + return new BuilderProblem() { @Override public String getSource() @@ -228,9 +227,9 @@ public String getMessage() } @Override - public ProjectBuilderProblemSeverity getSeverity() + public Severity getSeverity() { - return ProjectBuilderProblemSeverity.valueOf( problem.getSeverity().name() ); + return Severity.valueOf( problem.getSeverity().name() ); } }; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsBuilder.java new file mode 100644 index 000000000000..8b7f598cb0c0 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsBuilder.java @@ -0,0 +1,188 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +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 + { + DefaultSession session = ( DefaultSession ) 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 getProblems() + { + return new MappedList<>( result.getProblems(), MappedBuilderProblem::new ); + } + }; + } + catch ( SettingsBuildingException e ) + { + throw new SettingsBuilderException( "Unable to build settings", e ); + } + } + + private Properties toProperties( Map 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.getInputStream(); + } + + @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() ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsBuilder.java new file mode 100644 index 000000000000..ef75abd4ce00 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsBuilder.java @@ -0,0 +1,187 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +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.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.Source; +import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; +import org.apache.maven.toolchain.building.ToolchainsBuildingException; +import org.apache.maven.toolchain.building.ToolchainsBuildingResult; +import org.apache.maven.api.toolchain.PersistedToolchains; + +@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 + { + DefaultSession session = ( DefaultSession ) request.getSession(); + 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 getProblems() + { + return new MappedList<>( result.getProblems(), MappedBuilderProblem::new ); + } + }; + } + catch ( ToolchainsBuildingException e ) + { + throw new ToolchainsBuilderException( "Unable to build Toolchains", e ); + } + } + + private Properties toProperties( Map map ) + { + Properties properties = new Properties(); + properties.putAll( map ); + return properties; + } + + 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.getInputStream(); + } + + @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() ); + } + } +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index 3809ac3b1862..1596f5005ef2 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -32,6 +32,7 @@ import org.apache.maven.api.Session; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.api.services.SettingsBuilder; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.DefaultMavenExecutionRequest; @@ -87,6 +88,12 @@ public class TestApi @Inject SessionScope sessionScope; + @Inject + SettingsBuilder settingsBuilder; + + @Inject + ToolchainsBuilder toolchainsBuilder; + @BeforeEach void setup() {