| @@ -0,0 +1,52 | |||
|
|
1 | package org.implab.gradle.common.tasks; | |
|
|
2 | ||
|
|
3 | import org.gradle.api.DefaultTask; | |
|
|
4 | import org.gradle.api.provider.ListProperty; | |
|
|
5 | import org.gradle.api.tasks.Internal; | |
|
|
6 | import org.implab.gradle.common.dsl.RedirectFromSpec; | |
|
|
7 | import org.implab.gradle.common.dsl.RedirectToSpec; | |
|
|
8 | ||
|
|
9 | public abstract class ExecuteTask extends DefaultTask { | |
|
|
10 | ||
|
|
11 | private final RedirectToSpec redirectStderr = new RedirectToSpec(); | |
|
|
12 | ||
|
|
13 | private final RedirectToSpec redirectStdout = new RedirectToSpec(); | |
|
|
14 | ||
|
|
15 | private final RedirectFromSpec redirectStdin = new RedirectFromSpec(); | |
|
|
16 | ||
|
|
17 | @Internal | |
|
|
18 | public abstract ListProperty<String> getCommandLine(); | |
|
|
19 | ||
|
|
20 | ||
|
|
21 | /** | |
|
|
22 | * STDIN redirection, if not specified, no input will be passed to the command | |
|
|
23 | */ | |
|
|
24 | @Internal | |
|
|
25 | public RedirectFromSpec getStdin() { | |
|
|
26 | return redirectStdin; | |
|
|
27 | } | |
|
|
28 | ||
|
|
29 | /** | |
|
|
30 | * STDOUT redirection, if not specified, redirected to logger::info | |
|
|
31 | */ | |
|
|
32 | @Internal | |
|
|
33 | public RedirectToSpec getStdout() { | |
|
|
34 | return redirectStdout; | |
|
|
35 | } | |
|
|
36 | ||
|
|
37 | /** | |
|
|
38 | * STDERR redirection, if not specified, redirected to logger::error | |
|
|
39 | */ | |
|
|
40 | @Internal | |
|
|
41 | public RedirectToSpec getStderr() { | |
|
|
42 | return redirectStderr; | |
|
|
43 | } | |
|
|
44 | ||
|
|
45 | ||
|
|
46 | /** Appends specified parameters to the command line */ | |
|
|
47 | void commandLine(String... args) { | |
|
|
48 | getCommandLine().addAll(args); | |
|
|
49 | } | |
|
|
50 | ||
|
|
51 | ||
|
|
52 | } | |
| @@ -0,0 +1,104 | |||
|
|
1 | package org.implab.gradle.common.tasks; | |
|
|
2 | ||
|
|
3 | import java.io.IOException; | |
|
|
4 | import java.util.Optional; | |
|
|
5 | import java.util.concurrent.ExecutionException; | |
|
|
6 | ||
|
|
7 | import org.gradle.api.DefaultTask; | |
|
|
8 | import org.implab.gradle.common.dsl.ProcessSpec; | |
|
|
9 | import org.implab.gradle.common.exec.Executor; | |
|
|
10 | import org.implab.gradle.common.exec.RedirectFrom; | |
|
|
11 | import org.implab.gradle.common.exec.RedirectTo; | |
|
|
12 | ||
|
|
13 | public abstract class ExternalTask extends DefaultTask { | |
|
|
14 | ||
|
|
15 | /** | |
|
|
16 | * A default redirection to the build log when loglevel is set to INFO, | |
|
|
17 | * otherwise returns an empty redirection. | |
|
|
18 | */ | |
|
|
19 | protected Optional<RedirectTo> loggerInfoRedirect() { | |
|
|
20 | return getLogger().isInfoEnabled() | |
|
|
21 | ? Optional.of(RedirectTo.consumer(getLogger()::info)) | |
|
|
22 | : Optional.empty(); | |
|
|
23 | } | |
|
|
24 | ||
|
|
25 | /** | |
|
|
26 | * A default redirection to the build log when loglevel is set to ERROR, | |
|
|
27 | * otherwise returns an empty redirection. Note that ERROR level is set | |
|
|
28 | * by default for a build runs. | |
|
|
29 | */ | |
|
|
30 | protected Optional<RedirectTo> loggerErrorRedirect() { | |
|
|
31 | return getLogger().isErrorEnabled() | |
|
|
32 | ? Optional.of(RedirectTo.consumer(getLogger()::error)) | |
|
|
33 | : Optional.empty(); | |
|
|
34 | } | |
|
|
35 | ||
|
|
36 | /** | |
|
|
37 | * Stdout redirection for {@link #exec(ProcessSpec)}, default implementation | |
|
|
38 | * will forward stdout to the build log through {@link #loggerErrorRedirect()} | |
|
|
39 | */ | |
|
|
40 | protected Optional<RedirectTo> stdoutRedirection() { | |
|
|
41 | return loggerInfoRedirect(); | |
|
|
42 | } | |
|
|
43 | ||
|
|
44 | /** | |
|
|
45 | * Stderr redirection for {@link #exec(ProcessSpec)}, default implementation | |
|
|
46 | * will forward stderr to build log through {@link #loggerErrorRedirect()}. | |
|
|
47 | */ | |
|
|
48 | protected Optional<RedirectTo> stderrRedirection() { | |
|
|
49 | return loggerErrorRedirect(); | |
|
|
50 | } | |
|
|
51 | ||
|
|
52 | /** | |
|
|
53 | * Stdin redirection for {@link #exec(ProcessSpec)}, empty by default. | |
|
|
54 | */ | |
|
|
55 | protected Optional<RedirectFrom> stdinRedirection() { | |
|
|
56 | return Optional.empty(); | |
|
|
57 | } | |
|
|
58 | ||
|
|
59 | /** | |
|
|
60 | * Executes the specified process specification | |
|
|
61 | * | |
|
|
62 | * @param spec | |
|
|
63 | * @throws InterruptedException | |
|
|
64 | * @throws ExecutionException | |
|
|
65 | * @throws IOException | |
|
|
66 | */ | |
|
|
67 | protected void exec(ProcessSpec spec) throws InterruptedException, ExecutionException, IOException { | |
|
|
68 | var executor = exec(); | |
|
|
69 | ||
|
|
70 | stdoutRedirection().ifPresent(executor::stdout); | |
|
|
71 | stderrRedirection().ifPresent(executor::stderr); | |
|
|
72 | stdinRedirection().ifPresent(executor::stdin); | |
|
|
73 | ||
|
|
74 | getLogger().info("Staring: {}", spec.command()); | |
|
|
75 | ||
|
|
76 | spec.accept(executor); | |
|
|
77 | ||
|
|
78 | // runs the command and checks the error code | |
|
|
79 | var code = executor.start().get(); | |
|
|
80 | ||
|
|
81 | // check success code | |
|
|
82 | if (code != 0) | |
|
|
83 | throw new IOException("The process exited with error code " + code); | |
|
|
84 | } | |
|
|
85 | ||
|
|
86 | protected boolean checkRetCode(ProcessSpec proc, int code) | |
|
|
87 | throws InterruptedException, ExecutionException, IOException { | |
|
|
88 | ||
|
|
89 | var executor = exec(); | |
|
|
90 | ||
|
|
91 | if (getLogger().isInfoEnabled()) { | |
|
|
92 | loggerInfoRedirect().ifPresent(executor::stdout); | |
|
|
93 | loggerInfoRedirect().ifPresent(executor::stderr); | |
|
|
94 | } | |
|
|
95 | ||
|
|
96 | getLogger().info("Starting: {}", proc.command()); | |
|
|
97 | ||
|
|
98 | proc.accept(executor); | |
|
|
99 | ||
|
|
100 | return executor.start().get() == code; | |
|
|
101 | } | |
|
|
102 | ||
|
|
103 | protected abstract Executor exec(); | |
|
|
104 | } | |
| @@ -0,0 +1,29 | |||
|
|
1 | package org.implab.gradle.common.utils; | |
|
|
2 | ||
|
|
3 | import java.util.concurrent.atomic.AtomicReference; | |
|
|
4 | import java.util.function.Supplier; | |
|
|
5 | ||
|
|
6 | public class LazyValue<T> implements Supplier<T> { | |
|
|
7 | private final AtomicReference<T> reference = new AtomicReference<>(); | |
|
|
8 | ||
|
|
9 | private final Supplier<T> innerSupplier; | |
|
|
10 | ||
|
|
11 | public LazyValue(Supplier<T> supplier) { | |
|
|
12 | this.innerSupplier = supplier; | |
|
|
13 | } | |
|
|
14 | ||
|
|
15 | @Override | |
|
|
16 | public T get() { | |
|
|
17 | var t = reference.get(); | |
|
|
18 | if (t != null) | |
|
|
19 | return t; | |
|
|
20 | return updateValue(); | |
|
|
21 | } | |
|
|
22 | ||
|
|
23 | private T updateValue() { | |
|
|
24 | var v = innerSupplier.get(); | |
|
|
25 | var t = reference.compareAndExchange(null, v); | |
|
|
26 | return t != null ? t : v; | |
|
|
27 | } | |
|
|
28 | ||
|
|
29 | } | |
| @@ -1,39 +1,40 | |||
|
|
1 | 1 | plugins { |
|
|
2 | 2 | id "java-library" |
|
|
3 | 3 | id "ivy-publish" |
|
|
4 | 4 | } |
|
|
5 | 5 | |
|
|
6 | 6 | java { |
|
|
7 | 7 | withJavadocJar() |
|
|
8 | 8 | withSourcesJar() |
|
|
9 | 9 | toolchain { |
|
|
10 | 10 | languageVersion = JavaLanguageVersion.of(17) |
|
|
11 | 11 | } |
|
|
12 | 12 | } |
|
|
13 | 13 | |
|
|
14 | 14 | dependencies { |
|
|
15 | compileOnly "org.eclipse.jdt:org.eclipse.jdt.annotation:2.3.0" | |
|
|
15 | 16 | api gradleApi() |
|
|
16 | 17 | } |
|
|
17 | 18 | |
|
|
18 | 19 | task printVersion{ |
|
|
19 | 20 | doLast { |
|
|
20 | 21 | println "project: $project.group:$project.name:$project.version" |
|
|
21 | 22 | println "jar: ${->jar.archiveFileName.get()}" |
|
|
22 | 23 | } |
|
|
23 | 24 | } |
|
|
24 | 25 | |
|
|
25 | 26 | publishing { |
|
|
26 | 27 | repositories { |
|
|
27 | 28 | ivy { |
|
|
28 | 29 | url "${System.properties["user.home"]}/ivy-repo" |
|
|
29 | 30 | } |
|
|
30 | 31 | } |
|
|
31 | 32 | publications { |
|
|
32 | 33 | ivy(IvyPublication) { |
|
|
33 | 34 | from components.java |
|
|
34 | 35 | descriptor.description { |
|
|
35 | 36 | text = providers.provider({ description }) |
|
|
36 | 37 | } |
|
|
37 | 38 | } |
|
|
38 | 39 | } |
|
|
39 | 40 | } No newline at end of file |
| @@ -1,13 +1,23 | |||
|
|
1 | 1 | /* |
|
|
2 | 2 | * This settings file was generated by the Gradle 'init' task. |
|
|
3 | 3 | * |
|
|
4 | 4 | * The settings file is used to specify which projects to include in your build. |
|
|
5 | 5 | * In a single project build this file can be empty or even removed. |
|
|
6 | 6 | * |
|
|
7 | 7 | * Detailed information about configuring a multi-project build in Gradle can be found |
|
|
8 | 8 | * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html |
|
|
9 | 9 | */ |
|
|
10 | 10 | |
|
|
11 | dependencyResolutionManagement { | |
|
|
12 | repositories { | |
|
|
13 | mavenCentral() | |
|
|
14 | mavenLocal() | |
|
|
15 | ivy { | |
|
|
16 | url "${System.properties["user.home"]}/ivy-repo" | |
|
|
17 | } | |
|
|
18 | } | |
|
|
19 | } | |
|
|
20 | ||
|
|
11 | 21 | rootProject.name = 'gradle-common' |
|
|
12 | 22 | |
|
|
13 | 23 | include 'common' |
General Comments 0
You need to be logged in to leave comments.
Login now
