blob: 39605c66a44fb0783e631de3aef26394243736c8 [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.osgi.core;
import java.text.ParseException;
import java.util.Comparator;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.osgi.util.Version;
import org.apache.ivy.plugins.latest.ArtifactInfo;
import org.apache.ivy.plugins.latest.ComparatorLatestStrategy;
import org.apache.ivy.plugins.resolver.util.MDResolvedResource;
import org.apache.ivy.plugins.version.VersionMatcher;
public class OsgiLatestStrategy extends ComparatorLatestStrategy {
final class MridComparator implements Comparator<ModuleRevisionId> {
public int compare(ModuleRevisionId o1, ModuleRevisionId o2) {
Version v1 = new Version(o1.getRevision());
Version v2 = new Version(o2.getRevision());
try {
return v1.compareTo(v2);
} catch (RuntimeException e) {
if (e.getCause() instanceof ParseException) {
throw new RuntimeException("Uncomparable versions:" + o1.getRevision()
+ " and " + o2.getRevision() + " (" + e.getMessage() + ")");
}
throw e;
}
}
}
final class ArtifactInfoComparator implements Comparator<ArtifactInfo> {
public int compare(ArtifactInfo o1, ArtifactInfo o2) {
String rev1 = o1.getRevision();
String rev2 = o2.getRevision();
/*
* The revisions can still be not resolved, so we use the current version matcher to
* know if one revision is dynamic, and in this case if it should be considered greater
* or lower than the other one. Note that if the version matcher compare method returns
* 0, it's because it's not possible to know which revision is greater. In this case we
* consider the dynamic one to be greater, because most of the time it will then be
* actually resolved and a real comparison will occur.
*/
VersionMatcher vmatcher = IvyContext.getContext().getSettings().getVersionMatcher();
ModuleRevisionId mrid1 = ModuleRevisionId.newInstance("", "", rev1);
ModuleRevisionId mrid2 = ModuleRevisionId.newInstance("", "", rev2);
if (vmatcher.isDynamic(mrid1)) {
int c = vmatcher.compare(mrid1, mrid2, mridComparator);
return c >= 0 ? 1 : -1;
} else if (vmatcher.isDynamic(mrid2)) {
int c = vmatcher.compare(mrid2, mrid1, mridComparator);
return c >= 0 ? -1 : 1;
}
int res = mridComparator.compare(mrid1, mrid2);
if (res == 0) {
// if same requirements, maybe we can make a difference on the implementation ?
ModuleRevisionId implMrid1 = getImplMrid(o1);
ModuleRevisionId implMrid2 = getImplMrid(o2);
if (implMrid1 != null && implMrid2 != null) {
if (implMrid1.getModuleId().equals(implMrid2.getModuleId())) {
// same implementation, compare the versions
res = mridComparator.compare(implMrid1, implMrid2);
} else {
// not same bundle
// to keep a total order, compare module names even if it means nothing
res = implMrid1.getModuleId().compareTo(implMrid2.getModuleId());
}
}
}
return res;
}
/*
* In the resolve process, a resolved requirement is represented in a special way. Here we
* deconstruct the resolved resource to know which implementation is actually resolved. See
* AbstractOSGiResolver.buildResolvedCapabilityMd()
*/
private ModuleRevisionId getImplMrid(ArtifactInfo o) {
if (!(o instanceof MDResolvedResource)) {
return null;
}
MDResolvedResource mdrr = (MDResolvedResource) o;
ResolvedModuleRevision rmr = mdrr.getResolvedModuleRevision();
if (rmr == null) {
return null;
}
ModuleDescriptor md = rmr.getDescriptor();
if (md == null) {
return null;
}
if (!md.getModuleRevisionId().getOrganisation().equals(BundleInfo.PACKAGE_TYPE)) {
return null;
}
DependencyDescriptor[] dds = md.getDependencies();
if (dds == null || dds.length != 1) {
return null;
}
return dds[0].getDependencyRevisionId();
}
}
private final Comparator<ModuleRevisionId> mridComparator = new MridComparator();
private final Comparator<ArtifactInfo> artifactInfoComparator = new ArtifactInfoComparator();
public OsgiLatestStrategy() {
setComparator(artifactInfoComparator);
setName("latest-osgi");
}
}