Skip to content

Commit

Permalink
Merge pull request #296 from eclipse-passage/565011
Browse files Browse the repository at this point in the history
Bug 565011 rebuild the core of condition expression evaluation
  • Loading branch information
eparovyshnaya authored Jul 9, 2020
2 parents b369027 + 14f1b73 commit ea3e2b7
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*******************************************************************************/
package org.eclipse.passage.lic.internal.api;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.PermissionEmittersRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluatorsRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionPasringRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionTokenAssessorsRegistry;
import org.eclipse.passage.lic.internal.api.conditions.mining.ConditionTransportRegistry;
import org.eclipse.passage.lic.internal.api.conditions.mining.MinedConditionsRegistry;
import org.eclipse.passage.lic.internal.api.io.KeyKeeperRegistry;
Expand All @@ -33,4 +37,12 @@ public interface AccessCycleConfiguration {

ConditionTransportRegistry transports();

PermissionEmittersRegistry permissionEmitters();

ExpressionPasringRegistry expressionParsers();

ExpressionEvaluatorsRegistry expressionEvaluators();

ExpressionTokenAssessorsRegistry expressionAssessors();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* 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.lic.internal.api.registry;

import java.util.Objects;

public final class AggregativeServiceId<I1 extends ServiceId, I2 extends ServiceId> implements ServiceId {

private final I1 first;
private final I2 second;

public AggregativeServiceId(I1 first, I2 second) {
this.first = first;
this.second = second;
}

@Override
public boolean equals(Object object) {
if (!AggregativeServiceId.class.isInstance(object)) {
return false;
}
@SuppressWarnings("rawtypes")
AggregativeServiceId another = (AggregativeServiceId) object;
return first.equals(another.first) && second.equals(another.second);
}

@Override
public int hashCode() {
return Objects.hash(first, second);
}

@Override
public String toString() {
return String.format("%s/%s", first, second); //$NON-NLS-1$
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
import org.eclipse.passage.lic.internal.api.AccessCycleConfiguration;
import org.eclipse.passage.lic.internal.api.LicensedProduct;
import org.eclipse.passage.lic.internal.api.LicensingException;
import org.eclipse.passage.lic.internal.api.conditions.EvaluationType;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.PermissionEmittingService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.PermissionEmittersRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluatorsRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionPasringRegistry;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionPasringService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionTokenAssessmentService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionTokenAssessorsRegistry;
import org.eclipse.passage.lic.internal.api.conditions.mining.ConditionTransport;
import org.eclipse.passage.lic.internal.api.conditions.mining.ConditionTransportRegistry;
import org.eclipse.passage.lic.internal.api.conditions.mining.ContentType;
Expand All @@ -32,6 +42,9 @@
import org.eclipse.passage.lic.internal.api.registry.StringServiceId;
import org.eclipse.passage.lic.internal.api.requirements.ResolvedRequirements;
import org.eclipse.passage.lic.internal.api.requirements.ResolvedRequirementsRegistry;
import org.eclipse.passage.lic.internal.base.conditions.evaluation.BasePermissionEmittingService;
import org.eclipse.passage.lic.internal.base.conditions.evaluation.AndsProtocolExpressionParseService;
import org.eclipse.passage.lic.internal.base.conditions.evaluation.SimpleMapExpressionEvaluationService;
import org.eclipse.passage.lic.internal.base.conditions.mining.MiningEquipment;
import org.eclipse.passage.lic.internal.base.conditions.mining.UserHomeResidentConditions;
import org.eclipse.passage.lic.internal.base.registry.ReadOnlyRegistry;
Expand All @@ -56,6 +69,10 @@ final class SealedAccessCycleConfiguration implements AccessCycleConfiguration {
private final Registry<ContentType, ConditionTransport> transports;
private final Registry<LicensedProduct, StreamCodec> codecs;
private final Registry<LicensedProduct, KeyKeeper> keys;
private final Registry<StringServiceId, PermissionEmittingService> emitters;
private final Registry<ExpressionProtocol, ExpressionPasringService> expressionParsers;
private final Registry<ExpressionProtocol, ExpressionEvaluationService> expressionEvaluators;
private final Registry<EvaluationType, ExpressionTokenAssessmentService> tokenEvaluators;

SealedAccessCycleConfiguration(Supplier<LicensedProduct> product) {
alarm = LicensingException::printStackTrace;
Expand All @@ -77,14 +94,33 @@ final class SealedAccessCycleConfiguration implements AccessCycleConfiguration {
));
transports = new ReadOnlyRegistry<>(Arrays.asList(//
new JsonConditionTransport(), //
new XmiConditionTransport() // FIXME: does not do `writing`
new XmiConditionTransport() //
));
codecs = new ReadOnlyRegistry<>(Arrays.asList(//
new BcStreamCodec(product) //
));
keys = new ReadOnlyRegistry<>(Arrays.asList(//
new BundleKeyKeeper(product, bundle()) //
));
emitters = new ReadOnlyRegistry<>(Arrays.asList(//
new BasePermissionEmittingService(//
expressionParsers(), //
expressionAssessors(), //
expressionEvaluators())//
));
expressionParsers = new ReadOnlyRegistry<>(Arrays.asList(//
new AndsProtocolExpressionParseService()//
));
expressionEvaluators = new ReadOnlyRegistry<>(Arrays.asList(//
new SimpleMapExpressionEvaluationService()//
));
tokenEvaluators = new ReadOnlyRegistry<>(Arrays.asList(//
// FIXME: OSHI-based evaluator for EvaluationType.Hardware
));
}

private Bundle bundle() {
return FrameworkUtil.getBundle(getClass());
}

@Override
Expand Down Expand Up @@ -112,8 +148,24 @@ public ConditionTransportRegistry transports() {
return () -> transports;
}

private Bundle bundle() {
return FrameworkUtil.getBundle(getClass());
@Override
public PermissionEmittersRegistry permissionEmitters() {
return () -> emitters;
}

@Override
public ExpressionPasringRegistry expressionParsers() {
return () -> expressionParsers;
}

@Override
public ExpressionEvaluatorsRegistry expressionEvaluators() {
return () -> expressionEvaluators;
}

@Override
public ExpressionTokenAssessorsRegistry expressionAssessors() {
return () -> tokenEvaluators;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,22 @@

import java.util.Optional;

import org.eclipse.passage.lic.api.tests.fakes.FakeConditionExpressionEvaluator;
import org.eclipse.passage.lic.api.tests.fakes.FakeConditionExpressionParser;
import org.eclipse.passage.lic.api.tests.fakes.FakeConditionTransport;
import org.eclipse.passage.lic.api.tests.fakes.FakeExpressionTokenAssessmentService;
import org.eclipse.passage.lic.api.tests.fakes.FakeKeyKeeper;
import org.eclipse.passage.lic.api.tests.fakes.FakeMinedConditions;
import org.eclipse.passage.lic.api.tests.fakes.FakeResolvedRequirements;
import org.eclipse.passage.lic.api.tests.fakes.FakeStreamCodec;
import org.eclipse.passage.lic.internal.api.AccessCycleConfiguration;
import org.eclipse.passage.lic.internal.api.Framework;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
import org.eclipse.passage.lic.internal.api.conditions.mining.ContentType;
import org.eclipse.passage.lic.internal.api.registry.Registry;
import org.eclipse.passage.lic.internal.api.registry.Service;
import org.eclipse.passage.lic.internal.api.registry.ServiceId;
import org.junit.Ignore;
import org.junit.Test;

/**
Expand Down Expand Up @@ -144,6 +149,64 @@ public final void hasTransportForXml() {
assertTrue(config().transports().get().hasService(new ContentType.Xml()));
}

@Test
public final void canParseConditionExpressions() {
assertServiceRegistryIsFunctional(config().expressionParsers().get());
}

@Test
public final void prohibitsExpressionParseServicesExtension() {
assertTrue(readOnly(config().expressionParsers().get()));
}

@Test
public final void prohibitsInjectionIntoExpressionParseServices() {
assertServiceInjectionsIsProhibited(config().expressionParsers().get(), new FakeConditionExpressionParser());
}

@Test
public final void hasParserForDefaultExpressionFormat() {
assertTrue(config().expressionParsers().get().hasService(new ExpressionProtocol.Default()));
}

@Test
public final void canEvaluateConditionExpressions() {
assertServiceRegistryIsFunctional(config().expressionEvaluators().get());
}

@Test
public final void prohibitsExpressionEvaluationServicesExtension() {
assertTrue(readOnly(config().expressionEvaluators().get()));
}

@Test
public final void prohibitsInjectionIntoExpressionEvaluationServices() {
assertServiceInjectionsIsProhibited(config().expressionEvaluators().get(),
new FakeConditionExpressionEvaluator());
}

@Test
public final void hasEvaluatorForDefaultExpressionFormat() {
assertTrue(config().expressionEvaluators().get().hasService(new ExpressionProtocol.Default()));
}

@Test
@Ignore // yet to be implemented (OSHI-based)
public final void canAssessConditionExpressionsSegment() {
assertServiceRegistryIsFunctional(config().expressionAssessors().get());
}

@Test
public final void prohibitsExpressionSegmentAssessmentServicesExtension() {
assertTrue(readOnly(config().expressionAssessors().get()));
}

@Test
public final void prohibitsInjectionIntoSegmentAssessmentServices() {
assertServiceInjectionsIsProhibited(config().expressionAssessors().get(),
new FakeExpressionTokenAssessmentService());
}

private <I extends ServiceId, S extends Service<I>> void assertServiceRegistryIsFunctional(
Registry<I, S> registry) {
assertNotNull(registry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*******************************************************************************
* 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.lic.api.tests.conditions.evaluation;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.Emission;
import org.junit.Test;

@SuppressWarnings("restriction")
public abstract class EmissionContractTest {

@Test(expected = Exception.class)
public void failedEmissionCannotHoldPermission() {
Emission failure = failed();
assumeTrue(failure.failed());
failure.permissions();
}

@Test
public void successfulEmissionMustHoldPermission() {
Emission success = successful();
assumeFalse(success.failed());
assertNotNull(success.permissions());
}

@Test
public void failedEmissionMustHoldDiagnosis() {
Emission failure = failed();
assumeTrue(failure.failed());
assertNotNull(failure.failureDiagnostic());
}

@Test(expected = Exception.class)
public void successfulEmissionCannotHoldDiagnosis() {
Emission success = successful();
assumeFalse(success.failed());
success.failureDiagnostic();

}

protected abstract Emission failed();

protected abstract Emission successful();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*******************************************************************************
* 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.lic.api.tests.conditions.evaluation;

import org.eclipse.passage.lic.api.tests.registry.ServiceIdContractTest;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
import org.eclipse.passage.lic.internal.api.registry.ServiceId;

@SuppressWarnings("restriction")
public class ExpressionFormatContractTest extends ServiceIdContractTest {

@Override
protected ServiceId ofSameData() {
return new ExpressionProtocol.Of("abra-cadabra"); //$NON-NLS-1$
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*******************************************************************************
* 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.lic.api.tests.fakes;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionTokenAssessmentService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;

@SuppressWarnings("restriction")
public class FakeConditionExpressionEvaluator implements ExpressionEvaluationService {

@Override
public ExpressionProtocol id() {
return new ExpressionProtocol.Of("brand-new-format"); //$NON-NLS-1$
}

@Override
public boolean evaluate(ParsedExpression expression, ExpressionTokenAssessmentService tokenEvaluator) {
throw new UnsupportedOperationException();
}

}
Loading

0 comments on commit ea3e2b7

Please sign in to comment.