Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/developer/org.eclipse.papyrus.dev.project.management/src/org/eclipse/papyrus/dev/project/management/internal/operations/VersionRules.java')
-rw-r--r--plugins/developer/org.eclipse.papyrus.dev.project.management/src/org/eclipse/papyrus/dev/project/management/internal/operations/VersionRules.java221
1 files changed, 221 insertions, 0 deletions
diff --git a/plugins/developer/org.eclipse.papyrus.dev.project.management/src/org/eclipse/papyrus/dev/project/management/internal/operations/VersionRules.java b/plugins/developer/org.eclipse.papyrus.dev.project.management/src/org/eclipse/papyrus/dev/project/management/internal/operations/VersionRules.java
new file mode 100644
index 00000000000..cf700faecae
--- /dev/null
+++ b/plugins/developer/org.eclipse.papyrus.dev.project.management/src/org/eclipse/papyrus/dev/project/management/internal/operations/VersionRules.java
@@ -0,0 +1,221 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.dev.project.management.internal.operations;
+
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.eclipse.osgi.service.resolver.ExportPackageDescription;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.core.plugin.PluginRegistry;
+import org.osgi.framework.Version;
+import org.osgi.framework.VersionRange;
+
+/**
+ * Utility for management of bundle dependency version ranges, defining rules
+ * governing how various specific dependencies are to be managed.
+ */
+public class VersionRules {
+
+ private final VersionRule rule = VersionRule.composeAll(
+ new CurrentVersionRule(), // The default behaviour
+ new FixedRangeRule(dep -> dep.startsWith("org.apache.batik"), "[1.6.0,1.7.0)"), //$NON-NLS-1$//$NON-NLS-2$
+ new SkipRule("com.ibm.icu"), //$NON-NLS-1$
+ new FixedRangeRule("com.google.guava", "11.0.0") //$NON-NLS-1$
+ );
+
+ public VersionRules() {
+ super();
+ }
+
+ /**
+ * Queries the version range that should constraint a dependency of the given {@code kind}
+ * on a bundle or package.
+ *
+ * @param kind
+ * the dependency kind
+ * @param dependency
+ * the bundle or package dependency
+ *
+ * @return the appropriate version range, or {@code null} if unknown or the range
+ * currently specified in the manfiest can be retained as is
+ */
+ public VersionRange getDependencyVersionRange(DependencyKind kind, String dependency) {
+ return rule.apply(kind, dependency);
+ }
+
+ static Version getCurrentMinorVersion(String dependencyName, boolean isPackageImport) {
+ Version result = Version.emptyVersion;
+
+ if (!isPackageImport) {
+ IPluginModelBase model = PluginRegistry.findModel(dependencyName);
+ if (model != null) {
+ result = Version.valueOf(model.getPluginBase().getVersion());
+ }
+ } else {
+ // Look for a bundle that exports the package
+ result = Stream.of(PluginRegistry.getActiveModels(false))
+ .filter(p -> exports(p, dependencyName))
+ // TODO: Sort by longest prefix match to the package name
+ .map(p -> getExportedVersion(p, dependencyName))
+ .findFirst()
+ .orElse(Version.emptyVersion);
+ }
+
+ if (!result.equals(Version.emptyVersion)) {
+ // 'Minorize' it
+ result = new Version(result.getMajor(), result.getMinor(), 0);
+ }
+
+ return result;
+ }
+
+ private static boolean exports(IPluginModelBase pluginModel, String packageName) {
+ boolean result = false;
+
+ BundleDescription desc = pluginModel.getBundleDescription();
+ if (desc != null) {
+ result = Stream.of(desc.getExportPackages())
+ .anyMatch(ep -> packageName.equals(ep.getName()));
+ }
+
+ return result;
+ }
+
+ private static Version getExportedVersion(IPluginModelBase pluginModel, String packageName) {
+ // In case there is no bundle description, which would be odd at this point
+ Version result = Version.emptyVersion;
+
+ BundleDescription desc = pluginModel.getBundleDescription();
+ if (desc != null) {
+ result = Stream.of(desc.getExportPackages())
+ .filter(ep -> packageName.equals(ep.getName()))
+ .map(ExportPackageDescription::getVersion)
+ .filter(Objects::nonNull)
+ .findAny().orElse(Version.emptyVersion);
+ }
+
+ return result;
+ }
+
+ //
+ // Nested types
+ //
+
+ private interface VersionRule extends BiPredicate<DependencyKind, String>, BiFunction<DependencyKind, String, VersionRange> {
+ default VersionRule compose(VersionRule other) {
+ return new VersionRule() {
+
+ @Override
+ public VersionRange apply(DependencyKind kind, String dependencyName) {
+ return VersionRule.this.test(kind, dependencyName)
+ ? VersionRule.this.apply(kind, dependencyName)
+ : other.apply(kind, dependencyName);
+ }
+
+ @Override
+ public boolean test(DependencyKind kind, String dependencyName) {
+ return VersionRule.this.test(kind, dependencyName) || other.test(kind, dependencyName);
+ }
+ };
+ }
+
+ static VersionRule composeAll(VersionRule default_, VersionRule... rules) {
+ VersionRule result = default_;
+ for (VersionRule next : rules) {
+ result = next.compose(result);
+ }
+ return result;
+ }
+ }
+
+ private static abstract class AbstractRule implements VersionRule {
+ private final BiPredicate<DependencyKind, String> predicate;
+
+ AbstractRule(BiPredicate<DependencyKind, String> predicate) {
+ super();
+
+ this.predicate = predicate;
+ }
+
+ AbstractRule(Predicate<String> predicate) {
+ this((kind, dep) -> predicate.test(dep));
+ }
+
+ @Override
+ public boolean test(DependencyKind kind, String dependencyName) {
+ return predicate.test(kind, dependencyName);
+ }
+ }
+
+ private static final class FixedRangeRule extends AbstractRule {
+ private final VersionRange range;
+
+ FixedRangeRule(String bundleID, String range) {
+ this(bundleID::equals, VersionRange.valueOf(range));
+ }
+
+ FixedRangeRule(Predicate<String> predicate, String range) {
+ this(predicate, VersionRange.valueOf(range));
+ }
+
+ FixedRangeRule(Predicate<String> predicate, VersionRange range) {
+ super(predicate);
+
+ this.range = range;
+ }
+
+ @Override
+ public VersionRange apply(DependencyKind kind, String dependencyName) {
+ return range;
+ }
+ }
+
+ private static final class SkipRule extends AbstractRule {
+ SkipRule(String dependencyName) {
+ this(dependencyName::equals);
+ }
+
+ SkipRule(Predicate<String> predicate) {
+ super(predicate);
+ }
+
+ @Override
+ public VersionRange apply(DependencyKind kind, String dependencyName) {
+ return null;
+ }
+ }
+
+ private static class CurrentVersionRule extends AbstractRule {
+ private CurrentVersionRule() {
+ super((kind, dep) -> true);
+ }
+
+ @Override
+ public VersionRange apply(DependencyKind kind, String dependencyName) {
+ Version current = getCurrentMinorVersion(dependencyName, kind == DependencyKind.IMPORT_PACKAGE);
+ Version next = ((current == null) || current.equals(Version.emptyVersion))
+ ? null
+ : new Version(current.getMajor() + 1, 0, 0);
+
+ return (next == null)
+ ? null
+ : new VersionRange(VersionRange.LEFT_CLOSED, current, next, VersionRange.RIGHT_OPEN);
+ }
+ }
+}

Back to the top