public VersionPatternVisitor newVisitor(final ModuleIdentifier module, final Collection<String> dest, final ResourceAwareResolveResult result) {
return new VersionPatternVisitor() {
final Set<ExternalResourceName> directories = new HashSet<ExternalResourceName>();
public void visit(ResourcePattern pattern, IvyArtifactName artifact) throws ResourceException {
ExternalResourceName versionListPattern = pattern.toVersionListPattern(module, artifact);
LOGGER.debug("Listing all in {}", versionListPattern);
try {
List<String> versionStrings = listRevisionToken(versionListPattern);
for (String versionString : versionStrings) {
dest.add(versionString);
}
} catch (ResourceException e) {
throw e;
} catch (Exception e) {
throw new ResourceException(String.format("Could not list versions using %s.", pattern), e);
}
}
// lists all the values a revision token listed by a given url lister
private List<String> listRevisionToken(ExternalResourceName versionListPattern) throws IOException {
String pattern = versionListPattern.getPath();
if (!pattern.contains(REVISION_TOKEN)) {
LOGGER.debug("revision token not defined in pattern {}.", pattern);
return Collections.emptyList();
}
String prefix = pattern.substring(0, pattern.indexOf(REVISION_TOKEN));
if (revisionMatchesDirectoryName(pattern)) {
ExternalResourceName parent = versionListPattern.getRoot().resolve(prefix);
return listAll(parent);
} else {
int parentFolderSlashIndex = prefix.lastIndexOf(fileSeparator);
String revisionParentFolder = parentFolderSlashIndex == -1 ? "" : prefix.substring(0, parentFolderSlashIndex + 1);
ExternalResourceName parent = versionListPattern.getRoot().resolve(revisionParentFolder);
LOGGER.debug("using {} to list all in {} ", repository, revisionParentFolder);
if (!directories.add(parent)) {
return Collections.emptyList();
}
result.attempted(parent);
List<String> all = repository.list(parent.getUri());
if (all == null) {
return Collections.emptyList();
}
LOGGER.debug("found {} urls", all.size());
Pattern regexPattern = createRegexPattern(pattern, parentFolderSlashIndex);
List<String> ret = filterMatchedValues(all, regexPattern);
LOGGER.debug("{} matched {}" + pattern, ret.size(), pattern);
return ret;
}
}
private List<String> filterMatchedValues(List<String> all, final Pattern p) {
List<String> ret = new ArrayList<String>(all.size());
for (String path : all) {
Matcher m = p.matcher(path);
if (m.matches()) {
String value = m.group(1);
ret.add(value);
}
}
return ret;
}
private Pattern createRegexPattern(String pattern, int prefixLastSlashIndex) {
int endNameIndex = pattern.indexOf(fileSeparator, prefixLastSlashIndex + 1);
String namePattern;
if (endNameIndex != -1) {
namePattern = pattern.substring(prefixLastSlashIndex + 1, endNameIndex);
} else {
namePattern = pattern.substring(prefixLastSlashIndex + 1);
}
namePattern = namePattern.replaceAll("\\.", "\\\\.");
String acceptNamePattern = namePattern.replaceAll("\\[revision\\]", "(.+)");
return Pattern.compile(acceptNamePattern);
}
private boolean revisionMatchesDirectoryName(String pattern) {
int startToken = pattern.indexOf(REVISION_TOKEN);
if (startToken > 0 && !pattern.substring(startToken - 1, startToken).equals(fileSeparator)) {
// previous character is not a separator
return false;
}
int endToken = startToken + REV_TOKEN_LENGTH;
if (endToken < pattern.length() && !pattern.substring(endToken, endToken + 1).equals(fileSeparator)) {
// next character is not a separator
return false;
}
return true;
}
private List<String> listAll(ExternalResourceName parent) throws IOException {
if (!directories.add(parent)) {
return Collections.emptyList();
}
LOGGER.debug("using {} to list all in {}", repository, parent);
result.attempted(parent.toString());
List<String> paths = repository.list(parent.getUri());
if (paths == null) {
return Collections.emptyList();
}
LOGGER.debug("found {} resources", paths.size());
return paths;