Skip to content

Commit

Permalink
Convert DittoExtensionPoint to an interface
Browse files Browse the repository at this point in the history
* Extension points are not meant to contain logic which should be reused,
  they should define a code interface which should be available at the place
  where the extension is used
* Also made all implementations final

Signed-off-by: Yannic Klem <Yannic.Klem@bosch.io>
  • Loading branch information
Yannic92 committed May 6, 2022
1 parent 466f821 commit 4fdfd4a
Show file tree
Hide file tree
Showing 32 changed files with 127 additions and 293 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,12 @@
*
* @since 3.0.0
*/
public abstract class DittoExtensionPoint implements Extension {

protected final ActorSystem actorSystem;

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected DittoExtensionPoint(final ActorSystem actorSystem) {
this.actorSystem = actorSystem;
}
public interface DittoExtensionPoint extends Extension {

/**
* @param <T> the class of the extension for which an implementation should be loaded.
*/
protected static final class ExtensionId<T extends Extension> extends AbstractExtensionId<T> {
final class ExtensionId<T extends Extension> extends AbstractExtensionId<T> {

private final String implementation;
private final Class<T> parentClass;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import org.eclipse.ditto.gateway.service.security.authentication.jwt.JwtAuthenticationFactory;
import org.eclipse.ditto.gateway.service.security.authentication.jwt.JwtAuthenticationProvider;
import org.eclipse.ditto.gateway.service.security.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import org.eclipse.ditto.gateway.service.util.config.DittoGatewayConfig;
import org.eclipse.ditto.gateway.service.util.config.security.AuthenticationConfig;
import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -35,7 +37,7 @@
/**
* Ditto's default factory for building authentication directives.
*/
public final class DittoGatewayAuthenticationDirectiveFactory extends GatewayAuthenticationDirectiveFactory {
public final class DittoGatewayAuthenticationDirectiveFactory implements GatewayAuthenticationDirectiveFactory {

private static final Logger LOGGER = LoggerFactory.getLogger(DittoGatewayAuthenticationDirectiveFactory.class);
private static final String AUTHENTICATION_DISPATCHER_NAME = "authentication-dispatcher";
Expand All @@ -46,8 +48,8 @@ public final class DittoGatewayAuthenticationDirectiveFactory extends GatewayAut
@Nullable private GatewayAuthenticationDirective gatewayWsAuthenticationDirective;

public DittoGatewayAuthenticationDirectiveFactory(final ActorSystem actorSystem) {
super(actorSystem);
authConfig = getAuthConfig(actorSystem);
authConfig = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(actorSystem.settings().config()))
.getAuthenticationConfig();
authenticationDispatcher = actorSystem.dispatchers().lookup(AUTHENTICATION_DISPATCHER_NAME);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,21 @@
/**
* Factory for authentication directives.
*/
public abstract class GatewayAuthenticationDirectiveFactory extends DittoExtensionPoint {

protected static final String AUTHENTICATION_DISPATCHER_NAME = "authentication-dispatcher";

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected GatewayAuthenticationDirectiveFactory(final ActorSystem actorSystem) {
super(actorSystem);
}
public interface GatewayAuthenticationDirectiveFactory extends DittoExtensionPoint {

/**
* Builds the {@link GatewayAuthenticationDirective authentication directive} that should be used for HTTP API.
*
* @return The built {@link GatewayAuthenticationDirective authentication directive}.
*/
public abstract GatewayAuthenticationDirective buildHttpAuthentication(
JwtAuthenticationFactory jwtAuthenticationFactory);
GatewayAuthenticationDirective buildHttpAuthentication(JwtAuthenticationFactory jwtAuthenticationFactory);

/**
* Builds the {@link GatewayAuthenticationDirective authentication directive} that should be used for WebSocket API.
*
* @return The built {@link GatewayAuthenticationDirective authentication directive}.
*/
public abstract GatewayAuthenticationDirective buildWsAuthentication(
JwtAuthenticationFactory jwtAuthenticationFactory);
GatewayAuthenticationDirective buildWsAuthentication(JwtAuthenticationFactory jwtAuthenticationFactory);

/**
* Loads the implementation of {@code GatewayAuthenticationDirectiveFactory} which is configured for the
Expand All @@ -61,15 +50,13 @@ public abstract GatewayAuthenticationDirective buildWsAuthentication(
* @throws NullPointerException if {@code actorSystem} is {@code null}.
* @since 3.0.0
*/
public static GatewayAuthenticationDirectiveFactory get(final ActorSystem actorSystem) {
static GatewayAuthenticationDirectiveFactory get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = getAuthConfig(actorSystem).getGatewayAuthenticationDirectiveFactory();

final AuthenticationConfig authenticationConfig =
DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(actorSystem.settings().config()))
.getAuthenticationConfig();
final var implementation = authenticationConfig.getGatewayAuthenticationDirectiveFactory();
return new ExtensionId<>(implementation, GatewayAuthenticationDirectiveFactory.class).get(actorSystem);
}

protected static AuthenticationConfig getAuthConfig(final ActorSystem actorSystem) {
return DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getAuthenticationConfig();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@
* Provider for custom routes.
* You can distinguish between routes for unauthorized access and authorized access.
*/
public abstract class CustomApiRoutesProvider extends DittoExtensionPoint {

protected CustomApiRoutesProvider(final ActorSystem actorSystem) {
super(actorSystem);
}
public interface CustomApiRoutesProvider extends DittoExtensionPoint {

/**
* Provides a custom route for unauthorized access.
Expand All @@ -41,8 +37,7 @@ protected CustomApiRoutesProvider(final ActorSystem actorSystem) {
* @param correlationId the correlation ID.
* @return custom route for unauthorized access.
*/
public abstract Route unauthorized(RouteBaseProperties routeBaseProperties, JsonSchemaVersion version,
CharSequence correlationId);
Route unauthorized(RouteBaseProperties routeBaseProperties, JsonSchemaVersion version, CharSequence correlationId);

/**
* Provides a custom route for authorized access.
Expand All @@ -51,7 +46,7 @@ public abstract Route unauthorized(RouteBaseProperties routeBaseProperties, Json
* @param headers headers of the request.
* @return custom route for authorized access.
*/
public abstract Route authorized(RouteBaseProperties routeBaseProperties, DittoHeaders headers);
Route authorized(RouteBaseProperties routeBaseProperties, DittoHeaders headers);

/**
* Loads the implementation of {@code CustomApiRoutesProvider} which is configured for the {@code ActorSystem}.
Expand All @@ -61,7 +56,7 @@ public abstract Route unauthorized(RouteBaseProperties routeBaseProperties, Json
* @throws NullPointerException if {@code actorSystem} is {@code null}.
* @since 3.0.0
*/
public static CustomApiRoutesProvider get(final ActorSystem actorSystem) {
static CustomApiRoutesProvider get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getHttpConfig().getCustomApiRoutesProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,14 @@
* Extension to add a custom bind flow for HTTP requests.
* @since 3.0.0
*/
public abstract class HttpBindFlowProvider extends DittoExtensionPoint {

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected HttpBindFlowProvider(final ActorSystem actorSystem) {
super(actorSystem);
}
public interface HttpBindFlowProvider extends DittoExtensionPoint {

/**
* Create a bind flow for HTTP requests.
*
* @return flow which processes HTTP requests.
*/
public abstract Flow<HttpRequest, HttpResponse, NotUsed> getFlow(final Route innerRoute);
Flow<HttpRequest, HttpResponse, NotUsed> getFlow(final Route innerRoute);

/**
* Loads the implementation of {@code HttpBindFlowProvider} which is configured for the
Expand All @@ -53,7 +46,7 @@ protected HttpBindFlowProvider(final ActorSystem actorSystem) {
* @return the {@code HttpBindFlowProvider} implementation.
* @throws NullPointerException if {@code actorSystem} is {@code null}.
*/
public static HttpBindFlowProvider get(final ActorSystem actorSystem) {
static HttpBindFlowProvider get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getHttpConfig().getBindFlowProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@

/**
* Default HTTP bind flow provider, which logs the requests.
*
* @since 3.0.0
*/
public class LoggingHttpBindFlowProvider extends HttpBindFlowProvider {
public final class LoggingHttpBindFlowProvider implements HttpBindFlowProvider {

private final ActorSystem actorSystem;

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected LoggingHttpBindFlowProvider(final ActorSystem actorSystem) {
super(actorSystem);
public LoggingHttpBindFlowProvider(final ActorSystem actorSystem) {
this.actorSystem = actorSystem;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
import akka.http.javadsl.server.Route;

@Immutable
public final class NoopCustomApiRoutesProvider extends CustomApiRoutesProvider {
public final class NoopCustomApiRoutesProvider implements CustomApiRoutesProvider {

private static final Route EMPTY_ROUTE = Directives.reject();

public NoopCustomApiRoutesProvider(final ActorSystem actorSystem) {
super(actorSystem);
// No-Op because Extensions need to have constructor accepting the actorSystem.
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
/**
* Null implementation for {@link SseAuthorizationEnforcer}.
*/
public final class NoOpSseAuthorizationEnforcer extends SseAuthorizationEnforcer {
public final class NoOpSseAuthorizationEnforcer implements SseAuthorizationEnforcer {

/**
* @param actorSystem the actor system in which to load the extension.
*/
public NoOpSseAuthorizationEnforcer(final ActorSystem actorSystem) {
super(actorSystem);
//No-Op because extensions need a constructor accepting an actorSystem
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
/**
* Null implementation for {@link SseConnectionSupervisor}.
*/
public final class NoOpSseConnectionSupervisor extends SseConnectionSupervisor {
public final class NoOpSseConnectionSupervisor implements SseConnectionSupervisor {

/**
* @param actorSystem the actor system in which to load the extension.
*/
public NoOpSseConnectionSupervisor(final ActorSystem actorSystem) {
super(actorSystem);
//No-Op because extensions need a constructor accepting an actorSystem
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,19 @@
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.sse.ServerSentEvent;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;

/**
* Sniffer for Server Sent Events that does purposefully nothing.
*/
public class NoOpSseEventSniffer extends SseEventSniffer {
public final class NoOpSseEventSniffer implements SseEventSniffer {

public NoOpSseEventSniffer(final ActorSystem actorSystem) {
super(actorSystem);
}

@Override
public Sink<ServerSentEvent, ?> createSink(final HttpRequest request) {
return Sink.ignore();
//No-Op because extensions need a constructor accepting an actorSystem
}

@Override
public Flow<ServerSentEvent, ServerSentEvent, NotUsed> toAsyncFlow(final HttpRequest request) {
return Flow.create();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,7 @@
* If the authorization check is successful nothing will happen, else a
* {@link org.eclipse.ditto.base.model.exceptions.DittoRuntimeException DittoRuntimeException} is thrown.
*/
public abstract class SseAuthorizationEnforcer extends DittoExtensionPoint {

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected SseAuthorizationEnforcer(final ActorSystem actorSystem) {
super(actorSystem);
}
public interface SseAuthorizationEnforcer extends DittoExtensionPoint {

/**
* Ensures that the establishment of a SSE connection is authorized for the given arguments.
Expand All @@ -46,8 +39,7 @@ protected SseAuthorizationEnforcer(final ActorSystem actorSystem) {
* @return a successful future if validation succeeds or a failed future if validation fails.
* @throws NullPointerException if any argument is {@code null}.
*/
protected abstract CompletionStage<Void> checkAuthorization(RequestContext requestContext,
DittoHeaders dittoHeaders);
CompletionStage<Void> checkAuthorization(RequestContext requestContext, DittoHeaders dittoHeaders);

/**
* Loads the implementation of {@code SseAuthorizationEnforcer} which is configured for the
Expand All @@ -58,7 +50,7 @@ protected abstract CompletionStage<Void> checkAuthorization(RequestContext reque
* @throws NullPointerException if {@code actorSystem} is {@code null}.
* @since 3.0.0
*/
public static SseAuthorizationEnforcer get(final ActorSystem actorSystem) {
static SseAuthorizationEnforcer get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getStreamingConfig().getSseConfig().getAuthorizationEnforcer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,7 @@
/**
* Provides the means to supervise a particular SSE connection.
*/
public abstract class SseConnectionSupervisor extends DittoExtensionPoint implements StreamSupervisor{

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected SseConnectionSupervisor(final ActorSystem actorSystem) {
super(actorSystem);
}
public interface SseConnectionSupervisor extends DittoExtensionPoint, StreamSupervisor{

/**
* Loads the implementation of {@code SseConnectionSupervisor} which is configured for the
Expand All @@ -42,7 +35,7 @@ protected SseConnectionSupervisor(final ActorSystem actorSystem) {
* @throws NullPointerException if {@code actorSystem} is {@code null}.
* @since 3.0.0
*/
public static SseConnectionSupervisor get(final ActorSystem actorSystem) {
static SseConnectionSupervisor get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getStreamingConfig().getSseConfig().getConnectionSupervisor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,36 +30,15 @@
/**
* Functional interface to sniff events over or SSE.
*/
public abstract class SseEventSniffer extends DittoExtensionPoint {

/**
* @param actorSystem the actor system in which to load the extension.
*/
protected SseEventSniffer(final ActorSystem actorSystem) {
super(actorSystem);
}

/**
* Create a receiver for sniffed events.
*
* @param request the HTTP request that started the event stream.
* @return sink to send events into.
*/
protected abstract Sink<ServerSentEvent, ?> createSink(HttpRequest request);
public interface SseEventSniffer extends DittoExtensionPoint {

/**
* Create an async flow for event sniffing.
*
* @param request the HTTP request that started the event stream.
* @return flow to pass events through with a wiretap attached over an async barrier to the sink for sniffed events.
*/
protected Flow<ServerSentEvent, ServerSentEvent, NotUsed> toAsyncFlow(final HttpRequest request) {
return Flow.<ServerSentEvent>create().wireTap(
Flow.<ServerSentEvent>create()
.async()
.to(Sink.lazyCompletionStageSink(() -> CompletableFuture.completedFuture(
createSink(request)))));
}
Flow<ServerSentEvent, ServerSentEvent, NotUsed> toAsyncFlow(final HttpRequest request);

/**
* Loads the implementation of {@code SseEventSniffer} which is configured for the
Expand All @@ -70,7 +49,7 @@ protected Flow<ServerSentEvent, ServerSentEvent, NotUsed> toAsyncFlow(final Http
* @throws NullPointerException if {@code actorSystem} is {@code null}.
* @since 3.0.0
*/
public static SseEventSniffer get(final ActorSystem actorSystem) {
static SseEventSniffer get(final ActorSystem actorSystem) {
checkNotNull(actorSystem, "actorSystem");
final var implementation = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(
actorSystem.settings().config())).getStreamingConfig().getSseConfig().getEventSniffer();
Expand Down
Loading

0 comments on commit 4fdfd4a

Please sign in to comment.