Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.gradle.api.internaldsl.DefaultComponentMetadataProcessor Maven / Gradle / Ivy
/*
* Copyright 2018 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.artifacts.dsl;
import com.google.common.collect.Lists;
import org.gradle.api.Action;
import org.gradle.api.InvalidUserCodeException;
import org.gradle.api.Transformer;
import org.gradle.api.artifacts.ComponentMetadata;
import org.gradle.api.artifacts.ComponentMetadataContext;
import org.gradle.api.artifacts.ComponentMetadataDetails;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.VariantMetadata;
import org.gradle.api.artifacts.component.ComponentIdentifier;
import org.gradle.api.artifacts.ivy.IvyModuleDescriptor;
import org.gradle.api.attributes.AttributeContainer;
import org.gradle.api.internal.artifacts.ComponentMetadataProcessor;
import org.gradle.api.internal.artifacts.MetadataResolutionContext;
import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyModuleDescriptor;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.UserProvidedMetadata;
import org.gradle.api.internal.artifacts.repositories.resolver.ComponentMetadataDetailsAdapter;
import org.gradle.api.internal.artifacts.repositories.resolver.DependencyConstraintMetadataImpl;
import org.gradle.api.internal.artifacts.repositories.resolver.DirectDependencyMetadataImpl;
import org.gradle.api.internal.attributes.AttributeContainerInternal;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.internal.Actions;
import org.gradle.internal.action.ConfigurableRule;
import org.gradle.internal.action.DefaultConfigurableRules;
import org.gradle.internal.action.InstantiatingAction;
import org.gradle.internal.component.external.model.ModuleComponentResolveMetadata;
import org.gradle.internal.component.external.model.MutableModuleComponentResolveMetadata;
import org.gradle.internal.component.external.model.ivy.DefaultIvyModuleResolveMetadata;
import org.gradle.internal.component.external.model.ivy.IvyModuleResolveMetadata;
import org.gradle.internal.component.external.model.ivy.RealisedIvyModuleResolveMetadata;
import org.gradle.internal.component.external.model.maven.DefaultMavenModuleResolveMetadata;
import org.gradle.internal.component.external.model.maven.RealisedMavenModuleResolveMetadata;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.resolve.ModuleVersionResolveException;
import org.gradle.internal.resolve.caching.ComponentMetadataRuleExecutor;
import org.gradle.internal.rules.RuleAction;
import org.gradle.internal.rules.SpecRuleAction;
import org.gradle.internal.serialize.InputStreamBackedDecoder;
import org.gradle.internal.serialize.OutputStreamBackedEncoder;
import org.gradle.internal.serialize.Serializer;
import org.gradle.internal.typeconversion.NotationParser;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.gradle.api.internal.artifacts.repositories.resolver.VirtualComponentHelper.makeVirtual;
public class DefaultComponentMetadataProcessor implements ComponentMetadataProcessor {
private final static boolean FORCE_REALIZE = Boolean.getBoolean("org.gradle.integtest.force.realize.metadata");
private static final Transformer DETAILS_TO_RESULT = new Transformer() {
@Override
public ModuleComponentResolveMetadata transform(WrappingComponentMetadataContext componentMetadataContext) {
ModuleComponentResolveMetadata metadata = componentMetadataContext.getMutableMetadata().asImmutable();
return realizeMetadata(metadata);
}
};
private ModuleComponentResolveMetadata maybeForceRealisation(ModuleComponentResolveMetadata metadata) {
if (FORCE_REALIZE) {
metadata = realizeMetadata(metadata);
metadata = forceSerialization(metadata);
}
return metadata;
}
private static ModuleComponentResolveMetadata realizeMetadata(ModuleComponentResolveMetadata metadata) {
if (metadata instanceof DefaultIvyModuleResolveMetadata) {
metadata = RealisedIvyModuleResolveMetadata.transform((DefaultIvyModuleResolveMetadata) metadata);
} else if (metadata instanceof DefaultMavenModuleResolveMetadata) {
metadata = RealisedMavenModuleResolveMetadata.transform((DefaultMavenModuleResolveMetadata) metadata);
} else {
throw new IllegalStateException("Invalid type received: " + metadata.getClass());
}
return metadata;
}
private ModuleComponentResolveMetadata forceSerialization(ModuleComponentResolveMetadata metadata) {
Serializer serializer = ruleExecutor.getComponentMetadataContextSerializer();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes;
try {
serializer.write(new OutputStreamBackedEncoder(byteArrayOutputStream), metadata);
bytes = byteArrayOutputStream.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
try {
ModuleComponentResolveMetadata forceRead = serializer.read(new InputStreamBackedDecoder(new ByteArrayInputStream(bytes)));
// TODO: CC cannot enable this assertion because moduleSource is not serialized, so doesn't appear in the deserialized form
//assert metadata.equals(forceRead);
metadata = forceRead;
} catch (Exception e) {
throw new RuntimeException(e);
}
return metadata;
}
private final Instantiator instantiator;
private final NotationParser dependencyMetadataNotationParser;
private final NotationParser dependencyConstraintMetadataNotationParser;
private final NotationParser componentIdentifierNotationParser;
private final ImmutableAttributesFactory attributesFactory;
private final ComponentMetadataRuleExecutor ruleExecutor;
private final MetadataResolutionContext metadataResolutionContext;
private final ComponentMetadataRuleContainer metadataRuleContainer;
public DefaultComponentMetadataProcessor(ComponentMetadataRuleContainer metadataRuleContainer,
Instantiator instantiator,
NotationParser dependencyMetadataNotationParser,
NotationParser dependencyConstraintMetadataNotationParser,
NotationParser componentIdentifierNotationParser,
ImmutableAttributesFactory attributesFactory,
ComponentMetadataRuleExecutor ruleExecutor,
MetadataResolutionContext resolutionContext) {
this.metadataRuleContainer = metadataRuleContainer;
this.instantiator = instantiator;
this.dependencyMetadataNotationParser = dependencyMetadataNotationParser;
this.dependencyConstraintMetadataNotationParser = dependencyConstraintMetadataNotationParser;
this.componentIdentifierNotationParser = componentIdentifierNotationParser;
this.attributesFactory = attributesFactory;
this.ruleExecutor = ruleExecutor;
this.metadataResolutionContext = resolutionContext;
}
@Override
public ModuleComponentResolveMetadata processMetadata(ModuleComponentResolveMetadata metadata) {
metadata.getVariantMetadataRules().setVariantDerivationStrategy(metadataRuleContainer.getVariantDerivationStrategy());
ModuleComponentResolveMetadata updatedMetadata;
if (metadataRuleContainer.isEmpty()) {
updatedMetadata = maybeForceRealisation(metadata);
} else if (metadataRuleContainer.isClassBasedRulesOnly()) {
Action action = collectRulesAndCreateAction(metadataRuleContainer.getOnlyClassRules(), metadata.getModuleVersionId(), metadataResolutionContext.getInjectingInstantiator());
if (action instanceof InstantiatingAction) {
InstantiatingAction ia = (InstantiatingAction) action;
if (ia.getRules().isCacheable()) {
updatedMetadata = processClassRuleWithCaching(ia, metadata, metadataResolutionContext);
} else {
MutableModuleComponentResolveMetadata mutableMetadata = metadata.asMutable();
processClassRule(action, metadata, createDetails(mutableMetadata));
updatedMetadata = maybeForceRealisation(mutableMetadata.asImmutable());
}
} else {
updatedMetadata = maybeForceRealisation(metadata);
}
} else {
MutableModuleComponentResolveMetadata mutableMetadata = metadata.asMutable();
ComponentMetadataDetails details = createDetails(mutableMetadata);
processAllRules(metadata, details, metadata.getModuleVersionId());
updatedMetadata = maybeForceRealisation(mutableMetadata.asImmutable());
}
if (!updatedMetadata.getStatusScheme().contains(updatedMetadata.getStatus())) {
throw new ModuleVersionResolveException(updatedMetadata.getModuleVersionId(), () -> String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().getDisplayName(), updatedMetadata.getStatusScheme()));
}
return updatedMetadata;
}
protected ComponentMetadataDetails createDetails(MutableModuleComponentResolveMetadata mutableMetadata) {
return instantiator.newInstance(ComponentMetadataDetailsAdapter.class, mutableMetadata, instantiator, dependencyMetadataNotationParser, dependencyConstraintMetadataNotationParser, componentIdentifierNotationParser);
}
@Override
public ComponentMetadata processMetadata(ComponentMetadata metadata) {
ComponentMetadata updatedMetadata;
if (metadataRuleContainer.isEmpty()) {
updatedMetadata = metadata;
} else {
ShallowComponentMetadataAdapter details = new ShallowComponentMetadataAdapter(componentIdentifierNotationParser, metadata, attributesFactory);
processAllRules(null, details, metadata.getId());
updatedMetadata = details.asImmutable();
}
if (!updatedMetadata.getStatusScheme().contains(updatedMetadata.getStatus())) {
throw new ModuleVersionResolveException(updatedMetadata.getId(), () -> String.format("Unexpected status '%s' specified for %s. Expected one of: %s", updatedMetadata.getStatus(), updatedMetadata.getId().toString(), updatedMetadata.getStatusScheme()));
}
return updatedMetadata;
}
@Override
public int getRulesHash() {
return metadataRuleContainer.getRulesHash();
}
private void processAllRules(ModuleComponentResolveMetadata metadata, ComponentMetadataDetails details, ModuleVersionIdentifier id) {
for (MetadataRuleWrapper wrapper : metadataRuleContainer) {
if (wrapper.isClassBased()) {
Collection rules = wrapper.getClassRules();
Action action = collectRulesAndCreateAction(rules, id, instantiator);
processClassRule(action, metadata, details);
} else {
processRule(wrapper.getRule(), metadata, details);
}
}
}
private void processClassRule(Action action, final ModuleComponentResolveMetadata metadata, final ComponentMetadataDetails details) {
DefaultComponentMetadataContext componentMetadataContext = new DefaultComponentMetadataContext(details, metadata);
try {
action.execute(componentMetadataContext);
} catch (InvalidUserCodeException e) {
throw e;
} catch (Exception e) {
throw new InvalidUserCodeException(String.format("There was an error while evaluating a component metadata rule for %s.", details.getId()), e);
}
}
private ModuleComponentResolveMetadata processClassRuleWithCaching(InstantiatingAction action, final ModuleComponentResolveMetadata metadata, MetadataResolutionContext metadataResolutionContext) {
try {
return ruleExecutor.execute(metadata, action, DETAILS_TO_RESULT,
new Transformer() {
@Override
public WrappingComponentMetadataContext transform(ModuleComponentResolveMetadata moduleVersionIdentifier) {
return new WrappingComponentMetadataContext(metadata, instantiator, dependencyMetadataNotationParser, dependencyConstraintMetadataNotationParser, componentIdentifierNotationParser);
}
}, metadataResolutionContext.getCachePolicy());
} catch (InvalidUserCodeException e) {
throw e;
} catch (Exception e) {
throw new InvalidUserCodeException(String.format("There was an error while evaluating a component metadata rule for %s.", metadata.getModuleVersionId()), e);
}
}
private Action collectRulesAndCreateAction(Collection rules, ModuleVersionIdentifier id, Instantiator instantiator) {
if (rules.isEmpty()) {
return Actions.doNothing();
}
ArrayList> collectedRules = new ArrayList>();
for (SpecConfigurableRule classBasedRule : rules) {
if (classBasedRule.getSpec().isSatisfiedBy(id)) {
collectedRules.add(classBasedRule.getConfigurableRule());
}
}
return new InstantiatingAction(new DefaultConfigurableRules(collectedRules), instantiator, new ExceptionHandler());
}
private void processRule(SpecRuleAction specRuleAction, ModuleComponentResolveMetadata metadata, final ComponentMetadataDetails details) {
if (!specRuleAction.getSpec().isSatisfiedBy(details)) {
return;
}
final List inputs = Lists.newArrayList();
final RuleAction action = specRuleAction.getAction();
for (Class inputType : action.getInputTypes()) {
if (inputType == IvyModuleDescriptor.class) {
// Ignore the rule if it expects Ivy metadata and this isn't an Ivy module
if (!(metadata instanceof IvyModuleResolveMetadata)) {
return;
}
IvyModuleResolveMetadata ivyMetadata = (IvyModuleResolveMetadata) metadata;
inputs.add(new DefaultIvyModuleDescriptor(ivyMetadata.getExtraAttributes(), ivyMetadata.getBranch(), ivyMetadata.getStatus()));
continue;
}
// We've already validated the inputs: should never get here.
throw new IllegalStateException();
}
try {
synchronized (this) {
action.execute(details, inputs);
}
} catch (InvalidUserCodeException e) {
throw e;
} catch (Exception e) {
throw new InvalidUserCodeException(String.format("There was an error while evaluating a component metadata rule for %s.", details.getId()), e);
}
}
private static class ExceptionHandler implements InstantiatingAction.ExceptionHandler {
@Override
public void handleException(ComponentMetadataContext context, Throwable throwable) {
throw new InvalidUserCodeException(String.format("There was an error while evaluating a component metadata rule for %s.", context.getDetails().getId()), throwable);
}
}
static class ShallowComponentMetadataAdapter implements ComponentMetadataDetails {
private final NotationParser componentIdentifierNotationParser;
private final ModuleVersionIdentifier id;
private boolean changing;
private List statusScheme;
private AttributeContainerInternal attributes;
private final List owners;
public ShallowComponentMetadataAdapter(NotationParser componentIdentifierNotationParser, ComponentMetadata source, ImmutableAttributesFactory attributesFactory) {
this.componentIdentifierNotationParser = componentIdentifierNotationParser;
id = source.getId();
changing = source.isChanging();
statusScheme = source.getStatusScheme();
attributes = attributesFactory.mutable((AttributeContainerInternal) source.getAttributes());
owners = Lists.newArrayListWithExpectedSize(1);
}
@Override
public void setChanging(boolean changing) {
this.changing = changing;
}
@Override
public void setStatus(String status) {
this.attributes.attribute(ProjectInternal.STATUS_ATTRIBUTE, status);
}
@Override
public void setStatusScheme(List statusScheme) {
this.statusScheme = statusScheme;
}
@Override
public void withVariant(String name, Action action) {
}
@Override
public void allVariants(Action action) {
}
@Override
public void belongsTo(Object notation) {
belongsTo(notation, true);
}
@Override
public void belongsTo(Object notation, boolean virtual) {
ComponentIdentifier id = componentIdentifierNotationParser.parseNotation(notation);
if (virtual) {
id = makeVirtual(id);
}
owners.add(id);
}
@Override
public ModuleVersionIdentifier getId() {
return id;
}
@Override
public boolean isChanging() {
return changing;
}
@Override
public String getStatus() {
return attributes.getAttribute(ProjectInternal.STATUS_ATTRIBUTE);
}
@Override
public List getStatusScheme() {
return statusScheme;
}
@Override
public ComponentMetadataDetails attributes(Action action) {
action.execute(attributes);
return this;
}
@Override
public AttributeContainer getAttributes() {
return attributes;
}
public ComponentMetadata asImmutable() {
return new UserProvidedMetadata(id, statusScheme, attributes.asImmutable());
}
}
}