mirror of https://github.com/apache/ant-ivy
530 lines
18 KiB
Java
530 lines
18 KiB
Java
/*
|
|
* 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.net.MalformedURLException;
|
|
import java.text.ParseException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
|
|
import org.apache.ivy.Ivy;
|
|
import org.apache.ivy.core.LogOptions;
|
|
import org.apache.ivy.core.module.descriptor.DefaultExcludeRule;
|
|
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
|
|
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
|
|
import org.apache.ivy.core.module.descriptor.ExtendsDescriptor;
|
|
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
|
|
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.resolve.ResolveProcessException;
|
|
import org.apache.ivy.core.settings.IvySettings;
|
|
import org.apache.ivy.util.Message;
|
|
import org.apache.ivy.util.filter.FilterHelper;
|
|
import org.apache.tools.ant.BuildException;
|
|
import org.apache.tools.ant.Project;
|
|
|
|
import static org.apache.ivy.util.StringUtils.splitToArray;
|
|
|
|
/**
|
|
* This task allow to call the Ivy dependency resolution from ant.
|
|
*/
|
|
public class IvyResolve extends IvyTask {
|
|
private File file = null;
|
|
|
|
private String conf = null;
|
|
|
|
private String organisation = null;
|
|
|
|
private String module = null;
|
|
|
|
private String branch = null;
|
|
|
|
private String revision = null;
|
|
|
|
private String pubdate = null;
|
|
|
|
private boolean inline = false;
|
|
|
|
private boolean haltOnFailure = true;
|
|
|
|
private boolean showProgress = true;
|
|
|
|
private boolean useCacheOnly = false;
|
|
|
|
private String type = null;
|
|
|
|
private boolean transitive = true;
|
|
|
|
private boolean refresh = false;
|
|
|
|
private boolean changing = false;
|
|
|
|
private Boolean keep = null;
|
|
|
|
private String failureProperty = null;
|
|
|
|
private boolean useOrigin = false;
|
|
|
|
private String resolveMode = null;
|
|
|
|
private String resolveId = null;
|
|
|
|
private String log = ResolveOptions.LOG_DEFAULT;
|
|
|
|
private boolean checkIfChanged = true; // for backward compatibility
|
|
|
|
private List<IvyDependency> dependencies = new ArrayList<>();
|
|
|
|
private List<IvyExclude> excludes = new ArrayList<>();
|
|
|
|
private List<IvyOverride> overrides = new ArrayList<>();
|
|
|
|
private List<IvyConflict> conflicts = new ArrayList<>();
|
|
|
|
public boolean isUseOrigin() {
|
|
return useOrigin;
|
|
}
|
|
|
|
public void setUseOrigin(boolean useOrigin) {
|
|
this.useOrigin = useOrigin;
|
|
}
|
|
|
|
public String getDate() {
|
|
return pubdate;
|
|
}
|
|
|
|
public void setDate(String pubdate) {
|
|
this.pubdate = pubdate;
|
|
}
|
|
|
|
public String getRevision() {
|
|
return revision;
|
|
}
|
|
|
|
public void setRevision(String revision) {
|
|
this.revision = revision;
|
|
}
|
|
|
|
public String getBranch() {
|
|
return branch;
|
|
}
|
|
|
|
public void setBranch(String branch) {
|
|
this.branch = branch;
|
|
}
|
|
|
|
public void setCache(File cache) {
|
|
cacheAttributeNotSupported();
|
|
}
|
|
|
|
public String getConf() {
|
|
return conf;
|
|
}
|
|
|
|
public void setConf(String conf) {
|
|
this.conf = conf;
|
|
}
|
|
|
|
public File getFile() {
|
|
return file;
|
|
}
|
|
|
|
public void setFile(File file) {
|
|
this.file = file;
|
|
}
|
|
|
|
public boolean isHaltonfailure() {
|
|
return haltOnFailure;
|
|
}
|
|
|
|
public void setHaltonfailure(boolean haltOnFailure) {
|
|
this.haltOnFailure = haltOnFailure;
|
|
}
|
|
|
|
public void setShowprogress(boolean show) {
|
|
this.showProgress = show;
|
|
}
|
|
|
|
public boolean isUseCacheOnly() {
|
|
return useCacheOnly;
|
|
}
|
|
|
|
public void setUseCacheOnly(boolean useCacheOnly) {
|
|
this.useCacheOnly = useCacheOnly;
|
|
}
|
|
|
|
public String getType() {
|
|
return type;
|
|
}
|
|
|
|
public void setType(String type) {
|
|
this.type = type;
|
|
}
|
|
|
|
public boolean isRefresh() {
|
|
return refresh;
|
|
}
|
|
|
|
public void setRefresh(boolean refresh) {
|
|
this.refresh = refresh;
|
|
}
|
|
|
|
public String getLog() {
|
|
return log;
|
|
}
|
|
|
|
public void setLog(String log) {
|
|
this.log = log;
|
|
}
|
|
|
|
/**
|
|
* @param failureProperty String
|
|
* @deprecated Use {@link #setFailureProperty(String)} instead
|
|
*/
|
|
@Deprecated
|
|
public void setFailurePropery(String failureProperty) {
|
|
log("The 'failurepropery' attribute is deprecated. "
|
|
+ "Please use the 'failureproperty' attribute instead", Project.MSG_WARN);
|
|
setFailureProperty(failureProperty);
|
|
}
|
|
|
|
public void setFailureProperty(String failureProperty) {
|
|
this.failureProperty = failureProperty;
|
|
}
|
|
|
|
public String getFailureProperty() {
|
|
return failureProperty;
|
|
}
|
|
|
|
public IvyDependency createDependency() {
|
|
IvyDependency dep = new IvyDependency();
|
|
dependencies.add(dep);
|
|
return dep;
|
|
}
|
|
|
|
public IvyExclude createExclude() {
|
|
IvyExclude ex = new IvyExclude();
|
|
excludes.add(ex);
|
|
return ex;
|
|
}
|
|
|
|
public IvyOverride createOverride() {
|
|
IvyOverride o = new IvyOverride();
|
|
overrides.add(o);
|
|
return o;
|
|
}
|
|
|
|
public IvyConflict createConflict() {
|
|
IvyConflict c = new IvyConflict();
|
|
conflicts.add(c);
|
|
return c;
|
|
}
|
|
|
|
@Override
|
|
protected void prepareTask() {
|
|
super.prepareTask();
|
|
Message.setShowProgress(showProgress);
|
|
}
|
|
|
|
@Override
|
|
public void doExecute() throws BuildException {
|
|
Ivy ivy = getIvyInstance();
|
|
IvySettings settings = ivy.getSettings();
|
|
try {
|
|
conf = getProperty(conf, settings, "ivy.configurations");
|
|
type = getProperty(type, settings, "ivy.resolve.default.type.filter");
|
|
String[] confs = splitToArray(conf);
|
|
|
|
boolean childs = !dependencies.isEmpty() || !excludes.isEmpty() || !overrides.isEmpty()
|
|
|| !conflicts.isEmpty();
|
|
|
|
ResolveReport report;
|
|
if (childs) {
|
|
if (isInline()) {
|
|
throw new BuildException("the inline mode is incompatible with child elements");
|
|
}
|
|
if (organisation != null) {
|
|
throw new BuildException("'organisation' is not allowed with child elements");
|
|
}
|
|
if (module != null) {
|
|
throw new BuildException("'module' is not allowed with child elements");
|
|
}
|
|
if (file != null) {
|
|
throw new BuildException("'file' not allowed with child elements");
|
|
}
|
|
if (!getAllowedLogOptions().contains(log)) {
|
|
throw new BuildException("invalid option for 'log': " + log
|
|
+ ". Available options are " + getAllowedLogOptions());
|
|
}
|
|
|
|
ModuleRevisionId mrid = ModuleRevisionId.newInstance("", "",
|
|
Ivy.getWorkingRevision());
|
|
DefaultModuleDescriptor md = DefaultModuleDescriptor.newBasicInstance(mrid, null);
|
|
|
|
for (IvyDependency dep : dependencies) {
|
|
DependencyDescriptor dd = dep.asDependencyDescriptor(md, "default", settings);
|
|
md.addDependency(dd);
|
|
}
|
|
|
|
for (IvyExclude exclude : excludes) {
|
|
DefaultExcludeRule rule = exclude.asRule(settings);
|
|
rule.addConfiguration("default");
|
|
md.addExcludeRule(rule);
|
|
}
|
|
|
|
for (IvyOverride override : overrides) {
|
|
override.addOverride(md, settings);
|
|
}
|
|
|
|
for (IvyConflict conflict : conflicts) {
|
|
conflict.addConflict(md, settings);
|
|
}
|
|
|
|
report = ivy
|
|
.resolve(md, getResolveOptions(ivy, new String[] {"default"}, settings));
|
|
} else if (isInline()) {
|
|
if (organisation == null) {
|
|
throw new BuildException("'organisation' is required when using inline mode");
|
|
}
|
|
if (module == null) {
|
|
throw new BuildException("'module' is required when using inline mode");
|
|
}
|
|
if (file != null) {
|
|
throw new BuildException("'file' not allowed when using inline mode");
|
|
}
|
|
if (!getAllowedLogOptions().contains(log)) {
|
|
throw new BuildException("invalid option for 'log': " + log
|
|
+ ". Available options are " + getAllowedLogOptions());
|
|
}
|
|
for (int i = 0; i < confs.length; i++) {
|
|
if ("*".equals(confs[i])) {
|
|
confs[i] = "*(public)";
|
|
}
|
|
}
|
|
if (revision == null) {
|
|
revision = "latest.integration";
|
|
}
|
|
report = ivy.resolve(
|
|
ModuleRevisionId.newInstance(organisation, module, branch, revision),
|
|
getResolveOptions(ivy, confs, settings), changing);
|
|
|
|
} else {
|
|
if (organisation != null) {
|
|
throw new BuildException(
|
|
"'organisation' not allowed when not using 'org' attribute");
|
|
}
|
|
if (module != null) {
|
|
throw new BuildException("'module' not allowed when not using 'org' attribute");
|
|
}
|
|
if (file == null) {
|
|
file = getProject().resolveFile(getProperty(settings, "ivy.dep.file"));
|
|
}
|
|
report = ivy.resolve(file.toURI().toURL(), getResolveOptions(ivy, confs, settings));
|
|
}
|
|
if (report.hasError()) {
|
|
if (failureProperty != null) {
|
|
getProject().setProperty(failureProperty, "true");
|
|
}
|
|
if (isHaltonfailure()) {
|
|
throw new BuildException("resolve failed - see output for details");
|
|
}
|
|
}
|
|
setResolved(report, resolveId, isKeep());
|
|
confs = report.getConfigurations();
|
|
|
|
if (isKeep()) {
|
|
ModuleDescriptor md = report.getModuleDescriptor();
|
|
// put resolved infos in ant properties and ivy variables
|
|
// putting them in ivy variables is important to be able to change from one resolve
|
|
// call to the other
|
|
String mdOrg = md.getModuleRevisionId().getOrganisation();
|
|
String mdName = md.getModuleRevisionId().getName();
|
|
String mdRev = md.getResolvedModuleRevisionId().getRevision();
|
|
getProject().setProperty("ivy.organisation", mdOrg);
|
|
settings.setVariable("ivy.organisation", mdOrg);
|
|
getProject().setProperty("ivy.module", mdName);
|
|
settings.setVariable("ivy.module", mdName);
|
|
getProject().setProperty("ivy.revision", mdRev);
|
|
settings.setVariable("ivy.revision", mdRev);
|
|
List<ExtendsDescriptor> parents = Arrays.asList(md.getInheritedDescriptors());
|
|
for (ExtendsDescriptor parent : parents) {
|
|
int i = parents.indexOf(parent);
|
|
String parentOrg = parent.getResolvedParentRevisionId().getOrganisation();
|
|
String parentModule = parent.getResolvedParentRevisionId().getName();
|
|
String parentRevision = parent.getResolvedParentRevisionId().getRevision();
|
|
String parentBranch = parent.getResolvedParentRevisionId().getBranch();
|
|
getProject().setProperty("ivy.parent[" + i + "].organisation", parentOrg);
|
|
settings.setVariable("ivy.parent[" + i + "].organisation", parentOrg);
|
|
getProject().setProperty("ivy.parent[" + i + "].module", parentModule);
|
|
settings.setVariable("ivy.parent[" + i + "].module", parentModule);
|
|
getProject().setProperty("ivy.parent[" + i + "].revision", parentRevision);
|
|
settings.setVariable("ivy.parent[" + i + "].revision", parentRevision);
|
|
if (parentBranch != null) {
|
|
getProject().setProperty("ivy.parent[" + i + "].branch", parentBranch);
|
|
settings.setVariable("ivy.parent[" + i + "].branch", parentBranch);
|
|
}
|
|
}
|
|
getProject().setProperty("ivy.parents.count",
|
|
String.valueOf(md.getInheritedDescriptors().length));
|
|
settings.setVariable("ivy.parents.count",
|
|
String.valueOf(md.getInheritedDescriptors().length));
|
|
|
|
Boolean hasChanged = null;
|
|
if (getCheckIfChanged()) {
|
|
hasChanged = report.hasChanged();
|
|
getProject().setProperty("ivy.deps.changed", hasChanged.toString());
|
|
settings.setVariable("ivy.deps.changed", hasChanged.toString());
|
|
}
|
|
getProject().setProperty("ivy.resolved.configurations", mergeConfs(confs));
|
|
settings.setVariable("ivy.resolved.configurations", mergeConfs(confs));
|
|
if (file != null) {
|
|
getProject().setProperty("ivy.resolved.file", file.getAbsolutePath());
|
|
settings.setVariable("ivy.resolved.file", file.getAbsolutePath());
|
|
}
|
|
if (resolveId != null) {
|
|
getProject().setProperty("ivy.organisation." + resolveId, mdOrg);
|
|
settings.setVariable("ivy.organisation." + resolveId, mdOrg);
|
|
getProject().setProperty("ivy.module." + resolveId, mdName);
|
|
settings.setVariable("ivy.module." + resolveId, mdName);
|
|
getProject().setProperty("ivy.revision." + resolveId, mdRev);
|
|
settings.setVariable("ivy.revision." + resolveId, mdRev);
|
|
if (getCheckIfChanged()) {
|
|
// hasChanged has already been set earlier
|
|
getProject().setProperty("ivy.deps.changed." + resolveId,
|
|
hasChanged.toString());
|
|
settings.setVariable("ivy.deps.changed." + resolveId, hasChanged.toString());
|
|
}
|
|
getProject().setProperty("ivy.resolved.configurations." + resolveId,
|
|
mergeConfs(confs));
|
|
settings.setVariable("ivy.resolved.configurations." + resolveId,
|
|
mergeConfs(confs));
|
|
if (file != null) {
|
|
getProject().setProperty("ivy.resolved.file." + resolveId,
|
|
file.getAbsolutePath());
|
|
settings.setVariable("ivy.resolved.file." + resolveId,
|
|
file.getAbsolutePath());
|
|
}
|
|
}
|
|
}
|
|
} catch (MalformedURLException e) {
|
|
throw new BuildException("unable to convert given ivy file to url: " + file + ": " + e,
|
|
e);
|
|
} catch (ParseException e) {
|
|
log(e.getMessage(), Project.MSG_ERR);
|
|
throw new BuildException("syntax errors in ivy file: " + e, e);
|
|
} catch (ResolveProcessException e) {
|
|
throw new BuildException("impossible to resolve dependencies:\n\t" + e.getMessage(), e);
|
|
} catch (Exception e) {
|
|
throw new BuildException("impossible to resolve dependencies:\n\t" + e, e);
|
|
}
|
|
}
|
|
|
|
protected Collection<String> getAllowedLogOptions() {
|
|
return Arrays.asList(LogOptions.LOG_DEFAULT, LogOptions.LOG_DOWNLOAD_ONLY,
|
|
LogOptions.LOG_QUIET);
|
|
}
|
|
|
|
private ResolveOptions getResolveOptions(Ivy ivy, String[] confs, IvySettings settings) {
|
|
if (useOrigin) {
|
|
settings.useDeprecatedUseOrigin();
|
|
}
|
|
return ((ResolveOptions) new ResolveOptions().setLog(log)).setConfs(confs)
|
|
.setValidate(doValidate(settings))
|
|
.setArtifactFilter(FilterHelper.getArtifactTypeFilter(type)).setRevision(revision)
|
|
.setDate(getPubDate(pubdate, null)).setUseCacheOnly(useCacheOnly)
|
|
.setRefresh(refresh).setTransitive(transitive).setResolveMode(resolveMode)
|
|
.setResolveId(resolveId).setCheckIfChanged(checkIfChanged);
|
|
}
|
|
|
|
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 boolean isTransitive() {
|
|
return transitive;
|
|
}
|
|
|
|
public void setTransitive(boolean transitive) {
|
|
this.transitive = transitive;
|
|
}
|
|
|
|
public boolean isChanging() {
|
|
return changing;
|
|
}
|
|
|
|
public void setChanging(boolean changing) {
|
|
this.changing = changing;
|
|
}
|
|
|
|
public boolean isKeep() {
|
|
return (keep == null) ? organisation == null : keep;
|
|
}
|
|
|
|
public void setKeep(boolean keep) {
|
|
this.keep = keep;
|
|
}
|
|
|
|
public boolean isInline() {
|
|
return inline;
|
|
}
|
|
|
|
public void setInline(boolean inline) {
|
|
this.inline = inline;
|
|
}
|
|
|
|
public String getResolveId() {
|
|
return resolveId;
|
|
}
|
|
|
|
public void setResolveId(String resolveId) {
|
|
this.resolveId = resolveId;
|
|
}
|
|
|
|
public String getResolveMode() {
|
|
return resolveMode;
|
|
}
|
|
|
|
public void setResolveMode(String resolveMode) {
|
|
this.resolveMode = resolveMode;
|
|
}
|
|
|
|
public boolean getCheckIfChanged() {
|
|
return checkIfChanged;
|
|
}
|
|
|
|
public void setCheckIfChanged(boolean checkIfChanged) {
|
|
this.checkIfChanged = checkIfChanged;
|
|
}
|
|
}
|