summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <jonbratseth@yahoo.com>2017-07-24 10:39:23 +0200
committerGitHub <noreply@github.com>2017-07-24 10:39:23 +0200
commit2b38f8b102042f23f7dea8a8c65b88e15793467d (patch)
tree2e40895e1f010d86722bfc25dbf23fc1f8419bec
parenta686e44549ccb59682511d1a2ad91ff86cc3443f (diff)
parentd84c0532dc98482d10204a6c7a4b6b8aa3c4b3f9 (diff)
Merge pull request #2990 from yahoo/bjorncs/scala-cleanup
Bjorncs/scala cleanup
-rw-r--r--application/pom.xml30
-rw-r--r--application/src/test/scala/com/yahoo/application/container/jersey/JerseyTest.scala19
-rw-r--r--bundle-plugin-test/pom.xml10
-rw-r--r--bundle-plugin-test/src/test/java/com/yahoo/BundleIT.java14
-rw-r--r--bundle-plugin/pom.xml2
-rw-r--r--bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala20
-rw-r--r--container-core/pom.xml31
-rw-r--r--container-core/src/main/java/com/yahoo/container/http/filter/FilterChainRepository.java165
-rw-r--r--container-core/src/main/scala/com/yahoo/container/http/filter/FilterChainRepository.scala154
-rw-r--r--container-di/pom.xml5
-rw-r--r--container-di/src/main/scala/com/yahoo/container/di/osgi/OsgiUtil.scala28
-rw-r--r--maven-plugins/pom.xml1
-rw-r--r--pom.xml1
-rw-r--r--scalalib/OWNERS1
-rw-r--r--scalalib/README1
-rw-r--r--scalalib/pom.xml64
-rw-r--r--scalalib/src/main/scala/com/yahoo/vespa/scalalib/arm/Using.scala17
-rw-r--r--scalalib/src/main/scala/com/yahoo/vespa/scalalib/java/function/FunctionConverters.scala20
-rw-r--r--scalalib/src/main/scala/com/yahoo/vespa/scalalib/osgi/maven/ProjectBundleClassPaths.scala44
-rw-r--r--vespajlib/src/main/java/com/yahoo/osgi/maven/ProjectBundleClassPaths.java130
-rw-r--r--vespajlib/src/test/java/com/yahoo/osgi/maven/ProjectBundleClassPathsTest.java35
21 files changed, 378 insertions, 414 deletions
diff --git a/application/pom.xml b/application/pom.xml
index f58e16a0341..8f301c1a884 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -76,12 +76,6 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>scalalib</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
@@ -119,31 +113,11 @@
<artifactId>scala-maven-plugin</artifactId>
<executions>
<execution>
- <id>compile</id>
- <goals>
- <goal>compile</goal>
- </goals>
- <phase>compile</phase>
- </execution>
- <execution>
- <id>test-compile</id>
+ <id>scala-test-compile</id>
+ <phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
- <phase>test-compile</phase>
- </execution>
- <execution>
- <phase>process-resources</phase>
- <goals>
- <goal>compile</goal>
- </goals>
- </execution>
- <execution>
- <phase>process-test-resources</phase>
- <id>early-test-compile</id>
- <goals>
- <goal>testCompile</goal>
- </goals>
</execution>
</executions>
</plugin>
diff --git a/application/src/test/scala/com/yahoo/application/container/jersey/JerseyTest.scala b/application/src/test/scala/com/yahoo/application/container/jersey/JerseyTest.scala
index a199c28a4b2..2aee68f254a 100644
--- a/application/src/test/scala/com/yahoo/application/container/jersey/JerseyTest.scala
+++ b/application/src/test/scala/com/yahoo/application/container/jersey/JerseyTest.scala
@@ -8,8 +8,8 @@ import com.yahoo.application.Networking
import com.yahoo.application.container.JDiscTest._
import com.yahoo.container.test.jars.jersey.resources.TestResourceBase
import com.yahoo.container.test.jars.jersey.{resources => jarResources}
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping
+import com.yahoo.osgi.maven.ProjectBundleClassPaths
+import com.yahoo.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClientBuilder
@@ -18,6 +18,7 @@ import org.hamcrest.CoreMatchers.is
import org.junit.Assert._
import org.junit.Test
+import scala.collection.JavaConverters._
import scala.io.Source
/**
@@ -51,11 +52,11 @@ class JerseyTest {
@Test
def jersey_resources_in_provided_dependencies_can_be_invoked_from_application(): Unit = {
- val providedDependency = BundleClasspathMapping(bundleSymbolicName, List(testClassesDirectory))
+ val providedDependency = new BundleClasspathMapping(bundleSymbolicName, List(testClassesDirectory).asJava)
- save(ProjectBundleClassPaths(
- mainBundle = BundleClasspathMapping("main", List()),
- providedDependencies = List(providedDependency)))
+ save(new ProjectBundleClassPaths(
+ new BundleClasspathMapping("main", List().asJava),
+ List(providedDependency).asJava))
with_jersey_resources() { httpGetter =>
assertResourcesResponds(classPathResources, httpGetter)
@@ -153,12 +154,12 @@ class JerseyTest {
}
def saveMainBundleClassPathMappings(classPathElement: String): Unit = {
- val mainBundleClassPathMappings = BundleClasspathMapping(bundleSymbolicName, List(classPathElement))
- save(ProjectBundleClassPaths(mainBundleClassPathMappings, providedDependencies = List()))
+ val mainBundleClassPathMappings = new BundleClasspathMapping(bundleSymbolicName, List(classPathElement).asJava)
+ save(new ProjectBundleClassPaths(mainBundleClassPathMappings, List().asJava))
}
def save(projectBundleClassPaths: ProjectBundleClassPaths): Unit = {
- val path = Paths.get(testClassesDirectory).resolve(ProjectBundleClassPaths.classPathMappingsFileName)
+ val path = Paths.get(testClassesDirectory).resolve(ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME)
ProjectBundleClassPaths.save(path, projectBundleClassPaths)
}
diff --git a/bundle-plugin-test/pom.xml b/bundle-plugin-test/pom.xml
index ebc60f86b93..2112d616523 100644
--- a/bundle-plugin-test/pom.xml
+++ b/bundle-plugin-test/pom.xml
@@ -42,16 +42,6 @@
<artifactId>jrt</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-library</artifactId>
- </dependency>
- <dependency>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>scalalib</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<plugins>
diff --git a/bundle-plugin-test/src/test/java/com/yahoo/BundleIT.java b/bundle-plugin-test/src/test/java/com/yahoo/BundleIT.java
index a7d27a449e6..f088007ebb7 100644
--- a/bundle-plugin-test/src/test/java/com/yahoo/BundleIT.java
+++ b/bundle-plugin-test/src/test/java/com/yahoo/BundleIT.java
@@ -1,11 +1,10 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo;
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths;
+import com.yahoo.osgi.maven.ProjectBundleClassPaths;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
-import scala.collection.JavaConverters;
import java.io.File;
import java.io.FilenameFilter;
@@ -132,18 +131,17 @@ public class BundleIT {
@SuppressWarnings("unchecked")
@Test
- public void bundle_class_path_mappings_are_generated() throws URISyntaxException {
- URL mappingsUrl = getClass().getResource("/" + ProjectBundleClassPaths.classPathMappingsFileName());
+ public void bundle_class_path_mappings_are_generated() throws URISyntaxException, IOException {
+ URL mappingsUrl = getClass().getResource("/" + com.yahoo.osgi.maven.ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME);
assertNotNull(
- "Could not find " + ProjectBundleClassPaths.classPathMappingsFileName() + " in the test output directory",
+ "Could not find " + ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME + " in the test output directory",
mappingsUrl);
ProjectBundleClassPaths bundleClassPaths = ProjectBundleClassPaths.load(Paths.get(mappingsUrl.toURI()));
- assertThat(bundleClassPaths.mainBundle().bundleSymbolicName(), is("bundle-plugin-test"));
+ assertThat(bundleClassPaths.mainBundle.bundleSymbolicName, is("bundle-plugin-test"));
- Collection<String> mainBundleClassPaths =
- JavaConverters.asJavaCollectionConverter(bundleClassPaths.mainBundle().classPathElements()).asJavaCollection();
+ Collection<String> mainBundleClassPaths = bundleClassPaths.mainBundle.classPathElements;
assertThat(mainBundleClassPaths,
hasItems(
diff --git a/bundle-plugin/pom.xml b/bundle-plugin/pom.xml
index 31355ff21d2..60facd877ed 100644
--- a/bundle-plugin/pom.xml
+++ b/bundle-plugin/pom.xml
@@ -74,7 +74,7 @@
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
- <artifactId>scalalib</artifactId>
+ <artifactId>vespajlib</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala
index cad91e00684..4f463e7b494 100644
--- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala
+++ b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala
@@ -6,14 +6,15 @@ import java.nio.file.Paths
import com.google.common.base.Preconditions
import com.yahoo.container.plugin.bundle.AnalyzeBundle
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths
-import ProjectBundleClassPaths.BundleClasspathMapping
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths
+import com.yahoo.osgi.maven.ProjectBundleClassPaths
+import com.yahoo.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping
import org.apache.maven.artifact.Artifact
import org.apache.maven.plugin.AbstractMojo
-import org.apache.maven.plugins.annotations.{ResolutionScope, Mojo, Parameter}
+import org.apache.maven.plugins.annotations.{Mojo, Parameter, ResolutionScope}
import org.apache.maven.project.MavenProject
+import scala.collection.JavaConverters._
+
/**
@@ -61,13 +62,12 @@ class GenerateBundleClassPathMappingsMojo extends AbstractMojo {
val classPathElements = (outputDirectory +: embeddedArtifactsFiles).map(_.getAbsolutePath)
- val classPathMappings = ProjectBundleClassPaths(
- mainBundle = BundleClasspathMapping(bundleSymbolicName, classPathElements),
- providedDependencies = providedJarArtifacts flatMap createDependencyClasspathMapping
- )
+ val classPathMappings = new ProjectBundleClassPaths(
+ new BundleClasspathMapping(bundleSymbolicName, classPathElements.asJava),
+ providedJarArtifacts.flatMap(createDependencyClasspathMapping).asJava)
ProjectBundleClassPaths.save(
- testOutputPath.resolve(ProjectBundleClassPaths.classPathMappingsFileName),
+ testOutputPath.resolve(ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME),
classPathMappings)
}
@@ -82,7 +82,7 @@ class GenerateBundleClassPathMappingsMojo extends AbstractMojo {
*/
def createDependencyClasspathMapping(artifact: Artifact): Option[BundleClasspathMapping] = {
for (bundleSymbolicName <- bundleSymbolicNameForArtifact(artifact))
- yield BundleClasspathMapping(bundleSymbolicName, classPathElements = List(artifact.getFile.getAbsolutePath))
+ yield new BundleClasspathMapping(bundleSymbolicName, List(artifact.getFile.getAbsolutePath).asJava)
}
def bundleSymbolicNameForArtifact(artifact: Artifact): Option[String] = {
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)
-}
diff --git a/container-di/pom.xml b/container-di/pom.xml
index f6a31ea16a1..86baa0f2081 100644
--- a/container-di/pom.xml
+++ b/container-di/pom.xml
@@ -50,11 +50,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>scalalib</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<scope>test</scope>
diff --git a/container-di/src/main/scala/com/yahoo/container/di/osgi/OsgiUtil.scala b/container-di/src/main/scala/com/yahoo/container/di/osgi/OsgiUtil.scala
index f2120786579..489760dcbc8 100644
--- a/container-di/src/main/scala/com/yahoo/container/di/osgi/OsgiUtil.scala
+++ b/container-di/src/main/scala/com/yahoo/container/di/osgi/OsgiUtil.scala
@@ -10,10 +10,8 @@ import java.util.stream.Collectors
import com.google.common.io.Files.fileTreeTraverser
import com.yahoo.component.ComponentSpecification
import com.yahoo.container.di.Osgi.RelativePath
-import com.yahoo.vespa.scalalib.arm.Using.using
-import com.yahoo.vespa.scalalib.java.function.FunctionConverters._
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths
-import com.yahoo.vespa.scalalib.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping
+import com.yahoo.osgi.maven.ProjectBundleClassPaths
+import com.yahoo.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping
import org.osgi.framework.Bundle
import org.osgi.framework.wiring.BundleWiring
@@ -46,7 +44,7 @@ object OsgiUtil {
bundleSpec: ComponentSpecification,
packagesToScan: Set[String]) = {
classEntriesFrom(
- bundleClassPathMapping(bundleSpec, classLoader).classPathElements,
+ bundleClassPathMapping(bundleSpec, classLoader).classPathElements.asScala.toList,
packagesToScan)
}
@@ -59,7 +57,7 @@ object OsgiUtil {
projectBundleClassPaths.mainBundle
} else {
log.log(Level.WARNING, s"Dependencies of the bundle $bundleSpec will not be scanned. Please file a feature request if you need this" )
- matchingBundleClassPathMapping(bundleSpec, projectBundleClassPaths.providedDependencies)
+ matchingBundleClassPathMapping(bundleSpec, projectBundleClassPaths.providedDependencies.asScala.toList)
}
}
@@ -71,9 +69,9 @@ object OsgiUtil {
}
private def loadProjectBundleClassPaths(classLoader: ClassLoader): ProjectBundleClassPaths = {
- val classPathMappingsFileLocation = classLoader.getResource(ProjectBundleClassPaths.classPathMappingsFileName)
+ val classPathMappingsFileLocation = classLoader.getResource(ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME)
if (classPathMappingsFileLocation == null)
- throw new RuntimeException(s"Couldn't find ${ProjectBundleClassPaths.classPathMappingsFileName} in the class path.")
+ throw new RuntimeException(s"Couldn't find ${ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME} in the class path.")
ProjectBundleClassPaths.load(Paths.get(classPathMappingsFileLocation.toURI))
}
@@ -119,15 +117,27 @@ object OsgiUtil {
if (packagePathsToScan.isEmpty) (name: String) => true
else (name: String) => packagePathsToScan(packagePath(name))
- using(new JarFile(jarPath.toFile)) { jarFile =>
+ var jarFile: JarFile = null
+ try {
+ jarFile = new JarFile(jarPath.toFile)
jarFile.stream().
map[String] { entry: JarEntry => entry.getName}.
filter { name: String => name.endsWith(classFileTypeSuffix)}.
filter(acceptedPackage).
collect(Collectors.toList()).
asScala
+ } finally {
+ if (jarFile != null) jarFile.close()
}
}
def packageToPath(packageName: String) = packageName.replaceAllLiterally(".", "/")
+
+ implicit class JavaPredicate[T](f: T => Boolean) extends Predicate[T] {
+ override def test(t: T): Boolean = f(t)
+ }
+
+ implicit class JavaFunction[T, R](f: T => R) extends java.util.function.Function[T, R] {
+ override def apply(t: T): R = f(t)
+ }
}
diff --git a/maven-plugins/pom.xml b/maven-plugins/pom.xml
index 3fdb91adf7f..2f7343e753c 100644
--- a/maven-plugins/pom.xml
+++ b/maven-plugins/pom.xml
@@ -17,7 +17,6 @@
<modules>
<module>../annotations</module>
- <module>../scalalib</module>
<module>../bundle-plugin</module>
<module>../configgen</module>
<module>../config-class-plugin</module>
diff --git a/pom.xml b/pom.xml
index 618cc3837fb..abe03898086 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1039,6 +1039,5 @@
<module>vsm</module>
<module>yolean</module>
<module>zkfacade</module>
- <module>scalalib</module>
</modules>
</project>
diff --git a/scalalib/OWNERS b/scalalib/OWNERS
deleted file mode 100644
index 3b2ba1ede81..00000000000
--- a/scalalib/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-gjoranv
diff --git a/scalalib/README b/scalalib/README
deleted file mode 100644
index 9c622c66ec0..00000000000
--- a/scalalib/README
+++ /dev/null
@@ -1 +0,0 @@
-Module for shared Scala utility code in Vespa.
diff --git a/scalalib/pom.xml b/scalalib/pom.xml
deleted file mode 100644
index 78237211ac3..00000000000
--- a/scalalib/pom.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0"?>
-<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>parent</artifactId>
- <version>6-SNAPSHOT</version>
- </parent>
- <artifactId>scalalib</artifactId>
- <packaging>jar</packaging>
- <version>6-SNAPSHOT</version>
- <name>${project.artifactId}</name>
- <description>Library for use in Scala components of Vespa.</description>
-
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-library</artifactId>
- </dependency>
- <dependency>
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>annotations</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.json4s</groupId>
- <artifactId>json4s-native_${scala.major-version}</artifactId>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>scala-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>add-source</goal>
- <goal>compile</goal>
- <goal>testCompile</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <forkMode>once</forkMode>
- <systemPropertyVariables>
- <expectedDefaultConfigGenVersion>${project.version}</expectedDefaultConfigGenVersion>
- </systemPropertyVariables>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
diff --git a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/arm/Using.scala b/scalalib/src/main/scala/com/yahoo/vespa/scalalib/arm/Using.scala
deleted file mode 100644
index bee1172a26f..00000000000
--- a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/arm/Using.scala
+++ /dev/null
@@ -1,17 +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.vespa.scalalib.arm
-
-import scala.language.reflectiveCalls
-
-/**
- * @author tonytv
- */
-object Using {
- def using[RESOURCE <: { def close() }, RETURN](resource: RESOURCE)(f: RESOURCE => RETURN) = {
- try {
- f(resource)
- } finally {
- if (resource != null) resource.close()
- }
- }
-}
diff --git a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/java/function/FunctionConverters.scala b/scalalib/src/main/scala/com/yahoo/vespa/scalalib/java/function/FunctionConverters.scala
deleted file mode 100644
index b8cce3cf343..00000000000
--- a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/java/function/FunctionConverters.scala
+++ /dev/null
@@ -1,20 +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.vespa.scalalib.java.function
-
-import java.util.function.Predicate
-
-import scala.language.implicitConversions
-
-/**
- * For using scala functions in Java APIs, such as the stream API.
- * @author tonytv
- */
-object FunctionConverters {
- implicit class JavaPredicate[T](f: T => Boolean) extends Predicate[T] {
- override def test(t: T): Boolean = f(t)
- }
-
- implicit class JavaFunction[T, R](f: T => R) extends java.util.function.Function[T, R] {
- override def apply(t: T): R = f(t)
- }
-}
diff --git a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/osgi/maven/ProjectBundleClassPaths.scala b/scalalib/src/main/scala/com/yahoo/vespa/scalalib/osgi/maven/ProjectBundleClassPaths.scala
deleted file mode 100644
index 08b8f05b96f..00000000000
--- a/scalalib/src/main/scala/com/yahoo/vespa/scalalib/osgi/maven/ProjectBundleClassPaths.scala
+++ /dev/null
@@ -1,44 +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.vespa.scalalib.osgi.maven
-
-import java.nio.charset.StandardCharsets
-import java.nio.file.{Files, Path}
-
-import org.json4s.NoTypeHints
-import org.json4s.native.Serialization
-
-import ProjectBundleClassPaths._
-
-/**
- * Represents the bundles in a maven project and the classpath elements
- * corresponding to code that would end up in the bundle.
- * @author tonytv
- */
-case class ProjectBundleClassPaths(mainBundle: BundleClasspathMapping,
- providedDependencies: List[BundleClasspathMapping])
-
-
-object ProjectBundleClassPaths {
- //Written by bundle-plugin in the test classes directory.
- val classPathMappingsFileName = "bundle-plugin.bundle-classpath-mappings.json"
-
- case class BundleClasspathMapping(bundleSymbolicName: String, classPathElements: List[String])
-
- //Used by Serialization.* methods. See https://github.com/json4s/json4s
- private implicit val serializationFormat = Serialization.formats(NoTypeHints)
-
- def save(path: Path, mappings: ProjectBundleClassPaths) {
- Files.createDirectories(path.getParent)
- val outputFile = Files.newBufferedWriter(path, StandardCharsets.UTF_8)
- try {
- Serialization.write(mappings, outputFile)
- } finally {
- outputFile.close()
- }
- }
-
- def load(path: Path): ProjectBundleClassPaths = {
- val inputFile = Files.newBufferedReader(path, StandardCharsets.UTF_8)
- Serialization.read[ProjectBundleClassPaths](inputFile)
- }
-}
diff --git a/vespajlib/src/main/java/com/yahoo/osgi/maven/ProjectBundleClassPaths.java b/vespajlib/src/main/java/com/yahoo/osgi/maven/ProjectBundleClassPaths.java
new file mode 100644
index 00000000000..92ba8b79572
--- /dev/null
+++ b/vespajlib/src/main/java/com/yahoo/osgi/maven/ProjectBundleClassPaths.java
@@ -0,0 +1,130 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.osgi.maven;
+
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.JsonDecoder;
+import com.yahoo.slime.JsonFormat;
+import com.yahoo.slime.Slime;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents the bundles in a maven project and the classpath elements
+ * corresponding to code that would end up in the bundle.
+ *
+ * @author tonytv
+ * @author bjorncs
+ */
+
+public class ProjectBundleClassPaths {
+ public static final String CLASSPATH_MAPPINGS_FILENAME = "bundle-plugin.bundle-classpath-mappings.json";
+
+ public final BundleClasspathMapping mainBundle;
+ public final List<BundleClasspathMapping> providedDependencies;
+
+ public ProjectBundleClassPaths(BundleClasspathMapping mainBundle,
+ List<BundleClasspathMapping> providedDependencies) {
+ this.mainBundle = mainBundle;
+ this.providedDependencies = providedDependencies;
+ }
+
+ public static void save(Path path, ProjectBundleClassPaths mappings) throws IOException {
+ Files.createDirectories(path.getParent());
+ try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(path))) {
+ save(out, mappings);
+ }
+ }
+
+ static void save(OutputStream out, ProjectBundleClassPaths mappings) throws IOException {
+ Slime slime = new Slime();
+ Cursor rootCursor = slime.setObject();
+ Cursor mainBundleCursor = rootCursor.setObject("mainBundle");
+ BundleClasspathMapping.save(mainBundleCursor, mappings.mainBundle);
+ Cursor dependenciesCursor = rootCursor.setArray("providedDependencies");
+ mappings.providedDependencies
+ .forEach(d -> BundleClasspathMapping.save(dependenciesCursor.addObject(), d));
+ new JsonFormat(false).encode(out, slime);
+ }
+
+ public static ProjectBundleClassPaths load(Path path) throws IOException {
+ byte[] bytes = Files.readAllBytes(path);
+ return load(bytes);
+ }
+
+ static ProjectBundleClassPaths load(byte[] bytes) {
+ Slime slime = new Slime();
+ new JsonDecoder().decode(slime, bytes);
+ Inspector inspector = slime.get();
+ BundleClasspathMapping mainBundle = BundleClasspathMapping.load(inspector.field("mainBundle"));
+ Inspector dependenciesInspector = inspector.field("providedDependencies");
+ List<BundleClasspathMapping> providedDependencies = new ArrayList<>();
+ for (int i = 0; i < dependenciesInspector.entries(); i++) {
+ providedDependencies.add(BundleClasspathMapping.load(dependenciesInspector.entry(i)));
+ }
+ return new ProjectBundleClassPaths(mainBundle, providedDependencies);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ProjectBundleClassPaths that = (ProjectBundleClassPaths) o;
+ return Objects.equals(mainBundle, that.mainBundle) &&
+ Objects.equals(providedDependencies, that.providedDependencies);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mainBundle, providedDependencies);
+ }
+
+ public static class BundleClasspathMapping {
+ public final String bundleSymbolicName;
+ public final List<String> classPathElements;
+
+ public BundleClasspathMapping(String bundleSymbolicName,
+ List<String> classPathElements) {
+ this.bundleSymbolicName = bundleSymbolicName;
+ this.classPathElements = classPathElements;
+ }
+
+ static void save(Cursor rootCursor, BundleClasspathMapping mapping) {
+ rootCursor.setString("bundleSymbolicName", mapping.bundleSymbolicName);
+ Cursor arrayCursor = rootCursor.setArray("classPathElements");
+ mapping.classPathElements.forEach(arrayCursor::addString);
+ }
+
+ static BundleClasspathMapping load(Inspector inspector) {
+ String bundleSymoblicName = inspector.field("bundleSymbolicName").asString();
+ Inspector elementsInspector = inspector.field("classPathElements");
+ List<String> classPathElements = new ArrayList<>();
+ for (int i = 0; i < elementsInspector.entries(); i++) {
+ classPathElements.add(elementsInspector.entry(i).asString());
+ }
+ return new BundleClasspathMapping(bundleSymoblicName, classPathElements);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ BundleClasspathMapping that = (BundleClasspathMapping) o;
+ return Objects.equals(bundleSymbolicName, that.bundleSymbolicName) &&
+ Objects.equals(classPathElements, that.classPathElements);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bundleSymbolicName, classPathElements);
+ }
+ }
+
+}
diff --git a/vespajlib/src/test/java/com/yahoo/osgi/maven/ProjectBundleClassPathsTest.java b/vespajlib/src/test/java/com/yahoo/osgi/maven/ProjectBundleClassPathsTest.java
new file mode 100644
index 00000000000..9bb66afd876
--- /dev/null
+++ b/vespajlib/src/test/java/com/yahoo/osgi/maven/ProjectBundleClassPathsTest.java
@@ -0,0 +1,35 @@
+package com.yahoo.osgi.maven;
+
+import com.yahoo.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author bjorncs
+ */
+public class ProjectBundleClassPathsTest {
+
+ @Test
+ public void bundle_classpaths_serializes_correctly_to_json() throws IOException {
+ ProjectBundleClassPaths projectBundleClassPaths =
+ new ProjectBundleClassPaths(
+ new BundleClasspathMapping("main-bundle-name", asList("classpath-elem-0-1", "classpath-elem-0-2")),
+ asList(
+ new BundleClasspathMapping(
+ "main-bundle-dep1",
+ asList("classpath-elem-1-1", "classpath-elem-1-2")),
+ new BundleClasspathMapping(
+ "main-bundle-dep2",
+ asList("classpath-elem-2-1", "classpath-elem-2-2"))));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ProjectBundleClassPaths.save(out, projectBundleClassPaths);
+ ProjectBundleClassPaths deserialized = ProjectBundleClassPaths.load(out.toByteArray());
+ assertEquals(projectBundleClassPaths, deserialized);
+ }
+
+}