diff options
author | Bjørn Christian Seime <bjorncs@yahoo-inc.com> | 2017-07-19 11:23:41 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahoo-inc.com> | 2017-07-20 13:13:09 +0200 |
commit | 94e3449f4b57647b199a03e2e59f91ee902b35eb (patch) | |
tree | 682aedfecbe6fa62fbfd3be986c74fe4338b1531 /container-core | |
parent | 929a44e999bbaae9600753aea1a8335a9facd69e (diff) |
Remove Scala from container-core
Diffstat (limited to 'container-core')
3 files changed, 165 insertions, 185 deletions
diff --git a/container-core/pom.xml b/container-core/pom.xml index 79d8fc1f199..c608f35f26c 100644 --- a/container-core/pom.xml +++ b/container-core/pom.xml @@ -186,11 +186,6 @@ <scope>test</scope> </dependency> <dependency> - <groupId>com.yahoo.vespa</groupId> - <artifactId>scalalib</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <scope>provided</scope> @@ -204,32 +199,6 @@ <build> <plugins> <plugin> - <groupId>net.alchim31.maven</groupId> - <artifactId>scala-maven-plugin</artifactId> - <executions> - <execution> - <id>compile</id> - <goals> - <goal>compile</goal> - </goals> - <phase>compile</phase> - </execution> - <execution> - <id>test-compile</id> - <goals> - <goal>testCompile</goal> - </goals> - <phase>test-compile</phase> - </execution> - <execution> - <phase>process-resources</phase> - <goals> - <goal>compile</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> diff --git a/container-core/src/main/java/com/yahoo/container/http/filter/FilterChainRepository.java b/container-core/src/main/java/com/yahoo/container/http/filter/FilterChainRepository.java new file mode 100644 index 00000000000..a736fd1372f --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/http/filter/FilterChainRepository.java @@ -0,0 +1,165 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.http.filter; + +import com.yahoo.component.AbstractComponent; +import com.yahoo.component.ComponentId; +import com.yahoo.component.ComponentSpecification; +import com.yahoo.component.chain.Chain; +import com.yahoo.component.chain.ChainedComponent; +import com.yahoo.component.chain.ChainsConfigurer; +import com.yahoo.component.chain.model.ChainsModel; +import com.yahoo.component.chain.model.ChainsModelBuilder; +import com.yahoo.component.provider.ComponentRegistry; +import com.yahoo.container.core.ChainsConfig; +import com.yahoo.jdisc.http.filter.RequestFilter; +import com.yahoo.jdisc.http.filter.ResponseFilter; +import com.yahoo.jdisc.http.filter.SecurityRequestFilter; +import com.yahoo.jdisc.http.filter.SecurityRequestFilterChain; +import com.yahoo.jdisc.http.filter.SecurityResponseFilter; +import com.yahoo.jdisc.http.filter.SecurityResponseFilterChain; +import com.yahoo.jdisc.http.filter.chain.RequestFilterChain; +import com.yahoo.jdisc.http.filter.chain.ResponseFilterChain; +import com.yahoo.processing.execution.chain.ChainRegistry; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; + +/** + * Creates JDisc request/response filter chains. + * + * @author tonytv + * @author bjorncs + */ +public class FilterChainRepository extends AbstractComponent { + + private final ComponentRegistry<Object> filterAndChains; + + public FilterChainRepository(ChainsConfig chainsConfig, + ComponentRegistry<RequestFilter> requestFilters, + ComponentRegistry<ResponseFilter> responseFilters, + ComponentRegistry<SecurityRequestFilter> securityRequestFilters, + ComponentRegistry<SecurityResponseFilter> securityResponseFilters) { + ComponentRegistry<Object> filterAndChains = new ComponentRegistry<>(); + addAllFilters(filterAndChains, requestFilters, responseFilters, securityRequestFilters, securityResponseFilters); + addAllChains(filterAndChains, chainsConfig, requestFilters, responseFilters, securityRequestFilters, securityResponseFilters); + filterAndChains.freeze(); + this.filterAndChains = filterAndChains; + } + + public Object getFilter(ComponentSpecification componentSpecification) { + return filterAndChains.getComponent(componentSpecification); + } + + private static void addAllFilters(ComponentRegistry<Object> destination, + ComponentRegistry<?>... registries) { + for (ComponentRegistry<?> registry : registries) { + registry.allComponentsById() + .forEach((id, filter) -> destination.register(id, wrapIfSecurityFilter(filter))); + } + } + + private static void addAllChains(ComponentRegistry<Object> destination, + ChainsConfig chainsConfig, + ComponentRegistry<?>... filters) { + ChainRegistry<FilterWrapper> chainRegistry = buildChainRegistry(chainsConfig, filters); + chainRegistry.allComponents() + .forEach(chain -> destination.register(chain.getId(), toJDiscChain(chain))); + } + + private static ChainRegistry<FilterWrapper> buildChainRegistry(ChainsConfig chainsConfig, + ComponentRegistry<?>... filters) { + ChainRegistry<FilterWrapper> chainRegistry = new ChainRegistry<>(); + ChainsModel chainsModel = ChainsModelBuilder.buildFromConfig(chainsConfig); + ChainsConfigurer.prepareChainRegistry(chainRegistry, chainsModel, allFiltersWrapped(filters)); + chainRegistry.freeze(); + return chainRegistry; + } + + @SuppressWarnings("unchecked") + private static Object toJDiscChain(Chain<FilterWrapper> chain) { + checkFilterTypesCompatible(chain); + List<?> jdiscFilters = chain.components().stream() + .map(filterWrapper -> filterWrapper.filter) + .collect(toList()); + Object head = jdiscFilters.get(0); + if (jdiscFilters.size() == 1) return head; + else if (head instanceof RequestFilter) + return RequestFilterChain.newInstance((List<RequestFilter>) jdiscFilters); + else if (head instanceof ResponseFilter) + return ResponseFilterChain.newInstance((List<ResponseFilter>) jdiscFilters); + throw new IllegalStateException(); + } + + private static void checkFilterTypesCompatible(Chain<FilterWrapper> chain) { + Set<ComponentId> requestFilters = chain.components().stream() + .filter(filter -> filter instanceof RequestFilter || filter instanceof SecurityRequestFilter) + .map(FilterWrapper::getId) + .collect(toSet()); + Set<ComponentId> responseFilters = chain.components().stream() + .filter(filter -> filter instanceof ResponseFilter || filter instanceof SecurityResponseFilter) + .map(FilterWrapper::getId) + .collect(toSet()); + if (!requestFilters.isEmpty() && !responseFilters.isEmpty()) { + throw new IllegalArgumentException( + String.format( + "Can't mix request and response filters in chain %s: request filters: %s, response filters: %s.", + chain.getId(), requestFilters, responseFilters)); + } + } + + private static ComponentRegistry<FilterWrapper> allFiltersWrapped(ComponentRegistry<?>... registries) { + ComponentRegistry<FilterWrapper> wrappedFilters = new ComponentRegistry<>(); + for (ComponentRegistry<?> registry : registries) { + registry.allComponentsById() + .forEach((id, filter) -> wrappedFilters.register(id, new FilterWrapper(id, filter))); + } + wrappedFilters.freeze(); + return wrappedFilters; + } + + private static Object wrapIfSecurityFilter(Object filter) { + if (isSecurityFilter(filter)) return createSecurityChain(Collections.singletonList(filter)); + return filter; + } + + @SuppressWarnings("unchecked") + private static Object createSecurityChain(List<?> filters) { + Object head = filters.get(0); + if (head instanceof SecurityRequestFilter) + return SecurityRequestFilterChain.newInstance((List<SecurityRequestFilter>) filters); + else if (head instanceof SecurityResponseFilter) + return SecurityResponseFilterChain.newInstance((List<SecurityResponseFilter>) filters); + throw new IllegalArgumentException("Unexpected class " + head.getClass()); + } + + private static boolean isSecurityFilter(Object filter) { + return filter instanceof SecurityRequestFilter || filter instanceof SecurityResponseFilter; + } + + private static class FilterWrapper extends ChainedComponent { + public final Object filter; + public final Class<?> filterType; + + public FilterWrapper(ComponentId id, Object filter) { + super(id); + this.filter = filter; + this.filterType = getFilterType(filter); + } + + private static Class<?> getFilterType(Object filter) { + if (filter instanceof RequestFilter) + return RequestFilter.class; + else if (filter instanceof ResponseFilter) + return ResponseFilter.class; + else if (filter instanceof SecurityRequestFilter) + return SecurityRequestFilter.class; + else if (filter instanceof SecurityResponseFilter) + return SecurityResponseFilter.class; + throw new IllegalArgumentException("Unsupported filter type: " + filter.getClass().getName()); + } + } +} diff --git a/container-core/src/main/scala/com/yahoo/container/http/filter/FilterChainRepository.scala b/container-core/src/main/scala/com/yahoo/container/http/filter/FilterChainRepository.scala deleted file mode 100644 index 18195b7dc50..00000000000 --- a/container-core/src/main/scala/com/yahoo/container/http/filter/FilterChainRepository.scala +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.http.filter - -import com.yahoo.component.chain.model.ChainsModelBuilder -import com.yahoo.component.chain.{Chain, ChainedComponent, ChainsConfigurer} -import com.yahoo.component.provider.ComponentRegistry -import com.yahoo.component.{AbstractComponent, ComponentId, ComponentSpecification} -import com.yahoo.container.core.ChainsConfig -import com.yahoo.container.http.filter.FilterChainRepository._ -import com.yahoo.jdisc.http.filter.chain.{RequestFilterChain, ResponseFilterChain} -import com.yahoo.jdisc.http.filter.{RequestFilter, ResponseFilter, SecurityRequestFilter, SecurityRequestFilterChain, SecurityResponseFilter, SecurityResponseFilterChain} -import com.yahoo.processing.execution.chain.ChainRegistry - -import scala.collection.JavaConverters._ - - -/** - * Creates JDisc request/response filter chains. - * @author tonytv - */ -class FilterChainRepository(chainsConfig: ChainsConfig, - requestFilters: ComponentRegistry[RequestFilter], - responseFilters: ComponentRegistry[ResponseFilter], - securityRequestFilters: ComponentRegistry[SecurityRequestFilter], - securityResponseFilters: ComponentRegistry[SecurityResponseFilter]) extends AbstractComponent { - - private val filtersAndChains = new ComponentRegistry[AnyRef] - addAllFilters(filtersAndChains, requestFilters, responseFilters, securityRequestFilters, securityResponseFilters) - addAllChains(filtersAndChains, chainsConfig, requestFilters, responseFilters, securityRequestFilters, securityResponseFilters) - filtersAndChains.freeze() - - def getFilter(componentSpecification: ComponentSpecification) = - filtersAndChains.getComponent(componentSpecification) -} - - private[filter] object FilterChainRepository { - case class FilterWrapper(id: ComponentId, filter: AnyRef) extends ChainedComponent(id) { - def filterType: Class[_] = filter match { - case f: RequestFilter => classOf[RequestFilter] - case f: ResponseFilter => classOf[ResponseFilter] - case f: SecurityRequestFilter => classOf[SecurityRequestFilter] - case f: SecurityResponseFilter => classOf[SecurityResponseFilter] - case _ => throw new IllegalArgumentException("Unsupported filter type: " + filter.getClass.getName) - } - } - - def allFiltersWrapped(registries: ComponentRegistry[_ <: AnyRef]*): ComponentRegistry[FilterWrapper] = { - val wrappedFilters = new ComponentRegistry[FilterWrapper] - - def registerWrappedFilters(registry: ComponentRegistry[_ <: AnyRef]) { - for ((id, filter) <- registry.allComponentsById().asScala) - wrappedFilters.register(id, new FilterWrapper(id, filter)) - } - - registries.foreach(registerWrappedFilters) - wrappedFilters.freeze() - wrappedFilters - } - - private def addAllFilters(destination: ComponentRegistry[AnyRef], registries: ComponentRegistry[_ <: AnyRef]*) { - def wrapSecurityFilter(filter: AnyRef) = { - if (isSecurityFilter(filter)) createSecurityChain(List(filter)) - else filter - } - - for { - registry <- registries - (id, filter) <- registry.allComponentsById().asScala - } destination.register(id, wrapSecurityFilter(filter)) - } - - private def addAllChains(destination: ComponentRegistry[AnyRef], chainsConfig: ChainsConfig, filters: ComponentRegistry[_ <: AnyRef]*) { - val chainRegistry = buildChainsRegistry(chainsConfig, filters) - - for (chain <- chainRegistry.allComponents().asScala) { - destination.register(chain.getId, toJDiscChain(chain)) - } - } - - - def buildChainsRegistry(chainsConfig: ChainsConfig, filters: Seq[ComponentRegistry[_ <: AnyRef]]) = { - val chainRegistry = new ChainRegistry[FilterWrapper] - val chainsModel = ChainsModelBuilder.buildFromConfig(chainsConfig) - - ChainsConfigurer.prepareChainRegistry(chainRegistry, chainsModel, allFiltersWrapped(filters: _*)) - chainRegistry.freeze() - chainRegistry - } - - private def toJDiscChain(chain: Chain[FilterWrapper]): AnyRef = { - checkFilterTypesCompatible(chain) - val jDiscFilters = chain.components().asScala map {_.filter} - - wrapJDiscChain(wrapSecurityFilters(jDiscFilters.toList)) - } - - def wrapJDiscChain(filters: List[AnyRef]): AnyRef = { - if (filters.size == 1) filters.head - else { - filters.head match { - case _: RequestFilter => RequestFilterChain.newInstance(filters.asInstanceOf[List[RequestFilter]].asJava) - case _: ResponseFilter => ResponseFilterChain.newInstance(filters.asInstanceOf[List[ResponseFilter]].asJava) - } - } - } - - def wrapSecurityFilters(filters: List[AnyRef]): List[AnyRef] = { - if (filters.isEmpty) List() - else { - val (securityFilters, rest) = filters.span(isSecurityFilter) - if (securityFilters.isEmpty) { - val (regularFilters, rest) = filters.span(!isSecurityFilter(_)) - regularFilters ++ wrapSecurityFilters(rest) - } else { - createSecurityChain(securityFilters) :: wrapSecurityFilters(rest) - } - } - } - - def createSecurityChain(filters: List[AnyRef]): AnyRef = { - filters.head match { - case _: SecurityRequestFilter => SecurityRequestFilterChain.newInstance(filters.asInstanceOf[List[SecurityRequestFilter]].asJava) - case _: SecurityResponseFilter => SecurityResponseFilterChain.newInstance(filters.asInstanceOf[List[SecurityResponseFilter]].asJava) - case _ => throw new IllegalArgumentException("Unexpected class " + filters.head.getClass) - } - } - - def isSecurityFilter(filter: AnyRef) = { - filter match { - case _: SecurityRequestFilter => true - case _: SecurityResponseFilter => true - case _ => false - } - } - - def checkFilterTypesCompatible(chain: Chain[FilterWrapper]) { - val requestFilters = Set[Class[_]](classOf[RequestFilter], classOf[SecurityRequestFilter]) - val responseFilters = Set[Class[_]](classOf[ResponseFilter], classOf[SecurityResponseFilter]) - - def check(a: FilterWrapper, b: FilterWrapper) { - if (requestFilters(a.filterType) && responseFilters(b.filterType)) - throw new RuntimeException("Can't mix request and response filters in chain %s: %s, %s".format(chain.getId, a.getId, b.getId)) - } - - overlappingPairIterator(chain.components.asScala).foreach { - case Seq(_) => - case Seq(filter1: FilterWrapper, filter2: FilterWrapper) => - check(filter1, filter2) - check(filter2, filter1) - } - } - - def overlappingPairIterator[T](s: Seq[T]) = s.iterator.sliding(2, 1) -} |