You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ro...@apache.org on 2021/02/23 05:51:34 UTC
[aries-jax-rs-whiteboard] 03/03: ARIES-2030 major improvements and
refactoring
This is an automated email from the ASF dual-hosted git repository.
rotty3000 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-jax-rs-whiteboard.git
commit b0943eba7942e4505ef41c9be99230499cf71696
Author: Raymond Auge <ro...@apache.org>
AuthorDate: Mon Feb 22 23:55:47 2021 -0500
ARIES-2030 major improvements and refactoring
Signed-off-by: Raymond Auge <ro...@apache.org>
---
.../rest-management/rest-management-itest/bnd.bnd | 2 +-
.../rest-management-itest/itest.bndrun | 135 +--
.../rest-management/rest-management-itest/pom.xml | 33 +-
.../rs/rest/management/test/BundleHeaderTest.java | 35 +-
.../rest/management/test/BundleStartLevelTest.java | 25 +-
.../rs/rest/management/test/BundleStateTest.java | 434 +++++----
.../jax/rs/rest/management/test/BundleTest.java | 211 ++---
.../jax/rs/rest/management/test/BundlesTest.java | 261 +++---
.../management/test/FrameworkStartLevelTest.java | 57 +-
.../rest/management/test/FrameworkStateTest.java | 9 +-
.../jax/rs/rest/management/test/FrameworkTest.java | 29 +-
.../rs/rest/management/test/RestClientTest.java | 59 +-
.../jax/rs/rest/management/test/ServiceTest.java | 189 ++++
.../jax/rs/rest/management/test/ServicesTest.java | 242 +----
.../jax/rs/rest/management/test/TestUtil.java | 42 +-
.../rest-management/rest-management/README.md | 24 +
.../rest/management/RestManagementConstants.java | 4 +
.../management/feature/RestManagementFeature.java | 17 +
.../{handler => feature}/package-info.java | 2 +-
.../handler/DictionaryJsonDeserializer.java | 50 --
.../handler/DictionaryJsonSerializer.java | 64 --
.../handler/RestManagementMessageBodyHandler.java | 992 ---------------------
.../ServiceReferenceDTOJsonDeserializer.java | 71 --
.../handler/ServiceReferenceDTOJsonSerializer.java | 66 --
.../ServiceReferenceDTOXMLDeserializer.java | 132 ---
.../handler/ServiceReferenceDTOXMLSerializer.java | 178 ----
.../rest/management/handler/XMLDeserializer.java | 60 --
.../rs/rest/management/handler/XMLSerializer.java | 81 --
.../rs/rest/management/internal/BaseResource.java | 153 ++++
.../internal/FrameworkBundleHeaderResource.java | 113 +++
.../internal/FrameworkBundleResource.java | 326 +++++++
.../FrameworkBundleStartLevelResource.java | 199 +++++
.../internal/FrameworkBundleStateResource.java | 226 +++++
.../FrameworkBundlesRepresentationsResource.java | 114 +++
.../internal/FrameworkBundlesResource.java | 281 ++++++
.../management/internal/FrameworkResource.java | 678 +-------------
.../internal/FrameworkServiceResource.java | 110 +++
.../FrameworkServicesRepresentationsResource.java | 125 +++
.../internal/FrameworkServicesResource.java | 131 +++
.../internal/FrameworkStartLevelResource.java | 136 +++
.../internal/FrameworkStateResource.java | 91 ++
.../rest/management/internal/RestClientImpl.java | 507 -----------
.../internal/RestManagementActivator.java | 75 +-
.../internal/RestManagementApplication.java | 34 +
.../{ => client}/RestClientFactoryImpl.java | 2 +-
.../management/internal/client/RestClientImpl.java | 786 ++++++++++++++++
.../{handler => internal/coerce}/Coerce.java | 10 +-
.../jaxb/ServiceSchemaContextResolver.java | 55 ++
.../internal/map/CaseInsensitiveMap.java | 116 +++
.../rs/rest/management/internal/package-info.java | 2 -
.../aries/jax/rs/rest/management/package-info.java | 17 +
.../BundleExceptionSchema.java} | 21 +-
.../management/schema/BundleHeaderAdapter.java | 45 +
.../BundleHeaderSchema.java} | 23 +-
.../BundleListSchema.java} | 21 +-
.../rs/rest/management/schema/BundleSchema.java | 51 ++
.../BundleSchemaListSchema.java} | 19 +-
.../management/schema/BundleStartLevelSchema.java | 45 +
.../BundleStateSchema.java} | 14 +-
.../schema/FrameworkStartLevelSchema.java | 41 +
.../rest/management/schema/PropertiesAdapter.java | 149 ++++
.../ServiceListSchema.java} | 18 +-
.../rs/rest/management/schema/ServiceSchema.java | 40 +
.../management/schema/ServiceSchemaAdapter.java | 40 +
.../ServiceSchemaListSchema.java} | 20 +-
.../management/{model => schema}/package-info.java | 2 +-
jax-rs.itests/itest.bndrun | 2 +-
pom.xml | 35 +
68 files changed, 4473 insertions(+), 3904 deletions(-)
diff --git a/integrations/rest-management/rest-management-itest/bnd.bnd b/integrations/rest-management/rest-management-itest/bnd.bnd
index eb946df..9ac2ecd 100644
--- a/integrations/rest-management/rest-management-itest/bnd.bnd
+++ b/integrations/rest-management/rest-management-itest/bnd.bnd
@@ -17,4 +17,4 @@
Bundle-Description: Integration Test bundle for the REST Management integration
-Test-Cases: ${classes;CONCRETE;ANNOTATED;org.junit.Test}
+Test-Cases: ${classes;CONCRETE;ANNOTATED;org.junit.jupiter.api.Test}
diff --git a/integrations/rest-management/rest-management-itest/itest.bndrun b/integrations/rest-management/rest-management-itest/itest.bndrun
index 91be3f9..85a1725 100644
--- a/integrations/rest-management/rest-management-itest/itest.bndrun
+++ b/integrations/rest-management/rest-management-itest/itest.bndrun
@@ -15,6 +15,8 @@
# specific language governing permissions and limitations
# under the License.
+-tester: biz.aQute.tester.junit-platform
+
-runpath: \
ch.qos.logback.classic,\
ch.qos.logback.core,\
@@ -38,7 +40,9 @@
osgi.identity;filter:='(osgi.identity=org.apache.aries.jax.rs.rest.management)',\
osgi.identity;filter:='(osgi.identity=org.apache.aries.jax.rs.rest.management.itest)',\
osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)',\
- osgi.identity;filter:='(osgi.identity=org.apache.johnzon.mapper)'
+ osgi.identity;filter:='(osgi.identity=org.apache.johnzon.mapper)',\
+ bnd.identity;id='junit-jupiter-engine',\
+ bnd.identity;id='junit-platform-launcher'
-runsystemcapabilities: ${native_capability}
-runproperties: \
@@ -51,67 +55,74 @@
org.apache.aries.spifly.auto.providers=com.sun.*
-runbundles: \
- assertj-core;version='[3.19.0,3.19.1)',\
- com.fasterxml.jackson.core.jackson-annotations;version='[2.10.1,2.10.2)',\
- com.fasterxml.jackson.core.jackson-core;version='[2.10.1,2.10.2)',\
- com.fasterxml.jackson.core.jackson-databind;version='[2.10.1,2.10.2)',\
- com.fasterxml.jackson.dataformat.jackson-dataformat-yaml;version='[2.10.1,2.10.2)',\
- com.fasterxml.jackson.datatype.jackson-datatype-jsr310;version='[2.10.1,2.10.2)',\
- com.fasterxml.woodstox.woodstox-core;version='[6.2.3,6.2.4)',\
- com.jayway.jsonpath.json-path;version='[2.4.0,2.4.1)',\
- com.sun.istack.commons-runtime;version='[3.0.11,3.0.12)',\
- com.sun.xml.bind.jaxb-osgi;version='[2.3.3,2.3.4)',\
- io.github.classgraph.classgraph;version='[4.6.32,4.6.33)',\
- io.swagger.core.v3.swagger-annotations;version='[2.1.0,2.1.1)',\
- io.swagger.core.v3.swagger-core;version='[2.1.0,2.1.1)',\
- io.swagger.core.v3.swagger-integration;version='[2.1.0,2.1.1)',\
- io.swagger.core.v3.swagger-jaxrs2;version='[2.1.0,2.1.1)',\
- io.swagger.core.v3.swagger-models;version='[2.1.0,2.1.1)',\
- jakarta.xml.bind-api;version='[2.3.3,2.3.4)',\
- javax.validation.api;version='[1.1.0,1.1.1)',\
- net.javacrumbs.json-unit.json-unit-assertj;version='[2.24.0,2.24.1)',\
- net.javacrumbs.json-unit.json-unit-core;version='[2.24.0,2.24.1)',\
- net.javacrumbs.json-unit.json-unit-json-path;version='[2.24.0,2.24.1)',\
- net.minidev.accessors-smart;version='[1.2.0,1.2.1)',\
- net.minidev.json-smart;version='[2.3.0,2.3.1)',\
- org.apache.aries.jax.rs.openapi.resource;version='[2.0.0,2.0.1)',\
- org.apache.aries.jax.rs.rest.management;version='[2.0.0,2.0.1)',\
- org.apache.aries.jax.rs.rest.management.itest;version='[2.0.0,2.0.1)',\
- org.apache.aries.jax.rs.whiteboard;version='[2.0.0,2.0.1)',\
- org.apache.aries.spifly.dynamic.framework.extension;version='[1.3.2,1.3.3)',\
- org.apache.commons.lang3;version='[3.7.0,3.7.1)',\
- org.apache.cxf.cxf-core;version='[3.4.2,3.4.3)',\
- org.apache.cxf.cxf-rt-frontend-jaxrs;version='[3.4.2,3.4.3)',\
- org.apache.cxf.cxf-rt-rs-client;version='[3.4.2,3.4.3)',\
- org.apache.cxf.cxf-rt-rs-sse;version='[3.4.2,3.4.3)',\
- org.apache.cxf.cxf-rt-security;version='[3.4.2,3.4.3)',\
- org.apache.cxf.cxf-rt-transports-http;version='[3.4.2,3.4.3)',\
- org.apache.felix.configadmin;version='[1.9.20,1.9.21)',\
- org.apache.felix.gogo.command;version='[1.1.2,1.1.3)',\
- org.apache.felix.gogo.runtime;version='[1.1.4,1.1.5)',\
- org.apache.felix.gogo.shell;version='[1.1.4,1.1.5)',\
- org.apache.felix.http.jetty;version='[4.1.4,4.1.5)',\
- org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
- org.apache.geronimo.specs.geronimo-annotation_1.3_spec;version='[1.3.0,1.3.1)',\
- org.apache.geronimo.specs.geronimo-jaxrs_2.1_spec;version='[1.1.0,1.1.1)',\
- org.apache.geronimo.specs.geronimo-json_1.1_spec;version='[1.5.0,1.5.1)',\
- org.apache.johnzon.core;version='[1.2.10,1.2.11)',\
- org.apache.johnzon.mapper;version='[1.2.10,1.2.11)',\
- org.apache.servicemix.bundles.junit;version='[4.13.0,4.13.1)',\
- org.apache.ws.xmlschema.core;version='[2.2.5,2.2.6)',\
- org.hamcrest;version='[2.2.0,2.2.1)',\
- org.objectweb.asm;version='[5.0.4,5.0.5)',\
- org.osgi.service.jaxrs;version='[1.0.0,1.0.1)',\
- org.osgi.service.rest;version='[1.0.0,1.0.1)',\
- org.osgi.test.assertj.framework;version='[0.10.0,0.10.1)',\
- org.osgi.test.common;version='[0.10.0,0.10.1)',\
- org.osgi.test.junit4;version='[0.10.0,0.10.1)',\
- org.osgi.util.function;version='[1.1.0,1.1.1)',\
- org.osgi.util.promise;version='[1.1.1,1.1.2)',\
- org.xmlunit.xmlunit-assertj3;version='[2.8.2,2.8.3)',\
- org.xmlunit.xmlunit-core;version='[2.8.2,2.8.3)',\
- org.yaml.snakeyaml;version='[1.24.0,1.24.1)',\
- stax2-api;version='[4.2.1,4.2.2)'
+ assertj-core;version='[3.19.0,3.19.1)',\
+ com.fasterxml.jackson.core.jackson-annotations;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.core.jackson-core;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.core.jackson-databind;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.dataformat.jackson-dataformat-yaml;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.datatype.jackson-datatype-jsr310;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.jaxrs.jackson-jaxrs-base;version='[2.10.1,2.10.2)',\
+ com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider;version='[2.10.1,2.10.2)',\
+ com.fasterxml.woodstox.woodstox-core;version='[6.2.3,6.2.4)',\
+ com.jayway.jsonpath.json-path;version='[2.4.0,2.4.1)',\
+ com.sun.istack.commons-runtime;version='[3.0.11,3.0.12)',\
+ com.sun.xml.bind.jaxb-osgi;version='[2.3.3,2.3.4)',\
+ io.github.classgraph.classgraph;version='[4.6.32,4.6.33)',\
+ io.swagger.core.v3.swagger-annotations;version='[2.1.0,2.1.1)',\
+ io.swagger.core.v3.swagger-core;version='[2.1.0,2.1.1)',\
+ io.swagger.core.v3.swagger-integration;version='[2.1.0,2.1.1)',\
+ io.swagger.core.v3.swagger-jaxrs2;version='[2.1.0,2.1.1)',\
+ io.swagger.core.v3.swagger-models;version='[2.1.0,2.1.1)',\
+ jakarta.xml.bind-api;version='[2.3.3,2.3.4)',\
+ javax.validation.api;version='[1.1.0,1.1.1)',\
+ junit-jupiter-api;version='[5.6.0,5.6.1)',\
+ junit-jupiter-engine;version='[5.6.0,5.6.1)',\
+ junit-platform-commons;version='[1.6.0,1.6.1)',\
+ junit-platform-engine;version='[1.6.0,1.6.1)',\
+ junit-platform-launcher;version='[1.6.0,1.6.1)',\
+ net.javacrumbs.json-unit.json-unit-assertj;version='[2.24.0,2.24.1)',\
+ net.javacrumbs.json-unit.json-unit-core;version='[2.24.0,2.24.1)',\
+ net.javacrumbs.json-unit.json-unit-json-path;version='[2.24.0,2.24.1)',\
+ net.minidev.accessors-smart;version='[1.2.0,1.2.1)',\
+ net.minidev.json-smart;version='[2.3.0,2.3.1)',\
+ org.apache.aries.jax.rs.openapi.resource;version='[2.0.0,2.0.1)',\
+ org.apache.aries.jax.rs.rest.management;version='[2.0.0,2.0.1)',\
+ org.apache.aries.jax.rs.rest.management.itest;version='[2.0.0,2.0.1)',\
+ org.apache.aries.jax.rs.whiteboard;version='[2.0.0,2.0.1)',\
+ org.apache.aries.spifly.dynamic.framework.extension;version='[1.3.2,1.3.3)',\
+ org.apache.commons.lang3;version='[3.7.0,3.7.1)',\
+ org.apache.cxf.cxf-core;version='[3.4.2,3.4.3)',\
+ org.apache.cxf.cxf-rt-frontend-jaxrs;version='[3.4.2,3.4.3)',\
+ org.apache.cxf.cxf-rt-rs-client;version='[3.4.2,3.4.3)',\
+ org.apache.cxf.cxf-rt-rs-sse;version='[3.4.2,3.4.3)',\
+ org.apache.cxf.cxf-rt-security;version='[3.4.2,3.4.3)',\
+ org.apache.cxf.cxf-rt-transports-http;version='[3.4.2,3.4.3)',\
+ org.apache.felix.configadmin;version='[1.9.20,1.9.21)',\
+ org.apache.felix.gogo.command;version='[1.1.2,1.1.3)',\
+ org.apache.felix.gogo.runtime;version='[1.1.4,1.1.5)',\
+ org.apache.felix.gogo.shell;version='[1.1.4,1.1.5)',\
+ org.apache.felix.http.jetty;version='[4.1.4,4.1.5)',\
+ org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
+ org.apache.geronimo.specs.geronimo-annotation_1.3_spec;version='[1.3.0,1.3.1)',\
+ org.apache.geronimo.specs.geronimo-jaxrs_2.1_spec;version='[1.1.0,1.1.1)',\
+ org.apache.geronimo.specs.geronimo-json_1.1_spec;version='[1.5.0,1.5.1)',\
+ org.apache.johnzon.core;version='[1.2.10,1.2.11)',\
+ org.apache.johnzon.mapper;version='[1.2.10,1.2.11)',\
+ org.apache.ws.xmlschema.core;version='[2.2.5,2.2.6)',\
+ org.hamcrest;version='[2.2.0,2.2.1)',\
+ org.objectweb.asm;version='[5.0.4,5.0.5)',\
+ org.opentest4j;version='[1.2.0,1.2.1)',\
+ org.osgi.service.jaxrs;version='[1.0.0,1.0.1)',\
+ org.osgi.service.rest;version='[1.0.0,1.0.1)',\
+ org.osgi.test.assertj.framework;version='[0.10.0,0.10.1)',\
+ org.osgi.test.common;version='[0.10.0,0.10.1)',\
+ org.osgi.test.junit5;version='[0.10.0,0.10.1)',\
+ org.osgi.util.function;version='[1.1.0,1.1.1)',\
+ org.osgi.util.promise;version='[1.1.1,1.1.2)',\
+ org.xmlunit.xmlunit-assertj3;version='[2.8.2,2.8.3)',\
+ org.xmlunit.xmlunit-core;version='[2.8.2,2.8.3)',\
+ org.yaml.snakeyaml;version='[1.24.0,1.24.1)',\
+ stax2-api;version='[4.2.1,4.2.2)'
-runstartlevel: \
order=sortbynameversion,\
diff --git a/integrations/rest-management/rest-management-itest/pom.xml b/integrations/rest-management/rest-management-itest/pom.xml
index 4a324c7..977ea08 100644
--- a/integrations/rest-management/rest-management-itest/pom.xml
+++ b/integrations/rest-management/rest-management-itest/pom.xml
@@ -30,6 +30,10 @@
<dependencies>
<dependency>
+ <groupId>net.javacrumbs.json-unit</groupId>
+ <artifactId>json-unit-assertj</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
@@ -49,33 +53,33 @@
<artifactId>org.apache.aries.component-dsl.component-dsl</artifactId>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.service.rest</artifactId>
- <version>1.0.0</version>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>osgi.enroute.junit.wrapper</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>osgi.enroute.hamcrest.wrapper</artifactId>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-commons</artifactId>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.test.assertj.framework</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.test.junit4</artifactId>
+ <artifactId>org.osgi.service.rest</artifactId>
+ <version>1.0.0</version>
</dependency>
<dependency>
- <groupId>net.javacrumbs.json-unit</groupId>
- <artifactId>json-unit-assertj</artifactId>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.test.assertj.framework</artifactId>
</dependency>
<dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-core</artifactId>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.test.junit5</artifactId>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
@@ -95,6 +99,7 @@
<configuration>
<failOnChanges>false</failOnChanges>
<includeDependencyManagement>true</includeDependencyManagement>
+ <reportOptional>false</reportOptional>
<bndruns>
<bndrun>itest.bndrun</bndrun>
</bndruns>
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleHeaderTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleHeaderTest.java
index fc54384..b551af1 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleHeaderTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleHeaderTest.java
@@ -21,30 +21,17 @@ import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.AP
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEHEADER_XML_TYPE;
import static org.assertj.core.api.Assertions.assertThat;
-import java.util.Dictionary;
-
import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Rule;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.test.common.annotation.InjectBundleContext;
-import org.osgi.test.junit4.context.BundleContextRule;
+import org.apache.aries.jax.rs.rest.management.schema.BundleHeaderSchema;
+import org.junit.jupiter.api.Test;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class BundleHeaderTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@Test
public void getBundleHeaderJSON() {
WebTarget target = createDefaultTarget().path(
@@ -85,28 +72,25 @@ public class BundleHeaderTest extends TestUtil {
result
).isInvalid(
).valueByXPath(
- "//bundleHeader/entry/@key"
+ "//bundleHeader/entry[@key = 'Bundle-ManifestVersion']/@value"
).isEqualTo(
- "Bundle-Name"
+ "2"
);
}
@Test
- public void getBundleHeaderDictionaryJSON() {
+ public void getBundleHeaderDTOJSON() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundle").path("{bundleid}").path("header");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.resolveTemplate(
"bundleid", 2l
).request(
APPLICATION_BUNDLEHEADER_JSON_TYPE
).get();
- Dictionary<String, String> bundleHeader = response.readEntity(
- new GenericType<Dictionary<String, String>>() {});
+ BundleHeaderSchema bundleHeader = response.readEntity(BundleHeaderSchema.class);
assertThat(
bundleHeader
@@ -118,21 +102,18 @@ public class BundleHeaderTest extends TestUtil {
}
@Test
- public void getBundleHeaderDictionaryXML() {
+ public void getBundleHeaderDTOXML() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundle").path("{bundleid}").path("header");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.resolveTemplate(
"bundleid", 2l
).request(
APPLICATION_BUNDLEHEADER_XML_TYPE
).get();
- Dictionary<String, String> bundleHeader = response.readEntity(
- new GenericType<Dictionary<String, String>>() {});
+ BundleHeaderSchema bundleHeader = response.readEntity(BundleHeaderSchema.class);
assertThat(
bundleHeader
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStartLevelTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStartLevelTest.java
index 4852bbe..d42c864 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStartLevelTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStartLevelTest.java
@@ -25,9 +25,8 @@ import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Test;
-import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStartLevelSchema;
+import org.junit.jupiter.api.Test;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
@@ -92,16 +91,14 @@ public class BundleStartLevelTest extends TestUtil {
}
@Test
- public void getBundleStartLevelDTO() {
+ public void getBundleStartLevelSchema() {
WebTarget target = createDefaultTarget().path(
"framework").path("bundle").path("{bundleid}").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.resolveTemplate("bundleid", 2l).request().get();
- BundleStartLevelDTO bundleStartLevelDTO =
- response.readEntity(BundleStartLevelDTO.class);
+ BundleStartLevelSchema bundleStartLevelDTO =
+ response.readEntity(BundleStartLevelSchema.class);
assertThat(
bundleStartLevelDTO.startLevel
@@ -115,10 +112,8 @@ public class BundleStartLevelTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundle").path("{bundleid}").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleStartLevelDTO bundleStartLevelDTO =
- new BundleStartLevelDTO();
+ BundleStartLevelSchema bundleStartLevelDTO =
+ new BundleStartLevelSchema();
Response response = target.resolveTemplate("bundleid", 2l).request().put(
Entity.entity(
@@ -136,10 +131,8 @@ public class BundleStartLevelTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundle").path("{bundleid}").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleStartLevelDTO bundleStartLevelDTO =
- new BundleStartLevelDTO();
+ BundleStartLevelSchema bundleStartLevelDTO =
+ new BundleStartLevelSchema();
bundleStartLevelDTO.startLevel = 2;
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStateTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStateTest.java
index 39df806..8fc7239 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStateTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleStateTest.java
@@ -26,27 +26,16 @@ import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import org.apache.aries.jax.rs.rest.management.RestManagementConstants;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.apache.aries.jax.rs.rest.management.model.BundleStateDTO;
-import org.junit.Rule;
-import org.junit.Test;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.junit.jupiter.api.Test;
import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.dto.BundleDTO;
-import org.osgi.test.common.annotation.InjectBundleContext;
-import org.osgi.test.junit4.context.BundleContextRule;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class BundleStateTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@Test
public void getBundleStateJSON() {
WebTarget target = createDefaultTarget().path(
@@ -98,15 +87,13 @@ public class BundleStateTest extends TestUtil {
"framework"
).path("bundle").path("{bundleid}").path("state");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.resolveTemplate(
"bundleid", 2l
).request(
APPLICATION_BUNDLESTATE_JSON_TYPE
).get();
- BundleStateDTO bundleStateDTO = response.readEntity(BundleStateDTO.class);
+ BundleStateSchema bundleStateDTO = response.readEntity(BundleStateSchema.class);
assertThat(
bundleStateDTO
@@ -120,68 +107,61 @@ public class BundleStateTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().post(
- Entity.entity(
- BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- assertThat(
- bundleDTO.state
- ).isEqualTo(
- 2
- );
-
- target = createDefaultTarget().path(
- "framework").path("bundle").path("{bundleid}").path("state");
-
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
-
- response = target.resolveTemplate(
- "bundleid", bundleDTO.id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleStateDTO = response.readEntity(BundleStateDTO.class);
-
- assertThat(
- bundleStateDTO.state
- ).isEqualTo(
- 32
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
+ BundleSchema bundleSchema = null;
+
+ Response response = target.request().post(
+ Entity.entity(
+ BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ assertThat(
+ bundleSchema.state
+ ).isEqualTo(
+ 2
+ );
+
+ target = createDefaultTarget().path(
+ "framework").path("bundle").path("{bundleid}").path("state");
+
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+
+ response = target.resolveTemplate(
+ "bundleid", bundleSchema.id
+ ).request().put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleStateDTO = response.readEntity(BundleStateSchema.class);
+
+ assertThat(
+ bundleStateDTO.state
+ ).isIn(
+ 2, 32
+ );
}
@Test
@@ -189,68 +169,61 @@ public class BundleStateTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().post(
- Entity.entity(
- BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- assertThat(
- bundleDTO.state
- ).isEqualTo(
- 2
- );
-
- target = createDefaultTarget().path(
- "framework").path("bundle").path("{bundleid}").path("state");
-
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
-
- response = target.resolveTemplate(
- "bundleid", bundleDTO.id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleStateDTO = response.readEntity(BundleStateDTO.class);
-
- assertThat(
- bundleStateDTO.state
- ).isEqualTo(
- Bundle.RESOLVED
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
+ BundleSchema bundleSchema = null;
+
+ Response response = target.request().post(
+ Entity.entity(
+ BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ assertThat(
+ bundleSchema.state
+ ).isEqualTo(
+ 2
+ );
+
+ target = createDefaultTarget().path(
+ "framework").path("bundle").path("{bundleid}").path("state");
+
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+
+ response = target.resolveTemplate(
+ "bundleid", bundleSchema.id
+ ).request().put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleStateDTO = response.readEntity(BundleStateSchema.class);
+
+ assertThat(
+ bundleStateDTO.state
+ ).isEqualTo(
+ Bundle.RESOLVED
+ );
}
@Test
@@ -258,99 +231,92 @@ public class BundleStateTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().post(
- Entity.entity(
- BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- assertThat(
- bundleDTO.state
- ).isEqualTo(
- 2
- );
-
- target = createDefaultTarget().path(
- "framework").path("bundle").path("{bundleid}").path("state");
-
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
-
- response = target.resolveTemplate(
- "bundleid", bundleDTO.id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleStateDTO = response.readEntity(BundleStateDTO.class);
-
- assertThat(
- bundleStateDTO.state
- ).isEqualTo(
- 32
- );
-
- ////////////////
-
- target = createDefaultTarget().path(
- "framework").path("bundle").path("{bundleid}").path("state");
-
- bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
-
- response = target.resolveTemplate(
- "bundleid", bundleDTO.id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- );
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleStateDTO = response.readEntity(BundleStateDTO.class);
-
- assertThat(
- bundleStateDTO.state
- ).isEqualTo(
- Bundle.RESOLVED
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
+ BundleSchema bundleSchema = null;
+
+ Response response = target.request().post(
+ Entity.entity(
+ BundleStateTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ assertThat(
+ bundleSchema.state
+ ).isEqualTo(
+ 2
+ );
+
+ target = createDefaultTarget().path(
+ "framework").path("bundle").path("{bundleid}").path("state");
+
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+
+ response = target.resolveTemplate(
+ "bundleid", bundleSchema.id
+ ).request().put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleStateDTO = response.readEntity(BundleStateSchema.class);
+
+ assertThat(
+ bundleStateDTO.state
+ ).isIn(
+ 2, 32
+ );
+
+ ////////////////
+
+ target = createDefaultTarget().path(
+ "framework").path("bundle").path("{bundleid}").path("state");
+
+ bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+
+ response = target.resolveTemplate(
+ "bundleid", bundleSchema.id
+ ).request().put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleStateDTO = response.readEntity(BundleStateSchema.class);
+
+ assertThat(
+ bundleStateDTO.state
+ ).isEqualTo(
+ Bundle.RESOLVED
+ );
}
}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleTest.java
index 0f58563..95805b0 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundleTest.java
@@ -23,31 +23,23 @@ import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.AP
import static org.assertj.core.api.Assertions.assertThat;
import static org.osgi.framework.Bundle.UNINSTALLED;
+import java.net.URL;
+
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Rule;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.dto.BundleDTO;
-import org.osgi.test.common.annotation.InjectBundleContext;
-import org.osgi.test.junit4.context.BundleContextRule;
+import org.apache.aries.jax.rs.rest.management.RestManagementConstants;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.junit.jupiter.api.Test;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class BundleTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@Test
public void getBundleJSON() {
WebTarget target = createDefaultTarget().path(
@@ -91,109 +83,36 @@ public class BundleTest extends TestUtil {
}
@Test
- public void getBundleDTO() {
+ public void getBundleSchema() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundle").path("{bundleid}");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.resolveTemplate(
"bundleid", 2l
).request(APPLICATION_BUNDLE_JSON_TYPE).get();
- BundleDTO bundleDTO = response.readEntity(BundleDTO.class);
+ BundleSchema bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.id
+ bundleSchema.id
).isEqualTo(2);
}
@Test
public void putBundleByLocation() throws Exception {
- try (HttpServer server = new HttpServer(
- BundleTest.class.getClassLoader().getResource("minor-change-1.0.1.jar"),
- "application/zip")) {
-
+ URL resource = BundleTest.class.getClassLoader().getResource("minor-change-1.0.1.jar");
+ try (HttpServer server = new HttpServer(resource, "application/zip")) {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().post(
- Entity.entity(String.format(
- "http://localhost:%d/minor-change-1.0.1.jar",
- server.getPort()),
- MediaType.TEXT_PLAIN));
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
-
- target = createDefaultTarget().path(
- "framework").path("bundle").path("{bundleid}");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- response = target.resolveTemplate(
- "bundleid", bundleDTO.id
- ).request().put(
- Entity.entity(String.format(
- "http://localhost:%d/minor-change-1.0.1.jar",
- server.getPort()),
- MediaType.TEXT_PLAIN));
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
- }
- }
-
- @Test
- public void putBundleByUpload() throws Exception {
- WebTarget target = createDefaultTarget().path(
- "framework").path("bundles");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleDTO bundleDTO = null;
+ BundleSchema bundleSchema = null;
- try {
- Response response = target.request().header(
- HttpHeaders.CONTENT_LOCATION, "minor-change-1.0.1.jar"
- ).post(
+ Response response = target.request().post(
Entity.entity(
- BundleTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- APPLICATION_VNDOSGIBUNDLE)
+ resource.openStream(),
+ RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE
+ )
);
assertThat(
@@ -202,27 +121,24 @@ public class BundleTest extends TestUtil {
200
);
- bundleDTO = response.readEntity(BundleDTO.class);
+ bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.symbolicName
+ bundleSchema.symbolicName
).isEqualTo(
"minor-and-removed-change"
);
target = createDefaultTarget().path(
- "framework"
- ).path("bundle").path("{bundleid}");
-
- target.register(RestManagementMessageBodyHandler.class);
+ "framework").path("bundle").path("{bundleid}");
response = target.resolveTemplate(
- "bundleid", bundleDTO.id
+ "bundleid", bundleSchema.id
).request().put(
- Entity.entity(
- BundleTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- APPLICATION_VNDOSGIBUNDLE)
- );
+ Entity.entity(String.format(
+ "http://localhost:%d/minor-change-1.0.1.jar",
+ server.getPort()),
+ MediaType.TEXT_PLAIN));
assertThat(
response.getStatus()
@@ -230,29 +146,22 @@ public class BundleTest extends TestUtil {
200
);
- bundleDTO = response.readEntity(BundleDTO.class);
+ bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.symbolicName
+ bundleSchema.symbolicName
).isEqualTo(
"minor-and-removed-change"
);
}
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
}
@Test
- public void deleteBundle() throws Exception {
+ public void putBundleByUpload() throws Exception {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleDTO bundleDTO = null;
+ BundleSchema bundleSchema = null;
Response response = target.request().header(
HttpHeaders.CONTENT_LOCATION, "minor-change-1.0.1.jar"
@@ -268,10 +177,10 @@ public class BundleTest extends TestUtil {
200
);
- bundleDTO = response.readEntity(BundleDTO.class);
+ bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.symbolicName
+ bundleSchema.symbolicName
).isEqualTo(
"minor-and-removed-change"
);
@@ -280,10 +189,64 @@ public class BundleTest extends TestUtil {
"framework"
).path("bundle").path("{bundleid}");
- target.register(RestManagementMessageBodyHandler.class);
+ response = target.resolveTemplate(
+ "bundleid", bundleSchema.id
+ ).request().put(
+ Entity.entity(
+ BundleTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ APPLICATION_VNDOSGIBUNDLE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ }
+
+ @Test
+ public void deleteBundle() throws Exception {
+ WebTarget target = createDefaultTarget().path(
+ "framework").path("bundles");
+
+ BundleSchema bundleSchema = null;
+
+ Response response = target.request().header(
+ HttpHeaders.CONTENT_LOCATION, "minor-change-1.0.1.jar"
+ ).post(
+ Entity.entity(
+ BundleTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ APPLICATION_VNDOSGIBUNDLE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+
+ target = createDefaultTarget().path(
+ "framework"
+ ).path("bundle").path("{bundleid}");
response = target.resolveTemplate(
- "bundleid", bundleDTO.id
+ "bundleid", bundleSchema.id
).request().delete();
assertThat(
@@ -292,10 +255,10 @@ public class BundleTest extends TestUtil {
200
);
- bundleDTO = response.readEntity(BundleDTO.class);
+ bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.state
+ bundleSchema.state
).matches(
state -> (state & UNINSTALLED) == UNINSTALLED
);
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundlesTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundlesTest.java
index 1b50680..136aa99 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundlesTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/BundlesTest.java
@@ -25,40 +25,25 @@ import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.AP
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_XML_TYPE;
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_VNDOSGIBUNDLE_TYPE;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.aries.jax.rs.rest.management.RestManagementConstants;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.apache.aries.jax.rs.rest.management.model.BundlesDTO;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.dto.BundleDTO;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchemaListSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleListSchema;
+import org.junit.jupiter.api.Test;
import org.osgi.test.assertj.bundle.BundleAssert;
-import org.osgi.test.common.annotation.InjectBundleContext;
-import org.osgi.test.junit4.context.BundleContextRule;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class BundlesTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@Test
public void getBundlesJSON() {
WebTarget target = createDefaultTarget().path(
@@ -87,8 +72,7 @@ public class BundlesTest extends TestUtil {
);
}
- @Ignore
- @Test
+ //@Test
public void getBundlesJSON_DOT() {
WebTarget target = createDefaultTarget().path(
"framework"
@@ -124,8 +108,7 @@ public class BundlesTest extends TestUtil {
).contains("/framework/bundle/0");
}
- @Ignore
- @Test
+ //@Test
public void getBundlesXML_DOT() {
WebTarget target = createDefaultTarget().path("framework").path("bundles.xml");
@@ -144,32 +127,28 @@ public class BundlesTest extends TestUtil {
public void getBundlesDTOJSON() {
WebTarget target = createDefaultTarget().path("framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request().get();
- BundlesDTO bundlesDTO = response.readEntity(BundlesDTO.class);
+ BundleListSchema bundlesDTO = response.readEntity(BundleListSchema.class);
- assertTrue(bundlesDTO.toString(), bundlesDTO.bundles.size() > 0);
+ assertThat(bundlesDTO.bundles.size()).isGreaterThan(0);
}
@Test
public void getBundlesDTOXML() {
WebTarget target = createDefaultTarget().path("framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_BUNDLES_XML_TYPE
).get();
- BundlesDTO bundlesDTO = response.readEntity(BundlesDTO.class);
+ BundleListSchema bundlesDTO = response.readEntity(BundleListSchema.class);
- assertTrue(bundlesDTO.toString(), bundlesDTO.bundles.size() > 0);
+ assertThat(bundlesDTO.bundles.size()).isGreaterThan(0);
}
@Test
- public void getBundleDTOsJSON() {
+ public void getBundleSchemasJSON() {
WebTarget target = createDefaultTarget().path("framework").path(
"bundles"
).path("representations");
@@ -183,19 +162,22 @@ public class BundlesTest extends TestUtil {
JsonAssertions.assertThatJson(
result
).and(
- j -> j.isArray(),
- j -> j.node("[0]").and(
- j1 -> j1.node("id").isNumber(),
- j1 -> j1.node("lastModified").isNumber(),
- j1 -> j1.node("state").isNumber(),
- j1 -> j1.node("symbolicName").isString(),
- j1 -> j1.node("version").isString()
+ j -> j.isObject(),
+ j -> j.node("bundles").and(
+ j1 -> j1.isArray(),
+ j1 -> j1.node("[0]").and(
+ j2 -> j2.node("id").isNumber(),
+ j2 -> j2.node("lastModified").isNumber(),
+ j2 -> j2.node("state").isNumber(),
+ j2 -> j2.node("symbolicName").isString(),
+ j2 -> j2.node("version").isString()
+ )
)
);
}
@Test
- public void getBundleDTOsXML() {
+ public void getBundleSchemasXML() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
@@ -214,32 +196,28 @@ public class BundlesTest extends TestUtil {
}
@Test
- public void getBundleDTOs_ListJSON() {
+ public void getBundleSchemas_ListJSON() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).isNotEmpty();
}
@Test
- public void getBundleDTOs_ListJSON_FilterError() {
+ public void getBundleSchemas_ListJSON_FilterError() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"osgi.wiring.package", "osgi.wiring.package=org.*"
).request(
@@ -252,55 +230,49 @@ public class BundlesTest extends TestUtil {
}
@Test
- public void getBundleDTOs_ListJSON_Filter_nomatch() {
+ public void getBundleSchemas_ListJSON_Filter_nomatch() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"osgi.wiring.package", "(osgi.wiring.package=org.osgi.service.jaxrs)"
).request(
APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).hasSize(0);
}
@Test
- public void getBundleDTOs_ListJSON_Filter() {
+ public void getBundleSchemas_ListJSON_Filter() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"osgi.wiring.package", "(osgi.wiring.package=org.osgi.service.*)"
).request(
APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).hasSize(5);
}
@Test
- public void getBundleDTOs_ListJSON_FilterOr() {
+ public void getBundleSchemas_ListJSON_FilterOr() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"osgi.wiring.package", "(osgi.wiring.package=org.osgi.service.jaxrs.whiteboard)"
).queryParam(
@@ -309,21 +281,19 @@ public class BundlesTest extends TestUtil {
APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).hasSize(2);
}
@Test
- public void getBundleDTOs_ListJSON_FilterAnd() {
+ public void getBundleSchemas_ListJSON_FilterAnd() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"osgi.wiring.package", "(osgi.wiring.package=org.osgi.service.*)"
).queryParam(
@@ -332,29 +302,27 @@ public class BundlesTest extends TestUtil {
APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).hasSize(3);
}
@Test
- public void getBundleDTOs_ListXML() {
+ public void getBundleSchemas_ListXML() {
WebTarget target = createDefaultTarget().path(
"framework"
).path("bundles").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE
).get();
- List<BundleDTO> bundleDTOList = response.readEntity(new GenericType<List<BundleDTO>>() {});
+ BundleSchemaListSchema bundleSchemas = response.readEntity(BundleSchemaListSchema.class);
assertThat(
- bundleDTOList
+ bundleSchemas.bundles
).isNotEmpty();
}
@@ -367,56 +335,13 @@ public class BundlesTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().post(
- Entity.entity(String.format(
- "http://localhost:%d/minor-change-1.0.1.jar",
- server.getPort()),
- MediaType.TEXT_PLAIN));
-
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
-
- bundleDTO = response.readEntity(BundleDTO.class);
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
- }
- }
+ BundleSchema bundleSchema = null;
- @Test
- public void postBundlesByUpload() throws Exception {
- WebTarget target = createDefaultTarget().path(
- "framework").path("bundles");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- BundleDTO bundleDTO = null;
-
- try {
- Response response = target.request().header(
- HttpHeaders.CONTENT_LOCATION, "minor-change-1.0.1.jar"
- ).post(
- Entity.entity(
- BundlesTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- APPLICATION_VNDOSGIBUNDLE_TYPE)
- );
+ Response response = target.request().post(
+ Entity.entity(String.format(
+ "http://localhost:%d/minor-change-1.0.1.jar",
+ server.getPort()),
+ MediaType.TEXT_PLAIN));
assertThat(
response.getStatus()
@@ -424,61 +349,77 @@ public class BundlesTest extends TestUtil {
200
);
- bundleDTO = response.readEntity(BundleDTO.class);
+ bundleSchema = response.readEntity(BundleSchema.class);
assertThat(
- bundleDTO.symbolicName
+ bundleSchema.symbolicName
).isEqualTo(
"minor-and-removed-change"
);
}
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
}
@Test
- public void postBundlesByUploadNoContentLocation() throws Exception {
+ public void postBundlesByUpload() throws Exception {
WebTarget target = createDefaultTarget().path(
"framework").path("bundles");
- target.register(RestManagementMessageBodyHandler.class);
+ BundleSchema bundleSchema = null;
- BundleDTO bundleDTO = null;
+ Response response = target.request().header(
+ HttpHeaders.CONTENT_LOCATION, "minor-change-1.0.1.jar"
+ ).post(
+ Entity.entity(
+ BundlesTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ APPLICATION_VNDOSGIBUNDLE_TYPE)
+ );
- try {
- Response response = target.request().post(
- Entity.entity(
- BundlesTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
- APPLICATION_VNDOSGIBUNDLE_TYPE)
- );
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
- assertThat(
- response.getStatus()
- ).isEqualTo(
- 200
- );
+ bundleSchema = response.readEntity(BundleSchema.class);
- bundleDTO = response.readEntity(BundleDTO.class);
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ }
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- BundleAssert.assertThat(
- bundleContext.getBundle(bundleDTO.id)
- ).hasLocationThat().contains(
- "org.apache.aries.jax.rs.whiteboard:"
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
+ @Test
+ public void postBundlesByUploadNoContentLocation() throws Exception {
+ WebTarget target = createDefaultTarget().path(
+ "framework").path("bundles");
+
+ BundleSchema bundleSchema = null;
+
+ Response response = target.request().post(
+ Entity.entity(
+ BundlesTest.class.getClassLoader().getResourceAsStream("minor-change-1.0.1.jar"),
+ APPLICATION_VNDOSGIBUNDLE_TYPE)
+ );
+
+ assertThat(
+ response.getStatus()
+ ).isEqualTo(
+ 200
+ );
+
+ bundleSchema = response.readEntity(BundleSchema.class);
+
+ assertThat(
+ bundleSchema.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
+ BundleAssert.assertThat(
+ bundleContext.getBundle(bundleSchema.id)
+ ).hasLocationThat().contains(
+ "org.apache.aries.jax.rs.whiteboard:"
+ );
}
}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStartLevelTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStartLevelTest.java
index 0ee2a79..69068ae 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStartLevelTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStartLevelTest.java
@@ -27,9 +27,8 @@ import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Test;
-import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+import org.apache.aries.jax.rs.rest.management.schema.FrameworkStartLevelSchema;
+import org.junit.jupiter.api.Test;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
@@ -133,24 +132,22 @@ public class FrameworkStartLevelTest extends TestUtil {
}
@Test
- public void getFrameworkStartLevelDTO() {
+ public void getFrameworkStartLevelSchema() {
WebTarget target = createDefaultTarget().path(
"framework").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request().get();
- FrameworkStartLevelDTO frameworkStartLevelDTO =
- response.readEntity(FrameworkStartLevelDTO.class);
+ FrameworkStartLevelSchema frameworkStartLevelSchema =
+ response.readEntity(FrameworkStartLevelSchema.class);
assertThat(
- frameworkStartLevelDTO.startLevel
+ frameworkStartLevelSchema.startLevel
).isGreaterThan(
0
);
assertThat(
- frameworkStartLevelDTO.initialBundleStartLevel
+ frameworkStartLevelSchema.initialBundleStartLevel
).isGreaterThan(
0
);
@@ -161,14 +158,12 @@ public class FrameworkStartLevelTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
- FrameworkStartLevelDTO frameworkStartLevelDTO =
- new FrameworkStartLevelDTO();
+ FrameworkStartLevelSchema frameworkStartLevelSchema =
+ new FrameworkStartLevelSchema();
Response response = target.request().put(
Entity.entity(
- frameworkStartLevelDTO, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
+ frameworkStartLevelSchema, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
assertThat(
response.getStatus()
@@ -182,18 +177,16 @@ public class FrameworkStartLevelTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
+ FrameworkStartLevelSchema frameworkStartLevelSchema =
+ new FrameworkStartLevelSchema();
- FrameworkStartLevelDTO frameworkStartLevelDTO =
- new FrameworkStartLevelDTO();
-
- frameworkStartLevelDTO.startLevel = 2;
- frameworkStartLevelDTO.initialBundleStartLevel = 1;
+ frameworkStartLevelSchema.startLevel = 2;
+ frameworkStartLevelSchema.initialBundleStartLevel = 1;
try {
Response response = target.request().put(
Entity.entity(
- frameworkStartLevelDTO, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
+ frameworkStartLevelSchema, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
assertThat(
response.getStatus()
@@ -202,11 +195,11 @@ public class FrameworkStartLevelTest extends TestUtil {
);
}
finally {
- frameworkStartLevelDTO.startLevel = 1;
+ frameworkStartLevelSchema.startLevel = 1;
Response response = target.request().put(
Entity.entity(
- frameworkStartLevelDTO, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
+ frameworkStartLevelSchema, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
assertThat(
response.getStatus()
@@ -221,18 +214,16 @@ public class FrameworkStartLevelTest extends TestUtil {
WebTarget target = createDefaultTarget().path(
"framework").path("startlevel");
- target.register(RestManagementMessageBodyHandler.class);
-
- FrameworkStartLevelDTO frameworkStartLevelDTO =
- new FrameworkStartLevelDTO();
+ FrameworkStartLevelSchema frameworkStartLevelSchema =
+ new FrameworkStartLevelSchema();
- frameworkStartLevelDTO.startLevel = 1;
- frameworkStartLevelDTO.initialBundleStartLevel = 2;
+ frameworkStartLevelSchema.startLevel = 1;
+ frameworkStartLevelSchema.initialBundleStartLevel = 2;
try {
Response response = target.request().put(
Entity.entity(
- frameworkStartLevelDTO, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
+ frameworkStartLevelSchema, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
assertThat(
response.getStatus()
@@ -241,11 +232,11 @@ public class FrameworkStartLevelTest extends TestUtil {
);
}
finally {
- frameworkStartLevelDTO.initialBundleStartLevel = 1;
+ frameworkStartLevelSchema.initialBundleStartLevel = 1;
Response response = target.request().put(
Entity.entity(
- frameworkStartLevelDTO, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
+ frameworkStartLevelSchema, APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE));
assertThat(
response.getStatus()
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStateTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStateTest.java
index a06908d..d1aed00 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStateTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkStateTest.java
@@ -23,9 +23,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.apache.aries.jax.rs.rest.management.model.BundleStateDTO;
-import org.junit.Test;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.junit.jupiter.api.Test;
import org.osgi.framework.Bundle;
import org.xmlunit.assertj3.XmlAssert;
@@ -102,11 +101,9 @@ public class FrameworkStateTest extends TestUtil {
public void getFrameworkStateDTO() {
WebTarget target = createDefaultTarget().path("framework").path("state");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request().get();
- BundleStateDTO bundleStateDTO = response.readEntity(BundleStateDTO.class);
+ BundleStateSchema bundleStateDTO = response.readEntity(BundleStateSchema.class);
assertThat(
bundleStateDTO.state
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkTest.java
index 0a17541..8f48572 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/FrameworkTest.java
@@ -18,14 +18,12 @@
package org.apache.aries.jax.rs.rest.management.test;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-import static org.junit.Assert.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.osgi.framework.dto.FrameworkDTO;
import org.xmlunit.assertj3.XmlAssert;
@@ -33,7 +31,7 @@ import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class FrameworkTest extends TestUtil {
- @Test
+ //@Test
public void getFrameworkJSON() {
WebTarget target = createDefaultTarget().path("framework");
@@ -57,7 +55,7 @@ public class FrameworkTest extends TestUtil {
);
}
- @Test
+ //@Test
public void getFramework_DOT_JSON() {
WebTarget target = createDefaultTarget().path("framework.json");
@@ -81,8 +79,7 @@ public class FrameworkTest extends TestUtil {
);
}
- @Ignore("This is non-standard anyway, cleanup later")
- @Test
+ //@Test
public void getFrameworkXML() {
WebTarget target = createDefaultTarget().path("framework");
@@ -97,8 +94,7 @@ public class FrameworkTest extends TestUtil {
).contains("0");
}
- @Ignore("This is non-standard anyway, cleanup later")
- @Test
+ //@Test
public void getFrameworkXML_DOT_XML() {
WebTarget target = createDefaultTarget().path("framework.xml");
@@ -113,31 +109,26 @@ public class FrameworkTest extends TestUtil {
).contains("0");
}
- @Test
+ //@Test
public void getFrameworkDTOJSON() {
WebTarget target = createDefaultTarget().path("framework");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request().get();
FrameworkDTO frameworkDTO = response.readEntity(FrameworkDTO.class);
- assertTrue(frameworkDTO.toString(), frameworkDTO.bundles.size() > 0);
+ assertThat(frameworkDTO.bundles.size()).isGreaterThan(0);
}
- @Ignore("This is non-standard anyway, cleanup later")
- @Test
+ //@Test
public void getFrameworkDTOXML() {
WebTarget target = createDefaultTarget().path("framework");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(APPLICATION_XML).get();
FrameworkDTO frameworkDTO = response.readEntity(FrameworkDTO.class);
- assertTrue(frameworkDTO.toString(), frameworkDTO.bundles.size() > 0);
+ assertThat(frameworkDTO.bundles.size()).isGreaterThan(0);
}
}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/RestClientTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/RestClientTest.java
index 1da050d..a94c6ac 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/RestClientTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/RestClientTest.java
@@ -22,25 +22,17 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.Collection;
-import org.junit.Rule;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
+import org.apache.aries.jax.rs.rest.management.schema.FrameworkStartLevelSchema;
+import org.junit.jupiter.api.Test;
+import org.osgi.framework.BundleException;
import org.osgi.framework.dto.BundleDTO;
import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
import org.osgi.service.rest.client.RestClient;
import org.osgi.service.rest.client.RestClientFactory;
-import org.osgi.test.common.annotation.InjectBundleContext;
import org.osgi.test.common.annotation.InjectService;
-import org.osgi.test.junit4.context.BundleContextRule;
public class RestClientTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@InjectService
public RestClientFactory restClientFactory;
@@ -65,7 +57,7 @@ public class RestClientTest extends TestUtil {
RestClient restClient = restClientFactory.createRestClient(
runtimeURI());
- FrameworkStartLevelDTO frameworkStartLevel = new FrameworkStartLevelDTO();
+ FrameworkStartLevelSchema frameworkStartLevel = new FrameworkStartLevelSchema();
assertThatThrownBy(
() -> restClient.setFrameworkStartLevel(frameworkStartLevel)
@@ -77,7 +69,7 @@ public class RestClientTest extends TestUtil {
RestClient restClient = restClientFactory.createRestClient(
runtimeURI());
- FrameworkStartLevelDTO frameworkStartLevel = new FrameworkStartLevelDTO();
+ FrameworkStartLevelSchema frameworkStartLevel = new FrameworkStartLevelSchema();
frameworkStartLevel.initialBundleStartLevel = 2;
frameworkStartLevel.startLevel = 1;
@@ -147,28 +139,21 @@ public class RestClientTest extends TestUtil {
BundleDTO bundleDTO = null;
- try {
- RestClient restClient = restClientFactory.createRestClient(
- runtimeURI());
-
- bundleDTO = restClient.installBundle(
- String.format(
- "http://localhost:%d/minor-change-1.0.1.jar",
- server.getPort()
- )
- );
-
- assertThat(
- bundleDTO.symbolicName
- ).isEqualTo(
- "minor-and-removed-change"
- );
- }
- finally {
- if (bundleDTO != null) {
- bundleContext.getBundle(bundleDTO.id).uninstall();
- }
- }
+ RestClient restClient = restClientFactory.createRestClient(
+ runtimeURI());
+
+ bundleDTO = restClient.installBundle(
+ String.format(
+ "http://localhost:%d/minor-change-1.0.1.jar",
+ server.getPort()
+ )
+ );
+
+ assertThat(
+ bundleDTO.symbolicName
+ ).isEqualTo(
+ "minor-and-removed-change"
+ );
}
}
@@ -182,9 +167,9 @@ public class RestClientTest extends TestUtil {
"http://localhost:%d/minor-change-1.0.1.jar"
);
}).isInstanceOf(
- Exception.class
+ BundleException.class
).hasMessageContaining(
- "Bad Request"
+ "Error reading bundle content."
);
}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServiceTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServiceTest.java
new file mode 100644
index 0000000..9403925
--- /dev/null
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServiceTest.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.test;
+
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_XML_TYPE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchema;
+import org.junit.jupiter.api.Test;
+import org.xmlunit.assertj3.XmlAssert;
+
+import net.javacrumbs.jsonunit.assertj.JsonAssertions;
+
+public class ServiceTest extends TestUtil {
+
+ @Test
+ public void getServiceJSON() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 1l
+ ).request(
+ APPLICATION_SERVICE_JSON_TYPE
+ ).get();
+
+ String result = response.readEntity(String.class);
+
+ JsonAssertions.assertThatJson(
+ result
+ ).and(
+ j -> j.isObject(),
+ j1 -> j1.node("id").isNumber().isEqualByComparingTo("1"),
+ j1 -> j1.node("properties").and(
+ j2 -> j2.isObject(),
+ j2 -> j2.node("objectClass").isArray().contains("org.osgi.service.log.LogReaderService", "org.eclipse.equinox.log.ExtendedLogReaderService"),
+ j2 -> j2.node("service\\.scope").isString().contains("bundle"),
+ j2 -> j2.node("service\\.id").isNumber().isEqualByComparingTo("1"),
+ j2 -> j2.node("service\\.bundleid").isNumber().isEqualByComparingTo("0")
+ ),
+ j1 -> j1.node("bundle").isString().contains("http://", "/rms/framework/bundle/"),
+ j1 -> j1.node("usingBundles").isArray()
+ );
+ }
+
+ @Test
+ public void getServiceXML() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 1l
+ ).request(
+ APPLICATION_SERVICE_XML_TYPE
+ ).get();
+
+ String result = response.readEntity(String.class);
+
+ XmlAssert.assertThat(
+ result
+ ).isInvalid().valueByXPath(
+ "//service/id"
+ ).isEqualTo("1");
+
+ XmlAssert.assertThat(
+ result
+ ).valueByXPath(
+ "//service/properties/property[3]/@name"
+ ).isEqualTo("service.id");
+
+ XmlAssert.assertThat(
+ result
+ ).valueByXPath(
+ "//service/properties/property[3]/@type"
+ ).isEqualTo("Long");
+
+ XmlAssert.assertThat(
+ result
+ ).valueByXPath(
+ "//service/properties/property[3]/@value"
+ ).isEqualTo("1");
+ }
+
+ @Test
+ public void getServiceDTOJSON() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 1l
+ ).request(
+ APPLICATION_SERVICE_JSON_TYPE
+ ).get();
+
+ ServiceSchema serviceSchema = response.readEntity(ServiceSchema.class);
+
+ assertThat(
+ serviceSchema.id
+ ).isEqualTo(
+ 1l
+ );
+ }
+
+ @Test
+ public void getServiceDTOXML() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 1l
+ ).request(
+ APPLICATION_SERVICE_XML_TYPE
+ ).get();
+
+ ServiceSchema serviceSchema = response.readEntity(ServiceSchema.class);
+
+ assertThat(
+ serviceSchema.id
+ ).isEqualTo(
+ 1l
+ );
+ }
+
+ //@Test
+ public void getService28XML() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 28l
+ ).request(
+ APPLICATION_SERVICE_XML_TYPE
+ ).get();
+
+ String result = response.readEntity(String.class);
+
+ XmlAssert.assertThat(
+ result
+ ).isInvalid().valueByXPath(
+ "//service/id"
+ ).isEqualTo("28");
+ }
+
+ //@Test
+ public void getService28DTOXML() {
+ WebTarget target = createDefaultTarget().path(
+ "framework"
+ ).path("service").path("{serviceid}");
+
+ Response response = target.resolveTemplate(
+ "serviceid", 28l
+ ).request(
+ APPLICATION_SERVICE_XML_TYPE
+ ).get();
+
+ ServiceSchema serviceSchema = response.readEntity(ServiceSchema.class);
+
+ assertThat(
+ serviceSchema.id
+ ).isEqualTo(
+ 28l
+ );
+ }
+
+}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServicesTest.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServicesTest.java
index 76a1da0..1d47967 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServicesTest.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/ServicesTest.java
@@ -21,38 +21,24 @@ import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.AP
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE;
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE;
import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_XML_TYPE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.MapEntry.entry;
+import java.util.Arrays;
import java.util.Map;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.apache.aries.jax.rs.rest.management.model.ServiceReferenceDTOs;
-import org.apache.aries.jax.rs.rest.management.model.ServicesDTO;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.dto.ServiceReferenceDTO;
-import org.osgi.test.common.annotation.InjectBundleContext;
-import org.osgi.test.junit4.context.BundleContextRule;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchemaListSchema;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceListSchema;
+import org.junit.jupiter.api.Test;
import org.xmlunit.assertj3.XmlAssert;
import net.javacrumbs.jsonunit.assertj.JsonAssertions;
public class ServicesTest extends TestUtil {
- @Rule
- public BundleContextRule bundleContextRule = new BundleContextRule();
-
- @InjectBundleContext
- BundleContext bundleContext;
-
@Test
public void getServicesJSON() {
WebTarget target = createDefaultTarget().path(
@@ -99,13 +85,11 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_SERVICES_JSON_TYPE
).get();
- ServicesDTO servicesDTO = response.readEntity(ServicesDTO.class);
+ ServiceListSchema servicesDTO = response.readEntity(ServiceListSchema.class);
assertThat(
servicesDTO.services
@@ -120,13 +104,11 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_SERVICES_XML_TYPE
).get();
- ServicesDTO servicesDTO = response.readEntity(ServicesDTO.class);
+ ServiceListSchema servicesDTO = response.readEntity(ServiceListSchema.class);
assertThat(
servicesDTO.services
@@ -210,16 +192,14 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE
).get();
- ServiceReferenceDTOs serviceReferenceDTOs = response.readEntity(ServiceReferenceDTOs.class);
+ ServiceSchemaListSchema serviceSchemaListSchema = response.readEntity(ServiceSchemaListSchema.class);
assertThat(
- serviceReferenceDTOs.services
+ serviceSchemaListSchema.services
).isNotEmpty();
}
@@ -229,183 +209,17 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.request(
APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE
).get();
- ServiceReferenceDTOs serviceReferenceDTOs = response.readEntity(ServiceReferenceDTOs.class);
+ ServiceSchemaListSchema serviceSchemaListSchema = response.readEntity(ServiceSchemaListSchema.class);
assertThat(
- serviceReferenceDTOs.services
+ serviceSchemaListSchema.services
).isNotEmpty();
}
- //////////
-
- @Test
- public void getServiceJSON() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- Response response = target.resolveTemplate(
- "serviceid", 1l
- ).request(
- APPLICATION_SERVICE_JSON_TYPE
- ).get();
-
- String result = response.readEntity(String.class);
-
- JsonAssertions.assertThatJson(
- result
- ).and(
- j -> j.isObject(),
- j1 -> j1.node("id").isNumber().isEqualByComparingTo("1"),
- j1 -> j1.node("properties").and(
- j2 -> j2.isObject(),
- j2 -> j2.node("objectClass").isArray().contains("org.osgi.service.log.LogReaderService", "org.eclipse.equinox.log.ExtendedLogReaderService"),
- j2 -> j2.node("service\\.scope").isString().contains("bundle"),
- j2 -> j2.node("service\\.id").isNumber().isEqualByComparingTo("1"),
- j2 -> j2.node("service\\.bundleid").isNumber().isEqualByComparingTo("0")
- ),
- j1 -> j1.node("bundle").isString().contains("http://", "/rms/framework/bundle/"),
- j1 -> j1.node("usingBundles").isArray()
- );
- }
-
- @Test
- public void getServiceXML() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- Response response = target.resolveTemplate(
- "serviceid", 1l
- ).request(
- APPLICATION_SERVICE_XML_TYPE
- ).get();
-
- String result = response.readEntity(String.class);
-
- XmlAssert.assertThat(
- result
- ).isInvalid().valueByXPath(
- "//service/id"
- ).isEqualTo("1");
-
- XmlAssert.assertThat(
- result
- ).valueByXPath(
- "//service/properties/property[3]/@name"
- ).isEqualTo("service.id");
-
- XmlAssert.assertThat(
- result
- ).valueByXPath(
- "//service/properties/property[3]/@type"
- ).isEqualTo("Long");
-
- XmlAssert.assertThat(
- result
- ).valueByXPath(
- "//service/properties/property[3]/@value"
- ).isEqualTo("1");
- }
-
- @Test
- public void getServiceDTOJSON() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- Response response = target.resolveTemplate(
- "serviceid", 1l
- ).request(
- APPLICATION_SERVICE_JSON_TYPE
- ).get();
-
- ServiceReferenceDTO serviceReferenceDTO = response.readEntity(ServiceReferenceDTO.class);
-
- assertThat(
- serviceReferenceDTO.id
- ).isEqualTo(
- 1l
- );
- }
-
- @Test
- public void getServiceDTOXML() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- Response response = target.resolveTemplate(
- "serviceid", 1l
- ).request(
- APPLICATION_SERVICE_XML_TYPE
- ).get();
-
- ServiceReferenceDTO serviceReferenceDTO = response.readEntity(ServiceReferenceDTO.class);
-
- assertThat(
- serviceReferenceDTO.id
- ).isEqualTo(
- 1l
- );
- }
-
- @Ignore("These are just tests for property coercion")
- @Test
- public void getService28XML() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- Response response = target.resolveTemplate(
- "serviceid", 28l
- ).request(
- APPLICATION_SERVICE_XML_TYPE
- ).get();
-
- String result = response.readEntity(String.class);
-
- XmlAssert.assertThat(
- result
- ).isInvalid().valueByXPath(
- "//service/id"
- ).isEqualTo("28");
- }
-
- @Ignore("These are just tests for property coercion")
- @Test
- public void getService28DTOXML() {
- WebTarget target = createDefaultTarget().path(
- "framework"
- ).path("service").path("{serviceid}");
-
- target.register(RestManagementMessageBodyHandler.class);
-
- Response response = target.resolveTemplate(
- "serviceid", 28l
- ).request(
- APPLICATION_SERVICE_XML_TYPE
- ).get();
-
- ServiceReferenceDTO serviceReferenceDTO = response.readEntity(ServiceReferenceDTO.class);
-
- assertThat(
- serviceReferenceDTO.id
- ).isEqualTo(
- 28l
- );
- }
-
////////////
@Test
@@ -459,15 +273,13 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"filter", "(service.id=25)"
).request(
APPLICATION_SERVICES_JSON_TYPE
).get();
- ServicesDTO servicesDTO = response.readEntity(ServicesDTO.class);
+ ServiceListSchema servicesDTO = response.readEntity(ServiceListSchema.class);
assertThat(
servicesDTO.services.get(0)
@@ -482,15 +294,13 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
"filter", "(service.id=25)"
).request(
APPLICATION_SERVICES_XML_TYPE
).get();
- ServicesDTO servicesDTO = response.readEntity(ServicesDTO.class);
+ ServiceListSchema servicesDTO = response.readEntity(ServiceListSchema.class);
assertThat(
servicesDTO.services.get(0)
@@ -505,18 +315,16 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
- "filter", "(objectClass=org.apache.aries.jax.rs.*)"
+ "filter", "(objectClass=org.eclipse.osgi.*)"
).request(
APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE
).get();
- ServiceReferenceDTOs serviceReferenceDTOs = response.readEntity(ServiceReferenceDTOs.class);
+ ServiceSchemaListSchema serviceSchemaListSchema = response.readEntity(ServiceSchemaListSchema.class);
assertThat(
- serviceReferenceDTOs.services.get(0)
+ serviceSchemaListSchema.services.get(0)
).hasFieldOrProperty(
"bundle"
).hasFieldOrProperty(
@@ -527,12 +335,12 @@ public class ServicesTest extends TestUtil {
"usingBundles"
);
- Map<String, Object> properties = serviceReferenceDTOs.services.get(0).properties;
+ Map<String, Object> properties = serviceSchemaListSchema.services.get(0).properties;
assertThat(properties).contains(
- entry("objectClass", new String[] {"org.apache.aries.jax.rs.rest.management.internal.FrameworkResource"})
+ entry("objectClass", Arrays.asList("org.eclipse.osgi.framework.log.FrameworkLog"))
).contains(
- entry("osgi.jaxrs.application.select", "(osgi.jaxrs.name=RestManagementApplication)")
+ entry("service.scope", "bundle")
);
}
@@ -542,18 +350,16 @@ public class ServicesTest extends TestUtil {
"framework"
).path("services").path("representations");
- target.register(RestManagementMessageBodyHandler.class);
-
Response response = target.queryParam(
- "filter", "(objectclass=org.apache.aries.jax.rs.*)"
+ "filter", "(objectclass=org.eclipse.osgi.*)"
).request(
APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE
).get();
- ServiceReferenceDTOs serviceReferenceDTOs = response.readEntity(ServiceReferenceDTOs.class);
+ ServiceSchemaListSchema serviceSchemaListSchema = response.readEntity(ServiceSchemaListSchema.class);
assertThat(
- serviceReferenceDTOs.services.get(0)
+ serviceSchemaListSchema.services.get(0)
).hasFieldOrProperty(
"bundle"
).hasFieldOrProperty(
@@ -564,12 +370,12 @@ public class ServicesTest extends TestUtil {
"usingBundles"
);
- Map<String, Object> properties = serviceReferenceDTOs.services.get(0).properties;
+ Map<String, Object> properties = serviceSchemaListSchema.services.get(0).properties;
assertThat(properties).contains(
- entry("objectClass", new String[] {"org.apache.aries.jax.rs.rest.management.internal.FrameworkResource"})
+ entry("objectClass", Arrays.asList("org.eclipse.osgi.framework.log.FrameworkLog"))
).contains(
- entry("osgi.jaxrs.application.select", "(osgi.jaxrs.name=RestManagementApplication)")
+ entry("service.scope", "bundle")
);
}
diff --git a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/TestUtil.java b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/TestUtil.java
index 53df239..c2ebef6 100644
--- a/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/TestUtil.java
+++ b/integrations/rest-management/rest-management-itest/src/main/java/org/apache/aries/jax/rs/rest/management/test/TestUtil.java
@@ -17,6 +17,7 @@
package org.apache.aries.jax.rs.rest.management.test;
+import static java.util.concurrent.TimeUnit.SECONDS;
import static org.osgi.service.jaxrs.runtime.JaxrsServiceRuntimeConstants.JAX_RS_SERVICE_ENDPOINT;
import java.io.IOException;
@@ -28,22 +29,29 @@ import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.junit.Rule;
+import org.apache.aries.jax.rs.rest.management.feature.RestManagementFeature;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.service.jaxrs.runtime.JaxrsServiceRuntime;
+import org.osgi.test.common.annotation.InjectBundleContext;
import org.osgi.test.common.annotation.InjectService;
import org.osgi.test.common.service.ServiceAware;
-import org.osgi.test.junit4.service.ServiceRule;
+import org.osgi.test.junit5.context.BundleContextExtension;
+import org.osgi.test.junit5.service.ServiceExtension;
+@ExtendWith({
+ BundleContextExtension.class,
+ ServiceExtension.class
+})
public class TestUtil {
- @Rule
- public ServiceRule serviceRule = new ServiceRule();
@InjectService
public ClientBuilder clientBuilder;
@@ -51,13 +59,29 @@ public class TestUtil {
@InjectService(filter = "(%s=*)", filterArguments = JAX_RS_SERVICE_ENDPOINT)
public ServiceAware<JaxrsServiceRuntime> jaxrsServiceRuntimeAware;
+ @InjectBundleContext
+ public BundleContext bundleContext;
+
+ @BeforeEach
+ public void beforeEach(@InjectBundleContext BundleContext bundleContext) {
+ Stream.of(bundleContext.getBundles()).filter(b -> b.getSymbolicName().equals("minor-and-removed-change")).forEach(
+ b -> {
+ try {
+ b.uninstall();
+ } catch (BundleException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ );
+ }
+
protected WebTarget createDefaultTarget() {
- clientBuilder.connectTimeout(600000, TimeUnit.SECONDS);
- clientBuilder.readTimeout(600000, TimeUnit.SECONDS);
+ clientBuilder.connectTimeout(600000, SECONDS);
+ clientBuilder.readTimeout(600000, SECONDS);
Client client = clientBuilder.build();
- client.register(RestManagementMessageBodyHandler.class);
+ client.register(RestManagementFeature.class);
return client.target(runtimeURI());
}
diff --git a/integrations/rest-management/rest-management/README.md b/integrations/rest-management/rest-management/README.md
new file mode 100644
index 0000000..877d229
--- /dev/null
+++ b/integrations/rest-management/rest-management/README.md
@@ -0,0 +1,24 @@
+## Apache Aries JAX-RS Rest Management Service
+
+Welcome to the Apache Aries JAX-RS OSGi REST Management integration. This integration implements **Chapter 137** of the **OSGi R7 Compendium** [REST Management Service Specification](https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.rest.html).
+
+In essence this integration allows for management and introspection of the OSGi framework over REST.
+
+### Rest Management Service Location
+
+Since there should only be one management API per framework the integration creates a separate application rooted at `${osgi.jaxrs.endpoint}/rms`
+
+### Open API
+
+To simplify developer experience there is an Open API endpoint mounted at `${osgi.jaxrs.endpoint}/rms/openapi.(json|yaml)`.
+
+#### TODO
+
+- fix conditional response type based on extension logic to account for mediatype resource method parameters
+
+##### Wish list
+
+- add HATEOS-style links within representations that allow for references to associated resources (e.g. in bundle representation add links to state, startlevel, headers)
+- add a extensions/inspect[/{bundleid}] (requirements and capabilities) resource (akin to gogo inspect command)
+- add a extension/repository that returns the [XML Repository Format](https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.repository.html#i3247820)
+- add a extension/cm* for integration for Configuration admin (uses [Configuration Resource Format](https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html#d0e131566))
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/RestManagementConstants.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/RestManagementConstants.java
index ac7003a..7dfd335 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/RestManagementConstants.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/RestManagementConstants.java
@@ -21,6 +21,10 @@ import javax.ws.rs.core.MediaType;
public class RestManagementConstants {
+ public static final String SPECIFICATION_IMPLEMENTATION = "osgi.rest";
+
+ public static final String SPECIFICATION_VERSION = "1.0.0";
+
public static final String APPLICATION_BUNDLE_JSON =
"application/org.osgi.bundle+json";
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/RestManagementFeature.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/RestManagementFeature.java
new file mode 100644
index 0000000..03c3a6c
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/RestManagementFeature.java
@@ -0,0 +1,17 @@
+package org.apache.aries.jax.rs.rest.management.feature;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+public class RestManagementFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(new JacksonJsonProvider());
+
+ return true;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/package-info.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/package-info.java
similarity index 94%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/package-info.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/package-info.java
index 1bf0e1c..0a1954e 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/package-info.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/feature/package-info.java
@@ -17,7 +17,7 @@
@Export
@Version("1.0.0")
-package org.apache.aries.jax.rs.rest.management.handler;
+package org.apache.aries.jax.rs.rest.management.feature;
import org.osgi.annotation.bundle.Export;
import org.osgi.annotation.versioning.Version;
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonDeserializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonDeserializer.java
deleted file mode 100644
index 8fc9f2d..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonDeserializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-@SuppressWarnings("serial")
-class DictionaryJsonDeserializer extends StdDeserializer<Dictionary<String, String>> {
-
- protected DictionaryJsonDeserializer() {
- this(null);
- }
-
- protected DictionaryJsonDeserializer(Class<Dictionary<String, String>> t) {
- super(t);
- }
-
- @Override
- public Dictionary<String, String> deserialize(JsonParser jp, DeserializationContext ctxt)
- throws IOException {
-
- Dictionary<String, String> dictionary = new Hashtable<>();
- JsonNode node = jp.getCodec().readTree(jp);
- node.fields().forEachRemaining(entry -> dictionary.put(entry.getKey(), entry.getValue().asText()));
- return dictionary;
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonSerializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonSerializer.java
deleted file mode 100644
index f49b8c2..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/DictionaryJsonSerializer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Dictionary;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-@SuppressWarnings({ "serial", "rawtypes" })
-class DictionaryJsonSerializer extends StdSerializer<Dictionary> {
-
- protected DictionaryJsonSerializer() {
- this(null);
- }
-
- protected DictionaryJsonSerializer(Class<Dictionary> t) {
- super(t);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void serialize(
- Dictionary value, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
-
- gen.writeStartObject();
-
- Collections.<String>list(value.keys()).stream().sorted().forEach(
- key -> {
- try {
- gen.writeStringField(
- String.valueOf(key),
- String.valueOf(value.get(key))
- );
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- );
-
- gen.writeEndObject();
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/RestManagementMessageBodyHandler.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/RestManagementMessageBodyHandler.java
deleted file mode 100644
index fa1cca5..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/RestManagementMessageBodyHandler.java
+++ /dev/null
@@ -1,992 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
-import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
-import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEHEADER_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEHEADER_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTARTLEVEL_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_FRAMEWORKSTARTLEVEL_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_XML_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_JSON_TYPE;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_XML_TYPE;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.namespace.QName;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
-
-import org.apache.aries.jax.rs.rest.management.model.BundleStateDTO;
-import org.apache.aries.jax.rs.rest.management.model.BundlesDTO;
-import org.apache.aries.jax.rs.rest.management.model.ServiceReferenceDTOs;
-import org.apache.aries.jax.rs.rest.management.model.ServicesDTO;
-import org.osgi.framework.dto.BundleDTO;
-import org.osgi.framework.dto.FrameworkDTO;
-import org.osgi.framework.dto.ServiceReferenceDTO;
-import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
-import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
-import org.w3c.dom.Element;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-public class RestManagementMessageBodyHandler
- implements MessageBodyReader<Object>,
- MessageBodyWriter<Object> {
-
- private static final TypeReference<Collection<BundleDTO>> BUNDLEDTO_COLLECTION =
- new TypeReference<Collection<BundleDTO>>() {};
- private static final TypeReference<Collection<ServiceReferenceDTO>> SERVICEDTO_COLLECTION =
- new TypeReference<Collection<ServiceReferenceDTO>>() {};
- private static final TypeReference<Dictionary<String, String>> BUNDLE_HEADER =
- new TypeReference<Dictionary<String, String>>() {};
- private final JAXBContext context;
-
- private final XMLSerializer serializer;
- private final XMLDeserializer deserializer;
- private final ServiceReferenceDTOXMLDeserializer serviceReferenceDTO_XMLDeserializer;
- private final ServiceReferenceDTOXMLSerializer serviceReferenceDTO_XMLSerializer;
-
- private final Function<UriInfo, ObjectMapper> jsonMapperFunction = uriInfo -> {
- ObjectMapper jsonMapper = new ObjectMapper().configure(
- INDENT_OUTPUT, true
- );
-
- SimpleModule module = new SimpleModule();
- module.addSerializer(Dictionary.class, new DictionaryJsonSerializer());
- module.addDeserializer(Dictionary.class, new DictionaryJsonDeserializer());
- module.addSerializer(ServiceReferenceDTO.class, new ServiceReferenceDTOJsonSerializer(uriInfo));
- module.addDeserializer(ServiceReferenceDTO.class, new ServiceReferenceDTOJsonDeserializer());
-
- return jsonMapper.registerModule(module);
- };
-
- @Context
- volatile UriInfo uriInfo;
-
- public RestManagementMessageBodyHandler() {
-
- serializer = new XMLSerializer();
- deserializer = new XMLDeserializer();
- serviceReferenceDTO_XMLDeserializer = new ServiceReferenceDTOXMLDeserializer(deserializer);
- serviceReferenceDTO_XMLSerializer = new ServiceReferenceDTOXMLSerializer(serializer);
-
- try {
- context = JAXBContext.newInstance(
- BundleDTO.class,
- BundleDTO[].class,
- BundlesDTO.class,
- BundleStartLevelDTO.class,
- BundleStateDTO.class,
- Dictionary.class,
- FrameworkStartLevelDTO.class,
- FrameworkDTO.class,
- ServicesDTO.class,
- ServiceReferenceDTO.class,
- ServiceReferenceDTOs.class
- );
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public boolean isReadable(
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType) {
-
- return
- (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, BundleDTO.class) && (
- APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)))
- ||
- (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, ServiceReferenceDTO.class) && (
- APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)))
- ||
- (Dictionary.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, String.class) &&
- nthTypeArgumentIs(1, genericType, String.class) && (
- APPLICATION_BUNDLEHEADER_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLEHEADER_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == BundleDTO.class && (
- APPLICATION_BUNDLE_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLE_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == BundlesDTO.class && (
- APPLICATION_BUNDLES_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLES_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == BundleStateDTO.class && (
- APPLICATION_BUNDLESTATE_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLESTATE_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == BundleStartLevelDTO.class && (
- APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_BUNDLESTARTLEVEL_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == FrameworkStartLevelDTO.class && (
- APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_FRAMEWORKSTARTLEVEL_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == FrameworkDTO.class && (
- APPLICATION_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == ServicesDTO.class && (
- APPLICATION_SERVICES_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_SERVICES_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == ServiceReferenceDTO.class && (
- APPLICATION_SERVICE_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_SERVICE_XML_TYPE.isCompatible(mediaType)))
- ||
- (type == ServiceReferenceDTOs.class && (
- APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType) ||
- APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)))
- ;
- }
-
- @Override
- public boolean isWriteable(
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType) {
-
- return isReadable(type, genericType, annotations, mediaType);
- }
-
- BundleDTO readBundleDTOFrom(
- Class<? extends BundleDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLE_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLE_XML_TYPE.isCompatible(mediaType)) {
- try {
- return (BundleDTO)context.createUnmarshaller().unmarshal(
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
-
- return null;
- }
-
- Collection<BundleDTO> readBundleDTOListFrom(
- @SuppressWarnings("rawtypes") Class<? extends Collection> type,
- Type genericType, Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(BUNDLEDTO_COLLECTION).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- List<BundleDTO> bundles = new ArrayList<>();
- AtomicReference<BundleDTO> bundle = new AtomicReference<>();
- deserializer.deserialize((start, next) -> {
- String el = start.getName().getLocalPart();
- XMLEvent event = start;
- if (el.equals("bundle")) {
- bundle.set(new BundleDTO());
- }
- else if (el.equals("id")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundle.get().id = Long.parseLong(event.asCharacters().getData());
- }
- else if (el.equals("lastModified")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundle.get().lastModified = Long.parseLong(event.asCharacters().getData());
- }
- else if (el.equals("state")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundle.get().state = Integer.parseInt(event.asCharacters().getData());
- }
- else if (el.equals("symbolicName")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundle.get().symbolicName = event.asCharacters().getData();
- }
- else if (el.equals("version")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundle.get().version = event.asCharacters().getData();
- }
- return event;
- }, end -> {
- String el = end.getName().getLocalPart();
- if (el.equals("bundle")) {
- bundles.add(bundle.get());
- bundle.set(null);
- }
- }, entityStream);
-
- return bundles;
- }
-
- return null;
- }
-
- Dictionary<String, String> readBundleHeadersFrom(
- @SuppressWarnings("rawtypes") Class<? extends Dictionary> asSubclass,
- Type genericType, Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException{
-
- if (APPLICATION_BUNDLEHEADER_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(BUNDLE_HEADER).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLEHEADER_XML_TYPE.isCompatible(mediaType)) {
- Dictionary<String, String> header = new Hashtable<>();
-
- deserializer.deserialize((start, next) -> {
- String el = start.getName().getLocalPart();
- if (el.equals("entry")) {
- Attribute keyAT = start.getAttributeByName(new QName("key"));
- Attribute valueAT = start.getAttributeByName(new QName("value"));
- header.put(keyAT.getValue(), valueAT.getValue());
- }
- return start;
- }, end -> {}, entityStream);
-
- return header;
- }
-
- return null;
- }
-
- BundlesDTO readBundlesDTOFrom(
- Class<? extends BundlesDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLES_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLES_XML_TYPE.isCompatible(mediaType)) {
- BundlesDTO bundlesDTO = new BundlesDTO();
- bundlesDTO.bundles = new ArrayList<>();
-
- deserializer.deserialize((start, next) -> {
- String el = start.getName().getLocalPart();
- XMLEvent event = start;
- if (el.equals("uri")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- bundlesDTO.bundles.add(event.asCharacters().getData());
- }
- return start;
- }, end -> {}, entityStream);
-
- return bundlesDTO;
- }
-
- return null;
- }
-
- BundleStartLevelDTO readBundleStartLevelDTOFrom(
- Class<? extends BundleStartLevelDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLESTARTLEVEL_XML_TYPE.isCompatible(mediaType)) {
- try {
- return (BundleStartLevelDTO)context.createUnmarshaller().unmarshal(
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
-
- return null;
- }
-
- BundleStateDTO readBundleStateDTOFrom(
- Class<? extends BundleStateDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLESTATE_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLESTATE_XML_TYPE.isCompatible(mediaType)) {
- try {
- return (BundleStateDTO)context.createUnmarshaller().unmarshal(
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
-
- return null;
- }
-
- FrameworkDTO readFrameworkDTOFrom(
- Class<? extends FrameworkDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_XML_TYPE.isCompatible(mediaType)) {
- try {
- return (FrameworkDTO)context.createUnmarshaller().unmarshal(
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
-
- return null;
- }
-
- FrameworkStartLevelDTO readFrameworkStartLevelDTOFrom(
- Class<? extends FrameworkStartLevelDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_FRAMEWORKSTARTLEVEL_XML_TYPE.isCompatible(mediaType)) {
- try {
- return (FrameworkStartLevelDTO)context.createUnmarshaller().unmarshal(
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
-
- return null;
- }
-
- @Override
- public Object readFrom(
- Class<Object> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders,
- InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, BundleDTO.class)) {
-
- return readBundleDTOListFrom(
- type.asSubclass(Collection.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, ServiceReferenceDTO.class)) {
-
- return readServiceReferenceDTOListFrom(
- type.asSubclass(Collection.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (Dictionary.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, String.class) &&
- nthTypeArgumentIs(1, genericType, String.class)) {
-
- return readBundleHeadersFrom(
- type.asSubclass(Dictionary.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundleDTO.class.equals(type)) {
- return readBundleDTOFrom(
- type.asSubclass(BundleDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundlesDTO.class.equals(type)) {
- return readBundlesDTOFrom(
- type.asSubclass(BundlesDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundleStateDTO.class.equals(type)) {
- return readBundleStateDTOFrom(
- type.asSubclass(BundleStateDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundleStartLevelDTO.class.equals(type)) {
- return readBundleStartLevelDTOFrom(
- type.asSubclass(BundleStartLevelDTO.class), genericType,
- annotations, mediaType, httpHeaders, entityStream);
- }
- else if (FrameworkStartLevelDTO.class.equals(type)) {
- return readFrameworkStartLevelDTOFrom(
- type.asSubclass(FrameworkStartLevelDTO.class), genericType,
- annotations, mediaType, httpHeaders, entityStream);
- }
- else if (FrameworkDTO.class.equals(type)) {
- return readFrameworkDTOFrom(
- type.asSubclass(FrameworkDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServicesDTO.class.equals(type)) {
- return readServicesDTOFrom(
- type.asSubclass(ServicesDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServiceReferenceDTO.class.equals(type)) {
- return readServiceReferenceDTOFrom(
- type.asSubclass(ServiceReferenceDTO.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServiceReferenceDTOs.class.equals(type)) {
- return readServiceReferenceDTOsFrom(
- type.asSubclass(ServiceReferenceDTOs.class), genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
-
- return null;
- }
-
- ServiceReferenceDTO readServiceReferenceDTOFrom(
- Class<? extends ServiceReferenceDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICE_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_SERVICE_XML_TYPE.isCompatible(mediaType)) {
- return serviceReferenceDTO_XMLDeserializer.deserializeServiceReferenceDTO(entityStream);
- }
-
- return null;
- }
-
- Collection<ServiceReferenceDTO> readServiceReferenceDTOListFrom(
- @SuppressWarnings("rawtypes") Class<? extends Collection> type,
- Type genericType, Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(SERVICEDTO_COLLECTION).readValue(entityStream);
- }
- else if (APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- return serviceReferenceDTO_XMLDeserializer.deserializeServiceReferenceDTOList(entityStream);
- }
-
- return null;
- }
-
- ServiceReferenceDTOs readServiceReferenceDTOsFrom(
- Class<? extends ServiceReferenceDTOs> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- ServiceReferenceDTOs serviceReferenceDTOs = new ServiceReferenceDTOs();
- serviceReferenceDTOs.services = serviceReferenceDTO_XMLDeserializer.deserializeServiceReferenceDTOList(entityStream);
- return serviceReferenceDTOs;
- }
-
- return null;
- }
-
- ServicesDTO readServicesDTOFrom(
- Class<? extends ServicesDTO> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException{
-
- if (APPLICATION_SERVICES_JSON_TYPE.isCompatible(mediaType)) {
- return jsonMapperFunction.apply(uriInfo).readerFor(type).readValue(entityStream);
- }
- else if (APPLICATION_SERVICES_XML_TYPE.isCompatible(mediaType)) {
- ServicesDTO servicesDTO = new ServicesDTO();
- servicesDTO.services = new ArrayList<>();
-
- deserializer.deserialize((start, next) -> {
- String el = start.getName().getLocalPart();
- XMLEvent event = start;
- if (el.equals("uri")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- servicesDTO.services.add(event.asCharacters().getData());
- }
- return start;
- }, end -> {}, entityStream);
-
- return servicesDTO;
- }
-
- return null;
- }
-
- void writeBundleDTOListTo(
- Collection<BundleDTO> list, Class<?> type, Type genericType,
- Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, list);
- }
- else if (APPLICATION_BUNDLES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- try {
- serializer.serialize(
- "bundles",
- (dom, rootEl) -> list.stream().map(
- bundleDTO -> {
- Element bundleEl = dom.createElement("bundle");
-
- Element idEl = dom.createElement("id");
- idEl.setTextContent(String.valueOf(bundleDTO.id));
- Element lastModifiedEl = dom.createElement("lastModified");
- lastModifiedEl.setTextContent(String.valueOf(bundleDTO.lastModified));
- Element stateEl = dom.createElement("state");
- stateEl.setTextContent(String.valueOf(bundleDTO.state));
- Element symbolicNameEl = dom.createElement("symbolicName");
- symbolicNameEl.setTextContent(bundleDTO.symbolicName);
- Element versionEl = dom.createElement("version");
- versionEl.setTextContent(bundleDTO.version);
-
- bundleEl.appendChild(idEl);
- bundleEl.appendChild(lastModifiedEl);
- bundleEl.appendChild(stateEl);
- bundleEl.appendChild(symbolicNameEl);
- bundleEl.appendChild(versionEl);
-
- return bundleEl;
- }
- ).forEach(
- bundleEL -> rootEl.appendChild(bundleEL)
- ),
- entityStream
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeBundleDTOTo(
- BundleDTO bundleDTO,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLE_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, bundleDTO);
- }
- else if (APPLICATION_BUNDLE_XML_TYPE.isCompatible(mediaType)) {
- try {
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true);
- marshaller.marshal(
- new JAXBElement<>(
- new QName("bundle"),
- BundleDTO.class,
- bundleDTO),
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeBundleHeadersTo(
- Dictionary<String, String> headers, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException{
-
- if (APPLICATION_BUNDLEHEADER_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, headers);
- }
- else if (APPLICATION_BUNDLEHEADER_XML_TYPE.isCompatible(mediaType)) {
- try {
- serializer.serialize(
- "bundleHeader",
- (dom, rootEl) -> Collections.list(
- headers.keys()
- ).stream().forEach(
- key -> {
- Element entryEl = dom.createElement("entry");
- entryEl.setAttribute("key", key);
- entryEl.setAttribute("value", headers.get(key));
- rootEl.appendChild(entryEl);
- }
- ),
- entityStream
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeBundlesDTOTo(
- BundlesDTO bundlesDTO,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLES_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, bundlesDTO);
- }
- else if (APPLICATION_BUNDLES_XML_TYPE.isCompatible(mediaType)) {
- try {
- serializer.serialize(
- "bundles",
- (dom, rootEl) -> bundlesDTO.bundles.stream().forEach(
- key -> {
- Element entryEl = dom.createElement("uri");
- entryEl.setTextContent(key);
- rootEl.appendChild(entryEl);
- }
- ),
- entityStream
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeBundleStartLevelDTOTo(
- BundleStartLevelDTO bundleStartLevelDTO, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, bundleStartLevelDTO);
- }
- else if (APPLICATION_BUNDLESTARTLEVEL_XML_TYPE.isCompatible(mediaType)) {
- try {
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true);
- marshaller.marshal(
- new JAXBElement<>(
- new QName("bundleStartLevel"),
- BundleStartLevelDTO.class,
- bundleStartLevelDTO),
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeBundleStateDTOTo(
- BundleStateDTO bundleStateDTO,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_BUNDLESTATE_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, bundleStateDTO);
- }
- else if (APPLICATION_BUNDLESTATE_XML_TYPE.isCompatible(mediaType)) {
- try {
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true);
- marshaller.marshal(
- new JAXBElement<>(
- new QName("bundleState"),
- BundleStateDTO.class,
- bundleStateDTO),
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeFrameworkDTOTo(
- FrameworkDTO frameworkDTO,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, frameworkDTO);
- }
- else if (APPLICATION_XML_TYPE.isCompatible(mediaType)) {
- try {
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true);
- marshaller.marshal(
- new JAXBElement<>(
- new QName("framework"),
- FrameworkDTO.class,
- frameworkDTO),
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeFrameworkStartLevelDTOTo(
- FrameworkStartLevelDTO frameworkStartLevelDTO,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_FRAMEWORKSTARTLEVEL_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, frameworkStartLevelDTO);
- }
- else if (APPLICATION_FRAMEWORKSTARTLEVEL_XML_TYPE.isCompatible(mediaType)) {
- try {
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, true);
- marshaller.marshal(
- new JAXBElement<>(
- new QName("frameworkStartLevel"),
- FrameworkStartLevelDTO.class,
- frameworkStartLevelDTO),
- entityStream);
- } catch (JAXBException e) {
- throw new IOException(e);
- }
- }
- }
-
- void writeServiceReferenceDTOTo(
- ServiceReferenceDTO serviceReferenceDTO, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICE_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, serviceReferenceDTO);
- }
- else if (APPLICATION_SERVICE_XML_TYPE.isCompatible(mediaType)) {
- serviceReferenceDTO_XMLSerializer.serialize(serviceReferenceDTO, uriInfo, entityStream);
- }
- }
-
- void writeServiceReferenceDTOListTo(
- Collection<ServiceReferenceDTO> list, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, list);
- }
- else if (APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- serviceReferenceDTO_XMLSerializer.serialize(list, uriInfo, entityStream);
- }
- }
-
- void writeServiceReferenceDTOsTo(
- ServiceReferenceDTOs serviceReferenceDTOs, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, serviceReferenceDTOs);
- }
- else if (APPLICATION_SERVICES_REPRESENTATIONS_XML_TYPE.isCompatible(mediaType)) {
- serviceReferenceDTO_XMLSerializer.serialize(
- serviceReferenceDTOs.services, uriInfo, entityStream);
- }
- }
-
- void writeServicesDTOTo(
- ServicesDTO servicesDTO, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (APPLICATION_SERVICES_JSON_TYPE.isCompatible(mediaType)) {
- jsonMapperFunction.apply(uriInfo).writeValue(entityStream, servicesDTO);
- }
- else if (APPLICATION_SERVICES_XML_TYPE.isCompatible(mediaType)) {
- try {
- serializer.serialize(
- "services",
- (dom, rootEl) -> servicesDTO.services.stream().forEach(
- key -> {
- Element entryEl = dom.createElement("uri");
- entryEl.setTextContent(key);
- rootEl.appendChild(entryEl);
- }
- ),
- entityStream
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void writeTo(
- Object entity,
- Class<?> type, Type genericType, Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream)
- throws IOException, WebApplicationException {
-
- if (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, BundleDTO.class)) {
-
- writeBundleDTOListTo(
- Collection.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (Collection.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, ServiceReferenceDTO.class)) {
-
- writeServiceReferenceDTOListTo(
- Collection.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (Dictionary.class.isAssignableFrom(type) &&
- nthTypeArgumentIs(0, genericType, String.class) &&
- nthTypeArgumentIs(1, genericType, String.class)) {
-
- writeBundleHeadersTo(
- Dictionary.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (type == BundleDTO.class) {
- writeBundleDTOTo(
- BundleDTO.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundlesDTO.class.equals(type)) {
- writeBundlesDTOTo(
- BundlesDTO.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (BundleStateDTO.class.equals(type)) {
- writeBundleStateDTOTo(
- BundleStateDTO.class.cast(entity), type, genericType,
- annotations, mediaType, httpHeaders, entityStream);
- }
- else if (BundleStartLevelDTO.class.equals(type)) {
- writeBundleStartLevelDTOTo(
- BundleStartLevelDTO.class.cast(entity), type, genericType,
- annotations, mediaType, httpHeaders, entityStream);
- }
- else if (FrameworkStartLevelDTO.class.equals(type)) {
- writeFrameworkStartLevelDTOTo(
- FrameworkStartLevelDTO.class.cast(entity), type, genericType,
- annotations, mediaType, httpHeaders, entityStream);
- }
- else if (FrameworkDTO.class.equals(type)) {
- writeFrameworkDTOTo(
- FrameworkDTO.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServiceReferenceDTO.class.equals(type)) {
- writeServiceReferenceDTOTo(
- ServiceReferenceDTO.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServicesDTO.class.equals(type)) {
- writeServicesDTOTo(
- ServicesDTO.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- else if (ServiceReferenceDTOs.class.equals(type)) {
- writeServiceReferenceDTOsTo(
- ServiceReferenceDTOs.class.cast(entity), type, genericType, annotations,
- mediaType, httpHeaders, entityStream);
- }
- }
-
- private boolean nthTypeArgumentIs(int n, Type type, Class<?> clazz) {
- return ((ParameterizedType)type).getActualTypeArguments()[n].equals(clazz);
- }
-
-}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonDeserializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonDeserializer.java
deleted file mode 100644
index f06b666..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonDeserializer.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import org.osgi.framework.dto.ServiceReferenceDTO;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-
-@SuppressWarnings("serial")
-class ServiceReferenceDTOJsonDeserializer extends StdDeserializer<ServiceReferenceDTO> {
-
- protected ServiceReferenceDTOJsonDeserializer() {
- this(null);
- }
-
- protected ServiceReferenceDTOJsonDeserializer(Class<ServiceReferenceDTO> t) {
- super(t);
- }
-
- @Override
- public ServiceReferenceDTO deserialize(JsonParser jp, DeserializationContext ctxt)
- throws IOException {
-
- ServiceReferenceDTO referenceDTO = new ServiceReferenceDTO();
- JsonNode node = jp.getCodec().readTree(jp);
- referenceDTO.id = node.get("id").asLong();
- referenceDTO.properties = new HashMap<>();
- node.get("properties").fields().forEachRemaining(
- entry -> {
- referenceDTO.properties.put(entry.getKey(), Coerce.from(entry));
- }
- );
-
- String bundleURL = node.get("bundle").asText();
- referenceDTO.bundle = Long.parseLong(bundleURL.substring(bundleURL.lastIndexOf('/') + 1));
-
- List<Long> usingBundles = new ArrayList<>();
- for (JsonNode arrayNode : (ArrayNode)node.get("usingBundles")) {
- bundleURL = arrayNode.asText();
- usingBundles.add(Long.parseLong(bundleURL.substring(bundleURL.lastIndexOf('/') + 1)));
- }
-
- referenceDTO.usingBundles = usingBundles.stream().mapToLong(Long::longValue).toArray();
- return referenceDTO;
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonSerializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonSerializer.java
deleted file mode 100644
index 90faa6a..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOJsonSerializer.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-
-import javax.ws.rs.core.UriInfo;
-
-import org.osgi.framework.dto.ServiceReferenceDTO;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-@SuppressWarnings("serial")
-class ServiceReferenceDTOJsonSerializer extends StdSerializer<ServiceReferenceDTO> {
-
- private final UriInfo uriInfo;
-
- protected ServiceReferenceDTOJsonSerializer(UriInfo uriInfo) {
- this(uriInfo, null);
- }
-
- protected ServiceReferenceDTOJsonSerializer(UriInfo uriInfo, Class<ServiceReferenceDTO> t) {
- super(t);
- this.uriInfo = uriInfo;
- }
-
- @Override
- public void serialize(
- ServiceReferenceDTO value, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
-
- gen.writeStartObject();
- gen.writeNumberField("id", value.id);
- gen.writeObjectField("properties", value.properties);
- gen.writeStringField(
- "bundle",
- uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(value.bundle).toASCIIString()
- );
- gen.writeArrayFieldStart("usingBundles");
- for (long usingBundle : value.usingBundles) {
- gen.writeString(
- uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(usingBundle).toASCIIString()
- );
- }
- gen.writeEndArray();
- gen.writeEndObject();
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLDeserializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLDeserializer.java
deleted file mode 100644
index 583ab8d..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLDeserializer.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-
-import javax.xml.namespace.QName;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
-
-import org.osgi.framework.dto.ServiceReferenceDTO;
-
-class ServiceReferenceDTOXMLDeserializer {
-
- private final XMLDeserializer deserializer;
-
- public ServiceReferenceDTOXMLDeserializer(XMLDeserializer deserializer) {
- this.deserializer = deserializer;
- }
-
- public ServiceReferenceDTO deserializeServiceReferenceDTO(InputStream entityStream) throws IOException {
- AtomicReference<ServiceReferenceDTO> service = new AtomicReference<>();
- deserialize(service::set, entityStream);
- return service.get();
- }
-
- public List<ServiceReferenceDTO> deserializeServiceReferenceDTOList(InputStream entityStream) throws IOException {
- List<ServiceReferenceDTO> services = new ArrayList<>();
- deserialize(services::add, entityStream);
- return services;
- }
-
- private void deserialize(
- Consumer<ServiceReferenceDTO> collector, InputStream entityStream)
- throws IOException {
-
- AtomicReference<ServiceReferenceDTO> service = new AtomicReference<>();
- AtomicBoolean inUsingBundles = new AtomicBoolean();
- deserializer.deserialize((start, next) -> {
- String el = start.getName().getLocalPart();
- XMLEvent event = start;
- if (el.equals("service")) {
- service.set(new ServiceReferenceDTO());
- }
- else if (el.equals("id")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- service.get().id = Long.parseLong(event.asCharacters().getData());
- }
- else if (el.equals("properties")) {
- service.get().properties = new HashMap<>();
- }
- else if (el.equals("property")) {
- Attribute keyAT = start.getAttributeByName(new QName("name"));
- Attribute typeAT = start.getAttributeByName(new QName("type"));
- Attribute valueAT = start.getAttributeByName(new QName("value"));
- String valueTxt = null;
- boolean array = false;
- if (valueAT == null) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- if (!event.isEndElement()) {
- valueTxt = event.asCharacters().getData();
- array = true;
- }
- }
- else {
- valueTxt = valueAT.getValue();
- }
-
- service.get().properties.put(keyAT.getValue(), Coerce.from(keyAT, typeAT, valueTxt, array));
- }
- else if (el.equals("bundle") && inUsingBundles.get()) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- long[] newArray = new long[service.get().usingBundles.length + 1];
- System.arraycopy(service.get().usingBundles, 0, newArray, 0, service.get().usingBundles.length);
- newArray[newArray.length - 1] = bundleIdFromURI(event.asCharacters().getData());
- service.get().usingBundles = newArray;
- }
- else if (el.equals("bundle")) {
- try {event = next.nextEvent();} catch (Exception e) {throw new RuntimeException(e);}
- service.get().bundle = bundleIdFromURI(event.asCharacters().getData());
- }
- else if (el.equals("usingBundles")) {
- service.get().usingBundles = new long[0];
- inUsingBundles.set(true);
- }
- return event;
- }, end -> {
- String el = end.getName().getLocalPart();
- if (el.equals("service")) {
- collector.accept(service.get());
- service.set(null);
- }
- else if (el.equals("usingBundles")) {
- inUsingBundles.set(false);
- }
- }, entityStream);
- }
-
- long bundleIdFromURI(String bundleURI) {
- final URI uri = URI.create(bundleURI);
- final String uriPath = uri.getPath();
- final Path path = Paths.get(uriPath);
- final String bundleId = path.getFileName().toString();
- return Long.parseLong(bundleId);
- }
-
-}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLSerializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLSerializer.java
deleted file mode 100644
index 939707b..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/ServiceReferenceDTOXMLSerializer.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import static java.util.Collections.singleton;
-import static java.util.stream.Collectors.joining;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.ws.rs.core.UriInfo;
-
-import org.osgi.framework.dto.ServiceReferenceDTO;
-import org.w3c.dom.Element;
-
-class ServiceReferenceDTOXMLSerializer {
-
- private final XMLSerializer serializer;
-
- public ServiceReferenceDTOXMLSerializer(XMLSerializer serializer) {
- this.serializer = serializer;
- }
-
- public void serialize(
- ServiceReferenceDTO service, UriInfo uriInfo, OutputStream entityStream) throws IOException {
-
- serialize(singleton(service), null, uriInfo, entityStream);
- }
-
-
- public void serialize(
- Collection<ServiceReferenceDTO> services, UriInfo uriInfo, OutputStream entityStream) throws IOException {
-
- serialize(services, "services", uriInfo, entityStream);
- }
-
- public void serialize(
- Collection<ServiceReferenceDTO> services, String rootElement, UriInfo uriInfo, OutputStream entityStream) throws IOException {
-
- try {
- serializer.serialize(
- rootElement,
- (dom, parentNode) -> services.stream().map(
- serviceReferenceDTO -> {
- Element serviceEl = dom.createElement("service");
-
- Element idEl = dom.createElement("id");
- idEl.setTextContent(String.valueOf(serviceReferenceDTO.id));
- Element propertiesEl = dom.createElement("properties");
- serviceReferenceDTO.properties.forEach((k, v) -> {
- Element propertyEl = dom.createElement("property");
- propertyEl.setAttribute("name", k);
- boolean array = false;
- if (Long.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Long");
- }
- else if (Long[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Long");
- array = true;
- }
- else if (Double.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Double");
- }
- else if (Double[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Double");
- array = true;
- }
- else if (Float.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Float");
- }
- else if (Float[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Float");
- array = true;
- }
- else if (Integer.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Integer");
- }
- else if (Integer[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Integer");
- array = true;
- }
- else if (Byte.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Byte");
- }
- else if (Byte[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Byte");
- array = true;
- }
- else if (Character.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Character");
- }
- else if (Character[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Character");
- array = true;
- }
- else if (Boolean.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Boolean");
- }
- else if (Boolean[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Boolean");
- array = true;
- }
- else if (Short.class.isInstance(v)) {
- propertyEl.setAttribute("type", "Short");
- }
- else if (Short[].class.isInstance(v)) {
- propertyEl.setAttribute("type", "Short");
- array = true;
- }
- else if (String[].class.isInstance(v)) {
- array = true;
- }
-
- if (!array) {
- propertyEl.setAttribute("value", String.valueOf(v));
- }
- else {
- propertyEl.setTextContent(
- Arrays.stream((Object[])v).map(
- String::valueOf
- ).collect(
- joining("\n")
- )
- );
- }
-
- propertiesEl.appendChild(propertyEl);
- });
-
- Element bundleEl = dom.createElement("bundle");
- bundleEl.setTextContent(
- uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(serviceReferenceDTO.bundle).toASCIIString()
- );
- Element usingBundlesEl = dom.createElement("usingBundles");
- for (long usingBundle : serviceReferenceDTO.usingBundles) {
- Element bEl = dom.createElement("bundle");
- bEl.setTextContent(
- uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(usingBundle).toASCIIString()
- );
- usingBundlesEl.appendChild(bEl);
- }
-
- serviceEl.appendChild(idEl);
- serviceEl.appendChild(propertiesEl);
- serviceEl.appendChild(bundleEl);
- serviceEl.appendChild(usingBundlesEl);
-
- return serviceEl;
- }
- ).forEach(
- bundleEL -> parentNode.appendChild(bundleEL)
- ),
- entityStream
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
-
-}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLDeserializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLDeserializer.java
deleted file mode 100644
index e3f803d..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLDeserializer.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.EndElement;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
-
-class XMLDeserializer {
-
- private final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
-
- public <T> void deserialize(
- BiFunction<StartElement, XMLEventReader, XMLEvent> startConsumer,
- Consumer<EndElement> endConsumer, InputStream entityStream)
- throws IOException {
-
- try {
- XMLEventReader eventReader = inputFactory.createXMLEventReader(entityStream);
-
- while (eventReader.hasNext()) {
- XMLEvent event = eventReader.nextEvent();
-
- if (event.isStartElement()) {
- event = startConsumer.apply(event.asStartElement(), eventReader);
- }
-
- if (event.isEndElement()) {
- endConsumer.accept(event.asEndElement());
- }
- }
- } catch (XMLStreamException e) {
- throw new IOException(e);
- }
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLSerializer.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLSerializer.java
deleted file mode 100644
index 1739236..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/XMLSerializer.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.function.BiConsumer;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-class XMLSerializer {
-
- private final DocumentBuilder db;
-
- public XMLSerializer() {
- try {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- db = dbf.newDocumentBuilder();
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public void serialize(
- String rootElement, BiConsumer<Document, Node> consumer,
- OutputStream entityStream)
- throws Exception {
-
- try {
- Document dom = db.newDocument();
- Node parentNode = dom;
- if (rootElement != null) {
- parentNode = dom.createElement(rootElement);
- dom.appendChild(parentNode);
- }
-
- consumer.accept(dom, parentNode);
-
- Transformer tr = TransformerFactory.newInstance().newTransformer();
- tr.setOutputProperty(OutputKeys.STANDALONE, "yes");
- tr.setOutputProperty(OutputKeys.INDENT, "yes");
- tr.setOutputProperty(OutputKeys.METHOD, "xml");
- tr.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
-
- tr.transform(
- new DOMSource(dom),
- new StreamResult(entityStream)
- );
- }
- catch (Exception e) {
- throw new IOException(e);
- }
- }
-
-}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/BaseResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/BaseResource.java
new file mode 100644
index 0000000..755958c
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/BaseResource.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.toList;
+import static org.osgi.framework.Bundle.ACTIVE;
+import static org.osgi.framework.Bundle.STARTING;
+import static org.osgi.framework.Bundle.STOPPING;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWiring;
+
+public abstract class BaseResource {
+
+ final BundleContext bundleContext;
+ final Bundle framework;
+
+ @Context
+ volatile UriInfo uriInfo;
+ @Context
+ volatile HttpHeaders headers;
+
+ public BaseResource(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ this.framework = bundleContext.getBundle(0);
+ }
+
+ BundleStateSchema bundleStateSchema(Bundle bundle) {
+ int state = bundle.getState();
+ BundleStartLevel bundleStartLevel = bundle.adapt(BundleStartLevel.class);
+ return BundleStateSchema.build(
+ state, (bundleStartLevel.isActivationPolicyUsed() ? Bundle.START_ACTIVATION_POLICY : 0) |
+ (((state & (STARTING|ACTIVE|STOPPING)) != 0) ?
+ (bundleStartLevel.isPersistentlyStarted() ? 0 : Bundle.START_TRANSIENT) : 0));
+ }
+
+ BundleSchema bundleSchema(Bundle bundle) {
+ return BundleSchema.build(
+ bundle.getBundleId(),
+ bundle.getLastModified(),
+ bundle.getState(),
+ bundle.getSymbolicName(),
+ bundle.getVersion().toString(),
+ bundle.getLocation()
+ );
+ }
+
+ static Predicate<Bundle> fromNamespaceQuery(UriInfo info) {
+ MultivaluedMap<String,String> parameters = info.getQueryParameters(true);
+
+ if (parameters.isEmpty()) {
+ return b -> true;
+ }
+
+ Map<String, List<Filter>> filters = parameters.entrySet().stream().flatMap(
+ e -> e.getValue().stream().map(v -> new SimpleEntry<>(e.getKey(), v))
+ ).map(
+ e -> new SimpleEntry<>(e.getKey(), create(e.getValue()))
+ ).collect(
+ groupingBy(Entry::getKey, mapping(Entry::getValue, toList()))
+ );
+
+ if (filters.isEmpty()) {
+ return b -> true;
+ }
+
+ return b -> {
+ BundleWiring wiring = b.adapt(BundleWiring.class);
+ return filters.entrySet().stream().allMatch(
+ entry -> {
+ String namespace = entry.getKey();
+ List<BundleCapability> caps = wiring.getCapabilities(namespace);
+ return entry.getValue().stream().anyMatch(
+ f ->
+ caps.stream().anyMatch(
+ cap ->
+ f.matches(cap.getAttributes())
+ )
+ );
+ }
+ );
+ };
+ }
+
+ static Predicate<ServiceReferenceDTO> fromFilterQuery(String filter) {
+ return Optional.ofNullable(
+ filter
+ ).map(
+ BaseResource::create
+ ).map(
+ toPredicate()
+ ).orElseGet(
+ () -> sr -> true
+ );
+ }
+
+ static Filter create(String filter) {
+ try {
+ return FrameworkUtil.createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new WebApplicationException(
+ String.format("Malformed filter [%s]", filter),
+ Response.Status.BAD_REQUEST);
+ }
+ }
+
+ static Function<Filter, Predicate<ServiceReferenceDTO>> toPredicate() {
+ return f -> sr ->
+ f.matches(sr.properties);
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleHeaderResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleHeaderResource.java
new file mode 100644
index 0000000..88cc130
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleHeaderResource.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static javax.ws.rs.core.HttpHeaders.ACCEPT_LANGUAGE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEHEADER_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEHEADER_XML;
+
+import java.util.Locale;
+import java.util.Optional;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.internal.map.CaseInsensitiveMap;
+import org.apache.aries.jax.rs.rest.management.schema.BundleHeaderSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundleHeaderResource extends BaseResource {
+
+ public FrameworkBundleHeaderResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.6.1
+ @GET
+ @Produces({APPLICATION_BUNDLEHEADER_JSON, APPLICATION_BUNDLEHEADER_XML})
+ @Path("framework/bundle/{bundleid}/header{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundle/header",
+ summary = "Retrieves a Bundle Header Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleHeaderSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ },
+ parameters = {
+ @Parameter(
+ name = ACCEPT_LANGUAGE,
+ description = "The raw header value is used unless an Accept-Language header is set on the HTTP request. If multiple accepted languages are set only the first is used to localize the header",
+ in = ParameterIn.HEADER
+ )
+ }
+ )
+ public Response bundleHeaders(
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ String language = headers.getAcceptableLanguages().stream().findFirst().map(Locale::toString).orElse(null);
+
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(404);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ new BundleHeaderSchema(new CaseInsensitiveMap<>(bundle.getHeaders(language)))
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLEHEADER_JSON : APPLICATION_BUNDLEHEADER_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleResource.java
new file mode 100644
index 0000000..aa1f68b
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleResource.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_VNDOSGIBUNDLE;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Optional;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleExceptionSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundleResource extends BaseResource {
+
+ public FrameworkBundleResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.4.1
+ @GET
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundle/{bundleid}{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundle",
+ summary = "Retrieves a Bundle Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response bundle(
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException("There is no bundle with the given bundle id", 404);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+ // 137.3.4.2
+ @PUT
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundle/{bundleid}{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "PUT/bundle",
+ summary = "Updates the bundle with a new version",
+ requestBody = @RequestBody(
+ description = "One of the following contents is allowed; a location string with content-type type 'text/plain' OR a bundle jar with content-type 'application/vnd.osgi.bundle'",
+ required = true,
+ content = {
+ @Content(mediaType = TEXT_PLAIN, schema = @Schema(description = "a location string", type = "string")),
+ @Content(mediaType = APPLICATION_VNDOSGIBUNDLE, schema = @Schema(description = "a bundle jar", type = "string", format = "binary"))
+ }
+ ),
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request was received and valid and the framework has issued the update",
+ content = @Content(schema = @Schema(implementation = BundleSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "the REST management service received a BundleException when trying to update",
+ content = {
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_JSON, schema = @Schema(implementation = BundleExceptionSchema.class)),
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_XML, schema = @Schema(implementation = BundleExceptionSchema.class))
+ }
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response bundle(
+ String location,
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(String.valueOf(bundleid), 404);
+ }
+
+ if (location != null && !location.isEmpty()) {
+ bundle.update(new URL(location).openStream());
+ }
+ else {
+ bundle.update();
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ catch (Exception e) {
+ throw new WebApplicationException(e, 400);
+ }
+ }
+
+ // 137.3.4.3
+ @PUT
+ @Consumes(APPLICATION_VNDOSGIBUNDLE)
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundle/{bundleid}{ext:(\\.json|\\.xml)*}")
+ @Operation(hidden = true)
+ public Response putBundle(
+ InputStream inputStream,
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(String.valueOf(bundleid), 404);
+ }
+
+ bundle.update(inputStream);
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ }
+
+ // 137.3.4.4
+ @DELETE
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundle/{bundleid}{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "DELETE/bundle",
+ summary = "Uninstalls the bundle from the framework",
+ responses = {
+ @ApiResponse(
+ responseCode = "204",
+ description = "The request was received and valid and the framework has uninstalled the bundle",
+ content = @Content(schema = @Schema(implementation = BundleSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "The REST management service received a BundleException when trying to uninstall",
+ content = {
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_JSON, schema = @Schema(implementation = BundleExceptionSchema.class)),
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_XML, schema = @Schema(implementation = BundleExceptionSchema.class))
+ }
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ )
+ }
+ )
+ public Response deleteBundle(
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(String.valueOf(bundleid), 404);
+ }
+
+ bundle.uninstall();
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ catch (Exception exception) {
+ throw new WebApplicationException(exception, 400);
+ }
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStartLevelResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStartLevelResource.java
new file mode 100644
index 0000000..77a3f6c
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStartLevelResource.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTARTLEVEL_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTARTLEVEL_XML;
+
+import java.util.Optional;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleExceptionSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStartLevelSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundleStartLevelResource extends BaseResource {
+
+ public FrameworkBundleStartLevelResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.7.1
+ @GET
+ @Produces({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
+ @Path("framework/bundle/{bundleid}/startlevel{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundle/startlevel",
+ summary = "Retrieves a Bundle Startlevel Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleStartLevelSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response bundleStartlevel(
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(404);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ BundleStartLevelSchema.build(bundle.adapt(BundleStartLevelDTO.class))
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTARTLEVEL_JSON : APPLICATION_BUNDLESTARTLEVEL_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+ // 137.3.7.2
+ @PUT
+ @Consumes({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
+ @Produces({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
+ @Path("framework/bundle/{bundleid}/startlevel{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "PUT/bundle/startlevel",
+ summary = "Sets the target bundle startlevel",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request was received and valid. The REST management service has changed the bundle startlevel according to the target value",
+ content = @Content(schema = @Schema(implementation = BundleStartLevelSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "Either the target startlevel state involved invalid values, e.g., a startlevel smaller or equal to zero and the REST management service got an IllegalArgumentException, or the REST management service received a BundleException when trying to perform the startlevel change",
+ content = {
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_JSON, schema = @Schema(implementation = BundleExceptionSchema.class)),
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_XML, schema = @Schema(implementation = BundleExceptionSchema.class))
+ }
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "415",
+ description = "The request had a media type that is not supported by the REST management service"
+ )
+ }
+ )
+ public Response bundleStartlevel(
+ BundleStartLevelSchema update,
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(404);
+ }
+
+ try {
+ BundleStartLevel current = bundle.adapt(BundleStartLevel.class);
+
+ if (current.getStartLevel() != update.startLevel) {
+ current.setStartLevel(update.startLevel);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ BundleStartLevelSchema.build(bundle.adapt(BundleStartLevelDTO.class))
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTARTLEVEL_JSON : APPLICATION_BUNDLESTARTLEVEL_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (Exception exception) {
+ if (exception instanceof BundleException) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(
+ ((BundleException)exception).getType(), exception.getMessage())
+ ).build();
+ }
+ else {
+ throw new WebApplicationException(exception, 400);
+ }
+ }
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStateResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStateResource.java
new file mode 100644
index 0000000..a555ca2
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundleStateResource.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_XML;
+import static org.osgi.framework.Bundle.ACTIVE;
+import static org.osgi.framework.Bundle.INSTALLED;
+import static org.osgi.framework.Bundle.RESOLVED;
+
+import java.util.Collections;
+import java.util.Optional;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleExceptionSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundleStateResource extends BaseResource {
+
+ public FrameworkBundleStateResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.5.1
+ @GET
+ @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
+ @Path("framework/bundle/{bundleid}/state{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundle/state",
+ summary = "Retrieves a Bundle State Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleStateSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response bundleState(
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException(404);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleStateSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTATE_JSON : APPLICATION_BUNDLESTATE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+ // 137.3.5.2
+ @PUT
+ @Consumes({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
+ @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
+ @Path("framework/bundle/{bundleid}/state{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "PUT/bundle/state",
+ summary = "Sets the target state for the given bundle. This can, e.g., be state=32 for transitioning the bundle to started, or state=4 for stopping the bundle and transitioning it to resolved",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request was received and valid and the framework has performed a state change",
+ content = @Content(schema = @Schema(implementation = BundleStateSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "The REST management service received a BundleException when trying to perform the state transition",
+ content = {
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_JSON, schema = @Schema(implementation = BundleExceptionSchema.class)),
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_XML, schema = @Schema(implementation = BundleExceptionSchema.class))
+ }
+ ),
+ @ApiResponse(
+ responseCode = "402",
+ description = "The requested target state is not reachable from the current bundle state or is not a target state"
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no bundle with the given bundle id"
+ ),
+ @ApiResponse(
+ responseCode = "415",
+ description = "The request had a media type that is not supported by the REST management service"
+ )
+ }
+ )
+ public Response bundleState(
+ BundleStateSchema bundleStateDTO,
+ @PathParam("bundleid") long bundleid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ Bundle bundle = bundleContext.getBundle(bundleid);
+
+ if (bundle == null) {
+ throw new WebApplicationException("there is no bundle with the given bundle id", 404);
+ }
+
+ int currentState = bundle.getState();
+
+ if ((currentState & INSTALLED) == INSTALLED ||
+ (currentState & RESOLVED) == RESOLVED) {
+ if ((bundleStateDTO.state & ACTIVE) == ACTIVE) {
+ bundle.start(bundleStateDTO.options);
+ }
+ else if ((bundleStateDTO.state & RESOLVED) == RESOLVED) {
+ framework.adapt(
+ FrameworkWiring.class
+ ).resolveBundles(
+ Collections.singleton(bundle)
+ );
+ }
+ }
+ else if ((currentState & ACTIVE) == ACTIVE) {
+ if ((bundleStateDTO.state & RESOLVED) == RESOLVED) {
+ bundle.stop(bundleStateDTO.options);
+ }
+ }
+ else {
+ throw new WebApplicationException(
+ String.format(
+ "the requested target state [%s] is not reachable " +
+ "from the current bundle state [%s] or is not a " +
+ "target state",
+ bundleStateDTO.state, currentState), 402);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleStateSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTATE_JSON : APPLICATION_BUNDLESTATE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLESTATE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ catch (Exception exception) {
+ throw new WebApplicationException(exception, 400);
+ }
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesRepresentationsResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesRepresentationsResource.java
new file mode 100644
index 0000000..6a44a54
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesRepresentationsResource.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_REPRESENTATIONS_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_REPRESENTATIONS_XML;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchemaListSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundlesRepresentationsResource extends BaseResource {
+
+ public FrameworkBundlesRepresentationsResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.3.1
+ @GET
+ @Produces({APPLICATION_BUNDLES_REPRESENTATIONS_JSON, APPLICATION_BUNDLES_REPRESENTATIONS_XML})
+ @Path("framework/bundles/representations{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundles/representations",
+ summary = "Retrieve the bundle representation of each installed bundle",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleSchemaListSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ },
+ parameters = {
+ @Parameter(
+ name = "<capability_namespace>",
+ in = ParameterIn.QUERY,
+ description = "A query parameter whose name is an osgi capability namespace and whose value is a filter expression that follows the Core Specifications Framework Filter Syntax; see OSGi Core, Chapter 3.2.7 Filter Syntax. Filters are matched against the attributes of capabilities in the respective namespaces. If multiple capabilities for a given namespace are present, then a filter succeeds when one of these capabilities matches. When multiple filter expressions across nam [...]
+ examples = @ExampleObject(
+ summary = "format: <capability_namespace>=<filter_string>",
+ value = "osgi.identity=(osgi.identity=foo)&osgi.package.wiring=(osgi.package.wiring=com.foo)"
+ )
+ )
+ }
+ )
+ public Response bundlesRepresentations(
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Predicate<Bundle> predicate = fromNamespaceQuery(uriInfo);
+
+ ResponseBuilder builder = Response.ok(
+ BundleSchemaListSchema.build(
+ Stream.of(
+ bundleContext.getBundles()
+ ).filter(
+ predicate
+ ).map(
+ this::bundleSchema
+ ).collect(toList())
+ )
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLES_REPRESENTATIONS_JSON : APPLICATION_BUNDLES_REPRESENTATIONS_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesResource.java
new file mode 100644
index 0000000..e5e53c4
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkBundlesResource.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static java.util.stream.Collectors.toList;
+import static javax.ws.rs.core.HttpHeaders.CONTENT_LOCATION;
+import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLEEXCEPTION_XML_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLES_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON_TYPE;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_VNDOSGIBUNDLE;
+
+import java.io.InputStream;
+import java.time.Instant;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleExceptionSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleListSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkBundlesResource extends BaseResource {
+
+ public FrameworkBundlesResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.2.1
+ @GET
+ @Produces({APPLICATION_BUNDLES_JSON, APPLICATION_BUNDLES_XML})
+ @Path("framework/bundles{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/bundles",
+ summary = "Retrieves a Bundle List Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = BundleListSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ },
+ parameters = {
+ @Parameter(
+ name = "<capability_namespace>",
+ in = ParameterIn.QUERY,
+ description = "A query parameter whose name is an osgi capability namespace and whose value is a filter expression that follows the Core Specifications Framework Filter Syntax; see OSGi Core, Chapter 3.2.7 Filter Syntax. Filters are matched against the attributes of capabilities in the respective namespaces. If multiple capabilities for a given namespace are present, then a filter succeeds when one of these capabilities matches. When multiple filter expressions across nam [...]
+ examples = @ExampleObject(
+ summary = "format: <capability_namespace>=<filter_string>",
+ value = "osgi.identity=(osgi.identity=foo)&osgi.package.wiring=(osgi.package.wiring=com.foo)"
+ )
+ )
+ }
+ )
+ public Response bundles(
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Predicate<Bundle> predicate = fromNamespaceQuery(uriInfo);
+
+ ResponseBuilder builder = Response.status(
+ Response.Status.OK
+ ).entity(
+ BundleListSchema.build(
+ Stream.of(
+ bundleContext.getBundles()
+ ).filter(
+ predicate
+ ).map(
+ Bundle::getBundleId
+ ).map(
+ String::valueOf
+ ).map(
+ id -> uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(id).toASCIIString()
+ ).collect(toList())
+ )
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTATE_JSON : APPLICATION_BUNDLESTATE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+ // 137.3.2.2
+ @POST
+ @Consumes(TEXT_PLAIN)
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundles{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "POST/bundles",
+ summary = "Installs a new bundle to the managed framework and thereby logically appends it to the bundles resource",
+ requestBody = @RequestBody(
+ description = "One of the following contents is allowed; a location string with content-type type 'text/plain' OR a bundle jar with content-type 'application/vnd.osgi.bundle'",
+ required = true,
+ content = {
+ @Content(mediaType = TEXT_PLAIN, schema = @Schema(description = "a location string", type = "string")),
+ @Content(mediaType = APPLICATION_VNDOSGIBUNDLE, schema = @Schema(description = "a bundle jar", type = "string", format = "binary"))
+ }
+ ),
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ content = @Content(schema = @Schema(implementation = BundleSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "the REST management service received a BundleException when trying to install",
+ content = {
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_JSON, schema = @Schema(implementation = BundleExceptionSchema.class)),
+ @Content(mediaType = APPLICATION_BUNDLEEXCEPTION_XML, schema = @Schema(implementation = BundleExceptionSchema.class))
+ }
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ },
+ parameters = {
+ @Parameter(
+ name = CONTENT_LOCATION,
+ in = ParameterIn.HEADER,
+ description = "When posting a bundle jar a location string can be specified using the 'Content-Location' header",
+ required = false
+ )
+ }
+ )
+ public Response bundles(
+ String location,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ Instant now = Instant.now().minusMillis(2);
+ Bundle bundle = bundleContext.installBundle(location);
+
+ if (!now.isBefore(Instant.ofEpochMilli(bundle.getLastModified()))) {
+ throw new WebApplicationException(location, 409);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ }
+
+ // 137.3.2.3
+ @POST
+ @Consumes(APPLICATION_VNDOSGIBUNDLE)
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Path("framework/bundles{ext:(\\.json|\\.xml)*}")
+ @Operation(hidden = true)
+ public Response bundles(
+ InputStream inputStream,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext,
+ @HeaderParam(CONTENT_LOCATION) String location,
+ @HeaderParam(CONTENT_TYPE) MediaType contentType) {
+
+ try {
+ location = Optional.ofNullable(location).orElseGet(
+ () -> "org.apache.aries.jax.rs.whiteboard:".concat(
+ UUID.randomUUID().toString()));
+
+ Instant now = Instant.now().minusMillis(2);
+ Bundle bundle = bundleContext.installBundle(location, inputStream);
+
+ if (!now.isBefore(Instant.ofEpochMilli(bundle.getLastModified()))) {
+ throw new WebApplicationException(location, 409);
+ }
+
+ ResponseBuilder builder = Response.ok(
+ bundleSchema(bundle)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+ catch (BundleException exception) {
+ return Response.status(400).type(
+ contentType.equals(APPLICATION_BUNDLE_JSON_TYPE) ?
+ APPLICATION_BUNDLEEXCEPTION_JSON_TYPE :
+ APPLICATION_BUNDLEEXCEPTION_XML_TYPE
+ ).entity(
+ BundleExceptionSchema.build(exception.getType(), exception.getMessage())
+ ).build();
+ }
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkResource.java
index faa8fb4..fc8396a 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkResource.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkResource.java
@@ -17,678 +17,72 @@
package org.apache.aries.jax.rs.rest.management.internal;
-import static java.util.stream.Collectors.groupingBy;
-import static java.util.stream.Collectors.mapping;
-import static java.util.stream.Collectors.toList;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.*;
-import static org.osgi.framework.Bundle.ACTIVE;
-import static org.osgi.framework.Bundle.INSTALLED;
-import static org.osgi.framework.Bundle.RESOLVED;
-import static org.osgi.framework.Bundle.STARTING;
-import static org.osgi.framework.Bundle.STOPPING;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLE_XML;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-import java.time.Instant;
-import java.util.AbstractMap;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
-import java.util.Set;
-import java.util.UUID;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import org.apache.aries.jax.rs.rest.management.model.BundleStateDTO;
-import org.apache.aries.jax.rs.rest.management.model.BundlesDTO;
-import org.apache.aries.jax.rs.rest.management.model.ServiceReferenceDTOs;
-import org.apache.aries.jax.rs.rest.management.model.ServicesDTO;
-import org.osgi.framework.Bundle;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.dto.BundleDTO;
-import org.osgi.framework.dto.FrameworkDTO;
-import org.osgi.framework.dto.ServiceReferenceDTO;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
-import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.framework.wiring.FrameworkWiring;
-public class FrameworkResource {
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
- private final BundleContext bundleContext;
- private final Bundle framework;
-
- @Context
- volatile UriInfo uriInfo;
- @Context
- volatile HttpHeaders headers;
+public class FrameworkResource extends BaseResource {
public FrameworkResource(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- this.framework = bundleContext.getBundle(0);
- }
-
- @GET
- @Path("framework{type: (\\.json|\\.xml)*}")
- @Produces({APPLICATION_JSON, APPLICATION_XML})
- public Response framework(@PathParam("type") String type) {
- ResponseBuilder builder = Response.status(
- Response.Status.OK
- ).entity(
- framework.adapt(FrameworkDTO.class)
- );
-
- return Optional.ofNullable(
- type
- ).map(
- String::trim
- ).map(
- t -> ".json".equals(t) ? APPLICATION_JSON : APPLICATION_XML
- ).map(t -> builder.type(t)).orElse(
- builder
- ).build();
- }
-
- @GET
- @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
- @Path("framework/state{type:(\\.json|\\.xml)*}")
- public Response state(@PathParam("type") String type) {
- ResponseBuilder builder = Response.status(
- Response.Status.OK
- ).entity(
- state(framework)
- );
-
- return Optional.ofNullable(
- type
- ).map(
- String::trim
- ).map(
- t -> ".json".equals(t) ? APPLICATION_BUNDLESTATE_JSON : APPLICATION_BUNDLESTATE_XML
- ).map(t -> builder.type(t)).orElse(
- builder
- ).build();
+ super(bundleContext);
}
- // 137.3.1.1
@GET
- @Produces({APPLICATION_FRAMEWORKSTARTLEVEL_JSON, APPLICATION_FRAMEWORKSTARTLEVEL_XML})
- @Path("framework/startlevel{type:(\\.json|\\.xml)*}")
- public Response startlevel(@PathParam("type") String type) {
+ @Path("framework{ext: (\\.json|\\.xml)*}")
+ @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
+ @Operation(
+ summary = "Get the framework bundle by extension type",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The framework bundle",
+ content = @Content(schema = @Schema(implementation = BundleSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "Framework not found"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response framework(
+ @Parameter(allowEmptyValue = true, schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
ResponseBuilder builder = Response.status(
Response.Status.OK
).entity(
- framework.adapt(FrameworkStartLevelDTO.class)
+ bundleSchema(framework)
);
return Optional.ofNullable(
- type
+ ext
).map(
String::trim
).map(
- t -> ".json".equals(t) ? APPLICATION_FRAMEWORKSTARTLEVEL_JSON : APPLICATION_FRAMEWORKSTARTLEVEL_XML
+ t -> ".json".equals(t) ? APPLICATION_BUNDLE_JSON : APPLICATION_BUNDLE_XML
).map(t -> builder.type(t)).orElse(
builder
).build();
}
- // 137.3.1.2
- @PUT
- @Consumes({APPLICATION_FRAMEWORKSTARTLEVEL_JSON, APPLICATION_FRAMEWORKSTARTLEVEL_XML})
- @Path("framework/startlevel")
- public Response startlevel(FrameworkStartLevelDTO update) {
- try {
- FrameworkStartLevel current = framework.adapt(FrameworkStartLevel.class);
-
- if (current.getStartLevel() != update.startLevel) {
- current.setStartLevel(update.startLevel);
- }
- if (current.getInitialBundleStartLevel() != update.initialBundleStartLevel) {
- current.setInitialBundleStartLevel(update.initialBundleStartLevel);
- }
-
- return Response.noContent().build();
- }
- catch (IllegalArgumentException exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.2.1
- @GET
- @Produces({APPLICATION_BUNDLES_JSON, APPLICATION_BUNDLES_XML})
- @Path("framework/bundles")
- public BundlesDTO bundles(@Context UriInfo info) {
- Predicate<Bundle> predicate = fromNamespaceQuery(info);
-
- return BundlesDTO.build(
- Stream.of(
- bundleContext.getBundles()
- ).filter(
- predicate
- ).map(
- Bundle::getBundleId
- ).map(
- String::valueOf
- ).map(
- id -> uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(id).toASCIIString()
- ).collect(toList())
- );
- }
-
- // 137.3.2.2
- @POST
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundles")
- public Response postBundles(String location) {
- try {
- Instant now = Instant.now().minusMillis(2);
- Bundle bundle = bundleContext.installBundle(location);
-
- if (!now.isBefore(Instant.ofEpochMilli(bundle.getLastModified()))) {
- throw new WebApplicationException(location, 409);
- }
-
- return Response.ok(
- bundle.adapt(BundleDTO.class)
- ).build();
- }
- catch (BundleException exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.2.3
- @POST
- @Consumes(APPLICATION_VNDOSGIBUNDLE)
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundles")
- public Response postBundles(
- InputStream inputStream,
- @HeaderParam(HttpHeaders.CONTENT_LOCATION) String location) {
-
- try {
- location = Optional.ofNullable(location).orElseGet(
- () -> "org.apache.aries.jax.rs.whiteboard:".concat(
- UUID.randomUUID().toString()));
-
- Instant now = Instant.now().minusMillis(2);
- Bundle bundle = bundleContext.installBundle(location, inputStream);
-
- if (!now.isBefore(Instant.ofEpochMilli(bundle.getLastModified()))) {
- throw new WebApplicationException(location, 409);
- }
-
- return Response.ok(
- bundle.adapt(BundleDTO.class)
- ).build();
- }
- catch (BundleException exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.3.1
- @GET
- @Produces({APPLICATION_BUNDLES_REPRESENTATIONS_JSON, APPLICATION_BUNDLES_REPRESENTATIONS_XML})
- @Path("framework/bundles/representations")
- public Collection<BundleDTO> bundleDTOs(@Context UriInfo info) {
- Predicate<Bundle> predicate = fromNamespaceQuery(info);
-
- return Stream.of(
- bundleContext.getBundles()
- ).filter(
- predicate
- ).map(
- b -> b.adapt(BundleDTO.class)
- ).collect(Collectors.toList());
- }
-
- // 137.3.4.1
- @GET
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundle/{bundleid}")
- public BundleDTO bundle(@PathParam("bundleid") long bundleid) {
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- return bundle.adapt(BundleDTO.class);
- }
-
- // 137.3.4.2
- @PUT
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundle/{bundleid}")
- public Response postBundle(
- @PathParam("bundleid") long bundleid, String location) {
-
- try {
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(String.valueOf(bundleid), 404);
- }
-
- if (location != null && !location.isEmpty()) {
- bundle.update(new URL(location).openStream());
- }
- else {
- bundle.update();
- }
-
- return Response.ok(
- bundle.adapt(BundleDTO.class)
- ).build();
- }
- catch (Exception exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.4.3
- @PUT
- @Consumes(APPLICATION_VNDOSGIBUNDLE)
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundle/{bundleid}")
- public Response postBundle(
- @PathParam("bundleid") long bundleid, InputStream inputStream) {
-
- try {
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(String.valueOf(bundleid), 404);
- }
-
- bundle.update(inputStream);
-
- return Response.ok(
- bundle.adapt(BundleDTO.class)
- ).build();
- }
- catch (Exception exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.4.4
- @DELETE
- @Produces({APPLICATION_BUNDLE_JSON, APPLICATION_BUNDLE_XML})
- @Path("framework/bundle/{bundleid}")
- public Response deleteBundle(@PathParam("bundleid") long bundleid) {
-
- try {
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(String.valueOf(bundleid), 404);
- }
-
- bundle.uninstall();
-
- return Response.ok(
- bundle.adapt(BundleDTO.class)
- ).build();
- }
- catch (Exception exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.5.1
- @GET
- @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
- @Path("framework/bundle/{bundleid}/state")
- public BundleStateDTO bundleState(@PathParam("bundleid") long bundleid) {
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- return state(bundle);
- }
-
- // 137.3.5.2
- @PUT
- @Consumes({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
- @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
- @Path("framework/bundle/{bundleid}/state")
- public BundleStateDTO bundleState(
- @PathParam("bundleid") long bundleid,
- BundleStateDTO bundleStateDTO) {
-
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- int currentState = bundle.getState();
-
- try {
- if ((currentState & INSTALLED) == INSTALLED ||
- (currentState & RESOLVED) == RESOLVED) {
- if ((bundleStateDTO.state & ACTIVE) == ACTIVE) {
- bundle.start(bundleStateDTO.options);
- }
- else if ((bundleStateDTO.state & RESOLVED) == RESOLVED) {
- framework.adapt(
- FrameworkWiring.class
- ).resolveBundles(
- Collections.singleton(bundle)
- );
- }
- }
- else if ((currentState & ACTIVE) == ACTIVE) {
- if ((bundleStateDTO.state & RESOLVED) == RESOLVED) {
- bundle.stop(bundleStateDTO.options);
- }
- }
- else {
- throw new WebApplicationException(
- String.format(
- "the requested target state [%s] is not reachable " +
- "from the current bundle state [%s] or is not a " +
- "target state",
- bundleStateDTO.state, currentState), 402);
- }
- }
- catch (BundleException exception) {
- throw new WebApplicationException(exception, 400);
- }
-
- return state(bundle);
- }
-
- // 137.3.6.1
- @GET
- @Produces({APPLICATION_BUNDLEHEADER_JSON, APPLICATION_BUNDLEHEADER_XML})
- @Path("framework/bundle/{bundleid}/header")
- public Dictionary<String, String> bundleHeaders(
- @PathParam("bundleid") long bundleid) {
-
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- return bundle.getHeaders();
- }
-
- // 137.3.7.1
- @GET
- @Produces({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
- @Path("framework/bundle/{bundleid}/startlevel")
- public BundleStartLevelDTO bundleStartlevel(
- @PathParam("bundleid") long bundleid) {
-
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- return bundle.adapt(BundleStartLevelDTO.class);
- }
-
- // 137.3.7.2
- @PUT
- @Consumes({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
- @Produces({APPLICATION_BUNDLESTARTLEVEL_JSON, APPLICATION_BUNDLESTARTLEVEL_XML})
- @Path("framework/bundle/{bundleid}/startlevel")
- public Response bundleStartlevel(
- @PathParam("bundleid") long bundleid, BundleStartLevelDTO update) {
-
- Bundle bundle = bundleContext.getBundle(bundleid);
-
- if (bundle == null) {
- throw new WebApplicationException(404);
- }
-
- try {
- BundleStartLevel current = bundle.adapt(BundleStartLevel.class);
-
- if (current.getStartLevel() != update.startLevel) {
- current.setStartLevel(update.startLevel);
- }
-
- return Response.ok(bundle.adapt(BundleStartLevelDTO.class)).build();
- }
- catch (IllegalArgumentException exception) {
- throw new WebApplicationException(exception, 400);
- }
- }
-
- // 137.3.8.1
- @GET
- @Produces({APPLICATION_SERVICES_JSON, APPLICATION_SERVICES_XML})
- @Path("framework/services")
- public ServicesDTO services(@QueryParam("filter") String filter) {
- Predicate<ServiceReferenceDTO> predicate = fromFilterQuery(filter);
-
- return ServicesDTO.build(
- framework.adapt(FrameworkDTO.class).services.stream().filter(
- predicate
- ).map(
- sr -> String.valueOf(sr.id)
- ).map(
- id -> uriInfo.getBaseUriBuilder().path("framework").path("service").path(id)
- ).map(
- UriBuilder::build
- ).map(
- URI::toASCIIString
- )
- .collect(toList())
- );
- }
-
- // 137.3.9.1
- @GET
- @Produces({APPLICATION_SERVICES_REPRESENTATIONS_JSON, APPLICATION_SERVICES_REPRESENTATIONS_XML})
- @Path("framework/services/representations")
- public ServiceReferenceDTOs serviceDTOs(@QueryParam("filter") String filter) {
- Predicate<ServiceReferenceDTO> predicate = fromFilterQuery(filter);
-
- return ServiceReferenceDTOs.build(
- framework.adapt(
- FrameworkDTO.class
- ).services.stream().filter(
- predicate
- ).collect(toList())
- );
- }
-
- // 137.3.9.1
- @GET
- @Produces({APPLICATION_SERVICE_JSON, APPLICATION_SERVICE_XML})
- @Path("framework/service/{serviceid}")
- public ServiceReferenceDTO service(
- @PathParam("serviceid") long serviceid) {
-
- return Stream.of(
- bundleContext.getBundles()
- ).flatMap(
- bundle -> Optional.ofNullable(
- bundle.adapt(ServiceReferenceDTO[].class)
- ).map(
- Stream::of
- ).orElseGet(
- Stream::empty
- )
- ).filter(
- sr -> sr.id == serviceid
- ).findFirst().orElseThrow(
- () -> new WebApplicationException(404)
- );
- }
-
- private BundleStateDTO state(Bundle bundle) {
- final BundleStateDTO bundleState = new BundleStateDTO();
- bundleState.state = bundle.getState();
- BundleStartLevel bundleStartLevel = bundle.adapt(BundleStartLevel.class);
- bundleState.options =
- (bundleStartLevel.isActivationPolicyUsed() ? Bundle.START_ACTIVATION_POLICY : 0) |
- (((bundleState.state & (STARTING|ACTIVE|STOPPING)) != 0) ?
- (bundleStartLevel.isPersistentlyStarted() ? 0 : Bundle.START_TRANSIENT) : 0);
- return bundleState;
- }
-
- static Predicate<Bundle> fromNamespaceQuery(UriInfo info) {
- MultivaluedMap<String,String> parameters = info.getQueryParameters(true);
-
- if (parameters.isEmpty()) {
- return b -> true;
- }
-
- Map<String, List<Filter>> filters = parameters.entrySet().stream().flatMap(
- e -> e.getValue().stream().map(v -> new SimpleEntry<>(e.getKey(), v))
- ).map(
- e -> new SimpleEntry<>(e.getKey(), create(e.getValue()))
- ).collect(
- groupingBy(Entry::getKey, mapping(Entry::getValue, toList()))
- );
-
- if (filters.isEmpty()) {
- return b -> true;
- }
-
- return b -> {
- BundleWiring wiring = b.adapt(BundleWiring.class);
- return filters.entrySet().stream().allMatch(
- entry -> {
- String namespace = entry.getKey();
- List<BundleCapability> caps = wiring.getCapabilities(namespace);
- return entry.getValue().stream().anyMatch(
- f ->
- caps.stream().anyMatch(
- cap ->
- f.matches(cap.getAttributes())
- )
- );
- }
- );
- };
- }
-
- static Predicate<ServiceReferenceDTO> fromFilterQuery(String filter) {
- return Optional.ofNullable(
- filter
- ).map(
- FrameworkResource::create
- ).map(
- toPredicate()
- ).orElseGet(
- () -> sr -> true
- );
- }
-
- static Filter create(String filter) {
- try {
- return FrameworkUtil.createFilter(filter);
- } catch (InvalidSyntaxException e) {
- throw new WebApplicationException(
- String.format("Malformed filter [%s]", filter),
- Response.Status.BAD_REQUEST);
- }
- }
-
- static Function<Filter, Predicate<ServiceReferenceDTO>> toPredicate() {
- return f -> sr -> f.matches(new CaseInsensitiveMap(sr.properties));
- }
-
-
- /**
- * This Map is used for case-insensitive key lookup during filter
- * evaluation. This Map implementation only supports the get operation using
- * a String key as no other operations are used by the Filter
- * implementation.
- */
- private static final class CaseInsensitiveMap extends AbstractMap<String, Object> {
- private final String[] keys;
- private final Map<String, Object> properties;
-
- /**
- * Create a case insensitive map from the specified dictionary.
- *
- * @param properties
- * @throws IllegalArgumentException If {@code dictionary} contains case
- * variants of the same key name.
- */
- CaseInsensitiveMap(Map<String, Object> properties) {
- this.properties = properties;
- List<String> keyList = new ArrayList<>(this.properties.size());
- this.properties.forEach((k,v) -> {
- for (String i : keyList) {
- if (k.equalsIgnoreCase(i)) {
- throw new IllegalArgumentException();
- }
- }
- keyList.add(k);
- });
- this.keys = keyList.toArray(new String[0]);
- }
-
- @Override
- public Object get(Object o) {
- String k = (String) o;
- for (String key : keys) {
- if (key.equalsIgnoreCase(k)) {
- return super.get(key);
- }
- }
- return null;
- }
-
- @Override
- public Set<Entry<String, Object>> entrySet() {
- return this.properties.entrySet();
- }
-
- }
-
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServiceResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServiceResource.java
new file mode 100644
index 0000000..7d64da5
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServiceResource.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.*;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchema;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkServiceResource extends BaseResource {
+
+ public FrameworkServiceResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.9.1
+ @GET
+ @Produces({APPLICATION_SERVICE_JSON, APPLICATION_SERVICE_XML})
+ @Path("framework/service/{serviceid}{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/service",
+ summary = "Retrieves a Service Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = ServiceSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "There is no service with the given service id"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response service(
+ @PathParam("serviceid") long serviceid,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ ResponseBuilder builder = Response.ok(
+ Stream.of(
+ bundleContext.getBundles()
+ ).flatMap(
+ bundle -> Optional.ofNullable(
+ bundle.adapt(ServiceReferenceDTO[].class)
+ ).map(
+ Stream::of
+ ).orElseGet(
+ Stream::empty
+ )
+ ).filter(
+ sr -> sr.id == serviceid
+ ).findFirst().map(
+ sr -> ServiceSchema.build(uriInfo, sr)
+ ).orElseThrow(
+ () -> new WebApplicationException(404)
+ )
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_SERVICE_JSON : APPLICATION_SERVICE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesRepresentationsResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesRepresentationsResource.java
new file mode 100644
index 0000000..df45ad0
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesRepresentationsResource.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_XML;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.internal.map.CaseInsensitiveMap;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchema;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchemaListSchema;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.dto.FrameworkDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkServicesRepresentationsResource extends BaseResource {
+
+ public FrameworkServicesRepresentationsResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.9.1
+ @GET
+ @Produces({APPLICATION_SERVICES_REPRESENTATIONS_JSON, APPLICATION_SERVICES_REPRESENTATIONS_XML})
+ @Path("framework/services/representations{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/services/representations",
+ summary = "Retrieves the service representation of each available service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = ServiceSchemaListSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "The provided filter expression was not valid"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response serviceDTOs(
+ @Parameter(
+ name = "filter",
+ in = ParameterIn.QUERY,
+ description = "A filter parameter whose value is a filter expression that follows the Core Specifications Framework Filter Syntax; see OSGi Core, Chapter 3.2.7 Filter Syntax. The filter is matched against the service attributes and only services that match are returned",
+ examples = @ExampleObject(
+ summary = "format: filter=<filter_string>",
+ value = "filter=(&(osgi.vendor=Apache Aries)(objectClass=com.acme.Widget))"
+ )
+ )
+ @QueryParam("filter") String filter,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Predicate<ServiceReferenceDTO> predicate = fromFilterQuery(filter);
+
+ ResponseBuilder builder = Response.ok(
+ ServiceSchemaListSchema.build(
+ framework.adapt(
+ FrameworkDTO.class
+ ).services.stream().map(
+ sr -> {
+ sr.properties = new CaseInsensitiveMap<Object>(sr.properties);
+ return sr;
+ }
+ ).filter(
+ predicate
+ ).map(
+ sr -> ServiceSchema.build(uriInfo, sr)
+ ).collect(toList())
+ )
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_SERVICES_REPRESENTATIONS_JSON : APPLICATION_SERVICES_REPRESENTATIONS_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesResource.java
new file mode 100644
index 0000000..099414f
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkServicesResource.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_XML;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.internal.map.CaseInsensitiveMap;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceListSchema;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.dto.FrameworkDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkServicesResource extends BaseResource {
+
+ public FrameworkServicesResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.8.1
+ @GET
+ @Produces({APPLICATION_SERVICES_JSON, APPLICATION_SERVICES_XML})
+ @Path("framework/services{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/services",
+ summary = "Retrieves a Service List Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The request has been served successfully",
+ content = @Content(schema = @Schema(implementation = ServiceListSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "The provided filter expression was not valid"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response services(
+ @Parameter(
+ name = "filter",
+ in = ParameterIn.QUERY,
+ description = "A filter parameter whose value is a filter expression that follows the Core Specifications Framework Filter Syntax; see OSGi Core, Chapter 3.2.7 Filter Syntax. The filter is matched against the service attributes and only services that match are returned",
+ examples = @ExampleObject(
+ summary = "format: filter=<filter_string>",
+ value = "filter=(&(osgi.vendor=Apache Aries)(objectClass=com.acme.Widget))"
+ )
+ )
+ @QueryParam("filter") String filter,
+ @Parameter(allowEmptyValue = true, description = "File extension", schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ Predicate<ServiceReferenceDTO> predicate = fromFilterQuery(filter);
+
+ ResponseBuilder builder = Response.ok(
+ ServiceListSchema.build(
+ framework.adapt(FrameworkDTO.class).services.stream().map(
+ sr -> {
+ sr.properties = new CaseInsensitiveMap<Object>(sr.properties);
+ return sr;
+ }
+ ).filter(
+ predicate
+ ).map(
+ sr -> String.valueOf(sr.id)
+ ).map(
+ id -> uriInfo.getBaseUriBuilder().path("framework").path("service").path(id)
+ ).map(
+ UriBuilder::build
+ ).map(
+ URI::toASCIIString
+ )
+ .collect(toList())
+ )
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_SERVICES_JSON : APPLICATION_SERVICES_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStartLevelResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStartLevelResource.java
new file mode 100644
index 0000000..ac25e05
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStartLevelResource.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_FRAMEWORKSTARTLEVEL_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_FRAMEWORKSTARTLEVEL_XML;
+
+import java.util.Optional;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.FrameworkStartLevelSchema;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkStartLevelResource extends BaseResource {
+
+ public FrameworkStartLevelResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ // 137.3.1.1
+ @GET
+ @Produces({APPLICATION_FRAMEWORKSTARTLEVEL_JSON, APPLICATION_FRAMEWORKSTARTLEVEL_XML})
+ @Path("framework/startlevel{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "GET/startlevel",
+ summary = "Retrieves a Framework Startlevel Representation from the REST management service",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The framework start level",
+ content = @Content(schema = @Schema(implementation = FrameworkStartLevelSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response startlevel(
+ @Parameter(allowEmptyValue = true, schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ ResponseBuilder builder = Response.status(
+ Response.Status.OK
+ ).entity(
+ FrameworkStartLevelSchema.build(framework.adapt(FrameworkStartLevelDTO.class))
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ t -> ".json".equals(t) ? APPLICATION_FRAMEWORKSTARTLEVEL_JSON : APPLICATION_FRAMEWORKSTARTLEVEL_XML
+ ).map(t -> builder.type(t)).orElse(
+ builder
+ ).build();
+ }
+
+ // 137.3.1.2
+ @PUT
+ @Consumes({APPLICATION_FRAMEWORKSTARTLEVEL_JSON, APPLICATION_FRAMEWORKSTARTLEVEL_XML})
+ @Path("framework/startlevel{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ operationId = "PUT/startlevel",
+ summary = "Set the target framework startlevel",
+ responses = {
+ @ApiResponse(
+ responseCode = "204",
+ description = "The request was received and valid. The framework will asynchronously start to adjust the framework startlevel until the target startlevel has been reached"
+ ),
+ @ApiResponse(
+ responseCode = "400",
+ description = "The REST management service received an IllegalArgumentException when trying to adjust the framework startlevel"
+ ),
+ @ApiResponse(
+ responseCode = "415",
+ description = "The request had a media type that is not supported by the REST management service"
+ )
+ }
+ )
+ public Response startlevel(
+ FrameworkStartLevelSchema update,
+ @Parameter(allowEmptyValue = true, schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ try {
+ FrameworkStartLevel current = framework.adapt(FrameworkStartLevel.class);
+
+ if (current.getStartLevel() != update.startLevel) {
+ current.setStartLevel(update.startLevel);
+ }
+ if (current.getInitialBundleStartLevel() != update.initialBundleStartLevel) {
+ current.setInitialBundleStartLevel(update.initialBundleStartLevel);
+ }
+
+ return Response.noContent().build();
+ }
+ catch (IllegalArgumentException exception) {
+ throw new WebApplicationException(exception, 400);
+ }
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStateResource.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStateResource.java
new file mode 100644
index 0000000..e832012
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/FrameworkStateResource.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal;
+
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_BUNDLESTATE_XML;
+
+import java.util.Optional;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.osgi.framework.BundleContext;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class FrameworkStateResource extends BaseResource {
+
+ public FrameworkStateResource(BundleContext bundleContext) {
+ super(bundleContext);
+ }
+
+ @GET
+ @Produces({APPLICATION_BUNDLESTATE_JSON, APPLICATION_BUNDLESTATE_XML})
+ @Path("framework/state{ext:(\\.json|\\.xml)*}")
+ @Operation(
+ summary = "Get the framework state by extension type",
+ responses = {
+ @ApiResponse(
+ responseCode = "200",
+ description = "The framework state",
+ content = @Content(schema = @Schema(implementation = BundleStateSchema.class))
+ ),
+ @ApiResponse(
+ responseCode = "404",
+ description = "Framework not found"
+ ),
+ @ApiResponse(
+ responseCode = "406",
+ description = "The REST management service does not support any of the requested representations"
+ )
+ }
+ )
+ public Response state(
+ @Parameter(allowEmptyValue = true, schema = @Schema(allowableValues = {".json", ".xml"}))
+ @PathParam("ext") String ext) {
+
+ ResponseBuilder builder = Response.status(
+ Response.Status.OK
+ ).entity(
+ bundleStateSchema(framework)
+ );
+
+ return Optional.ofNullable(
+ ext
+ ).map(
+ String::trim
+ ).map(
+ e -> ".json".equals(e) ? APPLICATION_BUNDLESTATE_JSON : APPLICATION_BUNDLESTATE_XML
+ ).map(
+ type -> builder.type(type)
+ ).orElse(
+ builder
+ ).build();
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientImpl.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientImpl.java
deleted file mode 100644
index d243dd5..0000000
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientImpl.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.aries.jax.rs.rest.management.internal;
-
-import static javax.ws.rs.core.MediaType.*;
-import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.*;
-
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.StatusType;
-
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
-import org.apache.aries.jax.rs.rest.management.model.BundleStateDTO;
-import org.apache.aries.jax.rs.rest.management.model.BundlesDTO;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.dto.BundleDTO;
-import org.osgi.framework.dto.ServiceReferenceDTO;
-import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
-import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
-import org.osgi.service.rest.client.RestClient;
-
-public class RestClientImpl implements RestClient {
-
- private static final GenericType<List<BundleDTO>> BUNDLE_LIST =
- new GenericType<List<BundleDTO>>() {};
-
- private final WebTarget webTarget;
-
- public RestClientImpl(WebTarget webTarget) {
- this.webTarget = webTarget;
-
- this.webTarget.register(RestManagementMessageBodyHandler.class);
- }
-
- @Override
- public FrameworkStartLevelDTO getFrameworkStartLevel() throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "startlevel"
- ).request().get()
- )) {
- return response.readEntity(FrameworkStartLevelDTO.class);
- }
- }
-
- @Override
- public void setFrameworkStartLevel(FrameworkStartLevelDTO startLevel) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "startlevel"
- ).request().put(
- Entity.entity(
- startLevel, APPLICATION_FRAMEWORKSTARTLEVEL_JSON)
- )
- )) {}
- }
-
- @Override
- public Collection<String> getBundlePaths() throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundles"
- ).request().get()
- )) {
- return response.readEntity(BundlesDTO.class).bundles;
- }
- }
-
- @Override
- public Collection<BundleDTO> getBundles() throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundles"
- ).path(
- "representations"
- ).request().get()
- )) {
- return response.readEntity(BUNDLE_LIST);
- }
- }
-
- @Override
- public BundleDTO getBundle(long id) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).resolveTemplate(
- "bundleid", id
- ).request().get()
- )) {
- return response.readEntity(BundleDTO.class);
- }
- }
-
- @Override
- public BundleDTO getBundle(String bundlePath) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).request().get()
- )) {
- return response.readEntity(BundleDTO.class);
- }
- }
-
- @Override
- public int getBundleState(long id) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).path(
- "state"
- ).resolveTemplate(
- "bundleid", id
- ).request().get()
- )) {
- return response.readEntity(BundleStateDTO.class).state;
- }
- }
-
- @Override
- public int getBundleState(String bundlePath) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).path(
- "state"
- ).request().get()
- )) {
- return response.readEntity(BundleStateDTO.class).state;
- }
- }
-
- @Override
- public void startBundle(long id) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
-
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).path(
- "state"
- ).resolveTemplate(
- "bundleid", id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void startBundle(String bundlePath) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
-
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).path(
- "state"
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void startBundle(long id, int options) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
- bundleStateDTO.options = options;
-
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).path(
- "state"
- ).resolveTemplate(
- "bundleid", id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void startBundle(String bundlePath, int options) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.ACTIVE;
- bundleStateDTO.options = options;
-
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).path(
- "state"
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void stopBundle(long id) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
-
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).path(
- "state"
- ).resolveTemplate(
- "bundleid", id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void stopBundle(String bundlePath) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
-
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).path(
- "state"
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void stopBundle(long id, int options) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
- bundleStateDTO.options = options;
-
- try (Response response = maybeThrow(
- webTarget.path(
- "framework"
- ).path(
- "bundle"
- ).path(
- "{bundleid}"
- ).path(
- "state"
- ).resolveTemplate(
- "bundleid", id
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public void stopBundle(String bundlePath, int options) throws Exception {
- BundleStateDTO bundleStateDTO = new BundleStateDTO();
- bundleStateDTO.state = Bundle.RESOLVED;
- bundleStateDTO.options = options;
-
- try (Response response = maybeThrow(
- webTarget.path(
- bundlePath
- ).path(
- "state"
- ).request().put(
- Entity.entity(
- bundleStateDTO,
- APPLICATION_BUNDLESTATE_JSON_TYPE
- )
- )
- )) {
- }
- }
-
- @Override
- public Map<String, String> getBundleHeaders(long id) throws Exception {
-// try (Response response = maybeThrow(
-// webTarget.path(
-// "framework"
-// ).path(
-// "bundle"
-// ).path(
-// "{bundleid}"
-// ).path(
-// "header"
-// ).resolveTemplate(
-// "bundleid", id
-// ).request().get()
-// )) {
-// }
- // TODO
- return null;
- }
-
- @Override
- public Map<String, String> getBundleHeaders(String bundlePath) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleStartLevelDTO getBundleStartLevel(long id) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleStartLevelDTO getBundleStartLevel(String bundlePath) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setBundleStartLevel(long id, int startLevel) throws Exception {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setBundleStartLevel(String bundlePath, int startLevel) throws Exception {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public BundleDTO installBundle(String location) throws Exception {
- try (Response response = maybeThrow(
- webTarget.path(
- "framework/bundles"
- ).request(APPLICATION_BUNDLE_JSON).post(
- Entity.entity(location, TEXT_PLAIN)
- )
- )) {
- return response.readEntity(
- BundleDTO.class
- );
- }
- }
-
- @Override
- public BundleDTO installBundle(String location, InputStream in) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleDTO uninstallBundle(long id) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleDTO uninstallBundle(String bundlePath) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleDTO updateBundle(long id) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleDTO updateBundle(long id, String url) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public BundleDTO updateBundle(long id, InputStream in) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection<String> getServicePaths() throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection<String> getServicePaths(String filter) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection<ServiceReferenceDTO> getServiceReferences() throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection<ServiceReferenceDTO> getServiceReferences(String filter) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ServiceReferenceDTO getServiceReference(long id) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ServiceReferenceDTO getServiceReference(String servicePath) throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
-
- private Response maybeThrow(Response response) throws Exception {
- StatusType statusInfo = response.getStatusInfo();
-
- if (statusInfo.getStatusCode() >= 300) {
- throw new Exception(statusInfo.getReasonPhrase());
- }
-
- return response;
- }
-
-}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementActivator.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementActivator.java
index 0b7cccc..e742c83 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementActivator.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementActivator.java
@@ -22,22 +22,20 @@ import static org.apache.aries.component.dsl.OSGi.ignore;
import static org.apache.aries.component.dsl.OSGi.register;
import static org.apache.aries.component.dsl.OSGi.service;
import static org.apache.aries.component.dsl.OSGi.serviceReferences;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.SPECIFICATION_VERSION;
import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_APPLICATION_SELECT;
import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_EXTENSION;
-import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_EXTENSION_SELECT;
import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_NAME;
-import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_RESOURCE;
import java.util.HashMap;
import java.util.function.BiFunction;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Application;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
import org.apache.aries.component.dsl.OSGiResult;
-import org.apache.aries.jax.rs.rest.management.handler.RestManagementMessageBodyHandler;
+import org.apache.aries.jax.rs.rest.management.feature.RestManagementFeature;
+import org.apache.aries.jax.rs.rest.management.internal.client.RestClientFactoryImpl;
import org.osgi.annotation.bundle.Header;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
@@ -48,9 +46,11 @@ import org.osgi.framework.ServiceRegistration;
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
import org.osgi.service.rest.client.RestClientFactory;
+import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
@Header(name = Constants.BUNDLE_ACTIVATOR, value = "${@class}")
public class RestManagementActivator implements BundleActivator {
@@ -65,7 +65,7 @@ public class RestManagementActivator implements BundleActivator {
ignore(
register(
Application.class,
- () -> new RestManagementApplication(),
+ () -> new RestManagementApplication(bundleContext),
() -> {
HashMap<String, Object> map = new HashMap<>();
@@ -90,17 +90,14 @@ public class RestManagementActivator implements BundleActivator {
),
ignore(
register(
- new String[] {
- MessageBodyReader.class.getName(),
- MessageBodyWriter.class.getName()
- },
- () -> new PrototypeWrapper<>(
- (b, r) -> new RestManagementMessageBodyHandler()
+ javax.ws.rs.core.Feature.class,
+ new PrototypeWrapper<>(
+ (b, r) -> new RestManagementFeature()
),
() -> {
HashMap<String, Object> map = new HashMap<>();
- map.put(JAX_RS_NAME, RestManagementMessageBodyHandler.class.getSimpleName());
+ map.put(JAX_RS_NAME, RestManagementFeature.class.getSimpleName());
map.put(
JAX_RS_APPLICATION_SELECT,
String.format(
@@ -114,40 +111,34 @@ public class RestManagementActivator implements BundleActivator {
),
ignore(
register(
- FrameworkResource.class,
- () -> new FrameworkResource(bundleContext),
- () -> {
- HashMap<String, Object> map = new HashMap<>();
-
- map.put(
- JAX_RS_APPLICATION_SELECT,
- String.format(
- "(%s=%s)", JAX_RS_NAME,
- RestManagementApplication.class.getSimpleName()));
- map.put(JAX_RS_RESOURCE, true);
- map.put(JAX_RS_EXTENSION_SELECT, new String[] {
- String.format(
- "(%s=%s)", JAX_RS_NAME,
- RestManagementMessageBodyHandler.class.getSimpleName())
- });
-
- return map;
- }
- )
- ),
- ignore(
- register(
OpenAPI.class,
() -> {
OpenAPI openAPI = new OpenAPI();
openAPI.info(
- new Info()
- .title("Apache Aries OSGi Rest Management Service")
- .description("Apache Aries OSGi Rest Management Service REST API")
- .contact(
- new Contact()
- .email("dev@aries.apache.org"))
+ new Info().title(
+ "Apache Aries OSGi Rest Management Service"
+ ).description(
+ "A REST API to manage an OSGi Framework"
+ ).license(
+ new License().name(
+ "Apache 2.0"
+ ).url(
+ "https://www.apache.org/licenses/LICENSE-2.0.html"
+ )
+ ).version(
+ SPECIFICATION_VERSION
+ ).contact(
+ new Contact().email(
+ "dev@aries.apache.org"
+ )
+ )
+ ).externalDocs(
+ new ExternalDocumentation().description(
+ "OSGi Compendium Chapter 137 - REST Management Service Specification"
+ ).url(
+ "https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.rest.html"
+ )
);
return openAPI;
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementApplication.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementApplication.java
index 7899130..d7d5ab3 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementApplication.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestManagementApplication.java
@@ -17,7 +17,41 @@
package org.apache.aries.jax.rs.rest.management.internal;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.ws.rs.core.Application;
+import org.apache.aries.jax.rs.rest.management.internal.jaxb.ServiceSchemaContextResolver;
+import org.osgi.framework.BundleContext;
+
public class RestManagementApplication extends Application {
+
+ private final BundleContext bundleContext;
+
+ public RestManagementApplication(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public Set<Object> getSingletons() {
+ Set<Object> singletons = new HashSet<>();
+
+ singletons.add(new ServiceSchemaContextResolver());
+
+ singletons.add(new FrameworkBundleHeaderResource(bundleContext));
+ singletons.add(new FrameworkBundleResource(bundleContext));
+ singletons.add(new FrameworkBundlesRepresentationsResource(bundleContext));
+ singletons.add(new FrameworkBundlesResource(bundleContext));
+ singletons.add(new FrameworkBundleStartLevelResource(bundleContext));
+ singletons.add(new FrameworkBundleStateResource(bundleContext));
+ singletons.add(new FrameworkResource(bundleContext));
+ singletons.add(new FrameworkServiceResource(bundleContext));
+ singletons.add(new FrameworkServicesRepresentationsResource(bundleContext));
+ singletons.add(new FrameworkServicesResource(bundleContext));
+ singletons.add(new FrameworkStartLevelResource(bundleContext));
+ singletons.add(new FrameworkStateResource(bundleContext));
+ return singletons;
+ }
+
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientFactoryImpl.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientFactoryImpl.java
similarity index 95%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientFactoryImpl.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientFactoryImpl.java
index 9ef5bd4..6dee095 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/RestClientFactoryImpl.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientFactoryImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.internal;
+package org.apache.aries.jax.rs.rest.management.internal.client;
import java.net.URI;
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientImpl.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientImpl.java
new file mode 100644
index 0000000..e69cfb3
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/client/RestClientImpl.java
@@ -0,0 +1,786 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal.client;
+
+import static java.util.stream.Collectors.toList;
+import static javax.ws.rs.core.HttpHeaders.CONTENT_LOCATION;
+import static javax.ws.rs.core.MediaType.*;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.*;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.StatusType;
+
+import org.apache.aries.jax.rs.rest.management.feature.RestManagementFeature;
+import org.apache.aries.jax.rs.rest.management.schema.BundleExceptionSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleHeaderSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleStateSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleListSchema;
+import org.apache.aries.jax.rs.rest.management.schema.BundleSchemaListSchema;
+import org.apache.aries.jax.rs.rest.management.schema.FrameworkStartLevelSchema;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchemaListSchema;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceListSchema;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+import org.osgi.service.rest.client.RestClient;
+
+public class RestClientImpl implements RestClient {
+
+ private final WebTarget webTarget;
+
+ public RestClientImpl(WebTarget webTarget) {
+ this.webTarget = webTarget;
+
+ this.webTarget.register(RestManagementFeature.class);
+ }
+
+ @Override
+ public FrameworkStartLevelDTO getFrameworkStartLevel() throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "startlevel"
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(FrameworkStartLevelSchema.class);
+ }
+ }
+
+ @Override
+ public void setFrameworkStartLevel(FrameworkStartLevelDTO startLevel) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "startlevel"
+ ).request(
+ ).put(
+ Entity.entity(
+ FrameworkStartLevelSchema.build(startLevel), APPLICATION_FRAMEWORKSTARTLEVEL_JSON
+ )
+ )
+ )) {}
+ }
+
+ @Override
+ public Collection<String> getBundlePaths() throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundles"
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleListSchema.class).bundles;
+ }
+ }
+
+ @Override
+ public Collection<BundleDTO> getBundles() throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundles"
+ ).path(
+ "representations"
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(
+ BundleSchemaListSchema.class
+ ).bundles.stream().map(
+ BundleDTO.class::cast
+ ).collect(toList());
+ }
+ }
+
+ @Override
+ public BundleDTO getBundle(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleSchema.class);
+ }
+ }
+
+ @Override
+ public BundleDTO getBundle(String bundlePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleSchema.class);
+ }
+ }
+
+ @Override
+ public int getBundleState(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "state"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleStateSchema.class).state;
+ }
+ }
+
+ @Override
+ public int getBundleState(String bundlePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "state"
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleStateSchema.class).state;
+ }
+ }
+
+ @Override
+ public void startBundle(long id) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "state"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void startBundle(String bundlePath) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "state"
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void startBundle(long id, int options) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+ bundleStateDTO.options = options;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "state"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void startBundle(String bundlePath, int options) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.ACTIVE;
+ bundleStateDTO.options = options;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "state"
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void stopBundle(long id) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "state"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void stopBundle(String bundlePath) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "state"
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void stopBundle(long id, int options) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+ bundleStateDTO.options = options;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "state"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void stopBundle(String bundlePath, int options) throws Exception {
+ BundleStateSchema bundleStateDTO = new BundleStateSchema();
+ bundleStateDTO.state = Bundle.RESOLVED;
+ bundleStateDTO.options = options;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "state"
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStateDTO,
+ APPLICATION_BUNDLESTATE_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public Map<String, String> getBundleHeaders(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "header"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleHeaderSchema.class);
+ }
+ }
+
+ @Override
+ public Map<String, String> getBundleHeaders(String bundlePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleHeaderSchema.class);
+ }
+ }
+
+ @Override
+ public BundleStartLevelDTO getBundleStartLevel(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "startlevel"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleStartLevelDTO.class);
+ }
+ }
+
+ @Override
+ public BundleStartLevelDTO getBundleStartLevel(String bundlePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "startlevel"
+ ).request(
+ ).get()
+ )) {
+ return response.readEntity(BundleStartLevelDTO.class);
+ }
+ }
+
+ @Override
+ public void setBundleStartLevel(long id, int startLevel) throws Exception {
+ BundleStartLevelDTO bundleStartLevelDTO = new BundleStartLevelDTO();
+ bundleStartLevelDTO.startLevel = startLevel;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).path(
+ "startlevel"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStartLevelDTO,
+ APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public void setBundleStartLevel(String bundlePath, int startLevel) throws Exception {
+ BundleStartLevelDTO bundleStartLevelDTO = new BundleStartLevelDTO();
+ bundleStartLevelDTO.startLevel = startLevel;
+
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).path(
+ "startlevel"
+ ).request(
+ ).put(
+ Entity.entity(
+ bundleStartLevelDTO,
+ APPLICATION_BUNDLESTARTLEVEL_JSON_TYPE
+ )
+ )
+ )) {
+ }
+ }
+
+ @Override
+ public BundleDTO installBundle(String location) throws Exception {
+ try (Response response = maybeThrow(() -> {
+ Response r = webTarget.path(
+ "framework"
+ ).path(
+ "bundles"
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).post(
+ Entity.entity(location, TEXT_PLAIN)
+ );
+
+ StatusType statusInfo = r.getStatusInfo();
+ if (statusInfo.getStatusCode() == 400) {
+ BundleExceptionSchema bundleExceptionSchema = r.readEntity(BundleExceptionSchema.class);
+ throw new BundleException(bundleExceptionSchema.message, bundleExceptionSchema.typecode);
+ }
+
+ return r;
+ })) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO installBundle(String location, InputStream in) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundles"
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).header(
+ CONTENT_LOCATION, location
+ ).post(
+ Entity.entity(in, APPLICATION_OCTET_STREAM_TYPE)
+ )
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO uninstallBundle(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).delete()
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO uninstallBundle(String bundlePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ bundlePath
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).delete()
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO updateBundle(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).put(
+ Entity.entity("", TEXT_PLAIN_TYPE)
+ )
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO updateBundle(long id, String url) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).put(
+ Entity.entity(url, TEXT_PLAIN_TYPE)
+ )
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public BundleDTO updateBundle(long id, InputStream in) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "bundle"
+ ).path(
+ "{bundleid}"
+ ).resolveTemplate(
+ "bundleid", id
+ ).request(
+ APPLICATION_BUNDLE_JSON
+ ).put(
+ Entity.entity(in, APPLICATION_OCTET_STREAM_TYPE)
+ )
+ )) {
+ return response.readEntity(
+ BundleSchema.class
+ );
+ }
+ }
+
+ @Override
+ public Collection<String> getServicePaths() throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "services"
+ ).request(
+ APPLICATION_SERVICES_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceListSchema.class
+ ).services;
+ }
+ }
+
+ @Override
+ public Collection<String> getServicePaths(String filter) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "services"
+ ).queryParam(
+ "filter", filter
+ ).request(
+ APPLICATION_SERVICES_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceListSchema.class
+ ).services;
+ }
+ }
+
+ @Override
+ public Collection<ServiceReferenceDTO> getServiceReferences() throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "services"
+ ).path(
+ "representations"
+ ).request(
+ APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceSchemaListSchema.class
+ ).services.stream().map(
+ ServiceReferenceDTO.class::cast
+ ).collect(toList());
+ }
+ }
+
+ @Override
+ public Collection<ServiceReferenceDTO> getServiceReferences(String filter) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "services"
+ ).path(
+ "representations"
+ ).queryParam(
+ "filter", filter
+ ).request(
+ APPLICATION_SERVICES_REPRESENTATIONS_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceSchemaListSchema.class
+ ).services.stream().map(
+ ServiceReferenceDTO.class::cast
+ ).collect(toList());
+ }
+ }
+
+ @Override
+ public ServiceReferenceDTO getServiceReference(long id) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ "framework"
+ ).path(
+ "service"
+ ).path(
+ "{serviceid}"
+ ).resolveTemplate(
+ "serviceid", id
+ ).request(
+ APPLICATION_SERVICE_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceReferenceDTO.class
+ );
+ }
+ }
+
+ @Override
+ public ServiceReferenceDTO getServiceReference(String servicePath) throws Exception {
+ try (Response response = maybeThrow(
+ webTarget.path(
+ servicePath
+ ).request(
+ APPLICATION_SERVICE_JSON_TYPE
+ ).get()
+ )) {
+ return response.readEntity(
+ ServiceReferenceDTO.class
+ );
+ }
+ }
+
+ private Response maybeThrow(Response response) throws Exception {
+ return maybeThrow(() -> response);
+ }
+
+ private Response maybeThrow(Callable<Response> alternate) throws Exception {
+ Response response = alternate.call();
+
+ StatusType statusInfo = response.getStatusInfo();
+
+ if (statusInfo.getStatusCode() >= 300) {
+ throw new Exception(statusInfo.getReasonPhrase());
+ }
+
+ return response;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/Coerce.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/coerce/Coerce.java
similarity index 96%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/Coerce.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/coerce/Coerce.java
index 249a698..f7e6528 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/handler/Coerce.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/coerce/Coerce.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.handler;
+package org.apache.aries.jax.rs.rest.management.internal.coerce;
import java.util.ArrayList;
import java.util.Arrays;
@@ -49,7 +49,7 @@ public class Coerce {
return list;
}
- public static String type(Attribute typeAT, String name) {
+ public static String type(String type, String name) {
if (Constants.SERVICE_ID.equals(name) ||
Constants.SERVICE_BUNDLEID.equals(name)) {
return "Long";
@@ -63,10 +63,10 @@ public class Coerce {
return "String";
}
- if (typeAT == null) {
+ if (type == null) {
return "String";
}
- return typeAT.getValue();
+ return type;
}
public static String type(JsonNode node, String name) {
@@ -134,7 +134,7 @@ public class Coerce {
s -> s.trim().split("\\s*\\n\\s*")
).map(Arrays::asList).orElseGet(ArrayList::new);
- return from(type(typeAT, keyAT.getValue()), array, valueParts);
+ return from(type((typeAT == null ? null : typeAT.getValue()), keyAT.getValue()), array, valueParts);
}
public static Object from(
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/jaxb/ServiceSchemaContextResolver.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/jaxb/ServiceSchemaContextResolver.java
new file mode 100644
index 0000000..6a5cacd
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/jaxb/ServiceSchemaContextResolver.java
@@ -0,0 +1,55 @@
+package org.apache.aries.jax.rs.rest.management.internal.jaxb;
+
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICES_REPRESENTATIONS_XML;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_JSON;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.APPLICATION_SERVICE_XML;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchema;
+import org.apache.aries.jax.rs.rest.management.schema.ServiceSchemaListSchema;
+
+@Provider
+@Produces({
+ APPLICATION_SERVICE_JSON,
+ APPLICATION_SERVICE_XML,
+ APPLICATION_SERVICES_REPRESENTATIONS_JSON,
+ APPLICATION_SERVICES_REPRESENTATIONS_XML
+})
+public class ServiceSchemaContextResolver implements ContextResolver<JAXBContext> {
+
+ private JAXBContext ctx;
+
+ public ServiceSchemaContextResolver() {
+ try {
+ this.ctx = JAXBContext.newInstance(
+ ArrayList.class,
+ AtomicLong.class,
+ Response.class,
+ ServiceSchema.class,
+ ServiceSchemaListSchema.class,
+ String[].class
+ );
+ }
+ catch (JAXBException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public JAXBContext getContext(Class<?> type) {
+ return (
+ type.equals(ServiceSchema.class) ||
+ type.equals(ServiceSchemaListSchema.class)? ctx : null
+ );
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/map/CaseInsensitiveMap.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/map/CaseInsensitiveMap.java
new file mode 100644
index 0000000..691b9d6
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/map/CaseInsensitiveMap.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.internal.map;
+
+import static java.util.stream.Collectors.toCollection;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * This Map is used for case-insensitive key lookup during filter
+ * evaluation. This Map implementation only supports the get operation using
+ * a String key as no other operations are used by the Filter
+ * implementation.
+ */
+public class CaseInsensitiveMap<T> extends AbstractMap<String, T> {
+ private final String[] keys;
+ private final Set<Map.Entry<String, T>> properties;
+
+ /**
+ * Create a case insensitive map from the specified dictionary.
+ *
+ * @param dictionary
+ * @throws IllegalArgumentException If {@code dictionary} contains case
+ * variants of the same key name.
+ */
+ @SuppressWarnings("serial")
+ public CaseInsensitiveMap(final Dictionary<String, T> dictionary) {
+ this(() -> {
+ Set<Map.Entry<String, T>> entries = new HashSet<>(dictionary.size());
+ for (Enumeration<String> e = dictionary.keys(); e.hasMoreElements();) {
+ final String k = e.nextElement();
+ entries.add(
+ new SimpleImmutableEntry<String, T>(k, null) {
+ public T getValue() {
+ return dictionary.get(getKey());
+ }
+ }
+ );
+ }
+ return entries;
+ });
+ }
+
+ /**
+ * Create a case insensitive map from the specified map.
+ *
+ * @param properties
+ * @throws IllegalArgumentException If {@code dictionary} contains case
+ * variants of the same key name.
+ */
+ public CaseInsensitiveMap(final Map<String, T> properties) {
+ this(() -> properties.entrySet());
+ }
+
+ CaseInsensitiveMap(final Supplier<Set<Map.Entry<String, T>>> properties) {
+ this.properties = properties.get().stream().sorted(
+ (a, b) -> a.getKey().compareTo(b.getKey())
+ ).collect(
+ toCollection(LinkedHashSet::new)
+ );
+
+ List<String> keyList = new ArrayList<>(this.properties.size());
+
+ this.properties.forEach(e -> {
+ for (String i : keyList) {
+ if (e.getKey().equalsIgnoreCase(i)) {
+ throw new IllegalArgumentException();
+ }
+ }
+ keyList.add(e.getKey());
+ });
+
+ this.keys = keyList.toArray(new String[0]);
+ }
+
+ @Override
+ public T get(Object o) {
+ String k = (String) o;
+ for (String key : keys) {
+ if (key.equalsIgnoreCase(k)) {
+ return super.get(key);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Set<Entry<String, T>> entrySet() {
+ return this.properties;
+ }
+
+}
\ No newline at end of file
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/package-info.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/package-info.java
index 6100eb1..90379a3 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/package-info.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/internal/package-info.java
@@ -19,10 +19,8 @@
namespace = IMPLEMENTATION_NAMESPACE,
name = "org.apache.aries.jax.rs.openapi"
)
-@Version("1.0.0")
package org.apache.aries.jax.rs.rest.management.internal;
import static org.osgi.namespace.implementation.ImplementationNamespace.IMPLEMENTATION_NAMESPACE;
import org.osgi.annotation.bundle.Requirement;
-import org.osgi.annotation.versioning.Version;
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/package-info.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/package-info.java
index 5621024..008d751 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/package-info.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/package-info.java
@@ -17,7 +17,24 @@
@Export
@Version("1.0.0")
+@Capability(
+ name = SPECIFICATION_IMPLEMENTATION,
+ namespace = IMPLEMENTATION_NAMESPACE,
+ version = SPECIFICATION_VERSION,
+ uses = org.osgi.service.rest.RestApiExtension.class
+)
+@org.osgi.annotation.bundle.Capability(
+ attribute = "objectClass:List<String>='org.osgi.service.rest.client.RestClientFactory'",
+ namespace = SERVICE_NAMESPACE,
+ uses = org.osgi.service.rest.client.RestClientFactory.class
+)
package org.apache.aries.jax.rs.rest.management;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.SPECIFICATION_IMPLEMENTATION;
+import static org.apache.aries.jax.rs.rest.management.RestManagementConstants.SPECIFICATION_VERSION;
+import static org.osgi.namespace.implementation.ImplementationNamespace.IMPLEMENTATION_NAMESPACE;
+import static org.osgi.namespace.service.ServiceNamespace.SERVICE_NAMESPACE;
+
+import org.osgi.annotation.bundle.Capability;
import org.osgi.annotation.bundle.Export;
import org.osgi.annotation.versioning.Version;
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServiceReferenceDTOs.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleExceptionSchema.java
similarity index 60%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServiceReferenceDTOs.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleExceptionSchema.java
index 7f553e4..a0e9260 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServiceReferenceDTOs.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleExceptionSchema.java
@@ -15,19 +15,22 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
-import java.util.List;
+import javax.xml.bind.annotation.XmlRootElement;
-import org.osgi.framework.dto.ServiceReferenceDTO;
+@XmlRootElement(name = "bundleexception")
+public class BundleExceptionSchema {
-public class ServiceReferenceDTOs {
- public List<ServiceReferenceDTO> services;
+ public int typecode;
- public static ServiceReferenceDTOs build(List<ServiceReferenceDTO> services) {
- ServiceReferenceDTOs serviceReferenceDTOs = new ServiceReferenceDTOs();
- serviceReferenceDTOs.services = services;
- return serviceReferenceDTOs;
+ public String message;
+
+ public static BundleExceptionSchema build(int typecode, String message) {
+ final BundleExceptionSchema bundleExceptionSchema = new BundleExceptionSchema();
+ bundleExceptionSchema.typecode = typecode;
+ bundleExceptionSchema.message = message;
+ return bundleExceptionSchema;
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderAdapter.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderAdapter.java
new file mode 100644
index 0000000..67cd005
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderAdapter.java
@@ -0,0 +1,45 @@
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class BundleHeaderAdapter extends XmlAdapter<BundleHeaderAdapter.BundleHeaderAdapted, BundleHeaderSchema> {
+
+ @XmlRootElement(name = "bundleHeader")
+ public static class BundleHeaderAdapted {
+ public List<Header> entry = new ArrayList<>();
+ }
+
+ public static class Header {
+ @XmlAttribute(name = "key", required = true)
+ public String key;
+ @XmlAttribute(name = "value", required = true)
+ public String value;
+ }
+
+ @Override
+ public BundleHeaderAdapted marshal(BundleHeaderSchema bundleHeaderSchema) throws Exception {
+ BundleHeaderAdapted adapter = new BundleHeaderAdapted();
+ bundleHeaderSchema.forEach((k, v) -> adapter.entry.add(build(k, v)));
+ return adapter;
+ }
+
+ @Override
+ public BundleHeaderSchema unmarshal(BundleHeaderAdapted adapter) throws Exception {
+ BundleHeaderSchema map = new BundleHeaderSchema();
+ adapter.entry.forEach(header -> map.put(header.key, header.value));
+ return map;
+ }
+
+ static Header build(String key, String value) {
+ final Header header = new Header();
+ header.key = key;
+ header.value = value;
+ return header;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderSchema.java
similarity index 60%
copy from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
copy to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderSchema.java
index 1bf866e..f01e249 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleHeaderSchema.java
@@ -15,20 +15,25 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
-import org.osgi.dto.DTO;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-public class ServicesDTO extends DTO {
+@SuppressWarnings("serial")
+@XmlRootElement(name = "bundleHeader")
+@XmlJavaTypeAdapter(BundleHeaderAdapter.class)
+public class BundleHeaderSchema extends LinkedHashMap<String, String> {
- public List<String> services;
+ public BundleHeaderSchema() {
+ super();
+ }
- public static ServicesDTO build(List<String> services) {
- ServicesDTO servicesDTO = new ServicesDTO();
- servicesDTO.services = services;
- return servicesDTO;
+ public BundleHeaderSchema(Map<String, String> map) {
+ super(map);
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleListSchema.java
similarity index 59%
copy from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java
copy to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleListSchema.java
index 25961e1..f3a90ff 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleListSchema.java
@@ -15,19 +15,28 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import static javax.xml.bind.annotation.XmlAccessType.FIELD;
import java.util.List;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
import org.osgi.dto.DTO;
-public class BundlesDTO extends DTO {
+@XmlRootElement(name = "bundles")
+@XmlAccessorType(FIELD)
+public class BundleListSchema extends DTO {
+ @XmlElement(name = "uri")
public List<String> bundles;
- public static BundlesDTO build(List<String> bundles) {
- BundlesDTO bundlesDTO = new BundlesDTO();
- bundlesDTO.bundles = bundles;
- return bundlesDTO;
+ public static BundleListSchema build(List<String> bundles) {
+ final BundleListSchema bundleListSchema = new BundleListSchema();
+ bundleListSchema.bundles = bundles;
+ return bundleListSchema;
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchema.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchema.java
new file mode 100644
index 0000000..2c26463
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchema.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.osgi.framework.dto.BundleDTO;
+
+@XmlRootElement(name = "bundle")
+public class BundleSchema extends BundleDTO {
+
+ public String location;
+
+ public static BundleSchema build(
+ long id, long lastModified, int state, String symbolicName, String version, String location) {
+ final BundleSchema bundleSchema = new BundleSchema();
+ bundleSchema.id = id;
+ bundleSchema.lastModified = lastModified;
+ bundleSchema.state = state;
+ bundleSchema.symbolicName = symbolicName;
+ bundleSchema.version = version;
+ bundleSchema.location = location;
+ return bundleSchema;
+ }
+
+ public static BundleSchema build(BundleDTO bundleDTO) {
+ final BundleSchema bundleSchema = new BundleSchema();
+ bundleSchema.id = bundleDTO.id;
+ bundleSchema.lastModified = bundleDTO.lastModified;
+ bundleSchema.state = bundleDTO.state;
+ bundleSchema.symbolicName = bundleDTO.symbolicName;
+ bundleSchema.version = bundleDTO.version;
+ return bundleSchema;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchemaListSchema.java
similarity index 61%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchemaListSchema.java
index 25961e1..ef7141b 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundlesDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleSchemaListSchema.java
@@ -15,19 +15,24 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
import org.osgi.dto.DTO;
-public class BundlesDTO extends DTO {
- public List<String> bundles;
+@XmlRootElement(name = "bundles")
+public class BundleSchemaListSchema extends DTO {
+ @XmlElement(name = "bundle")
+ public List<BundleSchema> bundles;
- public static BundlesDTO build(List<String> bundles) {
- BundlesDTO bundlesDTO = new BundlesDTO();
- bundlesDTO.bundles = bundles;
- return bundlesDTO;
+ public static BundleSchemaListSchema build(List<BundleSchema> bundles) {
+ final BundleSchemaListSchema bundlesSchema = new BundleSchemaListSchema();
+ bundlesSchema.bundles = bundles;
+ return bundlesSchema;
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStartLevelSchema.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStartLevelSchema.java
new file mode 100644
index 0000000..84b910e
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStartLevelSchema.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+
+@XmlRootElement(name = "bundleStartLevel")
+public class BundleStartLevelSchema extends BundleStartLevelDTO {
+
+ public static BundleStartLevelSchema build(boolean activationPolicyUsed, long bundle, boolean persistentlyStarted, int startLevel) {
+ final BundleStartLevelSchema bundleStartLevelSchema = new BundleStartLevelSchema();
+ bundleStartLevelSchema.activationPolicyUsed = activationPolicyUsed;
+ bundleStartLevelSchema.bundle = bundle;
+ bundleStartLevelSchema.persistentlyStarted = persistentlyStarted;
+ bundleStartLevelSchema.startLevel = startLevel;
+ return bundleStartLevelSchema;
+ }
+
+ public static BundleStartLevelSchema build(BundleStartLevelDTO bundleStartLevelDTO) {
+ final BundleStartLevelSchema bundleStartLevelSchema = new BundleStartLevelSchema();
+ bundleStartLevelSchema.activationPolicyUsed = bundleStartLevelDTO.activationPolicyUsed;
+ bundleStartLevelSchema.bundle = bundleStartLevelDTO.bundle;
+ bundleStartLevelSchema.persistentlyStarted = bundleStartLevelDTO.persistentlyStarted;
+ bundleStartLevelSchema.startLevel = bundleStartLevelDTO.startLevel;
+ return bundleStartLevelSchema;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundleStateDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStateSchema.java
similarity index 66%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundleStateDTO.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStateSchema.java
index 8ec7895..e32df17 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/BundleStateDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/BundleStateSchema.java
@@ -15,14 +15,24 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
import org.osgi.dto.DTO;
-public class BundleStateDTO extends DTO {
+@XmlRootElement(name = "bundleState")
+public class BundleStateSchema extends DTO {
public int state;
public int options;
+ public static BundleStateSchema build(int state, int options) {
+ final BundleStateSchema bundleState = new BundleStateSchema();
+ bundleState.state = state;
+ bundleState.options = options;
+ return bundleState;
+ }
+
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/FrameworkStartLevelSchema.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/FrameworkStartLevelSchema.java
new file mode 100644
index 0000000..b141d75
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/FrameworkStartLevelSchema.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+
+@XmlRootElement(name = "frameworkStartLevel")
+public class FrameworkStartLevelSchema extends FrameworkStartLevelDTO {
+
+ public static FrameworkStartLevelSchema build(int initialBundleStartLevel, int startLevel) {
+ final FrameworkStartLevelSchema frameworkStartLevelSchema = new FrameworkStartLevelSchema();
+ frameworkStartLevelSchema.initialBundleStartLevel = initialBundleStartLevel;
+ frameworkStartLevelSchema.startLevel = startLevel;
+ return frameworkStartLevelSchema;
+ }
+
+ public static FrameworkStartLevelSchema build(FrameworkStartLevelDTO frameworkStartLevelDTO) {
+ final FrameworkStartLevelSchema frameworkStartLevelSchema = new FrameworkStartLevelSchema();
+ frameworkStartLevelSchema.initialBundleStartLevel = frameworkStartLevelDTO.initialBundleStartLevel;
+ frameworkStartLevelSchema.startLevel = frameworkStartLevelDTO.startLevel;
+ return frameworkStartLevelSchema;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/PropertiesAdapter.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/PropertiesAdapter.java
new file mode 100644
index 0000000..08ed1a7
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/PropertiesAdapter.java
@@ -0,0 +1,149 @@
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import static java.util.stream.Collectors.joining;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlValue;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+import org.apache.aries.jax.rs.rest.management.internal.coerce.Coerce;
+
+public class PropertiesAdapter extends XmlAdapter<PropertiesAdapter.PropertiesAdapted, Map<String, Object>> {
+
+ public static class PropertiesAdapted {
+ public List<Property> property = new ArrayList<>();
+ }
+
+ public static class Property {
+ @XmlAttribute(name = "name", required = true)
+ public String key;
+ @XmlAttribute(name = "type")
+ public String type;
+ @XmlAttribute(name = "value")
+ public String attributeValue;
+ @XmlValue
+ public String elementValue;
+ }
+
+ @Override
+ public PropertiesAdapted marshal(Map<String, Object> map) throws Exception {
+ PropertiesAdapted adapter = new PropertiesAdapted();
+ for(Map.Entry<String, Object> entry : map.entrySet()) {
+ Property property = new Property();
+ property.key = entry.getKey();
+ Object v = entry.getValue();
+
+ boolean array = false;
+ if (Long.class.isInstance(v)) {
+ property.type = "Long";
+ }
+ else if (Long[].class.isInstance(v)) {
+ property.type = "Long";
+ array = true;
+ }
+ else if (Double.class.isInstance(v)) {
+ property.type = "Double";
+ }
+ else if (Double[].class.isInstance(v)) {
+ property.type = "Double";
+ array = true;
+ }
+ else if (Float.class.isInstance(v)) {
+ property.type = "Float";
+ }
+ else if (Float[].class.isInstance(v)) {
+ property.type = "Float";
+ array = true;
+ }
+ else if (Integer.class.isInstance(v)) {
+ property.type = "Integer";
+ }
+ else if (Integer[].class.isInstance(v)) {
+ property.type = "Integer";
+ array = true;
+ }
+ else if (Byte.class.isInstance(v)) {
+ property.type = "Byte";
+ }
+ else if (Byte[].class.isInstance(v)) {
+ property.type = "Byte";
+ array = true;
+ }
+ else if (Character.class.isInstance(v)) {
+ property.type = "Character";
+ }
+ else if (Character[].class.isInstance(v)) {
+ property.type = "Character";
+ array = true;
+ }
+ else if (Boolean.class.isInstance(v)) {
+ property.type = "Boolean";
+ }
+ else if (Boolean[].class.isInstance(v)) {
+ property.type = "Boolean";
+ array = true;
+ }
+ else if (Short.class.isInstance(v)) {
+ property.type = "Short";
+ }
+ else if (Short[].class.isInstance(v)) {
+ property.type = "Short";
+ array = true;
+ }
+ else if (String[].class.isInstance(v)) {
+ array = true;
+ }
+
+ if (!array) {
+ property.attributeValue = String.valueOf(v);
+ }
+ else {
+ property.elementValue = Arrays.stream(
+ (Object[])v
+ ).map(
+ String::valueOf
+ ).collect(
+ joining("\n")
+ );
+ }
+
+ adapter.property.add(property);
+ }
+ return adapter;
+ }
+
+ @Override
+ public Map<String, Object> unmarshal(PropertiesAdapted adapter) throws Exception {
+ Map<String, Object> map = new HashMap<>();
+ for(Property property : adapter.property) {
+ String valueTxt = property.attributeValue;
+ boolean array = false;
+ if (property.elementValue != null) {
+ valueTxt = property.elementValue;
+ array = true;
+ }
+ map.put(
+ property.key,
+ Coerce.from(
+ Coerce.type(property.type, property.key),
+ array,
+ Optional.ofNullable(
+ valueTxt
+ ).map(
+ s -> s.trim().split("\\s*\\n\\s*")
+ ).map(Arrays::asList).orElseGet(ArrayList::new)
+ )
+ );
+ }
+
+ return map;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceListSchema.java
similarity index 65%
copy from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
copy to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceListSchema.java
index 1bf866e..80d0a16 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceListSchema.java
@@ -15,20 +15,24 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
import java.util.List;
-import org.osgi.dto.DTO;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
-public class ServicesDTO extends DTO {
+import org.osgi.dto.DTO;
+@XmlRootElement(name = "services")
+public class ServiceListSchema extends DTO {
+ @XmlElement(name = "uri")
public List<String> services;
- public static ServicesDTO build(List<String> services) {
- ServicesDTO servicesDTO = new ServicesDTO();
- servicesDTO.services = services;
- return servicesDTO;
+ public static ServiceListSchema build(List<String> services) {
+ ServiceListSchema serviceListSchema = new ServiceListSchema();
+ serviceListSchema.services = services;
+ return serviceListSchema;
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchema.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchema.java
new file mode 100644
index 0000000..fe93b56
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchema.java
@@ -0,0 +1,40 @@
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import java.util.Map;
+
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+@XmlRootElement(name = "service")
+@XmlJavaTypeAdapter(ServiceSchemaAdapter.class)
+public class ServiceSchema extends ServiceReferenceDTO {
+
+ public String bundle;
+ public String[] usingBundles;
+
+ public static ServiceSchema build(
+ String bundle, long id, Map<String, Object> properties, String[] usingBundles) {
+ final ServiceSchema serviceSchema = new ServiceSchema();
+ serviceSchema.bundle = bundle;
+ serviceSchema.id = id;
+ serviceSchema.properties = properties;
+ serviceSchema.usingBundles = usingBundles;
+ return serviceSchema;
+ }
+
+ public static ServiceSchema build(UriInfo uriInfo, ServiceReferenceDTO serviceReferenceDTO) {
+ final ServiceSchema serviceSchema = new ServiceSchema();
+ serviceSchema.bundle = uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(serviceReferenceDTO.bundle).toASCIIString();
+ serviceSchema.id = serviceReferenceDTO.id;
+ serviceSchema.properties = serviceReferenceDTO.properties;
+ serviceSchema.usingBundles = new String[serviceReferenceDTO.usingBundles.length];
+ for (int i = 0; i < serviceReferenceDTO.usingBundles.length; i++) {
+ serviceSchema.usingBundles[i] = uriInfo.getBaseUriBuilder().path("framework").path("bundle").path("{id}").build(serviceReferenceDTO.usingBundles[i]).toASCIIString();
+ }
+ return serviceSchema;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaAdapter.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaAdapter.java
new file mode 100644
index 0000000..5f39bd9
--- /dev/null
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaAdapter.java
@@ -0,0 +1,40 @@
+package org.apache.aries.jax.rs.rest.management.schema;
+
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+public class ServiceSchemaAdapter extends XmlAdapter<ServiceSchemaAdapter.ServiceSchemaAdapted, ServiceSchema> {
+
+ @XmlRootElement(name = "service")
+ public static class ServiceSchemaAdapted {
+ public long id;
+ public String bundle;
+ @XmlJavaTypeAdapter(PropertiesAdapter.class)
+ public Map<String, Object> properties;
+ public String[] usingBundles;
+ }
+
+ @Override
+ public ServiceSchemaAdapted marshal(ServiceSchema serviceSchema) throws Exception {
+ ServiceSchemaAdapted adapter = new ServiceSchemaAdapted();
+ adapter.id = serviceSchema.id;
+ adapter.bundle = serviceSchema.bundle;
+ adapter.properties = serviceSchema.properties;
+ adapter.usingBundles = serviceSchema.usingBundles;
+ return adapter;
+ }
+
+ @Override
+ public ServiceSchema unmarshal(ServiceSchemaAdapted adapter) throws Exception {
+ ServiceSchema serviceSchema = new ServiceSchema();
+ serviceSchema.id = adapter.id;
+ serviceSchema.bundle = adapter.bundle;
+ serviceSchema.properties = adapter.properties;
+ serviceSchema.usingBundles = adapter.usingBundles;
+ return serviceSchema;
+ }
+
+}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaListSchema.java
similarity index 59%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaListSchema.java
index 1bf866e..b617b1f 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/ServicesDTO.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/ServiceSchemaListSchema.java
@@ -15,20 +15,24 @@
* limitations under the License.
*/
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
import java.util.List;
-import org.osgi.dto.DTO;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
-public class ServicesDTO extends DTO {
+import org.osgi.dto.DTO;
- public List<String> services;
+@XmlRootElement(name = "services")
+public class ServiceSchemaListSchema extends DTO {
+ @XmlElement(name = "service")
+ public List<ServiceSchema> services;
- public static ServicesDTO build(List<String> services) {
- ServicesDTO servicesDTO = new ServicesDTO();
- servicesDTO.services = services;
- return servicesDTO;
+ public static ServiceSchemaListSchema build(List<ServiceSchema> services) {
+ final ServiceSchemaListSchema serviceSchemaListSchema = new ServiceSchemaListSchema();
+ serviceSchemaListSchema.services = services;
+ return serviceSchemaListSchema;
}
}
diff --git a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/package-info.java b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/package-info.java
similarity index 94%
rename from integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/package-info.java
rename to integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/package-info.java
index 4b23f73..9360930 100644
--- a/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/model/package-info.java
+++ b/integrations/rest-management/rest-management/src/main/java/org/apache/aries/jax/rs/rest/management/schema/package-info.java
@@ -17,7 +17,7 @@
@Export
@Version("1.0.0")
-package org.apache.aries.jax.rs.rest.management.model;
+package org.apache.aries.jax.rs.rest.management.schema;
import org.osgi.annotation.bundle.Export;
import org.osgi.annotation.versioning.Version;
diff --git a/jax-rs.itests/itest.bndrun b/jax-rs.itests/itest.bndrun
index b73a8bc..0050270 100644
--- a/jax-rs.itests/itest.bndrun
+++ b/jax-rs.itests/itest.bndrun
@@ -48,7 +48,7 @@
org.apache.aries.spifly.auto.providers=com.sun.*
-runbundles: \
- assertj-core;version='[3.17.2,3.17.3)',\
+ assertj-core;version='[3.19.0,3.19.1)',\
com.fasterxml.woodstox.woodstox-core;version='[6.2.3,6.2.4)',\
com.sun.xml.bind.jaxb-osgi;version='[2.3.3,2.3.4)',\
jakarta.xml.bind-api;version='[2.3.3,2.3.4)',\
diff --git a/pom.xml b/pom.xml
index 303f36e..896bc1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,8 @@
<openapi.version>2.1.7</openapi.version>
<shiro.version>1.7.1</shiro.version>
<slf4j.version>1.7.30</slf4j.version>
+ <junit.jupiter.version>5.6.0</junit.jupiter.version>
+ <junit.platform.version>1.6.0</junit.platform.version>
</properties>
<scm>
@@ -286,6 +288,33 @@
<version>2.2</version>
</dependency>
<dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
... 39 lines suppressed ...