Skip to content

Commit

Permalink
Merge pull request #31746 from vespa-engine/jonmv/provide-filter-on-d…
Browse files Browse the repository at this point in the history
…ata-plane-filters

Jonmv/provide filter on data plane filters
  • Loading branch information
freva committed Jun 28, 2024
2 parents 1b83df1 + 1eae59a commit 35d82c3
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 90 deletions.
22 changes: 14 additions & 8 deletions container-core/abi-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
},
"com.yahoo.component.chain.ChainedComponent" : {
"superClass" : "com.yahoo.component.AbstractComponent",
"interfaces" : [ ],
"interfaces" : [
"com.yahoo.component.chain.model.Chainable"
],
"attributes" : [
"public",
"abstract"
Expand All @@ -32,9 +34,7 @@
"public void <init>(com.yahoo.component.ComponentId)",
"protected void <init>()",
"public void initDependencies(com.yahoo.component.chain.dependencies.Dependencies)",
"public com.yahoo.component.chain.dependencies.Dependencies getDependencies()",
"protected com.yahoo.component.chain.dependencies.Dependencies getDefaultAnnotatedDependencies()",
"protected com.yahoo.component.chain.dependencies.Dependencies getAnnotatedDependencies(java.lang.Class, java.lang.Class, java.lang.Class)"
"public com.yahoo.component.chain.dependencies.Dependencies getDependencies()"
],
"fields" : [ ]
},
Expand Down Expand Up @@ -2370,7 +2370,9 @@
},
"com.yahoo.jdisc.http.filter.RequestFilterBase" : {
"superClass" : "java.lang.Object",
"interfaces" : [ ],
"interfaces" : [
"com.yahoo.component.chain.model.Chainable"
],
"attributes" : [
"public",
"interface",
Expand Down Expand Up @@ -2414,7 +2416,9 @@
},
"com.yahoo.jdisc.http.filter.ResponseFilterBase" : {
"superClass" : "java.lang.Object",
"interfaces" : [ ],
"interfaces" : [
"com.yahoo.component.chain.model.Chainable"
],
"attributes" : [
"public",
"interface",
Expand All @@ -2426,7 +2430,8 @@
"com.yahoo.jdisc.http.filter.SecurityRequestFilter" : {
"superClass" : "java.lang.Object",
"interfaces" : [
"com.yahoo.jdisc.http.filter.RequestFilterBase"
"com.yahoo.jdisc.http.filter.RequestFilterBase",
"com.yahoo.component.chain.model.Chainable"
],
"attributes" : [
"public",
Expand Down Expand Up @@ -2459,7 +2464,8 @@
"com.yahoo.jdisc.http.filter.SecurityResponseFilter" : {
"superClass" : "java.lang.Object",
"interfaces" : [
"com.yahoo.jdisc.http.filter.ResponseFilterBase"
"com.yahoo.jdisc.http.filter.ResponseFilterBase",
"com.yahoo.component.chain.model.Chainable"
],
"attributes" : [
"public",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.yahoo.component.chain.dependencies.Before;
import com.yahoo.component.chain.dependencies.Dependencies;
import com.yahoo.component.chain.dependencies.Provides;
import com.yahoo.component.chain.model.Chainable;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
Expand All @@ -19,80 +20,32 @@
*
* @author Tony Vaagenes
*/
public abstract class ChainedComponent extends AbstractComponent {
public abstract class ChainedComponent extends AbstractComponent implements Chainable {

/** The immutable set of dependencies of this. NOTE: the default is only for unit testing. */
private Dependencies dependencies = getDefaultAnnotatedDependencies();
/**
* The immutable set of dependencies of this. NOTE: the default is only for unit testing.
*/
private Dependencies dependencies = getAnnotatedDependencies();

public ChainedComponent(ComponentId id) {
super(id);
}

protected ChainedComponent() {}
protected ChainedComponent() { }

/**
* Called by the container to assign the full set of dependencies to this class (configured and declared).
* This is called once before this is started.
* @param dependencies The configured dependencies, that this method will merge with annotated dependencies.
*
* @param dependencies The configured dependencies, that this method will merge with annotated dependencies.
*/
public void initDependencies(Dependencies dependencies) {
this.dependencies = dependencies.union(getDefaultAnnotatedDependencies());
}

/** Returns the configured and declared dependencies of this chainedcomponent */
public Dependencies getDependencies() { return dependencies; }

/** This method is here only for legacy reasons, do not override. */
protected Dependencies getDefaultAnnotatedDependencies() {
Dependencies dependencies = getAnnotatedDependencies(com.yahoo.yolean.chain.Provides.class, com.yahoo.yolean.chain.Before.class, com.yahoo.yolean.chain.After.class);
Dependencies legacyDependencies = getAnnotatedDependencies(Provides.class, Before.class, After.class);

return dependencies.union(legacyDependencies);
this.dependencies = dependencies.union(getAnnotatedDependencies());
}

/**
* @param providesClass The annotation class representing 'provides'.
* @param beforeClass The annotation class representing 'before'.
* @param afterClass The annotation class representing 'after'.
* @return a new {@link Dependencies} created from the annotations given in this component's class.
* Returns the configured and declared dependencies of this chainedcomponent
*/
protected Dependencies getAnnotatedDependencies(Class<? extends Annotation> providesClass,
Class<? extends Annotation> beforeClass,
Class<? extends Annotation> afterClass) {
return new Dependencies(
allOf(getSymbols(this, providesClass), this.getClass().getSimpleName(), this.getClass().getName()),
getSymbols(this, beforeClass),
getSymbols(this, afterClass));
}

// TODO: move to vespajlib.
private static List<String> allOf(List<String> symbols, String... otherSymbols) {
List<String> result = new ArrayList<>(symbols);
result.addAll(List.of(otherSymbols));
return result;
}


private static List<String> getSymbols(ChainedComponent component, Class<? extends Annotation> annotationClass) {
List<String> result = new ArrayList<>();

result.addAll(annotationSymbols(component, annotationClass));
return result;
}

private static Collection<String> annotationSymbols(ChainedComponent component, Class<? extends Annotation> annotationClass) {

try {
Annotation annotation = component.getClass().getAnnotation(annotationClass);
if (annotation != null) {
Object values = annotationClass.getMethod("value").invoke(annotation);
return List.of((String[])values);
}
return List.of();

} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public Dependencies getDependencies() { return dependencies; }

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,7 @@ private boolean popAllPhase(OrderedReadyNodes readyNodes) {
}

private NameProvider getNameProvider(String name) {
NameProvider nameProvider = nameProviders.get(name);
if (nameProvider != null)
return nameProvider;
else {
nameProvider = new ComponentNameProvider(name);
nameProviders.put(name, nameProvider);
return nameProvider;
}
return nameProviders.computeIfAbsent(name, ComponentNameProvider::new);
}

private OrderedReadyNodes getReadyNodes() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.yahoo.component.chain.model;

import com.yahoo.component.chain.dependencies.After;
import com.yahoo.component.chain.dependencies.Before;
import com.yahoo.component.chain.dependencies.Dependencies;
import com.yahoo.component.chain.dependencies.Provides;

import java.lang.annotation.Annotation;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* Components which can be chained together, and where dependency information is provided through annotations.
*
* @author jonmv
*/
public interface Chainable {

default Dependencies getAnnotatedDependencies() {
Set<String> provides = new LinkedHashSet<>();
Set<String> before = new LinkedHashSet<>();
Set<String> after = new LinkedHashSet<>();

for (Annotation annotation : getClass().getAnnotations()) {
if (annotation instanceof Provides p) provides.addAll(List.of(p.value()));
if (annotation instanceof com.yahoo.yolean.chain.Provides p) provides.addAll(List.of(p.value()));

if (annotation instanceof Before b) before.addAll(List.of(b.value()));
if (annotation instanceof com.yahoo.yolean.chain.Before b) before.addAll(List.of(b.value()));

if (annotation instanceof After a) after.addAll(List.of(a.value()));
if (annotation instanceof com.yahoo.yolean.chain.After a) after.addAll(List.of(a.value()));
}

provides.add(getClass().getSimpleName());
provides.add(getClass().getName());

return new Dependencies(provides, before, after);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.yahoo.component.chain.Chain;
import com.yahoo.component.chain.ChainedComponent;
import com.yahoo.component.chain.ChainsConfigurer;
import com.yahoo.component.chain.dependencies.Dependencies;
import com.yahoo.component.chain.model.Chainable;
import com.yahoo.component.chain.model.ChainsModel;
import com.yahoo.component.chain.model.ChainsModelBuilder;
import com.yahoo.component.provider.ComponentRegistry;
Expand Down Expand Up @@ -65,16 +67,18 @@ private static void addAllFilters(ComponentRegistry<Object> destination,
}
}

@SafeVarargs
private static void addAllChains(ComponentRegistry<Object> destination,
ChainsConfig chainsConfig,
ComponentRegistry<?>... filters) {
ComponentRegistry<? extends Chainable>... filters) {
ChainRegistry<FilterWrapper> chainRegistry = buildChainRegistry(chainsConfig, filters);
chainRegistry.allComponents()
.forEach(chain -> destination.register(chain.getId(), toJDiscChain(chain)));
}

@SafeVarargs
private static ChainRegistry<FilterWrapper> buildChainRegistry(ChainsConfig chainsConfig,
ComponentRegistry<?>... filters) {
ComponentRegistry<? extends Chainable>... filters) {
ChainRegistry<FilterWrapper> chainRegistry = new ChainRegistry<>();
ChainsModel chainsModel = ChainsModelBuilder.buildFromConfig(chainsConfig);
ChainsConfigurer.prepareChainRegistry(chainRegistry, chainsModel, allFiltersWrapped(filters));
Expand Down Expand Up @@ -146,9 +150,10 @@ private static void checkFilterTypesCompatible(Chain<FilterWrapper> chain) {
}
}

private static ComponentRegistry<FilterWrapper> allFiltersWrapped(ComponentRegistry<?>... registries) {
@SafeVarargs
private static ComponentRegistry<FilterWrapper> allFiltersWrapped(ComponentRegistry<? extends Chainable>... registries) {
ComponentRegistry<FilterWrapper> wrappedFilters = new ComponentRegistry<>();
for (ComponentRegistry<?> registry : registries) {
for (ComponentRegistry<? extends Chainable> registry : registries) {
registry.allComponentsById()
.forEach((id, filter) -> wrappedFilters.register(id, new FilterWrapper(id, filter)));
}
Expand Down Expand Up @@ -176,16 +181,21 @@ private static boolean isSecurityFilter(Object filter) {
}

private static class FilterWrapper extends ChainedComponent {
public final Object filter;
public final Class<?> filterType;
public final Chainable filter;
public final Class<? extends Chainable> filterType;

public FilterWrapper(ComponentId id, Object filter) {
public FilterWrapper(ComponentId id, Chainable filter) {
super(id);
this.filter = filter;
this.filterType = getFilterType(filter);
}

private static Class<?> getFilterType(Object filter) {
@Override
public Dependencies getAnnotatedDependencies() {
return filter == null ? super.getAnnotatedDependencies() : filter.getAnnotatedDependencies();
}

private static Class<? extends Chainable> getFilterType(Object filter) {
if (filter instanceof RequestFilter)
return RequestFilter.class;
else if (filter instanceof ResponseFilter)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.filter;

import com.yahoo.component.chain.model.Chainable;

/**
* @author gjoranv
* @since 2.4
*/
public interface RequestFilterBase {
public interface RequestFilterBase extends Chainable {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.yahoo.jdisc.SharedResource;

/**
* @author <a href="mailto:[email protected]">Einar M R Rosenvinge</a>
* @author Einar M R Rosenvinge
*/
public interface ResponseFilter extends SharedResource, ResponseFilterBase {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.filter;

import com.yahoo.component.chain.model.Chainable;

/**
* @author gjoranv
* @since 2.4
*/
public interface ResponseFilterBase {
public interface ResponseFilterBase extends Chainable {
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.filter;

import com.yahoo.component.chain.model.Chainable;
import com.yahoo.jdisc.handler.ResponseHandler;

/**
* @author Simon Thoresen Hult
*/
public interface SecurityRequestFilter extends RequestFilterBase {
public interface SecurityRequestFilter extends RequestFilterBase, Chainable {

void filter(DiscFilterRequest request, ResponseHandler handler);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.filter;

public interface SecurityResponseFilter extends ResponseFilterBase {
import com.yahoo.component.chain.model.Chainable;

public interface SecurityResponseFilter extends ResponseFilterBase, Chainable {

void filter(DiscFilterResponse response, RequestView request);

Expand Down
Loading

0 comments on commit 35d82c3

Please sign in to comment.