org.apache.ivy.plugins.resolver.BasicResolver Maven / Gradle / Ivy
/*
* 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
*
* 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.apache.ivy.plugins.resolver;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.LogOptions;
import org.apache.ivy.core.cache.ArtifactOrigin;
import org.apache.ivy.core.cache.ModuleDescriptorWriter;
import org.apache.ivy.core.cache.RepositoryCacheManager;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
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.ArtifactDownloadReport;
import org.apache.ivy.core.report.DownloadReport;
import org.apache.ivy.core.report.DownloadStatus;
import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
import org.apache.ivy.core.resolve.DownloadOptions;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.core.search.ModuleEntry;
import org.apache.ivy.core.search.OrganisationEntry;
import org.apache.ivy.core.search.RevisionEntry;
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter;
import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.repository.ResourceDownloader;
import org.apache.ivy.plugins.repository.file.FileRepository;
import org.apache.ivy.plugins.repository.file.FileResource;
import org.apache.ivy.plugins.repository.url.URLRepository;
import org.apache.ivy.plugins.repository.url.URLResource;
import org.apache.ivy.plugins.resolver.util.MDResolvedResource;
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
import org.apache.ivy.util.Checks;
import org.apache.ivy.util.ChecksumHelper;
import org.apache.ivy.util.HostUtil;
import org.apache.ivy.util.Message;
/**
*
*/
public abstract class BasicResolver extends AbstractResolver {
public static final String DESCRIPTOR_OPTIONAL = "optional";
public static final String DESCRIPTOR_REQUIRED = "required";
/**
* Exception thrown internally in getDependency to indicate a dependency is unresolved.
*
* Due to the contract of getDependency, this exception is never thrown publicly, but rather
* converted in a message (either error or verbose) and returning null
*
*/
private static class UnresolvedDependencyException extends RuntimeException {
private boolean error;
/**
* Dependency has not been resolved.
* This is not an error and won't log any message.
*/
public UnresolvedDependencyException() {
this("", false);
}
/**
* Dependency has not been resolved.
* This is an error and will log a message.
*/
public UnresolvedDependencyException(String message) {
this(message, true);
}
/**
* Dependency has not been resolved.
* The boolean tells if it is an error or not, a message will be logged if non empty.
*/
public UnresolvedDependencyException(String message, boolean error) {
super(message);
this.error = error;
}
public boolean isError() {
return error;
}
}
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
private String workspaceName;
/**
* True if the files resolved are dependent of the environment from which they have been
* resolved, false otherwise. In general, relative paths are dependent of the environment, and
* absolute paths including machine reference are not.
*/
private boolean envDependent = true;
private List ivyattempts = new ArrayList();
private Map artattempts = new HashMap();
private boolean checkconsistency = true;
private boolean allownomd = true;
private boolean force = false;
private String checksums = null;
private URLRepository extartifactrep = new URLRepository(); // used only to download
// external artifacts
public BasicResolver() {
workspaceName = HostUtil.getLocalHostName();
}
public String getWorkspaceName() {
return workspaceName;
}
public void setWorkspaceName(String workspaceName) {
this.workspaceName = workspaceName;
}
public boolean isEnvDependent() {
return envDependent;
}
public void setEnvDependent(boolean envDependent) {
this.envDependent = envDependent;
}
public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data)
throws ParseException {
IvyContext context = IvyContext.pushNewCopyContext();
try {
ResolvedModuleRevision mr = data.getCurrentResolvedModuleRevision();
if (mr != null) {
if (shouldReturnResolvedModule(dd, mr)) {
return mr;
}
}
if (isForce()) {
dd = dd.clone(ModuleRevisionId.newInstance(
dd.getDependencyRevisionId(), "latest.integration"));
}
DependencyDescriptor systemDd = dd;
DependencyDescriptor nsDd = fromSystem(dd);
context.setDependencyDescriptor(systemDd);
context.setResolveData(data);
clearIvyAttempts();
clearArtifactAttempts();
ModuleRevisionId systemMrid = systemDd.getDependencyRevisionId();
ModuleRevisionId nsMrid = nsDd.getDependencyRevisionId();
checkRevision(systemMrid);
boolean isDynamic = getAndCheckIsDynamic(systemMrid);
// we first search for the dependency in cache
ResolvedModuleRevision rmr = null;
rmr = findModuleInCache(systemDd, data);
if (rmr != null) {
if (rmr.getDescriptor().isDefault() && rmr.getResolver() != this) {
Message.verbose("\t" + getName() + ": found revision in cache: "
+ systemMrid
+ " (resolved by " + rmr.getResolver().getName()
+ "): but it's a default one, maybe we can find a better one");
} else if (isForce() && rmr.getResolver() != this) {
Message.verbose("\t" + getName() + ": found revision in cache: "
+ systemMrid
+ " (resolved by " + rmr.getResolver().getName()
+ "): but we are in force mode, let's try to find one ourself");
} else {
Message.verbose("\t" + getName() + ": revision in cache: " + systemMrid);
return checkLatest(checkForcedResolvedModuleRevision(rmr), data);
}
}
checkInterrupted();
ResolvedResource ivyRef = findIvyFileRef(nsDd, data);
checkInterrupted();
// get module descriptor
ModuleDescriptor nsMd;
ModuleDescriptor systemMd = null;
if (ivyRef == null) {
if (!isAllownomd()) {
throw new UnresolvedDependencyException(
"\t" + getName() + ": no ivy file found for " + systemMrid, false);
}
nsMd = DefaultModuleDescriptor.newDefaultInstance(nsMrid, nsDd
.getAllDependencyArtifacts());
ResolvedResource artifactRef = findFirstArtifactRef(nsMd, nsDd, data);
checkInterrupted();
if (artifactRef == null) {
throw new UnresolvedDependencyException("\t" + getName()
+ ": no ivy file nor artifact found for " + systemMrid, false);
} else {
long lastModified = artifactRef.getLastModified();
if (lastModified != 0 && nsMd instanceof DefaultModuleDescriptor) {
((DefaultModuleDescriptor) nsMd).setLastModified(lastModified);
}
Message.verbose("\t" + getName() + ": no ivy file found for " + systemMrid
+ ": using default data");
if (isDynamic) {
nsMd.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(nsMrid,
artifactRef.getRevision()));
}
systemMd = toSystem(nsMd);
MetadataArtifactDownloadReport madr =
new MetadataArtifactDownloadReport(systemMd.getMetadataArtifact());
madr.setDownloadStatus(DownloadStatus.NO);
madr.setSearched(true);
rmr = new ResolvedModuleRevision(this, this, systemMd, madr, isForce());
}
} else {
if (ivyRef instanceof MDResolvedResource) {
rmr = ((MDResolvedResource) ivyRef).getResolvedModuleRevision();
}
if (rmr == null) {
rmr = parse(ivyRef, systemDd, data);
if (rmr == null) {
throw new UnresolvedDependencyException();
}
}
if (!rmr.getReport().isDownloaded()
&& rmr.getReport().getLocalFile() != null) {
return checkLatest(checkForcedResolvedModuleRevision(rmr), data);
} else {
nsMd = rmr.getDescriptor();
// check descriptor data is in sync with resource revision and names
systemMd = toSystem(nsMd);
if (isCheckconsistency()) {
checkDescriptorConsistency(systemMrid, systemMd, ivyRef);
checkDescriptorConsistency(nsMrid, nsMd, ivyRef);
} else {
if (systemMd instanceof DefaultModuleDescriptor) {
DefaultModuleDescriptor defaultMd = (DefaultModuleDescriptor) systemMd;
ModuleRevisionId revision = getRevision(ivyRef, systemMrid, systemMd);
defaultMd.setModuleRevisionId(revision);
defaultMd.setResolvedModuleRevisionId(revision);
} else {
Message.warn(
"consistency disabled with instance of non DefaultModuleDescriptor..."
+ " module info can't be updated, so consistency check will be done");
checkDescriptorConsistency(nsMrid, nsMd, ivyRef);
checkDescriptorConsistency(systemMrid, systemMd, ivyRef);
}
}
rmr = new ResolvedModuleRevision(
this, this, systemMd, toSystem(rmr.getReport()), isForce());
}
}
resolveAndCheckRevision(systemMd, systemMrid, ivyRef, isDynamic);
resolveAndCheckPublicationDate(systemDd, systemMd, systemMrid, data);
checkNotConvertedExclusionRule(systemMd, ivyRef, data);
cacheModuleDescriptor(systemMd, systemMrid, ivyRef, rmr);
return checkLatest(checkForcedResolvedModuleRevision(rmr), data);
} catch (UnresolvedDependencyException ex) {
if (ex.getMessage().length() > 0) {
if (ex.isError()) {
Message.error(ex.getMessage());
} else {
Message.verbose(ex.getMessage());
}
}
return data.getCurrentResolvedModuleRevision();
} finally {
IvyContext.popContext();
}
}
protected boolean shouldReturnResolvedModule(
DependencyDescriptor dd, ResolvedModuleRevision mr) {
// a resolved module revision has already been found by a prior dependency resolver
// let's see if it should be returned and bypass this resolver
ModuleRevisionId mrid = dd.getDependencyRevisionId();
boolean isDynamic = getSettings().getVersionMatcher().isDynamic(mrid);
boolean shouldReturn = mr.isForce();
shouldReturn |= !isDynamic && !mr.getDescriptor().isDefault();
shouldReturn &= !isForce();
return shouldReturn;
}
private ResolvedModuleRevision checkForcedResolvedModuleRevision(ResolvedModuleRevision rmr) {
if (rmr == null) {
return null;
}
if (!isForce() || rmr.isForce()) {
return rmr;
}
return new ResolvedModuleRevision(
rmr.getResolver(), rmr.getArtifactResolver(),
rmr.getDescriptor(), rmr.getReport(), true);
}
private void cacheModuleDescriptor(ModuleDescriptor systemMd, ModuleRevisionId systemMrid,
ResolvedResource ivyRef, ResolvedModuleRevision rmr) {
RepositoryCacheManager cacheManager = getRepositoryCacheManager();
final ModuleDescriptorParser parser = systemMd.getParser();
// the metadata artifact which was used to cache the original metadata file
Artifact requestedMetadataArtifact =
ivyRef == null
? systemMd.getMetadataArtifact()
: parser.getMetadataArtifact(
ModuleRevisionId.newInstance(systemMrid, ivyRef.getRevision()),
ivyRef.getResource());
cacheManager.originalToCachedModuleDescriptor(this, ivyRef, requestedMetadataArtifact,
rmr, new ModuleDescriptorWriter() {
public void write(ResolvedResource originalMdResource, ModuleDescriptor md,
File src, File dest)
throws IOException, ParseException {
if (originalMdResource == null) {
// a basic ivy file is written containing default data
XmlModuleDescriptorWriter.write(md, dest);
} else {
// copy and update ivy file from source to cache
parser.toIvyFile(
new FileInputStream(src),
originalMdResource.getResource(), dest,
md);
long repLastModified = originalMdResource.getLastModified();
if (repLastModified > 0) {
dest.setLastModified(repLastModified);
}
}
}
});
}
private void checkNotConvertedExclusionRule(ModuleDescriptor systemMd, ResolvedResource ivyRef,
ResolveData data) {
if (!systemMd.isDefault()
&& data.getSettings().logNotConvertedExclusionRule()
&& systemMd instanceof DefaultModuleDescriptor) {
DefaultModuleDescriptor dmd = (DefaultModuleDescriptor) systemMd;
if (dmd.isNamespaceUseful()) {
Message.warn(
"the module descriptor "
+ ivyRef.getResource()
+ " has information which can't be converted into "
+ "the system namespace. "
+ "It will require the availability of the namespace '"
+ getNamespace().getName() + "' to be fully usable.");
}
}
}
private void resolveAndCheckPublicationDate(DependencyDescriptor systemDd,
ModuleDescriptor systemMd, ModuleRevisionId systemMrid, ResolveData data) {
// resolve and check publication date
if (data.getDate() != null) {
long pubDate = getPublicationDate(systemMd, systemDd, data);
if (pubDate > data.getDate().getTime()) {
throw new UnresolvedDependencyException(
"\t" + getName() + ": unacceptable publication date => was="
+ new Date(pubDate) + " required=" + data.getDate());
} else if (pubDate == -1) {
throw new UnresolvedDependencyException("\t" + getName()
+ ": impossible to guess publication date: artifact missing for "
+ systemMrid);
}
systemMd.setResolvedPublicationDate(new Date(pubDate));
}
}
private void checkModuleDescriptorRevision(ModuleDescriptor systemMd,
ModuleRevisionId systemMrid) {
if (!getSettings().getVersionMatcher().accept(systemMrid, systemMd)) {
throw new UnresolvedDependencyException(
"\t" + getName() + ": unacceptable revision => was="
+ systemMd.getResolvedModuleRevisionId().getRevision() + " required="
+ systemMrid.getRevision());
}
}
private boolean getAndCheckIsDynamic(ModuleRevisionId systemMrid) {
boolean isDynamic = getSettings().getVersionMatcher().isDynamic(systemMrid);
if (isDynamic && !acceptLatest()) {
throw new UnresolvedDependencyException(
"dynamic revisions not handled by " + getClass().getName()
+ ". impossible to resolve " + systemMrid);
}
return isDynamic;
}
private void checkRevision(ModuleRevisionId systemMrid) {
// check revision
int index = systemMrid.getRevision().indexOf("@");
if (index != -1
&& !systemMrid.getRevision().substring(index + 1).equals(workspaceName)) {
throw new UnresolvedDependencyException("\t" + getName()
+ ": unhandled revision => " + systemMrid.getRevision());
}
}
private void resolveAndCheckRevision(ModuleDescriptor systemMd,
ModuleRevisionId dependencyConstraint, ResolvedResource ivyRef, boolean isDynamic) {
// we get the resolved module revision id from the descriptor: it may contain extra
// attributes that were not included in the dependency constraint
ModuleRevisionId resolvedMrid = systemMd.getResolvedModuleRevisionId();
if (resolvedMrid.getRevision() == null
|| resolvedMrid.getRevision().length() == 0
|| resolvedMrid.getRevision().startsWith("working@")) {
if (!isDynamic) {
resolvedMrid = ModuleRevisionId.newInstance(
resolvedMrid, dependencyConstraint.getRevision());
} else if (ivyRef == null) {
resolvedMrid = systemMd.getMetadataArtifact().getModuleRevisionId();
} else if (ivyRef.getRevision() == null || ivyRef.getRevision().length() == 0) {
resolvedMrid = ModuleRevisionId.newInstance(resolvedMrid, "working@"
+ getName());
} else {
resolvedMrid = ModuleRevisionId.newInstance(resolvedMrid, ivyRef
.getRevision());
}
}
if (isDynamic) {
Message.verbose("\t\t[" + toSystem(resolvedMrid).getRevision() + "] "
+ dependencyConstraint.getModuleId());
}
systemMd.setResolvedModuleRevisionId(resolvedMrid);
checkModuleDescriptorRevision(systemMd, dependencyConstraint);
}
private ModuleRevisionId getRevision(ResolvedResource ivyRef, ModuleRevisionId askedMrid,
ModuleDescriptor md) throws ParseException {
Map allAttributes = new HashMap();
allAttributes.putAll(md.getQualifiedExtraAttributes());
allAttributes.putAll(askedMrid.getQualifiedExtraAttributes());
String revision = ivyRef.getRevision();
if (revision == null) {
Message.debug("no revision found in reference for " + askedMrid);
if (getSettings().getVersionMatcher().isDynamic(askedMrid)) {
if (md.getModuleRevisionId().getRevision() == null) {
revision = "working@" + getName();
} else {
Message.debug("using " + askedMrid);
revision = askedMrid.getRevision();
}
} else {
Message.debug("using " + askedMrid);
revision = askedMrid.getRevision();
}
}
return ModuleRevisionId.newInstance(askedMrid.getOrganisation(), askedMrid.getName(),
askedMrid.getBranch(), revision, allAttributes);
}
public ResolvedModuleRevision parse(final ResolvedResource mdRef, DependencyDescriptor dd,
ResolveData data) throws ParseException {
DependencyDescriptor nsDd = dd;
dd = toSystem(nsDd);
ModuleRevisionId mrid = dd.getDependencyRevisionId();
ModuleDescriptorParser parser = ModuleDescriptorParserRegistry
.getInstance().getParser(mdRef.getResource());
if (parser == null) {
Message.warn("no module descriptor parser available for " + mdRef.getResource());
return null;
}
Message.verbose("\t" + getName() + ": found md file for " + mrid);
Message.verbose("\t\t=> " + mdRef);
Message.debug("\tparser = " + parser);
ModuleRevisionId resolvedMrid = mrid;
// first check if this dependency has not yet been resolved
if (getSettings().getVersionMatcher().isDynamic(mrid)) {
resolvedMrid = ModuleRevisionId.newInstance(mrid, mdRef.getRevision());
IvyNode node = data.getNode(resolvedMrid);
if (node != null && node.getModuleRevision() != null) {
// this revision has already be resolved : return it
if (node.getDescriptor() != null && node.getDescriptor().isDefault()) {
Message.verbose("\t" + getName() + ": found already resolved revision: "
+ resolvedMrid
+ ": but it's a default one, maybe we can find a better one");
} else {
Message.verbose("\t" + getName() + ": revision already resolved: "
+ resolvedMrid);
node.getModuleRevision().getReport().setSearched(true);
return node.getModuleRevision();
}
}
}
Artifact moduleArtifact = parser.getMetadataArtifact(resolvedMrid, mdRef.getResource());
return getRepositoryCacheManager().cacheModuleDescriptor(
this, mdRef, dd, moduleArtifact, downloader,
getCacheOptions(data));
}
protected ResourceMDParser getRMDParser(final DependencyDescriptor dd, final ResolveData data) {
return new ResourceMDParser() {
public MDResolvedResource parse(Resource resource, String rev) {
try {
ResolvedModuleRevision rmr = BasicResolver.this.parse(new ResolvedResource(
resource, rev), dd, data);
if (rmr == null) {
return null;
} else {
return new MDResolvedResource(resource, rev, rmr);
}
} catch (ParseException e) {
Message.warn("Failed to parse the file '" + resource + "': "
+ e.getMessage());
return null;
}
}
};
}
protected ResourceMDParser getDefaultRMDParser(final ModuleId mid) {
return new ResourceMDParser() {
public MDResolvedResource parse(Resource resource, String rev) {
DefaultModuleDescriptor md =
DefaultModuleDescriptor.newDefaultInstance(new ModuleRevisionId(mid, rev));
MetadataArtifactDownloadReport madr =
new MetadataArtifactDownloadReport(md.getMetadataArtifact());
madr.setDownloadStatus(DownloadStatus.NO);
madr.setSearched(true);
return new MDResolvedResource(resource, rev, new ResolvedModuleRevision(
BasicResolver.this, BasicResolver.this, md, madr, isForce()));
}
};
}
// private boolean isResolved(ResolveData data, ModuleRevisionId mrid) {
// IvyNode node = getSystemNode(data, mrid);
// return node != null && node.getModuleRevision() != null;
// }
//
private void checkDescriptorConsistency(ModuleRevisionId mrid, ModuleDescriptor md,
ResolvedResource ivyRef) throws ParseException {
boolean ok = true;
StringBuffer errors = new StringBuffer();
if (!mrid.getOrganisation().equals(md.getModuleRevisionId().getOrganisation())) {
Message.error("\t" + getName() + ": bad organisation found in " + ivyRef.getResource()
+ ": expected='" + mrid.getOrganisation() + "' found='"
+ md.getModuleRevisionId().getOrganisation() + "'");
errors.append("bad organisation: expected='" + mrid.getOrganisation() + "' found='"
+ md.getModuleRevisionId().getOrganisation() + "'; ");
ok = false;
}
if (!mrid.getName().equals(md.getModuleRevisionId().getName())) {
Message.error("\t" + getName() + ": bad module name found in " + ivyRef.getResource()
+ ": expected='" + mrid.getName() + " found='"
+ md.getModuleRevisionId().getName() + "'");
errors.append("bad module name: expected='" + mrid.getName() + "' found='"
+ md.getModuleRevisionId().getName() + "'; ");
ok = false;
}
if (mrid.getBranch() != null
&& !mrid.getBranch().equals(md.getModuleRevisionId().getBranch())) {
Message.error("\t" + getName() + ": bad branch name found in " + ivyRef.getResource()
+ ": expected='" + mrid.getBranch() + " found='"
+ md.getModuleRevisionId().getBranch() + "'");
errors.append("bad branch name: expected='" + mrid.getBranch() + "' found='"
+ md.getModuleRevisionId().getBranch() + "'; ");
ok = false;
}
if (ivyRef.getRevision() != null && !ivyRef.getRevision().startsWith("working@")) {
ModuleRevisionId expectedMrid = ModuleRevisionId
.newInstance(mrid, ivyRef.getRevision());
if (!getSettings().getVersionMatcher().accept(expectedMrid, md)) {
Message.error("\t" + getName() + ": bad revision found in " + ivyRef.getResource()
+ ": expected='" + ivyRef.getRevision() + " found='"
+ md.getModuleRevisionId().getRevision() + "'");
errors.append("bad revision: expected='" + ivyRef.getRevision() + "' found='"
+ md.getModuleRevisionId().getRevision() + "'; ");
ok = false;
}
}
if (!getSettings().getStatusManager().isStatus(md.getStatus())) {
Message.error("\t" + getName() + ": bad status found in " + ivyRef.getResource()
+ ": '" + md.getStatus() + "'");
errors.append("bad status: '" + md.getStatus() + "'; ");
ok = false;
}
for (Iterator it = mrid.getExtraAttributes().entrySet().iterator(); it.hasNext();) {
Entry extra = (Entry) it.next();
if (extra.getValue() != null && !extra.getValue().equals(
md.getExtraAttribute((String) extra.getKey()))) {
String errorMsg = "bad " + extra.getKey() + " found in " + ivyRef.getResource()
+ ": expected='" + extra.getValue() + "' found='"
+ md.getExtraAttribute((String) extra.getKey()) + "'";
Message.error("\t" + getName() + ": " + errorMsg);
errors.append(errorMsg + ";");
ok = false;
}
}
if (!ok) {
throw new ParseException("inconsistent module descriptor file found in '"
+ ivyRef.getResource() + "': " + errors, 0);
}
}
protected void clearIvyAttempts() {
ivyattempts.clear();
clearArtifactAttempts();
}
protected void logIvyAttempt(String attempt) {
ivyattempts.add(attempt);
Message.verbose("\t\ttried " + attempt);
}
protected void logArtifactAttempt(Artifact art, String attempt) {
List attempts = (List) artattempts.get(art);
if (attempts == null) {
attempts = new ArrayList();
artattempts.put(art, attempts);
}
attempts.add(attempt);
Message.verbose("\t\ttried " + attempt);
}
protected void logAttempt(String attempt) {
Artifact currentArtifact = (Artifact) IvyContext.getContext().get(getName() + ".artifact");
if (currentArtifact != null) {
logArtifactAttempt(currentArtifact, attempt);
} else {
logIvyAttempt(attempt);
}
}
public void reportFailure() {
Message.warn("==== " + getName() + ": tried");
for (ListIterator iter = ivyattempts.listIterator(); iter.hasNext();) {
String m = (String) iter.next();
Message.warn(" " + m);
}
for (Iterator iter = artattempts.keySet().iterator(); iter.hasNext();) {
Artifact art = (Artifact) iter.next();
List attempts = (List) artattempts.get(art);
if (attempts != null) {
Message.warn(" -- artifact " + art + ":");
for (ListIterator iterator = attempts.listIterator(); iterator.hasNext();) {
String m = (String) iterator.next();
Message.warn(" " + m);
}
}
}
}
public void reportFailure(Artifact art) {
Message.warn("==== " + getName() + ": tried");
List attempts = (List) artattempts.get(art);
if (attempts != null) {
for (ListIterator iter = attempts.listIterator(); iter.hasNext();) {
String m = (String) iter.next();
Message.warn(" " + m);
}
}
}
protected boolean acceptLatest() {
return true;
}
public DownloadReport download(Artifact[] artifacts, DownloadOptions options) {
RepositoryCacheManager cacheManager = getRepositoryCacheManager();
clearArtifactAttempts();
DownloadReport dr = new DownloadReport();
for (int i = 0; i < artifacts.length; i++) {
ArtifactDownloadReport adr = cacheManager.download(
artifacts[i], artifactResourceResolver, downloader,
getCacheDownloadOptions(options));
if (DownloadStatus.FAILED == adr.getDownloadStatus()) {
if (!ArtifactDownloadReport.MISSING_ARTIFACT.equals(adr.getDownloadDetails())) {
Message.warn("\t" + adr);
}
} else if (DownloadStatus.NO == adr.getDownloadStatus()) {
Message.verbose("\t" + adr);
} else if (LogOptions.LOG_QUIET.equals(options.getLog())) {
Message.verbose("\t" + adr);
} else {
Message.info("\t" + adr);
}
dr.addArtifactReport(adr);
checkInterrupted();
}
return dr;
}
protected void clearArtifactAttempts() {
artattempts.clear();
}
public ArtifactDownloadReport download(final ArtifactOrigin origin, DownloadOptions options) {
Checks.checkNotNull(origin, "origin");
return getRepositoryCacheManager().download(
origin.getArtifact(),
new ArtifactResourceResolver() {
public ResolvedResource resolve(Artifact artifact) {
try {
Resource resource = getResource(origin.getLocation());
if (resource == null) {
return null;
}
String revision = origin.getArtifact().getModuleRevisionId().getRevision();
return new ResolvedResource(resource, revision);
} catch (IOException e) {
return null;
}
}
},
downloader,
getCacheDownloadOptions(options));
}
protected abstract Resource getResource(String source) throws IOException;
public boolean exists(Artifact artifact) {
ResolvedResource artifactRef = getArtifactRef(artifact, null);
if (artifactRef != null) {
return artifactRef.getResource().exists();
}
return false;
}
public ArtifactOrigin locate(Artifact artifact) {
ArtifactOrigin origin = getRepositoryCacheManager().getSavedArtifactOrigin(artifact);
if (!ArtifactOrigin.isUnknown(origin)) {
return origin;
}
ResolvedResource artifactRef = getArtifactRef(artifact, null);
if (artifactRef != null && artifactRef.getResource().exists()) {
return new ArtifactOrigin(
artifact,
artifactRef.getResource().isLocal(),
artifactRef.getResource().getName());
}
return null;
}
protected long getPublicationDate(ModuleDescriptor md, DependencyDescriptor dd,
ResolveData data) {
if (md.getPublicationDate() != null) {
return md.getPublicationDate().getTime();
}
ResolvedResource artifactRef = findFirstArtifactRef(md, dd, data);
if (artifactRef != null) {
return artifactRef.getLastModified();
}
return -1;
}
public String toString() {
return getName();
}
public String[] listTokenValues(String token, Map otherTokenValues) {
Collection ret = findNames(otherTokenValues, token);
return (String[]) ret.toArray(new String[ret.size()]);
}
public OrganisationEntry[] listOrganisations() {
Collection names = findNames(Collections.EMPTY_MAP, IvyPatternHelper.ORGANISATION_KEY);
OrganisationEntry[] ret = new OrganisationEntry[names.size()];
int i = 0;
for (Iterator iter = names.iterator(); iter.hasNext(); i++) {
String org = (String) iter.next();
ret[i] = new OrganisationEntry(this, org);
}
return ret;
}
public ModuleEntry[] listModules(OrganisationEntry org) {
Map tokenValues = new HashMap();
tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, org.getOrganisation());
Collection names = findNames(tokenValues, IvyPatternHelper.MODULE_KEY);
ModuleEntry[] ret = new ModuleEntry[names.size()];
int i = 0;
for (Iterator iter = names.iterator(); iter.hasNext(); i++) {
String name = (String) iter.next();
ret[i] = new ModuleEntry(org, name);
}
return ret;
}
public RevisionEntry[] listRevisions(ModuleEntry mod) {
Map tokenValues = new HashMap();
tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, mod.getOrganisation());
tokenValues.put(IvyPatternHelper.MODULE_KEY, mod.getModule());
Collection names = findNames(tokenValues, IvyPatternHelper.REVISION_KEY);
RevisionEntry[] ret = new RevisionEntry[names.size()];
int i = 0;
for (Iterator iter = names.iterator(); iter.hasNext(); i++) {
String name = (String) iter.next();
ret[i] = new RevisionEntry(mod, name);
}
return ret;
}
protected abstract Collection findNames(Map tokenValues, String token);
protected ResolvedResource findFirstArtifactRef(ModuleDescriptor md, DependencyDescriptor dd,
ResolveData data) {
ResolvedResource ret = null;
String[] conf = md.getConfigurationsNames();
for (int i = 0; i < conf.length; i++) {
Artifact[] artifacts = md.getArtifacts(conf[i]);
for (int j = 0; j < artifacts.length; j++) {
ret = getArtifactRef(artifacts[j], data.getDate());
if (ret != null) {
return ret;
}
}
}
return null;
}
protected long getAndCheck(Resource resource, File dest) throws IOException {
long size = get(resource, dest);
String[] checksums = getChecksumAlgorithms();
boolean checked = false;
for (int i = 0; i < checksums.length && !checked; i++) {
checked = check(resource, dest, checksums[i]);
}
return size;
}
/**
* Checks the given resource checksum if a checksum resource exists.
*
* @param resource
* the resource to check
* @param dest
* the file where the resource has been downloaded
* @param algorithm
* the checksum algorithm to use
* @return true if the checksum has been successfully checked, false if the checksum wasn't
* available
* @throws IOException
* if a checksum exist but do not match the downloaded file checksum
*/
private boolean check(Resource resource, File dest, String algorithm) throws IOException {
Resource csRes = resource.clone(resource.getName() + "." + algorithm);
if (csRes.exists()) {
Message.debug(algorithm + " file found for " + resource + ": checking...");
File csFile = File.createTempFile("ivytmp", algorithm);
try {
get(csRes, csFile);
try {
ChecksumHelper.check(dest, csFile, algorithm);
Message.verbose(algorithm + " OK for " + resource);
return true;
} catch (IOException ex) {
dest.delete();
throw ex;
}
} finally {
csFile.delete();
}
} else {
return false;
}
}
protected ResolvedResource getArtifactRef(Artifact artifact, Date date) {
IvyContext.getContext().set(getName() + ".artifact", artifact);
try {
ResolvedResource ret = findArtifactRef(artifact, date);
if (ret == null && artifact.getUrl() != null) {
URL url = artifact.getUrl();
Message.verbose("\tusing url for " + artifact + ": " + url);
logArtifactAttempt(artifact, url.toExternalForm());
Resource resource;
if ("file".equals(url.getProtocol())) {
resource = new FileResource(new FileRepository(), new File(url.getPath()));
} else {
resource = new URLResource(url);
}
ret = new ResolvedResource(resource, artifact.getModuleRevisionId()
.getRevision());
}
return ret;
} finally {
IvyContext.getContext().set(getName() + ".artifact", null);
}
}
protected abstract ResolvedResource findArtifactRef(Artifact artifact, Date date);
protected abstract long get(Resource resource, File dest) throws IOException;
public boolean isCheckconsistency() {
return checkconsistency;
}
public void setCheckconsistency(boolean checkConsitency) {
checkconsistency = checkConsitency;
}
public void setForce(boolean force) {
this.force = force;
}
public boolean isForce() {
return force;
}
public boolean isAllownomd() {
return allownomd;
}
public void setAllownomd(boolean b) {
Message.deprecated(
"allownomd is deprecated, please use descriptor=\""
+ (b ? DESCRIPTOR_OPTIONAL : DESCRIPTOR_REQUIRED) + "\" instead");
allownomd = b;
}
/**
* Sets the module descriptor presence rule.
* Should be one of {@link #DESCRIPTOR_REQUIRED} or {@link #DESCRIPTOR_OPTIONAL}.
*
* @param descriptorRule the descriptor rule to use with this resolver.
*/
public void setDescriptor(String descriptorRule) {
if (DESCRIPTOR_REQUIRED.equals(descriptorRule)) {
allownomd = false;
} else if (DESCRIPTOR_OPTIONAL.equals(descriptorRule)) {
allownomd = true;
} else {
throw new IllegalArgumentException(
"unknown descriptor rule '" + descriptorRule
+ "'. Allowed rules are: "
+ Arrays.asList(new String[] {DESCRIPTOR_REQUIRED, DESCRIPTOR_OPTIONAL}));
}
}
public String[] getChecksumAlgorithms() {
String csDef = checksums == null ? getSettings().getVariable("ivy.checksums") : checksums;
if (csDef == null) {
return new String[0];
}
// csDef is a comma separated list of checksum algorithms to use with this resolver
// we parse and return it as a String[]
String[] checksums = csDef.split(",");
List algos = new ArrayList();
for (int i = 0; i < checksums.length; i++) {
String cs = checksums[i].trim();
if (!"".equals(cs) && !"none".equals(cs)) {
algos.add(cs);
}
}
return (String[]) algos.toArray(new String[algos.size()]);
}
public void setChecksums(String checksums) {
this.checksums = checksums;
}
private final ArtifactResourceResolver artifactResourceResolver
= new ArtifactResourceResolver() {
public ResolvedResource resolve(Artifact artifact) {
artifact = fromSystem(artifact);
return getArtifactRef(artifact, null);
}
};
private final ResourceDownloader downloader = new ResourceDownloader() {
public void download(Artifact artifact, Resource resource, File dest) throws IOException {
if (dest.exists()) {
dest.delete();
}
File part = new File(dest.getAbsolutePath() + ".part");
if (resource.getName().equals(
String.valueOf(artifact.getUrl()))) {
if (part.getParentFile() != null) {
part.getParentFile().mkdirs();
}
extartifactrep.get(resource.getName(), part);
} else {
getAndCheck(resource, part);
}
if (!part.renameTo(dest)) {
throw new IOException(
"impossible to move part file to definitive one: "
+ part + " -> " + dest);
}
}
};
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy