blob: 6565bd1f1992adb1baff9845be30e8e82d8b9bbe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* https://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.apache.ivy.ant;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.ivy.Ivy;
import org.apache.ivy.core.cache.ResolutionCacheManager;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.util.Message;
import org.apache.ivy.util.filter.Filter;
import org.apache.ivy.util.filter.FilterHelper;
import org.apache.tools.ant.BuildException;
import static org.apache.ivy.util.StringUtils.joinArray;
import static org.apache.ivy.util.StringUtils.splitToArray;
/**
* Base class for tasks needing to be performed after a resolve.
*/
public abstract class IvyPostResolveTask extends IvyTask {
private String conf;
private boolean haltOnFailure = true;
private boolean transitive = true;
private boolean inline = false;
private String organisation;
private String branch = null;
private String module;
private String revision = "latest.integration";
private String resolveId;
private String type;
private File file;
private Filter<Artifact> artifactFilter = null;
private boolean useOrigin = false;
private Boolean keep = null;
private boolean refresh = false;
private String resolveMode = null;
private String log = ResolveOptions.LOG_DEFAULT;
private boolean changing = false;
private IvyResolve resolve = new IvyResolve();
public boolean isUseOrigin() {
return useOrigin;
}
public void setUseOrigin(boolean useOrigin) {
this.useOrigin = useOrigin;
}
public String getLog() {
return log;
}
public void setLog(String log) {
this.log = log;
}
public IvyDependency createDependency() {
return resolve.createDependency();
}
public IvyExclude createExclude() {
return resolve.createExclude();
}
public IvyConflict createConflict() {
return resolve.createConflict();
}
protected void prepareAndCheck() {
Ivy ivy = getIvyInstance();
IvySettings settings = ivy.getSettings();
boolean orgAndModSetManually = organisation != null && module != null;
organisation = getProperty(organisation, settings, "ivy.organisation");
module = getProperty(module, settings, "ivy.module");
if (file == null) {
String fileName = getProperty(settings, "ivy.resolved.file", resolveId);
if (fileName != null) {
file = getProject().resolveFile(fileName);
}
}
if (isInline()) {
if (conf == null) {
conf = "*";
}
if (organisation == null) {
throw new BuildException(
"no organisation provided for ivy cache task in inline mode: "
+ "It can either be set explicitly via the attribute 'organisation' "
+ "or via 'ivy.organisation' property");
}
if (module == null) {
throw new BuildException(
"no module name provided for ivy cache task in inline mode: "
+ "It can either be set explicitly via the attribute 'module' "
+ "or via 'ivy.module' property");
}
String[] toResolve = getConfsToResolve(getOrganisation(), getModule() + "-caller",
conf, true);
// When we make an inline resolution, we can not resolve private confs.
for (int i = 0; i < toResolve.length; i++) {
if ("*".equals(toResolve[i])) {
toResolve[i] = "*(public)";
}
}
if (toResolve.length > 0) {
Message.verbose(String.format("using inline mode to resolve %s %s %s (%s)",
getOrganisation(), getModule(), getRevision(), joinArray(toResolve, ", ")));
IvyResolve resolve = setupResolve(isHaltonfailure(), isUseOrigin());
resolve.setOrganisation(getOrganisation());
resolve.setModule(getModule());
resolve.setBranch(getBranch());
resolve.setRevision(getRevision());
resolve.setInline(true);
resolve.setChanging(isChanging());
resolve.setConf(conf);
resolve.setResolveId(resolveId);
resolve.setTransitive(isTransitive());
resolve.execute();
} else {
Message.verbose(String.format("inline resolve already done for %s %s %s (%s)",
getOrganisation(), getModule(), getRevision(), conf));
}
if ("*".equals(conf)) {
conf = joinArray(
getResolvedConfigurations(getOrganisation(), getModule() + "-caller", true),
", ");
}
} else {
Message.debug("using standard ensure resolved");
// if the organization and module has been manually specified, we'll reuse the resolved
// data from another build (there is no way to know which configurations were resolved
// there (TODO: maybe we can check which reports exist and extract the configurations
// from these report names?)
if (!orgAndModSetManually) {
ensureResolved(settings);
}
conf = getProperty(conf, settings, "ivy.resolved.configurations");
if ("*".equals(conf)) {
conf = getProperty(settings, "ivy.resolved.configurations");
if (conf == null) {
throw new BuildException("bad conf provided for ivy cache task: "
+ "'*' can only be used with a prior call to <resolve/>");
}
}
}
organisation = getProperty(organisation, settings, "ivy.organisation");
module = getProperty(module, settings, "ivy.module");
if (organisation == null) {
throw new BuildException("no organisation provided for ivy cache task: "
+ "It can either be set explicitly via the attribute 'organisation' "
+ "or via 'ivy.organisation' property or a prior call to <resolve/>");
}
if (module == null) {
throw new BuildException("no module name provided for ivy cache task: "
+ "It can either be set explicitly via the attribute 'module' "
+ "or via 'ivy.module' property or a prior call to <resolve/>");
}
if (conf == null) {
throw new BuildException("no conf provided for ivy cache task: "
+ "It can either be set explicitly via the attribute 'conf' or "
+ "via 'ivy.resolved.configurations' property or a prior call to <resolve/>");
}
artifactFilter = FilterHelper.getArtifactTypeFilter(type);
}
protected void ensureResolved(IvySettings settings) {
String requestedConfigs = getProperty(getConf(), settings, "ivy.resolved.configurations");
String[] confs = (getResolveId() == null)
? getConfsToResolve(getOrganisation(), getModule(), requestedConfigs, false)
: getConfsToResolve(getResolveId(), requestedConfigs);
if (confs.length > 0) {
IvyResolve resolve = setupResolve(isHaltonfailure(), isUseOrigin());
resolve.setFile(getFile());
resolve.setTransitive(isTransitive());
resolve.setConf(joinArray(confs, ", "));
resolve.setResolveId(getResolveId());
resolve.execute();
}
}
protected String[] getConfsToResolve(String org, String module, String conf, boolean strict) {
ModuleDescriptor reference = getResolvedDescriptor(org, module, strict);
String[] rconfs = getResolvedConfigurations(org, module, strict);
return getConfsToResolve(reference, conf, rconfs);
}
protected String[] getConfsToResolve(String resolveId, String conf) {
ModuleDescriptor reference = getResolvedDescriptor(resolveId, false);
if (reference == null) {
// assume the module has been resolved outside this build, resolve the required
// configurations again
// TODO: find a way to discover which confs were resolved by that previous resolve
if (conf == null) {
return new String[] {"*"};
}
return splitToArray(conf);
}
String[] rconfs = getProject().getReference("ivy.resolved.configurations.ref." + resolveId);
return getConfsToResolve(reference, conf, rconfs);
}
private String[] getConfsToResolve(ModuleDescriptor reference, String conf, String[] rconfs) {
Message.debug("calculating configurations to resolve");
if (reference == null) {
Message.debug("module not yet resolved, all confs still need to be resolved");
if (conf == null) {
return new String[] {"*"};
}
return splitToArray(conf);
}
if (conf == null) {
Message.debug("module already resolved, no configuration to resolve");
return new String[0];
}
String[] confs;
if ("*".equals(conf)) {
confs = reference.getConfigurationsNames();
} else {
confs = splitToArray(conf);
}
Set<String> rconfsSet = new HashSet<>();
// for each resolved configuration, check if the report still exists
ResolutionCacheManager cache = getSettings().getResolutionCacheManager();
for (String resolvedConf : rconfs) {
String resolveId = getResolveId();
if (resolveId == null) {
resolveId = ResolveOptions.getDefaultResolveId(reference);
}
File report = cache.getConfigurationResolveReportInCache(resolveId, resolvedConf);
// if the report does not exist any longer, we have to recreate it...
if (report.exists()) {
rconfsSet.add(resolvedConf);
}
}
Set<String> confsSet = new HashSet<>(Arrays.asList(confs));
Message.debug("resolved configurations: " + rconfsSet);
Message.debug("asked configurations: " + confsSet);
confsSet.removeAll(rconfsSet);
Message.debug("to resolve configurations: " + confsSet);
return confsSet.toArray(new String[confsSet.size()]);
}
protected IvyResolve setupResolve(boolean haltOnFailure, boolean useOrigin) {
Message.verbose("no resolved descriptor found: launching default resolve");
resolve.setTaskName(getTaskName());
resolve.setProject(getProject());
resolve.setHaltonfailure(haltOnFailure);
resolve.setUseOrigin(useOrigin);
resolve.setValidate(doValidate(getSettings()));
resolve.setKeep(isKeep());
resolve.setRefresh(isRefresh());
resolve.setLog(getLog());
resolve.setSettingsRef(getSettingsRef());
resolve.setResolveMode(getResolveMode());
return resolve;
}
protected ModuleRevisionId getResolvedMrid() {
return new ModuleRevisionId(getResolvedModuleId(),
(getRevision() == null) ? Ivy.getWorkingRevision() : getRevision());
}
protected ModuleId getResolvedModuleId() {
return isInline() ? new ModuleId(getOrganisation(), getModule() + "-caller")
: new ModuleId(getOrganisation(), getModule());
}
protected ResolveReport getResolvedReport() {
return getResolvedReport(getOrganisation(), isInline() ? getModule() + "-caller"
: getModule(), resolveId);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getConf() {
return conf;
}
public void setConf(String conf) {
this.conf = conf;
}
public String getModule() {
return module;
}
public void setModule(String module) {
this.module = module;
}
public String getOrganisation() {
return organisation;
}
public void setOrganisation(String organisation) {
this.organisation = organisation;
}
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
public boolean isHaltonfailure() {
return haltOnFailure;
}
public void setHaltonfailure(boolean haltOnFailure) {
this.haltOnFailure = haltOnFailure;
}
public void setCache(File cache) {
cacheAttributeNotSupported();
}
public String getRevision() {
return revision;
}
public void setRevision(String rev) {
revision = rev;
}
public Filter<Artifact> getArtifactFilter() {
return artifactFilter;
}
public boolean isTransitive() {
return transitive;
}
public void setTransitive(boolean transitive) {
this.transitive = transitive;
}
public boolean isInline() {
return inline;
}
public void setInline(boolean inline) {
this.inline = inline;
}
public void setResolveId(String resolveId) {
this.resolveId = resolveId;
}
public String getResolveId() {
return resolveId;
}
public void setFile(File file) {
this.file = file;
}
public File getFile() {
return file;
}
public void setKeep(boolean keep) {
this.keep = keep;
}
public boolean isKeep() {
return this.keep == null ? !isInline() : this.keep;
}
public void setChanging(boolean changing) {
this.changing = changing;
}
public boolean isChanging() {
return this.changing;
}
public void setRefresh(boolean refresh) {
this.refresh = refresh;
}
public boolean isRefresh() {
return refresh;
}
public String getResolveMode() {
return resolveMode;
}
public void setResolveMode(String resolveMode) {
this.resolveMode = resolveMode;
}
}