Merge pull request #13349 from gradle/bamboo/cc/generateModuleMetadata/i
Extract serializable `ModuleMetadata` model from `ModuleMetadataJsonWriter`
diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriter.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriter.java
index 5fc8026..85e7315 100644
--- a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriter.java
+++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriter.java
@@ -17,11 +17,8 @@
package org.gradle.api.publish.internal.metadata;
import com.google.gson.stream.JsonWriter;
-import org.gradle.api.component.ComponentWithVariants;
-import org.gradle.api.component.SoftwareComponent;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser;
import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver;
-import org.gradle.api.internal.component.SoftwareComponentInternal;
import org.gradle.api.publish.internal.PublicationInternal;
import org.gradle.internal.hash.ChecksumService;
import org.gradle.internal.scopeids.id.BuildInvocationScopeId;
@@ -29,8 +26,6 @@
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
/**
* <p>The Gradle module metadata file generator is responsible for generating a JSON file
@@ -58,15 +53,9 @@
}
public void writeTo(Writer writer, PublicationInternal<?> publication, Collection<? extends PublicationInternal<?>> publications) throws IOException {
- // Collect a map from component to coordinates. This might be better to move to the component or some publications model
- Map<SoftwareComponent, ComponentData> coordinates = new HashMap<>();
- collectCoordinates(publications, coordinates);
- // Collect a map from component to its owning component. This might be better to move to the component or some publications model
- Map<SoftwareComponent, SoftwareComponent> owners = new HashMap<>();
- collectOwners(publications, owners);
-
- InvalidPublicationChecker checker = new InvalidPublicationChecker(publication.getName());
+ ModuleMetadata metadata = moduleMetadataFor(publication, publications);
+ String buildId = publication.isPublishBuildId() ? buildInvocationScopeId.getId().asString() : null;
// Write the output
JsonWriter jsonWriter = new JsonWriter(writer);
@@ -75,42 +64,24 @@
new ModuleMetadataJsonWriter(
jsonWriter,
- checker,
- checksumService,
- projectDependencyResolver,
- buildInvocationScopeId.getId().asString(),
- publication,
- publication.getComponent(),
- coordinates,
- owners
+ metadata,
+ buildId,
+ checksumService
).write();
jsonWriter.flush();
writer.append('\n');
+ }
+ private ModuleMetadata moduleMetadataFor(PublicationInternal<?> publication, Collection<? extends PublicationInternal<?>> publications) {
+ InvalidPublicationChecker checker = new InvalidPublicationChecker(publication.getName());
+ ModuleMetadata metadata = new ModuleMetadataBuilder(
+ publication,
+ publications,
+ checker,
+ projectDependencyResolver
+ ).build();
checker.validate();
- }
-
- private void collectOwners(Collection<? extends PublicationInternal<?>> publications, Map<SoftwareComponent, SoftwareComponent> owners) {
- for (PublicationInternal<?> publication : publications) {
- if (publication.getComponent() instanceof ComponentWithVariants) {
- ComponentWithVariants componentWithVariants = (ComponentWithVariants) publication.getComponent();
- for (SoftwareComponent child : componentWithVariants.getVariants()) {
- owners.put(child, publication.getComponent());
- }
- }
- }
- }
-
- private void collectCoordinates(Collection<? extends PublicationInternal<?>> publications, Map<SoftwareComponent, ComponentData> coordinates) {
- for (PublicationInternal<?> publication : publications) {
- SoftwareComponentInternal component = publication.getComponent();
- if (component != null) {
- coordinates.put(
- component,
- new ComponentData(publication.getCoordinates(), publication.getAttributes())
- );
- }
- }
+ return metadata;
}
}
diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadata.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadata.java
new file mode 100644
index 0000000..7ae7d13
--- /dev/null
+++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadata.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2020 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.publish.internal.metadata;
+
+import org.gradle.api.artifacts.ExcludeRule;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+class ModuleMetadata {
+
+ final Identity identity;
+ final List<Variant> variants;
+
+ ModuleMetadata(Identity identity, List<Variant> variants) {
+ this.identity = identity;
+ this.variants = variants;
+ }
+
+ static class Identity {
+
+ final ModuleVersionIdentifier coordinates;
+ final List<Attribute> attributes;
+ @Nullable
+ final String relativeUrl;
+
+ Identity(
+ ModuleVersionIdentifier coordinates,
+ List<Attribute> attributes,
+ @Nullable String relativeUrl
+ ) {
+ this.coordinates = coordinates;
+ this.attributes = attributes;
+ this.relativeUrl = relativeUrl;
+ }
+ }
+
+ static class LocalVariant extends Variant {
+
+ final String name;
+ final List<Attribute> attributes;
+ final List<Capability> capabilities;
+ final List<Dependency> dependencies;
+ final List<DependencyConstraint> dependencyConstraints;
+ final List<Artifact> artifacts;
+
+ LocalVariant(
+ String name,
+ List<Attribute> attributes,
+ List<Capability> capabilities,
+ List<Dependency> dependencies,
+ List<DependencyConstraint> dependencyConstraints,
+ List<Artifact> artifacts
+ ) {
+ this.name = name;
+ this.attributes = attributes;
+ this.capabilities = capabilities;
+ this.dependencies = dependencies;
+ this.dependencyConstraints = dependencyConstraints;
+ this.artifacts = artifacts;
+ }
+ }
+
+ static class RemoteVariant extends Variant {
+
+ final String name;
+ final List<Attribute> attributes;
+ final AvailableAt availableAt;
+ final List<Capability> capabilities;
+
+ RemoteVariant(
+ String name,
+ List<Attribute> attributes,
+ AvailableAt availableAt,
+ List<Capability> capabilities
+ ) {
+ this.name = name;
+ this.attributes = attributes;
+ this.availableAt = availableAt;
+ this.capabilities = capabilities;
+ }
+ }
+
+ static class Dependency {
+
+ final DependencyCoordinates coordinates;
+ final Set<ExcludeRule> excludeRules;
+ final List<Attribute> attributes;
+ final List<Capability> requestedCapabilities;
+ final boolean endorseStrictVersions;
+ final String reason;
+ final ArtifactSelector artifactSelector;
+
+ public Dependency(
+ DependencyCoordinates coordinates,
+ Set<ExcludeRule> excludeRules,
+ List<Attribute> attributes,
+ List<Capability> requestedCapabilities,
+ boolean endorseStrictVersions,
+ String reason,
+ ArtifactSelector artifactSelector
+ ) {
+ this.coordinates = coordinates;
+ this.excludeRules = excludeRules;
+ this.attributes = attributes;
+ this.requestedCapabilities = requestedCapabilities;
+ this.endorseStrictVersions = endorseStrictVersions;
+ this.reason = reason;
+ this.artifactSelector = artifactSelector;
+ }
+ }
+
+ static abstract class Variant {
+ }
+
+ static class Attribute {
+
+ final String name;
+ final Object value;
+
+ public Attribute(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+ }
+
+ static class Capability {
+
+ final String group;
+ final String name;
+ @Nullable
+ final String version;
+
+ public Capability(String group, String name, @Nullable String version) {
+ this.group = group;
+ this.name = name;
+ this.version = version;
+ }
+ }
+
+ static class Version {
+
+ @Nullable
+ final String requires;
+ @Nullable
+ final String strictly;
+ @Nullable
+ final String preferred;
+ final List<String> rejectedVersions;
+
+ public Version(
+ @Nullable String requires,
+ @Nullable String strictly,
+ @Nullable String preferred,
+ List<String> rejectedVersions
+ ) {
+ this.requires = requires;
+ this.strictly = strictly;
+ this.preferred = preferred;
+ this.rejectedVersions = rejectedVersions;
+ }
+ }
+
+ static class DependencyCoordinates {
+
+ final String group;
+ final String name;
+ final Version version;
+
+ public DependencyCoordinates(
+ String group, String name, Version version
+ ) {
+ this.group = group;
+ this.name = name;
+ this.version = version;
+ }
+ }
+
+ static class ArtifactSelector {
+
+ final String name;
+ final String type;
+ @Nullable
+ final String extension;
+ @Nullable
+ final String classifier;
+
+ public ArtifactSelector(
+ String name,
+ String type,
+ @Nullable String extension,
+ @Nullable String classifier
+ ) {
+ this.name = name;
+ this.type = type;
+ this.extension = extension;
+ this.classifier = classifier;
+ }
+ }
+
+ static class DependencyConstraint {
+
+ final String group;
+ final String module;
+ final Version version;
+ final List<Attribute> attributes;
+ final String reason;
+
+ public DependencyConstraint(
+ String group,
+ String module,
+ Version version,
+ List<Attribute> attributes,
+ String reason
+ ) {
+ this.group = group;
+ this.module = module;
+ this.version = version;
+ this.attributes = attributes;
+ this.reason = reason;
+ }
+ }
+
+ static class Artifact {
+
+ final String name;
+ final String uri;
+ final File file;
+
+ public Artifact(String name, String uri, File file) {
+ this.name = name;
+ this.uri = uri;
+ this.file = file;
+ }
+ }
+
+ static class AvailableAt {
+
+ final String url;
+ final ModuleVersionIdentifier coordinates;
+
+ public AvailableAt(String url, ModuleVersionIdentifier coordinates) {
+ this.url = url;
+ this.coordinates = coordinates;
+ }
+ }
+}
diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataBuilder.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataBuilder.java
new file mode 100644
index 0000000..b02bdfc
--- /dev/null
+++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataBuilder.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2020 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.publish.internal.metadata;
+
+import com.google.common.collect.Sets;
+import org.gradle.api.Named;
+import org.gradle.api.artifacts.DependencyArtifact;
+import org.gradle.api.artifacts.DependencyConstraint;
+import org.gradle.api.artifacts.ExcludeRule;
+import org.gradle.api.artifacts.ExternalDependency;
+import org.gradle.api.artifacts.ModuleDependency;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.api.artifacts.ProjectDependency;
+import org.gradle.api.artifacts.PublishArtifact;
+import org.gradle.api.attributes.Attribute;
+import org.gradle.api.attributes.AttributeContainer;
+import org.gradle.api.capabilities.Capability;
+import org.gradle.api.component.ComponentWithCoordinates;
+import org.gradle.api.component.ComponentWithVariants;
+import org.gradle.api.component.SoftwareComponent;
+import org.gradle.api.internal.artifacts.DefaultExcludeRule;
+import org.gradle.api.internal.artifacts.ImmutableVersionConstraint;
+import org.gradle.api.internal.artifacts.PublishArtifactInternal;
+import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint;
+import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependencyConstraint;
+import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver;
+import org.gradle.api.internal.attributes.AttributeContainerInternal;
+import org.gradle.api.internal.attributes.ImmutableAttributes;
+import org.gradle.api.internal.component.SoftwareComponentInternal;
+import org.gradle.api.internal.component.UsageContext;
+import org.gradle.api.publish.internal.PublicationInternal;
+import org.gradle.api.publish.internal.versionmapping.VariantVersionMappingStrategyInternal;
+import org.gradle.api.publish.internal.versionmapping.VersionMappingStrategyInternal;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static com.google.common.base.Strings.nullToEmpty;
+import static java.lang.String.format;
+import static java.util.Collections.emptyList;
+import static org.apache.commons.lang.StringUtils.isNotEmpty;
+
+class ModuleMetadataBuilder {
+
+ private final PublicationInternal<?> publication;
+ private final ModuleVersionIdentifier publicationCoordinates;
+ private final SoftwareComponentInternal component;
+ private final Collection<? extends PublicationInternal<?>> publications;
+ private final Map<SoftwareComponent, ComponentData> componentCoordinates = new HashMap<>();
+ private final ProjectDependencyPublicationResolver projectDependencyResolver;
+ private final InvalidPublicationChecker checker;
+
+ public ModuleMetadataBuilder(
+ PublicationInternal<?> publication,
+ Collection<? extends PublicationInternal<?>> publications,
+ InvalidPublicationChecker checker,
+ ProjectDependencyPublicationResolver projectDependencyResolver
+ ) {
+ this.component = publication.getComponent();
+ this.publicationCoordinates = publication.getCoordinates();
+ this.publication = publication;
+ this.publications = publications;
+ this.checker = checker;
+ this.projectDependencyResolver = projectDependencyResolver;
+ // Collect a map from component to coordinates. This might be better to move to the component or some publications model
+ collectCoordinates(componentCoordinates);
+ }
+
+ ModuleMetadata build() {
+ return new ModuleMetadata(identity(), variants());
+ }
+
+ private ModuleMetadata.Identity identity() {
+ // Collect a map from component to its owning component. This might be better to move to the component or some publications model
+ Map<SoftwareComponent, SoftwareComponent> owners = new HashMap<>();
+ collectOwners(publications, owners);
+
+ SoftwareComponent owner = owners.get(component);
+ ComponentData ownerData = owner == null ? null : componentCoordinates.get(owner);
+ ComponentData componentData = componentCoordinates.get(component);
+
+ return ownerData != null
+ ? identityFor(ownerData, relativeUrlTo(componentData.coordinates, ownerData.coordinates))
+ : identityFor(componentData, null);
+ }
+
+ private ModuleMetadata.Identity identityFor(ComponentData componentData, String relativeUrl) {
+ return new ModuleMetadata.Identity(
+ componentData.coordinates,
+ attributesFor(componentData.attributes),
+ relativeUrl
+ );
+ }
+
+ private List<ModuleMetadata.Variant> variants() {
+ ArrayList<ModuleMetadata.Variant> variants = new ArrayList<>();
+ for (UsageContext variant : component.getUsages()) {
+ checkVariant(variant);
+ variants.add(
+ new ModuleMetadata.LocalVariant(
+ variant.getName(),
+ attributesFor(variant.getAttributes()),
+ capabilitiesFor(variant.getCapabilities()),
+ dependenciesOf(variant),
+ dependencyConstraintsFor(variant),
+ artifactsOf(variant)
+ )
+ );
+ }
+ if (component instanceof ComponentWithVariants) {
+ for (SoftwareComponent childComponent : ((ComponentWithVariants) component).getVariants()) {
+ ModuleVersionIdentifier childCoordinates = coordinatesOf(childComponent);
+ assert childCoordinates != null;
+ if (childComponent instanceof SoftwareComponentInternal) {
+ for (UsageContext variant : ((SoftwareComponentInternal) childComponent).getUsages()) {
+ checkVariant(variant);
+ variants.add(
+ new ModuleMetadata.RemoteVariant(
+ variant.getName(),
+ attributesFor(variant.getAttributes()),
+ availableAt(publicationCoordinates, childCoordinates),
+ capabilitiesFor(variant.getCapabilities())
+ )
+ );
+ }
+ }
+ }
+ }
+ return variants;
+ }
+
+ private List<ModuleMetadata.Artifact> artifactsOf(UsageContext variant) {
+ if (variant.getArtifacts().isEmpty()) {
+ return emptyList();
+ }
+ ArrayList<ModuleMetadata.Artifact> artifacts = new ArrayList<>();
+ for (PublishArtifact artifact : variant.getArtifacts()) {
+ ModuleMetadata.Artifact metadataArtifact = artifactFor(artifact);
+ if (metadataArtifact != null) {
+ artifacts.add(metadataArtifact);
+ }
+ }
+ return artifacts;
+ }
+
+ @Nullable
+ private ModuleMetadata.Artifact artifactFor(PublishArtifact artifact) {
+ if (shouldNotBePublished(artifact)) {
+ return null;
+ }
+ PublicationInternal.PublishedFile publishedFile = publication.getPublishedFile(artifact);
+ return new ModuleMetadata.Artifact(
+ publishedFile.getName(),
+ publishedFile.getUri(),
+ artifact.getFile()
+ );
+ }
+
+ private boolean shouldNotBePublished(PublishArtifact artifact) {
+ return artifact instanceof PublishArtifactInternal
+ && !((PublishArtifactInternal) artifact).shouldBePublished();
+ }
+
+ private ModuleMetadata.AvailableAt availableAt(ModuleVersionIdentifier coordinates, ModuleVersionIdentifier targetCoordinates) {
+ return new ModuleMetadata.AvailableAt(
+ relativeUrlTo(coordinates, targetCoordinates),
+ targetCoordinates
+ );
+ }
+
+ private ModuleMetadata.Dependency dependencyFor(
+ ModuleDependency dependency,
+ Set<ExcludeRule> additionalExcludes,
+ VariantVersionMappingStrategyInternal versionMappingStrategy,
+ DependencyArtifact dependencyArtifact
+ ) {
+ return new ModuleMetadata.Dependency(
+ dependencyCoordinatesFor(dependency, versionMappingStrategy),
+ excludedRulesFor(dependency, additionalExcludes),
+ attributesFor(dependency.getAttributes()),
+ capabilitiesFor(dependency.getRequestedCapabilities()),
+ dependency.isEndorsingStrictVersions(),
+ isNotEmpty(dependency.getReason()) ? dependency.getReason() : null,
+ dependencyArtifact != null ? artifactSelectorFor(dependencyArtifact) : null
+ );
+ }
+
+ private ModuleMetadata.DependencyCoordinates dependencyCoordinatesFor(
+ ModuleDependency dependency,
+ VariantVersionMappingStrategyInternal versionMappingStrategy
+ ) {
+ return dependency instanceof ProjectDependency
+ ? projectDependencyCoordinatesFor((ProjectDependency) dependency, versionMappingStrategy)
+ : moduleDependencyCoordinatesFor(dependency, versionMappingStrategy);
+ }
+
+ private ModuleMetadata.ArtifactSelector artifactSelectorFor(DependencyArtifact dependencyArtifact) {
+ return new ModuleMetadata.ArtifactSelector(
+ dependencyArtifact.getName(),
+ dependencyArtifact.getType(),
+ isNullOrEmpty(dependencyArtifact.getExtension()) ? null : dependencyArtifact.getExtension(),
+ isNullOrEmpty(dependencyArtifact.getClassifier()) ? null : dependencyArtifact.getClassifier()
+ );
+ }
+
+ private List<ModuleMetadata.Capability> capabilitiesFor(Collection<? extends Capability> capabilities) {
+ if (capabilities.isEmpty()) {
+ return emptyList();
+ }
+
+ ArrayList<ModuleMetadata.Capability> metadataCapabilities = new ArrayList<>();
+ for (Capability capability : capabilities) {
+ metadataCapabilities.add(
+ new ModuleMetadata.Capability(
+ capability.getGroup(),
+ capability.getName(),
+ isNotEmpty(capability.getVersion()) ? capability.getVersion() : null
+ )
+ );
+ }
+ return metadataCapabilities;
+ }
+
+ private List<ModuleMetadata.Attribute> attributesFor(AttributeContainer attributes) {
+ if (attributes.isEmpty()) {
+ return emptyList();
+ }
+
+ ArrayList<ModuleMetadata.Attribute> metadataAttributes = new ArrayList<>();
+ for (Attribute<?> attribute : sorted(attributes).values()) {
+ String name = attribute.getName();
+ Object value = attributes.getAttribute(attribute);
+ Object effectiveValue = attributeValueFor(value);
+ if (effectiveValue == null) {
+ throw new IllegalArgumentException(
+ format("Cannot write attribute %s with unsupported value %s of type %s.", name, value, value.getClass().getName())
+ );
+ }
+ metadataAttributes.add(
+ new ModuleMetadata.Attribute(name, effectiveValue)
+ );
+ }
+ return metadataAttributes;
+ }
+
+ private Object attributeValueFor(Object value) {
+ if (value instanceof Boolean || value instanceof Integer || value instanceof String) {
+ return value;
+ } else if (value instanceof Named) {
+ return ((Named) value).getName();
+ } else if (value instanceof Enum) {
+ return ((Enum<?>) value).name();
+ } else {
+ return null;
+ }
+ }
+
+ private ModuleMetadata.DependencyCoordinates moduleDependencyCoordinatesFor(
+ ModuleDependency dependency,
+ VariantVersionMappingStrategyInternal versionMappingStrategy
+ ) {
+ String group = dependency.getGroup();
+ String name = dependency.getName();
+ String resolvedVersion = null;
+ if (versionMappingStrategy != null) {
+ ModuleVersionIdentifier resolvedVersionId = versionMappingStrategy.maybeResolveVersion(group, name);
+ if (resolvedVersionId != null) {
+ group = resolvedVersionId.getGroup();
+ name = resolvedVersionId.getName();
+ resolvedVersion = resolvedVersionId.getVersion();
+ }
+ }
+ return new ModuleMetadata.DependencyCoordinates(
+ group,
+ name,
+ versionFor(versionConstraintFor(dependency), resolvedVersion)
+ );
+ }
+
+ private ModuleMetadata.DependencyCoordinates projectDependencyCoordinatesFor(
+ ProjectDependency projectDependency,
+ VariantVersionMappingStrategyInternal versionMappingStrategy
+ ) {
+ String resolvedVersion = null;
+ ModuleVersionIdentifier identifier = moduleIdentifierFor(projectDependency);
+ if (versionMappingStrategy != null) {
+ ModuleVersionIdentifier resolved =
+ versionMappingStrategy.maybeResolveVersion(
+ identifier.getGroup(),
+ identifier.getName()
+ );
+ if (resolved != null) {
+ identifier = resolved;
+ resolvedVersion = identifier.getVersion();
+ }
+ }
+ return new ModuleMetadata.DependencyCoordinates(
+ identifier.getGroup(),
+ identifier.getName(),
+ versionFor(
+ DefaultImmutableVersionConstraint.of(identifier.getVersion()),
+ resolvedVersion
+ )
+ );
+ }
+
+ private List<ModuleMetadata.Dependency> dependenciesOf(UsageContext variant) {
+ if (variant.getDependencies().isEmpty()) {
+ return emptyList();
+ }
+ ArrayList<ModuleMetadata.Dependency> dependencies = new ArrayList<>();
+ Set<ExcludeRule> additionalExcludes = variant.getGlobalExcludes();
+ VariantVersionMappingStrategyInternal versionMappingStrategy = versionMappingStrategyFor(variant);
+ for (ModuleDependency moduleDependency : variant.getDependencies()) {
+ if (moduleDependency.getArtifacts().isEmpty()) {
+ dependencies.add(
+ dependencyFor(
+ moduleDependency,
+ additionalExcludes,
+ versionMappingStrategy,
+ null
+ )
+ );
+ } else {
+ for (DependencyArtifact dependencyArtifact : moduleDependency.getArtifacts()) {
+ dependencies.add(
+ dependencyFor(
+ moduleDependency,
+ additionalExcludes,
+ versionMappingStrategy,
+ dependencyArtifact
+ )
+ );
+ }
+ }
+ }
+ return dependencies;
+ }
+
+ private List<ModuleMetadata.DependencyConstraint> dependencyConstraintsFor(UsageContext variant) {
+ if (variant.getDependencyConstraints().isEmpty()) {
+ return emptyList();
+ }
+ VariantVersionMappingStrategyInternal versionMappingStrategy = versionMappingStrategyFor(variant);
+ ArrayList<ModuleMetadata.DependencyConstraint> dependencyConstraints = new ArrayList<>();
+ for (DependencyConstraint dependencyConstraint : variant.getDependencyConstraints()) {
+ dependencyConstraints.add(
+ dependencyConstraintFor(dependencyConstraint, versionMappingStrategy)
+ );
+ }
+ return dependencyConstraints;
+ }
+
+ private ModuleMetadata.DependencyConstraint dependencyConstraintFor(DependencyConstraint dependencyConstraint, VariantVersionMappingStrategyInternal variantVersionMappingStrategy) {
+ String group;
+ String module;
+ String resolvedVersion = null;
+ if (dependencyConstraint instanceof DefaultProjectDependencyConstraint) {
+ DefaultProjectDependencyConstraint dependency = (DefaultProjectDependencyConstraint) dependencyConstraint;
+ ProjectDependency projectDependency = dependency.getProjectDependency();
+ ModuleVersionIdentifier identifier = moduleIdentifierFor(projectDependency);
+ group = identifier.getGroup();
+ module = identifier.getName();
+ resolvedVersion = identifier.getVersion();
+ } else {
+ group = dependencyConstraint.getGroup();
+ module = dependencyConstraint.getName();
+ }
+ ModuleVersionIdentifier resolvedVersionId = variantVersionMappingStrategy != null
+ ? variantVersionMappingStrategy.maybeResolveVersion(group, module)
+ : null;
+ String effectiveGroup = resolvedVersionId != null ? resolvedVersionId.getGroup() : group;
+ String effectiveModule = resolvedVersionId != null ? resolvedVersionId.getName() : module;
+ String effectiveVersion = resolvedVersionId != null ? resolvedVersionId.getVersion() : resolvedVersion;
+ return new ModuleMetadata.DependencyConstraint(
+ effectiveGroup,
+ effectiveModule,
+ versionFor(
+ DefaultImmutableVersionConstraint.of(dependencyConstraint.getVersionConstraint()),
+ effectiveVersion
+ ),
+ attributesFor(dependencyConstraint.getAttributes()),
+ isNotEmpty(dependencyConstraint.getReason()) ? dependencyConstraint.getReason() : null
+ );
+ }
+
+ @Nullable
+ private ModuleMetadata.Version versionFor(
+ ImmutableVersionConstraint versionConstraint,
+ @Nullable String resolvedVersion
+ ) {
+ checker.sawDependencyOrConstraint();
+ if (resolvedVersion == null && isEmpty(versionConstraint)) {
+ return null;
+ }
+ checker.sawVersion();
+
+ boolean isStrict = !versionConstraint.getStrictVersion().isEmpty();
+ String version;
+ String preferred;
+ if (resolvedVersion != null) {
+ version = resolvedVersion;
+ preferred = null;
+ } else {
+ version = isStrict
+ ? versionConstraint.getStrictVersion()
+ : !versionConstraint.getRequiredVersion().isEmpty()
+ ? versionConstraint.getRequiredVersion()
+ : null;
+ preferred = !versionConstraint.getPreferredVersion().isEmpty()
+ ? versionConstraint.getPreferredVersion()
+ : null;
+ }
+ return new ModuleMetadata.Version(
+ version,
+ isStrict ? version : null,
+ preferred,
+ versionConstraint.getRejectedVersions()
+ );
+ }
+
+ private void collectOwners(
+ Collection<? extends PublicationInternal<?>> publications,
+ Map<SoftwareComponent, SoftwareComponent> owners
+ ) {
+ for (PublicationInternal<?> publication : publications) {
+ if (publication.getComponent() instanceof ComponentWithVariants) {
+ ComponentWithVariants componentWithVariants = (ComponentWithVariants) publication.getComponent();
+ for (SoftwareComponent child : componentWithVariants.getVariants()) {
+ owners.put(child, publication.getComponent());
+ }
+ }
+ }
+ }
+
+ private void collectCoordinates(Map<SoftwareComponent, ComponentData> coordinates) {
+ for (PublicationInternal<?> publication : publications) {
+ SoftwareComponentInternal component = publication.getComponent();
+ if (component != null) {
+ coordinates.put(
+ component,
+ new ComponentData(publication.getCoordinates(), publication.getAttributes())
+ );
+ }
+ }
+ }
+
+ private void checkVariant(UsageContext usageContext) {
+ checker.registerVariant(
+ usageContext.getName(),
+ usageContext.getAttributes(),
+ usageContext.getCapabilities()
+ );
+ }
+
+ private ImmutableVersionConstraint versionConstraintFor(ModuleDependency dependency) {
+ return dependency instanceof ExternalDependency
+ ? DefaultImmutableVersionConstraint.of(((ExternalDependency) dependency).getVersionConstraint())
+ : DefaultImmutableVersionConstraint.of(nullToEmpty(dependency.getVersion()));
+ }
+
+ private Set<ExcludeRule> excludedRulesFor(ModuleDependency moduleDependency, Set<ExcludeRule> additionalExcludes) {
+ return moduleDependency.isTransitive()
+ ? Sets.union(additionalExcludes, moduleDependency.getExcludeRules())
+ : Collections.singleton(new DefaultExcludeRule(null, null));
+ }
+
+ private Map<String, Attribute<?>> sorted(AttributeContainer attributes) {
+ Map<String, Attribute<?>> sortedAttributes = new TreeMap<>();
+ for (Attribute<?> attribute : attributes.keySet()) {
+ sortedAttributes.put(attribute.getName(), attribute);
+ }
+ return sortedAttributes;
+ }
+
+ private ModuleVersionIdentifier coordinatesOf(SoftwareComponent childComponent) {
+ if (childComponent instanceof ComponentWithCoordinates) {
+ return ((ComponentWithCoordinates) childComponent).getCoordinates();
+ }
+ ComponentData componentData = componentCoordinates.get(childComponent);
+ if (componentData != null) {
+ return componentData.coordinates;
+ }
+ return null;
+ }
+
+ private ModuleVersionIdentifier moduleIdentifierFor(ProjectDependency projectDependency) {
+ return projectDependencyResolver.resolve(ModuleVersionIdentifier.class, projectDependency);
+ }
+
+ private VariantVersionMappingStrategyInternal versionMappingStrategyFor(UsageContext variant) {
+ VersionMappingStrategyInternal versionMappingStrategy = publication.getVersionMappingStrategy();
+ return versionMappingStrategy != null
+ ? versionMappingStrategy.findStrategyForVariant(immutableAttributesOf(variant))
+ : null;
+ }
+
+ private ImmutableAttributes immutableAttributesOf(UsageContext variant) {
+ return ((AttributeContainerInternal) variant.getAttributes()).asImmutable();
+ }
+
+ private boolean isEmpty(ImmutableVersionConstraint versionConstraint) {
+ return DefaultImmutableVersionConstraint.of().equals(versionConstraint);
+ }
+
+ public static String relativeUrlTo(
+ @SuppressWarnings("unused") ModuleVersionIdentifier from,
+ ModuleVersionIdentifier to
+ ) {
+ // TODO - do not assume Maven layout
+ StringBuilder path = new StringBuilder();
+ path.append("../../");
+ path.append(to.getName());
+ path.append("/");
+ path.append(to.getVersion());
+ path.append("/");
+ path.append(to.getName());
+ path.append("-");
+ path.append(to.getVersion());
+ path.append(".module");
+ return path.toString();
+ }
+}
diff --git a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataJsonWriter.java b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataJsonWriter.java
index fc4265b..5d21d6e 100644
--- a/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataJsonWriter.java
+++ b/subprojects/publish/src/main/java/org/gradle/api/publish/internal/metadata/ModuleMetadataJsonWriter.java
@@ -16,97 +16,44 @@
package org.gradle.api.publish.internal.metadata;
-import com.google.common.collect.Sets;
import com.google.gson.stream.JsonWriter;
-import org.gradle.api.Named;
-import org.gradle.api.artifacts.DependencyArtifact;
-import org.gradle.api.artifacts.DependencyConstraint;
import org.gradle.api.artifacts.ExcludeRule;
-import org.gradle.api.artifacts.ExternalDependency;
-import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.api.artifacts.ProjectDependency;
-import org.gradle.api.artifacts.PublishArtifact;
-import org.gradle.api.attributes.Attribute;
-import org.gradle.api.attributes.AttributeContainer;
-import org.gradle.api.capabilities.Capability;
-import org.gradle.api.component.ComponentWithCoordinates;
-import org.gradle.api.component.ComponentWithVariants;
-import org.gradle.api.component.SoftwareComponent;
-import org.gradle.api.internal.artifacts.DefaultExcludeRule;
-import org.gradle.api.internal.artifacts.ImmutableVersionConstraint;
-import org.gradle.api.internal.artifacts.PublishArtifactInternal;
-import org.gradle.api.internal.artifacts.dependencies.DefaultImmutableVersionConstraint;
-import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependencyConstraint;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.GradleModuleMetadataParser;
-import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver;
-import org.gradle.api.internal.attributes.AttributeContainerInternal;
-import org.gradle.api.internal.attributes.ImmutableAttributes;
-import org.gradle.api.internal.component.SoftwareComponentInternal;
-import org.gradle.api.internal.component.UsageContext;
-import org.gradle.api.publish.internal.PublicationInternal;
-import org.gradle.api.publish.internal.versionmapping.VariantVersionMappingStrategyInternal;
-import org.gradle.api.publish.internal.versionmapping.VersionMappingStrategyInternal;
import org.gradle.internal.hash.ChecksumService;
import org.gradle.util.GradleVersion;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.TreeMap;
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static com.google.common.base.Strings.nullToEmpty;
-import static java.lang.String.format;
-import static org.apache.commons.lang.StringUtils.isNotEmpty;
import static org.gradle.util.GUtil.elvis;
-
class ModuleMetadataJsonWriter extends JsonWriterScope {
+ private final ModuleMetadata metadata;
+ @Nullable
private final String buildId;
- private final PublicationInternal<?> publication;
- private final SoftwareComponentInternal component;
- private final Map<SoftwareComponent, ComponentData> componentCoordinates;
- private final Map<SoftwareComponent, SoftwareComponent> owners;
- private final InvalidPublicationChecker checker;
- private final ProjectDependencyPublicationResolver projectDependencyResolver;
private final ChecksumService checksumService;
public ModuleMetadataJsonWriter(
JsonWriter jsonWriter,
- InvalidPublicationChecker checker,
- ChecksumService checksumService,
- ProjectDependencyPublicationResolver projectDependencyResolver,
- String buildId,
- PublicationInternal<?> publication,
- SoftwareComponentInternal component,
- Map<SoftwareComponent, ComponentData> componentCoordinates,
- Map<SoftwareComponent, SoftwareComponent> owners
+ ModuleMetadata metadata,
+ @Nullable String buildId,
+ ChecksumService checksumService
) {
super(jsonWriter);
+ this.metadata = metadata;
this.buildId = buildId;
- this.publication = publication;
- this.component = component;
- this.componentCoordinates = componentCoordinates;
- this.owners = owners;
- this.checker = checker;
- this.projectDependencyResolver = projectDependencyResolver;
this.checksumService = checksumService;
}
void write() throws IOException {
- SoftwareComponent owner = owners.get(component);
- ComponentData ownerData = owner == null ? null : componentCoordinates.get(owner);
- ComponentData componentData = componentCoordinates.get(component);
writeObject(() -> {
writeFormat();
- writeIdentity(componentData, ownerData);
+ writeIdentity();
writeCreator();
writeVariants();
});
@@ -116,23 +63,22 @@
write("formatVersion", GradleModuleMetadataParser.FORMAT_VERSION);
}
- private void writeIdentity(
- ComponentData component,
- @Nullable ComponentData owner
- ) throws IOException {
- if (owner != null) {
- String relativeUrl = relativeUrlTo(component.coordinates, owner.coordinates);
- writeComponentRef(owner, relativeUrl);
- } else {
- writeComponentRef(component, null);
- }
+ private void writeIdentity() throws IOException {
+ writeObject("component", () -> {
+ ModuleMetadata.Identity identity = metadata.identity;
+ if (identity.relativeUrl != null) {
+ write("url", identity.relativeUrl);
+ }
+ writeCoordinates(identity.coordinates);
+ writeAttributes(identity.attributes);
+ });
}
private void writeCreator() throws IOException {
writeObject("createdBy", () ->
writeObject("gradle", () -> {
write("version", GradleVersion.current().getVersion());
- if (publication.isPublishBuildId()) {
+ if (buildId != null) {
write("buildId", buildId);
}
})
@@ -140,121 +86,86 @@
}
private void writeVariants() throws IOException {
- boolean started = false;
- for (UsageContext usageContext : component.getUsages()) {
- checkVariant(usageContext);
- if (!started) {
- beginArray("variants");
- started = true;
- }
- writeVariantHostedInThisModule(usageContext);
- }
- if (component instanceof ComponentWithVariants) {
- for (SoftwareComponent childComponent : ((ComponentWithVariants) component).getVariants()) {
- ModuleVersionIdentifier childCoordinates = coordinatesOf(childComponent);
- assert childCoordinates != null;
- if (childComponent instanceof SoftwareComponentInternal) {
- for (UsageContext usageContext : ((SoftwareComponentInternal) childComponent).getUsages()) {
- checkVariant(usageContext);
- if (!started) {
- beginArray("variants");
- started = true;
- }
- writeVariantHostedInAnotherModule(publication.getCoordinates(), childCoordinates, usageContext);
- }
- }
- }
- }
- if (started) {
- endArray();
- }
- }
-
- private void writeVariantHostedInThisModule(UsageContext variant) throws IOException {
- writeObject(() -> {
- write("name", variant.getName());
- writeAttributes(variant.getAttributes());
- writeDependencies(variant);
- writeDependencyConstraints(variant);
- writeArtifacts(publication, variant);
- writeCapabilities("capabilities", variant.getCapabilities());
- });
- }
-
- private void writeVariantHostedInAnotherModule(ModuleVersionIdentifier coordinates, ModuleVersionIdentifier targetCoordinates, UsageContext variant) throws IOException {
- writeObject(() -> {
- write("name", variant.getName());
- writeAttributes(variant.getAttributes());
- writeAvailableAt(coordinates, targetCoordinates);
- writeCapabilities("capabilities", variant.getCapabilities());
- });
- }
-
- private void writeAttributes(AttributeContainer attributes) throws IOException {
- if (attributes.isEmpty()) {
+ List<ModuleMetadata.Variant> variants = metadata.variants;
+ if (variants.isEmpty()) {
return;
}
- writeObject("attributes", () -> {
- for (Attribute<?> attribute : sorted(attributes).values()) {
- String name = attribute.getName();
- Object value = attributes.getAttribute(attribute);
- if (!writeAttribute(name, value)) {
- throw new IllegalArgumentException(
- format("Cannot write attribute %s with unsupported value %s of type %s.", name, value, value.getClass().getName())
- );
+ writeArray("variants", () -> {
+ for (ModuleMetadata.Variant variant : variants) {
+ if (variant instanceof ModuleMetadata.LocalVariant) {
+ ModuleMetadata.LocalVariant local = (ModuleMetadata.LocalVariant) variant;
+ writeObject(() -> {
+ write("name", local.name);
+ writeAttributes(local.attributes);
+ writeDependencies(local.dependencies);
+ writeDependencyConstraints(local.dependencyConstraints);
+ writeArtifacts(local.artifacts);
+ writeCapabilities("capabilities", local.capabilities);
+ });
+ continue;
}
+ if (variant instanceof ModuleMetadata.RemoteVariant) {
+ ModuleMetadata.RemoteVariant remote = (ModuleMetadata.RemoteVariant) variant;
+ writeObject(() -> {
+ write("name", remote.name);
+ writeAttributes(remote.attributes);
+ writeAvailableAt(remote.availableAt);
+ writeCapabilities("capabilities", remote.capabilities);
+ });
+ continue;
+ }
+ throw new IllegalStateException("Unknown variant type: " + variant);
}
});
}
- private boolean writeAttribute(String name, Object value) throws IOException {
+ private void writeNonEmptyAttributes(List<ModuleMetadata.Attribute> attributes) throws IOException {
+ if (!attributes.isEmpty()) {
+ writeAttributes(attributes);
+ }
+ }
+
+ private void writeAttributes(List<ModuleMetadata.Attribute> attributes) throws IOException {
+ writeObject("attributes", () -> {
+ for (ModuleMetadata.Attribute attribute : attributes) {
+ writeAttribute(attribute.name, attribute.value);
+ }
+ });
+ }
+
+ private void writeAttribute(String name, Object value) throws IOException {
if (value instanceof Boolean) {
write(name, (Boolean) value);
} else if (value instanceof Integer) {
write(name, (Integer) value);
} else if (value instanceof String) {
write(name, (String) value);
- } else if (value instanceof Named) {
- write(name, ((Named) value).getName());
- } else if (value instanceof Enum) {
- write(name, ((Enum<?>) value).name());
} else {
- return false;
+ throw new IllegalArgumentException("value");
}
- return true;
}
- private void writeCapabilities(String key, Collection<? extends Capability> capabilities) throws IOException {
+ private void writeCapabilities(String key, List<ModuleMetadata.Capability> capabilities) throws IOException {
if (capabilities.isEmpty()) {
return;
}
writeArray(key, () -> {
- for (Capability capability : capabilities) {
+ for (ModuleMetadata.Capability capability : capabilities) {
writeObject(() -> {
- write("group", capability.getGroup());
- write("name", capability.getName());
- if (isNotEmpty(capability.getVersion())) {
- write("version", capability.getVersion());
+ write("group", capability.group);
+ write("name", capability.name);
+ if (capability.version != null) {
+ write("version", capability.version);
}
});
}
});
}
- private void writeAvailableAt(ModuleVersionIdentifier coordinates, ModuleVersionIdentifier targetCoordinates) throws IOException {
+ private void writeAvailableAt(ModuleMetadata.AvailableAt availableAt) throws IOException {
writeObject("available-at", () -> {
- write("url", relativeUrlTo(coordinates, targetCoordinates));
- writeCoordinates(targetCoordinates);
- });
- }
-
- private void writeComponentRef(ComponentData data, @Nullable String relativeUrl) throws IOException {
- writeObject("component", () -> {
- if (relativeUrl != null) {
- write("url", relativeUrl);
- }
- writeCoordinates(data.coordinates);
- writeAttributes(data.attributes);
+ write("url", availableAt.url);
+ writeCoordinates(availableAt.coordinates);
});
}
@@ -264,230 +175,109 @@
write("version", coordinates.getVersion());
}
- private void writeArtifacts(PublicationInternal<?> publication, UsageContext variant) throws IOException {
- if (variant.getArtifacts().isEmpty()) {
+ private void writeArtifacts(List<ModuleMetadata.Artifact> artifacts) throws IOException {
+ if (artifacts.isEmpty()) {
return;
}
writeArray("files", () -> {
- for (PublishArtifact artifact : variant.getArtifacts()) {
- writeArtifact(publication, artifact);
+ for (ModuleMetadata.Artifact artifact : artifacts) {
+ writeObject(() -> {
+ write("name", artifact.name);
+ write("url", artifact.uri);
+ File file = artifact.file;
+ write("size", file.length());
+ write("sha512", sha512(file));
+ write("sha256", sha256(file));
+ write("sha1", sha1(file));
+ write("md5", md5(file));
+ });
}
});
}
- private void writeArtifact(PublicationInternal<?> publication, PublishArtifact artifact) throws IOException {
- if (artifact instanceof PublishArtifactInternal) {
- if (!((PublishArtifactInternal) artifact).shouldBePublished()) {
- return;
- }
- }
- PublicationInternal.PublishedFile publishedFile = publication.getPublishedFile(artifact);
- File artifactFile = artifact.getFile();
-
- writeObject(() -> {
- write("name", publishedFile.getName());
- write("url", publishedFile.getUri());
- write("size", artifactFile.length());
- writeChecksumsOf(artifactFile);
- });
- }
-
- private void writeChecksumsOf(File artifactFile) throws IOException {
- write("sha512", checksumService.sha512(artifactFile).toString());
- write("sha256", checksumService.sha256(artifactFile).toString());
- write("sha1", checksumService.sha1(artifactFile).toString());
- write("md5", checksumService.md5(artifactFile).toString());
- }
-
- private void writeDependencies(UsageContext variant) throws IOException {
- if (variant.getDependencies().isEmpty()) {
+ private void writeDependencies(List<ModuleMetadata.Dependency> dependencies) throws IOException {
+ if (dependencies.isEmpty()) {
return;
}
writeArray("dependencies", () -> {
- Set<ExcludeRule> additionalExcludes = variant.getGlobalExcludes();
- VariantVersionMappingStrategyInternal variantVersionMappingStrategy = findVariantVersionMappingStrategy(variant);
- for (ModuleDependency moduleDependency : variant.getDependencies()) {
- if (moduleDependency.getArtifacts().isEmpty()) {
- writeDependency(moduleDependency, additionalExcludes, variantVersionMappingStrategy, null);
- } else {
- for (DependencyArtifact dependencyArtifact : moduleDependency.getArtifacts()) {
- writeDependency(moduleDependency, additionalExcludes, variantVersionMappingStrategy, dependencyArtifact);
+ for (ModuleMetadata.Dependency moduleDependency : dependencies) {
+ writeObject(() -> {
+ ModuleMetadata.DependencyCoordinates identifier = moduleDependency.coordinates;
+ write("group", identifier.group);
+ write("module", identifier.name);
+ writeVersionConstraint(identifier.version);
+ writeExcludes(moduleDependency.excludeRules);
+ writeNonEmptyAttributes(moduleDependency.attributes);
+ writeCapabilities("requestedCapabilities", moduleDependency.requestedCapabilities);
+ if (moduleDependency.endorseStrictVersions) {
+ write("endorseStrictVersions", true);
}
+ if (moduleDependency.reason != null) {
+ write("reason", moduleDependency.reason);
+ }
+ if (moduleDependency.artifactSelector != null) {
+ writeDependencyArtifact(moduleDependency.artifactSelector);
+ }
+ });
+ }
+ });
+ }
+
+ private void writeVersionConstraint(@Nullable ModuleMetadata.Version version) throws IOException {
+ if (version == null) {
+ return;
+ }
+ writeObject("version", () -> {
+ if (version.strictly != null) {
+ write("strictly", version.strictly);
+ }
+ if (version.requires != null) {
+ write("requires", version.requires);
+ }
+ if (version.preferred != null) {
+ write("prefers", version.preferred);
+ }
+ if (!version.rejectedVersions.isEmpty()) {
+ writeArray("rejects", version.rejectedVersions);
+ }
+ });
+ }
+
+ private void writeDependencyArtifact(ModuleMetadata.ArtifactSelector artifactSelector) throws IOException {
+ writeObject("thirdPartyCompatibility", () ->
+ writeObject("artifactSelector", () -> {
+ write("name", artifactSelector.name);
+ write("type", artifactSelector.type);
+ if (artifactSelector.extension != null) {
+ write("extension", artifactSelector.extension);
}
- }
- });
- }
-
- private void writeDependency(ModuleDependency dependency, Set<ExcludeRule> additionalExcludes, VariantVersionMappingStrategyInternal variantVersionMappingStrategy, DependencyArtifact dependencyArtifact) throws IOException {
- writeObject(() -> {
- if (dependency instanceof ProjectDependency) {
- writeProjectDependency((ProjectDependency) dependency, variantVersionMappingStrategy);
- } else {
- writeModuleDependency(dependency, variantVersionMappingStrategy);
- }
- writeExcludes(dependency, additionalExcludes);
- writeAttributes(dependency.getAttributes());
- writeCapabilities("requestedCapabilities", dependency.getRequestedCapabilities());
-
- boolean endorsing = dependency.isEndorsingStrictVersions();
- if (endorsing) {
- write("endorseStrictVersions", true);
- }
- String reason = dependency.getReason();
- if (isNotEmpty(reason)) {
- write("reason", reason);
- }
- if (dependencyArtifact != null) {
- writeDependencyArtifact(dependencyArtifact);
- }
- });
- }
-
- private void writeModuleDependency(ModuleDependency dependency, VariantVersionMappingStrategyInternal variantVersionMappingStrategy) throws IOException {
- String group = dependency.getGroup();
- String name = dependency.getName();
- String resolvedVersion = null;
- if (variantVersionMappingStrategy != null) {
- ModuleVersionIdentifier resolvedVersionId = variantVersionMappingStrategy.maybeResolveVersion(group, name);
- if (resolvedVersionId != null) {
- group = resolvedVersionId.getGroup();
- name = resolvedVersionId.getName();
- resolvedVersion = resolvedVersionId.getVersion();
- }
- }
- write("group", group);
- write("module", name);
- writeVersionConstraint(versionConstraintFor(dependency), resolvedVersion);
- }
-
- private void writeProjectDependency(
- ProjectDependency projectDependency,
- VariantVersionMappingStrategyInternal variantVersionMappingStrategy
- ) throws IOException {
- String resolvedVersion = null;
- ModuleVersionIdentifier identifier = projectDependencyResolver.resolve(ModuleVersionIdentifier.class, projectDependency);
- if (variantVersionMappingStrategy != null) {
- ModuleVersionIdentifier resolved = variantVersionMappingStrategy.maybeResolveVersion(
- identifier.getGroup(), identifier.getName()
- );
- if (resolved != null) {
- identifier = resolved;
- resolvedVersion = identifier.getVersion();
- }
- }
- write("group", identifier.getGroup());
- write("module", identifier.getName());
- writeVersionConstraint(
- DefaultImmutableVersionConstraint.of(identifier.getVersion()), resolvedVersion
+ if (artifactSelector.classifier != null) {
+ write("classifier", artifactSelector.classifier);
+ }
+ })
);
}
- private void writeVersionConstraint(
- ImmutableVersionConstraint versionConstraint,
- @Nullable String resolvedVersion
- ) throws IOException {
- checker.sawDependencyOrConstraint();
- if (resolvedVersion == null && isEmpty(versionConstraint)) {
- return;
- }
- checker.sawVersion();
-
- writeObject("version", () -> {
- boolean isStrict = !versionConstraint.getStrictVersion().isEmpty();
- String version;
- String preferred;
- if (resolvedVersion != null) {
- version = resolvedVersion;
- preferred = null;
- } else {
- version = isStrict
- ? versionConstraint.getStrictVersion()
- : !versionConstraint.getRequiredVersion().isEmpty()
- ? versionConstraint.getRequiredVersion()
- : null;
- preferred = !versionConstraint.getPreferredVersion().isEmpty()
- ? versionConstraint.getPreferredVersion()
- : null;
- }
- List<String> rejectedVersions = versionConstraint.getRejectedVersions();
- if (version != null) {
- if (isStrict) {
- write("strictly", version);
- }
- write("requires", version);
- }
- if (preferred != null) {
- write("prefers", preferred);
- }
- if (!rejectedVersions.isEmpty()) {
- writeArray("rejects", rejectedVersions);
- }
- });
- }
-
- private void writeDependencyArtifact(DependencyArtifact dependencyArtifact) throws IOException {
- writeObject("thirdPartyCompatibility", () -> {
- writeObject("artifactSelector", () -> {
- write("name", dependencyArtifact.getName());
- write("type", dependencyArtifact.getType());
- if (!isNullOrEmpty(dependencyArtifact.getExtension())) {
- write("extension", dependencyArtifact.getExtension());
- }
- if (!isNullOrEmpty(dependencyArtifact.getClassifier())) {
- write("classifier", dependencyArtifact.getClassifier());
- }
- });
- });
- }
-
- private void writeDependencyConstraints(UsageContext variant) throws IOException {
- if (variant.getDependencyConstraints().isEmpty()) {
+ private void writeDependencyConstraints(List<ModuleMetadata.DependencyConstraint> constraints) throws IOException {
+ if (constraints.isEmpty()) {
return;
}
writeArray("dependencyConstraints", () -> {
- VariantVersionMappingStrategyInternal mappingStrategy = findVariantVersionMappingStrategy(variant);
- for (DependencyConstraint dependencyConstraint : variant.getDependencyConstraints()) {
- writeDependencyConstraint(dependencyConstraint, mappingStrategy);
+ for (ModuleMetadata.DependencyConstraint constraint : constraints) {
+ writeObject(() -> {
+ write("group", constraint.group);
+ write("module", constraint.module);
+ writeVersionConstraint(constraint.version);
+ writeNonEmptyAttributes(constraint.attributes);
+ if (constraint.reason != null) {
+ write("reason", constraint.reason);
+ }
+ });
}
});
}
- private void writeDependencyConstraint(DependencyConstraint dependencyConstraint, VariantVersionMappingStrategyInternal variantVersionMappingStrategy) throws IOException {
- writeObject(() -> {
- String group;
- String module;
- String resolvedVersion = null;
- if (dependencyConstraint instanceof DefaultProjectDependencyConstraint) {
- DefaultProjectDependencyConstraint dependency = (DefaultProjectDependencyConstraint) dependencyConstraint;
- ProjectDependency projectDependency = dependency.getProjectDependency();
- ModuleVersionIdentifier identifier = projectDependencyResolver.resolve(ModuleVersionIdentifier.class, projectDependency);
- group = identifier.getGroup();
- module = identifier.getName();
- resolvedVersion = identifier.getVersion();
- } else {
- group = dependencyConstraint.getGroup();
- module = dependencyConstraint.getName();
- }
- ModuleVersionIdentifier resolvedVersionId = variantVersionMappingStrategy != null ? variantVersionMappingStrategy.maybeResolveVersion(group, module) : null;
- String effectiveGroup = resolvedVersionId != null ? resolvedVersionId.getGroup() : group;
- String effectiveModule = resolvedVersionId != null ? resolvedVersionId.getName() : module;
- String effectiveVersion = resolvedVersionId != null ? resolvedVersionId.getVersion() : resolvedVersion;
- write("group", effectiveGroup);
- write("module", effectiveModule);
- writeVersionConstraint(
- DefaultImmutableVersionConstraint.of(dependencyConstraint.getVersionConstraint()),
- effectiveVersion
- );
- writeAttributes(dependencyConstraint.getAttributes());
- String reason = dependencyConstraint.getReason();
- if (isNotEmpty(reason)) {
- write("reason", reason);
- }
- });
- }
-
- private void writeExcludes(ModuleDependency moduleDependency, Set<ExcludeRule> additionalExcludes) throws IOException {
- Set<ExcludeRule> excludeRules = excludedRulesFor(moduleDependency, additionalExcludes);
+ private void writeExcludes(Set<ExcludeRule> excludeRules) throws IOException {
if (excludeRules.isEmpty()) {
return;
}
@@ -501,73 +291,19 @@
});
}
- private ImmutableVersionConstraint versionConstraintFor(ModuleDependency dependency) {
- return dependency instanceof ExternalDependency
- ? DefaultImmutableVersionConstraint.of(((ExternalDependency) dependency).getVersionConstraint())
- : DefaultImmutableVersionConstraint.of(nullToEmpty(dependency.getVersion()));
+ private String md5(File file) {
+ return checksumService.md5(file).toString();
}
- private Set<ExcludeRule> excludedRulesFor(ModuleDependency moduleDependency, Set<ExcludeRule> additionalExcludes) {
- return moduleDependency.isTransitive()
- ? Sets.union(additionalExcludes, moduleDependency.getExcludeRules())
- : Collections.singleton(new DefaultExcludeRule(null, null));
+ private String sha1(File file) {
+ return checksumService.sha1(file).toString();
}
- private void checkVariant(UsageContext usageContext) {
- checker.registerVariant(
- usageContext.getName(),
- usageContext.getAttributes(),
- usageContext.getCapabilities()
- );
+ private String sha256(File file) {
+ return checksumService.sha256(file).toString();
}
- private ModuleVersionIdentifier coordinatesOf(SoftwareComponent childComponent) {
- if (childComponent instanceof ComponentWithCoordinates) {
- return ((ComponentWithCoordinates) childComponent).getCoordinates();
- }
- ComponentData componentData = componentCoordinates.get(childComponent);
- if (componentData != null) {
- return componentData.coordinates;
- }
- return null;
- }
-
- private VariantVersionMappingStrategyInternal findVariantVersionMappingStrategy(UsageContext variant) {
- VersionMappingStrategyInternal versionMappingStrategy = publication.getVersionMappingStrategy();
- if (versionMappingStrategy != null) {
- ImmutableAttributes attributes = ((AttributeContainerInternal) variant.getAttributes()).asImmutable();
- return versionMappingStrategy.findStrategyForVariant(attributes);
- }
- return null;
- }
-
- private boolean isEmpty(ImmutableVersionConstraint versionConstraint) {
- return DefaultImmutableVersionConstraint.of().equals(versionConstraint);
- }
-
- private String relativeUrlTo(
- @SuppressWarnings("unused") ModuleVersionIdentifier from,
- ModuleVersionIdentifier to
- ) {
- // TODO - do not assume Maven layout
- StringBuilder path = new StringBuilder();
- path.append("../../");
- path.append(to.getName());
- path.append("/");
- path.append(to.getVersion());
- path.append("/");
- path.append(to.getName());
- path.append("-");
- path.append(to.getVersion());
- path.append(".module");
- return path.toString();
- }
-
- private Map<String, Attribute<?>> sorted(AttributeContainer attributes) {
- Map<String, Attribute<?>> sortedAttributes = new TreeMap<>();
- for (Attribute<?> attribute : attributes.keySet()) {
- sortedAttributes.put(attribute.getName(), attribute);
- }
- return sortedAttributes;
+ private String sha512(File file) {
+ return checksumService.sha512(file).toString();
}
}
diff --git a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriterTest.groovy b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriterTest.groovy
index c2cdecb..3398f0e 100644
--- a/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriterTest.groovy
+++ b/subprojects/publish/src/test/groovy/org/gradle/api/publish/internal/metadata/GradleModuleMetadataWriterTest.groovy
@@ -642,7 +642,6 @@
getVersion() >> '1'
}
-
def v1 = Stub(UsageContext)
v1.name >> "v1"
v1.attributes >> attributes(usage: "compile")