mirror of https://github.com/apache/maven.git
[MNG-8375] CLIng diet (#1897)
First part was to "reverse" MavenCli into CLIng, that also became a huge and complex beast. Now, sanitization comes, tearing down unneeded stuff. CLIng should be simple and straightforward. Now the **invoker** fully parses args, creates Maven instance (ie. local, using Maven components on classpath) and invokes Maven. The new **executor** in turn does NOT fully parses args and is logical equivalent of maven-invoker. Changes: * radically simplify CLIng existing classes (and especially API - the fact we have "local", "resident" etc invoker is actually implementation detail). * introduce "executor", a "lower level" tool that does not parse args (and is logical equivalent of maven-invoker) and support Maven 4.x and Maven 3.x. --- https://issues.apache.org/jira/browse/MNG-8375
This commit is contained in:
parent
c7effeb15c
commit
a67d2746af
|
@ -0,0 +1 @@
|
|||
-Daether.transport.jdk.httpVersion=HTTP_1_1
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.cli;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
|
||||
/**
|
||||
* Defines the contract for a component responsible for executing a Maven tool
|
||||
* using the information provided in an {@link ExecutorRequest}. This interface is central
|
||||
* to the execution of Maven commands and builds, but it does not construct nor fully parses arguments.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface Executor extends AutoCloseable {
|
||||
/**
|
||||
* Invokes the tool application using the provided {@link ExecutorRequest}.
|
||||
* This method is responsible for executing the command or build
|
||||
* process based on the information contained in the request.
|
||||
*
|
||||
* @param executorRequest the request containing all necessary information for the execution
|
||||
* @return an integer representing the exit code of the execution (0 typically indicates success)
|
||||
* @throws ExecutorException if an error occurs during the execution process
|
||||
*/
|
||||
int execute(@Nonnull ExecutorRequest executorRequest) throws ExecutorException;
|
||||
|
||||
/**
|
||||
* Closes and disposes of this {@link Executor} instance, releasing any resources it may hold.
|
||||
* This method is called automatically when using try-with-resources statements.
|
||||
*
|
||||
* <p>The default implementation does nothing. Subclasses should override this method
|
||||
* if they need to perform cleanup operations.</p>
|
||||
*
|
||||
* @throws ExecutorException if an error occurs while closing the {@link Executor}
|
||||
*/
|
||||
@Override
|
||||
default void close() throws ExecutorException {}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.cli;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.apache.maven.api.services.MavenException;
|
||||
|
||||
/**
|
||||
* Represents an exception that occurs during the execution of a Maven build or command.
|
||||
* This exception is typically thrown when there are errors during the execution of a Maven
|
||||
* process, such as wrong cwd, non-existent installation directory, or other runtime issues.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public class ExecutorException extends MavenException {
|
||||
/**
|
||||
* Constructs a new {@code InvokerException} with the specified detail message.
|
||||
*
|
||||
* @param message the detail message explaining the cause of the exception
|
||||
*/
|
||||
public ExecutorException(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code InvokerException} with the specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message explaining the cause of the exception
|
||||
* @param cause the underlying cause of the exception
|
||||
*/
|
||||
public ExecutorException(@Nullable String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Immutable;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
|
||||
/**
|
||||
* Represents a request to execute Maven with command-line arguments.
|
||||
* This interface encapsulates all the necessary information needed to execute
|
||||
* Maven command with arguments. The arguments were not parsed, they are just passed over
|
||||
* to executed tool.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Immutable
|
||||
@Experimental
|
||||
public interface ExecutorRequest {
|
||||
/**
|
||||
* The parser request this instance was created from.
|
||||
*/
|
||||
@Nonnull
|
||||
ParserRequest parserRequest();
|
||||
|
||||
/**
|
||||
* Returns the current working directory for the Maven execution.
|
||||
* This is typically the directory from which Maven was invoked.
|
||||
*
|
||||
* @return the current working directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path cwd();
|
||||
|
||||
/**
|
||||
* Returns the Maven installation directory.
|
||||
* This is usually set by the Maven launcher script using the "maven.home" system property.
|
||||
*
|
||||
* @return the Maven installation directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path installationDirectory();
|
||||
|
||||
/**
|
||||
* Returns the user's home directory.
|
||||
* This is typically obtained from the "user.home" system property.
|
||||
*
|
||||
* @return the user's home directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path userHomeDirectory();
|
||||
|
||||
/**
|
||||
* Returns the list of extra JVM arguments to be passed to the forked process.
|
||||
* These arguments allow for customization of the JVM environment in which tool will run.
|
||||
* This property is used ONLY by executors and invokers that spawn a new JVM.
|
||||
*
|
||||
* @return an Optional containing the list of extra JVM arguments, or empty if not specified
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<List<String>> jvmArguments();
|
||||
}
|
|
@ -24,18 +24,16 @@ import org.apache.maven.api.annotations.Nonnull;
|
|||
/**
|
||||
* Defines the contract for a component responsible for invoking a Maven application
|
||||
* using the information provided in an {@link InvokerRequest}. This interface is central
|
||||
* to the execution of Maven commands and builds.
|
||||
* to the construction and invocation of Maven commands and builds, and it fully parses arguments.
|
||||
*
|
||||
* <p>The Invoker is designed to be flexible, allowing for different implementations
|
||||
* that can handle various types of {@link InvokerRequest InvokerRequests}. It also implements
|
||||
* {@link AutoCloseable} to ensure proper resource management.</p>
|
||||
*
|
||||
* @param <R> The specific type of {@link InvokerRequest} this {@code Invoker} can handle, extending {@link InvokerRequest}
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface Invoker<R extends InvokerRequest<? extends Options>> extends AutoCloseable {
|
||||
public interface Invoker extends AutoCloseable {
|
||||
/**
|
||||
* Invokes the Maven application using the provided {@link InvokerRequest}.
|
||||
* This method is responsible for executing the Maven command or build
|
||||
|
@ -45,7 +43,7 @@ public interface Invoker<R extends InvokerRequest<? extends Options>> extends Au
|
|||
* @return an integer representing the exit code of the invocation (0 typically indicates success)
|
||||
* @throws InvokerException if an error occurs during the invocation process
|
||||
*/
|
||||
int invoke(@Nonnull R invokerRequest) throws InvokerException;
|
||||
int invoke(@Nonnull InvokerRequest invokerRequest) throws InvokerException;
|
||||
|
||||
/**
|
||||
* Closes and disposes of this {@link Invoker} instance, releasing any resources it may hold.
|
||||
|
|
|
@ -49,4 +49,21 @@ public class InvokerException extends MavenException {
|
|||
public InvokerException(@Nullable String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for intentional exit: No message or anything will be displayed, just the
|
||||
* carried exit code will be returned from invoker {@link Invoker#invoke(InvokerRequest)} method.
|
||||
*/
|
||||
public static final class ExitException extends InvokerException {
|
||||
private final int exitCode;
|
||||
|
||||
public ExitException(int exitCode) {
|
||||
super("EXIT");
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,22 +33,14 @@ import org.apache.maven.api.services.Lookup;
|
|||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
|
||||
/**
|
||||
* Represents a Maven execution request, encapsulating all necessary information
|
||||
* for invoking a Maven build or command.
|
||||
*
|
||||
* @param <O> the type of {@link Options} used for this request, extending the base {@link Options} interface
|
||||
* Represents a Maven invocation request, encapsulating all necessary information
|
||||
* for invoking a Maven build or command. Arguments are parsed and exposed via methods.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Immutable
|
||||
@Experimental
|
||||
public interface InvokerRequest<O extends Options> {
|
||||
/**
|
||||
* The parser request this instance was created from.
|
||||
*/
|
||||
@Nonnull
|
||||
ParserRequest parserRequest();
|
||||
|
||||
public interface InvokerRequest extends ExecutorRequest {
|
||||
/**
|
||||
* Shorthand for {@link Logger} to use.
|
||||
*/
|
||||
|
@ -70,33 +62,6 @@ public interface InvokerRequest<O extends Options> {
|
|||
return parserRequest().lookup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current working directory for the Maven execution.
|
||||
* This is typically the directory from which Maven was invoked.
|
||||
*
|
||||
* @return the current working directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path cwd();
|
||||
|
||||
/**
|
||||
* Returns the Maven installation directory.
|
||||
* This is usually set by the Maven launcher script using the "maven.home" system property.
|
||||
*
|
||||
* @return the Maven installation directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path installationDirectory();
|
||||
|
||||
/**
|
||||
* Returns the user's home directory.
|
||||
* This is typically obtained from the "user.home" system property.
|
||||
*
|
||||
* @return the user's home directory path
|
||||
*/
|
||||
@Nonnull
|
||||
Path userHomeDirectory();
|
||||
|
||||
/**
|
||||
* Returns a map of user-defined properties for the Maven execution.
|
||||
* These properties can be set using the -D command-line option.
|
||||
|
@ -172,5 +137,5 @@ public interface InvokerRequest<O extends Options> {
|
|||
* @return the options object
|
||||
*/
|
||||
@Nonnull
|
||||
O options();
|
||||
Options options();
|
||||
}
|
||||
|
|
|
@ -22,47 +22,35 @@ import java.io.IOException;
|
|||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
|
||||
/**
|
||||
* Defines the contract for parsing Maven command-line arguments and creating an InvokerRequest.
|
||||
* This interface is responsible for interpreting the command-line input and constructing
|
||||
* the appropriate {@link InvokerRequest} object.
|
||||
*
|
||||
* @param <R> the type of {@link InvokerRequest} produced by this parser, extending {@link InvokerRequest}
|
||||
* Defines the contract for parsing Maven command-line arguments and creating an execution or invoker requests.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface Parser<R extends InvokerRequest<? extends Options>> {
|
||||
public interface Parser {
|
||||
/**
|
||||
* Parses the given Maven arguments to create an InvokerRequest.
|
||||
* This is a convenience method that internally creates a ParserRequest using
|
||||
* {@link ParserRequest#mvn(String[], Logger, MessageBuilderFactory)}.
|
||||
*
|
||||
* @param args the command-line arguments
|
||||
* @param logger the logger to use during parsing
|
||||
* @param messageBuilderFactory the factory for creating message builders
|
||||
* @return the parsed InvokerRequest
|
||||
* @throws ParserException if there's an error during parsing of the command or arguments
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
default R mvn(@Nonnull String[] args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory)
|
||||
throws ParserException, IOException {
|
||||
return parse(ParserRequest.mvn(args, logger, messageBuilderFactory).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given ParserRequest to create an InvokerRequest.
|
||||
* This method is responsible for interpreting the contents of the ParserRequest
|
||||
* and constructing the appropriate InvokerRequest object.
|
||||
* Parses the given ParserRequest to create an {@link ExecutorRequest}.
|
||||
* This method does not interpret tool arguments.
|
||||
*
|
||||
* @param parserRequest the request containing all necessary information for parsing
|
||||
* @return the parsed InvokerRequest
|
||||
* @return the parsed executor request
|
||||
* @throws ParserException if there's an error during parsing of the request
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
R parse(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
ExecutorRequest parseExecution(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
|
||||
/**
|
||||
* Parses the given ParserRequest to create an {@link InvokerRequest}.
|
||||
* This method does interpret tool arguments.
|
||||
*
|
||||
* @param parserRequest the request containing all necessary information for parsing
|
||||
* @return the parsed invoker request
|
||||
* @throws ParserException if there's an error during parsing of the request
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
InvokerRequest parseInvocation(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
}
|
||||
|
|
|
@ -46,12 +46,6 @@ import static java.util.Objects.requireNonNull;
|
|||
@Immutable
|
||||
@Experimental
|
||||
public interface ParserRequest {
|
||||
String MVN_CMD = "mvn";
|
||||
String MVN_NAME = "Maven";
|
||||
|
||||
String MVNENC_CMD = "mvnenc";
|
||||
String MVNENC_NAME = "Maven Password Encrypting Tool";
|
||||
|
||||
/**
|
||||
* Returns the Maven command to be executed. This command is used in some invokers (ie forked) but also to
|
||||
* present help to user.
|
||||
|
@ -179,7 +173,7 @@ public interface ParserRequest {
|
|||
@Nonnull
|
||||
static Builder mvn(
|
||||
@Nonnull List<String> args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
|
||||
return builder(MVN_CMD, MVN_NAME, args, logger, messageBuilderFactory);
|
||||
return builder(Tools.MVN_CMD, Tools.MVN_NAME, args, logger, messageBuilderFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +201,7 @@ public interface ParserRequest {
|
|||
@Nonnull
|
||||
static Builder mvnenc(
|
||||
@Nonnull List<String> args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
|
||||
return builder(MVNENC_CMD, MVNENC_NAME, args, logger, messageBuilderFactory);
|
||||
return builder(Tools.MVNENC_CMD, Tools.MVNENC_NAME, args, logger, messageBuilderFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,17 +16,24 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.api.cli.mvn.local;
|
||||
package org.apache.maven.api.cli;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvoker;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.annotations.Immutable;
|
||||
|
||||
/**
|
||||
* Local Maven invoker, it expects all the Maven be present in classpath.
|
||||
* Represents most common tools supported by CLIng.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Immutable
|
||||
@Experimental
|
||||
public interface LocalMavenInvoker extends MavenInvoker<MavenInvokerRequest<MavenOptions>> {}
|
||||
public final class Tools {
|
||||
private Tools() {}
|
||||
|
||||
public static final String MVN_CMD = "mvn";
|
||||
public static final String MVN_NAME = "Maven";
|
||||
|
||||
public static final String MVNENC_CMD = "mvnenc";
|
||||
public static final String MVNENC_NAME = "Maven Password Encrypting Tool";
|
||||
}
|
|
@ -1,47 +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.api.cli.mvn;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
|
||||
/**
|
||||
* Defines the contract for a component responsible for invoking Maven using information provided in an invoker request.
|
||||
* This interface extends the general {@link Invoker} interface, specializing it for Maven-specific operations.
|
||||
*
|
||||
* @param <R> The specific type of {@link MavenInvokerRequest} this invoker can handle
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface MavenInvoker<R extends MavenInvokerRequest<? extends MavenOptions>> extends Invoker<R> {
|
||||
/**
|
||||
* Invokes Maven using the provided MavenInvokerRequest.
|
||||
* This method is responsible for executing the Maven build process
|
||||
* based on the information contained in the request.
|
||||
*
|
||||
* @param invokerRequest the request containing all necessary information for the Maven invocation
|
||||
* @return an integer representing the exit code of the Maven invocation (0 typically indicates success)
|
||||
* @throws InvokerException if an error occurs during the Maven invocation process
|
||||
*/
|
||||
@Override
|
||||
int invoke(@Nonnull R invokerRequest) throws InvokerException;
|
||||
}
|
|
@ -1,39 +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.api.cli.mvn;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
|
||||
/**
|
||||
* Represents a request to invoke Maven.
|
||||
* This interface extends the general {@link InvokerRequest}, specializing it for Maven-specific operations.
|
||||
*
|
||||
* <p>A {@link MavenInvokerRequest} encapsulates all the necessary information needed to perform
|
||||
* a Maven build, including any Maven-specific options defined in {@link MavenOptions}.</p>
|
||||
*
|
||||
* @param <O> The specific Options type this request carries
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface MavenInvokerRequest<O extends MavenOptions> extends InvokerRequest<O> {
|
||||
// This interface doesn't declare any additional methods beyond those inherited from InvokerRequest.
|
||||
// It serves to type-specify the Options as MavenOptions for Maven-specific requests.
|
||||
}
|
|
@ -1,51 +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.api.cli.mvn;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
|
||||
/**
|
||||
* Defines the contract for parsing Maven-specific command-line arguments and creating a MavenInvokerRequest.
|
||||
* This interface extends the general {@link Parser} interface, specializing it for Maven operations.
|
||||
*
|
||||
* @param <R> The specific type of MavenInvokerRequest this parser produces
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface MavenParser<R extends MavenInvokerRequest<? extends MavenOptions>> extends Parser<R> {
|
||||
/**
|
||||
* Parses the given {@link ParserRequest} to create a {@link MavenInvokerRequest}.
|
||||
* This method is responsible for interpreting the contents of the ParserRequest
|
||||
* and constructing the appropriate {@link MavenInvokerRequest} object for Maven operations.
|
||||
*
|
||||
* @param parserRequest the request containing all necessary information for parsing
|
||||
* @return the parsed {@link MavenInvokerRequest}
|
||||
* @throws ParserException if there's an error during parsing of the request
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
R parse(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
}
|
|
@ -1,45 +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.api.cli.mvn.forked;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
|
||||
/**
|
||||
* Represents a request to invoke Maven in a forked JVM.
|
||||
* This interface extends the {@link MavenInvokerRequest}, adding capabilities specific to forked Maven executions.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface ForkedMavenInvokerRequest extends MavenInvokerRequest<MavenOptions> {
|
||||
/**
|
||||
* Returns the list of extra JVM arguments to be passed to the forked Maven process.
|
||||
* These arguments allow for customization of the JVM environment in which Maven will run.
|
||||
*
|
||||
* @return an Optional containing the list of extra JVM arguments, or empty if not specified
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<List<String>> jvmArguments();
|
||||
}
|
|
@ -1,49 +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.api.cli.mvn.forked;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenParser;
|
||||
|
||||
/**
|
||||
* Defines the contract for parsing command-line arguments specific to forked Maven executions.
|
||||
* This interface extends the {@link MavenParser}, specializing it for creating {@link ForkedMavenInvokerRequest} objects.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface ForkedMavenParser extends MavenParser<ForkedMavenInvokerRequest> {
|
||||
/**
|
||||
* Parses the given ParserRequest to create a ForkedMavenInvokerRequest.
|
||||
* This method is responsible for interpreting the contents of the ParserRequest
|
||||
* and constructing the appropriate ForkedMavenInvokerRequest object for forked Maven operations.
|
||||
*
|
||||
* @param parserRequest the request containing all necessary information for parsing
|
||||
* @return the parsed ForkedMavenInvokerRequest
|
||||
* @throws ParserException if there's an error during parsing of the request
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
ForkedMavenInvokerRequest parse(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
}
|
|
@ -1,47 +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.api.cli.mvnenc;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
|
||||
/**
|
||||
* Defines the contract for a component responsible for invoking the Maven encryption tool.
|
||||
* This interface extends the general Invoker interface, specializing it for encryption-related operations.
|
||||
*
|
||||
* <p>The EncryptInvoker is designed to handle encryption tasks within the Maven ecosystem,
|
||||
* such as encrypting passwords or other sensitive information in Maven settings files.</p>
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface EncryptInvoker extends Invoker<EncryptInvokerRequest> {
|
||||
/**
|
||||
* Invokes the encryption tool using the provided EncryptInvokerRequest.
|
||||
* This method is responsible for executing the encryption command or process
|
||||
* based on the information contained in the request.
|
||||
*
|
||||
* @param invokerRequest the request containing all necessary information for the encryption invocation
|
||||
* @return an integer representing the exit code of the invocation (0 typically indicates success)
|
||||
* @throws InvokerException if an error occurs during the encryption process
|
||||
*/
|
||||
@Override
|
||||
int invoke(EncryptInvokerRequest invokerRequest) throws InvokerException;
|
||||
}
|
|
@ -1,37 +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.api.cli.mvnenc;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
|
||||
/**
|
||||
* Represents a request to invoke the Maven encryption tool.
|
||||
* This interface extends the general InvokerRequest, specializing it for encryption-related operations.
|
||||
*
|
||||
* <p>An EncryptInvokerRequest encapsulates all the necessary information needed to perform
|
||||
* an encryption operation, including any encryption-specific options defined in EncryptOptions.</p>
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface EncryptInvokerRequest extends InvokerRequest<EncryptOptions> {
|
||||
// This interface doesn't declare any additional methods beyond those inherited from InvokerRequest.
|
||||
// It serves to type-specify the Options as EncryptOptions for encryption-related requests.
|
||||
}
|
|
@ -1,49 +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.api.cli.mvnenc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
|
||||
/**
|
||||
* Defines the contract for parsing encryption-related command-line arguments and creating an EncryptInvokerRequest.
|
||||
* This interface extends the general {@link Parser} interface, specializing it for encryption operations.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public interface EncryptParser extends Parser<EncryptInvokerRequest> {
|
||||
/**
|
||||
* Parses the given ParserRequest to create an EncryptInvokerRequest.
|
||||
* This method is responsible for interpreting the contents of the ParserRequest
|
||||
* and constructing the appropriate EncryptInvokerRequest object for encryption operations.
|
||||
*
|
||||
* @param parserRequest the request containing all necessary information for parsing
|
||||
* @return the parsed EncryptInvokerRequest
|
||||
* @throws ParserException if there's an error during parsing of the request
|
||||
* @throws IOException if there's an I/O error during the parsing process
|
||||
*/
|
||||
@Nonnull
|
||||
EncryptInvokerRequest parse(@Nonnull ParserRequest parserRequest) throws ParserException, IOException;
|
||||
}
|
|
@ -23,7 +23,6 @@ import java.io.IOException;
|
|||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
|
||||
|
@ -31,11 +30,8 @@ import static java.util.Objects.requireNonNull;
|
|||
|
||||
/**
|
||||
* The CLI "new-gen".
|
||||
*
|
||||
* @param <O> the options type
|
||||
* @param <R> the request type
|
||||
*/
|
||||
public abstract class ClingSupport<O extends Options, R extends InvokerRequest<O>> {
|
||||
public abstract class ClingSupport {
|
||||
static final String CORE_CLASS_REALM_ID = "plexus.core";
|
||||
|
||||
protected final ClassWorld classWorld;
|
||||
|
@ -64,7 +60,7 @@ public abstract class ClingSupport<O extends Options, R extends InvokerRequest<O
|
|||
* The main entry point.
|
||||
*/
|
||||
public int run(String[] args) throws IOException {
|
||||
try (Invoker<R> invoker = createInvoker()) {
|
||||
try (Invoker invoker = createInvoker()) {
|
||||
return invoker.invoke(parseArguments(args));
|
||||
} catch (ParserException e) {
|
||||
System.err.println(e.getMessage());
|
||||
|
@ -78,7 +74,7 @@ public abstract class ClingSupport<O extends Options, R extends InvokerRequest<O
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract Invoker<R> createInvoker();
|
||||
protected abstract Invoker createInvoker();
|
||||
|
||||
protected abstract R parseArguments(String[] args) throws ParserException, IOException;
|
||||
protected abstract InvokerRequest parseArguments(String[] args) throws ParserException, IOException;
|
||||
}
|
||||
|
|
|
@ -21,20 +21,20 @@ package org.apache.maven.cling;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.cling.invoker.ProtoLogger;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.local.DefaultLocalMavenInvoker;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.local.LocalMavenInvoker;
|
||||
import org.apache.maven.jline.JLineMessageBuilderFactory;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
|
||||
/**
|
||||
* Maven CLI "new-gen".
|
||||
*/
|
||||
public class MavenCling extends ClingSupport<MavenOptions, MavenInvokerRequest<MavenOptions>> {
|
||||
public class MavenCling extends ClingSupport {
|
||||
/**
|
||||
* "Normal" Java entry point. Note: Maven uses ClassWorld Launcher and this entry point is NOT used under normal
|
||||
* circumstances.
|
||||
|
@ -60,13 +60,15 @@ public class MavenCling extends ClingSupport<MavenOptions, MavenInvokerRequest<M
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Invoker<MavenInvokerRequest<MavenOptions>> createInvoker() {
|
||||
return new DefaultLocalMavenInvoker(
|
||||
protected Invoker createInvoker() {
|
||||
return new LocalMavenInvoker(
|
||||
ProtoLookup.builder().addMapping(ClassWorld.class, classWorld).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MavenInvokerRequest<MavenOptions> parseArguments(String[] args) throws ParserException, IOException {
|
||||
return new DefaultMavenParser().mvn(args, new ProtoLogger(), new JLineMessageBuilderFactory());
|
||||
protected InvokerRequest parseArguments(String[] args) throws ParserException, IOException {
|
||||
return new MavenParser()
|
||||
.parseInvocation(ParserRequest.mvn(args, new ProtoLogger(), new JLineMessageBuilderFactory())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,21 +21,20 @@ package org.apache.maven.cling;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.cling.invoker.ProtoLogger;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptParser;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptParser;
|
||||
import org.apache.maven.jline.JLineMessageBuilderFactory;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
|
||||
/**
|
||||
* Maven encrypt CLI "new-gen".
|
||||
*/
|
||||
public class MavenEncCling extends ClingSupport<EncryptOptions, EncryptInvokerRequest> {
|
||||
public class MavenEncCling extends ClingSupport {
|
||||
/**
|
||||
* "Normal" Java entry point. Note: Maven uses ClassWorld Launcher and this entry point is NOT used under normal
|
||||
* circumstances.
|
||||
|
@ -61,15 +60,15 @@ public class MavenEncCling extends ClingSupport<EncryptOptions, EncryptInvokerRe
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Invoker<EncryptInvokerRequest> createInvoker() {
|
||||
return new DefaultEncryptInvoker(
|
||||
protected Invoker createInvoker() {
|
||||
return new EncryptInvoker(
|
||||
ProtoLookup.builder().addMapping(ClassWorld.class, classWorld).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EncryptInvokerRequest parseArguments(String[] args) throws ParserException, IOException {
|
||||
return new DefaultEncryptParser()
|
||||
.parse(ParserRequest.mvnenc(args, new ProtoLogger(), new JLineMessageBuilderFactory())
|
||||
protected InvokerRequest parseArguments(String[] args) throws ParserException, IOException {
|
||||
return new EncryptParser()
|
||||
.parseInvocation(ParserRequest.mvnenc(args, new ProtoLogger(), new JLineMessageBuilderFactory())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.cling.invoker;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.apache.maven.api.cli.ExecutorRequest;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class BaseExecutorRequest implements ExecutorRequest {
|
||||
private final ParserRequest parserRequest;
|
||||
private final Path cwd;
|
||||
private final Path installationDirectory;
|
||||
private final Path userHomeDirectory;
|
||||
private final List<String> jvmArguments;
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
public BaseExecutorRequest(
|
||||
@Nonnull ParserRequest parserRequest,
|
||||
@Nonnull Path cwd,
|
||||
@Nonnull Path installationDirectory,
|
||||
@Nonnull Path userHomeDirectory,
|
||||
@Nullable List<String> jvmArguments) {
|
||||
this.parserRequest = requireNonNull(parserRequest);
|
||||
this.cwd = requireNonNull(cwd);
|
||||
this.installationDirectory = requireNonNull(installationDirectory);
|
||||
this.userHomeDirectory = requireNonNull(userHomeDirectory);
|
||||
this.jvmArguments = jvmArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParserRequest parserRequest() {
|
||||
return parserRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path cwd() {
|
||||
return cwd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path installationDirectory() {
|
||||
return installationDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path userHomeDirectory() {
|
||||
return userHomeDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> jvmArguments() {
|
||||
return Optional.ofNullable(jvmArguments);
|
||||
}
|
||||
}
|
|
@ -28,26 +28,20 @@ import java.util.Optional;
|
|||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public abstract class BaseInvokerRequest<T extends Options> implements InvokerRequest<T> {
|
||||
private final ParserRequest parserRequest;
|
||||
private final Path cwd;
|
||||
private final Path installationDirectory;
|
||||
private final Path userHomeDirectory;
|
||||
public abstract class BaseInvokerRequest extends BaseExecutorRequest implements InvokerRequest {
|
||||
private final Map<String, String> userProperties;
|
||||
private final Map<String, String> systemProperties;
|
||||
private final Path topDirectory;
|
||||
private final Path rootDirectory;
|
||||
|
||||
private final List<CoreExtension> coreExtensions;
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
private final OutputStream err;
|
||||
private final List<CoreExtension> coreExtensions;
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
public BaseInvokerRequest(
|
||||
|
@ -62,40 +56,18 @@ public abstract class BaseInvokerRequest<T extends Options> implements InvokerRe
|
|||
@Nullable InputStream in,
|
||||
@Nullable OutputStream out,
|
||||
@Nullable OutputStream err,
|
||||
@Nullable List<CoreExtension> coreExtensions) {
|
||||
this.parserRequest = requireNonNull(parserRequest);
|
||||
this.cwd = requireNonNull(cwd);
|
||||
this.installationDirectory = requireNonNull(installationDirectory);
|
||||
this.userHomeDirectory = requireNonNull(userHomeDirectory);
|
||||
@Nullable List<CoreExtension> coreExtensions,
|
||||
@Nullable List<String> jvmArguments) {
|
||||
super(parserRequest, cwd, installationDirectory, userHomeDirectory, jvmArguments);
|
||||
this.userProperties = requireNonNull(userProperties);
|
||||
this.systemProperties = requireNonNull(systemProperties);
|
||||
this.topDirectory = requireNonNull(topDirectory);
|
||||
this.rootDirectory = rootDirectory;
|
||||
this.coreExtensions = coreExtensions;
|
||||
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
this.coreExtensions = coreExtensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParserRequest parserRequest() {
|
||||
return parserRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path cwd() {
|
||||
return cwd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path installationDirectory() {
|
||||
return installationDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path userHomeDirectory() {
|
||||
return userHomeDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,9 +33,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.api.Constants;
|
||||
import org.apache.maven.api.annotations.Nullable;
|
||||
import org.apache.maven.api.cli.ExecutorRequest;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
|
@ -57,7 +59,7 @@ import static org.apache.maven.cling.invoker.Utils.prefix;
|
|||
import static org.apache.maven.cling.invoker.Utils.stripLeadingAndTrailingQuotes;
|
||||
import static org.apache.maven.cling.invoker.Utils.toMap;
|
||||
|
||||
public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>> implements Parser<R> {
|
||||
public abstract class BaseParser implements Parser {
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public static class LocalContext {
|
||||
|
@ -93,7 +95,26 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
|
|||
}
|
||||
|
||||
@Override
|
||||
public R parse(ParserRequest parserRequest) throws ParserException, IOException {
|
||||
public ExecutorRequest parseExecution(ParserRequest parserRequest) throws ParserException, IOException {
|
||||
requireNonNull(parserRequest);
|
||||
|
||||
LocalContext context = new LocalContext(parserRequest);
|
||||
|
||||
// the basics
|
||||
context.cwd = requireNonNull(getCwd(context));
|
||||
context.installationDirectory = requireNonNull(getInstallationDirectory(context));
|
||||
context.userHomeDirectory = requireNonNull(getUserHomeDirectory(context));
|
||||
|
||||
return getExecutionRequest(context);
|
||||
}
|
||||
|
||||
protected ExecutorRequest getExecutionRequest(LocalContext context) {
|
||||
return new BaseExecutorRequest(
|
||||
context.parserRequest, context.cwd, context.installationDirectory, context.userHomeDirectory, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvokerRequest parseInvocation(ParserRequest parserRequest) throws ParserException, IOException {
|
||||
requireNonNull(parserRequest);
|
||||
|
||||
LocalContext context = new LocalContext(parserRequest);
|
||||
|
@ -108,7 +129,7 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
|
|||
context.rootDirectory = getRootDirectory(context);
|
||||
|
||||
// options
|
||||
List<O> parsedOptions = parseCliOptions(context);
|
||||
List<Options> parsedOptions = parseCliOptions(context);
|
||||
|
||||
// warn about deprecated options
|
||||
PrintWriter printWriter = new PrintWriter(parserRequest.out() != null ? parserRequest.out() : System.out, true);
|
||||
|
@ -131,7 +152,7 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
|
|||
return getInvokerRequest(context);
|
||||
}
|
||||
|
||||
protected abstract R getInvokerRequest(LocalContext context);
|
||||
protected abstract InvokerRequest getInvokerRequest(LocalContext context);
|
||||
|
||||
protected Path getCwd(LocalContext context) throws ParserException {
|
||||
if (context.parserRequest.cwd() != null) {
|
||||
|
@ -271,9 +292,9 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
|
|||
return toMap(userProperties);
|
||||
}
|
||||
|
||||
protected abstract List<O> parseCliOptions(LocalContext context) throws ParserException, IOException;
|
||||
protected abstract List<Options> parseCliOptions(LocalContext context) throws ParserException, IOException;
|
||||
|
||||
protected abstract O assembleOptions(List<O> parsedOptions);
|
||||
protected abstract Options assembleOptions(List<Options> parsedOptions);
|
||||
|
||||
protected List<CoreExtension> readCoreExtensionsDescriptor(LocalContext context)
|
||||
throws ParserException, IOException {
|
||||
|
@ -304,4 +325,21 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
|
|||
throw new ParserException("Failed to parse extensions file: " + extensionsFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<String> getJvmArguments(Path rootDirectory) throws ParserException {
|
||||
if (rootDirectory != null) {
|
||||
Path jvmConfig = rootDirectory.resolve(".mvn/jvm.config");
|
||||
if (Files.exists(jvmConfig)) {
|
||||
try {
|
||||
return Files.readAllLines(jvmConfig).stream()
|
||||
.filter(l -> !l.isBlank() && !l.startsWith("#"))
|
||||
.flatMap(l -> Arrays.stream(l.split(" ")))
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new ParserException("Failed to read JVM configuration file: " + jvmConfig, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.apache.maven.cling.invoker;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.services.Lookup;
|
||||
|
@ -32,6 +34,12 @@ public interface ContainerCapsule extends AutoCloseable {
|
|||
@Nonnull
|
||||
Lookup getLookup();
|
||||
|
||||
/**
|
||||
* The TCCL, if implementation requires it.
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<ClassLoader> currentThreadClassLoader();
|
||||
|
||||
/**
|
||||
* Performs a clean shutdown of backing container.
|
||||
*/
|
||||
|
|
|
@ -20,21 +20,16 @@ package org.apache.maven.cling.invoker;
|
|||
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
|
||||
/**
|
||||
* Container capsule factory.
|
||||
*
|
||||
* @param <O> the options type
|
||||
* @param <R> the invoker request type
|
||||
* @param <C> the invoker context type
|
||||
* @param <C> The context type.
|
||||
*/
|
||||
public interface ContainerCapsuleFactory<
|
||||
O extends Options, R extends InvokerRequest<O>, C extends LookupInvoker.LookupInvokerContext<O, R, C>> {
|
||||
public interface ContainerCapsuleFactory<C extends LookupContext> {
|
||||
/**
|
||||
* Creates container capsule.
|
||||
*/
|
||||
@Nonnull
|
||||
ContainerCapsule createContainerCapsule(C context) throws InvokerException;
|
||||
ContainerCapsule createContainerCapsule(LookupInvoker<C> invoker, C context) throws InvokerException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.cling.invoker;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.maven.api.Session;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Logger;
|
||||
import org.apache.maven.api.services.Lookup;
|
||||
import org.apache.maven.api.settings.Settings;
|
||||
import org.apache.maven.cling.invoker.mvn.ProtoSession;
|
||||
import org.apache.maven.cling.logging.Slf4jConfiguration;
|
||||
import org.jline.terminal.Terminal;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public class LookupContext implements AutoCloseable {
|
||||
public final InvokerRequest invokerRequest;
|
||||
public final Function<String, Path> cwdResolver;
|
||||
public final Function<String, Path> installationResolver;
|
||||
public final Function<String, Path> userResolver;
|
||||
public final Session session;
|
||||
|
||||
protected LookupContext(InvokerRequest invokerRequest) {
|
||||
this.invokerRequest = requireNonNull(invokerRequest);
|
||||
this.cwdResolver = s -> invokerRequest.cwd().resolve(s).normalize().toAbsolutePath();
|
||||
this.installationResolver = s ->
|
||||
invokerRequest.installationDirectory().resolve(s).normalize().toAbsolutePath();
|
||||
this.userResolver =
|
||||
s -> invokerRequest.userHomeDirectory().resolve(s).normalize().toAbsolutePath();
|
||||
this.logger = invokerRequest.parserRequest().logger();
|
||||
|
||||
Map<String, String> user = new HashMap<>(invokerRequest.userProperties());
|
||||
user.put("session.rootDirectory", invokerRequest.rootDirectory().toString());
|
||||
user.put("session.topDirectory", invokerRequest.topDirectory().toString());
|
||||
Map<String, String> system = new HashMap<>(invokerRequest.systemProperties());
|
||||
this.session = ProtoSession.create(user, system);
|
||||
}
|
||||
|
||||
public Logger logger;
|
||||
public ILoggerFactory loggerFactory;
|
||||
public Slf4jConfiguration slf4jConfiguration;
|
||||
public Slf4jConfiguration.Level loggerLevel;
|
||||
public Boolean coloredOutput;
|
||||
public Terminal terminal;
|
||||
public Consumer<String> writer;
|
||||
public ContainerCapsule containerCapsule;
|
||||
public Lookup lookup;
|
||||
|
||||
public boolean interactive;
|
||||
public Path localRepositoryPath;
|
||||
public Path installationSettingsPath;
|
||||
public Path projectSettingsPath;
|
||||
public Path userSettingsPath;
|
||||
public Settings effectiveSettings;
|
||||
|
||||
public final List<AutoCloseable> closeables = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
List<Exception> causes = null;
|
||||
List<AutoCloseable> cs = new ArrayList<>(closeables);
|
||||
Collections.reverse(cs);
|
||||
for (AutoCloseable c : cs) {
|
||||
if (c != null) {
|
||||
try {
|
||||
c.close();
|
||||
} catch (Exception e) {
|
||||
if (causes == null) {
|
||||
causes = new ArrayList<>();
|
||||
}
|
||||
causes.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (causes != null) {
|
||||
InvokerException exception = new InvokerException("Unable to close context");
|
||||
causes.forEach(exception::addSuppressed);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,8 +24,6 @@ import java.io.PrintWriter;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -35,7 +33,6 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
|
||||
import org.apache.maven.api.Constants;
|
||||
import org.apache.maven.api.Session;
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
|
@ -43,7 +40,6 @@ import org.apache.maven.api.cli.Logger;
|
|||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.services.Lookup;
|
||||
import org.apache.maven.api.services.MavenException;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
|
@ -62,7 +58,6 @@ import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
|
|||
import org.apache.maven.artifact.repository.MavenArtifactRepository;
|
||||
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
|
||||
import org.apache.maven.bridge.MavenRepositorySystem;
|
||||
import org.apache.maven.cling.invoker.mvn.ProtoSession;
|
||||
import org.apache.maven.cling.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cling.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cling.transfer.ConsoleMavenTransferListener;
|
||||
|
@ -82,7 +77,6 @@ import org.jline.terminal.Terminal;
|
|||
import org.jline.terminal.TerminalBuilder;
|
||||
import org.jline.terminal.impl.AbstractPosixTerminal;
|
||||
import org.jline.terminal.spi.TerminalExt;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.spi.LocationAwareLogger;
|
||||
|
||||
|
@ -91,108 +85,11 @@ import static org.apache.maven.cling.invoker.Utils.toMavenExecutionRequestLoggin
|
|||
import static org.apache.maven.cling.invoker.Utils.toProperties;
|
||||
|
||||
/**
|
||||
* Plexus invoker implementation, that boots up Plexus DI container. This class expects fully setup ClassWorld via constructor.
|
||||
* Lookup invoker implementation, that boots up DI container.
|
||||
*
|
||||
* @param <O> the options type
|
||||
* @param <R> the request type
|
||||
* @param <C> the context type
|
||||
* @param <C> The context type.
|
||||
*/
|
||||
public abstract class LookupInvoker<
|
||||
O extends Options, R extends InvokerRequest<O>, C extends LookupInvoker.LookupInvokerContext<O, R, C>>
|
||||
implements Invoker<R> {
|
||||
|
||||
/**
|
||||
* Exception for intentional exit: No message or anything will be displayed, just the
|
||||
* carried exit code will be returned from {@link #invoke(InvokerRequest)} method.
|
||||
*/
|
||||
public static final class ExitException extends InvokerException {
|
||||
private final int exitCode;
|
||||
|
||||
public ExitException(int exitCode) {
|
||||
super("EXIT");
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public static class LookupInvokerContext<
|
||||
O extends Options, R extends InvokerRequest<O>, C extends LookupInvokerContext<O, R, C>>
|
||||
implements AutoCloseable {
|
||||
public final LookupInvoker<O, R, C> invoker;
|
||||
public final ProtoLookup protoLookup;
|
||||
public final R invokerRequest;
|
||||
public final Function<String, Path> cwdResolver;
|
||||
public final Function<String, Path> installationResolver;
|
||||
public final Function<String, Path> userResolver;
|
||||
public final Session session;
|
||||
|
||||
protected LookupInvokerContext(LookupInvoker<O, R, C> invoker, R invokerRequest) {
|
||||
this.invoker = invoker;
|
||||
this.protoLookup = invoker.protoLookup;
|
||||
this.invokerRequest = requireNonNull(invokerRequest);
|
||||
this.cwdResolver = s -> invokerRequest.cwd().resolve(s).normalize().toAbsolutePath();
|
||||
this.installationResolver = s -> invokerRequest
|
||||
.installationDirectory()
|
||||
.resolve(s)
|
||||
.normalize()
|
||||
.toAbsolutePath();
|
||||
this.userResolver = s ->
|
||||
invokerRequest.userHomeDirectory().resolve(s).normalize().toAbsolutePath();
|
||||
this.logger = invokerRequest.parserRequest().logger();
|
||||
|
||||
Map<String, String> user = new HashMap<>(invokerRequest.userProperties());
|
||||
user.put("session.rootDirectory", invokerRequest.rootDirectory().toString());
|
||||
user.put("session.topDirectory", invokerRequest.topDirectory().toString());
|
||||
Map<String, String> system = new HashMap<>(invokerRequest.systemProperties());
|
||||
this.session = ProtoSession.create(user, system);
|
||||
}
|
||||
|
||||
public Logger logger;
|
||||
public ILoggerFactory loggerFactory;
|
||||
public Slf4jConfiguration slf4jConfiguration;
|
||||
public Slf4jConfiguration.Level loggerLevel;
|
||||
public Boolean coloredOutput;
|
||||
public Terminal terminal;
|
||||
public Consumer<String> writer;
|
||||
public ClassLoader currentThreadContextClassLoader;
|
||||
public ContainerCapsule containerCapsule;
|
||||
public Lookup lookup;
|
||||
public SettingsBuilder settingsBuilder;
|
||||
|
||||
public boolean interactive;
|
||||
public Path localRepositoryPath;
|
||||
public Path installationSettingsPath;
|
||||
public Path projectSettingsPath;
|
||||
public Path userSettingsPath;
|
||||
public Settings effectiveSettings;
|
||||
|
||||
public final List<AutoCloseable> closeables = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
List<Exception> causes = null;
|
||||
List<AutoCloseable> cs = new ArrayList<>(closeables);
|
||||
Collections.reverse(cs);
|
||||
for (AutoCloseable c : cs) {
|
||||
if (c != null) {
|
||||
try {
|
||||
c.close();
|
||||
} catch (Exception e) {
|
||||
if (causes == null) {
|
||||
causes = new ArrayList<>();
|
||||
}
|
||||
causes.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (causes != null) {
|
||||
InvokerException exception = new InvokerException("Unable to close context");
|
||||
causes.forEach(exception::addSuppressed);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class LookupInvoker<C extends LookupContext> implements Invoker {
|
||||
protected final ProtoLookup protoLookup;
|
||||
|
||||
public LookupInvoker(ProtoLookup protoLookup) {
|
||||
|
@ -200,19 +97,23 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
@Override
|
||||
public int invoke(R invokerRequest) throws InvokerException {
|
||||
public int invoke(InvokerRequest invokerRequest) throws InvokerException {
|
||||
requireNonNull(invokerRequest);
|
||||
|
||||
Properties oldProps = (Properties) System.getProperties().clone();
|
||||
ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
|
||||
try (C context = createContext(invokerRequest)) {
|
||||
try {
|
||||
if (context.currentThreadContextClassLoader != null) {
|
||||
Thread.currentThread().setContextClassLoader(context.currentThreadContextClassLoader);
|
||||
if (context.containerCapsule != null
|
||||
&& context.containerCapsule.currentThreadClassLoader().isPresent()) {
|
||||
Thread.currentThread()
|
||||
.setContextClassLoader(context.containerCapsule
|
||||
.currentThreadClassLoader()
|
||||
.get());
|
||||
}
|
||||
return doInvoke(context);
|
||||
} catch (ExitException e) {
|
||||
return e.exitCode;
|
||||
} catch (InvokerException.ExitException e) {
|
||||
return e.getExitCode();
|
||||
} catch (Exception e) {
|
||||
throw handleException(context, e);
|
||||
}
|
||||
|
@ -238,8 +139,7 @@ public abstract class LookupInvoker<
|
|||
return execute(context);
|
||||
}
|
||||
|
||||
protected InvokerException handleException(LookupInvokerContext<O, R, C> context, Exception e)
|
||||
throws InvokerException {
|
||||
protected InvokerException handleException(C context, Exception e) throws InvokerException {
|
||||
boolean showStackTrace = context.invokerRequest.options().showErrors().orElse(false);
|
||||
if (showStackTrace) {
|
||||
context.logger.error(
|
||||
|
@ -255,10 +155,10 @@ public abstract class LookupInvoker<
|
|||
return new InvokerException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
protected abstract C createContext(R invokerRequest) throws InvokerException;
|
||||
protected abstract C createContext(InvokerRequest invokerRequest) throws InvokerException;
|
||||
|
||||
protected void pushProperties(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
HashSet<String> sys = new HashSet<>(invokerRequest.systemProperties().keySet());
|
||||
invokerRequest.userProperties().entrySet().stream()
|
||||
.filter(k -> !sys.contains(k.getKey()))
|
||||
|
@ -272,7 +172,7 @@ public abstract class LookupInvoker<
|
|||
protected void prepare(C context) throws Exception {}
|
||||
|
||||
protected void configureLogging(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
// LOG COLOR
|
||||
Options mavenOptions = invokerRequest.options();
|
||||
Map<String, String> userProperties = invokerRequest.userProperties();
|
||||
|
@ -338,7 +238,7 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected void doConfigureWithTerminal(C context, Terminal terminal) {
|
||||
O options = context.invokerRequest.options();
|
||||
Options options = context.invokerRequest.options();
|
||||
if (options.rawStreams().isEmpty() || !options.rawStreams().get()) {
|
||||
MavenSimpleLogger stdout = (MavenSimpleLogger) context.loggerFactory.getLogger("stdout");
|
||||
MavenSimpleLogger stderr = (MavenSimpleLogger) context.loggerFactory.getLogger("stderr");
|
||||
|
@ -358,7 +258,7 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected Consumer<String> doDetermineWriter(C context) {
|
||||
O options = context.invokerRequest.options();
|
||||
Options options = context.invokerRequest.options();
|
||||
if (options.logFile().isPresent()) {
|
||||
Path logFile = context.cwdResolver.apply(options.logFile().get());
|
||||
try {
|
||||
|
@ -380,7 +280,7 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected void activateLogging(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
Options mavenOptions = invokerRequest.options();
|
||||
|
||||
context.slf4jConfiguration.activate();
|
||||
|
@ -412,21 +312,21 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected void helpOrVersionAndMayExit(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
if (invokerRequest.options().help().isPresent()) {
|
||||
Consumer<String> writer = determineWriter(context);
|
||||
invokerRequest.options().displayHelp(context.invokerRequest.parserRequest(), writer);
|
||||
throw new ExitException(0);
|
||||
throw new InvokerException.ExitException(0);
|
||||
}
|
||||
if (invokerRequest.options().showVersionAndExit().isPresent()) {
|
||||
showVersion(context);
|
||||
throw new ExitException(0);
|
||||
throw new InvokerException.ExitException(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected void showVersion(C context) {
|
||||
Consumer<String> writer = determineWriter(context);
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
if (invokerRequest.options().quiet().orElse(false)) {
|
||||
writer.accept(CLIReportingUtils.showVersionMinimal());
|
||||
} else if (invokerRequest.options().verbose().orElse(false)) {
|
||||
|
@ -466,10 +366,9 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected void container(C context) throws Exception {
|
||||
context.containerCapsule = createContainerCapsuleFactory().createContainerCapsule(context);
|
||||
context.containerCapsule = createContainerCapsuleFactory().createContainerCapsule(this, context);
|
||||
context.closeables.add(context.containerCapsule);
|
||||
context.lookup = context.containerCapsule.getLookup();
|
||||
context.settingsBuilder = context.lookup.lookup(SettingsBuilder.class);
|
||||
|
||||
// refresh logger in case container got customized by spy
|
||||
org.slf4j.Logger l = context.loggerFactory.getLogger(this.getClass().getName());
|
||||
|
@ -478,7 +377,7 @@ public abstract class LookupInvoker<
|
|||
.log(message);
|
||||
}
|
||||
|
||||
protected ContainerCapsuleFactory<O, R, C> createContainerCapsuleFactory() {
|
||||
protected ContainerCapsuleFactory<C> createContainerCapsuleFactory() {
|
||||
return new PlexusContainerCapsuleFactory<>();
|
||||
}
|
||||
|
||||
|
@ -487,7 +386,7 @@ public abstract class LookupInvoker<
|
|||
protected void init(C context) throws Exception {}
|
||||
|
||||
protected void postCommands(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
Logger logger = context.logger;
|
||||
if (invokerRequest.options().showErrors().orElse(false)) {
|
||||
logger.info("Error stacktraces are turned on.");
|
||||
|
@ -513,7 +412,7 @@ public abstract class LookupInvoker<
|
|||
}
|
||||
|
||||
protected void settings(C context) throws Exception {
|
||||
settings(context, context.settingsBuilder);
|
||||
settings(context, context.lookup.lookup(SettingsBuilder.class));
|
||||
}
|
||||
|
||||
protected void settings(C context, SettingsBuilder settingsBuilder) throws Exception {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.apache.maven.cling.invoker;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.services.Lookup;
|
||||
import org.apache.maven.internal.impl.DefaultLookup;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
|
@ -43,6 +45,11 @@ public class PlexusContainerCapsule implements ContainerCapsule {
|
|||
return lookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ClassLoader> currentThreadClassLoader() {
|
||||
return Optional.of(plexusContainer.getContainerRealm());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.apache.maven.api.Constants;
|
|||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Logger;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.api.services.SettingsBuilder;
|
||||
|
@ -65,28 +64,26 @@ import static org.apache.maven.cling.invoker.Utils.toPlexusLoggingLevel;
|
|||
/**
|
||||
* Container capsule backed by Plexus Container.
|
||||
*
|
||||
* @param <O> the options type
|
||||
* @param <R> the invoker request type
|
||||
* @param <C> the invoker context type
|
||||
* @param <C> The context type.
|
||||
*/
|
||||
public class PlexusContainerCapsuleFactory<
|
||||
O extends Options, R extends InvokerRequest<O>, C extends LookupInvoker.LookupInvokerContext<O, R, C>>
|
||||
implements ContainerCapsuleFactory<O, R, C> {
|
||||
public class PlexusContainerCapsuleFactory<C extends LookupContext> implements ContainerCapsuleFactory<C> {
|
||||
@Override
|
||||
public ContainerCapsule createContainerCapsule(C context) throws InvokerException {
|
||||
public ContainerCapsule createContainerCapsule(LookupInvoker<C> invoker, C context) throws InvokerException {
|
||||
try {
|
||||
return new PlexusContainerCapsule(Thread.currentThread().getContextClassLoader(), container(context));
|
||||
return new PlexusContainerCapsule(
|
||||
Thread.currentThread().getContextClassLoader(), container(invoker, context));
|
||||
} catch (Exception e) {
|
||||
throw new InvokerException("Failed to create plexus container capsule", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected PlexusContainer container(C context) throws Exception {
|
||||
ClassWorld classWorld = context.protoLookup.lookup(ClassWorld.class);
|
||||
protected PlexusContainer container(LookupInvoker<C> invoker, C context) throws Exception {
|
||||
ClassWorld classWorld = invoker.protoLookup.lookup(ClassWorld.class);
|
||||
ClassRealm coreRealm = classWorld.getClassRealm("plexus.core");
|
||||
List<Path> extClassPath = parseExtClasspath(context);
|
||||
CoreExtensionEntry coreEntry = CoreExtensionEntry.discoverFrom(coreRealm);
|
||||
List<CoreExtensionEntry> extensions = loadCoreExtensions(context, coreRealm, coreEntry.getExportedArtifacts());
|
||||
List<CoreExtensionEntry> extensions =
|
||||
loadCoreExtensions(invoker, context, coreRealm, coreEntry.getExportedArtifacts());
|
||||
ClassRealm containerRealm =
|
||||
setupContainerRealm(context.logger, classWorld, coreRealm, extClassPath, extensions);
|
||||
ContainerConfiguration cc = new DefaultContainerConfiguration()
|
||||
|
@ -108,11 +105,10 @@ public class PlexusContainerCapsuleFactory<
|
|||
|
||||
// NOTE: To avoid inconsistencies, we'll use the TCCL exclusively for lookups
|
||||
container.setLookupRealm(null);
|
||||
context.currentThreadContextClassLoader = container.getContainerRealm();
|
||||
Thread.currentThread().setContextClassLoader(container.getContainerRealm());
|
||||
|
||||
container.setLoggerManager(createLoggerManager());
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
Function<String, String> extensionSource = expression -> {
|
||||
String value = invokerRequest.userProperties().get(expression);
|
||||
if (value == null) {
|
||||
|
@ -193,7 +189,7 @@ public class PlexusContainerCapsuleFactory<
|
|||
protected void customizeContainer(C context, PlexusContainer container) throws Exception {}
|
||||
|
||||
protected List<Path> parseExtClasspath(C context) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
String extClassPath = invokerRequest.userProperties().get(Constants.MAVEN_EXT_CLASS_PATH);
|
||||
if (extClassPath == null) {
|
||||
extClassPath = invokerRequest.systemProperties().get(Constants.MAVEN_EXT_CLASS_PATH);
|
||||
|
@ -255,8 +251,9 @@ public class PlexusContainerCapsuleFactory<
|
|||
}
|
||||
|
||||
protected List<CoreExtensionEntry> loadCoreExtensions(
|
||||
C context, ClassRealm containerRealm, Set<String> providedArtifacts) throws Exception {
|
||||
R invokerRequest = context.invokerRequest;
|
||||
LookupInvoker<C> invoker, C context, ClassRealm containerRealm, Set<String> providedArtifacts)
|
||||
throws Exception {
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
if (invokerRequest.coreExtensions().isEmpty()
|
||||
|| invokerRequest.coreExtensions().get().isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
|
@ -286,10 +283,10 @@ public class PlexusContainerCapsuleFactory<
|
|||
container.getLoggerManager().setThresholds(toPlexusLoggingLevel(context.loggerLevel));
|
||||
Thread.currentThread().setContextClassLoader(container.getContainerRealm());
|
||||
|
||||
context.invoker.settings(context, container.lookup(SettingsBuilder.class));
|
||||
invoker.settings(context, container.lookup(SettingsBuilder.class));
|
||||
|
||||
MavenExecutionRequest mer = new DefaultMavenExecutionRequest();
|
||||
context.invoker.populateRequest(context, mer);
|
||||
invoker.populateRequest(context, mer);
|
||||
mer = container.lookup(MavenExecutionRequestPopulator.class).populateDefaults(mer);
|
||||
return Collections.unmodifiableList(container
|
||||
.lookup(BootstrapCoreExtensionManager.class)
|
||||
|
|
|
@ -61,7 +61,7 @@ public class ProtoLogger implements Logger {
|
|||
public void log(Level level, String message, Throwable error) {
|
||||
PrintWriter pw = level == Level.ERROR ? err : level == Level.WARN ? out : null;
|
||||
if (pw != null) {
|
||||
pw.print(level.name() + " " + message);
|
||||
pw.println(level.name() + " " + message);
|
||||
if (error != null) {
|
||||
error.printStackTrace(pw);
|
||||
}
|
||||
|
|
|
@ -1,62 +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.cling.invoker.mvn;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.MavenParser;
|
||||
|
||||
public class DefaultMavenParser extends BaseMavenParser<MavenOptions, MavenInvokerRequest<MavenOptions>>
|
||||
implements MavenParser<MavenInvokerRequest<MavenOptions>> {
|
||||
@Override
|
||||
protected DefaultMavenInvokerRequest<MavenOptions> getInvokerRequest(LocalContext context) {
|
||||
return new DefaultMavenInvokerRequest<>(
|
||||
context.parserRequest,
|
||||
context.cwd,
|
||||
context.installationDirectory,
|
||||
context.userHomeDirectory,
|
||||
context.userProperties,
|
||||
context.systemProperties,
|
||||
context.topDirectory,
|
||||
context.rootDirectory,
|
||||
context.parserRequest.in(),
|
||||
context.parserRequest.out(),
|
||||
context.parserRequest.err(),
|
||||
context.extensions,
|
||||
(MavenOptions) context.options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MavenOptions parseArgs(String source, List<String> args) throws ParserException {
|
||||
try {
|
||||
return CommonsCliMavenOptions.parse(source, args.toArray(new String[0]));
|
||||
} catch (ParseException e) {
|
||||
throw new ParserException("Failed to parse source " + source + ": " + e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MavenOptions assembleOptions(List<MavenOptions> parsedOptions) {
|
||||
return LayeredMavenOptions.layerMavenOptions(parsedOptions);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn;
|
||||
|
||||
import org.apache.maven.Maven;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.services.model.ModelProcessor;
|
||||
import org.apache.maven.cling.invoker.LookupContext;
|
||||
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenExecutionRequestPopulator;
|
||||
import org.apache.maven.logging.BuildEventListener;
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public class MavenContext extends LookupContext {
|
||||
public MavenContext(InvokerRequest invokerRequest) {
|
||||
super(invokerRequest);
|
||||
}
|
||||
|
||||
public BuildEventListener buildEventListener;
|
||||
public MavenExecutionRequest mavenExecutionRequest;
|
||||
public EventSpyDispatcher eventSpyDispatcher;
|
||||
public MavenExecutionRequestPopulator mavenExecutionRequestPopulator;
|
||||
public ModelProcessor modelProcessor;
|
||||
public Maven maven;
|
||||
}
|
|
@ -34,9 +34,8 @@ import java.util.regex.Pattern;
|
|||
import org.apache.maven.InternalErrorException;
|
||||
import org.apache.maven.Maven;
|
||||
import org.apache.maven.api.Constants;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.Logger;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvoker;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.services.BuilderProblem;
|
||||
import org.apache.maven.api.services.SettingsBuilderRequest;
|
||||
|
@ -77,32 +76,13 @@ import org.eclipse.aether.transfer.TransferListener;
|
|||
import static java.util.Comparator.comparing;
|
||||
import static org.apache.maven.cling.invoker.Utils.toProperties;
|
||||
|
||||
public abstract class DefaultMavenInvoker<
|
||||
O extends MavenOptions,
|
||||
R extends MavenInvokerRequest<O>,
|
||||
C extends DefaultMavenInvoker.MavenContext<O, R, C>>
|
||||
extends LookupInvoker<O, R, C> implements MavenInvoker<R> {
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public static class MavenContext<
|
||||
O extends MavenOptions,
|
||||
R extends MavenInvokerRequest<O>,
|
||||
C extends DefaultMavenInvoker.MavenContext<O, R, C>>
|
||||
extends LookupInvokerContext<O, R, C> {
|
||||
protected MavenContext(DefaultMavenInvoker<O, R, C> invoker, R invokerRequest) {
|
||||
super(invoker, invokerRequest);
|
||||
}
|
||||
|
||||
public BuildEventListener buildEventListener;
|
||||
public MavenExecutionRequest mavenExecutionRequest;
|
||||
public EventSpyDispatcher eventSpyDispatcher;
|
||||
public MavenExecutionRequestPopulator mavenExecutionRequestPopulator;
|
||||
public ToolchainsBuilder toolchainsBuilder;
|
||||
public ModelProcessor modelProcessor;
|
||||
public Maven maven;
|
||||
}
|
||||
|
||||
public DefaultMavenInvoker(ProtoLookup protoLookup) {
|
||||
/**
|
||||
* The "local" Maven invoker, that expects whole Maven on classpath and invokes it.
|
||||
*
|
||||
* @param <C> The context type.
|
||||
*/
|
||||
public abstract class MavenInvoker<C extends MavenContext> extends LookupInvoker<C> {
|
||||
public MavenInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
}
|
||||
|
||||
|
@ -136,14 +116,13 @@ public abstract class DefaultMavenInvoker<
|
|||
protected void lookup(C context) throws Exception {
|
||||
context.eventSpyDispatcher = context.lookup.lookup(EventSpyDispatcher.class);
|
||||
context.mavenExecutionRequestPopulator = context.lookup.lookup(MavenExecutionRequestPopulator.class);
|
||||
context.toolchainsBuilder = context.lookup.lookup(ToolchainsBuilder.class);
|
||||
context.modelProcessor = context.lookup.lookup(ModelProcessor.class);
|
||||
context.maven = context.lookup.lookup(Maven.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(C context) throws Exception {
|
||||
MavenInvokerRequest<O> invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("plexus", context.lookup.lookup(PlexusContainer.class));
|
||||
data.put("workingDirectory", invokerRequest.cwd().toString());
|
||||
|
@ -157,11 +136,12 @@ public abstract class DefaultMavenInvoker<
|
|||
protected void postCommands(C context) throws Exception {
|
||||
super.postCommands(context);
|
||||
|
||||
R invokerRequest = context.invokerRequest;
|
||||
InvokerRequest invokerRequest = context.invokerRequest;
|
||||
MavenOptions options = (MavenOptions) invokerRequest.options();
|
||||
Logger logger = context.logger;
|
||||
if (invokerRequest.options().relaxedChecksums().orElse(false)) {
|
||||
if (options.relaxedChecksums().orElse(false)) {
|
||||
logger.info("Disabling strict checksum verification on all artifact downloads.");
|
||||
} else if (invokerRequest.options().strictChecksums().orElse(false)) {
|
||||
} else if (options.strictChecksums().orElse(false)) {
|
||||
logger.info("Enabling strict checksum verification on all artifact downloads.");
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +240,8 @@ public abstract class DefaultMavenInvoker<
|
|||
context.logger.debug("Reading installation toolchains from '" + installationToolchainsFile + "'");
|
||||
context.logger.debug("Reading user toolchains from '" + userToolchainsFile + "'");
|
||||
|
||||
ToolchainsBuilderResult toolchainsResult = context.toolchainsBuilder.build(toolchainsRequest);
|
||||
ToolchainsBuilderResult toolchainsResult =
|
||||
context.lookup.lookup(ToolchainsBuilder.class).build(toolchainsRequest);
|
||||
|
||||
context.eventSpyDispatcher.onEvent(toolchainsResult);
|
||||
|
||||
|
@ -290,7 +271,7 @@ public abstract class DefaultMavenInvoker<
|
|||
request.setRootDirectory(context.invokerRequest.topDirectory());
|
||||
}
|
||||
|
||||
MavenOptions options = context.invokerRequest.options();
|
||||
MavenOptions options = (MavenOptions) context.invokerRequest.options();
|
||||
request.setNoSnapshotUpdates(options.suppressSnapshotUpdates().orElse(false));
|
||||
request.setGoals(options.goals().orElse(List.of()));
|
||||
request.setReactorFailureBehavior(determineReactorFailureBehaviour(context));
|
||||
|
@ -346,9 +327,9 @@ public abstract class DefaultMavenInvoker<
|
|||
// parameters but this is sufficient for now. Ultimately we want components like Builders to provide a way to
|
||||
// extend the command line to accept its own configuration parameters.
|
||||
//
|
||||
if (context.invokerRequest.options().threads().isPresent()) {
|
||||
int degreeOfConcurrency = calculateDegreeOfConcurrency(
|
||||
context.invokerRequest.options().threads().get());
|
||||
if (options.threads().isPresent()) {
|
||||
int degreeOfConcurrency =
|
||||
calculateDegreeOfConcurrency(options.threads().get());
|
||||
if (degreeOfConcurrency > 1) {
|
||||
request.setBuilderId("multithreaded");
|
||||
request.setDegreeOfConcurrency(degreeOfConcurrency);
|
||||
|
@ -358,16 +339,16 @@ public abstract class DefaultMavenInvoker<
|
|||
//
|
||||
// Allow the builder to be overridden by the user if requested. The builders are now pluggable.
|
||||
//
|
||||
if (context.invokerRequest.options().builder().isPresent()) {
|
||||
request.setBuilderId(context.invokerRequest.options().builder().get());
|
||||
if (options.builder().isPresent()) {
|
||||
request.setBuilderId(options.builder().get());
|
||||
}
|
||||
}
|
||||
|
||||
protected Path determinePom(C context) {
|
||||
Path current = context.invokerRequest.cwd();
|
||||
if (context.invokerRequest.options().alternatePomFile().isPresent()) {
|
||||
current = context.cwdResolver.apply(
|
||||
context.invokerRequest.options().alternatePomFile().get());
|
||||
MavenOptions options = (MavenOptions) context.invokerRequest.options();
|
||||
if (options.alternatePomFile().isPresent()) {
|
||||
current = context.cwdResolver.apply(options.alternatePomFile().get());
|
||||
}
|
||||
if (context.modelProcessor != null) {
|
||||
return context.modelProcessor.locateExistingPom(current);
|
||||
|
@ -377,7 +358,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
|
||||
protected String determineReactorFailureBehaviour(C context) {
|
||||
MavenOptions mavenOptions = context.invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) context.invokerRequest.options();
|
||||
if (mavenOptions.failFast().isPresent()) {
|
||||
return MavenExecutionRequest.REACTOR_FAIL_FAST;
|
||||
} else if (mavenOptions.failAtEnd().isPresent()) {
|
||||
|
@ -390,7 +371,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
|
||||
protected String determineGlobalChecksumPolicy(C context) {
|
||||
MavenOptions mavenOptions = context.invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) context.invokerRequest.options();
|
||||
if (mavenOptions.strictChecksums().orElse(false)) {
|
||||
return MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
|
||||
} else if (mavenOptions.relaxedChecksums().orElse(false)) {
|
||||
|
@ -415,7 +396,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
|
||||
protected String determineMakeBehavior(C context) {
|
||||
MavenOptions mavenOptions = context.invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) context.invokerRequest.options();
|
||||
if (mavenOptions.alsoMake().isPresent()
|
||||
&& mavenOptions.alsoMakeDependents().isEmpty()) {
|
||||
return MavenExecutionRequest.REACTOR_MAKE_UPSTREAM;
|
||||
|
@ -431,7 +412,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
|
||||
protected void performProjectActivation(C context, ProjectActivation projectActivation) {
|
||||
MavenOptions mavenOptions = context.invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) context.invokerRequest.options();
|
||||
if (mavenOptions.projects().isPresent()
|
||||
&& !mavenOptions.projects().get().isEmpty()) {
|
||||
List<String> optionValues = mavenOptions.projects().get();
|
||||
|
@ -459,7 +440,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
|
||||
protected void performProfileActivation(C context, ProfileActivation profileActivation) {
|
||||
MavenOptions mavenOptions = context.invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) context.invokerRequest.options();
|
||||
if (mavenOptions.activatedProfiles().isPresent()
|
||||
&& !mavenOptions.activatedProfiles().get().isEmpty()) {
|
||||
List<String> optionValues = mavenOptions.activatedProfiles().get();
|
||||
|
@ -549,7 +530,7 @@ public abstract class DefaultMavenInvoker<
|
|||
}
|
||||
}
|
||||
|
||||
if (context.invokerRequest.options().failNever().orElse(false)) {
|
||||
if (((MavenOptions) context.invokerRequest.options()).failNever().orElse(false)) {
|
||||
context.logger.info("Build failures were ignored.");
|
||||
return 0;
|
||||
} else {
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
|||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.cling.invoker.BaseInvokerRequest;
|
||||
|
||||
|
@ -35,15 +34,12 @@ import static java.util.Objects.requireNonNull;
|
|||
|
||||
/**
|
||||
* Maven execution request.
|
||||
*
|
||||
* @param <O> the options type this request carries
|
||||
*/
|
||||
public class DefaultMavenInvokerRequest<O extends MavenOptions> extends BaseInvokerRequest<O>
|
||||
implements MavenInvokerRequest<O> {
|
||||
private final O options;
|
||||
public class MavenInvokerRequest extends BaseInvokerRequest {
|
||||
private final MavenOptions options;
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
public DefaultMavenInvokerRequest(
|
||||
public MavenInvokerRequest(
|
||||
ParserRequest parserRequest,
|
||||
Path cwd,
|
||||
Path installationDirectory,
|
||||
|
@ -56,7 +52,8 @@ public class DefaultMavenInvokerRequest<O extends MavenOptions> extends BaseInvo
|
|||
OutputStream out,
|
||||
OutputStream err,
|
||||
List<CoreExtension> coreExtensions,
|
||||
O options) {
|
||||
List<String> jvmArguments,
|
||||
MavenOptions options) {
|
||||
super(
|
||||
parserRequest,
|
||||
cwd,
|
||||
|
@ -69,7 +66,8 @@ public class DefaultMavenInvokerRequest<O extends MavenOptions> extends BaseInvo
|
|||
in,
|
||||
out,
|
||||
err,
|
||||
coreExtensions);
|
||||
coreExtensions,
|
||||
jvmArguments);
|
||||
this.options = requireNonNull(options);
|
||||
}
|
||||
|
||||
|
@ -77,7 +75,7 @@ public class DefaultMavenInvokerRequest<O extends MavenOptions> extends BaseInvo
|
|||
* The mandatory Maven options.
|
||||
*/
|
||||
@Nonnull
|
||||
public O options() {
|
||||
public MavenOptions options() {
|
||||
return options;
|
||||
}
|
||||
}
|
|
@ -26,19 +26,17 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.MavenParser;
|
||||
import org.apache.maven.cling.invoker.BaseParser;
|
||||
|
||||
public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInvokerRequest<O>> extends BaseParser<O, R>
|
||||
implements MavenParser<R> {
|
||||
public class MavenParser extends BaseParser {
|
||||
|
||||
@Override
|
||||
protected List<O> parseCliOptions(LocalContext context) throws ParserException, IOException {
|
||||
ArrayList<O> result = new ArrayList<>();
|
||||
protected List<Options> parseCliOptions(LocalContext context) throws ParserException, IOException {
|
||||
ArrayList<Options> result = new ArrayList<>();
|
||||
// CLI args
|
||||
result.add(parseMavenCliOptions(context.parserRequest.args()));
|
||||
// maven.config; if exists
|
||||
|
@ -49,15 +47,15 @@ public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInv
|
|||
return result;
|
||||
}
|
||||
|
||||
protected O parseMavenCliOptions(List<String> args) throws ParserException {
|
||||
protected MavenOptions parseMavenCliOptions(List<String> args) throws ParserException {
|
||||
return parseArgs(Options.SOURCE_CLI, args);
|
||||
}
|
||||
|
||||
protected O parseMavenConfigOptions(Path configFile) throws ParserException, IOException {
|
||||
protected MavenOptions parseMavenConfigOptions(Path configFile) throws ParserException, IOException {
|
||||
try (Stream<String> lines = Files.lines(configFile, Charset.defaultCharset())) {
|
||||
List<String> args =
|
||||
lines.filter(arg -> !arg.isEmpty() && !arg.startsWith("#")).toList();
|
||||
O options = parseArgs("maven.config", args);
|
||||
MavenOptions options = parseArgs("maven.config", args);
|
||||
if (options.goals().isPresent()) {
|
||||
// This file can only contain options, not args (goals or phases)
|
||||
throw new ParserException("Unrecognized maven.config file entries: "
|
||||
|
@ -67,5 +65,36 @@ public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInv
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract O parseArgs(String source, List<String> args) throws ParserException;
|
||||
protected MavenOptions parseArgs(String source, List<String> args) throws ParserException {
|
||||
try {
|
||||
return CommonsCliMavenOptions.parse(source, args.toArray(new String[0]));
|
||||
} catch (ParseException e) {
|
||||
throw new ParserException("Failed to parse source " + source + ": " + e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MavenInvokerRequest getInvokerRequest(LocalContext context) {
|
||||
return new MavenInvokerRequest(
|
||||
context.parserRequest,
|
||||
context.cwd,
|
||||
context.installationDirectory,
|
||||
context.userHomeDirectory,
|
||||
context.userProperties,
|
||||
context.systemProperties,
|
||||
context.topDirectory,
|
||||
context.rootDirectory,
|
||||
context.parserRequest.in(),
|
||||
context.parserRequest.out(),
|
||||
context.parserRequest.err(),
|
||||
context.extensions,
|
||||
getJvmArguments(context.rootDirectory),
|
||||
(MavenOptions) context.options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected MavenOptions assembleOptions(List<Options> parsedOptions) {
|
||||
return LayeredMavenOptions.layerMavenOptions((List) parsedOptions);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn.embedded;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.api.cli.Executor;
|
||||
import org.apache.maven.api.cli.ExecutorException;
|
||||
import org.apache.maven.api.cli.ExecutorRequest;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Embedded executor implementation, that invokes Maven from installation directory within this same JVM but in isolated
|
||||
* classloader. This class supports Maven 4.x and Maven 3.x as well.
|
||||
* The class world with Maven is kept in memory as long as instance of this class is not closed. Subsequent execution
|
||||
* requests over same installation home are cached.
|
||||
*/
|
||||
public class EmbeddedMavenExecutor implements Executor {
|
||||
protected static final class Context {
|
||||
private final Properties properties;
|
||||
private final URLClassLoader bootClassLoader;
|
||||
private final String version;
|
||||
private final Object classWorld;
|
||||
private final ClassLoader tccl;
|
||||
private final Function<ExecutorRequest, Integer> exec;
|
||||
|
||||
public Context(
|
||||
Properties properties,
|
||||
URLClassLoader bootClassLoader,
|
||||
String version,
|
||||
Object classWorld,
|
||||
ClassLoader tccl,
|
||||
Function<ExecutorRequest, Integer> exec) {
|
||||
this.properties = properties;
|
||||
this.bootClassLoader = bootClassLoader;
|
||||
this.version = version;
|
||||
this.classWorld = classWorld;
|
||||
this.tccl = tccl;
|
||||
this.exec = exec;
|
||||
}
|
||||
}
|
||||
|
||||
private final Properties originalProperties;
|
||||
private final ClassLoader originalClassLoader;
|
||||
private final ConcurrentHashMap<Path, Context> contexts;
|
||||
|
||||
public EmbeddedMavenExecutor() {
|
||||
this.originalClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
this.contexts = new ConcurrentHashMap<>();
|
||||
this.originalProperties = System.getProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int execute(ExecutorRequest executorRequest) throws ExecutorException {
|
||||
requireNonNull(executorRequest);
|
||||
validate(executorRequest);
|
||||
Context context = mayCreate(executorRequest);
|
||||
|
||||
System.setProperties(context.properties);
|
||||
Thread.currentThread().setContextClassLoader(context.tccl);
|
||||
try {
|
||||
return context.exec.apply(executorRequest);
|
||||
} catch (Exception e) {
|
||||
throw new ExecutorException("Failed to execute", e);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
System.setProperties(originalProperties);
|
||||
}
|
||||
}
|
||||
|
||||
protected Context mayCreate(ExecutorRequest executorRequest) {
|
||||
Path installation = executorRequest.installationDirectory();
|
||||
if (!Files.isDirectory(installation)) {
|
||||
throw new IllegalArgumentException("Installation directory must point to existing directory");
|
||||
}
|
||||
return contexts.computeIfAbsent(installation, k -> {
|
||||
Path mavenHome = installation.toAbsolutePath().normalize();
|
||||
Path boot = mavenHome.resolve("boot");
|
||||
Path m2conf = mavenHome.resolve("bin/m2.conf");
|
||||
if (!Files.isDirectory(boot) || !Files.isRegularFile(m2conf)) {
|
||||
throw new IllegalArgumentException("Installation directory does not point to Maven installation");
|
||||
}
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(System.getProperties());
|
||||
properties.put(
|
||||
"user.dir",
|
||||
executorRequest.cwd().toAbsolutePath().normalize().toString());
|
||||
properties.put(
|
||||
"maven.multiModuleProjectDirectory",
|
||||
executorRequest.cwd().toAbsolutePath().normalize().toString());
|
||||
properties.put(
|
||||
"user.home",
|
||||
executorRequest
|
||||
.userHomeDirectory()
|
||||
.toAbsolutePath()
|
||||
.normalize()
|
||||
.toString());
|
||||
properties.put("maven.home", mavenHome.toString());
|
||||
properties.put("maven.mainClass", "org.apache.maven.cling.MavenCling");
|
||||
properties.put(
|
||||
"library.jline.path", mavenHome.resolve("lib/jline-native").toString());
|
||||
|
||||
System.setProperties(properties);
|
||||
URLClassLoader bootClassLoader = createMavenBootClassLoader(boot, Collections.emptyList());
|
||||
Thread.currentThread().setContextClassLoader(bootClassLoader);
|
||||
try {
|
||||
Class<?> launcherClass = bootClassLoader.loadClass("org.codehaus.plexus.classworlds.launcher.Launcher");
|
||||
Object launcher = launcherClass.getDeclaredConstructor().newInstance();
|
||||
Method configure = launcherClass.getMethod("configure", InputStream.class);
|
||||
try (InputStream inputStream = Files.newInputStream(m2conf)) {
|
||||
configure.invoke(launcher, inputStream);
|
||||
}
|
||||
Object classWorld = launcherClass.getMethod("getWorld").invoke(launcher);
|
||||
Class<?> cliClass =
|
||||
(Class<?>) launcherClass.getMethod("getMainClass").invoke(launcher);
|
||||
String version = getMavenVersion(cliClass.getClassLoader());
|
||||
Function<ExecutorRequest, Integer> exec;
|
||||
|
||||
if (version.startsWith("3.")) {
|
||||
// 3.x
|
||||
Constructor<?> newMavenCli = cliClass.getConstructor(classWorld.getClass());
|
||||
Object mavenCli = newMavenCli.newInstance(classWorld);
|
||||
Class<?>[] parameterTypes = {String[].class, String.class, PrintStream.class, PrintStream.class};
|
||||
Method doMain = cliClass.getMethod("doMain", parameterTypes);
|
||||
exec = r -> {
|
||||
try {
|
||||
return (int) doMain.invoke(mavenCli, new Object[] {
|
||||
r.parserRequest().args().toArray(new String[0]),
|
||||
r.cwd().toString(),
|
||||
null,
|
||||
null
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new ExecutorException("Failed to execute", e);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// assume 4.x
|
||||
Method mainMethod = cliClass.getMethod("main", String[].class, classWorld.getClass());
|
||||
exec = r -> {
|
||||
try {
|
||||
return (int) mainMethod.invoke(
|
||||
null, r.parserRequest().args().toArray(new String[0]), classWorld);
|
||||
} catch (Exception e) {
|
||||
throw new ExecutorException("Failed to execute", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new Context(properties, bootClassLoader, version, classWorld, cliClass.getClassLoader(), exec);
|
||||
} catch (Exception e) {
|
||||
throw new ExecutorException("Failed to create executor", e);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
System.setProperties(originalProperties);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws ExecutorException {
|
||||
try {
|
||||
ArrayList<Exception> exceptions = new ArrayList<>();
|
||||
for (Context context : contexts.values()) {
|
||||
try {
|
||||
doClose(context);
|
||||
} catch (Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
if (!exceptions.isEmpty()) {
|
||||
ExecutorException e = new ExecutorException("Could not close cleanly");
|
||||
exceptions.forEach(e::addSuppressed);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
System.setProperties(originalProperties);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doClose(Context context) throws Exception {
|
||||
Thread.currentThread().setContextClassLoader(context.bootClassLoader);
|
||||
try {
|
||||
try {
|
||||
((Closeable) context.classWorld).close();
|
||||
} finally {
|
||||
context.bootClassLoader.close();
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(originalClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validate(ExecutorRequest executorRequest) throws ExecutorException {}
|
||||
|
||||
protected URLClassLoader createMavenBootClassLoader(Path boot, List<URL> extraClasspath) {
|
||||
ArrayList<URL> urls = new ArrayList<>(extraClasspath);
|
||||
try (Stream<Path> stream = Files.list(boot)) {
|
||||
stream.filter(Files::isRegularFile)
|
||||
.filter(p -> p.toString().endsWith(".jar"))
|
||||
.forEach(f -> {
|
||||
try {
|
||||
urls.add(f.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ExecutorException("Failed to build classpath: " + f, e);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new ExecutorException("Failed to build classpath: " + e, e);
|
||||
}
|
||||
if (urls.isEmpty()) {
|
||||
throw new IllegalArgumentException("Invalid Maven home directory; boot is empty");
|
||||
}
|
||||
return new URLClassLoader(
|
||||
urls.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent());
|
||||
}
|
||||
|
||||
public String getMavenVersion(ClassLoader classLoader) throws IOException {
|
||||
Properties props = new Properties();
|
||||
try (InputStream is =
|
||||
classLoader.getResourceAsStream("/META-INF/maven/org.apache.maven/maven-core/pom.properties")) {
|
||||
if (is != null) {
|
||||
props.load(is);
|
||||
}
|
||||
String version = props.getProperty("version");
|
||||
if (version != null) {
|
||||
return version;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,78 +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.cling.invoker.mvn.forked;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenInvokerRequest;
|
||||
|
||||
/**
|
||||
* Maven execution request.
|
||||
*/
|
||||
public class DefaultForkedMavenInvokerRequest extends DefaultMavenInvokerRequest<MavenOptions>
|
||||
implements ForkedMavenInvokerRequest {
|
||||
private final List<String> jvmArguments;
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
public DefaultForkedMavenInvokerRequest(
|
||||
ParserRequest parserRequest,
|
||||
Path cwd,
|
||||
Path installationDirectory,
|
||||
Path userHomeDirectory,
|
||||
Map<String, String> userProperties,
|
||||
Map<String, String> systemProperties,
|
||||
Path topDirectory,
|
||||
Path rootDirectory,
|
||||
InputStream in,
|
||||
OutputStream out,
|
||||
OutputStream err,
|
||||
List<CoreExtension> coreExtensions,
|
||||
List<String> jvmArguments,
|
||||
MavenOptions options) {
|
||||
super(
|
||||
parserRequest,
|
||||
cwd,
|
||||
installationDirectory,
|
||||
userHomeDirectory,
|
||||
userProperties,
|
||||
systemProperties,
|
||||
topDirectory,
|
||||
rootDirectory,
|
||||
in,
|
||||
out,
|
||||
err,
|
||||
coreExtensions,
|
||||
options);
|
||||
this.jvmArguments = jvmArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> jvmArguments() {
|
||||
return Optional.ofNullable(jvmArguments);
|
||||
}
|
||||
}
|
|
@ -1,96 +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.cling.invoker.mvn.forked;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.BaseMavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.CommonsCliMavenOptions;
|
||||
import org.apache.maven.cling.invoker.mvn.LayeredMavenOptions;
|
||||
|
||||
/**
|
||||
* Forked invoker that invokes Maven in a child process.
|
||||
*/
|
||||
public class DefaultForkedMavenParser extends BaseMavenParser<MavenOptions, ForkedMavenInvokerRequest>
|
||||
implements ForkedMavenParser {
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
@Override
|
||||
protected ForkedMavenInvokerRequest getInvokerRequest(LocalContext context) {
|
||||
return new DefaultForkedMavenInvokerRequest(
|
||||
context.parserRequest,
|
||||
context.cwd,
|
||||
context.installationDirectory,
|
||||
context.userHomeDirectory,
|
||||
context.userProperties,
|
||||
context.systemProperties,
|
||||
context.topDirectory,
|
||||
context.rootDirectory,
|
||||
context.parserRequest.in(),
|
||||
context.parserRequest.out(),
|
||||
context.parserRequest.err(),
|
||||
context.extensions,
|
||||
getJvmArguments(context.rootDirectory),
|
||||
(MavenOptions) context.options);
|
||||
}
|
||||
|
||||
protected List<String> getJvmArguments(Path rootDirectory) {
|
||||
if (rootDirectory != null) {
|
||||
Path jvmConfig = rootDirectory.resolve(".mvn/jvm.config");
|
||||
if (Files.exists(jvmConfig)) {
|
||||
try {
|
||||
return Files.readAllLines(jvmConfig).stream()
|
||||
.filter(l -> !l.isBlank() && !l.startsWith("#"))
|
||||
.flatMap(l -> Arrays.stream(l.split(" ")))
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: same is in DefaultMavenParser!!! (duplication)
|
||||
@Override
|
||||
protected MavenOptions parseArgs(String source, List<String> args) throws ParserException {
|
||||
try {
|
||||
return CommonsCliMavenOptions.parse(source, args.toArray(new String[0]));
|
||||
} catch (ParseException e) {
|
||||
throw new ParserException("Failed to parse source " + source, e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: same is in DefaultMavenParser!!! (duplication)
|
||||
@Override
|
||||
protected MavenOptions assembleOptions(List<MavenOptions> parsedOptions) {
|
||||
return LayeredMavenOptions.layerMavenOptions(parsedOptions);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn.forked;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.maven.api.cli.Executor;
|
||||
import org.apache.maven.api.cli.ExecutorException;
|
||||
import org.apache.maven.api.cli.ExecutorRequest;
|
||||
import org.apache.maven.internal.impl.model.profile.Os;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Forked executor implementation, that spawns a subprocess with Maven from the installation directory.
|
||||
*/
|
||||
public class ForkedMavenExecutor implements Executor {
|
||||
@Override
|
||||
public int execute(ExecutorRequest executorRequest) throws ExecutorException {
|
||||
requireNonNull(executorRequest);
|
||||
validate(executorRequest);
|
||||
|
||||
ArrayList<String> cmdAndArguments = new ArrayList<>();
|
||||
cmdAndArguments.add(executorRequest
|
||||
.installationDirectory()
|
||||
.resolve("bin")
|
||||
.resolve(
|
||||
Os.IS_WINDOWS
|
||||
? executorRequest.parserRequest().command() + ".cmd"
|
||||
: executorRequest.parserRequest().command())
|
||||
.toString());
|
||||
|
||||
cmdAndArguments.addAll(executorRequest.parserRequest().args());
|
||||
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder()
|
||||
.directory(executorRequest.cwd().toFile())
|
||||
.command(cmdAndArguments);
|
||||
|
||||
if (executorRequest.jvmArguments().isPresent()) {
|
||||
pb.environment()
|
||||
.put(
|
||||
"MAVEN_OPTS",
|
||||
String.join(" ", executorRequest.jvmArguments().get()));
|
||||
}
|
||||
|
||||
return pb.start().waitFor();
|
||||
} catch (IOException e) {
|
||||
throw new ExecutorException("IO problem while executing command: " + cmdAndArguments, e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ExecutorException("Interrupted while executing command: " + cmdAndArguments, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validate(ExecutorRequest executorRequest) throws ExecutorException {}
|
||||
}
|
|
@ -23,21 +23,21 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvoker;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest;
|
||||
import org.apache.maven.internal.impl.model.profile.Os;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Forked invoker implementation, it spawns a subprocess with Maven.
|
||||
* Forked invoker implementation, that spawns a subprocess with Maven from the installation directory.
|
||||
*/
|
||||
public class DefaultForkedMavenInvoker implements ForkedMavenInvoker {
|
||||
public class ForkedMavenInvoker implements Invoker {
|
||||
@SuppressWarnings("MethodLength")
|
||||
@Override
|
||||
public int invoke(ForkedMavenInvokerRequest invokerRequest) throws InvokerException {
|
||||
public int invoke(InvokerRequest invokerRequest) throws InvokerException {
|
||||
requireNonNull(invokerRequest);
|
||||
validate(invokerRequest);
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class DefaultForkedMavenInvoker implements ForkedMavenInvoker {
|
|||
: invokerRequest.parserRequest().command())
|
||||
.toString());
|
||||
|
||||
MavenOptions mavenOptions = invokerRequest.options();
|
||||
MavenOptions mavenOptions = (MavenOptions) invokerRequest.options();
|
||||
if (mavenOptions.userProperties().isPresent()) {
|
||||
for (Map.Entry<String, String> entry :
|
||||
mavenOptions.userProperties().get().entrySet()) {
|
||||
|
@ -216,5 +216,5 @@ public class DefaultForkedMavenInvoker implements ForkedMavenInvoker {
|
|||
}
|
||||
}
|
||||
|
||||
protected void validate(ForkedMavenInvokerRequest invokerRequest) throws InvokerException {}
|
||||
protected void validate(InvokerRequest invokerRequest) throws InvokerException {}
|
||||
}
|
|
@ -1,54 +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.cling.invoker.mvn.local;
|
||||
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.local.LocalMavenInvoker;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenInvoker;
|
||||
|
||||
/**
|
||||
* Local invoker implementation, when Maven CLI is being run. System uses ClassWorld launcher, and class world
|
||||
* instance is passed in via "enhanced" main method. Hence, this class expects fully setup ClassWorld via constructor.
|
||||
*
|
||||
* @see org.apache.maven.cling.MavenCling
|
||||
*/
|
||||
public class DefaultLocalMavenInvoker
|
||||
extends DefaultMavenInvoker<
|
||||
MavenOptions, MavenInvokerRequest<MavenOptions>, DefaultLocalMavenInvoker.LocalContext>
|
||||
implements LocalMavenInvoker {
|
||||
|
||||
public static class LocalContext
|
||||
extends DefaultMavenInvoker.MavenContext<
|
||||
MavenOptions, MavenInvokerRequest<MavenOptions>, DefaultLocalMavenInvoker.LocalContext> {
|
||||
protected LocalContext(DefaultLocalMavenInvoker invoker, MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
super(invoker, invokerRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultLocalMavenInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalContext createContext(MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
return new LocalContext(this, invokerRequest);
|
||||
}
|
||||
}
|
|
@ -16,24 +16,24 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.api.cli.mvn.resident;
|
||||
package org.apache.maven.cling.invoker.mvn.local;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvoker;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenContext;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenInvoker;
|
||||
|
||||
/**
|
||||
* Resident Maven invoker, similar to local. Instance is shut down when this instance is closed.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* Local Maven invoker implementation, that expects all the Maven to be on classpath.
|
||||
*/
|
||||
@Experimental
|
||||
public interface ResidentMavenInvoker extends MavenInvoker<MavenInvokerRequest<MavenOptions>> {
|
||||
/**
|
||||
* Closes cleanly the daemon.
|
||||
*/
|
||||
public class LocalMavenInvoker extends MavenInvoker<MavenContext> {
|
||||
public LocalMavenInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
void close() throws InvokerException;
|
||||
protected MavenContext createContext(InvokerRequest invokerRequest) throws InvokerException {
|
||||
return new MavenContext(invokerRequest);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the {@code mvn} tool implementation.
|
||||
*/
|
||||
package org.apache.maven.cling.invoker.mvn;
|
|
@ -1,139 +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.cling.invoker.mvn.resident;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.resident.ResidentMavenInvoker;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenInvoker;
|
||||
|
||||
/**
|
||||
* Local resident invoker implementation, similar to "local" but keeps Maven instance resident. This implies, that
|
||||
* things like environment, system properties, extensions etc. are loaded only once. It is caller duty to ensure
|
||||
* that subsequent call is right for the resident instance (ie no env change or different extension needed).
|
||||
*/
|
||||
public class DefaultResidentMavenInvoker
|
||||
extends DefaultMavenInvoker<
|
||||
MavenOptions, MavenInvokerRequest<MavenOptions>, DefaultResidentMavenInvoker.LocalContext>
|
||||
implements ResidentMavenInvoker {
|
||||
|
||||
public static class LocalContext
|
||||
extends DefaultMavenInvoker.MavenContext<
|
||||
MavenOptions, MavenInvokerRequest<MavenOptions>, DefaultResidentMavenInvoker.LocalContext> {
|
||||
|
||||
protected LocalContext(DefaultResidentMavenInvoker invoker, MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
super(invoker, invokerRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
// we are resident, we do not shut down here
|
||||
}
|
||||
|
||||
public void shutDown() throws InvokerException {
|
||||
super.close();
|
||||
}
|
||||
|
||||
public LocalContext copy(MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
if (invokerRequest == this.invokerRequest) {
|
||||
return this;
|
||||
}
|
||||
LocalContext shadow = new LocalContext((DefaultResidentMavenInvoker) invoker, invokerRequest);
|
||||
|
||||
shadow.logger = logger;
|
||||
shadow.loggerFactory = loggerFactory;
|
||||
shadow.loggerLevel = loggerLevel;
|
||||
shadow.containerCapsule = containerCapsule;
|
||||
shadow.lookup = lookup;
|
||||
shadow.settingsBuilder = settingsBuilder;
|
||||
|
||||
shadow.interactive = interactive;
|
||||
shadow.localRepositoryPath = localRepositoryPath;
|
||||
shadow.installationSettingsPath = installationSettingsPath;
|
||||
shadow.projectSettingsPath = projectSettingsPath;
|
||||
shadow.userSettingsPath = userSettingsPath;
|
||||
shadow.effectiveSettings = effectiveSettings;
|
||||
|
||||
shadow.mavenExecutionRequest = mavenExecutionRequest;
|
||||
shadow.eventSpyDispatcher = eventSpyDispatcher;
|
||||
shadow.mavenExecutionRequestPopulator = mavenExecutionRequestPopulator;
|
||||
shadow.toolchainsBuilder = toolchainsBuilder;
|
||||
shadow.modelProcessor = modelProcessor;
|
||||
shadow.maven = maven;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<String, LocalContext> residentContext;
|
||||
|
||||
public DefaultResidentMavenInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
this.residentContext = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
ArrayList<InvokerException> exceptions = new ArrayList<>();
|
||||
for (LocalContext context : residentContext.values()) {
|
||||
try {
|
||||
context.shutDown();
|
||||
} catch (InvokerException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
if (!exceptions.isEmpty()) {
|
||||
InvokerException exception = new InvokerException("Could not cleanly shut down context pool");
|
||||
exceptions.forEach(exception::addSuppressed);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalContext createContext(MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
return residentContext
|
||||
.computeIfAbsent(getContextId(invokerRequest), k -> new LocalContext(this, invokerRequest))
|
||||
.copy(invokerRequest);
|
||||
}
|
||||
|
||||
protected String getContextId(MavenInvokerRequest<MavenOptions> invokerRequest) {
|
||||
// TODO: in a moment Maven stop pushing user properties to system properties (and maybe something more)
|
||||
// and allow multiple instances per JVM, this may become a pool?
|
||||
return "resident";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void container(LocalContext context) throws Exception {
|
||||
if (context.containerCapsule == null) {
|
||||
super.container(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lookup(LocalContext context) throws Exception {
|
||||
if (context.maven == null) {
|
||||
super.lookup(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn.resident;
|
||||
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenContext;
|
||||
|
||||
public class ResidentMavenContext extends MavenContext {
|
||||
|
||||
protected ResidentMavenContext(InvokerRequest invokerRequest) {
|
||||
super(invokerRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
// we are resident, we do not shut down here
|
||||
}
|
||||
|
||||
public void shutDown() throws InvokerException {
|
||||
super.close();
|
||||
}
|
||||
|
||||
public ResidentMavenContext copy(InvokerRequest invokerRequest) {
|
||||
if (invokerRequest == this.invokerRequest) {
|
||||
return this;
|
||||
}
|
||||
ResidentMavenContext shadow = new ResidentMavenContext(invokerRequest);
|
||||
|
||||
shadow.logger = logger;
|
||||
shadow.loggerFactory = loggerFactory;
|
||||
shadow.loggerLevel = loggerLevel;
|
||||
shadow.containerCapsule = containerCapsule;
|
||||
shadow.lookup = lookup;
|
||||
|
||||
shadow.interactive = interactive;
|
||||
shadow.localRepositoryPath = localRepositoryPath;
|
||||
shadow.installationSettingsPath = installationSettingsPath;
|
||||
shadow.projectSettingsPath = projectSettingsPath;
|
||||
shadow.userSettingsPath = userSettingsPath;
|
||||
shadow.effectiveSettings = effectiveSettings;
|
||||
|
||||
shadow.mavenExecutionRequest = mavenExecutionRequest;
|
||||
shadow.eventSpyDispatcher = eventSpyDispatcher;
|
||||
shadow.mavenExecutionRequestPopulator = mavenExecutionRequestPopulator;
|
||||
shadow.modelProcessor = modelProcessor;
|
||||
shadow.maven = maven;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn.resident;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.maven.api.cli.InvokerException;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenInvoker;
|
||||
|
||||
/**
|
||||
* Resident invoker implementation, similar to "local", but keeps Maven instance resident. This implies, that
|
||||
* things like environment, system properties, extensions etc. are loaded only once. It is caller duty to ensure
|
||||
* that subsequent call is right for the resident instance (ie no env change or different extension needed).
|
||||
*/
|
||||
public class ResidentMavenInvoker extends MavenInvoker<ResidentMavenContext> {
|
||||
|
||||
private final ConcurrentHashMap<String, ResidentMavenContext> residentContext;
|
||||
|
||||
public ResidentMavenInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
this.residentContext = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws InvokerException {
|
||||
ArrayList<InvokerException> exceptions = new ArrayList<>();
|
||||
for (ResidentMavenContext context : residentContext.values()) {
|
||||
try {
|
||||
context.shutDown();
|
||||
} catch (InvokerException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
if (!exceptions.isEmpty()) {
|
||||
InvokerException exception = new InvokerException("Could not cleanly shut down context pool");
|
||||
exceptions.forEach(exception::addSuppressed);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResidentMavenContext createContext(InvokerRequest invokerRequest) {
|
||||
return residentContext
|
||||
.computeIfAbsent(getContextId(invokerRequest), k -> new ResidentMavenContext(invokerRequest))
|
||||
.copy(invokerRequest);
|
||||
}
|
||||
|
||||
protected String getContextId(InvokerRequest invokerRequest) {
|
||||
// TODO: in a moment Maven stop pushing user properties to system properties (and maybe something more)
|
||||
// and allow multiple instances per JVM, this may become a pool?
|
||||
return "resident";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void container(ResidentMavenContext context) throws Exception {
|
||||
if (context.containerCapsule == null) {
|
||||
super.container(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lookup(ResidentMavenContext context) throws Exception {
|
||||
if (context.maven == null) {
|
||||
super.lookup(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,9 @@ import org.codehaus.plexus.interpolation.InterpolationException;
|
|||
|
||||
import static org.apache.maven.cling.invoker.Utils.createInterpolator;
|
||||
|
||||
/**
|
||||
* Implementation of {@link EncryptOptions} (base + mvnenc).
|
||||
*/
|
||||
public class CommonsCliEncryptOptions extends CommonsCliOptions implements EncryptOptions {
|
||||
public static CommonsCliEncryptOptions parse(String[] args) throws ParseException {
|
||||
CLIManager cliManager = new CLIManager();
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvnenc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.cling.invoker.LookupContext;
|
||||
import org.jline.consoleui.prompt.ConsolePrompt;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.utils.AttributedString;
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public class EncryptContext extends LookupContext {
|
||||
protected EncryptContext(InvokerRequest invokerRequest) {
|
||||
super(invokerRequest);
|
||||
}
|
||||
|
||||
public Map<String, Goal> goals;
|
||||
|
||||
public List<AttributedString> header;
|
||||
public AttributedStyle style;
|
||||
public LineReader reader;
|
||||
public ConsolePrompt prompt;
|
||||
|
||||
public void addInHeader(String text) {
|
||||
addInHeader(AttributedStyle.DEFAULT, text);
|
||||
}
|
||||
|
||||
public void addInHeader(AttributedStyle style, String text) {
|
||||
AttributedStringBuilder asb = new AttributedStringBuilder();
|
||||
asb.style(style).append(text);
|
||||
header.add(asb.toAttributedString());
|
||||
}
|
||||
}
|
|
@ -20,75 +20,41 @@ package org.apache.maven.cling.invoker.mvnenc;
|
|||
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvoker;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
|
||||
import org.apache.maven.api.cli.InvokerRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.cling.invoker.LookupInvoker;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.utils.CLIReportingUtils;
|
||||
import org.jline.consoleui.prompt.ConsolePrompt;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
import org.jline.reader.UserInterruptException;
|
||||
import org.jline.terminal.Terminal;
|
||||
import org.jline.utils.AttributedString;
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
import org.jline.utils.Colors;
|
||||
import org.jline.utils.OSUtils;
|
||||
|
||||
/**
|
||||
* Encrypt invoker implementation, when Encrypt CLI is being run. System uses ClassWorld launcher, and class world
|
||||
* instance is passed in via "enhanced" main method. Hence, this class expects fully setup ClassWorld via constructor.
|
||||
* mvnenc invoker implementation.
|
||||
*/
|
||||
public class DefaultEncryptInvoker
|
||||
extends LookupInvoker<EncryptOptions, EncryptInvokerRequest, DefaultEncryptInvoker.LocalContext>
|
||||
implements EncryptInvoker {
|
||||
public class EncryptInvoker extends LookupInvoker<EncryptContext> {
|
||||
|
||||
@SuppressWarnings("VisibilityModifier")
|
||||
public static class LocalContext
|
||||
extends LookupInvokerContext<EncryptOptions, EncryptInvokerRequest, DefaultEncryptInvoker.LocalContext> {
|
||||
protected LocalContext(DefaultEncryptInvoker invoker, EncryptInvokerRequest invokerRequest) {
|
||||
super(invoker, invokerRequest);
|
||||
}
|
||||
|
||||
public Map<String, Goal> goals;
|
||||
|
||||
public List<AttributedString> header;
|
||||
public AttributedStyle style;
|
||||
public LineReader reader;
|
||||
public ConsolePrompt prompt;
|
||||
|
||||
public void addInHeader(String text) {
|
||||
addInHeader(AttributedStyle.DEFAULT, text);
|
||||
}
|
||||
|
||||
public void addInHeader(AttributedStyle style, String text) {
|
||||
AttributedStringBuilder asb = new AttributedStringBuilder();
|
||||
asb.style(style).append(text);
|
||||
header.add(asb.toAttributedString());
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultEncryptInvoker(ProtoLookup protoLookup) {
|
||||
public EncryptInvoker(ProtoLookup protoLookup) {
|
||||
super(protoLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int execute(LocalContext context) throws Exception {
|
||||
protected int execute(EncryptContext context) throws Exception {
|
||||
return doExecute(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalContext createContext(EncryptInvokerRequest invokerRequest) {
|
||||
return new LocalContext(this, invokerRequest);
|
||||
protected EncryptContext createContext(InvokerRequest invokerRequest) {
|
||||
return new EncryptContext(invokerRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lookup(LocalContext context) {
|
||||
protected void lookup(EncryptContext context) {
|
||||
context.goals = context.lookup.lookupMap(Goal.class);
|
||||
}
|
||||
|
||||
|
@ -97,7 +63,7 @@ public class DefaultEncryptInvoker
|
|||
public static final int BAD_OPERATION = 2; // bad user input or alike
|
||||
public static final int CANCELED = 3; // user canceled
|
||||
|
||||
protected int doExecute(LocalContext context) throws Exception {
|
||||
protected int doExecute(EncryptContext context) throws Exception {
|
||||
try {
|
||||
if (!context.interactive) {
|
||||
context.terminal.writer().println("This tool works only in interactive mode!");
|
||||
|
@ -139,12 +105,12 @@ public class DefaultEncryptInvoker
|
|||
LineReaderBuilder.builder().terminal(context.terminal).build();
|
||||
context.prompt = new ConsolePrompt(context.reader, context.terminal, config);
|
||||
|
||||
if (context.invokerRequest.options().goals().isEmpty()
|
||||
|| context.invokerRequest.options().goals().get().size() != 1) {
|
||||
EncryptOptions options = (EncryptOptions) context.invokerRequest.options();
|
||||
if (options.goals().isEmpty() || options.goals().get().size() != 1) {
|
||||
return badGoalsErrorMessage("No goal or multiple goals specified, specify only one goal.", context);
|
||||
}
|
||||
|
||||
String goalName = context.invokerRequest.options().goals().get().get(0);
|
||||
String goalName = options.goals().get().get(0);
|
||||
Goal goal = context.goals.get(goalName);
|
||||
|
||||
if (goal == null) {
|
||||
|
@ -168,7 +134,7 @@ public class DefaultEncryptInvoker
|
|||
}
|
||||
}
|
||||
|
||||
protected int badGoalsErrorMessage(String message, LocalContext context) {
|
||||
protected int badGoalsErrorMessage(String message, EncryptContext context) {
|
||||
context.terminal.writer().println(message);
|
||||
context.terminal.writer().println("Supported goals are: " + String.join(", ", context.goals.keySet()));
|
||||
context.terminal.writer().println("Use -h to display help.");
|
|
@ -25,20 +25,18 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.extensions.CoreExtension;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.cling.invoker.BaseInvokerRequest;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class DefaultEncryptInvokerRequest extends BaseInvokerRequest<EncryptOptions> implements EncryptInvokerRequest {
|
||||
public class EncryptInvokerRequest extends BaseInvokerRequest {
|
||||
private final EncryptOptions options;
|
||||
|
||||
@SuppressWarnings("ParameterNumber")
|
||||
public DefaultEncryptInvokerRequest(
|
||||
public EncryptInvokerRequest(
|
||||
ParserRequest parserRequest,
|
||||
Path cwd,
|
||||
Path installationDirectory,
|
||||
|
@ -51,7 +49,8 @@ public class DefaultEncryptInvokerRequest extends BaseInvokerRequest<EncryptOpti
|
|||
OutputStream out,
|
||||
OutputStream err,
|
||||
List<CoreExtension> coreExtensions,
|
||||
Options options) {
|
||||
List<String> jvmArguments,
|
||||
EncryptOptions options) {
|
||||
super(
|
||||
parserRequest,
|
||||
cwd,
|
||||
|
@ -64,8 +63,9 @@ public class DefaultEncryptInvokerRequest extends BaseInvokerRequest<EncryptOpti
|
|||
in,
|
||||
out,
|
||||
err,
|
||||
coreExtensions);
|
||||
this.options = (EncryptOptions) requireNonNull(options);
|
||||
coreExtensions,
|
||||
jvmArguments);
|
||||
this.options = requireNonNull(options);
|
||||
}
|
||||
|
||||
/**
|
|
@ -22,16 +22,15 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.api.cli.Options;
|
||||
import org.apache.maven.api.cli.ParserException;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptParser;
|
||||
import org.apache.maven.cling.invoker.BaseParser;
|
||||
|
||||
public class DefaultEncryptParser extends BaseParser<EncryptOptions, EncryptInvokerRequest> implements EncryptParser {
|
||||
public class EncryptParser extends BaseParser {
|
||||
@Override
|
||||
protected EncryptInvokerRequest getInvokerRequest(LocalContext context) {
|
||||
return new DefaultEncryptInvokerRequest(
|
||||
return new EncryptInvokerRequest(
|
||||
context.parserRequest,
|
||||
context.cwd,
|
||||
context.installationDirectory,
|
||||
|
@ -44,11 +43,12 @@ public class DefaultEncryptParser extends BaseParser<EncryptOptions, EncryptInvo
|
|||
context.parserRequest.out(),
|
||||
context.parserRequest.err(),
|
||||
context.extensions,
|
||||
context.options);
|
||||
getJvmArguments(context.rootDirectory),
|
||||
(EncryptOptions) context.options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<EncryptOptions> parseCliOptions(LocalContext context) throws ParserException {
|
||||
protected List<Options> parseCliOptions(LocalContext context) throws ParserException {
|
||||
return Collections.singletonList(parseEncryptCliOptions(context.parserRequest.args()));
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public class DefaultEncryptParser extends BaseParser<EncryptOptions, EncryptInvo
|
|||
}
|
||||
|
||||
@Override
|
||||
protected EncryptOptions assembleOptions(List<EncryptOptions> parsedOptions) {
|
||||
protected Options assembleOptions(List<Options> parsedOptions) {
|
||||
// nothing to assemble, we deal with CLI only
|
||||
return parsedOptions.get(0);
|
||||
}
|
|
@ -22,5 +22,5 @@ package org.apache.maven.cling.invoker.mvnenc;
|
|||
* The mvnenc tool goal.
|
||||
*/
|
||||
public interface Goal {
|
||||
int execute(DefaultEncryptInvoker.LocalContext context) throws Exception;
|
||||
int execute(EncryptContext context) throws Exception;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptContext;
|
||||
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
|
||||
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.ERROR;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.ERROR;
|
||||
|
||||
/**
|
||||
* The support class for goal implementations that requires valid/workable config.
|
||||
|
@ -37,7 +37,7 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int execute(DefaultEncryptInvoker.LocalContext context) throws Exception {
|
||||
public int execute(EncryptContext context) throws Exception {
|
||||
if (!validateConfiguration(context)) {
|
||||
context.terminal
|
||||
.writer()
|
||||
|
@ -50,7 +50,7 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
|
|||
return doExecute(context);
|
||||
}
|
||||
|
||||
protected boolean validateConfiguration(DefaultEncryptInvoker.LocalContext context) {
|
||||
protected boolean validateConfiguration(EncryptContext context) {
|
||||
SecDispatcher.ValidationResponse response = secDispatcher.validateConfiguration();
|
||||
if (!response.isValid() || context.invokerRequest.options().verbose().orElse(false)) {
|
||||
dumpResponse(context, "", response);
|
||||
|
@ -58,8 +58,7 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
|
|||
return response.isValid();
|
||||
}
|
||||
|
||||
protected void dumpResponse(
|
||||
DefaultEncryptInvoker.LocalContext context, String indent, SecDispatcher.ValidationResponse response) {
|
||||
protected void dumpResponse(EncryptContext context, String indent, SecDispatcher.ValidationResponse response) {
|
||||
context.terminal
|
||||
.writer()
|
||||
.println(messageBuilderFactory
|
||||
|
@ -100,5 +99,5 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract int doExecute(DefaultEncryptInvoker.LocalContext context) throws Exception;
|
||||
protected abstract int doExecute(EncryptContext context) throws Exception;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,11 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptContext;
|
||||
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
|
||||
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.BAD_OPERATION;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.OK;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.BAD_OPERATION;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
|
||||
|
||||
/**
|
||||
* The "decrypt" goal.
|
||||
|
@ -41,7 +41,7 @@ public class Decrypt extends ConfiguredGoalSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doExecute(DefaultEncryptInvoker.LocalContext context) throws Exception {
|
||||
protected int doExecute(EncryptContext context) throws Exception {
|
||||
String encrypted = context.reader.readLine("Enter the password to decrypt: ");
|
||||
if (secDispatcher.isAnyEncryptedString(encrypted)) {
|
||||
context.terminal.writer().println(secDispatcher.decrypt(encrypted));
|
||||
|
|
|
@ -23,10 +23,10 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptContext;
|
||||
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
|
||||
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.OK;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
|
||||
|
||||
/**
|
||||
* The "diag" goal.
|
||||
|
@ -40,7 +40,7 @@ public class Diag extends ConfiguredGoalSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doExecute(DefaultEncryptInvoker.LocalContext context) {
|
||||
protected int doExecute(EncryptContext context) {
|
||||
dumpResponse(context, "", secDispatcher.validateConfiguration());
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptContext;
|
||||
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
|
||||
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.OK;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
|
||||
|
||||
/**
|
||||
* The "encrypt" goal.
|
||||
|
@ -40,7 +40,7 @@ public class Encrypt extends ConfiguredGoalSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doExecute(DefaultEncryptInvoker.LocalContext context) throws Exception {
|
||||
protected int doExecute(EncryptContext context) throws Exception {
|
||||
String cleartext = context.reader.readLine("Enter the password to encrypt: ", '*');
|
||||
context.terminal.writer().println(secDispatcher.encrypt(cleartext, null));
|
||||
return OK;
|
||||
|
|
|
@ -26,8 +26,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.maven.api.cli.mvnenc.EncryptOptions;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
|
||||
import org.apache.maven.cling.invoker.mvnenc.EncryptContext;
|
||||
import org.codehaus.plexus.components.secdispatcher.DispatcherMeta;
|
||||
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
|
||||
import org.codehaus.plexus.components.secdispatcher.model.Config;
|
||||
|
@ -45,8 +46,8 @@ import org.jline.reader.LineReader;
|
|||
import org.jline.reader.ParsedLine;
|
||||
import org.jline.utils.Colors;
|
||||
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.BAD_OPERATION;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker.OK;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.BAD_OPERATION;
|
||||
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
|
||||
|
||||
/**
|
||||
* The "init" goal.
|
||||
|
@ -62,13 +63,15 @@ public class Init extends GoalSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int execute(DefaultEncryptInvoker.LocalContext context) throws Exception {
|
||||
public int execute(EncryptContext context) throws Exception {
|
||||
context.addInHeader(context.style.italic().bold().foreground(Colors.rgbColor("yellow")), "goal: init");
|
||||
context.addInHeader("");
|
||||
|
||||
ConsolePrompt prompt = context.prompt;
|
||||
boolean force = context.invokerRequest.options().force().orElse(false);
|
||||
boolean yes = context.invokerRequest.options().yes().orElse(false);
|
||||
|
||||
EncryptOptions options = (EncryptOptions) context.invokerRequest.options();
|
||||
boolean force = options.force().orElse(false);
|
||||
boolean yes = options.yes().orElse(false);
|
||||
|
||||
if (configExists() && !force) {
|
||||
context.terminal
|
||||
|
@ -238,8 +241,7 @@ public class Init extends GoalSupport {
|
|||
}
|
||||
|
||||
private PromptBuilder configureDispatcher(
|
||||
DefaultEncryptInvoker.LocalContext context, DispatcherMeta dispatcherMeta, PromptBuilder promptBuilder)
|
||||
throws Exception {
|
||||
EncryptContext context, DispatcherMeta dispatcherMeta, PromptBuilder promptBuilder) throws Exception {
|
||||
context.addInHeader(
|
||||
context.style.italic().bold().foreground(Colors.rgbColor("yellow")),
|
||||
"Configure " + dispatcherMeta.displayName());
|
||||
|
|
|
@ -16,15 +16,8 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.api.cli.mvn.forked;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvoker;
|
||||
|
||||
/**
|
||||
* Forked Maven invoker.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* This package contains the {@code mvnenc} tool implementation.
|
||||
*/
|
||||
@Experimental
|
||||
public interface ForkedMavenInvoker extends MavenInvoker<ForkedMavenInvokerRequest> {}
|
||||
package org.apache.maven.cling.invoker.mvnenc;
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contain support (mostly abstract) classes, that implement "base" of CLIng.
|
||||
* In packages below you find actual implementations.
|
||||
*/
|
||||
package org.apache.maven.cling.invoker;
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.cli.Executor;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.cling.invoker.ProtoLogger;
|
||||
import org.apache.maven.jline.JLineMessageBuilderFactory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public abstract class MavenExecutorTestSupport {
|
||||
|
||||
protected void execute(Path cwd, Collection<String> goals) throws Exception {
|
||||
Files.createDirectory(cwd.resolve(".mvn"));
|
||||
Path pom = cwd.resolve("pom.xml").toAbsolutePath();
|
||||
Files.writeString(pom, MavenTestSupport.POM_STRING);
|
||||
Path appJava = cwd.resolve("src/main/java/org/apache/maven/samples/sample/App.java");
|
||||
Files.createDirectories(appJava.getParent());
|
||||
Files.writeString(appJava, MavenTestSupport.APP_JAVA_STRING);
|
||||
|
||||
Parser parser = createParser();
|
||||
try (Executor invoker = createExecutor()) {
|
||||
for (String goal : goals) {
|
||||
Path logFile = cwd.resolve(goal + "-build.log").toAbsolutePath();
|
||||
int exitCode = invoker.execute(parser.parseExecution(ParserRequest.mvn(
|
||||
List.of("-l", logFile.toString(), goal),
|
||||
new ProtoLogger(),
|
||||
new JLineMessageBuilderFactory())
|
||||
.cwd(cwd)
|
||||
.build()));
|
||||
String log = Files.readString(logFile);
|
||||
System.out.println(log);
|
||||
assertEquals(0, exitCode, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Executor createExecutor();
|
||||
|
||||
protected abstract Parser createParser();
|
||||
}
|
|
@ -27,15 +27,13 @@ import java.util.List;
|
|||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.ParserRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.cling.invoker.ProtoLogger;
|
||||
import org.apache.maven.jline.JLineMessageBuilderFactory;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public abstract class MavenInvokerTestSupport<O extends MavenOptions, R extends MavenInvokerRequest<O>> {
|
||||
public abstract class MavenInvokerTestSupport {
|
||||
|
||||
protected void invoke(Path cwd, Collection<String> goals) throws Exception {
|
||||
// works only in recent Maven4
|
||||
|
@ -46,75 +44,30 @@ public abstract class MavenInvokerTestSupport<O extends MavenOptions, R extends
|
|||
"${maven.home}/conf/maven.properties must be a file");
|
||||
|
||||
Files.createDirectory(cwd.resolve(".mvn"));
|
||||
|
||||
String pomString =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.maven.samples</groupId>
|
||||
<artifactId>sample</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.11.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
""";
|
||||
Path pom = cwd.resolve("pom.xml").toAbsolutePath();
|
||||
Files.writeString(pom, pomString);
|
||||
|
||||
String appJavaString =
|
||||
"""
|
||||
package org.apache.maven.samples.sample;
|
||||
|
||||
public class App {
|
||||
public static void main(String... args) {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
""";
|
||||
Files.writeString(pom, MavenTestSupport.POM_STRING);
|
||||
Path appJava = cwd.resolve("src/main/java/org/apache/maven/samples/sample/App.java");
|
||||
Files.createDirectories(appJava.getParent());
|
||||
Files.writeString(appJava, appJavaString);
|
||||
Files.writeString(appJava, MavenTestSupport.APP_JAVA_STRING);
|
||||
|
||||
Parser<R> parser = createParser();
|
||||
try (Invoker<R> invoker = createInvoker()) {
|
||||
Parser parser = createParser();
|
||||
try (Invoker invoker = createInvoker()) {
|
||||
for (String goal : goals) {
|
||||
Path logFile = cwd.resolve(goal + "-build.log").toAbsolutePath();
|
||||
int exitCode = invoker.invoke(parser.parse(ParserRequest.mvn(
|
||||
int exitCode = invoker.invoke(parser.parseInvocation(ParserRequest.mvn(
|
||||
List.of("-l", logFile.toString(), goal),
|
||||
new ProtoLogger(),
|
||||
new JLineMessageBuilderFactory())
|
||||
.cwd(cwd)
|
||||
.build()));
|
||||
String log = Files.readString(logFile);
|
||||
System.out.println(log);
|
||||
assertEquals(0, exitCode, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Invoker<R> createInvoker();
|
||||
protected abstract Invoker createInvoker();
|
||||
|
||||
protected abstract Parser<R> createParser();
|
||||
protected abstract Parser createParser();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn;
|
||||
|
||||
public final class MavenTestSupport {
|
||||
private MavenTestSupport() {}
|
||||
|
||||
public static final String POM_STRING =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.maven.samples</groupId>
|
||||
<artifactId>sample</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.11.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
""";
|
||||
|
||||
public static final String APP_JAVA_STRING =
|
||||
"""
|
||||
package org.apache.maven.samples.sample;
|
||||
|
||||
public class App {
|
||||
public static void main(String... args) {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.cling.invoker.mvn.embedded;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.cli.Executor;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenExecutorTestSupport;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenParser;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.CleanupMode;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/**
|
||||
* Forked UT: it cannot use jimFS as it runs in child process.
|
||||
*/
|
||||
@Disabled(
|
||||
"The tests reuse properties from the JVM being launched, thus may lead to failures depending on which options are used")
|
||||
public class EmbeddedMavenExecutorTest extends MavenExecutorTestSupport {
|
||||
|
||||
@Override
|
||||
protected Executor createExecutor() {
|
||||
return new EmbeddedMavenExecutor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parser createParser() {
|
||||
return new MavenParser();
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultFs(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
|
||||
System.setProperty("maven.home", "/home/cstamas/Tools/maven/apache-maven-4.0.0-beta-6-SNAPSHOT");
|
||||
execute(tempDir, List.of("verify"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultFs3x(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
|
||||
System.setProperty("maven.home", "/home/cstamas/.sdkman/candidates/maven/3.9.9");
|
||||
execute(tempDir, List.of("verify"));
|
||||
}
|
||||
}
|
|
@ -23,9 +23,9 @@ import java.util.Arrays;
|
|||
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenInvokerTestSupport;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenParser;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.CleanupMode;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -33,16 +33,18 @@ import org.junit.jupiter.api.io.TempDir;
|
|||
/**
|
||||
* Forked UT: it cannot use jimFS as it runs in child process.
|
||||
*/
|
||||
public class DefaultForkedMavenInvokerTest extends MavenInvokerTestSupport<MavenOptions, ForkedMavenInvokerRequest> {
|
||||
@Disabled(
|
||||
"The tests reuse properties from the JVM being launched, thus may lead to failures depending on which options are used")
|
||||
public class ForkedMavenInvokerTest extends MavenInvokerTestSupport {
|
||||
|
||||
@Override
|
||||
protected Invoker<ForkedMavenInvokerRequest> createInvoker() {
|
||||
return new DefaultForkedMavenInvoker();
|
||||
protected Invoker createInvoker() {
|
||||
return new ForkedMavenInvoker();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parser<ForkedMavenInvokerRequest> createParser() {
|
||||
return new DefaultForkedMavenParser();
|
||||
protected Parser createParser() {
|
||||
return new MavenParser();
|
||||
}
|
||||
|
||||
@Test
|
|
@ -26,11 +26,9 @@ import com.google.common.jimfs.Configuration;
|
|||
import com.google.common.jimfs.Jimfs;
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenInvokerTestSupport;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenParser;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -42,18 +40,17 @@ import org.junit.jupiter.api.io.TempDir;
|
|||
*/
|
||||
@Disabled(
|
||||
"The tests reuse properties from the JVM being launched, thus may lead to failures depending on which options are used")
|
||||
public class DefaultLocalMavenInvokerTest
|
||||
extends MavenInvokerTestSupport<MavenOptions, MavenInvokerRequest<MavenOptions>> {
|
||||
public class DefaultLocalMavenInvokerTest extends MavenInvokerTestSupport {
|
||||
@Override
|
||||
protected Invoker<MavenInvokerRequest<MavenOptions>> createInvoker() {
|
||||
return new DefaultLocalMavenInvoker(ProtoLookup.builder()
|
||||
protected Invoker createInvoker() {
|
||||
return new LocalMavenInvoker(ProtoLookup.builder()
|
||||
.addMapping(ClassWorld.class, new ClassWorld("plexus.core", ClassLoader.getSystemClassLoader()))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parser<MavenInvokerRequest<MavenOptions>> createParser() {
|
||||
return new DefaultMavenParser();
|
||||
protected Parser createParser() {
|
||||
return new MavenParser();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -26,11 +26,9 @@ import com.google.common.jimfs.Configuration;
|
|||
import com.google.common.jimfs.Jimfs;
|
||||
import org.apache.maven.api.cli.Invoker;
|
||||
import org.apache.maven.api.cli.Parser;
|
||||
import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
|
||||
import org.apache.maven.api.cli.mvn.MavenOptions;
|
||||
import org.apache.maven.cling.invoker.ProtoLookup;
|
||||
import org.apache.maven.cling.invoker.mvn.DefaultMavenParser;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenInvokerTestSupport;
|
||||
import org.apache.maven.cling.invoker.mvn.MavenParser;
|
||||
import org.codehaus.plexus.classworlds.ClassWorld;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -42,19 +40,18 @@ import org.junit.jupiter.api.io.TempDir;
|
|||
*/
|
||||
@Disabled(
|
||||
"The tests reuse properties from the JVM being launched, thus may lead to failures depending on which options are used")
|
||||
public class DefaultResidentMavenInvokerTest
|
||||
extends MavenInvokerTestSupport<MavenOptions, MavenInvokerRequest<MavenOptions>> {
|
||||
public class DefaultResidentMavenInvokerTest extends MavenInvokerTestSupport {
|
||||
|
||||
@Override
|
||||
protected Invoker<MavenInvokerRequest<MavenOptions>> createInvoker() {
|
||||
return new DefaultResidentMavenInvoker(ProtoLookup.builder()
|
||||
protected Invoker createInvoker() {
|
||||
return new ResidentMavenInvoker(ProtoLookup.builder()
|
||||
.addMapping(ClassWorld.class, new ClassWorld("plexus.core", ClassLoader.getSystemClassLoader()))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parser<MavenInvokerRequest<MavenOptions>> createParser() {
|
||||
return new DefaultMavenParser();
|
||||
protected Parser createParser() {
|
||||
return new MavenParser();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue