package aQute.bnd.deployer.repository; import static aQute.bnd.deployer.repository.RepoResourceUtils.getResourceIdentity; import static aQute.bnd.deployer.repository.RepoResourceUtils.getResourceVersion; import static aQute.bnd.deployer.repository.RepoResourceUtils.narrowVersionsByVersionRange; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import org.osgi.resource.Resource; import aQute.bnd.version.Version; import aQute.lib.collections.SortedList; public class VersionedResourceIndex { private final Map<String,SortedMap<Version,Resource>> map = new HashMap<String,SortedMap<Version,Resource>>(); public synchronized void clear() { map.clear(); } public synchronized Set<String> getIdentities() { return map.keySet(); } public synchronized SortedSet<Version> getVersions(String bsn) { SortedMap<Version,Resource> versionMap = map.get(bsn); if (versionMap == null || versionMap.isEmpty()) return SortedList.empty(); return new SortedList<Version>(versionMap.keySet()); } public synchronized List<Resource> getRange(String bsn, String range) { SortedMap<Version,Resource> versionMap = map.get(bsn); if (versionMap == null || versionMap.isEmpty()) return null; return narrowVersionsByVersionRange(versionMap, range); } public synchronized void put(Resource resource) { String id = getResourceIdentity(resource); if (id == null) throw new IllegalArgumentException("Missing identity capability on resource"); Version version = getResourceVersion(resource); SortedMap<Version,Resource> versionMap = map.get(id); if (versionMap == null) { versionMap = new TreeMap<Version,Resource>(); map.put(id, versionMap); } versionMap.put(version, resource); } public synchronized Resource getExact(String identity, Version version) { SortedMap<Version,Resource> versions = map.get(identity); if (versions == null) return null; return findVersion(version, versions); } private static Resource findVersion(Version version, SortedMap<Version,Resource> versions) { if (version.getQualifier() != null && version.getQualifier().length() > 0) { return versions.get(version); } Resource latest = null; for (Map.Entry<Version,Resource> entry : versions.entrySet()) { if (version.getMicro() == entry.getKey().getMicro() && version.getMinor() == entry.getKey().getMinor() && version.getMajor() == entry.getKey().getMajor()) { latest = entry.getValue(); continue; } if (compare(version, entry.getKey()) < 0) { break; } } return latest; } private static int compare(Version v1, Version v2) { if (v1.getMajor() != v2.getMajor()) return v1.getMajor() - v2.getMajor(); if (v1.getMinor() != v2.getMinor()) return v1.getMinor() - v2.getMinor(); if (v1.getMicro() != v2.getMicro()) return v1.getMicro() - v2.getMicro(); return 0; } }