##// END OF EJS Templates
Refactoring, removed GenericSourceSetOutput.
cin -
r23:8e57f0a2d4de default
parent child
Show More
@@ -2,6 +2,7
2 2 "java.configuration.updateBuildConfiguration": "automatic",
3 3 "java.compile.nullAnalysis.mode": "automatic",
4 4 "cSpell.words": [
5 "implab"
5 "implab",
6 "rawtypes"
6 7 ]
7 8 } No newline at end of file
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.gradle;
2 2
3 3 import java.util.function.Consumer;
4 4
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.gradle;
2 2
3 3 import java.util.HashMap;
4 4 import java.util.Map;
@@ -1,4 +1,4
1 package org.implab.gradle.common.tasks;
1 package org.implab.gradle.common.core.gradle;
2 2
3 3 import org.gradle.api.Project;
4 4 import org.gradle.api.Task;
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 3 import groovy.lang.Closure;
4 4
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 3 import java.util.function.Consumer;
4 4 import java.util.function.Function;
@@ -12,7 +12,6 public class Exceptions {
12 12 * @param clazz
13 13 * @throws E
14 14 */
15 @SuppressWarnings("unused")
16 15 public static <E extends Throwable> void mayThrow(Class<E> clazz) throws E {
17 16 }
18 17
@@ -1,10 +1,10
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 import java.util.concurrent.atomic.AtomicReference;
3 import java.util.Objects;
4 4 import java.util.function.Supplier;
5 5
6 6 public class LazyValue<T> implements Supplier<T> {
7 private final AtomicReference<T> reference = new AtomicReference<>();
7 private volatile T value;
8 8
9 9 private final Supplier<T> innerSupplier;
10 10
@@ -14,16 +14,21 public class LazyValue<T> implements Sup
14 14
15 15 @Override
16 16 public T get() {
17 var t = reference.get();
18 if (t != null)
19 return t;
20 return updateValue();
17 var v = value;
18 if (v != null) {
19 return v;
21 20 }
22 21
23 private T updateValue() {
24 var v = innerSupplier.get();
25 var t = reference.compareAndExchange(null, v);
26 return t != null ? t : v;
22 synchronized (this) {
23 v = value;
24 if (v == null) {
25 v = Objects.requireNonNull(
26 innerSupplier.get(),
27 "LazyValue supplier returned null");
28 value = v;
29 }
30 return v;
31 }
27 32 }
28 33
29 34 }
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 3 import com.fasterxml.jackson.annotation.JsonCreator;
4 4 import com.fasterxml.jackson.annotation.JsonValue;
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 3 import java.util.regex.Pattern;
4 4
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.lang;
2 2
3 3 import java.text.MessageFormat;
4 4 import java.util.Iterator;
@@ -1,8 +1,6
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 import org.implab.gradle.common.utils.OperatingSystem;
4
5 public class FreeBsd extends GenericSystem{
3 class FreeBsd extends GenericSystem{
6 4
7 5 FreeBsd(String name, String version) {
8 6 super(name, version);
@@ -1,4 +1,4
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 3 import java.io.File;
4 4 import java.util.Arrays;
@@ -7,8 +7,7 import java.util.function.Function;
7 7 import java.util.regex.Pattern;
8 8 import java.util.stream.Stream;
9 9
10 import org.implab.gradle.common.utils.OperatingSystem;
11 import org.implab.gradle.common.utils.Values;
10 import org.implab.gradle.common.core.lang.Values;
12 11
13 12 class GenericSystem implements OperatingSystem {
14 13
@@ -1,8 +1,6
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 import org.implab.gradle.common.utils.OperatingSystem;
4
5 public class Linux extends GenericSystem {
3 class Linux extends GenericSystem {
6 4
7 5 Linux(String name, String version) {
8 6 super(name, version);
@@ -1,8 +1,6
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 import org.implab.gradle.common.utils.OperatingSystem;
4
5 public class MacOs extends GenericSystem {
3 class MacOs extends GenericSystem {
6 4
7 5 MacOs(String name, String version) {
8 6 super(name, version);
@@ -1,10 +1,8
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.core.os;
2 2
3 3 import java.io.File;
4 4 import java.util.Optional;
5 5
6 import org.implab.gradle.common.utils.os.SystemResolver;
7
8 6 public interface OperatingSystem {
9 7
10 8 public static final String WINDOWS_FAMILY = "windows";
@@ -1,9 +1,8
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 import org.implab.gradle.common.utils.LazyValue;
4 import org.implab.gradle.common.utils.OperatingSystem;
3 import org.implab.gradle.common.core.lang.LazyValue;
5 4
6 public class SystemResolver {
5 class SystemResolver {
7 6
8 7 private final static LazyValue<OperatingSystem> current = new LazyValue<>(SystemResolver::resolveCurrent);
9 8
@@ -1,11 +1,9
1 package org.implab.gradle.common.utils.os;
1 package org.implab.gradle.common.core.os;
2 2
3 3 import java.io.File;
4 4 import java.util.function.Function;
5 5 import java.util.stream.Stream;
6 6
7 import org.implab.gradle.common.utils.OperatingSystem;
8
9 7 class Windows extends GenericSystem {
10 8
11 9 private Stream<String> exeSuffixes = Stream.of(".cmd", ".bat", ".exe");
@@ -1,4 +1,4
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.exec.dsl;
2 2
3 3 import java.io.File;
4 4 import java.io.InputStream;
@@ -7,8 +7,8 import java.util.function.Supplier;
7 7
8 8 import org.gradle.api.provider.Provider;
9 9 import org.gradle.util.Configurable;
10 import org.implab.gradle.common.exec.RedirectFrom;
11 import org.implab.gradle.common.utils.Closures;
10 import org.implab.gradle.common.core.lang.Closures;
11 import org.implab.gradle.common.exec.runtime.RedirectFrom;
12 12
13 13 import groovy.lang.Closure;
14 14
@@ -1,4 +1,4
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.exec.dsl;
2 2
3 3 import java.io.File;
4 4 import java.io.OutputStream;
@@ -10,8 +10,8 import org.eclipse.jdt.annotation.NonNul
10 10 import org.eclipse.jdt.annotation.Nullable;
11 11 import org.gradle.api.provider.Provider;
12 12 import org.gradle.util.Configurable;
13 import org.implab.gradle.common.exec.RedirectTo;
14 import org.implab.gradle.common.utils.Closures;
13 import org.implab.gradle.common.core.lang.Closures;
14 import org.implab.gradle.common.exec.runtime.RedirectTo;
15 15
16 16 import groovy.lang.Closure;
17 17
@@ -1,9 +1,9
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.exec.dsl;
2 2
3 3 import java.util.stream.Stream;
4 4
5 5 import org.gradle.api.provider.ListProperty;
6 import org.implab.gradle.common.utils.Properties;
6 import org.implab.gradle.common.core.gradle.Properties;
7 7
8 8 public interface TaskCommandSpecMixin {
9 9 ListProperty<String> getCommandLine();
@@ -1,4 +1,4
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.exec.dsl;
2 2
3 3 import java.util.Map;
4 4
@@ -6,8 +6,8 import org.gradle.api.Action;
6 6 import org.gradle.api.file.DirectoryProperty;
7 7 import org.gradle.api.provider.MapProperty;
8 8 import org.gradle.api.provider.Property;
9 import org.implab.gradle.common.utils.Closures;
10 import org.implab.gradle.common.utils.Properties;
9 import org.implab.gradle.common.core.gradle.Properties;
10 import org.implab.gradle.common.core.lang.Closures;
11 11
12 12 import groovy.lang.Closure;
13 13
@@ -1,4 +1,4
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.exec.dsl;
2 2
3 3 import org.eclipse.jdt.annotation.NonNullByDefault;
4 4
@@ -1,11 +1,11
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2 2
3 3 import static java.util.Objects.requireNonNull;
4 4
5 5 import java.util.Optional;
6 6
7 7 import org.eclipse.jdt.annotation.NonNullByDefault;
8 import org.implab.gradle.common.utils.Values;
8 import org.implab.gradle.common.core.lang.Values;
9 9
10 10 @NonNullByDefault
11 11 public interface CommandArgumentsBuilder<S extends CommandArgumentsBuilder<S>> {
@@ -1,9 +1,9
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2 2
3 3 import java.io.File;
4 4
5 5 import org.eclipse.jdt.annotation.NonNullByDefault;
6 import org.implab.gradle.common.utils.Values;
6 import org.implab.gradle.common.core.lang.Values;
7 7
8 8 /** Command builder interface, used to specify the executable and parameters */
9 9 @NonNullByDefault
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2 2
3 3 import java.util.List;
4 4 import java.util.stream.Stream;
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2 2
3 3 import java.util.List;
4 4
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2 2
3 3 import java.io.File;
4 4 import java.util.Map;
@@ -1,4 +1,7
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.model;
2
3 import org.implab.gradle.common.exec.runtime.RedirectFrom;
4 import org.implab.gradle.common.exec.runtime.RedirectTo;
2 5
3 6 import java.util.Optional;
4 7
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.util.HashMap;
4 4 import java.util.Map;
@@ -7,6 +7,8 import java.util.concurrent.CompletableF
7 7
8 8 import org.eclipse.jdt.annotation.NonNullByDefault;
9 9 import org.eclipse.jdt.annotation.Nullable;
10 import org.implab.gradle.common.exec.model.EnvironmentSpec;
11 import org.implab.gradle.common.exec.model.PipeSpec;
10 12
11 13 import java.io.File;
12 14 import java.io.IOException;
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.ByteArrayInputStream;
4 4 import java.io.IOException;
@@ -7,6 +7,9 import java.util.concurrent.CompletableF
7 7 import java.util.stream.Collectors;
8 8
9 9 import org.eclipse.jdt.annotation.NonNullByDefault;
10 import org.implab.gradle.common.exec.model.CommandSpec;
11 import org.implab.gradle.common.exec.model.EnvironmentSpec;
12 import org.implab.gradle.common.exec.model.PipeSpec;
10 13
11 14 @NonNullByDefault
12 15 class EchoExecBuilder extends AbstractExecBuilder<CommandSpec> {
@@ -1,10 +1,11
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.File;
4 4 import java.util.Map;
5 5 import java.util.Optional;
6 6
7 7 import org.eclipse.jdt.annotation.NonNullByDefault;
8 import org.implab.gradle.common.exec.model.EnvironmentSpec;
8 9
9 10 @NonNullByDefault
10 11 public interface EnvironmentBuilder {
@@ -1,8 +1,9
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.util.Optional;
4 4
5 5 import org.eclipse.jdt.annotation.NonNullByDefault;
6 import org.implab.gradle.common.exec.model.PipeSpec;
6 7
7 8 @NonNullByDefault
8 9 public interface PipeBuilder {
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.File;
4 4 import java.io.FileInputStream;
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.File;
4 4 import java.io.FileOutputStream;
@@ -108,4 +108,4 public interface RedirectTo {
108 108 throw new IllegalArgumentException("The specified argument type isn't supported: " + output.getClass());
109 109 }
110 110 }
111 } No newline at end of file
111 }
@@ -1,6 +1,7
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import org.eclipse.jdt.annotation.NonNullByDefault;
4 import org.implab.gradle.common.exec.model.CommandSpec;
4 5
5 6 @NonNullByDefault
6 7 public interface Shell {
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.IOException;
4 4 import java.util.ArrayList;
@@ -6,7 +6,7 import java.util.List;
6 6 import java.util.concurrent.CompletableFuture;
7 7
8 8 import org.eclipse.jdt.annotation.NonNullByDefault;
9 import org.implab.gradle.common.utils.Exceptions;
9 import org.implab.gradle.common.core.lang.Exceptions;
10 10
11 11 @NonNullByDefault
12 12 public interface ShellExec extends PipeBuilder, EnvironmentBuilder {
@@ -1,7 +1,9
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import org.eclipse.jdt.annotation.NonNullByDefault;
4 4 import org.gradle.api.Action;
5 import org.implab.gradle.common.exec.model.CommandArgumentsBuilder;
6 import org.implab.gradle.common.exec.model.CommandSpec;
5 7
6 8 @NonNullByDefault
7 9 public class ShellTool {
@@ -1,4 +1,4
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec.runtime;
2 2
3 3 import java.io.IOException;
4 4 import java.lang.ProcessBuilder.Redirect;
@@ -6,6 +6,9 import java.util.ArrayList;
6 6 import java.util.concurrent.CompletableFuture;
7 7
8 8 import org.eclipse.jdt.annotation.NonNullByDefault;
9 import org.implab.gradle.common.exec.model.CommandSpec;
10 import org.implab.gradle.common.exec.model.EnvironmentSpec;
11 import org.implab.gradle.common.exec.model.PipeSpec;
9 12
10 13 @NonNullByDefault
11 14 class SystemExecBuilder extends AbstractExecBuilder<CommandSpec> {
@@ -1,4 +1,4
1 package org.implab.gradle.common.tasks;
1 package org.implab.gradle.common.exec.tasks;
2 2
3 3 import java.io.IOException;
4 4 import java.util.Map;
@@ -11,14 +11,14 import org.gradle.api.provider.MapProper
11 11 import org.gradle.api.provider.Property;
12 12 import org.gradle.api.tasks.Internal;
13 13 import org.gradle.api.tasks.TaskAction;
14 import org.implab.gradle.common.dsl.RedirectFromSpec;
15 import org.implab.gradle.common.dsl.RedirectToSpec;
16 import org.implab.gradle.common.dsl.TaskEnvSpecMixin;
17 import org.implab.gradle.common.dsl.TaskPipeSpecMixin;
18 import org.implab.gradle.common.exec.RedirectTo;
19 import org.implab.gradle.common.exec.ShellExec;
20 import org.implab.gradle.common.utils.Exceptions;
21 import org.implab.gradle.common.utils.Values;
14 import org.implab.gradle.common.core.lang.Exceptions;
15 import org.implab.gradle.common.core.lang.Values;
16 import org.implab.gradle.common.exec.dsl.RedirectFromSpec;
17 import org.implab.gradle.common.exec.dsl.RedirectToSpec;
18 import org.implab.gradle.common.exec.dsl.TaskEnvSpecMixin;
19 import org.implab.gradle.common.exec.dsl.TaskPipeSpecMixin;
20 import org.implab.gradle.common.exec.runtime.RedirectTo;
21 import org.implab.gradle.common.exec.runtime.ShellExec;
22 22
23 23 public abstract class AbstractShellExecTask
24 24 extends DefaultTask
@@ -105,4 +105,4 public abstract class AbstractShellExecT
105 105 if (code != 0)
106 106 throw new IOException(String.format("The process is terminated with code %s", code));
107 107 }
108 } No newline at end of file
108 }
@@ -1,12 +1,12
1 package org.implab.gradle.common.tasks;
1 package org.implab.gradle.common.exec.tasks;
2 2
3 3 import org.gradle.api.provider.ListProperty;
4 4 import org.gradle.api.provider.Property;
5 5 import org.gradle.api.tasks.Internal;
6 import org.implab.gradle.common.dsl.TaskCommandSpecMixin;
7 import org.implab.gradle.common.exec.CommandSpec;
8 import org.implab.gradle.common.exec.Shell;
9 import org.implab.gradle.common.exec.ShellExec;
6 import org.implab.gradle.common.exec.dsl.TaskCommandSpecMixin;
7 import org.implab.gradle.common.exec.model.CommandSpec;
8 import org.implab.gradle.common.exec.runtime.Shell;
9 import org.implab.gradle.common.exec.runtime.ShellExec;
10 10
11 11 public abstract class ShellExecTask
12 12 extends AbstractShellExecTask
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.core;
2 2
3 3 import java.io.File;
4 4 import java.io.IOException;
@@ -6,7 +6,7 import java.util.Map;
6 6 import java.util.function.Consumer;
7 7 import java.util.function.Function;
8 8
9 import org.implab.gradle.common.utils.LazyValue;
9 import org.implab.gradle.common.core.lang.LazyValue;
10 10
11 11 import com.fasterxml.jackson.annotation.JsonInclude.Include;
12 12 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.core;
2 2
3 3 import java.util.Arrays;
4 4 import java.util.LinkedHashSet;
@@ -6,7 +6,7 import java.util.Set;
6 6 import java.util.function.Predicate;
7 7
8 8 import org.gradle.api.Action;
9 import org.implab.gradle.common.utils.Closures;
9 import org.implab.gradle.common.core.lang.Closures;
10 10
11 11 import groovy.lang.Closure;
12 12
@@ -63,4 +63,4 public class MapImportSpec {
63 63 public static Predicate<String> buildPredicate(Closure<?> closure) {
64 64 return buildPredicate(Closures.action(closure));
65 65 }
66 } No newline at end of file
66 }
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3
4 4 import org.gradle.api.provider.Provider;
@@ -26,4 +26,4 public class DefaultJsonArraySpec implem
26 26 public List<Object> toList() {
27 27 return Collections.unmodifiableList(values);
28 28 }
29 } No newline at end of file
29 }
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3 import org.gradle.api.provider.Provider;
4 4
@@ -23,4 +23,4 public class DefaultJsonObjectSpec imple
23 23 public Map<String, Object> toMap() {
24 24 return Collections.unmodifiableMap(values);
25 25 }
26 } No newline at end of file
26 }
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3 import java.util.Arrays;
4 4
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3 import org.gradle.api.Action;
4 4
@@ -17,4 +17,4 public interface JsonArraySpec {
17 17 action.execute(child);
18 18 add(child.toList());
19 19 }
20 } No newline at end of file
20 }
@@ -1,10 +1,11
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3 import java.io.File;
4 4
5 5 import org.gradle.api.Action;
6 6 import org.gradle.api.file.RegularFile;
7 7 import org.gradle.api.provider.Provider;
8 import org.implab.gradle.common.json.core.MapImportSpec;
8 9
9 10 public interface JsonMapSpec extends GroovyObjectSpec {
10 11 void from(File file, Action<? super MapImportSpec> action);
@@ -1,4 +1,4
1 package org.implab.gradle.common.json;
1 package org.implab.gradle.common.json.dsl;
2 2
3 3 import org.gradle.api.Action;
4 4
@@ -17,4 +17,4 public interface JsonObjectSpec {
17 17 action.execute(child);
18 18 set(key, child.toList());
19 19 }
20 } No newline at end of file
20 }
@@ -1,4 +1,4
1 package org.implab.gradle.common.tasks;
1 package org.implab.gradle.common.json.tasks;
2 2
3 3 import java.util.LinkedHashMap;
4 4 import java.util.Map;
@@ -20,13 +20,12 import org.gradle.api.tasks.Input;
20 20 import org.gradle.api.tasks.Internal;
21 21 import org.gradle.api.tasks.Optional;
22 22 import org.gradle.api.tasks.OutputFile;
23 import org.gradle.api.tasks.SkipWhenEmpty;
24 23 import org.gradle.api.tasks.TaskAction;
25 import org.implab.gradle.common.json.MapImportSpec;
26 import org.implab.gradle.common.json.Json;
27 import org.implab.gradle.common.json.JsonObjectSpec;
28 import org.implab.gradle.common.utils.Closures;
29 import org.implab.gradle.common.utils.Properties;
24 import org.implab.gradle.common.core.gradle.Properties;
25 import org.implab.gradle.common.core.lang.Closures;
26 import org.implab.gradle.common.json.core.Json;
27 import org.implab.gradle.common.json.core.MapImportSpec;
28 import org.implab.gradle.common.json.dsl.JsonObjectSpec;
30 29
31 30 import groovy.lang.Closure;
32 31
@@ -1,39 +1,61
1 package org.implab.gradle.common.files;
1 package org.implab.gradle.common.sources;
2 2
3 3 import java.io.File;
4 4 import java.nio.file.Paths;
5 5 import java.util.HashSet;
6 import java.util.LinkedHashMap;
6 7 import java.util.List;
8 import java.util.Map;
7 9 import java.util.Objects;
8 10 import java.util.Set;
9 11 import java.util.concurrent.Callable;
12 import java.util.function.Function;
10 13 import java.util.stream.Collectors;
11 14
12 15 import javax.inject.Inject;
13 16
17 import org.gradle.api.InvalidUserDataException;
14 18 import org.gradle.api.Named;
15 19 import org.gradle.api.NamedDomainObjectContainer;
20 import org.gradle.api.Task;
21 import org.gradle.api.file.ConfigurableFileCollection;
16 22 import org.gradle.api.file.DirectoryProperty;
17 23 import org.gradle.api.file.FileCollection;
18 24 import org.gradle.api.file.ProjectLayout;
19 25 import org.gradle.api.file.SourceDirectorySet;
20 import org.gradle.api.logging.Logger;
21 import org.gradle.api.logging.Logging;
22 26 import org.gradle.api.model.ObjectFactory;
27 import org.gradle.api.tasks.TaskProvider;
23 28 import org.gradle.util.Configurable;
24 import org.implab.gradle.common.utils.Closures;
29 import org.implab.gradle.common.core.lang.Closures;
25 30
26 31 import groovy.lang.Closure;
27 32
33 /**
34 * A configurable source set abstraction with named output roles.
35 *
36 * <p>
37 * Each instance aggregates multiple {@link SourceDirectorySet source sets}
38 * under a shared name and exposes typed outputs that must be declared up front.
39 * Default locations are {@code src/<name>} for sources and
40 * {@code build/<name>} for outputs, both of which can be customized via the
41 * exposed {@link DirectoryProperty} setters.
42 * </p>
43 *
44 * <p>
45 * Outputs are grouped by roles to make task wiring explicit. A role must be
46 * declared with {@link #declareRoles(String, String...)} (or the synonym
47 * {@link #declareOutputs(String, String...)}) before files can be registered
48 * against it. Attempting to register or retrieve an undeclared role results in
49 * {@link InvalidUserDataException}.
50 * </p>
51 */
28 52 public abstract class GenericSourceSet
29 53 implements Named, Configurable<GenericSourceSet> {
30 private final Logger logger = Logging.getLogger(GenericSourceSet.class);
31
32 54 private final String name;
33 55
34 56 private final NamedDomainObjectContainer<SourceDirectorySet> sourceDirectorySets;
35 57
36 private final NamedDomainObjectContainer<GenericSourceSetOutput> outputs;
58 private final Map<String, ConfigurableFileCollection> outputs;
37 59
38 60 private final FileCollection allOutputs;
39 61
@@ -41,7 +63,7 public abstract class GenericSourceSet
41 63
42 64 private final ObjectFactory objects;
43 65
44 private final Set<String> declaredOutputs = new HashSet<>();
66 private final Set<String> declaredRoles = new HashSet<>();
45 67
46 68 @Inject
47 69 public GenericSourceSet(String name, ObjectFactory objects, ProjectLayout layout) {
@@ -52,14 +74,12 public abstract class GenericSourceSet
52 74 SourceDirectorySet.class,
53 75 this::createSourceDirectorySet);
54 76
55 outputs = objects.domainObjectContainer(GenericSourceSetOutput.class);
77 outputs = new LinkedHashMap<>();
56 78
57 79 allSourceDirectories = objects.fileCollection().from(sourceDirectoriesProvider());
58 80
59 81 allOutputs = objects.fileCollection().from(outputsProvider());
60 82
61 outputs.addRule("Register a declared set on demand", this::registerOutputOnDemand);
62
63 83 getSourceSetDir().convention(layout
64 84 .getProjectDirectory()
65 85 .dir(Paths.get("src", name).toString()));
@@ -74,57 +94,109 public abstract class GenericSourceSet
74 94 return name;
75 95 }
76 96
97 /**
98 * Base directory for this source set. Defaults to {@code src/<name>} under
99 * the project directory.
100 */
77 101 public abstract DirectoryProperty getSourceSetDir();
78 102
103 /**
104 * Base directory for outputs of this source set. Defaults to
105 * {@code build/<name>}.
106 */
79 107 public abstract DirectoryProperty getOutputsDir();
80 108
109 /**
110 * The container of {@link SourceDirectorySet} instances that belong to this
111 * logical source set.
112 */
81 113 public NamedDomainObjectContainer<SourceDirectorySet> getSets() {
82 114 return sourceDirectorySets;
83 115 }
84 116
85 public NamedDomainObjectContainer<GenericSourceSetOutput> getOutputs() {
86 return outputs;
87 }
88
117 /**
118 * All registered outputs grouped across roles.
119 */
89 120 public FileCollection getAllOutputs() {
90 121 return allOutputs;
91 122 }
92 123
124 /**
125 * All source directories from every contained {@link SourceDirectorySet}.
126 */
93 127 public FileCollection getAllSourceDirectories() {
94 128 return allSourceDirectories;
95 129 }
96 130
97 public FileCollection output(String name) {
98 return getOutputs().getAt(name).getFileCollection();
131 /**
132 * Returns the file collection for the specified output role, creating it
133 * if necessary.
134 *
135 * @throws InvalidUserDataException if the role was not declared
136 */
137 public ConfigurableFileCollection output(String name) {
138 requireDeclaredRole(name);
139 return outputs.computeIfAbsent(name, key -> objects.fileCollection());
99 140 }
100 141
101 public void declareOutputs(String name, String... extra) {
102 declaredOutputs.add(Objects.requireNonNull(name, "declareOutputs: The output name cannot be null"));
142 /**
143 * Declares allowed output roles. Roles must be declared before registering
144 * files under them.
145 */
146 public void declareRoles(String name, String... extra) {
147 declaredRoles.add(Objects.requireNonNull(name, "declareRoles: The output name cannot be null"));
103 148 for (var x : extra)
104 declaredOutputs.add(Objects.requireNonNull(x, "declareOutputs: The output name cannot be null"));
149 declaredRoles.add(Objects.requireNonNull(x, "declareRoles: The output name cannot be null"));
105 150 }
106 151
107 @Override
108 public GenericSourceSet configure(@SuppressWarnings("rawtypes") Closure configure) {
109 Closures.apply(configure, this);
110 return this;
152 /**
153 * Alias for {@link #declareRoles(String, String...)} kept for DSL clarity.
154 */
155 public void declareOutputs(String name, String... extra) {
156 declareRoles(name, extra);
157 }
158
159 /**
160 * Registers files produced elsewhere under the given role.
161 */
162 public void registerOutput(String name, Object... files) {
163 output(name).from(files);
111 164 }
112 165
113 private void registerOutputOnDemand(String outputName) {
114 logger.info("SourceSet '{}': registerOutputOnDemand '{}'", name, outputName);
166 /**
167 * Registers output files produced by a task, using a mapper to extract the
168 * output from the task. The task will be added as a build dependency of this
169 * output.
170 */
171 public <T extends Task> void registerOutput(String name, TaskProvider<T> task,
172 Function<? super T, ?> mapper) {
173 output(name).from(task.map(mapper::apply))
174 .builtBy(task);
175 }
115 176
116 if (declaredOutputs.contains(outputName))
117 outputs.register(outputName);
177 /**
178 * Applies a Groovy closure to this source set, enabling DSL-style
179 * configuration.
180 */
181 @Override
182 public GenericSourceSet configure(Closure configure) {
183 Closures.apply(configure, this);
184 return this;
118 185 }
119 186
120 187 private SourceDirectorySet createSourceDirectorySet(String name) {
121 188 return objects.sourceDirectorySet(name, name);
122 189 }
123 190
191 private void requireDeclaredRole(String roleName) {
192 if (!declaredRoles.contains(roleName)) {
193 throw new InvalidUserDataException(
194 "Output role '" + roleName + "' is not declared for source set '" + name + "'");
195 }
196 }
197
124 198 private Callable<List<? extends FileCollection>> outputsProvider() {
125 return () -> outputs.stream()
126 .map(GenericSourceSetOutput::getFileCollection)
127 .toList();
199 return () -> outputs.values().stream().toList();
128 200 }
129 201
130 202 private Callable<Set<File>> sourceDirectoriesProvider() {
@@ -1,4 +1,4
1 package org.implab.gradle.common;
1 package org.implab.gradle.common.sources;
2 2
3 3 import org.gradle.api.Action;
4 4 import org.gradle.api.Plugin;
@@ -10,8 +10,7 import org.gradle.api.tasks.Delete;
10 10 import org.gradle.api.tasks.TaskContainer;
11 11 import org.gradle.api.tasks.TaskProvider;
12 12 import org.gradle.language.base.plugins.LifecycleBasePlugin;
13 import org.implab.gradle.common.files.GenericSourceSet;
14 import org.implab.gradle.common.utils.Strings;
13 import org.implab.gradle.common.core.lang.Strings;
15 14
16 15 /**
17 16 * This plugin creates a {@code sources} extension which is
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now