├── .gitignore
├── docs
└── logo.png
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── src
├── main
│ └── java
│ │ └── com
│ │ └── maciejwalkowiak
│ │ └── paseq
│ │ ├── InvalidTaskDefinitionException.java
│ │ ├── TaskBuilder.java
│ │ ├── Exec.java
│ │ ├── Task.java
│ │ └── ExecMojo.java
└── test
│ ├── java
│ └── com
│ │ └── maciejwalkowiak
│ │ └── paseq
│ │ ├── ExecMojoTestIT.java
│ │ ├── TaskTests.java
│ │ └── ExecMojoTests.java
│ └── resources-its
│ └── com
│ └── maciejwalkowiak
│ └── paseq
│ └── ExecMojoTestIT
│ └── the_first_test_case
│ └── pom.xml
├── .github
└── workflows
│ ├── release.yml
│ └── build.yml
├── LICENSE
├── README.md
├── mvnw.cmd
├── pom.xml
└── mvnw
/.gitignore:
--------------------------------------------------------------------------------
1 | *.ipr
2 | *.iml
3 | .DS_Store
4 | .idea
5 |
6 | target
7 |
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maciejwalkowiak/paseq-maven-plugin/HEAD/docs/logo.png
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maciejwalkowiak/paseq-maven-plugin/HEAD/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/src/main/java/com/maciejwalkowiak/paseq/InvalidTaskDefinitionException.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 | /**
4 | * Exception thrown when task is in invalid state.
5 | *
6 | * @author Maciej Walkowiak
7 | */
8 | public class InvalidTaskDefinitionException extends RuntimeException {
9 | public InvalidTaskDefinitionException(String s) {
10 | super(s);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/java/com/maciejwalkowiak/paseq/ExecMojoTestIT.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 | import static com.soebes.itf.extension.assertj.MavenITAssertions.assertThat;
4 |
5 | import com.soebes.itf.jupiter.extension.MavenGoal;
6 | import com.soebes.itf.jupiter.extension.MavenJupiterExtension;
7 | import com.soebes.itf.jupiter.extension.MavenTest;
8 | import com.soebes.itf.jupiter.maven.MavenExecutionResult;
9 |
10 | /**
11 | * Integration tests for {@link ExecMojo}.
12 | *
13 | * @author Maciej Walkowiak
14 | */
15 | @MavenJupiterExtension
16 | public class ExecMojoTestIT {
17 |
18 | @MavenGoal("${project.groupId}:${project.artifactId}:${project.version}:exec")
19 | @MavenTest
20 | void the_first_test_case(MavenExecutionResult result) {
21 | assertThat(result).isSuccessful();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/maciejwalkowiak/paseq/TaskBuilder.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 |
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | /**
7 | * Builder for {@link Task}. Meant to be used mainly in tests.
8 | *
9 | * @author Maciej Walkowiak
10 | */
11 | public class TaskBuilder {
12 | private boolean async;
13 | private boolean wait;
14 | private @Nullable String[] goals;
15 | private @Nullable Exec exec;
16 |
17 | TaskBuilder setGoals(String[] goals) {
18 | this.goals = goals;
19 | return this;
20 | }
21 |
22 | TaskBuilder setExec(Exec exec) {
23 | this.exec = exec;
24 | return this;
25 | }
26 |
27 | TaskBuilder async() {
28 | this.async = true;
29 | return this;
30 | }
31 |
32 | TaskBuilder waits() {
33 | this.wait = true;
34 | return this;
35 | }
36 |
37 | Task build() {
38 | return new Task(this.async, this.wait, this.goals, this.exec);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Publish package to the Maven Central Repository
2 | on:
3 | push:
4 | tags:
5 | - v*
6 | jobs:
7 | publish:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v3
11 | - name: Set up Java
12 | uses: actions/setup-java@v3
13 | with:
14 | java-version: '11'
15 | distribution: 'adopt'
16 | - name: Publish package
17 | env:
18 | JRELEASER_NEXUS2_USERNAME: ${{ secrets.OSSRH_USERNAME }}
19 | JRELEASER_NEXUS2_MAVEN_CENTRAL_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
20 | JRELEASER_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
21 | JRELEASER_GPG_SECRET_KEY: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
22 | JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}
23 | JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 | run: ./mvnw -Prelease deploy jreleaser:deploy -DaltDeploymentRepository=local::file:./target/staging-deploy
25 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Maciej Walkowiak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | permissions:
10 | contents: read
11 |
12 | jobs:
13 | build:
14 | name: "Build with ${{ matrix.version }}"
15 | strategy:
16 | matrix:
17 | version: [ 11.0.17-tem, 17.0.5-tem, 19-tem ]
18 | runs-on: ubuntu-latest
19 | steps:
20 | - uses: actions/checkout@v2
21 | - name: Cache local Maven repository
22 | uses: actions/cache@v2
23 | with:
24 | path: ~/.m2/repository
25 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
26 | restore-keys: ${{ runner.os }}-maven-
27 | - name: Download ${{ matrix.version }}
28 | uses: sdkman/sdkman-action@master
29 | id: sdkman
30 | with:
31 | candidate: java
32 | version: ${{ matrix.version }}
33 | - name: Set up ${{ matrix.version }}
34 | uses: actions/setup-java@v1
35 | with:
36 | java-version: 8
37 | jdkFile: ${{ steps.sdkman.outputs.file }}
38 | - name: Build with Maven
39 | run: ./mvnw verify
40 |
--------------------------------------------------------------------------------
/src/test/java/com/maciejwalkowiak/paseq/TaskTests.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 | import static org.assertj.core.api.Assertions.assertThat;
4 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
5 |
6 | import org.junit.jupiter.api.Test;
7 |
8 | /**
9 | * Tests for {@link Task}.
10 | *
11 | * @author Maciej Walkowiak
12 | */
13 | class TaskTests {
14 |
15 | @Test
16 | void throwsExceptionWhenTaskDoesNotHaveGoalNorCommand() {
17 | var task = new Task();
18 | assertThatThrownBy(task::validate).isInstanceOf(InvalidTaskDefinitionException.class);
19 | }
20 |
21 | @Test
22 | void taskIsSyncByDefault() {
23 | var task = Task.withGoals("clean").build();
24 | assertThat(task.isAsync()).isFalse();
25 | }
26 |
27 | @Test
28 | void taskDoesNotWaitByDefault() {
29 | var task = Task.withGoals("clean").build();
30 | assertThat(task.isWait()).isFalse();
31 | }
32 |
33 | @Test
34 | void throwsExceptionWhenTaskHasBothGoalsAndCommand() {
35 | var task = Task.withGoals("clean").setExec(new Exec("ls -l")).build();
36 | assertThatThrownBy(task::validate).isInstanceOf(InvalidTaskDefinitionException.class);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/maciejwalkowiak/paseq/Exec.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 |
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | /**
7 | * Configuration for executing a command.
8 | *
9 | * @author Maciej Walkowiak
10 | */
11 | public class Exec {
12 | /**
13 | * Command to execute.
14 | */
15 | private String command;
16 |
17 | /**
18 | * Directory from which the command is meant to be executed.
19 | */
20 | private @Nullable String directory;
21 |
22 | // public no-arg constructor is required by maven
23 | public Exec() {
24 | }
25 |
26 | Exec(String command) {
27 | this(command, null);
28 | }
29 |
30 | public Exec(String command, @Nullable String directory) {
31 | this.command = command;
32 | this.directory = directory;
33 | }
34 |
35 | public String getCommand() {
36 | return command;
37 | }
38 |
39 | public @Nullable String getDirectory() {
40 | return directory;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return "Exec{" + "command='" + command + '\'' + ", directory='" + directory + '\'' + '}';
46 | }
47 |
48 | String toLoggableString() {
49 | return command + (directory != null ? " in directory: " + directory : "");
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/resources-its/com/maciejwalkowiak/paseq/ExecMojoTestIT/the_first_test_case/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.example
7 | demo
8 | 0.0.1-SNAPSHOT
9 | new-spring-boot-app
10 | Demo project for Spring Boot
11 |
12 | 11
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | com.maciejwalkowiak.paseq
21 | paseq-maven-plugin
22 | 0.1.0-SNAPSHOT
23 |
24 |
25 |
26 | true
27 |
28 | ps aux
29 |
30 |
31 |
32 | true
33 |
34 | ${project.basedir}/..
35 | ls -l
36 |
37 |
38 |
39 | dependency:tree
40 |
41 |
42 | true
43 | help:active-profiles
44 |
45 |
46 | clean,compile
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Paseq Maven Plugin
2 |
3 | 
4 |
5 | by [@maciejwalkowiak](https://twitter.com/maciejwalkowiak)
6 |
7 | Paseq Maven Plugin executes series of commands or Maven goals sequentially or in parallel.
8 |
9 | ## Example
10 |
11 | Plugin has to be configured in `build/plugins` section of `pom.xml`:
12 |
13 | ```xml
14 |
15 |
16 |
17 |
18 | com.maciejwalkowiak.paseq
19 | paseq-maven-plugin
20 | 0.1.1
21 |
22 |
23 |
24 |
25 |
26 | etc
27 | docker-compose up -d --wait
28 |
29 |
30 |
31 |
32 | true
33 |
34 | npx run develop
35 |
36 |
37 |
38 |
39 | spring-boot:run
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ```
48 |
49 | Then the series of commands can be executed with:
50 |
51 | ```bash
52 | $ mvn paseq:exec
53 | ```
54 |
55 | ## Configuration
56 |
57 | **Task** can have either `goals` or `exec` configured:
58 |
59 | - `goals` - Maven goals or lifecycle phases. Can be either a list or comma-separated list
60 | - `exec` - executable run in a separate process. Must have `command` configured, and optionally can have `directory` which sets the directory in which the command gets executed
61 | - `async` - if task should be executed in the background thread. By default `false`
62 | - `wait` - if task should wait for all async tasks started before
63 |
64 | ---
65 | [Belt icons created by Freepik - Flaticon](https://www.flaticon.com/free-icons/belt)
66 |
--------------------------------------------------------------------------------
/src/main/java/com/maciejwalkowiak/paseq/Task.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 |
4 | import java.util.Arrays;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | /**
8 | * Defines a task. Either {@link #goals} {@link #exec} can be defined on a
9 | * single task.
10 | *
11 | * @author Maciej Walkowiak
12 | */
13 | public class Task {
14 | /**
15 | * If task is executed in a background thread.
16 | */
17 | private boolean async;
18 |
19 | /**
20 | * If task should wait for all previously started async tasks to finish.
21 | */
22 | private boolean wait;
23 |
24 | /**
25 | * Maven goals to run in this task.
26 | */
27 | private @Nullable String[] goals;
28 |
29 | /**
30 | * Configuration for the command to run in this task.
31 | */
32 | private @Nullable Exec exec;
33 |
34 | // public no-arg constructor is required by maven
35 | public Task() {
36 | }
37 |
38 | static TaskBuilder withGoals(String... goals) {
39 | return new TaskBuilder().setGoals(goals);
40 | }
41 |
42 | static TaskBuilder withCommand(String command) {
43 | return withCommand(command, null);
44 | }
45 |
46 | static TaskBuilder withCommand(String command, @Nullable String directory) {
47 | return new TaskBuilder().setExec(new Exec(command, directory));
48 | }
49 |
50 | Task(boolean async, boolean wait, @Nullable String[] goals, @Nullable Exec exec) {
51 | this.async = async;
52 | this.wait = wait;
53 | this.goals = goals;
54 | this.exec = exec;
55 | }
56 |
57 | /**
58 | * Checks if task is in valid state.
59 | *
60 | * @throws InvalidTaskDefinitionException
61 | * when task is not in valid state.
62 | */
63 | public void validate() {
64 | if (!hasGoals() && !hasCommand()) {
65 | throw new InvalidTaskDefinitionException("Either `goals` or `command` must be set on a task");
66 | }
67 | if (hasGoals() && hasCommand()) {
68 | throw new InvalidTaskDefinitionException("Task cannot have both `goals` or `command` set");
69 | }
70 | }
71 |
72 | boolean hasGoals() {
73 | return goals != null && goals.length > 0;
74 | }
75 |
76 | boolean hasCommand() {
77 | return exec != null && exec.getCommand() != null;
78 | }
79 |
80 | public boolean isWait() {
81 | return wait;
82 | }
83 |
84 | public @Nullable Exec getExec() {
85 | return exec;
86 | }
87 |
88 | public @Nullable String[] getGoals() {
89 | return goals;
90 | }
91 |
92 | public boolean isAsync() {
93 | return async;
94 | }
95 |
96 | String toLoggableString() {
97 | String loggableString;
98 | if (hasGoals()) {
99 | loggableString = Arrays.toString(goals);
100 | } else if (hasCommand()) {
101 | loggableString = exec.toLoggableString();
102 | } else {
103 | throw new RuntimeException(
104 | "Task is invalid state. Looks like a bug in task validation. You must set either task goals or the command");
105 | }
106 | return loggableString + " (" + (async ? "async" : "sync") + ")";
107 | }
108 |
109 | @Override
110 | public String toString() {
111 | return "Task{" + "async=" + async + ", wait=" + wait + ", goals=" + Arrays.toString(goals) + ", exec=" + exec
112 | + '}';
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/maciejwalkowiak/paseq/ExecMojo.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 |
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.concurrent.CompletableFuture;
10 | import java.util.concurrent.CompletionException;
11 | import org.apache.maven.plugin.AbstractMojo;
12 | import org.apache.maven.plugin.MojoExecutionException;
13 | import org.apache.maven.plugins.annotations.Component;
14 | import org.apache.maven.plugins.annotations.Mojo;
15 | import org.apache.maven.plugins.annotations.Parameter;
16 | import org.apache.maven.shared.invoker.DefaultInvocationRequest;
17 | import org.apache.maven.shared.invoker.InvocationRequest;
18 | import org.apache.maven.shared.invoker.InvocationResult;
19 | import org.apache.maven.shared.invoker.Invoker;
20 | import org.apache.maven.shared.invoker.MavenInvocationException;
21 |
22 | /**
23 | * Executes series of tasks.
24 | */
25 | @Mojo(name = "exec")
26 | public class ExecMojo extends AbstractMojo {
27 |
28 | @Parameter(property = "tasks")
29 | private Task[] tasks;
30 |
31 | @Component
32 | protected Invoker invoker;
33 |
34 | // public no-arg constructor is required by maven
35 | public ExecMojo() {
36 | }
37 |
38 | ExecMojo(List tasks, Invoker invoker) {
39 | this.tasks = tasks.toArray(new Task[]{});
40 | this.invoker = invoker;
41 | }
42 |
43 | public void execute() throws MojoExecutionException {
44 | // validate
45 | try {
46 | Arrays.stream(tasks).forEach(Task::validate);
47 | } catch (InvalidTaskDefinitionException e) {
48 | getLog().error(e.getMessage());
49 | throw e;
50 | }
51 |
52 | List> futures = new ArrayList<>();
53 |
54 | for (Task task : tasks) {
55 | if (task.isAsync()) {
56 | futures.add(CompletableFuture.runAsync(() -> {
57 | try {
58 | runAndLog(task);
59 | } catch (MojoExecutionException e) {
60 | throw new CompletionException(e);
61 | }
62 | }));
63 | } else {
64 | if (task.isWait()) {
65 | waitAndClear(futures);
66 | }
67 | runAndLog(task);
68 | }
69 | }
70 | waitAndClear(futures);
71 | }
72 |
73 | private void runAndLog(Task task) throws MojoExecutionException {
74 | getLog().info("Started invocation of " + task.toLoggableString());
75 | run(task);
76 | getLog().info("Finished invocation of " + task.toLoggableString());
77 | }
78 |
79 | private void run(Task task) throws MojoExecutionException {
80 | if (task.hasGoals()) {
81 | invoke(toInvocationRequest(task));
82 | } else if (task.getExec() != null && task.hasCommand()) {
83 | try {
84 | ProcessBuilder processBuilder = new ProcessBuilder();
85 | Exec exec = task.getExec();
86 | if (exec.getDirectory() != null) {
87 | processBuilder.directory(new File(exec.getDirectory()));
88 | }
89 | Process process = processBuilder.command(exec.getCommand().split(" ")).inheritIO().start();
90 | int result = process.waitFor();
91 | process.destroy();
92 |
93 | if (result != 0) {
94 | throw new MojoExecutionException("Running task " + task + " finished with a exit code " + result);
95 | }
96 | } catch (IOException | InterruptedException e) {
97 | throw new RuntimeException(e);
98 | }
99 | } else {
100 | throw new RuntimeException("either goals or command has to be set");
101 | }
102 | }
103 |
104 | private void waitAndClear(List> futures) throws MojoExecutionException {
105 | if (!futures.isEmpty()) {
106 | for (CompletableFuture> future : futures) {
107 | try {
108 | future.join();
109 | } catch (CompletionException e) {
110 | if (e.getCause() instanceof MojoExecutionException) {
111 | throw (MojoExecutionException) e.getCause();
112 | } else {
113 | throw new RuntimeException(e);
114 | }
115 | }
116 | }
117 | futures.clear();
118 | }
119 | }
120 |
121 | private void invoke(InvocationRequest invocationRequest) throws MojoExecutionException {
122 | try {
123 | InvocationResult result = invoker.execute(invocationRequest);
124 | if (result.getExitCode() != 0 || result.getExecutionException() != null) {
125 | throw new MojoExecutionException(result.getExecutionException());
126 | }
127 | } catch (MavenInvocationException e) {
128 | throw new MojoExecutionException(e);
129 | }
130 | }
131 |
132 | private static InvocationRequest toInvocationRequest(Task task) {
133 | InvocationRequest invocationRequest = new DefaultInvocationRequest();
134 | invocationRequest.setGoals(Arrays.asList(task.getGoals()));
135 | return invocationRequest;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/test/java/com/maciejwalkowiak/paseq/ExecMojoTests.java:
--------------------------------------------------------------------------------
1 | package com.maciejwalkowiak.paseq;
2 |
3 | import static org.assertj.core.api.Assertions.assertThat;
4 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
5 | import static org.mockito.ArgumentMatchers.any;
6 | import static org.mockito.ArgumentMatchers.argThat;
7 | import static org.mockito.Mockito.mock;
8 | import static org.mockito.Mockito.verify;
9 | import static org.mockito.Mockito.when;
10 |
11 | import java.io.IOException;
12 | import java.nio.file.Files;
13 | import java.nio.file.Path;
14 | import java.util.Arrays;
15 | import java.util.Collections;
16 | import org.apache.maven.plugin.MojoExecutionException;
17 | import org.apache.maven.shared.invoker.InvocationResult;
18 | import org.apache.maven.shared.invoker.Invoker;
19 | import org.apache.maven.shared.invoker.MavenInvocationException;
20 | import org.apache.maven.shared.utils.cli.CommandLineException;
21 | import org.junit.jupiter.api.BeforeEach;
22 | import org.junit.jupiter.api.Test;
23 |
24 | /**
25 | * Unit tests for {@link ExecMojo}.
26 | *
27 | * @author Maciej Walkowiak
28 | */
29 | class ExecMojoTests {
30 |
31 | private final Invoker invoker = mock(Invoker.class);
32 |
33 | // configured in maven-surefire-plugin
34 | private final String directory = System.getProperty("buildDirectory");
35 |
36 | @BeforeEach
37 | void cleanup() throws IOException {
38 | Files.deleteIfExists(Path.of(directory).resolve("test-file"));
39 | }
40 |
41 | @Test
42 | void failsWhenTasksAreInvalid() {
43 | var mojo = new ExecMojo(Collections.singletonList(new Task()), invoker);
44 | assertThatThrownBy(mojo::execute).isInstanceOf(InvalidTaskDefinitionException.class);
45 | }
46 |
47 | @Test
48 | void executesMavenGoals() throws MavenInvocationException, MojoExecutionException {
49 | when(invoker.execute(any())).thenReturn(new DummyInvocationResult(0));
50 | var mojo = new ExecMojo(Collections.singletonList(Task.withGoals("clean", "install").build()), invoker);
51 | mojo.execute();
52 | verify(invoker).execute(argThat(invocationRequest -> {
53 | assertThat(invocationRequest.getGoals()).containsExactly("clean", "install");
54 | return true;
55 | }));
56 | }
57 |
58 | @Test
59 | void executesCommand() throws MojoExecutionException {
60 | var command = "touch test-file";
61 | var mojo = new ExecMojo(Collections.singletonList(Task.withCommand(command, directory).build()), invoker);
62 | mojo.execute();
63 | assertThat(Path.of(directory).resolve("test-file")).exists();
64 | }
65 |
66 | @Test
67 | void failsWhenCommandExecutionFails() {
68 | var mojo = new ExecMojo(
69 | Arrays.asList(Task.withCommand("touch non-existing-directory/bar.txt", directory).build(),
70 | Task.withCommand("touch test-file", directory).build()),
71 | invoker);
72 | assertThatThrownBy(mojo::execute).isInstanceOf(MojoExecutionException.class);
73 | assertThat(Path.of(directory).resolve("test-file")).doesNotExist();
74 | }
75 |
76 | @Test
77 | void failsWhenGoalExecutionFails() throws MavenInvocationException {
78 | when(invoker.execute(any())).thenReturn(new DummyInvocationResult(1));
79 | var mojo = new ExecMojo(Arrays.asList(Task.withGoals("compile", directory).build(),
80 | Task.withCommand("touch test-file", directory).build()), invoker);
81 | assertThatThrownBy(mojo::execute).isInstanceOf(MojoExecutionException.class);
82 | assertThat(Path.of(directory).resolve("test-file")).doesNotExist();
83 | }
84 |
85 | @Test
86 | void executesGoalAndCommandSequentially() throws MavenInvocationException, MojoExecutionException {
87 | var commandTask = Task.withCommand("touch test-file", directory).build();
88 | var goalTask = Task.withGoals("package").build();
89 | var mojo = new ExecMojo(Arrays.asList(goalTask, commandTask), invoker);
90 | when(invoker.execute(any())).thenReturn(new DummyInvocationResult(0));
91 |
92 | mojo.execute();
93 |
94 | verify(invoker).execute(argThat(invocationRequest -> {
95 | assertThat(invocationRequest.getGoals()).containsExactly("package");
96 | return true;
97 | }));
98 | assertThat(Path.of(directory).resolve("test-file")).exists();
99 | }
100 |
101 | @Test
102 | void waitsForAllAsyncTasksToFinish() throws MavenInvocationException, MojoExecutionException {
103 | var commandTask = Task.withCommand("touch test-file", directory).async().build();
104 | var goalTask = Task.withGoals("package").async().build();
105 | var mojo = new ExecMojo(Arrays.asList(goalTask, commandTask), invoker);
106 | when(invoker.execute(any())).thenReturn(new DummyInvocationResult(0));
107 |
108 | mojo.execute();
109 |
110 | verify(invoker).execute(argThat(invocationRequest -> {
111 | assertThat(invocationRequest.getGoals()).containsExactly("package");
112 | return true;
113 | }));
114 | assertThat(Path.of(directory).resolve("test-file")).exists();
115 | }
116 |
117 | static class DummyInvocationResult implements InvocationResult {
118 | private final int exitCode;
119 | private final CommandLineException commandLineException;
120 |
121 | DummyInvocationResult(int exitCode, CommandLineException commandLineException) {
122 | this.exitCode = exitCode;
123 | this.commandLineException = commandLineException;
124 | }
125 |
126 | public DummyInvocationResult(int exitCode) {
127 | this(exitCode, null);
128 | }
129 |
130 | @Override
131 | public CommandLineException getExecutionException() {
132 | return commandLineException;
133 | }
134 |
135 | @Override
136 | public int getExitCode() {
137 | return exitCode;
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Apache Maven Wrapper startup batch script, version 3.1.1
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
30 | @REM e.g. to debug Maven itself, use
31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
33 | @REM ----------------------------------------------------------------------------
34 |
35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
36 | @echo off
37 | @REM set title of command window
38 | title %0
39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
41 |
42 | @REM set %HOME% to equivalent of $HOME
43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
44 |
45 | @REM Execute a user defined script before this one
46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
50 | :skipRcPre
51 |
52 | @setlocal
53 |
54 | set ERROR_CODE=0
55 |
56 | @REM To isolate internal variables from possible post scripts, we use another setlocal
57 | @setlocal
58 |
59 | @REM ==== START VALIDATION ====
60 | if not "%JAVA_HOME%" == "" goto OkJHome
61 |
62 | echo.
63 | echo Error: JAVA_HOME not found in your environment. >&2
64 | echo Please set the JAVA_HOME variable in your environment to match the >&2
65 | echo location of your Java installation. >&2
66 | echo.
67 | goto error
68 |
69 | :OkJHome
70 | if exist "%JAVA_HOME%\bin\java.exe" goto init
71 |
72 | echo.
73 | echo Error: JAVA_HOME is set to an invalid directory. >&2
74 | echo JAVA_HOME = "%JAVA_HOME%" >&2
75 | echo Please set the JAVA_HOME variable in your environment to match the >&2
76 | echo location of your Java installation. >&2
77 | echo.
78 | goto error
79 |
80 | @REM ==== END VALIDATION ====
81 |
82 | :init
83 |
84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
85 | @REM Fallback to current working directory if not found.
86 |
87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
89 |
90 | set EXEC_DIR=%CD%
91 | set WDIR=%EXEC_DIR%
92 | :findBaseDir
93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
94 | cd ..
95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
96 | set WDIR=%CD%
97 | goto findBaseDir
98 |
99 | :baseDirFound
100 | set MAVEN_PROJECTBASEDIR=%WDIR%
101 | cd "%EXEC_DIR%"
102 | goto endDetectBaseDir
103 |
104 | :baseDirNotFound
105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
106 | cd "%EXEC_DIR%"
107 |
108 | :endDetectBaseDir
109 |
110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
111 |
112 | @setlocal EnableExtensions EnableDelayedExpansion
113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
115 |
116 | :endReadAdditionalConfig
117 |
118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
123 |
124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | if "%MVNW_VERBOSE%" == "true" (
132 | echo Found %WRAPPER_JAR%
133 | )
134 | ) else (
135 | if not "%MVNW_REPOURL%" == "" (
136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
137 | )
138 | if "%MVNW_VERBOSE%" == "true" (
139 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
140 | echo Downloading from: %WRAPPER_URL%
141 | )
142 |
143 | powershell -Command "&{"^
144 | "$webclient = new-object System.Net.WebClient;"^
145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
147 | "}"^
148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
149 | "}"
150 | if "%MVNW_VERBOSE%" == "true" (
151 | echo Finished downloading %WRAPPER_JAR%
152 | )
153 | )
154 | @REM End of extension
155 |
156 | @REM Provide a "standardized" way to retrieve the CLI args that will
157 | @REM work with both Windows and non-Windows executions.
158 | set MAVEN_CMD_LINE_ARGS=%*
159 |
160 | %MAVEN_JAVA_EXE% ^
161 | %JVM_CONFIG_MAVEN_PROPS% ^
162 | %MAVEN_OPTS% ^
163 | %MAVEN_DEBUG_OPTS% ^
164 | -classpath %WRAPPER_JAR% ^
165 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
166 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
167 | if ERRORLEVEL 1 goto error
168 | goto end
169 |
170 | :error
171 | set ERROR_CODE=1
172 |
173 | :end
174 | @endlocal & set ERROR_CODE=%ERROR_CODE%
175 |
176 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
177 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
178 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
179 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
180 | :skipRcPost
181 |
182 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
183 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
184 |
185 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
186 |
187 | cmd /C exit /B %ERROR_CODE%
188 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.maciejwalkowiak.paseq
7 | paseq-maven-plugin
8 | 0.1.2-SNAPSHOT
9 | maven-plugin
10 | Paseq Maven Plugin
11 | Maven Plugin for running Maven goals and commands sequentially or in parallel
12 |
13 | ${maven.version}
14 |
15 |
16 | https://github.com/maciejwalkowiak/paseq-maven-plugin/
17 |
18 | https://github.com/maciejwalkowiak/paseq-maven-plugin
19 | scm:git:git://github.com/maciejwalkowiak/paseq-maven-plugin.git
20 |
21 |
22 | scm:git:ssh://git@github.com/maciejwalkowiak/paseq-maven-plugin.git
23 |
24 | HEAD
25 |
26 |
27 |
28 | UTF-8
29 | 11
30 | 11
31 | 3.8.6
32 | 2.27.2
33 |
34 |
35 |
36 |
37 | org.jetbrains
38 | annotations
39 | 16.0.2
40 | compile
41 |
42 |
43 | org.apache.maven.shared
44 | maven-invoker
45 | 3.2.0
46 |
47 |
48 | org.apache.maven
49 | maven-plugin-api
50 | ${maven.version}
51 | provided
52 |
53 |
54 | org.apache.maven
55 | maven-core
56 | ${maven.version}
57 | provided
58 |
59 |
60 | org.apache.maven
61 | maven-artifact
62 | ${maven.version}
63 | provided
64 |
65 |
66 | org.apache.maven
67 | maven-compat
68 | ${maven.version}
69 | test
70 |
71 |
72 | org.apache.maven.plugin-tools
73 | maven-plugin-annotations
74 | 3.6.4
75 | provided
76 |
77 |
78 | org.junit.jupiter
79 | junit-jupiter-engine
80 | 5.9.0
81 | test
82 |
83 |
84 | com.soebes.itf.jupiter.extension
85 | itf-jupiter-extension
86 | 0.11.0
87 | test
88 |
89 |
90 | com.soebes.itf.jupiter.extension
91 | itf-assertj
92 | 0.11.0
93 | test
94 |
95 |
96 | org.mockito
97 | mockito-core
98 | 4.8.0
99 | test
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | maven-clean-plugin
108 | 3.2.0
109 |
110 |
111 | maven-resources-plugin
112 | 3.3.0
113 |
114 |
115 | maven-compiler-plugin
116 | 3.10.1
117 |
118 |
119 | maven-plugin-plugin
120 | 3.6.4
121 |
122 |
123 | maven-surefire-plugin
124 | 2.22.2
125 |
126 |
127 | maven-failsafe-plugin
128 | 2.22.2
129 |
130 |
131 | maven-jar-plugin
132 | 3.3.0
133 |
134 |
135 | maven-install-plugin
136 | 3.0.1
137 |
138 |
139 | maven-deploy-plugin
140 | 3.0.0
141 |
142 |
143 | maven-invoker-plugin
144 | 3.3.0
145 |
146 |
147 |
148 |
149 |
150 | com.soebes.itf.jupiter.extension
151 | itf-maven-plugin
152 | 0.11.0
153 |
154 |
155 | installing
156 | pre-integration-test
157 |
158 | install
159 | resources-its
160 |
161 |
162 |
163 |
164 |
165 |
166 | org.apache.maven.plugins
167 | maven-surefire-plugin
168 |
169 |
170 | ${project.build.directory}
171 |
172 |
173 |
174 |
175 |
176 | org.apache.maven.plugins
177 | maven-failsafe-plugin
178 |
179 |
182 |
183 | ${maven.version}
184 | ${maven.home}
185 |
186 |
187 |
188 |
189 |
190 | integration-test
191 | verify
192 |
193 |
194 |
195 |
196 |
197 |
198 | com.diffplug.spotless
199 | spotless-maven-plugin
200 | ${spotless.version}
201 |
202 |
203 | process-sources
204 |
205 | apply
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 | true
214 | 4
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 | MIT License
227 | http://www.opensource.org/licenses/mit-license.php
228 | repo
229 |
230 |
231 |
232 |
233 |
234 | maciejwalkowiak
235 | Maciej Walkowiak
236 |
237 |
238 |
239 |
240 |
241 | release
242 |
243 |
244 |
245 | org.jreleaser
246 | jreleaser-maven-plugin
247 | 1.3.1
248 |
249 |
250 |
251 | ALWAYS
252 | true
253 |
254 |
255 |
256 |
257 |
258 | ALWAYS
259 | https://s01.oss.sonatype.org/service/local;
260 |
261 | false
262 | false
263 | target/staging-deploy
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 | org.apache.maven.plugins
273 | maven-javadoc-plugin
274 | 3.4.1
275 |
276 |
277 | attach-javadoc
278 |
279 | jar
280 |
281 |
282 |
283 |
284 |
285 | org.apache.maven.plugins
286 | maven-source-plugin
287 | 3.2.1
288 |
289 |
290 | attach-source
291 |
292 | jar
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Apache Maven Wrapper startup batch script, version 3.1.1
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | # e.g. to debug Maven itself, use
32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | # ----------------------------------------------------------------------------
35 |
36 | if [ -z "$MAVEN_SKIP_RC" ] ; then
37 |
38 | if [ -f /usr/local/etc/mavenrc ] ; then
39 | . /usr/local/etc/mavenrc
40 | fi
41 |
42 | if [ -f /etc/mavenrc ] ; then
43 | . /etc/mavenrc
44 | fi
45 |
46 | if [ -f "$HOME/.mavenrc" ] ; then
47 | . "$HOME/.mavenrc"
48 | fi
49 |
50 | fi
51 |
52 | # OS specific support. $var _must_ be set to either true or false.
53 | cygwin=false;
54 | darwin=false;
55 | mingw=false
56 | case "`uname`" in
57 | CYGWIN*) cygwin=true ;;
58 | MINGW*) mingw=true;;
59 | Darwin*) darwin=true
60 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
61 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
62 | if [ -z "$JAVA_HOME" ]; then
63 | if [ -x "/usr/libexec/java_home" ]; then
64 | JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME
65 | else
66 | JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
67 | fi
68 | fi
69 | ;;
70 | esac
71 |
72 | if [ -z "$JAVA_HOME" ] ; then
73 | if [ -r /etc/gentoo-release ] ; then
74 | JAVA_HOME=`java-config --jre-home`
75 | fi
76 | fi
77 |
78 | # For Cygwin, ensure paths are in UNIX format before anything is touched
79 | if $cygwin ; then
80 | [ -n "$JAVA_HOME" ] &&
81 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
82 | [ -n "$CLASSPATH" ] &&
83 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
84 | fi
85 |
86 | # For Mingw, ensure paths are in UNIX format before anything is touched
87 | if $mingw ; then
88 | [ -n "$JAVA_HOME" ] &&
89 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
90 | fi
91 |
92 | if [ -z "$JAVA_HOME" ]; then
93 | javaExecutable="`which javac`"
94 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
95 | # readlink(1) is not available as standard on Solaris 10.
96 | readLink=`which readlink`
97 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
98 | if $darwin ; then
99 | javaHome="`dirname \"$javaExecutable\"`"
100 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
101 | else
102 | javaExecutable="`readlink -f \"$javaExecutable\"`"
103 | fi
104 | javaHome="`dirname \"$javaExecutable\"`"
105 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
106 | JAVA_HOME="$javaHome"
107 | export JAVA_HOME
108 | fi
109 | fi
110 | fi
111 |
112 | if [ -z "$JAVACMD" ] ; then
113 | if [ -n "$JAVA_HOME" ] ; then
114 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
115 | # IBM's JDK on AIX uses strange locations for the executables
116 | JAVACMD="$JAVA_HOME/jre/sh/java"
117 | else
118 | JAVACMD="$JAVA_HOME/bin/java"
119 | fi
120 | else
121 | JAVACMD="`\\unset -f command; \\command -v java`"
122 | fi
123 | fi
124 |
125 | if [ ! -x "$JAVACMD" ] ; then
126 | echo "Error: JAVA_HOME is not defined correctly." >&2
127 | echo " We cannot execute $JAVACMD" >&2
128 | exit 1
129 | fi
130 |
131 | if [ -z "$JAVA_HOME" ] ; then
132 | echo "Warning: JAVA_HOME environment variable is not set."
133 | fi
134 |
135 | # traverses directory structure from process work directory to filesystem root
136 | # first directory with .mvn subdirectory is considered project base directory
137 | find_maven_basedir() {
138 | if [ -z "$1" ]
139 | then
140 | echo "Path not specified to find_maven_basedir"
141 | return 1
142 | fi
143 |
144 | basedir="$1"
145 | wdir="$1"
146 | while [ "$wdir" != '/' ] ; do
147 | if [ -d "$wdir"/.mvn ] ; then
148 | basedir=$wdir
149 | break
150 | fi
151 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
152 | if [ -d "${wdir}" ]; then
153 | wdir=`cd "$wdir/.."; pwd`
154 | fi
155 | # end of workaround
156 | done
157 | printf '%s' "$(cd "$basedir"; pwd)"
158 | }
159 |
160 | # concatenates all lines of a file
161 | concat_lines() {
162 | if [ -f "$1" ]; then
163 | echo "$(tr -s '\n' ' ' < "$1")"
164 | fi
165 | }
166 |
167 | BASE_DIR=$(find_maven_basedir "$(dirname $0)")
168 | if [ -z "$BASE_DIR" ]; then
169 | exit 1;
170 | fi
171 |
172 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
173 | if [ "$MVNW_VERBOSE" = true ]; then
174 | echo $MAVEN_PROJECTBASEDIR
175 | fi
176 |
177 | ##########################################################################################
178 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
179 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
180 | ##########################################################################################
181 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
182 | if [ "$MVNW_VERBOSE" = true ]; then
183 | echo "Found .mvn/wrapper/maven-wrapper.jar"
184 | fi
185 | else
186 | if [ "$MVNW_VERBOSE" = true ]; then
187 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
188 | fi
189 | if [ -n "$MVNW_REPOURL" ]; then
190 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
191 | else
192 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
193 | fi
194 | while IFS="=" read key value; do
195 | case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;;
196 | esac
197 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
198 | if [ "$MVNW_VERBOSE" = true ]; then
199 | echo "Downloading from: $wrapperUrl"
200 | fi
201 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
202 | if $cygwin; then
203 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
204 | fi
205 |
206 | if command -v wget > /dev/null; then
207 | QUIET="--quiet"
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found wget ... using wget"
210 | QUIET=""
211 | fi
212 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
213 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath"
214 | else
215 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath"
216 | fi
217 | [ $? -eq 0 ] || rm -f "$wrapperJarPath"
218 | elif command -v curl > /dev/null; then
219 | QUIET="--silent"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Found curl ... using curl"
222 | QUIET=""
223 | fi
224 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
225 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L
226 | else
227 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L
228 | fi
229 | [ $? -eq 0 ] || rm -f "$wrapperJarPath"
230 | else
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Falling back to using Java to download"
233 | fi
234 | javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
235 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class"
236 | # For Cygwin, switch paths to Windows format before running javac
237 | if $cygwin; then
238 | javaSource=`cygpath --path --windows "$javaSource"`
239 | javaClass=`cygpath --path --windows "$javaClass"`
240 | fi
241 | if [ -e "$javaSource" ]; then
242 | if [ ! -e "$javaClass" ]; then
243 | if [ "$MVNW_VERBOSE" = true ]; then
244 | echo " - Compiling MavenWrapperDownloader.java ..."
245 | fi
246 | # Compiling the Java class
247 | ("$JAVA_HOME/bin/javac" "$javaSource")
248 | fi
249 | if [ -e "$javaClass" ]; then
250 | # Running the downloader
251 | if [ "$MVNW_VERBOSE" = true ]; then
252 | echo " - Running MavenWrapperDownloader.java ..."
253 | fi
254 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
255 | fi
256 | fi
257 | fi
258 | fi
259 | ##########################################################################################
260 | # End of extension
261 | ##########################################################################################
262 |
263 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
264 |
265 | # For Cygwin, switch paths to Windows format before running java
266 | if $cygwin; then
267 | [ -n "$JAVA_HOME" ] &&
268 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
269 | [ -n "$CLASSPATH" ] &&
270 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
271 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
272 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
273 | fi
274 |
275 | # Provide a "standardized" way to retrieve the CLI args that will
276 | # work with both Windows and non-Windows executions.
277 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
278 | export MAVEN_CMD_LINE_ARGS
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | $MAVEN_DEBUG_OPTS \
285 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
286 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
287 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
288 |
--------------------------------------------------------------------------------