diff --git a/bundles/org.eclipse.passage.lic.base/.settings/.api_filters b/bundles/org.eclipse.passage.lic.base/.settings/.api_filters index 2910bc162..8614956dd 100644 --- a/bundles/org.eclipse.passage.lic.base/.settings/.api_filters +++ b/bundles/org.eclipse.passage.lic.base/.settings/.api_filters @@ -8,6 +8,15 @@ + + + + + + + + + diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Cycle.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Cycle.java index ddc868afd..6ffe1f6cd 100644 --- a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Cycle.java +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Cycle.java @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -23,11 +22,11 @@ import org.eclipse.passage.lic.api.Framework; import org.eclipse.passage.lic.api.ServiceInvocationResult; import org.eclipse.passage.lic.api.conditions.ConditionPack; -import org.eclipse.passage.lic.api.conditions.evaluation.Permission; import org.eclipse.passage.lic.api.diagnostic.Diagnostic; import org.eclipse.passage.lic.api.requirements.Requirement; import org.eclipse.passage.lic.api.restrictions.ExaminationCertificate; import org.eclipse.passage.lic.base.BaseServiceInvocationResult; +import org.eclipse.passage.lic.base.access.Permissions.AppliedLicenses; import org.eclipse.passage.lic.base.diagnostic.BaseDiagnostic; import org.eclipse.passage.lic.base.diagnostic.SumOfDiagnostics; @@ -64,7 +63,7 @@ protected Optional feature() { } private T examine(Supplier>> requirements, // - Supplier>> permissions) { + Supplier> permissions) { ServiceInvocationResult> reqs = requirements.get(); if (failed(reqs)) { return stop(); @@ -74,7 +73,7 @@ private T examine(Supplier>> req // we just want to avoid heavy operations below return freeWayOut(); } - ServiceInvocationResult> perms = permissions.get(); + ServiceInvocationResult perms = permissions.get(); if (failed(perms)) { return stop(); } @@ -141,11 +140,10 @@ private ServiceInvocationResult> conditions() { filter.conditional()).get()); } - private ServiceInvocationResult> permissions() { + private ServiceInvocationResult permissions() { ServiceInvocationResult> conditions = conditions(); if (failed(conditions) || empty(conditions)) { - return new BaseServiceInvocationResult>(conditions.diagnostic(), - Collections.emptyList()); + return new BaseServiceInvocationResult(conditions.diagnostic(), new AppliedLicenses()); } return scan(new Permissions(// framework.accessCycleConfiguration().permissionEmitters().get(), // @@ -154,9 +152,11 @@ private ServiceInvocationResult> permissions() { } private ServiceInvocationResult restrictions(Collection requirements, - Collection permissions) { + AppliedLicenses permissions) { return scan(new Restrictions(// + framework.product(), // framework.accessCycleConfiguration().examinators().get(), // + framework.accessCycleConfiguration().acceptance(), // requirements, // permissions).get()); } diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Permissions.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Permissions.java index e7d51c22d..788764a59 100644 --- a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Permissions.java +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Permissions.java @@ -18,9 +18,11 @@ import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.eclipse.passage.lic.api.LicensedProduct; import org.eclipse.passage.lic.api.ServiceInvocationResult; +import org.eclipse.passage.lic.api.agreements.GlobalAgreement; import org.eclipse.passage.lic.api.conditions.ConditionPack; import org.eclipse.passage.lic.api.conditions.evaluation.Emission; import org.eclipse.passage.lic.api.conditions.evaluation.Permission; @@ -29,13 +31,14 @@ import org.eclipse.passage.lic.api.registry.StringServiceId; import org.eclipse.passage.lic.base.BaseServiceInvocationResult; import org.eclipse.passage.lic.base.SumOfCollections; +import org.eclipse.passage.lic.base.access.Permissions.AppliedLicenses; /** * FIXME: Has public visibility only for testing. * * @since 2.1 */ -public final class Permissions implements Supplier>> { +public final class Permissions implements Supplier> { private final Registry registry; private final Collection conditions; @@ -49,7 +52,17 @@ public Permissions(Registry registry } @Override - public ServiceInvocationResult> get() { + public ServiceInvocationResult get() { + BaseServiceInvocationResult> permissions = permissions(); + return new BaseServiceInvocationResult<>(// + permissions.diagnostic(), // + new AppliedLicenses(// + permissions.data().get(), // + agreements())// + ); + } + + private BaseServiceInvocationResult> permissions() { return registry.services().stream() // .map(service -> service.emit(conditions, product))// .reduce(new BaseServiceInvocationResult.Sum<>(new SumOfCollections()))// @@ -70,6 +83,13 @@ private Collection allPermissions(Optional> emi new SumOfCollections()); } + private Collection agreements() { + return conditions.stream()// + .map(ConditionPack::agreements)// + .flatMap(Collection::stream)// + .collect(Collectors.toList()); + } + /** * Here we do not need `ConditionPack` granularity, thus unfold each one to * amass all the permissions we have. @@ -85,4 +105,27 @@ public Collection apply(Collection sum, Emission emissio } + public static final class AppliedLicenses { + + private final Collection permissions; + private final Collection agreements; + + AppliedLicenses() { + this(Collections.emptyList(), Collections.emptyList()); + } + + AppliedLicenses(Collection permissions, Collection agreements) { + this.permissions = permissions; + this.agreements = agreements; + } + + Collection permissions() { + return permissions; + } + + Collection agreements() { + return agreements; + } + } + } diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Restrictions.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Restrictions.java index 5ec893de2..11ee9649f 100644 --- a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Restrictions.java +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/access/Restrictions.java @@ -13,18 +13,33 @@ package org.eclipse.passage.lic.base.access; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.eclipse.passage.lic.api.LicensedProduct; import org.eclipse.passage.lic.api.ServiceInvocationResult; -import org.eclipse.passage.lic.api.conditions.evaluation.Permission; +import org.eclipse.passage.lic.api.agreements.AgreementAcceptanceService; +import org.eclipse.passage.lic.api.agreements.AgreementState; +import org.eclipse.passage.lic.api.agreements.AgreementToAccept; +import org.eclipse.passage.lic.api.agreements.GlobalAgreement; +import org.eclipse.passage.lic.api.agreements.ResolvedAgreement; import org.eclipse.passage.lic.api.diagnostic.Trouble; import org.eclipse.passage.lic.api.registry.Registry; import org.eclipse.passage.lic.api.registry.StringServiceId; import org.eclipse.passage.lic.api.requirements.Requirement; import org.eclipse.passage.lic.api.restrictions.ExaminationCertificate; import org.eclipse.passage.lic.api.restrictions.PermissionsExaminationService; +import org.eclipse.passage.lic.api.restrictions.Restriction; import org.eclipse.passage.lic.base.BaseServiceInvocationResult; +import org.eclipse.passage.lic.base.access.Permissions.AppliedLicenses; +import org.eclipse.passage.lic.base.agreements.AgreementAcceptanceDemand; +import org.eclipse.passage.lic.base.agreements.BaseAgreementToAccept; +import org.eclipse.passage.lic.base.agreements.MinedAgreement; +import org.eclipse.passage.lic.base.agreements.UnacceptedAgreementRestriction; import org.eclipse.passage.lic.base.diagnostic.code.NoServicesOfType; +import org.eclipse.passage.lic.base.restrictions.BaseExaminationCertificate; import org.eclipse.passage.lic.internal.base.i18n.AccessCycleMessages; /** @@ -33,12 +48,16 @@ public final class Restrictions implements Supplier> { private final Registry registry; + private final AgreementAcceptanceService acceptance; private final Collection requirements; - private final Collection permissions; + private final AppliedLicenses permissions; + private final LicensedProduct product; - public Restrictions(Registry registry, - Collection requirements, Collection permissions) { + public Restrictions(LicensedProduct product, Registry registry, + AgreementAcceptanceService acceptance, Collection requirements, AppliedLicenses permissions) { + this.product = product; this.registry = registry; + this.acceptance = acceptance; this.requirements = requirements; this.permissions = permissions; } @@ -52,11 +71,43 @@ public ServiceInvocationResult get() { AccessCycleMessages.getString("Restrictions.no_services"))); //$NON-NLS-1$ } return new BaseServiceInvocationResult(// - registry.services().stream()// - .map(service -> service.examine(requirements, permissions)) // - .reduce(new SumOfCertificates())// - .get() // guaranteed to exist as there is at least one service + new SumOfCertificates().apply(// + permissionBasedCertificate(), // + agreementsBasedCertificate())// ); } + private ExaminationCertificate permissionBasedCertificate() { + return registry.services().stream()// + .map(service -> service.examine(requirements, permissions.permissions())) // + .reduce(new SumOfCertificates())// + .get(); // guaranteed to exist as there is at least one service + } + + private ExaminationCertificate agreementsBasedCertificate() { + List agreements = permissions.agreements().stream()// + .map(this::agreementToAccept)// + .collect(Collectors.toList()); + return new BaseExaminationCertificate(Collections.emptyMap(), restrictions(agreements), agreements); + } + + private AgreementToAccept agreementToAccept(GlobalAgreement agreement) { + ResolvedAgreement definition = new MinedAgreement(agreement); + return new BaseAgreementToAccept(// + new AgreementAcceptanceDemand(definition), // + definition, // + acceptanceState(agreement)); + } + + private AgreementState acceptanceState(GlobalAgreement agreement) { + return acceptance.accepted(agreement.content(), agreement.name()); + } + + private Collection restrictions(List agreements) { + return agreements.stream()// + .filter(agreement -> !agreement.acceptance().accepted())// + .map(agreement -> new UnacceptedAgreementRestriction(product, agreement).get())// + .collect(Collectors.toList()); + } + } diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/AgreementAcceptanceDemand.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/AgreementAcceptanceDemand.java new file mode 100644 index 000000000..765ab5277 --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/AgreementAcceptanceDemand.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.base.agreements; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.passage.lic.api.agreements.ResolvedAgreement; +import org.eclipse.passage.lic.api.requirements.Feature; +import org.eclipse.passage.lic.api.requirements.Requirement; +import org.eclipse.passage.lic.api.restrictions.RestrictionLevel; + +public final class AgreementAcceptanceDemand implements Requirement { + + private final Feature feature; + private final List agreement; + + public AgreementAcceptanceDemand(ResolvedAgreement agreement) { + this.feature = new GlobalAgreementSupportFeature().get(); + this.agreement = Collections.singletonList(agreement); + } + + @Override + public Feature feature() { + return feature; + } + + @Override + public RestrictionLevel restrictionLevel() { + return new RestrictionLevel.Fatal(); + } + + @Override + public List agreements() { + return agreement; + } + + @Override + public Object source() { + return "a license"; //$NON-NLS-1$ + } + +} diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/GlobalAgreementSupportFeature.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/GlobalAgreementSupportFeature.java new file mode 100644 index 000000000..ba9e79f82 --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/GlobalAgreementSupportFeature.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.base.agreements; + +import java.util.function.Supplier; + +import org.eclipse.passage.lic.api.requirements.Feature; +import org.eclipse.passage.lic.base.requirements.BaseFeature; + +public final class GlobalAgreementSupportFeature implements Supplier { + + @Override + public Feature get() { + return new BaseFeature(// + "passage.global-agreement-support.feature", //$NON-NLS-1$ + "0.0.0", //$NON-NLS-1$ + "Global Agreements Support", //$NON-NLS-1$ + "Eclipse Passage Runtime" //$NON-NLS-1$ + ); + } + +} diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/MinedAgreement.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/MinedAgreement.java new file mode 100644 index 000000000..e423d749a --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/MinedAgreement.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.base.agreements; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.passage.lic.api.agreements.GlobalAgreement; +import org.eclipse.passage.lic.api.agreements.ResolvedAgreement; + +public final class MinedAgreement implements ResolvedAgreement { + private final GlobalAgreement agreement; + + public MinedAgreement(GlobalAgreement agreement) { + this.agreement = agreement; + } + + @Override + public InputStream content() throws IOException { + return new ByteArrayInputStream(agreement.content()); + } + + @Override + public String path() { + return agreement.file(); + } + +} diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/UnacceptedAgreementRestriction.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/UnacceptedAgreementRestriction.java new file mode 100644 index 000000000..a73751b60 --- /dev/null +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/agreements/UnacceptedAgreementRestriction.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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.base.agreements; + +import java.util.function.Supplier; + +import org.eclipse.passage.lic.api.LicensedProduct; +import org.eclipse.passage.lic.api.agreements.AgreementToAccept; +import org.eclipse.passage.lic.api.restrictions.Restriction; +import org.eclipse.passage.lic.base.diagnostic.code.AgreementNotAccepted; +import org.eclipse.passage.lic.base.restrictions.BaseRestriction; + +public final class UnacceptedAgreementRestriction implements Supplier { + + private final LicensedProduct product; + private final AgreementToAccept agreement; + + public UnacceptedAgreementRestriction(LicensedProduct product, AgreementToAccept agreement) { + this.product = product; + this.agreement = agreement; + } + + @Override + public Restriction get() { + return new BaseRestriction(product, agreement.origin(), new AgreementNotAccepted()); + } + +} diff --git a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/restrictions/BasePermissionsExaminationService.java b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/restrictions/BasePermissionsExaminationService.java index b2208961d..20630ef00 100644 --- a/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/restrictions/BasePermissionsExaminationService.java +++ b/bundles/org.eclipse.passage.lic.base/src/org/eclipse/passage/lic/base/restrictions/BasePermissionsExaminationService.java @@ -32,7 +32,7 @@ import org.eclipse.passage.lic.api.restrictions.PermissionsExaminationService; import org.eclipse.passage.lic.api.restrictions.Restriction; import org.eclipse.passage.lic.base.agreements.AgreementAssessmentService; -import org.eclipse.passage.lic.base.diagnostic.code.AgreementNotAccepted; +import org.eclipse.passage.lic.base.agreements.UnacceptedAgreementRestriction; import org.eclipse.passage.lic.base.diagnostic.code.InsufficientLicenseCoverage; /** @@ -126,12 +126,8 @@ private Restriction insufficientLicenseCoverage(Requirement requirement) { private List unacceptedAgreements(Collection agreements) { return agreements.stream()// . .filter(agreement -> !agreement.acceptance().accepted())// - .map(this::restrictionForUnacceptedAgreement)// + .map(agreement -> new UnacceptedAgreementRestriction(product, agreement).get())// .collect(Collectors.toList()); } - private Restriction restrictionForUnacceptedAgreement(AgreementToAccept agreement) { - return new BaseRestriction(product, agreement.origin(), new AgreementNotAccepted()); - } - }