From 40e63cc3239819b44af9c6db8d9f0008d899440c Mon Sep 17 00:00:00 2001 From: Elena Parovyshnaia Date: Wed, 23 Feb 2022 21:36:12 +0300 Subject: [PATCH 1/3] #1054 LIC: library-licensed-separately: support license import add utility for filtered requirement gathering --- .../lic/api/agreements/AgreementState.java | 15 ++--- .../requirements/FilteredRequirements.java | 57 +++++++++++++++++++ .../passage/lic/jface/EquinoxPassageUI.java | 7 +-- 3 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java diff --git a/bundles/org.eclipse.passage.lic.api/src/org/eclipse/passage/lic/api/agreements/AgreementState.java b/bundles/org.eclipse.passage.lic.api/src/org/eclipse/passage/lic/api/agreements/AgreementState.java index fc898d284..df4e4b824 100644 --- a/bundles/org.eclipse.passage.lic.api/src/org/eclipse/passage/lic/api/agreements/AgreementState.java +++ b/bundles/org.eclipse.passage.lic.api/src/org/eclipse/passage/lic/api/agreements/AgreementState.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021 ArSysOp + * Copyright (c) 2022 ArSysOp * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -35,16 +35,9 @@ public interface AgreementState { byte[] content(); /** - * Path to the agreement content file deployed. - * - * @return - */ - // Path located(); - - /** - * Agreement acceptance check could possible fail due to a wide variety of - * reasons, not only because the agreement has not indeed be accepted. Is the - * case state is still 'not accepted' and diagnostic is supplied + * Agreement acceptance check could possibly fail due to a wide variety of + * reasons, not only because the agreement has not indeed be accepted. In the + * case state is still 'not accepted' and diagnostic is supplied by this method. */ Optional error(); diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java new file mode 100644 index 000000000..8d8768294 --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.lic.internal.requirements; + +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.eclipse.passage.lic.api.ServiceInvocationResult; +import org.eclipse.passage.lic.api.registry.StringServiceId; +import org.eclipse.passage.lic.api.requirements.Requirement; +import org.eclipse.passage.lic.api.requirements.ResolvedRequirements; +import org.eclipse.passage.lic.base.BaseServiceInvocationResult; + +public final class FilteredRequirements implements ResolvedRequirements { + + private final ResolvedRequirements delegate; + private final Predicate condition; + + public FilteredRequirements(ResolvedRequirements delegate, Predicate condition) { + Objects.requireNonNull(delegate, "FilteredRequirements::delegate"); //$NON-NLS-1$ + Objects.requireNonNull(condition, "FilteredRequirements::condition"); //$NON-NLS-1$ + this.delegate = delegate; + this.condition = condition; + } + + @Override + public StringServiceId id() { + return new StringServiceId("filtered-" + delegate.id().toString()); //$NON-NLS-1$ + } + + @Override + public ServiceInvocationResult> all() { + ServiceInvocationResult> all = delegate.all(); + Optional> some = all.data().map(this::filtered); + return new BaseServiceInvocationResult<>(all.diagnostic(), some); + } + + private Collection filtered(Collection all) { + return all.stream()// + .filter(condition)// + .collect(Collectors.toList()); + } + +} diff --git a/bundles/org.eclipse.passage.lic.jface/src/org/eclipse/passage/lic/jface/EquinoxPassageUI.java b/bundles/org.eclipse.passage.lic.jface/src/org/eclipse/passage/lic/jface/EquinoxPassageUI.java index bd41f4eab..0ff7fff0d 100644 --- a/bundles/org.eclipse.passage.lic.jface/src/org/eclipse/passage/lic/jface/EquinoxPassageUI.java +++ b/bundles/org.eclipse.passage.lic.jface/src/org/eclipse/passage/lic/jface/EquinoxPassageUI.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2021 ArSysOp + * Copyright (c) 2020, 2022 ArSysOp * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -42,11 +42,10 @@ public EquinoxPassageUI(Supplier shell) { @Override public ServiceInvocationResult acquireLicense(String feature) { - ServiceInvocationResult lock = investigate(// + return investigate(// () -> acquire(feature), // GrantLockAttempt::certificate, // - cert -> !new CertificateWorthAttention().test(cert)); - return lock; + new CertificateWorthAttention().negate()); } @Override From 04145bf92844e4db864011269e258a8def04fe87 Mon Sep 17 00:00:00 2001 From: Elena Parovyshnaia Date: Wed, 23 Feb 2022 21:44:13 +0300 Subject: [PATCH 2/3] #1054 LIC: library-licensed-separately: support license import fix copyright header --- .../passage/lic/internal/requirements/FilteredRequirements.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java index 8d8768294..ba09b7e5a 100644 --- a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/requirements/FilteredRequirements.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021 ArSysOp + * Copyright (c) 2022 ArSysOp * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at From b9a37efe0f2e9c750ecfeb00b25fe26058a1058f Mon Sep 17 00:00:00 2001 From: Elena Parovyshnaia Date: Thu, 24 Feb 2022 09:56:58 +0300 Subject: [PATCH 3/3] #1054 LIC: library-licensed-separately: support license import - define extension representing a library for a product licensing scenario - extract for reuse extension reading of the most common structure --- .../.settings/.api_filters | 8 -- .../META-INF/MANIFEST.MF | 2 +- .../OSGI-INF/l10n/bundle.properties | 2 + .../build.properties | 3 +- .../org.eclipse.passage.lic.base/plugin.xml | 18 +++ .../schema/library.exsd | 114 ++++++++++++++++++ .../access/DelegatedLicensingService.java | 40 ++++++ .../META-INF/MANIFEST.MF | 1 + .../internal/equinox/ServiceExtensions.java | 79 ++++++++++++ .../internal/jetty/interaction/Commands.java | 32 ++--- .../ContributedLicensePackIssueListener.java | 28 +---- 11 files changed, 274 insertions(+), 53 deletions(-) create mode 100644 bundles/org.eclipse.passage.lic.base/plugin.xml create mode 100644 bundles/org.eclipse.passage.lic.base/schema/library.exsd create mode 100644 bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/base/access/DelegatedLicensingService.java create mode 100644 bundles/org.eclipse.passage.lic.equinox/src/org/eclipse/passage/lic/internal/equinox/ServiceExtensions.java diff --git a/bundles/org.eclipse.passage.lic.base/.settings/.api_filters b/bundles/org.eclipse.passage.lic.base/.settings/.api_filters index 8614956dd..402e820e7 100644 --- a/bundles/org.eclipse.passage.lic.base/.settings/.api_filters +++ b/bundles/org.eclipse.passage.lic.base/.settings/.api_filters @@ -1,13 +1,5 @@ - - - - - - - - diff --git a/bundles/org.eclipse.passage.lic.base/META-INF/MANIFEST.MF b/bundles/org.eclipse.passage.lic.base/META-INF/MANIFEST.MF index fcd846d91..0a6435299 100644 --- a/bundles/org.eclipse.passage.lic.base/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.passage.lic.base/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Automatic-Module-Name: org.eclipse.passage.lic.base Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.eclipse.passage.lic.base +Bundle-SymbolicName: org.eclipse.passage.lic.base;singleton:=true Bundle-Version: 2.3.0.qualifier Bundle-Name: %Bundle-Name Bundle-Vendor: %Bundle-Vendor diff --git a/bundles/org.eclipse.passage.lic.base/OSGI-INF/l10n/bundle.properties b/bundles/org.eclipse.passage.lic.base/OSGI-INF/l10n/bundle.properties index bf3993fa9..a42b8233a 100644 --- a/bundles/org.eclipse.passage.lic.base/OSGI-INF/l10n/bundle.properties +++ b/bundles/org.eclipse.passage.lic.base/OSGI-INF/l10n/bundle.properties @@ -21,3 +21,5 @@ available under the terms of the Eclipse Public License 2.0\n\ which is available at https://www.eclipse.org/legal/epl-2.0/\n\ \n\ SPDX-License-Identifier: EPL-2.0\n\ + +extension-point.name = External Library licensing service \ No newline at end of file diff --git a/bundles/org.eclipse.passage.lic.base/build.properties b/bundles/org.eclipse.passage.lic.base/build.properties index 809966a74..0adde03a7 100644 --- a/bundles/org.eclipse.passage.lic.base/build.properties +++ b/bundles/org.eclipse.passage.lic.base/build.properties @@ -16,4 +16,5 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ OSGI-INF/,\ - about.html + about.html,\ + plugin.xml diff --git a/bundles/org.eclipse.passage.lic.base/plugin.xml b/bundles/org.eclipse.passage.lic.base/plugin.xml new file mode 100644 index 000000000..96ef72423 --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/plugin.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/bundles/org.eclipse.passage.lic.base/schema/library.exsd b/bundles/org.eclipse.passage.lic.base/schema/library.exsd new file mode 100644 index 000000000..ad82c8daf --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/schema/library.exsd @@ -0,0 +1,114 @@ + + + + + + + + + + A library or component, developed separately, should use the extension to participate in licensing process of an outer project. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/base/access/DelegatedLicensingService.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/base/access/DelegatedLicensingService.java new file mode 100644 index 000000000..878ce96de --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/internal/base/access/DelegatedLicensingService.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2022 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.lic.internal.base.access; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Optional; + +import org.eclipse.passage.lic.api.LicensedProduct; +import org.eclipse.passage.lic.api.PassageLicenseCoverage; +import org.eclipse.passage.lic.api.ServiceInvocationResult; +import org.eclipse.passage.lic.api.agreements.AgreementAcceptanceService; +import org.eclipse.passage.lic.api.conditions.Condition; +import org.eclipse.passage.lic.api.restrictions.ExaminationCertificate; + +public interface DelegatedLicensingService extends PassageLicenseCoverage { + + LicensedProduct product(); + + @Override + ServiceInvocationResult assess(); + + Optional agreementsService(); + + Collection conditions(Path license); + + void installLicense(Path license) throws IOException; + +} diff --git a/bundles/org.eclipse.passage.lic.equinox/META-INF/MANIFEST.MF b/bundles/org.eclipse.passage.lic.equinox/META-INF/MANIFEST.MF index cbd2f14fa..7f0387755 100644 --- a/bundles/org.eclipse.passage.lic.equinox/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.passage.lic.equinox/META-INF/MANIFEST.MF @@ -19,6 +19,7 @@ Export-Package: org.eclipse.passage.lic.equinox, org.eclipse.passage.lic.equinox.conditions, org.eclipse.passage.lic.equinox.io, org.eclipse.passage.lic.equinox.requirements, + org.eclipse.passage.lic.internal.equinox;x-friends:="org.eclipse.passage.loc.licenses.core,org.eclipse.passage.lic.jetty", org.eclipse.passage.lic.internal.equinox.events; x-friends:="org.eclipse.passage.loc.features.core, org.eclipse.passage.loc.products.core, diff --git a/bundles/org.eclipse.passage.lic.equinox/src/org/eclipse/passage/lic/internal/equinox/ServiceExtensions.java b/bundles/org.eclipse.passage.lic.equinox/src/org/eclipse/passage/lic/internal/equinox/ServiceExtensions.java new file mode 100644 index 000000000..deab777bb --- /dev/null +++ b/bundles/org.eclipse.passage.lic.equinox/src/org/eclipse/passage/lic/internal/equinox/ServiceExtensions.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2022 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.lic.internal.equinox; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.Platform; + +/** + *

+ * Reads and instantiates executables for the most common service-supplying + * extensions of sequence> structure. + *

+ *

+ * In case there is a trouble with any single library, logs details and proceeds + * with the rest of them. + *

+ */ +public final class ServiceExtensions implements Supplier> { + + private final String namespace; + private final String point; + private final Class service; + private final Logger log = LogManager.getLogger(getClass()); + + public ServiceExtensions(String namespace, String point, Class service) { + Objects.requireNonNull(namespace, "ServiceExtensions::namespace"); //$NON-NLS-1$ + Objects.requireNonNull(point, "ServiceExtensions::point"); //$NON-NLS-1$ + Objects.requireNonNull(service, "ServiceExtensions::service"); //$NON-NLS-1$ + this.namespace = namespace; + this.point = point; + this.service = service; + } + + @Override + public List get() { + return Arrays.stream(extensions())// + .map(IExtension::getConfigurationElements)// + .flatMap(Arrays::stream)// + .map(this::oneService)// + .filter(Optional::isPresent) // + .map(Optional::get) // + .collect(Collectors.toList()); + } + + private IExtension[] extensions() { + return Platform.getExtensionRegistry().getExtensionPoint(namespace, point).getExtensions(); + } + + private Optional oneService(IConfigurationElement config) { + try { + Object executable = config.createExecutableExtension("class"); //$NON-NLS-1$ + return Optional.of(service.cast(executable)); + } catch (CoreException e) { + log.error("failed to instanciate a service ", e); //$NON-NLS-1$ + return Optional.empty(); + } + } +} diff --git a/bundles/org.eclipse.passage.lic.jetty/src/org/eclipse/passage/lic/internal/jetty/interaction/Commands.java b/bundles/org.eclipse.passage.lic.jetty/src/org/eclipse/passage/lic/internal/jetty/interaction/Commands.java index bc1039544..4b3d0bdde 100644 --- a/bundles/org.eclipse.passage.lic.jetty/src/org/eclipse/passage/lic/internal/jetty/interaction/Commands.java +++ b/bundles/org.eclipse.passage.lic.jetty/src/org/eclipse/passage/lic/internal/jetty/interaction/Commands.java @@ -12,19 +12,15 @@ *******************************************************************************/ package org.eclipse.passage.lic.internal.jetty.interaction; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtension; -import org.eclipse.core.runtime.Platform; +import java.util.List; + +import org.eclipse.passage.lic.internal.equinox.ServiceExtensions; import org.eclipse.passage.lic.internal.jetty.JettyServer; import org.osgi.framework.BundleContext; final class Commands { private ServerHandles server; - private final Logger log = LogManager.getLogger(getClass()); void register(BundleContext context, JettyServer jetty, String name) { registerSelfLicensingCommands(context); @@ -47,20 +43,14 @@ private void registerServerHandles(BundleContext context, JettyServer jetty, Str } private void registerFromExtension(BundleContext context) { - final IExtension[] extensions = Platform.getExtensionRegistry() - .getExtensionPoint("org.eclipse.passage.lic.jetty", "commands").getExtensions(); //$NON-NLS-1$//$NON-NLS-2$ - for (IExtension extension : extensions) { - for (IConfigurationElement config : extension.getConfigurationElements()) { - try { - JettyCommands created = (JettyCommands) config.createExecutableExtension("class"); //$NON-NLS-1$ - created.register(context); - } catch (CoreException e) { - log.error("failed to instanciate command", e); //$NON-NLS-1$ - e.printStackTrace(); - } - } - } - + commands().forEach(command -> command.register(context)); } + private List commands() { + return new ServiceExtensions(// + "org.eclipse.passage.lic.jetty", //$NON-NLS-1$ + "commands", //$NON-NLS-1$ + JettyCommands.class)// + .get(); + } } diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/ContributedLicensePackIssueListener.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/ContributedLicensePackIssueListener.java index 08ff6cb85..db227cb86 100644 --- a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/ContributedLicensePackIssueListener.java +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/ContributedLicensePackIssueListener.java @@ -1,23 +1,16 @@ package org.eclipse.passage.loc.internal.licenses.core; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtension; -import org.eclipse.core.runtime.Platform; +import org.eclipse.passage.lic.internal.equinox.ServiceExtensions; import org.eclipse.passage.lic.licenses.model.api.FloatingLicenseAccess; import org.eclipse.passage.lic.licenses.model.api.FloatingLicensePack; import org.eclipse.passage.lic.licenses.model.api.PersonalLicensePack; final class ContributedLicensePackIssueListener implements LicensePackIssueListener { - private final Logger log = LogManager.getLogger(getClass()); private final List contributed; ContributedLicensePackIssueListener() { @@ -36,20 +29,11 @@ public void personal(PersonalLicensePack license, Path residence) { } private List read() { - IExtension[] extensions = Platform.getExtensionRegistry() - .getExtensionPoint("org.eclipse.passage.loc.licenses.core", "issue").getExtensions(); //$NON-NLS-1$//$NON-NLS-2$ - List found = new ArrayList<>(); - for (IExtension extension : extensions) { - for (IConfigurationElement config : extension.getConfigurationElements()) { - try { - found.add((LicensePackIssueListener) config.createExecutableExtension("class")); //$NON-NLS-1$ - } catch (CoreException e) { - log.error("failed to instanciate licence pack issue listener", e); //$NON-NLS-1$ - e.printStackTrace(); - } - } - } - return found; + return new ServiceExtensions(// + "org.eclipse.passage.loc.licenses.core", //$NON-NLS-1$ + "issue", //$NON-NLS-1$ + LicensePackIssueListener.class)// + .get(); } }