Skip to content

Commit

Permalink
[#1482] From-The-Box Support for optional license storage
Browse files Browse the repository at this point in the history
Signed-off-by: eparovyshnaia <[email protected]>
  • Loading branch information
eparovyshnaia committed Jan 28, 2025
1 parent 7d40238 commit baea7a1
Show file tree
Hide file tree
Showing 14 changed files with 475 additions and 186 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2018, 2024 ArSysOp and others
# Copyright (c) 2018, 2025 ArSysOp and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
Expand All @@ -13,7 +13,7 @@

Bundle-Name = Passage LIC Base
Bundle-Vendor = Eclipse Passage
Bundle-Copyright = Copyright (c) 2018, 2024 ArSysOp and others.\n\
Bundle-Copyright = Copyright (c) 2018, 2025 ArSysOp and others.\n\
\n\
This program and the accompanying materials are made\n\
available under the terms of the Eclipse Public License 2.0\n\
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*******************************************************************************
* Copyright (c) 2025 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.conditions.mining;

import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Supplier;

import org.eclipse.passage.lic.api.LicensedProduct;
import org.eclipse.passage.lic.api.LicensingException;
import org.eclipse.passage.lic.api.ServiceInvocationResult;
import org.eclipse.passage.lic.api.conditions.Condition;
import org.eclipse.passage.lic.api.conditions.ConditionMiningTarget;
import org.eclipse.passage.lic.api.conditions.ConditionPack;
import org.eclipse.passage.lic.api.conditions.mining.MinedConditions;
import org.eclipse.passage.lic.api.conditions.mining.MiningEquipment;
import org.eclipse.passage.lic.api.diagnostic.Trouble;
import org.eclipse.passage.lic.base.BaseServiceInvocationResult;
import org.eclipse.passage.lic.base.diagnostic.BaseDiagnostic;
import org.eclipse.passage.lic.base.diagnostic.code.NoLicenses;
import org.eclipse.passage.lic.base.diagnostic.code.ServiceFailedOnInfrastructureDenial;
import org.eclipse.passage.lic.base.io.PassageFileExtension;
import org.eclipse.passage.lic.internal.base.i18n.ConditionMiningMessages;

/**
* <p>
* Scans the configured part of the local file system for encrypted license
* files, reads them and retrieves all the licensing {@linkplain Condition}s
* they declare.
* </p>
* <p>
* Bearable warning leased in case of no license file is found.
* </p>
* <p>
* Severe (infrastructure denial) error leased in case of any mining error.
* </p>
*
* @since 4.1
*/
abstract class BaseLocalConditions implements MinedConditions {

private final ConditionMiningTarget id;
private final MiningEquipment equipment;
protected final PassageFileExtension scope;

protected BaseLocalConditions(ConditionMiningTarget id, MiningEquipment equipment, PassageFileExtension scope) {
String cls = getClass().getSimpleName();
this.id = Objects.requireNonNull(id, cls + "::id"); //$NON-NLS-1$
this.equipment = Objects.requireNonNull(equipment, cls + "::equipment"); //$NON-NLS-1$
this.scope = Objects.requireNonNull(scope, cls + "::scope"); //$NON-NLS-1$
}

protected BaseLocalConditions(ConditionMiningTarget id, MiningEquipment equipment) {
this(id, equipment, new PassageFileExtension.LicenseEncrypted());
}

@Override
public final ConditionMiningTarget id() {
return id;
}

@Override
public final ServiceInvocationResult<Collection<ConditionPack>> all(LicensedProduct product) {
try {
Collection<Path> licenses = licenses(product);
if (licenses.isEmpty()) {
return noLicenses(product);
}
return equipment.tool(product, id).mine(licenses);
} catch (LicensingException e) {
return scanFailed(e);
}
}

protected abstract Collection<Path> licenses(LicensedProduct product) throws LicensingException;

protected abstract Supplier<Path> base(LicensedProduct product);

private ServiceInvocationResult<Collection<ConditionPack>> noLicenses(LicensedProduct product) {
return new BaseServiceInvocationResult<Collection<ConditionPack>>(//
new BaseDiagnostic(//
Collections.emptyList(), //
Collections.singletonList(//
new Trouble(//
new NoLicenses(), //
String.format(//
ConditionMiningMessages.getString("BaseLocalConditions.no_licenses"), //$NON-NLS-1$
base(product).get().toAbsolutePath())))//
), //
Collections.emptyList()//
);
}

private BaseServiceInvocationResult<Collection<ConditionPack>> scanFailed(LicensingException e) {
return new BaseServiceInvocationResult<Collection<ConditionPack>>( //
new Trouble(//
new ServiceFailedOnInfrastructureDenial(), //
ConditionMiningMessages.getString("BaseLocalConditions.failed"), //$NON-NLS-1$
e));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2025 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.conditions.mining;

import java.nio.file.Path;
import java.util.Collection;

import org.eclipse.passage.lic.api.LicensedProduct;
import org.eclipse.passage.lic.api.LicensingException;
import org.eclipse.passage.lic.api.conditions.ConditionMiningTarget;
import org.eclipse.passage.lic.api.conditions.mining.MiningEquipment;
import org.eclipse.passage.lic.base.io.LenientFileCollection;
import org.eclipse.passage.lic.base.io.PassageFileExtension;

/**
* @since 4.1
*/
public abstract class LenientLocalConditions extends BaseLocalConditions {

protected LenientLocalConditions(ConditionMiningTarget id, MiningEquipment equipment, PassageFileExtension scope) {
super(id, equipment, scope);
}

protected LenientLocalConditions(ConditionMiningTarget id, MiningEquipment equipment) {
this(id, equipment, new PassageFileExtension.LicenseEncrypted());
}

@Override
protected Collection<Path> licenses(LicensedProduct product) throws LicensingException {
return new LenientFileCollection(base(product), scope).get();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020, 2021 ArSysOp
* Copyright (c) 2020, 2025 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
Expand All @@ -9,102 +9,43 @@
*
* Contributors:
* ArSysOp - initial API and implementation
* ArSysOp - evolved to grow configurable in the place of actual files supplying (#1482)
*******************************************************************************/
package org.eclipse.passage.lic.base.conditions.mining;

import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Supplier;

import org.eclipse.passage.lic.api.LicensedProduct;
import org.eclipse.passage.lic.api.LicensingException;
import org.eclipse.passage.lic.api.ServiceInvocationResult;
import org.eclipse.passage.lic.api.conditions.Condition;
import org.eclipse.passage.lic.api.conditions.ConditionMiningTarget;
import org.eclipse.passage.lic.api.conditions.ConditionPack;
import org.eclipse.passage.lic.api.conditions.mining.MinedConditions;
import org.eclipse.passage.lic.api.conditions.mining.MiningEquipment;
import org.eclipse.passage.lic.api.diagnostic.Trouble;
import org.eclipse.passage.lic.base.BaseServiceInvocationResult;
import org.eclipse.passage.lic.base.diagnostic.BaseDiagnostic;
import org.eclipse.passage.lic.base.diagnostic.code.NoLicenses;
import org.eclipse.passage.lic.base.diagnostic.code.ServiceFailedOnInfrastructureDenial;
import org.eclipse.passage.lic.base.io.FileCollection;
import org.eclipse.passage.lic.base.io.PassageFileExtension;
import org.eclipse.passage.lic.internal.base.i18n.ConditionMiningMessages;

/**
* <p>
* Scans the configured part of the local file system for encrypted license
* files, read 'em and retrieve all the licensing {@linkplain Condition}s they
* declare.
* files, reads them and retrieves all the licensing {@linkplain Condition}s
* they declare.
* </p>
*
* @since 2.1
*/
public abstract class LocalConditions implements MinedConditions {

private final ConditionMiningTarget id;
private final MiningEquipment equipment;
private final PassageFileExtension scope;
public abstract class LocalConditions extends BaseLocalConditions {

protected LocalConditions(ConditionMiningTarget id, MiningEquipment equipment, PassageFileExtension scope) {
String cls = getClass().getSimpleName();
Objects.requireNonNull(id, cls + "::id"); //$NON-NLS-1$
Objects.requireNonNull(equipment, cls + "::equipment"); //$NON-NLS-1$
Objects.requireNonNull(scope, cls + "::scope"); //$NON-NLS-1$
this.id = id;
this.equipment = equipment;
this.scope = scope;
super(id, equipment, scope);
}

protected LocalConditions(ConditionMiningTarget id, MiningEquipment equipment) {
this(id, equipment, new PassageFileExtension.LicenseEncrypted());
}

@Override
public final ConditionMiningTarget id() {
return id;
}

@Override
public final ServiceInvocationResult<Collection<ConditionPack>> all(LicensedProduct product) {
try {
Collection<Path> licenses = licenses(product);
if (licenses.isEmpty()) {
return noLicenses(product);
}
return equipment.tool(product, id).mine(licenses);
} catch (LicensingException e) {
return new BaseServiceInvocationResult<Collection<ConditionPack>>( //
new Trouble(//
new ServiceFailedOnInfrastructureDenial(), //
ConditionMiningMessages.getString("LocalConditions.failed"), //$NON-NLS-1$
e));
}
}

private ServiceInvocationResult<Collection<ConditionPack>> noLicenses(LicensedProduct product) {
return new BaseServiceInvocationResult<Collection<ConditionPack>>(//
new BaseDiagnostic(//
Collections.emptyList(), //
Collections.singletonList(//
new Trouble(//
new NoLicenses(), //
String.format(//
ConditionMiningMessages.getString("LocalConditions.no_licenses"), //$NON-NLS-1$
base(product).get().toAbsolutePath())))//
), //
Collections.emptyList()//
);
}

private Collection<Path> licenses(LicensedProduct product) throws LicensingException {
protected Collection<Path> licenses(LicensedProduct product) throws LicensingException {
return new FileCollection(base(product), scope).get();
}

protected abstract Supplier<Path> base(LicensedProduct product);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2025 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.io;

import java.nio.file.Path;
import java.util.Collection;

import org.eclipse.passage.lic.api.LicensingException;

/**
* Collects regular files of the given {@code extension} starting from the given
* {@code base} path recursively. No particular order is guaranteed.
*
* @since 4.1
*/
public interface CollectedFiles {

Collection<Path> get() throws LicensingException;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020, 2022 ArSysOp
* Copyright (c) 2020, 2025 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
Expand All @@ -10,6 +10,7 @@
* Contributors:
* ArSysOp - initial API and implementation
* Hannes Wellmann (IILS mbH) - Simplify IO operations(#1071)
* ArSysOp - evolved to be dispensable (#1482)
*******************************************************************************/
package org.eclipse.passage.lic.base.io;

Expand All @@ -27,26 +28,31 @@
import org.eclipse.passage.lic.internal.base.i18n.BaseMessages;

/**
* Collects regular files of the given {@code extension} starting from the given
* {@code base} path recursively. No particular order is guaranteed.
* <p>
* Does not tolerate {@code base} directory or file absence.
* </p>
*
* <p>
* These is no obligations as to how many times {@code base} supplier to be
* called, so make sure your implementation is system-wide idempotent.
* </p>
*
* @since 2.1
*/
public final class FileCollection {
public final class FileCollection implements CollectedFiles {

private final Supplier<Path> base;
private final PassageFileExtension extension;

/**
* @param base expected to supply path to an existing directory
* @param base expected to supply path to an existing directory or file
*/
public FileCollection(Supplier<Path> base, PassageFileExtension extension) {
Objects.requireNonNull(base, "FileCollection::base path"); //$NON-NLS-1$
Objects.requireNonNull(extension, "FileCollection::extension"); //$NON-NLS-1$
this.base = base;
this.extension = extension;
this.base = Objects.requireNonNull(base, "FileCollection::base path"); //$NON-NLS-1$
this.extension = Objects.requireNonNull(extension, "FileCollection::extension"); //$NON-NLS-1$
}

@Override
public Collection<Path> get() throws LicensingException {
try (Stream<Path> all = files(base.get())) {
return filtered(all);
Expand Down
Loading

0 comments on commit baea7a1

Please sign in to comment.