diff --git a/bundles/org.eclipse.passage.loc.api/src/org/eclipse/passage/loc/internal/api/IssuedFloatingLicense.java b/bundles/org.eclipse.passage.loc.api/src/org/eclipse/passage/loc/internal/api/IssuedFloatingLicense.java index dc40931b8..49327364f 100644 --- a/bundles/org.eclipse.passage.loc.api/src/org/eclipse/passage/loc/internal/api/IssuedFloatingLicense.java +++ b/bundles/org.eclipse.passage.loc.api/src/org/eclipse/passage/loc/internal/api/IssuedFloatingLicense.java @@ -12,6 +12,12 @@ *******************************************************************************/ package org.eclipse.passage.loc.internal.api; +import java.nio.file.Path; +import java.util.List; + public interface IssuedFloatingLicense { + Path residence(); + + List files(); } diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/BaseIssuedFloatingLicense.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/BaseIssuedFloatingLicense.java new file mode 100644 index 000000000..d60a4dcfe --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/BaseIssuedFloatingLicense.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2020 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.loc.internal.licenses.core; + +import java.nio.file.Path; +import java.util.List; + +import org.eclipse.passage.loc.internal.api.IssuedFloatingLicense; + +public final class BaseIssuedFloatingLicense implements IssuedFloatingLicense { + + private final Path residence; + private final List files; + + public BaseIssuedFloatingLicense(Path residence, List files) { + this.residence = residence; + this.files = files; + } + + @Override + public Path residence() { + return residence; + } + + @Override + public List files() { + return files; + } + +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java new file mode 100644 index 000000000..be0b15dda --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2020 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.loc.internal.licenses.core; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.passage.lic.emf.ecore.LicensingEcore; +import org.eclipse.passage.lic.floating.FloatingFileExtensions; +import org.eclipse.passage.lic.floating.model.api.FloatingLicenseAccess; +import org.eclipse.passage.lic.floating.model.api.FloatingLicensePack; +import org.eclipse.passage.lic.floating.model.api.LicenseRequisites; +import org.eclipse.passage.lic.floating.model.api.ProductRef; +import org.eclipse.passage.lic.internal.api.LicensedProduct; +import org.eclipse.passage.lic.internal.api.LicensingException; +import org.eclipse.passage.lic.internal.api.ServiceInvocationResult; +import org.eclipse.passage.lic.internal.api.diagnostic.Trouble; +import org.eclipse.passage.lic.internal.base.BaseLicensedProduct; +import org.eclipse.passage.lic.internal.base.BaseServiceInvocationResult; +import org.eclipse.passage.lic.internal.base.diagnostic.NoSevereErrors; +import org.eclipse.passage.lic.internal.base.diagnostic.SumOfLists; +import org.eclipse.passage.lic.internal.base.io.UserHomeProductResidence; +import org.eclipse.passage.loc.internal.api.IssuedFloatingLicense; +import org.eclipse.passage.loc.internal.api.OperatorProductService; +import org.eclipse.passage.loc.internal.licenses.core.i18n.LicensesCoreMessages; +import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseIssuingFailed; +import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseValidationFailed; +import org.eclipse.passage.loc.internal.products.ProductRegistry; + +final class IssueFloatingLicense { + + private final ProductRegistry products; + private final OperatorProductService operator; + + IssueFloatingLicense(ProductRegistry products, OperatorProductService operator) { + this.products = products; + this.operator = operator; + } + + ServiceInvocationResult issue(FloatingLicensePack pack, + Collection configs) { + LicensedProduct product = product(pack.getLicense().getProduct()); + Path residence = residence(pack.getLicense()); + ServiceInvocationResult> license = // + persist(pack, product, residence, decryptedFile(pack), encryptedFile(pack)); + ServiceInvocationResult> files = configs.stream()// + .map(access -> persist(access, product, residence, decryptedFile(access), encryptedFile(access)))// + .reduce(license, new BaseServiceInvocationResult.Sum<>(new SumOfLists())); + if (!new NoSevereErrors().test(files.diagnostic())) { + return new BaseServiceInvocationResult<>(files.diagnostic()); + } + return new BaseServiceInvocationResult<>(new BaseIssuedFloatingLicense(residence, files.data().get())); + } + + private ServiceInvocationResult> persist(EObject target, LicensedProduct product, // + Path folder, String decrypted, String encrypted) { + // validate + Optional errors = Optional.ofNullable(LicensingEcore.extractValidationError(target)); + if (errors.isPresent()) { + return new BaseServiceInvocationResult<>(new Trouble(new LicenseValidationFailed(), errors.get())); + } + // persist decoded + Path lic; + try { + lic = new PersistedDecoded(folder, target).write(decrypted); + } catch (LicensingException e) { + return new BaseServiceInvocationResult<>(new Trouble(new LicenseIssuingFailed(), // + LicensesCoreMessages.LicenseOperatorServiceImpl_floating_save_decoded_failed, e)); + } + // persist encoded + Path licen; + try { + licen = new PersistedEncoded(product, lic, new ProductPassword(products, operator)).write(encrypted); + } catch (LicensingException e) { + return new BaseServiceInvocationResult<>(new Trouble(new LicenseIssuingFailed(), // + LicensesCoreMessages.LicenseOperatorServiceImpl_floating_save_decoded_failed, e)); + } + return new BaseServiceInvocationResult<>(Arrays.asList(lic, licen)); + } + + private Path residence(LicenseRequisites license) { + return new UserHomeProductResidence(// + license.getProduct().getProduct(), // + license.getProduct().getVersion())// + .get()// + .resolve(license.getIdentifier()); + } + + private LicensedProduct product(ProductRef ref) { + return new BaseLicensedProduct(ref.getProduct(), ref.getVersion()); + + } + + private String decryptedFile(FloatingLicensePack pack) { + return pack.getLicense().getIdentifier() + new FloatingFileExtensions.LicenseDecrypted().get(); + } + + private String encryptedFile(FloatingLicensePack pack) { + return pack.getLicense().getIdentifier() + new FloatingFileExtensions.LicenseEncrypted().get(); + } + + private String decryptedFile(FloatingLicenseAccess access) { + return accessFile(access, new FloatingFileExtensions.LicenseAccessDecrypted()); + } + + private String encryptedFile(FloatingLicenseAccess access) { + return accessFile(access, new FloatingFileExtensions.LicenseAccessEncrypted()); + } + + private String accessFile(FloatingLicenseAccess access, FloatingFileExtensions ext) { + return String.format("%s_%s%s", //$NON-NLS-1$ + access.getOriginLicensePack(), // + access.getUser(), // + ext.get()); + } +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/LicenseOperatorServiceImpl.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/LicenseOperatorServiceImpl.java index 6f98233b9..9ccb8c1ed 100644 --- a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/LicenseOperatorServiceImpl.java +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/LicenseOperatorServiceImpl.java @@ -36,7 +36,6 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.event.EventAdmin; -@SuppressWarnings("restriction") @Component public class LicenseOperatorServiceImpl implements OperatorLicenseService { @@ -126,8 +125,7 @@ public ServiceInvocationResult issueLicensePack(PersonalLicenseRe Supplier pack = (template instanceof LicensePack) // ? () -> LicensePack.class.cast(template)// : () -> createLicensePack(request); - return new IssuePersonalLicense(users, products, operator, events) - .issue(request, pack); + return new IssuePersonalLicense(users, products, operator, events).issue(request, pack); } @Override @@ -139,8 +137,10 @@ public FloatingLicensePack createFloatingLicensePack(FloatingLicenseRequest requ @Override public ServiceInvocationResult issueFloatingLicensePack(FloatingLicensePack pack, Collection configs) { - // TODO YTBD - return null; + Objects.requireNonNull(pack, + "LicenseOperatorServiceImpl::issueFloatingLicensePack: cannot issue license over no data"); //$NON-NLS-1$ + Objects.requireNonNull(configs, "LicenseOperatorServiceImpl::configs"); //$NON-NLS-1$ + return new IssueFloatingLicense(products, operator).issue(pack, configs); } } diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/PersistedDecoded.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/PersistedDecoded.java index 18facb9a0..64137a056 100644 --- a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/PersistedDecoded.java +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/PersistedDecoded.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Collections; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; @@ -47,7 +48,7 @@ private Resource resource(Path path) { private void save(Path decrypted, Resource resource) throws LicensingException { try { - resource.save(null); + resource.save(Collections.emptyMap()); } catch (IOException e) { throw new LicensingException(// String.format(LicensesCoreMessages.EmfObjectPersisted_failed, target, decrypted), e);