Skip to content

Commit

Permalink
made placeholder resolver definitions in AbstractPlaceholderSubstitut…
Browse files Browse the repository at this point in the history
…ionPreEnforcer extenable via inheritance

* made PoliciesPlaceholderSubstitutionPreEnforcer and ThingsPlaceholderSubstitutionPreEnforcer not final to allow inheritance

Signed-off-by: Thomas Jaeckle <thomas.jaeckle@bosch.io>
  • Loading branch information
thjaeckle committed Jun 29, 2022
1 parent f19c99a commit bfec791
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import javax.annotation.Nullable;

import org.eclipse.ditto.internal.utils.akka.logging.DittoLoggerFactory;
import org.eclipse.ditto.internal.utils.akka.logging.ThreadSafeDittoLogger;
import org.eclipse.ditto.internal.utils.cache.CacheFactory;
import org.eclipse.ditto.internal.utils.cache.config.DefaultCacheConfig;
import org.eclipse.ditto.internal.utils.cache.entry.Entry;
Expand All @@ -32,7 +33,6 @@
import org.eclipse.ditto.policies.api.PoliciesMessagingConstants;
import org.eclipse.ditto.policies.enforcement.config.DefaultEnforcementConfig;
import org.eclipse.ditto.policies.model.PolicyId;
import org.slf4j.Logger;

import com.github.benmanes.caffeine.cache.AsyncCacheLoader;

Expand All @@ -46,7 +46,9 @@
*/
public final class DefaultPolicyEnforcerProvider implements PolicyEnforcerProvider {

private static Logger LOGGER = DittoLoggerFactory.getThreadSafeLogger(DefaultPolicyEnforcerProvider.class);
private static final ThreadSafeDittoLogger LOGGER =
DittoLoggerFactory.getThreadSafeLogger(DefaultPolicyEnforcerProvider.class);

private final AsyncCacheLoader<EnforcementCacheKey, Entry<PolicyEnforcer>> policyEnforcerCacheLoader;
private final MessageDispatcher enforcementCacheDispatcher;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ public abstract class AbstractPlaceholderSubstitutionPreEnforcer implements PreE
private final HeaderBasedPlaceholderSubstitutionAlgorithm substitutionAlgorithm;
private final SubstitutionStrategyRegistry substitutionStrategyRegistry;

protected AbstractPlaceholderSubstitutionPreEnforcer(final HeaderBasedPlaceholderSubstitutionAlgorithm substitutionAlgorithm,
protected AbstractPlaceholderSubstitutionPreEnforcer(
final SubstitutionStrategyRegistry substitutionStrategyRegistry) {

this.substitutionAlgorithm = substitutionAlgorithm;
this.substitutionAlgorithm = HeaderBasedPlaceholderSubstitutionAlgorithm.newInstance(
createReplacementDefinitions()
);
this.substitutionStrategyRegistry = substitutionStrategyRegistry;
}

Expand All @@ -65,7 +67,15 @@ public CompletionStage<Signal<?>> apply(final Signal<?> signal) {
}
}

protected static Map<String, Function<DittoHeaders, String>> createDefaultReplacementDefinitions() {
/**
* Creates the replacement definitions as map of placeholder as key and function as value for determining the
* placeholder based on {@link DittoHeaders} of a processed {@link Signal}.
* May be overwritten by subclasses in order to provide additional replacement definitions.
*
* @return the default replacement definitions resolving placeholders from {@link DittoHeaders} of a processed
* {@link Signal}
*/
protected Map<String, Function<DittoHeaders, String>> createReplacementDefinitions() {
final Map<String, Function<DittoHeaders, String>> defaultReplacementDefinitions = new LinkedHashMap<>();
defaultReplacementDefinitions.put(SubjectIdReplacementDefinition.REPLACER_NAME,
SubjectIdReplacementDefinition.getInstance());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public final class SubjectIdReplacementDefinition implements Function<DittoHeade
* The name of the replacer.
*/
public static final String REPLACER_NAME = "request:subjectId";

/**
* The legacy name of the replacer which still is supported.
*/
public static final String LEGACY_REPLACER_NAME = "request.subjectId";

private static final SubjectIdReplacementDefinition INSTANCE = new SubjectIdReplacementDefinition();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,19 @@
*/
package org.eclipse.ditto.policies.service.enforcement.pre;

import static java.util.Objects.requireNonNull;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.policies.enforcement.placeholders.AbstractPlaceholderSubstitutionPreEnforcer;
import org.eclipse.ditto.policies.enforcement.placeholders.HeaderBasedPlaceholderSubstitutionAlgorithm;
import org.eclipse.ditto.policies.enforcement.placeholders.strategies.SubstitutionStrategyRegistry;

import akka.actor.ActorSystem;

/**
* Policies specific Pre-Enforcer which applies substitution of placeholders on a policy command
* (subtype of {@link org.eclipse.ditto.base.model.signals.Signal}) based on its {@link DittoHeaders}.
*
* May be subclassed in order to provide additional/different {@link #createReplacementDefinitions()} by overwriting
* that method.
*/
public final class PoliciesPlaceholderSubstitutionPreEnforcer extends AbstractPlaceholderSubstitutionPreEnforcer {
public class PoliciesPlaceholderSubstitutionPreEnforcer extends AbstractPlaceholderSubstitutionPreEnforcer {

/**
* Constructs a new instance of PoliciesPlaceholderSubstitutionPreEnforcer extension.
Expand All @@ -38,61 +33,7 @@ public final class PoliciesPlaceholderSubstitutionPreEnforcer extends AbstractPl
*/
@SuppressWarnings("unused")
public PoliciesPlaceholderSubstitutionPreEnforcer(final ActorSystem actorSystem) {
super(
HeaderBasedPlaceholderSubstitutionAlgorithm.newInstance(createDefaultReplacementDefinitions()),
PolicySubstitutionStrategyRegistry.newInstance()
);
}

private PoliciesPlaceholderSubstitutionPreEnforcer(
final HeaderBasedPlaceholderSubstitutionAlgorithm substitutionAlgorithm,
final SubstitutionStrategyRegistry substitutionStrategyRegistry) {
super(substitutionAlgorithm, substitutionStrategyRegistry);
}

/**
* Creates a new instance with default replacement definitions.
*
* @return the created instance.
* @see #newExtendedInstance(java.util.Map)
*/
public static PoliciesPlaceholderSubstitutionPreEnforcer newInstance() {
final Map<String, Function<DittoHeaders, String>> defaultReplacementDefinitions =
createDefaultReplacementDefinitions();

return createInstance(defaultReplacementDefinitions);
super(PolicySubstitutionStrategyRegistry.newInstance());
}

/**
* Creates a new instance with default replacement definitions, extended with
* {@code additionalReplacementDefinitions}.
*
* @param additionalReplacementDefinitions the additional replacement definitions.
* @return the created instance.
* @see #newInstance()
*/
public static PoliciesPlaceholderSubstitutionPreEnforcer newExtendedInstance(
final Map<String, Function<DittoHeaders, String>> additionalReplacementDefinitions) {
requireNonNull(additionalReplacementDefinitions);

final Map<String, Function<DittoHeaders, String>> defaultReplacementDefinitions =
createDefaultReplacementDefinitions();

final Map<String, Function<DittoHeaders, String>> allReplacementDefinitions =
new LinkedHashMap<>();
allReplacementDefinitions.putAll(defaultReplacementDefinitions);
allReplacementDefinitions.putAll(additionalReplacementDefinitions);

return createInstance(allReplacementDefinitions);
}

private static PoliciesPlaceholderSubstitutionPreEnforcer createInstance(
final Map<String, Function<DittoHeaders, String>> replacementDefinitions) {
final HeaderBasedPlaceholderSubstitutionAlgorithm algorithm =
HeaderBasedPlaceholderSubstitutionAlgorithm.newInstance(replacementDefinitions);
final SubstitutionStrategyRegistry substitutionStrategyRegistry =
PolicySubstitutionStrategyRegistry.newInstance();

return new PoliciesPlaceholderSubstitutionPreEnforcer(algorithm, substitutionStrategyRegistry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import org.eclipse.ditto.policies.model.Resource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import akka.actor.ActorSystem;

/**
* Abstract base class for test of concrete implementations of
Expand Down Expand Up @@ -55,7 +58,7 @@ abstract class AbstractPolicySubstitutionStrategyTestBase {

@Before
public void init() {
substitution = PoliciesPlaceholderSubstitutionPreEnforcer.newInstance();
substitution = new PoliciesPlaceholderSubstitutionPreEnforcer(Mockito.mock(ActorSystem.class));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
package org.eclipse.ditto.policies.service.enforcement.pre;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mutabilitydetector.unittesting.AllowedReason.provided;
import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areImmutable;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
Expand All @@ -29,8 +27,6 @@
import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.base.model.headers.WithDittoHeaders;
import org.eclipse.ditto.base.model.signals.Signal;
import org.eclipse.ditto.policies.enforcement.placeholders.HeaderBasedPlaceholderSubstitutionAlgorithm;
import org.eclipse.ditto.policies.enforcement.placeholders.strategies.SubstitutionStrategyRegistry;
import org.eclipse.ditto.policies.model.EffectedPermissions;
import org.eclipse.ditto.policies.model.Label;
import org.eclipse.ditto.policies.model.PolicyId;
Expand All @@ -42,6 +38,9 @@
import org.eclipse.ditto.policies.model.signals.commands.modify.ModifySubject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import akka.actor.ActorSystem;

/**
* Tests specifics of {@link PoliciesPlaceholderSubstitutionPreEnforcer}.
Expand All @@ -65,14 +64,7 @@ public final class PoliciesPlaceholderSubstitutionPreEnforcerTest {

@Before
public void init() {
underTest = PoliciesPlaceholderSubstitutionPreEnforcer.newInstance();
}

@Test
public void assertImmutability() {
assertInstancesOf(PoliciesPlaceholderSubstitutionPreEnforcer.class, areImmutable(),
provided(HeaderBasedPlaceholderSubstitutionAlgorithm.class, SubstitutionStrategyRegistry.class)
.areAlsoImmutable());
underTest = new PoliciesPlaceholderSubstitutionPreEnforcer(Mockito.mock(ActorSystem.class));
}

@Test
Expand All @@ -93,7 +85,15 @@ public void applyWithHandledCommandReturnsTheReplacedCommandInstanceWhenCustomPl
Collections.singletonMap(customPlaceholderKey,
dittoHeaders -> dittoHeaders.get(CUSTOM_HEADER_KEY));
final PoliciesPlaceholderSubstitutionPreEnforcer extendedPlaceholderSubstitution =
PoliciesPlaceholderSubstitutionPreEnforcer.newExtendedInstance(additionalReplacementDefinitions);
new PoliciesPlaceholderSubstitutionPreEnforcer(Mockito.mock(ActorSystem.class)) {
@Override
protected Map<String, Function<DittoHeaders, String>> createReplacementDefinitions() {
final Map<String, Function<DittoHeaders, String>> definitions = super.createReplacementDefinitions();
final Map<String, Function<DittoHeaders, String>> mergedDefinitions = new HashMap<>(definitions);
mergedDefinitions.putAll(additionalReplacementDefinitions);
return mergedDefinitions;
}
};
final ModifySubject commandWithoutPlaceholders = ModifySubject.of(PolicyId.of("org.eclipse.ditto:my-policy"),
Label.of("my-label"), Subject.newInstance("{{ " + customPlaceholderKey + " }}",
SubjectType.GENERATED), DITTO_HEADERS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,19 @@
*/
package org.eclipse.ditto.things.service.enforcement.pre;

import static java.util.Objects.requireNonNull;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.policies.enforcement.placeholders.AbstractPlaceholderSubstitutionPreEnforcer;
import org.eclipse.ditto.policies.enforcement.placeholders.HeaderBasedPlaceholderSubstitutionAlgorithm;
import org.eclipse.ditto.policies.enforcement.placeholders.strategies.SubstitutionStrategyRegistry;

import akka.actor.ActorSystem;

/**
* Things specific Pre-Enforcer which applies substitution of placeholders on a thing command
* (subtype of {@link org.eclipse.ditto.base.model.signals.Signal}) based on its {@link DittoHeaders}.
*
* May be subclassed in order to provide additional/different {@link #createReplacementDefinitions()} by overwriting
* that method.
*/
public final class ThingsPlaceholderSubstitutionPreEnforcer extends AbstractPlaceholderSubstitutionPreEnforcer {
public class ThingsPlaceholderSubstitutionPreEnforcer extends AbstractPlaceholderSubstitutionPreEnforcer {

/**
* Constructs a new instance of ThingsPlaceholderSubstitutionPreEnforcer extension.
Expand All @@ -38,61 +33,7 @@ public final class ThingsPlaceholderSubstitutionPreEnforcer extends AbstractPlac
*/
@SuppressWarnings("unused")
public ThingsPlaceholderSubstitutionPreEnforcer(final ActorSystem actorSystem) {
super(
HeaderBasedPlaceholderSubstitutionAlgorithm.newInstance(createDefaultReplacementDefinitions()),
ThingSubstitutionStrategyRegistry.newInstance()
);
}

private ThingsPlaceholderSubstitutionPreEnforcer(
final HeaderBasedPlaceholderSubstitutionAlgorithm substitutionAlgorithm,
final SubstitutionStrategyRegistry substitutionStrategyRegistry) {
super(substitutionAlgorithm, substitutionStrategyRegistry);
}

/**
* Creates a new instance with default replacement definitions.
*
* @return the created instance.
* @see #newExtendedInstance(java.util.Map)
*/
public static ThingsPlaceholderSubstitutionPreEnforcer newInstance() {
final Map<String, Function<DittoHeaders, String>> defaultReplacementDefinitions =
createDefaultReplacementDefinitions();

return createInstance(defaultReplacementDefinitions);
super(ThingSubstitutionStrategyRegistry.newInstance());
}

/**
* Creates a new instance with default replacement definitions, extended with
* {@code additionalReplacementDefinitions}.
*
* @param additionalReplacementDefinitions the additional replacement definitions.
* @return the created instance.
* @see #newInstance()
*/
public static ThingsPlaceholderSubstitutionPreEnforcer newExtendedInstance(
final Map<String, Function<DittoHeaders, String>> additionalReplacementDefinitions) {
requireNonNull(additionalReplacementDefinitions);

final Map<String, Function<DittoHeaders, String>> defaultReplacementDefinitions =
createDefaultReplacementDefinitions();

final Map<String, Function<DittoHeaders, String>> allReplacementDefinitions =
new LinkedHashMap<>();
allReplacementDefinitions.putAll(defaultReplacementDefinitions);
allReplacementDefinitions.putAll(additionalReplacementDefinitions);

return createInstance(allReplacementDefinitions);
}

private static ThingsPlaceholderSubstitutionPreEnforcer createInstance(
final Map<String, Function<DittoHeaders, String>> replacementDefinitions) {
final HeaderBasedPlaceholderSubstitutionAlgorithm algorithm =
HeaderBasedPlaceholderSubstitutionAlgorithm.newInstance(replacementDefinitions);
final SubstitutionStrategyRegistry substitutionStrategyRegistry =
ThingSubstitutionStrategyRegistry.newInstance();

return new ThingsPlaceholderSubstitutionPreEnforcer(algorithm, substitutionStrategyRegistry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
import org.eclipse.ditto.things.model.signals.commands.modify.CreateThing;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import akka.actor.ActorSystem;

/**
* Tests {@link CreateThingSubstitutionStrategy} in context of
Expand Down Expand Up @@ -72,7 +75,7 @@ public class CreateThingSubstitutionStrategyTest {

@Before
public void init() {
substitution = ThingsPlaceholderSubstitutionPreEnforcer.newInstance();
substitution = new ThingsPlaceholderSubstitutionPreEnforcer(Mockito.mock(ActorSystem.class));
}

@Test
Expand Down

0 comments on commit bfec791

Please sign in to comment.