diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
index 226419345eea..d6dde425d33b 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/dsl/DependencyHandler.java
@@ -451,6 +451,42 @@ public interface DependencyHandler extends ExtensionAware {
/**
* Registers an artifact transform.
*
+ *
+ * The registration action needs to specify the {@code from} and {@code to} attributes.
+ * It may also provide parameters for the transform action by using {@link TransformSpec#parameters(Action)}.
+ *
+ *
+ *
Example: When you have a transform action like this:
+ *
* @since 5.3
*/
@Incubating
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java
index b36c3d0a7b48..6c7076847478 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifact.java
@@ -29,11 +29,27 @@
import java.lang.annotation.Target;
/**
- * Attached to a property that should receive the input artifact for an artifact transform. This is the artifact that the transform should be applied to.
+ * Attached to a property that should receive the input artifact for an artifact transform.
+ * This is the artifact that the transform is applied to.
*
- *
- * The input artifact can be injected as a {@link Provider}<{@link org.gradle.api.file.FileSystemLocation}>.
- *
+ *
The input artifact can be injected as a {@link Provider}<{@link org.gradle.api.file.FileSystemLocation}>.
+ *
+ *
Example usage:
+ *
+ *
+ * import org.gradle.api.artifacts.transform.TransformParameters;
+ *
+ * public abstract class MyTransform implements TransformAction<TransformParameters.None> {
+ *
+ * {@literal @}InputArtifact
+ * public abstract Provider<FileSystemLocation> getInputArtifact();
+ * {@literal @}Override
+ * public void transform(TransformOutputs outputs) {
+ * File input = getInputArtifact().get().getAsFile();
+ * // Do something with the input
+ * }
+ * }
+ *
*
* @since 5.3
*/
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifactDependencies.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifactDependencies.java
index eb0d0380c703..8fa1da51be2b 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifactDependencies.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/InputArtifactDependencies.java
@@ -29,8 +29,32 @@
/**
* Attached to a property that should receive the artifact dependencies of the {@link InputArtifact} of an artifact transform.
*
- * The order of the files match that of the dependencies in the source artifact view.
- * The type of the injected dependencies is {@link org.gradle.api.file.FileCollection}.
+ *
+ * The order of the files match that of the dependencies in the source artifact view.
+ * The type of the injected dependencies is {@link org.gradle.api.file.FileCollection}.
+ * For example, when a project depends on {@code spring-web}, when the project is transformed (i.e. the project is the input artifact),
+ * the input artifact dependencies are the file collection containing the {@code spring-web} JAR and all its dependencies like e.g. the {@code spring-core} JAR.
+ *
+ *
+ *
Example usage:
+ *
+ * import org.gradle.api.artifacts.transform.TransformParameters;
+ *
+ * public abstract class MyTransform implements TransformAction<TransformParameters.None> {
+ *
+ * {@literal @}InputArtifact
+ * public abstract Provider<FileSystemLocation> getInputArtifact();
+ *
+ * {@literal @}InputArtifactDependencies
+ * public abstract FileCollection getDependencies();
+ *
+ * {@literal @}Override
+ * public void transform(TransformOutputs outputs) {
+ * FileCollection dependencies = getDependencies();
+ * // Do something with the dependencies
+ * }
+ * }
+ *
Implementations must provide a public constructor.
+ *
+ * A transform action implementation is an abstract class implementing the {@link #transform(TransformOutputs)} method.
+ * A minimal implementation may look like this:
+ *
*
- *
Implementations can receive parameters by using annotated abstract getter methods.
A property annotated with {@link InputArtifact} will receive the input artifact location, which is the file or directory that the transform should be applied to.
+ * public abstract class MyTransform implements TransformAction<TransformParameters.None> {
+ * {@literal @}InputArtifact
+ * public abstract Provider<FileSystemLocation> getInputArtifact();
*
- *
A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact.
+ * {@literal @}Override
+ * public void transform(TransformOutputs outputs) {
+ * File input = getInputArtifact().get().getAsFile();
+ * File output = outputs.file(input.getName() + ".transformed");
+ * // Do something to generate output from input
+ * }
+ * }
+ *
+ *
+ *
+ *
Do not implement {@link #getParameters()} in your class, the method will be implemented by Gradle.
+ *
Implementations may only have a default constructor.
+ *
Implementations can receive parameters by using annotated abstract getter methods.
+ *
A property annotated with {@link InputArtifact} will receive the input artifact location, which is the file or directory that the transform should be applied to.
+ *
A property annotated with {@link InputArtifactDependencies} will receive the dependencies of its input artifact.
+ *
*
* @param Parameter type for the transform action. Should be {@link TransformParameters.None} if the action does not have parameters.
* @since 5.3
@@ -38,7 +60,12 @@
public interface TransformAction {
/**
- * The object provided by {@link TransformSpec#getParameters()}.
+ * The object provided by {@link TransformSpec#getParameters()} when registering the artifact transform.
+ *
+ *
+ * Do not implement this method in your subclass.
+ * Gradle provides the implementation when registering the transform action via {@link org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)}.
+ *
*/
@Inject
T getParameters();
@@ -46,6 +73,8 @@ public interface TransformAction {
/**
* Executes the transform.
*
+ *
This method must be implemented in the subclass.
+ *
* @param outputs Receives the outputs of the transform.
*/
void transform(TransformOutputs outputs);
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformOutputs.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformOutputs.java
index 35757baf651c..ce083571f7ef 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformOutputs.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformOutputs.java
@@ -35,7 +35,46 @@
public interface TransformOutputs {
/**
* Registers an output directory.
- * For a relative path, a location for the output directory is provided.
+ *
+ *
+ * For an absolute path, the location is registered as an output directory of the {@link TransformAction}.
+ * The path is required to point to the {@link InputArtifact}, or point inside the input artifact if it is a directory.
+ * Example:
+ *
+ * For a relative path, a location for the output directory is provided by Gradle, so that the {@link TransformAction} can produce its outputs at that location.
+ * The directory is created automatically when calling the method.
+ * Example:
+ *
+ * Note: it is an error if the registered directory does not exist when the {@link TransformAction#transform(TransformOutputs)} method finishes.
+ *
*
* @param path path of the output directory
* @return determined location of the output
@@ -44,9 +83,52 @@ public interface TransformOutputs {
/**
* Registers an output file.
- * For a relative path, a location for the output file is provided.
*
- * @param path path of the output directory
+ *
+ * For an absolute path, the location is registered as an output file of the {@link TransformAction}.
+ * The path is required to point to the {@link InputArtifact} or be inside it if the input artifact is a directory.
+ * Example:
+ *
+ * For a relative path, a location for the output file is provided by Gradle, so that the {@link TransformAction} can produce its outputs at that location.
+ * The parent directory of the provided location is created automatically when calling the method.
+ * Example:
+ *
The registered file needs to exist when the {@link TransformAction#transform(TransformOutputs)} method finishes.
+ *
+ * @param path path of the output file
* @return determined location of the output
*/
File file(Object path);
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java
index 72bc2c266f7a..2fb824c93fa6 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformParameters.java
@@ -21,6 +21,22 @@
/**
* Marker interface for parameter objects to {@link TransformAction}s.
*
+ *
+ * Parameter types should be interfaces, only declaring getters for {@link org.gradle.api.provider.Property}-like objects.
+ * All getters must be annotated with an input annotation like {@link org.gradle.api.tasks.Input} or {@link org.gradle.api.tasks.InputFiles}.
+ * Normalization annotations such as {@link org.gradle.api.tasks.PathSensitive} or {@link org.gradle.api.tasks.Classpath} can be used as well.
+ * See the table of incremental build property type annotations for all annotations which can be used.
+ * Example:
+ *
+ *
* @since 5.3
*/
@Incubating
@@ -28,6 +44,8 @@ public interface TransformParameters {
/**
* Used for {@link TransformAction}s without parameters.
*
+ *
When {@link None} is used as parameters, calling {@link TransformAction#getParameters()} throws an exception.
+ *
* @since 5.3
*/
@Incubating
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java
index 1c5b61f3271e..e1b51d532dac 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/TransformSpec.java
@@ -23,6 +23,7 @@
/**
* Base configuration for artifact transform registrations.
*
+ * @see org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)
* @param The transform specific parameter type.
* @since 5.3
*/
@@ -30,21 +31,29 @@
public interface TransformSpec {
/**
* Attributes that match the variant that is consumed.
+ *
+ * @see org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)
*/
AttributeContainer getFrom();
/**
* Attributes that match the variant that is produced.
+ *
+ * @see org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)
*/
AttributeContainer getTo();
/**
* The parameters for the transform action.
+ *
+ * @see org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)
*/
T getParameters();
/**
* Configure the parameters for the transform action.
+ *
+ * @see org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(Class, Action)
*/
void parameters(Action super T> action);
}
diff --git a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/package-info.java b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/package-info.java
index 04f4a630ad16..9c21f9e50946 100644
--- a/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/package-info.java
+++ b/subprojects/core-api/src/main/java/org/gradle/api/artifacts/transform/package-info.java
@@ -15,7 +15,14 @@
*/
/**
- * Classes that perform artifact transformations.
+ * Provides classes, interfaces and annotations for registering and implementing artifact transforms.
+ *
+ *
+ * To register an artifact transform, use {@link org.gradle.api.artifacts.dsl.DependencyHandler#registerTransform(java.lang.Class, org.gradle.api.Action)}.
+ * This allows you to register a {@link org.gradle.api.artifacts.transform.TransformAction} using {@link org.gradle.api.artifacts.transform.TransformSpec}.
+ *
+ *
+ *
If you want to create a new artifact transform action, have a look at {@link org.gradle.api.artifacts.transform.TransformAction}.
Creates a new {@link NamedDomainObjectContainer} for managing named objects of the specified type. The specified type must have a public constructor which takes the name as a String parameter.
+ *
+ *
All objects MUST expose their name as a bean property named "name". The name must be constant for the life of the object.
+ *
+ * @param elementType The type of objects for the container to contain.
+ * @param The type of objects for the container to contain.
+ * @return The container. Never returns null.
+ * @since 5.5
+ */
+ NamedDomainObjectContainer container(Class elementType);
+
+ /**
+ *
Creates a new {@link NamedDomainObjectContainer} for managing named objects of the specified type. The given factory is used to create object instances.
+ *
+ *
All objects MUST expose their name as a bean property named "name". The name must be constant for the life of the object.
+ *
+ *
+ * @param elementType The type of objects for the container to contain.
+ * @param factory The factory to use to create object instances.
+ * @param The type of objects for the container to contain.
+ * @return The container. Never returns null.
+ * @since 5.5
+ */
+ NamedDomainObjectContainer container(Class elementType, NamedDomainObjectFactory factory);
+
+ /**
+ * Creates a new {@link DomainObjectSet} for managing objects of the specified type.
+ *
+ * @param elementType The type of objects for the domain object set to contain.
+ * @param The type of objects for the domain object set to contain.
+ * @return The domain object set. Never returns null.
+ * @since 5.5
+ */
+ DomainObjectSet domainObjectSet(Class elementType);
+
/**
* Creates a {@link Property} implementation to hold values of the given type. The property has no initial value.
*
@@ -122,7 +161,7 @@ public interface ObjectFactory {
*
* @param elementType The type of element.
* @param The type of element.
- * @return The property. Never returns null;
+ * @return The property. Never returns null.
* @since 4.3
*/
ListProperty listProperty(Class elementType);
@@ -134,7 +173,7 @@ public interface ObjectFactory {
*
* @param elementType The type of element.
* @param The type of element.
- * @return The property. Never returns null;
+ * @return The property. Never returns null.
* @since 4.5
*/
SetProperty setProperty(Class elementType);
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/NamedDomainObjectContainerIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/NamedDomainObjectContainerIntegrationTest.groovy
index 7896b9755539..f3e44b69e9d2 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/NamedDomainObjectContainerIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/NamedDomainObjectContainerIntegrationTest.groovy
@@ -16,6 +16,8 @@
package org.gradle.api
+import spock.lang.Issue
+
class NamedDomainObjectContainerIntegrationTest extends AbstractDomainObjectContainerIntegrationTest {
@Override
String getContainerStringRepresentation() {
@@ -61,4 +63,36 @@ class NamedDomainObjectContainerIntegrationTest extends AbstractDomainObjectCont
expect:
succeeds "verify"
}
+
+
+ def "chained lookup of testContainer.withType.matching"() {
+ buildFile << """
+ testContainer.withType(testContainer.type).matching({ it.name.endsWith("foo") }).all { element ->
+ assert element.name in ['foo', 'barfoo']
+ }
+
+ testContainer.register("foo")
+ testContainer.register("bar")
+ testContainer.register("foobar")
+ testContainer.register("barfoo")
+ """
+ expect:
+ succeeds "help"
+ }
+
+ @Issue("https://github.com/gradle/gradle/issues/9446")
+ def "chained lookup of testContainer.matching.withType"() {
+ buildFile << """
+ testContainer.matching({ it.name.endsWith("foo") }).withType(testContainer.type).all { element ->
+ assert element.name in ['foo', 'barfoo']
+ }
+
+ testContainer.register("foo")
+ testContainer.register("bar")
+ testContainer.register("foobar")
+ testContainer.register("barfoo")
+ """
+ expect:
+ succeeds "help"
+ }
}
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/TaskContainerIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/TaskContainerIntegrationTest.groovy
index 741d810b1db3..27e60f38829d 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/TaskContainerIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/TaskContainerIntegrationTest.groovy
@@ -16,7 +16,7 @@
package org.gradle.api
-import groovy.transform.NotYetImplemented
+
import spock.lang.Issue
class TaskContainerIntegrationTest extends AbstractDomainObjectContainerIntegrationTest {
@@ -37,30 +37,29 @@ class TaskContainerIntegrationTest extends AbstractDomainObjectContainerIntegrat
def "chained lookup of tasks.withType.matching"() {
buildFile << """
tasks.withType(Copy).matching({ it.name.endsWith("foo") }).all { task ->
- assert task.path in [':foo', ':barfoo']
+ assert task.path in [':foo']
}
tasks.register("foo", Copy)
tasks.register("bar", Copy)
- tasks.register("foobar", Copy)
- tasks.register("barfoo", Copy)
+ tasks.register("foobar", Delete)
+ tasks.register("barfoo", Delete)
"""
expect:
succeeds "help"
}
@Issue("https://github.com/gradle/gradle/issues/9446")
- @NotYetImplemented
def "chained lookup of tasks.matching.withType"() {
buildFile << """
tasks.matching({ it.name.endsWith("foo") }).withType(Copy).all { task ->
- assert task.path in [':foo', ':barfoo']
+ assert task.path in [':foo']
}
tasks.register("foo", Copy)
tasks.register("bar", Copy)
- tasks.register("foobar", Copy)
- tasks.register("barfoo", Copy)
+ tasks.register("foobar", Delete)
+ tasks.register("barfoo", Delete)
"""
expect:
succeeds "help"
diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/model/ObjectFactoryIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/model/ObjectFactoryIntegrationTest.groovy
index 7b0ad84b0a49..5ed28961e588 100644
--- a/subprojects/core/src/integTest/groovy/org/gradle/api/internal/model/ObjectFactoryIntegrationTest.groovy
+++ b/subprojects/core/src/integTest/groovy/org/gradle/api/internal/model/ObjectFactoryIntegrationTest.groovy
@@ -499,4 +499,61 @@ class ObjectFactoryIntegrationTest extends AbstractIntegrationSpec {
expect:
succeeds()
}
+
+ def "plugin can create NamedDomainObjectContainer instances"() {
+ given:
+ buildFile << """
+ class NamedThing implements Named {
+ final String name
+ NamedThing(String name) {
+ this.name = name
+ }
+ }
+
+ def container = project.objects.container(NamedThing)
+ assert container != null
+ def element = container.create('foo')
+ assert element.name == 'foo'
+ assert container.size() == 1
+ """
+
+ expect:
+ succeeds()
+ }
+
+ def "plugin can create NamedDomainObjectContainer instances with factory"() {
+ given:
+ buildFile << """
+ class NamedThing implements Named {
+ final String name
+ NamedThing(String name) {
+ this.name = name
+ }
+ }
+
+ def container = project.objects.container(NamedThing) {
+ return new NamedThing("prefix-" + it)
+ }
+ assert container != null
+ def element = container.create("foo")
+ assert element.name == 'prefix-foo'
+ assert container.size() == 1
+ """
+
+ expect:
+ succeeds()
+ }
+
+ def "plugin can create DomainObjectSet instances"() {
+ given:
+ buildFile << """
+ def domainObjectSet = project.objects.domainObjectSet(String)
+ assert domainObjectSet != null
+ assert domainObjectSet.add('foo')
+ assert domainObjectSet.size() == 1
+ """
+
+ expect:
+ succeeds()
+ }
}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/CollectionCallbackActionDecorator.java b/subprojects/core/src/main/java/org/gradle/api/internal/CollectionCallbackActionDecorator.java
index 4335f6a45a0a..6d4d6165c5d3 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/CollectionCallbackActionDecorator.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/CollectionCallbackActionDecorator.java
@@ -22,7 +22,6 @@
public interface CollectionCallbackActionDecorator {
- @Nullable
Action decorate(@Nullable Action action);
CollectionCallbackActionDecorator NOOP = new CollectionCallbackActionDecorator() {
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultDomainObjectCollection.java b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultDomainObjectCollection.java
index 56ef2c93824a..3ad793a82390 100755
--- a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultDomainObjectCollection.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultDomainObjectCollection.java
@@ -168,7 +168,7 @@ public void all(Action super T> action) {
@Override
public void configureEach(Action super T> action) {
assertMutable("configureEach(Action)");
- Action super T> wrappedAction = withMutationDisabled(action);
+ Action super T> wrappedAction = withMutationDisabled(decorate(action));
Action super T> registerLazyAddActionDecorated = eventRegister.registerLazyAddAction(wrappedAction);
// copy in case any actions mutate the store
@@ -224,12 +224,12 @@ public void whenObjectAdded(Closure action) {
private Action super T> addEagerAction(Action super T> action) {
store.realizePending(type);
- return eventRegister.registerEagerAddAction(type, action);
+ return eventRegister.registerEagerAddAction(type, decorate(action));
}
@Override
public Action super T> whenObjectRemoved(Action super T> action) {
- eventRegister.registerRemoveAction(type, action);
+ eventRegister.registerRemoveAction(type, decorate(action));
return action;
}
@@ -238,6 +238,10 @@ public void whenObjectRemoved(Closure action) {
whenObjectRemoved(toAction(action));
}
+ private Action super T> decorate(Action super T> action) {
+ return eventRegister.getDecorator().decorate(action);
+ }
+
private Action super T> toAction(Closure action) {
return ConfigureUtil.configureUsing(action);
}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/collections/CollectionEventRegister.java b/subprojects/core/src/main/java/org/gradle/api/internal/collections/CollectionEventRegister.java
index 33578bcfee88..9f171c1cd6ed 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/collections/CollectionEventRegister.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/collections/CollectionEventRegister.java
@@ -41,5 +41,6 @@ public interface CollectionEventRegister {
CollectionEventRegister filtered(CollectionFilter filter);
+ // TODO: Migrate this away from here
CollectionCallbackActionDecorator getDecorator();
}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultCollectionEventRegister.java b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultCollectionEventRegister.java
index e29db114f4be..88c5e05c0885 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultCollectionEventRegister.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultCollectionEventRegister.java
@@ -17,6 +17,7 @@
import org.gradle.api.Action;
import org.gradle.api.internal.CollectionCallbackActionDecorator;
+import org.gradle.internal.Cast;
import org.gradle.internal.ImmutableActionSet;
import java.util.HashSet;
@@ -78,17 +79,17 @@ public void fireObjectRemoved(T element) {
@Override
public Action super T> registerEagerAddAction(Class extends T> type, Action super T> addAction) {
- return registerEagerAddDecoratedAction(type, decorate(addAction));
+ return registerEagerAddDecoratedAction(type, addAction);
}
@Override
public Action super T> registerLazyAddAction(Action super T> addAction) {
- return registerLazyAddDecoratedAction(decorate(addAction));
+ return registerLazyAddDecoratedAction(addAction);
}
@Override
public void registerRemoveAction(Class extends T> type, Action super T> removeAction) {
- registerRemoveDecoratedAction(decorate(removeAction));
+ registerRemoveDecoratedAction(removeAction);
}
private Action super T> registerEagerAddDecoratedAction(Class extends T> type, Action super T> decorated) {
@@ -105,17 +106,9 @@ private void registerRemoveDecoratedAction(Action super T> decorated) {
removeActions = removeActions.add(decorated);
}
- private Action super T> decorate(Action super T> action) {
- return decorator.decorate(action);
- }
-
- private Action super T> decorate(Action super S> action, CollectionFilter filter) {
- return filter.filtered(decorator.decorate(action));
- }
-
@Override
public CollectionEventRegister filtered(CollectionFilter filter) {
- return new FilteredEventRegister(filter);
+ return new FilteredEventRegister(filter, this);
}
private void subscribe(Class extends T> type) {
@@ -135,14 +128,16 @@ private void subscribe(Class extends T> type) {
private class FilteredEventRegister implements CollectionEventRegister {
private final CollectionFilter filter;
+ private final CollectionEventRegister delegate;
- FilteredEventRegister(CollectionFilter filter) {
+ FilteredEventRegister(CollectionFilter filter, CollectionEventRegister delegate) {
this.filter = filter;
+ this.delegate = Cast.uncheckedCast(delegate);
}
@Override
public CollectionCallbackActionDecorator getDecorator() {
- return decorator;
+ return delegate.getDecorator();
}
@Override
@@ -167,22 +162,22 @@ public boolean isSubscribed(Class> type) {
@Override
public Action super S> registerEagerAddAction(Class extends S> type, Action super S> addAction) {
- return registerEagerAddDecoratedAction(type, decorate(addAction, filter));
+ return delegate.registerEagerAddAction(type, filter.filtered(addAction));
}
@Override
public Action super S> registerLazyAddAction(Action super S> addAction) {
- return registerLazyAddDecoratedAction(decorate(addAction, filter));
+ return delegate.registerLazyAddAction(filter.filtered(addAction));
}
@Override
public void registerRemoveAction(Class extends S> type, Action super S> removeAction) {
- registerRemoveDecoratedAction(decorate(removeAction, filter));
+ delegate.registerRemoveAction(type, filter.filtered(removeAction));
}
@Override
public CollectionEventRegister filtered(CollectionFilter filter) {
- return new FilteredEventRegister(filter);
+ return new FilteredEventRegister(filter, (CollectionEventRegister) this);
}
}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultDomainObjectCollectionFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultDomainObjectCollectionFactory.java
new file mode 100644
index 000000000000..c944087af3d5
--- /dev/null
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DefaultDomainObjectCollectionFactory.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed 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.gradle.api.internal.collections;
+
+import groovy.lang.Closure;
+import org.gradle.api.DomainObjectCollection;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.NamedDomainObjectFactory;
+import org.gradle.api.internal.CollectionCallbackActionDecorator;
+import org.gradle.api.internal.CompositeDomainObjectSet;
+import org.gradle.api.internal.DefaultDomainObjectSet;
+import org.gradle.api.internal.DynamicPropertyNamer;
+import org.gradle.api.internal.FactoryNamedDomainObjectContainer;
+import org.gradle.api.internal.MutationGuard;
+import org.gradle.api.internal.ReflectiveNamedDomainObjectFactory;
+import org.gradle.internal.Cast;
+import org.gradle.internal.instantiation.InstantiatorFactory;
+import org.gradle.internal.reflect.Instantiator;
+import org.gradle.internal.service.ServiceRegistry;
+
+public class DefaultDomainObjectCollectionFactory implements DomainObjectCollectionFactory {
+ private final InstantiatorFactory instantiatorFactory;
+ private final ServiceRegistry servicesToInject;
+ private final CollectionCallbackActionDecorator collectionCallbackActionDecorator;
+ private final MutationGuard mutationGuard;
+
+ public DefaultDomainObjectCollectionFactory(InstantiatorFactory instantiatorFactory, ServiceRegistry servicesToInject, CollectionCallbackActionDecorator collectionCallbackActionDecorator, MutationGuard mutationGuard) {
+ this.instantiatorFactory = instantiatorFactory;
+ this.servicesToInject = servicesToInject;
+ this.collectionCallbackActionDecorator = collectionCallbackActionDecorator;
+ this.mutationGuard = mutationGuard;
+ }
+
+ @Override
+ public NamedDomainObjectContainer newNamedDomainObjectContainer(Class elementType) {
+ // TODO - this should also be using the decorating instantiator but cannot for backwards compatibility
+ ReflectiveNamedDomainObjectFactory objectFactory = new ReflectiveNamedDomainObjectFactory(elementType, instantiatorFactory.injectLenient(servicesToInject));
+ Instantiator instantiator = instantiatorFactory.decorateLenient();
+ return Cast.uncheckedCast(instantiator.newInstance(FactoryNamedDomainObjectContainer.class, elementType, instantiator, new DynamicPropertyNamer(), objectFactory, mutationGuard, collectionCallbackActionDecorator));
+ }
+
+ @Override
+ public NamedDomainObjectContainer newNamedDomainObjectContainer(Class elementType, NamedDomainObjectFactory factory) {
+ Instantiator instantiator = instantiatorFactory.decorateLenient();
+ return Cast.uncheckedCast(instantiator.newInstance(FactoryNamedDomainObjectContainer.class, elementType, instantiator, new DynamicPropertyNamer(), factory, mutationGuard, collectionCallbackActionDecorator));
+ }
+
+ @Override
+ public NamedDomainObjectContainer newNamedDomainObjectContainer(Class type, Closure factoryClosure) {
+ Instantiator instantiator = instantiatorFactory.decorateLenient();
+ return Cast.uncheckedCast(instantiator.newInstance(FactoryNamedDomainObjectContainer.class, type, instantiator, new DynamicPropertyNamer(), factoryClosure, mutationGuard, collectionCallbackActionDecorator));
+ }
+
+ @Override
+ public DomainObjectSet newDomainObjectSet(Class elementType) {
+ Instantiator instantiator = instantiatorFactory.decorateLenient();
+ return Cast.uncheckedCast(instantiator.newInstance(DefaultDomainObjectSet.class, elementType, collectionCallbackActionDecorator));
+ }
+
+ @Override
+ public CompositeDomainObjectSet newDomainObjectSet(Class elementType, DomainObjectCollection extends T>... collections) {
+ return CompositeDomainObjectSet.create(elementType, collectionCallbackActionDecorator, collections);
+ }
+}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/collections/DomainObjectCollectionFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DomainObjectCollectionFactory.java
new file mode 100644
index 000000000000..cb0720cdbc11
--- /dev/null
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/collections/DomainObjectCollectionFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed 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.gradle.api.internal.collections;
+
+import groovy.lang.Closure;
+import org.gradle.api.DomainObjectCollection;
+import org.gradle.api.DomainObjectSet;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.NamedDomainObjectFactory;
+import org.gradle.api.internal.CompositeDomainObjectSet;
+
+public interface DomainObjectCollectionFactory {
+ /**
+ * Creates a {@link NamedDomainObjectContainer} for managing named objects of the specified type.
+ */
+ NamedDomainObjectContainer newNamedDomainObjectContainer(Class elementType);
+
+ /**
+ * Creates a {@link NamedDomainObjectContainer} for managing named objects of the specified type created with the given factory.
+ */
+ NamedDomainObjectContainer newNamedDomainObjectContainer(Class elementType, NamedDomainObjectFactory factory);
+
+ /**
+ * Creates a {@link NamedDomainObjectContainer} for managing named objects of the specified type. The given closure is used to create object instances. The name of the instance to be created is passed as a parameter to the closure.
+ */
+ NamedDomainObjectContainer newNamedDomainObjectContainer(Class type, Closure factoryClosure);
+
+ /**
+ * Creates a {@link DomainObjectSet} for managing objects of the specified type.
+ */
+ DomainObjectSet newDomainObjectSet(Class elementType);
+
+ /**
+ * Creates a {@link CompositeDomainObjectSet} for managing a collection of {@link DomainObjectCollection} of the specified type.
+ */
+ CompositeDomainObjectSet newDomainObjectSet(Class elementType, DomainObjectCollection extends T>... collections);
+}
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/model/DefaultObjectFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/model/DefaultObjectFactory.java
index 6c990c564370..e58d49634e31 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/model/DefaultObjectFactory.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/model/DefaultObjectFactory.java
@@ -16,13 +16,17 @@
package org.gradle.api.internal.model;
+import org.gradle.api.DomainObjectSet;
import org.gradle.api.Named;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.NamedDomainObjectFactory;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.DefaultSourceDirectorySet;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FilePropertyFactory;
@@ -56,14 +60,16 @@ public class DefaultObjectFactory implements ObjectFactory {
private final DirectoryFileTreeFactory directoryFileTreeFactory;
private final FilePropertyFactory filePropertyFactory;
private final FileCollectionFactory fileCollectionFactory;
+ private final DomainObjectCollectionFactory domainObjectCollectionFactory;
- public DefaultObjectFactory(Instantiator instantiator, NamedObjectInstantiator namedObjectInstantiator, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FilePropertyFactory filePropertyFactory, FileCollectionFactory fileCollectionFactory) {
+ public DefaultObjectFactory(Instantiator instantiator, NamedObjectInstantiator namedObjectInstantiator, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FilePropertyFactory filePropertyFactory, FileCollectionFactory fileCollectionFactory, DomainObjectCollectionFactory domainObjectCollectionFactory) {
this.instantiator = instantiator;
this.namedObjectInstantiator = namedObjectInstantiator;
this.fileResolver = fileResolver;
this.directoryFileTreeFactory = directoryFileTreeFactory;
this.filePropertyFactory = filePropertyFactory;
this.fileCollectionFactory = fileCollectionFactory;
+ this.domainObjectCollectionFactory = domainObjectCollectionFactory;
}
@Override
@@ -102,6 +108,21 @@ public RegularFileProperty fileProperty() {
return filePropertyFactory.newFileProperty();
}
+ @Override
+ public NamedDomainObjectContainer container(Class elementType) {
+ return domainObjectCollectionFactory.newNamedDomainObjectContainer(elementType);
+ }
+
+ @Override
+ public NamedDomainObjectContainer container(Class elementType, NamedDomainObjectFactory factory) {
+ return domainObjectCollectionFactory.newNamedDomainObjectContainer(elementType, factory);
+ }
+
+ @Override
+ public DomainObjectSet domainObjectSet(Class elementType) {
+ return domainObjectCollectionFactory.newDomainObjectSet(elementType);
+ }
+
@Override
public Property property(Class valueType) {
if (valueType == null) {
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/model/InstantiatorBackedObjectFactory.java b/subprojects/core/src/main/java/org/gradle/api/internal/model/InstantiatorBackedObjectFactory.java
index 1d34ed34baee..3a76bde048f1 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/model/InstantiatorBackedObjectFactory.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/model/InstantiatorBackedObjectFactory.java
@@ -15,7 +15,10 @@
*/
package org.gradle.api.internal.model;
+import org.gradle.api.DomainObjectSet;
import org.gradle.api.Named;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.NamedDomainObjectFactory;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
@@ -51,6 +54,21 @@ public ConfigurableFileCollection fileCollection() {
throw new UnsupportedOperationException("This ObjectFactory implementation does not support constructing file collections");
}
+ @Override
+ public NamedDomainObjectContainer container(Class elementType) {
+ throw new UnsupportedOperationException("This ObjectFactory implementation does not support constructing named domain object container");
+ }
+
+ @Override
+ public NamedDomainObjectContainer container(Class elementType, NamedDomainObjectFactory factory) {
+ throw new UnsupportedOperationException("This ObjectFactory implementation does not support constructing named domain object container with factory");
+ }
+
+ @Override
+ public DomainObjectSet domainObjectSet(Class elementType) {
+ throw new UnsupportedOperationException("This ObjectFactory implementation does not support constructing domain object set");
+ }
+
@Override
public Property property(Class valueType) {
return new DefaultPropertyState(valueType);
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java
index eafb0b90fa26..261dc34b8139 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/plugins/DefaultPluginManager.java
@@ -23,7 +23,7 @@
import org.gradle.api.DomainObjectSet;
import org.gradle.api.Plugin;
import org.gradle.api.internal.CollectionCallbackActionDecorator;
-import org.gradle.api.internal.DefaultDomainObjectSet;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.plugins.AppliedPlugin;
import org.gradle.api.plugins.InvalidPluginException;
import org.gradle.api.plugins.PluginContainer;
@@ -56,7 +56,6 @@ public class DefaultPluginManager implements PluginManagerInternal {
private final Instantiator instantiator;
private final PluginTarget target;
private final PluginRegistry pluginRegistry;
- private final CollectionCallbackActionDecorator callbackDecorator;
private final DefaultPluginContainer pluginContainer;
private final Map, PluginImplementation>> plugins = Maps.newHashMap();
private final Map, Plugin> instances = Maps.newLinkedHashMap();
@@ -64,15 +63,16 @@ public class DefaultPluginManager implements PluginManagerInternal {
private final BuildOperationExecutor buildOperationExecutor;
private final UserCodeApplicationContext userCodeApplicationContext;
+ private DomainObjectCollectionFactory domainObjectCollectionFactory;
- public DefaultPluginManager(final PluginRegistry pluginRegistry, Instantiator instantiator, final PluginTarget target, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator callbackDecorator) {
+ public DefaultPluginManager(final PluginRegistry pluginRegistry, Instantiator instantiator, final PluginTarget target, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator callbackDecorator, DomainObjectCollectionFactory domainObjectCollectionFactory) {
this.instantiator = instantiator;
this.target = target;
this.pluginRegistry = pluginRegistry;
+ this.domainObjectCollectionFactory = domainObjectCollectionFactory;
this.pluginContainer = new DefaultPluginContainer(pluginRegistry, this, callbackDecorator);
this.buildOperationExecutor = buildOperationExecutor;
this.userCodeApplicationContext = userCodeApplicationContext;
- this.callbackDecorator = callbackDecorator;
}
private T instantiatePlugin(Class type) {
@@ -218,7 +218,7 @@ public DomainObjectSet pluginsForId(String id) {
PluginId pluginId = DefaultPluginId.unvalidated(id);
DomainObjectSet pluginsForId = idMappings.get(pluginId);
if (pluginsForId == null) {
- pluginsForId = new DefaultDomainObjectSet(PluginWithId.class, callbackDecorator);
+ pluginsForId = domainObjectCollectionFactory.newDomainObjectSet(PluginWithId.class);
idMappings.put(pluginId, pluginsForId);
for (PluginImplementation> plugin : plugins.values()) {
if (plugin.isAlsoKnownAs(pluginId)) {
diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/project/DefaultProject.java b/subprojects/core/src/main/java/org/gradle/api/internal/project/DefaultProject.java
index e80f8a2b0bf8..c7af5312100d 100644
--- a/subprojects/core/src/main/java/org/gradle/api/internal/project/DefaultProject.java
+++ b/subprojects/core/src/main/java/org/gradle/api/internal/project/DefaultProject.java
@@ -46,14 +46,12 @@
import org.gradle.api.file.FileTree;
import org.gradle.api.internal.CollectionCallbackActionDecorator;
import org.gradle.api.internal.DynamicObjectAware;
-import org.gradle.api.internal.DynamicPropertyNamer;
-import org.gradle.api.internal.FactoryNamedDomainObjectContainer;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.MutationGuards;
import org.gradle.api.internal.ProcessOperations;
-import org.gradle.api.internal.ReflectiveNamedDomainObjectFactory;
import org.gradle.api.internal.artifacts.Module;
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.DefaultProjectLayout;
import org.gradle.api.internal.file.FileOperations;
import org.gradle.api.internal.file.FileResolver;
@@ -1318,23 +1316,17 @@ public Object passThrough(Object object) {
@Override
public NamedDomainObjectContainer container(Class type) {
- InstantiatorFactory instantiatorFactory = getServices().get(InstantiatorFactory.class);
- // TODO - this should also be using the decorating instantiator but cannot for backwards compatibility
- ReflectiveNamedDomainObjectFactory objectFactory = new ReflectiveNamedDomainObjectFactory(type, instantiatorFactory.injectLenient(getServices()));
- Instantiator instantiator = instantiatorFactory.decorateLenient();
- return instantiator.newInstance(FactoryNamedDomainObjectContainer.class, type, instantiator, new DynamicPropertyNamer(), objectFactory, MutationGuards.of(getProjectConfigurator()), services.get(CollectionCallbackActionDecorator.class));
+ return getServices().get(DomainObjectCollectionFactory.class).newNamedDomainObjectContainer(type);
}
@Override
public NamedDomainObjectContainer container(Class type, NamedDomainObjectFactory factory) {
- Instantiator instantiator = getServices().get(InstantiatorFactory.class).decorateLenient();
- return instantiator.newInstance(FactoryNamedDomainObjectContainer.class, type, instantiator, new DynamicPropertyNamer(), factory, MutationGuards.of(getProjectConfigurator()), services.get(CollectionCallbackActionDecorator.class));
+ return getServices().get(DomainObjectCollectionFactory.class).newNamedDomainObjectContainer(type, factory);
}
@Override
public NamedDomainObjectContainer container(Class type, Closure factoryClosure) {
- Instantiator instantiator = getServices().get(InstantiatorFactory.class).decorateLenient();
- return instantiator.newInstance(FactoryNamedDomainObjectContainer.class, type, instantiator, new DynamicPropertyNamer(), factoryClosure, MutationGuards.of(getProjectConfigurator()), services.get(CollectionCallbackActionDecorator.class));
+ return getServices().get(DomainObjectCollectionFactory.class).newNamedDomainObjectContainer(type, factoryClosure);
}
@Override
diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
index 778398941dbf..60eb6cde9d56 100755
--- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
+++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GlobalScopeServices.java
@@ -19,8 +19,12 @@
import com.google.common.collect.Iterables;
import org.gradle.api.execution.internal.DefaultTaskInputsListener;
import org.gradle.api.execution.internal.TaskInputsListener;
+import org.gradle.api.internal.CollectionCallbackActionDecorator;
+import org.gradle.api.internal.MutationGuards;
import org.gradle.api.internal.StartParameterInternal;
import org.gradle.api.internal.cache.StringInterner;
+import org.gradle.api.internal.collections.DefaultDomainObjectCollectionFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.DefaultFilePropertyFactory;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FilePropertyFactory;
@@ -246,14 +250,19 @@ FilePropertyFactory createFilePropertyFactory(FileResolver fileResolver) {
return new DefaultFilePropertyFactory(fileResolver);
}
- ObjectFactory createObjectFactory(InstantiatorFactory instantiatorFactory, ServiceRegistry services, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FileCollectionFactory fileCollectionFactory, FilePropertyFactory filePropertyFactory) {
+ ObjectFactory createObjectFactory(InstantiatorFactory instantiatorFactory, ServiceRegistry services, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FileCollectionFactory fileCollectionFactory, DomainObjectCollectionFactory domainObjectCollectionFactory) {
return new DefaultObjectFactory(
instantiatorFactory.injectAndDecorate(services),
NamedObjectInstantiator.INSTANCE,
fileResolver,
directoryFileTreeFactory,
- filePropertyFactory,
- fileCollectionFactory);
+ new DefaultFilePropertyFactory(fileResolver),
+ fileCollectionFactory,
+ domainObjectCollectionFactory);
+ }
+
+ DomainObjectCollectionFactory createDomainObjectCollectionFactory(InstantiatorFactory instantiatorFactory, ServiceRegistry services) {
+ return new DefaultDomainObjectCollectionFactory(instantiatorFactory, services, CollectionCallbackActionDecorator.NOOP, MutationGuards.identity());
}
ProviderFactory createProviderFactory() {
diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleScopeServices.java
index 1886c62424c1..d9340db9153b 100644
--- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleScopeServices.java
+++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/GradleScopeServices.java
@@ -21,6 +21,7 @@
import org.gradle.api.internal.CollectionCallbackActionDecorator;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.plugins.DefaultPluginManager;
import org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget;
@@ -260,9 +261,9 @@ PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
return parentRegistry.createChild(get(GradleInternal.class).getClassLoaderScope());
}
- PluginManagerInternal createPluginManager(Instantiator instantiator, GradleInternal gradleInternal, PluginRegistry pluginRegistry, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator) {
+ PluginManagerInternal createPluginManager(Instantiator instantiator, GradleInternal gradleInternal, PluginRegistry pluginRegistry, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator, DomainObjectCollectionFactory domainObjectCollectionFactory) {
PluginTarget target = new ImperativeOnlyPluginTarget(gradleInternal);
- return instantiator.newInstance(DefaultPluginManager.class, pluginRegistry, instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator);
+ return instantiator.newInstance(DefaultPluginManager.class, pluginRegistry, instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator, domainObjectCollectionFactory);
}
FileContentCacheFactory createFileContentCacheFactory(FileContentCacheFactory globalCacheFactory, ListenerManager listenerManager, FileSystemSnapshotter fileSystemSnapshotter, CacheRepository cacheRepository, InMemoryCacheDecoratorFactory inMemoryCacheDecoratorFactory, Gradle gradle, WellKnownFileLocations wellKnownFileLocations) {
diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ProjectScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ProjectScopeServices.java
index e83fd26d1645..467af8c12054 100644
--- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ProjectScopeServices.java
+++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/ProjectScopeServices.java
@@ -21,11 +21,14 @@
import org.gradle.api.component.SoftwareComponentContainer;
import org.gradle.api.internal.CollectionCallbackActionDecorator;
import org.gradle.api.internal.DomainObjectContext;
+import org.gradle.api.internal.MutationGuards;
import org.gradle.api.internal.artifacts.DependencyManagementServices;
import org.gradle.api.internal.artifacts.Module;
import org.gradle.api.internal.artifacts.ProjectBackedModule;
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider;
import org.gradle.api.internal.artifacts.dsl.dependencies.ProjectFinder;
+import org.gradle.api.internal.collections.DefaultDomainObjectCollectionFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.component.ComponentRegistry;
import org.gradle.api.internal.component.DefaultSoftwareComponentContainer;
import org.gradle.api.internal.file.BaseDirFileResolver;
@@ -183,13 +186,13 @@ protected ToolingModelBuilderRegistry decorateToolingModelRegistry(ToolingModelB
return new DefaultToolingModelBuilderRegistry(buildOperationExecutor, projectStateRegistry, buildScopedToolingModelBuilders);
}
- protected PluginManagerInternal createPluginManager(Instantiator instantiator, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator) {
+ protected PluginManagerInternal createPluginManager(Instantiator instantiator, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator, DomainObjectCollectionFactory domainObjectCollectionFactory) {
PluginTarget target = new RuleBasedPluginTarget(
project,
get(ModelRuleExtractor.class),
get(ModelRuleSourceDetector.class)
);
- return instantiator.newInstance(DefaultPluginManager.class, get(PluginRegistry.class), instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator);
+ return instantiator.newInstance(DefaultPluginManager.class, get(PluginRegistry.class), instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator, domainObjectCollectionFactory);
}
protected ITaskFactory createTaskFactory(ITaskFactory parentFactory, TaskScheme taskScheme) {
@@ -312,9 +315,15 @@ protected FileCollectionFactory createFileCollectionFactory(PathToFileResolver f
return new DefaultFileCollectionFactory(fileResolver, taskResolver);
}
- protected ObjectFactory createObjectFactory(InstantiatorFactory instantiatorFactory, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FilePropertyFactory filePropertyFactory, FileCollectionFactory fileCollectionFactory) {
- Instantiator instantiator = instantiatorFactory.injectAndDecorate(ProjectScopeServices.this);
- return new DefaultObjectFactory(instantiator, NamedObjectInstantiator.INSTANCE, fileResolver, directoryFileTreeFactory, filePropertyFactory, fileCollectionFactory);
+ protected ObjectFactory createObjectFactory(InstantiatorFactory instantiatorFactory, FileResolver fileResolver, DirectoryFileTreeFactory directoryFileTreeFactory, FilePropertyFactory filePropertyFactory, FileCollectionFactory fileCollectionFactory, DomainObjectCollectionFactory domainObjectCollectionFactory) {
+ ServiceRegistry services = ProjectScopeServices.this;
+ Instantiator instantiator = instantiatorFactory.injectAndDecorate(services);
+ return new DefaultObjectFactory(instantiator, NamedObjectInstantiator.INSTANCE, fileResolver, directoryFileTreeFactory, filePropertyFactory, fileCollectionFactory, domainObjectCollectionFactory);
+ }
+
+ protected DomainObjectCollectionFactory createDomainObjectCollectionFactory(InstantiatorFactory instantiatorFactory, CollectionCallbackActionDecorator collectionCallbackActionDecorator, CrossProjectConfigurator projectConfigurator) {
+ ServiceRegistry services = ProjectScopeServices.this;
+ return new DefaultDomainObjectCollectionFactory(instantiatorFactory, services, collectionCallbackActionDecorator, MutationGuards.of(projectConfigurator));
}
}
diff --git a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/SettingsScopeServices.java b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/SettingsScopeServices.java
index 919046fe395c..7fb1d49c3256 100644
--- a/subprojects/core/src/main/java/org/gradle/internal/service/scopes/SettingsScopeServices.java
+++ b/subprojects/core/src/main/java/org/gradle/internal/service/scopes/SettingsScopeServices.java
@@ -20,6 +20,7 @@
import org.gradle.api.internal.CollectionCallbackActionDecorator;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.SettingsInternal;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.BaseDirFileResolver;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.api.internal.plugins.DefaultPluginManager;
@@ -63,9 +64,9 @@ protected PluginRegistry createPluginRegistry(PluginRegistry parentRegistry) {
return parentRegistry.createChild(settings.getClassLoaderScope());
}
- protected PluginManagerInternal createPluginManager(Instantiator instantiator, PluginRegistry pluginRegistry, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator) {
+ protected PluginManagerInternal createPluginManager(Instantiator instantiator, PluginRegistry pluginRegistry, InstantiatorFactory instantiatorFactory, BuildOperationExecutor buildOperationExecutor, UserCodeApplicationContext userCodeApplicationContext, CollectionCallbackActionDecorator decorator, DomainObjectCollectionFactory domainObjectCollectionFactory) {
PluginTarget target = new ImperativeOnlyPluginTarget(settings);
- return instantiator.newInstance(DefaultPluginManager.class, pluginRegistry, instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator);
+ return instantiator.newInstance(DefaultPluginManager.class, pluginRegistry, instantiatorFactory.inject(this), target, buildOperationExecutor, userCodeApplicationContext, decorator, domainObjectCollectionFactory);
}
protected ProjectDescriptorRegistry createProjectDescriptorRegistry() {
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy
index 4850052a1cc6..2d2f692f7c90 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy
@@ -16,6 +16,7 @@
package org.gradle.api.internal.model
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory
import org.gradle.api.internal.file.FileCollectionFactory
import org.gradle.api.internal.file.FilePropertyFactory
import org.gradle.api.internal.file.FileResolver
@@ -26,7 +27,7 @@ import spock.lang.Unroll
class DefaultObjectFactoryTest extends Specification {
- def factory = new DefaultObjectFactory(Stub(Instantiator), Stub(NamedObjectInstantiator), Stub(FileResolver), Stub(DirectoryFileTreeFactory), Stub(FilePropertyFactory), Stub(FileCollectionFactory))
+ def factory = new DefaultObjectFactory(Stub(Instantiator), Stub(NamedObjectInstantiator), Stub(FileResolver), Stub(DirectoryFileTreeFactory), Stub(FilePropertyFactory), Stub(FileCollectionFactory), Stub(DomainObjectCollectionFactory))
def "property has no value"() {
expect:
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.groovy
index 8dbc2d43a9a2..f431d1d58f8a 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginContainerTest.groovy
@@ -37,7 +37,7 @@ class DefaultPluginContainerTest extends Specification {
def pluginRegistry = new DefaultPluginRegistry(pluginInspector, scope(classLoader))
def target = Mock(PluginTarget)
def instantiator = TestUtil.instantiatorFactory().inject()
- def pluginManager = new DefaultPluginManager(pluginRegistry, instantiator, target, new TestBuildOperationExecutor(), new DefaultUserCodeApplicationContext(), CollectionCallbackActionDecorator.NOOP)
+ def pluginManager = new DefaultPluginManager(pluginRegistry, instantiator, target, new TestBuildOperationExecutor(), new DefaultUserCodeApplicationContext(), CollectionCallbackActionDecorator.NOOP, TestUtil.domainObjectCollectionFactory())
@Subject
def container = pluginManager.pluginContainer
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginManagerTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginManagerTest.groovy
index 78c8333c536b..06388820eab5 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginManagerTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/plugins/DefaultPluginManagerTest.groovy
@@ -38,7 +38,7 @@ class DefaultPluginManagerTest extends Specification {
}
def registry = new DefaultPluginRegistry(new PluginInspector(new ModelRuleSourceDetector()), classLoaderScope)
def target = Mock(PluginTarget)
- def manager = new DefaultPluginManager(registry, TestUtil.instantiatorFactory().inject(), target, new TestBuildOperationExecutor(), new DefaultUserCodeApplicationContext(), CollectionCallbackActionDecorator.NOOP)
+ def manager = new DefaultPluginManager(registry, TestUtil.instantiatorFactory().inject(), target, new TestBuildOperationExecutor(), new DefaultUserCodeApplicationContext(), CollectionCallbackActionDecorator.NOOP, TestUtil.domainObjectCollectionFactory())
Class> rulesClass
Class extends Plugin> hybridClass
diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
index f04b191ae99f..8186bf1dbd8c 100644
--- a/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/project/DefaultProjectTest.groovy
@@ -42,6 +42,7 @@ import org.gradle.api.internal.ProcessOperations
import org.gradle.api.internal.artifacts.Module
import org.gradle.api.internal.artifacts.ProjectBackedModule
import org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory
import org.gradle.api.internal.file.DefaultProjectLayout
import org.gradle.api.internal.file.FileCollectionFactory
import org.gradle.api.internal.file.FileOperations
@@ -204,10 +205,11 @@ class DefaultProjectTest extends Specification {
serviceRegistryMock.get((Type) PluginManagerInternal) >> pluginManager
serviceRegistryMock.get((Type) TextResourceLoader) >> textResourceLoader
serviceRegistryMock.get(ManagedProxyFactory) >> managedProxyFactory
- serviceRegistryMock.get(AttributesSchema) >> attributesSchema
- serviceRegistryMock.get(BuildOperationExecutor) >> buildOperationExecutor
- serviceRegistryMock.get((Type) ListenerBuildOperationDecorator) >> listenerBuildOperationDecorator
- serviceRegistryMock.get((Type) CrossProjectConfigurator) >> crossProjectConfigurator
+ serviceRegistryMock.get(AttributesSchema) >> attributesSchema
+ serviceRegistryMock.get(BuildOperationExecutor) >> buildOperationExecutor
+ serviceRegistryMock.get((Type) ListenerBuildOperationDecorator) >> listenerBuildOperationDecorator
+ serviceRegistryMock.get((Type) CrossProjectConfigurator) >> crossProjectConfigurator
+ serviceRegistryMock.get(DomainObjectCollectionFactory) >> TestUtil.domainObjectCollectionFactory()
pluginManager.getPluginContainer() >> pluginContainer
serviceRegistryMock.get((Type) DeferredProjectConfiguration) >> Stub(DeferredProjectConfiguration)
diff --git a/subprojects/core/src/test/groovy/org/gradle/util/NameValidatorTest.groovy b/subprojects/core/src/test/groovy/org/gradle/util/NameValidatorTest.groovy
index 4c848addb433..c59b9b1676dd 100644
--- a/subprojects/core/src/test/groovy/org/gradle/util/NameValidatorTest.groovy
+++ b/subprojects/core/src/test/groovy/org/gradle/util/NameValidatorTest.groovy
@@ -46,7 +46,7 @@ class NameValidatorTest extends Specification {
@Shared
def domainObjectContainersWithValidation = [
["artifact types", new DefaultArtifactTypeContainer(TestUtil.instantiatorFactory().decorateLenient(), AttributeTestUtil.attributesFactory(), CollectionCallbackActionDecorator.NOOP)],
- ["configurations", new DefaultConfigurationContainer(null, TestUtil.instantiatorFactory().decorateLenient(), domainObjectContext(), Mock(ListenerManager), null, null, null, null, Mock(FileCollectionFactory), null, null, null, null, null, AttributeTestUtil.attributesFactory(), null, null, null, null, Stub(DocumentationRegistry), CollectionCallbackActionDecorator.NOOP, null)],
+ ["configurations", new DefaultConfigurationContainer(null, TestUtil.instantiatorFactory().decorateLenient(), domainObjectContext(), Mock(ListenerManager), null, null, null, null, Mock(FileCollectionFactory), null, null, null, null, null, AttributeTestUtil.attributesFactory(), null, null, null, null, Stub(DocumentationRegistry), CollectionCallbackActionDecorator.NOOP, null, TestUtil.domainObjectCollectionFactory())],
["flavors", new DefaultFlavorContainer(TestUtil.instantiatorFactory().decorateLenient(), CollectionCallbackActionDecorator.NOOP)],
["source sets", new DefaultSourceSetContainer(TestFiles.resolver(), null, TestUtil.instantiatorFactory().decorateLenient(), TestUtil.objectFactory(), CollectionCallbackActionDecorator.NOOP)]
]
diff --git a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy
index 1f31a911473a..808554b4a317 100644
--- a/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy
+++ b/subprojects/core/src/testFixtures/groovy/org/gradle/util/TestUtil.groovy
@@ -17,7 +17,11 @@ package org.gradle.util
import org.gradle.api.Task
+import org.gradle.api.internal.CollectionCallbackActionDecorator
import org.gradle.api.internal.FeaturePreviews
+import org.gradle.api.internal.MutationGuards
+import org.gradle.api.internal.collections.DefaultDomainObjectCollectionFactory
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory
import org.gradle.api.internal.file.DefaultFilePropertyFactory
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.file.TestFiles
@@ -33,6 +37,7 @@ import org.gradle.internal.instantiation.DefaultInstantiatorFactory
import org.gradle.internal.instantiation.InjectAnnotationHandler
import org.gradle.internal.instantiation.InstantiatorFactory
import org.gradle.internal.service.DefaultServiceRegistry
+import org.gradle.internal.service.ServiceRegistry
import org.gradle.test.fixtures.file.TestDirectoryProvider
import org.gradle.test.fixtures.file.TestFile
import org.gradle.testfixtures.ProjectBuilder
@@ -44,6 +49,7 @@ import static org.gradle.api.internal.FeaturePreviews.Feature.GRADLE_METADATA
class TestUtil {
public static final Closure TEST_CLOSURE = {}
private static InstantiatorFactory instantiatorFactory
+ private static ServiceRegistry services
private final File rootDir
@@ -61,6 +67,10 @@ class TestUtil {
return instantiatorFactory
}
+ static DomainObjectCollectionFactory domainObjectCollectionFactory() {
+ return new DefaultDomainObjectCollectionFactory(instantiatorFactory(), services(), CollectionCallbackActionDecorator.NOOP, MutationGuards.identity())
+ }
+
static ObjectFactory objectFactory() {
return objFactory(TestFiles.resolver())
}
@@ -70,10 +80,16 @@ class TestUtil {
}
private static ObjectFactory objFactory(FileResolver fileResolver) {
- DefaultServiceRegistry services = new DefaultServiceRegistry()
- services.add(ProviderFactory, new DefaultProviderFactory())
- services.add(InstantiatorFactory, instantiatorFactory())
- return new DefaultObjectFactory(instantiatorFactory().injectAndDecorate(services), NamedObjectInstantiator.INSTANCE, fileResolver, TestFiles.directoryFileTreeFactory(), new DefaultFilePropertyFactory(fileResolver), TestFiles.fileCollectionFactory())
+ return new DefaultObjectFactory(instantiatorFactory().injectAndDecorate(services()), NamedObjectInstantiator.INSTANCE, fileResolver, TestFiles.directoryFileTreeFactory(), new DefaultFilePropertyFactory(fileResolver), TestFiles.fileCollectionFactory(), domainObjectCollectionFactory())
+ }
+
+ private static ServiceRegistry services() {
+ if (services == null) {
+ services = new DefaultServiceRegistry()
+ services.add(ProviderFactory, new DefaultProviderFactory())
+ services.add(InstantiatorFactory, instantiatorFactory())
+ }
+ return services
}
static NamedObjectInstantiator objectInstantiator() {
diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
index 091a6ca63770..bce08e7f5325 100644
--- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
+++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DefaultDependencyManagementServices.java
@@ -93,6 +93,7 @@
import org.gradle.api.internal.attributes.AttributesSchemaInternal;
import org.gradle.api.internal.attributes.DefaultAttributesSchema;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.component.ComponentTypeRegistry;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FileResolver;
@@ -465,7 +466,8 @@ ConfigurationContainerInternal createConfigurationContainer(Instantiator instant
ProjectStateRegistry projectStateRegistry,
DocumentationRegistry documentationRegistry,
CollectionCallbackActionDecorator callbackDecorator,
- UserCodeApplicationContext userCodeApplicationContext) {
+ UserCodeApplicationContext userCodeApplicationContext,
+ DomainObjectCollectionFactory domainObjectCollectionFactory) {
return instantiator.newInstance(DefaultConfigurationContainer.class,
configurationResolver,
instantiator,
@@ -488,7 +490,8 @@ ConfigurationContainerInternal createConfigurationContainer(Instantiator instant
projectStateRegistry,
documentationRegistry,
callbackDecorator,
- userCodeApplicationContext
+ userCodeApplicationContext,
+ domainObjectCollectionFactory
);
}
diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
index 38ae463b6bbf..c3135b7e1c87 100644
--- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
+++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
@@ -52,7 +52,6 @@
import org.gradle.api.attributes.AttributeContainer;
import org.gradle.api.capabilities.Capability;
import org.gradle.api.file.FileCollection;
-import org.gradle.api.internal.CollectionCallbackActionDecorator;
import org.gradle.api.internal.CompositeDomainObjectSet;
import org.gradle.api.internal.DefaultDomainObjectSet;
import org.gradle.api.internal.DocumentationRegistry;
@@ -81,6 +80,7 @@
import org.gradle.api.internal.attributes.ImmutableAttributeContainerWithErrorMessage;
import org.gradle.api.internal.attributes.ImmutableAttributes;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.AbstractFileCollection;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FileCollectionInternal;
@@ -217,8 +217,8 @@ public void validateMutation(MutationType type) {
private final FileCollection intrinsicFiles;
private final DisplayName displayName;
- private CollectionCallbackActionDecorator callbackActionDecorator;
private UserCodeApplicationContext userCodeApplicationContext;
+ private final DomainObjectCollectionFactory domainObjectCollectionFactory;
private Action super ConfigurationInternal> beforeLocking;
@@ -239,12 +239,12 @@ public DefaultConfiguration(DomainObjectContext domainObjectContext,
ImmutableAttributesFactory attributesFactory,
RootComponentMetadataBuilder rootComponentMetadataBuilder,
DocumentationRegistry documentationRegistry,
- CollectionCallbackActionDecorator callbackDecorator,
UserCodeApplicationContext userCodeApplicationContext,
- DomainObjectProjectStateHandler domainObjectProjectStateHandler
+ DomainObjectProjectStateHandler domainObjectProjectStateHandler,
+ DomainObjectCollectionFactory domainObjectCollectionFactory
) {
- this.callbackActionDecorator = callbackDecorator;
this.userCodeApplicationContext = userCodeApplicationContext;
+ this.domainObjectCollectionFactory = domainObjectCollectionFactory;
this.identityPath = domainObjectContext.identityPath(name);
this.name = name;
this.configurationsProvider = configurationsProvider;
@@ -270,20 +270,20 @@ public DefaultConfiguration(DomainObjectContext domainObjectContext,
displayName = Describables.memoize(new ConfigurationDescription(identityPath));
- this.ownDependencies = new DefaultDomainObjectSet(Dependency.class, callbackDecorator);
+ this.ownDependencies = (DefaultDomainObjectSet)domainObjectCollectionFactory.newDomainObjectSet(Dependency.class);
this.ownDependencies.beforeCollectionChanges(validateMutationType(this, MutationType.DEPENDENCIES));
- this.ownDependencyConstraints = new DefaultDomainObjectSet(DependencyConstraint.class, callbackDecorator);
+ this.ownDependencyConstraints = (DefaultDomainObjectSet) domainObjectCollectionFactory.newDomainObjectSet(DependencyConstraint.class);
this.ownDependencyConstraints.beforeCollectionChanges(validateMutationType(this, MutationType.DEPENDENCIES));
this.dependencies = new DefaultDependencySet(Describables.of(displayName, "dependencies"), this, ownDependencies);
this.dependencyConstraints = new DefaultDependencyConstraintSet(Describables.of(displayName, "dependency constraints"), ownDependencyConstraints);
- this.ownArtifacts = new DefaultDomainObjectSet(PublishArtifact.class, callbackDecorator);
+ this.ownArtifacts = (DefaultDomainObjectSet)domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class);
this.ownArtifacts.beforeCollectionChanges(validateMutationType(this, MutationType.ARTIFACTS));
this.artifacts = new DefaultPublishArtifactSet(Describables.of(displayName, "artifacts"), ownArtifacts, fileCollectionFactory);
- this.outgoing = instantiator.newInstance(DefaultConfigurationPublications.class, displayName, artifacts, new AllArtifactsProvider(), configurationAttributes, instantiator, artifactNotationParser, capabilityNotationParser, fileCollectionFactory, attributesFactory, callbackDecorator);
+ this.outgoing = instantiator.newInstance(DefaultConfigurationPublications.class, displayName, artifacts, new AllArtifactsProvider(), configurationAttributes, instantiator, artifactNotationParser, capabilityNotationParser, fileCollectionFactory, attributesFactory, domainObjectCollectionFactory);
this.rootComponentMetadataBuilder = rootComponentMetadataBuilder;
this.projectStateHandler = domainObjectProjectStateHandler;
path = domainObjectContext.projectPath(name);
@@ -766,7 +766,7 @@ private synchronized void initAllDependencies() {
if (allDependencies != null) {
return;
}
- inheritedDependencies = CompositeDomainObjectSet.create(Dependency.class, callbackActionDecorator, ownDependencies);
+ inheritedDependencies = domainObjectCollectionFactory.newDomainObjectSet(Dependency.class, ownDependencies);
for (Configuration configuration : this.extendsFrom) {
inheritedDependencies.addCollection(configuration.getAllDependencies());
}
@@ -790,7 +790,7 @@ private synchronized void initAllDependencyConstraints() {
if (allDependencyConstraints != null) {
return;
}
- inheritedDependencyConstraints = CompositeDomainObjectSet.create(DependencyConstraint.class, callbackActionDecorator, ownDependencyConstraints);
+ inheritedDependencyConstraints = domainObjectCollectionFactory.newDomainObjectSet(DependencyConstraint.class, ownDependencyConstraints);
for (Configuration configuration : this.extendsFrom) {
inheritedDependencyConstraints.addCollection(configuration.getAllDependencyConstraints());
}
@@ -822,14 +822,14 @@ private synchronized void initAllArtifacts() {
if (canBeMutated) {
// If the configuration can still be mutated, we need to create a composite
- inheritedArtifacts = CompositeDomainObjectSet.create(PublishArtifact.class, callbackActionDecorator, ownArtifacts);
+ inheritedArtifacts = domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class, ownArtifacts);
}
for (Configuration configuration : this.extendsFrom) {
PublishArtifactSet allArtifacts = configuration.getAllArtifacts();
if (inheritedArtifacts != null || !allArtifacts.isEmpty()) {
if (inheritedArtifacts == null) {
// This configuration cannot be mutated, but some parent configurations provide artifacts
- inheritedArtifacts = CompositeDomainObjectSet.create(PublishArtifact.class, callbackActionDecorator, ownArtifacts);
+ inheritedArtifacts = domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class, ownArtifacts);
}
inheritedArtifacts.addCollection(allArtifacts);
}
@@ -968,7 +968,7 @@ private DefaultConfiguration createCopy(Set dependencies, Set childResolutionStrategy = resolutionStrategy != null ? Factories.constant(resolutionStrategy.copy()) : resolutionStrategyFactory;
DefaultConfiguration copiedConfiguration = instantiator.newInstance(DefaultConfiguration.class, domainObjectContext, newName,
configurationsProvider, resolver, listenerManager, metaDataProvider, childResolutionStrategy, projectAccessListener, projectFinder, fileCollectionFactory, buildOperationExecutor, instantiator, artifactNotationParser, capabilityNotationParser, attributesFactory,
- rootComponentMetadataBuilder, documentationRegistry, callbackActionDecorator, userCodeApplicationContext, projectStateHandler);
+ rootComponentMetadataBuilder, documentationRegistry, userCodeApplicationContext, projectStateHandler, domainObjectCollectionFactory);
configurationsProvider.setTheOnlyConfiguration(copiedConfiguration);
// state, cachedResolvedConfiguration, and extendsFrom intentionally not copied - must re-resolve copy
// copying extendsFrom could mess up dependencies when copy was re-resolved
diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
index 085f649b7b2a..716555315fcb 100644
--- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
+++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationContainer.java
@@ -40,6 +40,7 @@
import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.DefaultResolutionStrategy;
import org.gradle.api.internal.artifacts.transform.DomainObjectProjectStateHandler;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.project.ProjectStateRegistry;
import org.gradle.api.internal.tasks.TaskResolver;
@@ -78,6 +79,7 @@ public class DefaultConfigurationContainer extends AbstractValidatingNamedDomain
private int detachedConfigurationDefaultNameCounter = 1;
private final Factory resolutionStrategyFactory;
private final DefaultRootComponentMetadataBuilder rootComponentMetadataBuilder;
+ private final DomainObjectCollectionFactory domainObjectCollectionFactory;
public DefaultConfigurationContainer(ConfigurationResolver resolver,
final Instantiator instantiator, DomainObjectContext context, ListenerManager listenerManager,
@@ -96,7 +98,8 @@ public DefaultConfigurationContainer(ConfigurationResolver resolver,
ProjectStateRegistry projectStateRegistry,
DocumentationRegistry documentationRegistry,
CollectionCallbackActionDecorator callbackDecorator,
- UserCodeApplicationContext userCodeApplicationContext) {
+ UserCodeApplicationContext userCodeApplicationContext,
+ DomainObjectCollectionFactory domainObjectCollectionFactory) {
super(Configuration.class, instantiator, new Configuration.Namer(), callbackDecorator);
this.resolver = resolver;
this.instantiator = instantiator;
@@ -108,6 +111,7 @@ public DefaultConfigurationContainer(ConfigurationResolver resolver,
this.fileCollectionFactory = fileCollectionFactory;
this.buildOperationExecutor = buildOperationExecutor;
this.userCodeApplicationContext = userCodeApplicationContext;
+ this.domainObjectCollectionFactory = domainObjectCollectionFactory;
this.artifactNotationParser = new PublishArtifactNotationParserFactory(instantiator, dependencyMetaDataProvider, taskResolver).create();
this.capabilityNotationParser = new CapabilityNotationParserFactory(true).create();
this.attributesFactory = attributesFactory;
@@ -126,7 +130,7 @@ public ResolutionStrategyInternal create() {
protected Configuration doCreate(String name) {
DefaultConfiguration configuration = instantiator.newInstance(DefaultConfiguration.class, context, name, this, resolver,
listenerManager, dependencyMetaDataProvider, resolutionStrategyFactory, projectAccessListener, projectFinder,
- fileCollectionFactory, buildOperationExecutor, instantiator, artifactNotationParser, capabilityNotationParser, attributesFactory, rootComponentMetadataBuilder, documentationRegistry, getEventRegister().getDecorator(), userCodeApplicationContext, new DomainObjectProjectStateHandler(projectStateRegistry, context, projectFinder));
+ fileCollectionFactory, buildOperationExecutor, instantiator, artifactNotationParser, capabilityNotationParser, attributesFactory, rootComponentMetadataBuilder, documentationRegistry, userCodeApplicationContext, new DomainObjectProjectStateHandler(projectStateRegistry, context, projectFinder), domainObjectCollectionFactory);
configuration.addMutationValidator(rootComponentMetadataBuilder.getValidator());
return configuration;
}
@@ -159,7 +163,7 @@ public ConfigurationInternal detachedConfiguration(Dependency... dependencies) {
context, name, detachedConfigurationsProvider, resolver,
listenerManager, dependencyMetaDataProvider, resolutionStrategyFactory, projectAccessListener, projectFinder,
fileCollectionFactory, buildOperationExecutor, instantiator, artifactNotationParser, capabilityNotationParser, attributesFactory,
- rootComponentMetadataBuilder.withConfigurationsProvider(detachedConfigurationsProvider), documentationRegistry, getEventRegister().getDecorator(), userCodeApplicationContext, new DomainObjectProjectStateHandler(projectStateRegistry, context, projectFinder));
+ rootComponentMetadataBuilder.withConfigurationsProvider(detachedConfigurationsProvider), documentationRegistry, userCodeApplicationContext, new DomainObjectProjectStateHandler(projectStateRegistry, context, projectFinder), domainObjectCollectionFactory);
DomainObjectSet detachedDependencies = detachedConfiguration.getDependencies();
for (Dependency dependency : dependencies) {
detachedDependencies.add(dependency.copy());
diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationPublications.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationPublications.java
index 815e93f13f96..88ecb673284b 100644
--- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationPublications.java
+++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/configurations/DefaultConfigurationPublications.java
@@ -30,11 +30,10 @@
import org.gradle.api.artifacts.PublishArtifactSet;
import org.gradle.api.attributes.AttributeContainer;
import org.gradle.api.capabilities.Capability;
-import org.gradle.api.internal.CollectionCallbackActionDecorator;
-import org.gradle.api.internal.FactoryNamedDomainObjectContainer;
import org.gradle.api.internal.artifacts.ConfigurationVariantInternal;
import org.gradle.api.internal.attributes.AttributeContainerInternal;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
+import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.internal.DisplayName;
import org.gradle.internal.reflect.Instantiator;
@@ -56,8 +55,8 @@ public class DefaultConfigurationPublications implements ConfigurationPublicatio
private final NotationParser