Revert "openHAB JAX-RS publisher (#905)"

This reverts commit ad81f040de.
This commit is contained in:
Kai Kreuzer 2019-07-16 18:49:53 +02:00
parent b3aabd73ab
commit b6aae6907f
36 changed files with 17 additions and 1737 deletions

View File

@ -91,8 +91,8 @@
<!-- EclipseSource JAX RS -->
<dependency>
<groupId>com.eclipsesource.jaxrs</groupId>
<artifactId>jersey-all</artifactId>
<version>2.22.2</version>
<artifactId>publisher</artifactId>
<version>5.3.1</version>
<scope>compile</scope>
</dependency>

View File

@ -233,7 +233,7 @@
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.publisher</artifactId>
<artifactId>org.openhab.core.io.rest.optimize</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>

View File

@ -852,11 +852,11 @@
<scope>compile</scope>
</dependency>
<!-- EclipseSource JAX RS -->
<!-- ... -->
<dependency>
<groupId>com.eclipsesource.jaxrs</groupId>
<artifactId>jersey-all</artifactId>
<version>2.22.2</version>
<artifactId>publisher</artifactId>
<version>5.3.1</version>
<scope>compile</scope>
</dependency>

View File

@ -13,12 +13,4 @@
<name>openHAB Core :: Bundles :: Authentication Support for the REST Interface</name>
<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.publisher</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -15,12 +15,13 @@ package org.eclipse.smarthome.io.rest.auth.internal;
import java.util.Dictionary;
import java.util.Hashtable;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ServletConfiguration;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import com.eclipsesource.jaxrs.publisher.ServletConfiguration;
/**
* Custom servlet configuration for jaxrs handler.
*

View File

@ -13,7 +13,6 @@
package org.eclipse.smarthome.io.rest.core.internal;
import org.eclipse.smarthome.io.rest.JSONResponse;
import org.eclipse.smarthome.io.rest.OhJAXRSResource;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
@ -36,7 +35,7 @@ public class RESTCoreActivator implements BundleActivator {
@Override
public void start(BundleContext bc) throws Exception {
context = bc;
mExcMapper = bc.registerService(OhJAXRSResource.class, new JSONResponse.ExceptionMapper(), null);
mExcMapper = bc.registerService(JSONResponse.ExceptionMapper.class.getName(), new JSONResponse.ExceptionMapper(), null);
}
/**

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src/3rdparty/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.io.rest.publisher</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -1,14 +0,0 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-core

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.reactor.bundles</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.io.rest.publisher</artifactId>
<name>openHAB Core :: Bundles :: REST Interface :: Publisher</name>
<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.sse</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openhab.tools.sat</groupId>
<artifactId>sat-plugin</artifactId>
<executions>
<execution>
<id>sat-all</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>add-source</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<sources>
<source>src/3rdparty/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation, ongoing development
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher;
import java.util.Map;
import javax.ws.rs.core.Application;
/**
* <p>
* Service that allows configuration of the JAX-RS {@link Application}. Multiple registrations will be tracked.
* </p>
*
* @since 4.3
*/
public interface ApplicationConfiguration {
/**
* <p>
* Will be called before the JAX-RS {@link Application} is registered. Please note that
* one {@link ApplicationConfiguration} can overwrite the values of other {@link ApplicationConfiguration}s. It
* depends on the order they are available in the OSGi container.
* </p>
*
* @see Application#getProperties()
*/
Map<String, Object> getProperties();
}

View File

@ -1,45 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher;
import org.osgi.framework.Filter;
import org.osgi.util.tracker.ServiceTracker;
/**
* <p>
* The JAX-RS publisher uses a {@link ServiceTracker} to track all services. If one has an @Path, @Provider etc.
* annotation it will be published. In rare cases it's necessary to modify the filter for the tracker e.g. to only
* publish resource starting with "com.foo.*".
* </p>
* <p>
* To accomplish this you can register a {@link ResourceFilter} as an OSGi service. The JAX-RS publisher will prefer
* use this service to construct it's {@link ServiceTracker}.
* </p>
*
* <p>
* <b>Please Note:</b> Right now the {@link ResourceFilter} service must be registered before the publisher bundle
* is started. Dynamic behavior may follow in future versions.
* </p>
*
* @see Filter
*
* @since 4.0
*/
public interface ResourceFilter {
/**
* <p>
* The OSGi filter to use for tracking the Resources. Must not return <code>null</code>.
* </p>
*/
Filter getFilter();
}

View File

@ -1,27 +0,0 @@
/*******************************************************************************
* Copyright (c) 2013 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation, ongoing development
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher;
public class ServiceProperties {
/**
* <p>
* When registering a @Path or @Provider annotated object as an OSGi service the connector does publish
* this resource automatically. Anyway, in some scenarios it's not wanted to publish those services. If you
* want a resource not publish set this property as a service property with the value <code>false</code>.
* </p>
*/
public static String PUBLISH = "com.eclipsesource.jaxrs.publish";
private ServiceProperties() {
// prevent instantiation
}
}

View File

@ -1,51 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Ivan Iliev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ivan Iliev - initial API and implementation
* Holger Staudacher - ongoing development
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher;
import java.util.Dictionary;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
/**
* <p>
* Service that allows contribution of initial parameters and HttpContext for the Jersey servlet.
* Only the first tracked service implementing this interface will be used.
* </p>
*
* @since 4.2
*/
public interface ServletConfiguration {
/**
* <p>
* Returns an HttpContext or <code>null</code> for the given httpService and rootPath.
* </p>
*
* @param httpService the {@link HttpService} to configure the servlet for.
* @param rootPath the configured root path of the servlet to register.
* @return the {@link HttpContext} to use for the servlet registration.
*/
HttpContext getHttpContext(HttpService httpService, String rootPath);
/**
* <p>
* Returns initial parameters or <code>null</code> for the given httpService and rootPath.
* </p>
*
* @param httpService the {@link HttpService} to configure the servlet for.
* @param rootPath the configured root path of the servlet to register.
* @return the init properties to use for the servlet registration.
*/
Dictionary<String, String> getInitParams(HttpService httpService, String rootPath);
}

View File

@ -1,106 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* ProSyst Software GmbH. - compatibility with OSGi specification 4.2 APIs
* Ivan Iliev - added ServletConfigurationTracker
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.ws.rs.Path;
import org.openhab.core.io.rest.publisher.internal.JAXRSConnectorProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
@Component
public class Activator implements JAXRSConnectorProvider {
private ServiceRegistration<JAXRSConnector> connectorRegistration;
private JAXRSConnector jaxRsConnector;
private HttpTracker httpTracker;
private ServletConfigurationTracker servletConfigurationTracker;
private ApplicationConfigurationTracker applicationConfigurationTracker;
private ServiceRegistration<ManagedService> configRegistration;
@Activate
public Activator(final BundleContext context) {
jaxRsConnector = new JAXRSConnector(context);
}
@Activate
public void start(BundleContext context) throws Exception {
System.setProperty("javax.ws.rs.ext.RuntimeDelegate",
"org.glassfish.jersey.server.internal.RuntimeDelegateImpl");
startJerseyServer();
registerConfiguration(context);
connectorRegistration = context.registerService(JAXRSConnector.class, jaxRsConnector, null);
openHttpServiceTracker(context);
openServletConfigurationTracker(context);
openApplicationConfigurationTracker(context);
}
@Deactivate
public void stop(BundleContext context) throws Exception {
httpTracker.close();
servletConfigurationTracker.close();
applicationConfigurationTracker.close();
connectorRegistration.unregister();
configRegistration.unregister();
}
private void registerConfiguration(BundleContext context) {
Dictionary<String, String> properties = new Hashtable<>();
properties.put(Constants.SERVICE_PID, Configuration.CONFIG_SERVICE_PID);
configRegistration = context.registerService(ManagedService.class, new Configuration(jaxRsConnector),
properties);
}
private void startJerseyServer() throws BundleException {
Bundle bundle = getJerseyAPIBundle();
if (bundle.getState() != Bundle.ACTIVE) {
bundle.start();
}
}
private void openHttpServiceTracker(BundleContext context) {
httpTracker = new HttpTracker(context, jaxRsConnector);
httpTracker.open();
}
private void openServletConfigurationTracker(BundleContext context) {
servletConfigurationTracker = new ServletConfigurationTracker(context, jaxRsConnector);
servletConfigurationTracker.open();
}
private void openApplicationConfigurationTracker(BundleContext context) {
applicationConfigurationTracker = new ApplicationConfigurationTracker(context, jaxRsConnector);
applicationConfigurationTracker.open();
}
// For testing purpose
Bundle getJerseyAPIBundle() {
return FrameworkUtil.getBundle(Path.class);
}
@Override
public JAXRSConnector getJAXRSConnector() {
return jaxRsConnector;
}
}

View File

@ -1,45 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import static org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ServiceProperties.PUBLISH;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ResourceFilter;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
public class AllResourceFilter implements ResourceFilter {
static final String ANY_SERVICE_FILTER = "(&(objectClass=*)(!(" + PUBLISH + "=false)))";
private final BundleContext context;
public AllResourceFilter(BundleContext context) {
validateContext(context);
this.context = context;
}
private void validateContext(BundleContext context) {
if (context == null) {
throw new IllegalArgumentException("context must not be null");
}
}
@Override
public Filter getFilter() {
try {
return context.createFilter(ANY_SERVICE_FILTER);
} catch (InvalidSyntaxException willNotHappen) {
throw new IllegalStateException(willNotHappen);
}
}
}

View File

@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Holger Staudacher and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ApplicationConfiguration;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
/**
* <p>
* Tracker for OSGi Services implementing the {@link ApplicationConfiguration} interface.
* </p>
*/
public class ApplicationConfigurationTracker extends ServiceTracker {
private final JAXRSConnector connector;
ApplicationConfigurationTracker(BundleContext context, JAXRSConnector connector) {
super(context, ApplicationConfiguration.class.getName(), null);
this.connector = connector;
}
@Override
public Object addingService(ServiceReference reference) {
return connector.addApplicationConfiguration(reference);
}
@Override
public void removedService(ServiceReference reference, Object service) {
if (service instanceof ApplicationConfiguration) {
connector.removeApplicationConfiguration(reference, (ApplicationConfiguration) service);
}
}
}

View File

@ -1,77 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation, ongoing development
* ProSyst Software GmbH. - compatibility with OSGi specification 4.2 APIs
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.Dictionary;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
@SuppressWarnings("rawtypes")
public class Configuration implements ManagedService {
static final String CONFIG_SERVICE_PID = "com.eclipsesource.jaxrs.connector";
static final String PROPERTY_ROOT = "root";
static final String PROPERTY_PUBLISH_DELAY = "publishDelay";
static final long DEFAULT_PUBLISH_DELAY = 150;
private final JAXRSConnector connector;
private long publishDelay;
private String rootPath;
public Configuration(JAXRSConnector jaxRsConnector) {
this.connector = jaxRsConnector;
this.publishDelay = DEFAULT_PUBLISH_DELAY;
}
@Override
public void updated(Dictionary properties) throws ConfigurationException {
if (properties != null) {
Object root = properties.get(PROPERTY_ROOT);
ensureRootIsPresent(root);
String rootPath = (String) root;
ensureRootIsValid(rootPath);
this.rootPath = rootPath;
this.publishDelay = getPublishDelay(properties);
connector.updateConfiguration(this);
}
}
private void ensureRootIsValid(String rootPath) throws ConfigurationException {
if (!rootPath.startsWith("/")) {
throw new ConfigurationException(PROPERTY_ROOT, "Root path does not start with a /");
}
}
private void ensureRootIsPresent(Object root) throws ConfigurationException {
if (root == null || !(root instanceof String)) {
throw new ConfigurationException(PROPERTY_ROOT, "Property is not set or invalid.");
}
}
private long getPublishDelay(Dictionary properties) {
Object interval = properties.get(PROPERTY_PUBLISH_DELAY);
if (interval == null) {
return DEFAULT_PUBLISH_DELAY;
}
return ((Long) interval);
}
public long getPublishDelay() {
return publishDelay;
}
public String getRoothPath() {
return rootPath == null ? "/services" : rootPath;
}
}

View File

@ -1,31 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation, ongoing development
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.HashMap;
import java.util.Map;
import org.glassfish.jersey.server.ServerProperties;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ApplicationConfiguration;
public class DefaultApplicationConfiguration implements ApplicationConfiguration {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
// don't look for implementations described by META-INF/services/*
properties.put(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, false);
// disable auto discovery on server, as it's handled via OSGI
properties.put(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
return properties;
}
}

View File

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (c) 2011,2015 Frank Appel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Frank Appel - initial API and implementation
* Holger Staudacher - ongoing development
* ProSyst Software GmbH. - compatibility with OSGi specification 4.2 APIs
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;
public class HttpTracker extends ServiceTracker {
private final JAXRSConnector connector;
HttpTracker(BundleContext context, JAXRSConnector connector) {
super(context, HttpService.class.getName(), null);
this.connector = connector;
}
@Override
public Object addingService(ServiceReference reference) {
return connector.addHttpService(reference);
}
@Override
public void removedService(ServiceReference reference, Object service) {
if (service instanceof HttpService) {
connector.removeHttpService((HttpService) service);
}
}
}

View File

@ -1,237 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* ProSyst Software GmbH. - compatibility with OSGi specification 4.2 APIs
* Ivan Iliev - Performance Optimizations
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ApplicationConfiguration;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ServletConfiguration;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal.ServiceContainer.ServiceHolder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
public class JAXRSConnector {
private static final String HTTP_SERVICE_PORT_PROPERTY = "org.osgi.service.http.port";
private static final String RESOURCE_HTTP_PORT_PROPERTY = "http.port";
private static final String DEFAULT_HTTP_PORT = "80";
private final Object lock = new Object();
private final ServiceContainer httpServices;
private final ServiceContainer resources;
private final Map<HttpService, JerseyContext> contextMap;
private final BundleContext bundleContext;
private final List<ServiceHolder> resourceCache;
private ServletConfiguration servletConfiguration;
private final ServiceContainer applicationConfigurations;
private Configuration configuration;
JAXRSConnector(BundleContext bundleContext) {
this.bundleContext = bundleContext;
this.configuration = new Configuration(this);
this.httpServices = new ServiceContainer(bundleContext);
this.resources = new ServiceContainer(bundleContext);
this.contextMap = new HashMap<>();
this.resourceCache = new ArrayList<>();
this.applicationConfigurations = new ServiceContainer(bundleContext);
}
void updateConfiguration(Configuration configuration) {
synchronized (lock) {
this.configuration = configuration;
doUpdateConfiguration(configuration);
}
}
HttpService addHttpService(ServiceReference reference) {
synchronized (lock) {
return doAddHttpService(reference);
}
}
ServletConfiguration setServletConfiguration(ServiceReference reference) {
if (servletConfiguration == null) {
servletConfiguration = (ServletConfiguration) bundleContext.getService(reference);
doUpdateServletConfiguration();
return servletConfiguration;
}
return null;
}
void unsetServletConfiguration(ServiceReference reference, ServletConfiguration service) {
if (servletConfiguration == service) {
servletConfiguration = null;
bundleContext.ungetService(reference);
doUpdateServletConfiguration();
}
}
ApplicationConfiguration addApplicationConfiguration(ServiceReference reference) {
synchronized (lock) {
ApplicationConfiguration service = (ApplicationConfiguration) applicationConfigurations.add(reference)
.getService();
doUpdateAppConfiguration();
return service;
}
}
void removeApplicationConfiguration(ServiceReference reference, ApplicationConfiguration service) {
synchronized (lock) {
applicationConfigurations.remove(service);
doUpdateAppConfiguration();
}
}
private void doUpdateServletConfiguration() {
ServiceHolder[] services = httpServices.getServices();
for (ServiceHolder serviceHolder : services) {
contextMap.get(serviceHolder.getService()).updateServletConfiguration(servletConfiguration);
}
}
private void doUpdateAppConfiguration() {
ServiceHolder[] services = httpServices.getServices();
for (ServiceHolder serviceHolder : services) {
contextMap.get(serviceHolder.getService()).updateAppConfiguration(applicationConfigurations);
}
}
private void doUpdateConfiguration(Configuration configuration) {
ServiceHolder[] services = httpServices.getServices();
for (ServiceHolder serviceHolder : services) {
contextMap.get(serviceHolder.getService()).updateConfiguration(configuration);
}
}
HttpService doAddHttpService(ServiceReference reference) {
ServiceHolder serviceHolder = httpServices.add(reference);
HttpService service = (HttpService) serviceHolder.getService();
contextMap.put(service, createJerseyContext(service, configuration, servletConfiguration));
clearCache();
return service;
}
private void clearCache() {
List<ServiceHolder> cache = new ArrayList<>(resourceCache);
resourceCache.clear();
for (ServiceHolder serviceHolder : cache) {
registerResource(serviceHolder);
}
}
void removeHttpService(HttpService service) {
synchronized (lock) {
doRemoveHttpService(service);
}
}
void doRemoveHttpService(HttpService service) {
JerseyContext context = contextMap.remove(service);
if (context != null) {
cacheFreedResources(context);
}
httpServices.remove(service);
}
private void cacheFreedResources(JerseyContext context) {
List<Object> freeResources = context.eliminate();
for (Object resource : freeResources) {
resourceCache.add(resources.find(resource));
}
}
public Object addResource(ServiceReference reference) {
synchronized (lock) {
return doAddResource(reference);
}
}
private Object doAddResource(ServiceReference reference) {
ServiceHolder serviceHolder = resources.add(reference);
registerResource(serviceHolder);
return serviceHolder.getService();
}
private void registerResource(ServiceHolder serviceHolder) {
Object port = getPort(serviceHolder);
registerResource(serviceHolder, port);
}
private Object getPort(ServiceHolder serviceHolder) {
Object port = serviceHolder.getReference().getProperty(RESOURCE_HTTP_PORT_PROPERTY);
if (port == null) {
port = bundleContext.getProperty(HTTP_SERVICE_PORT_PROPERTY);
if (port == null) {
port = DEFAULT_HTTP_PORT;
}
}
return port;
}
private void registerResource(ServiceHolder serviceHolder, Object port) {
HttpService service = findHttpServiceForPort(port);
if (service != null) {
JerseyContext jerseyContext = contextMap.get(service);
jerseyContext.addResource(serviceHolder.getService());
} else {
cacheResource(serviceHolder);
}
}
private void cacheResource(ServiceHolder serviceHolder) {
resourceCache.add(serviceHolder);
}
private HttpService findHttpServiceForPort(Object port) {
ServiceHolder[] serviceHolders = httpServices.getServices();
HttpService result = null;
for (ServiceHolder serviceHolder : serviceHolders) {
Object servicePort = getPort(serviceHolder);
if (servicePort.equals(port)) {
result = (HttpService) serviceHolder.getService();
}
}
return result;
}
public void removeResource(Object resource) {
synchronized (lock) {
doRemoveResource(resource);
}
}
private void doRemoveResource(Object resource) {
ServiceHolder serviceHolder = resources.find(resource);
resourceCache.remove(serviceHolder);
HttpService httpService = findHttpServiceForPort(getPort(serviceHolder));
removeResourcesFromContext(resource, httpService);
resources.remove(resource);
}
private void removeResourcesFromContext(Object resource, HttpService httpService) {
JerseyContext jerseyContext = contextMap.get(httpService);
if (jerseyContext != null) {
jerseyContext.removeResource(resource);
}
}
// For testing purpose
JerseyContext createJerseyContext(HttpService service, Configuration configuration,
ServletConfiguration servletConfiguration) {
return new JerseyContext(service, configuration, servletConfiguration, applicationConfigurations);
}
}

View File

@ -1,219 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* Dragos Dascalita - disbaled autodiscovery
* Lars Pfannenschmidt - made WADL generation configurable
* Ivan Iliev - added ServletConfiguration handling, Optimized Performance
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.ws.rs.core.Application;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ApplicationConfiguration;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ServletConfiguration;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal.ServiceContainer.ServiceHolder;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
@SuppressWarnings("rawtypes")
public class JerseyContext {
private final RootApplication application;
private final HttpService httpService;
private final ServletContainerBridge servletContainerBridge;
private final ResourcePublisher resourcePublisher;
private volatile boolean isApplicationRegistered;
private ServletConfiguration servletConfiguration;
private String rootPath;
private ServiceContainer applicationConfigurations;
public JerseyContext(HttpService httpService, Configuration configuration,
ServletConfiguration servletConfiguration, ServiceContainer applicationConfigurations) {
this.httpService = httpService;
this.rootPath = configuration.getRoothPath();
this.application = new RootApplication();
this.applicationConfigurations = applicationConfigurations;
applyApplicationConfigurations(applicationConfigurations);
this.servletContainerBridge = new ServletContainerBridge(application);
this.servletConfiguration = servletConfiguration;
this.resourcePublisher = new ResourcePublisher(servletContainerBridge, configuration.getPublishDelay());
}
void applyApplicationConfigurations(ServiceContainer applicationConfigurations) {
getRootApplication().addProperties(new DefaultApplicationConfiguration().getProperties());
ServiceHolder[] services = applicationConfigurations.getServices();
for (ServiceHolder serviceHolder : services) {
Object service = serviceHolder.getService();
if (service instanceof ApplicationConfiguration) {
Map<String, Object> properties = ((ApplicationConfiguration) service).getProperties();
if (properties != null) {
getRootApplication().addProperties(properties);
}
}
}
}
public void addResource(Object resource) {
getRootApplication().addResource(resource);
registerServletWhenNotAlreadyRegistered();
resourcePublisher.schedulePublishing();
}
public void updateConfiguration(Configuration configuration) {
resourcePublisher.setPublishDelay(configuration.getPublishDelay());
String oldRootPath = this.rootPath;
this.rootPath = configuration.getRoothPath();
handleRootPath(oldRootPath);
applyApplicationConfigurations(this.applicationConfigurations);
handeRepublish();
}
private void handleRootPath(String oldRootPath) {
// if rootPath has changed and we already have registered our servlet and we need to refresh it
if (isApplicationRegistered && !oldRootPath.equals(rootPath)) {
refreshServletRegistration(oldRootPath);
}
}
public void updateAppConfiguration(ServiceContainer applicationConfigurations) {
this.applicationConfigurations = applicationConfigurations;
applyApplicationConfigurations(this.applicationConfigurations);
handeRepublish();
}
public void updateServletConfiguration(ServletConfiguration servletConfiguration) {
boolean isServletUpdateRequired = this.servletConfiguration != servletConfiguration;
this.servletConfiguration = servletConfiguration;
// if servletConfiguration object has changed and we already have a servlet - refresh it
if (isApplicationRegistered && isServletUpdateRequired) {
refreshServletRegistration(rootPath);
}
handeRepublish();
}
private void handeRepublish() {
// if application has been marked dirty and we have registered resources - we will republish
if (isApplicationRegistered) {
resourcePublisher.schedulePublishing();
}
}
private void refreshServletRegistration(String pathToUnregister) {
synchronized (servletContainerBridge) {
safeUnregister(pathToUnregister);
}
registerServletWhenNotAlreadyRegistered();
}
void registerServletWhenNotAlreadyRegistered() {
if (!isApplicationRegistered) {
isApplicationRegistered = true;
registerApplication();
}
}
private void registerApplication() {
ClassLoader loader = getContextClassloader();
setContextClassloader();
try {
registerServlet();
} catch (ServletException shouldNotHappen) {
throw new IllegalStateException(shouldNotHappen);
} catch (NamespaceException shouldNotHappen) {
throw new IllegalStateException(shouldNotHappen);
} finally {
resetContextClassloader(loader);
}
}
private ClassLoader getContextClassloader() {
return Thread.currentThread().getContextClassLoader();
}
private void setContextClassloader() {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
}
private void registerServlet() throws ServletException, NamespaceException {
ClassLoader original = getContextClassloader();
try {
Thread.currentThread().setContextClassLoader(Application.class.getClassLoader());
httpService.registerServlet(rootPath, servletContainerBridge, getInitParams(), getHttpContext());
} finally {
resetContextClassloader(original);
}
}
private Dictionary getInitParams() {
if (servletConfiguration != null) {
return servletConfiguration.getInitParams(httpService, rootPath);
}
return null;
}
private HttpContext getHttpContext() {
if (servletConfiguration != null) {
return servletConfiguration.getHttpContext(httpService, rootPath);
}
return null;
}
private void resetContextClassloader(ClassLoader loader) {
Thread.currentThread().setContextClassLoader(loader);
}
public void removeResource(Object resource) {
getRootApplication().removeResource(resource);
unregisterServletWhenNoResourcePresents();
resourcePublisher.schedulePublishing();
}
private void unregisterServletWhenNoResourcePresents() {
if (!getRootApplication().hasResources() && isApplicationRegistered) {
// unregistering while jersey context is being reloaded can lead to many exceptions
resourcePublisher.cancelPublishing();
synchronized (servletContainerBridge) {
safeUnregister(this.rootPath);
}
}
}
public List<Object> eliminate() {
resourcePublisher.cancelPublishing();
resourcePublisher.shutdown();
if (isApplicationRegistered) {
synchronized (servletContainerBridge) {
safeUnregister(this.rootPath);
}
}
return new ArrayList<>(getRootApplication().getResources());
}
void safeUnregister(String rootPath) {
try {
// this should call destroy on our servlet container
httpService.unregister(rootPath);
} catch (Exception jerseyShutdownException) {
// do nothing because jersey sometimes throws an exception during shutdown
}
isApplicationRegistered = false;
}
// For testing purpose
RootApplication getRootApplication() {
return application;
}
}

View File

@ -1,77 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* Ivan Iliev - Performance Optimizations
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class ResourcePublisher {
private final ServletContainerBridge servletContainerBridge;
private final ScheduledExecutorService executor;
private long publishDelay;
private volatile ScheduledFuture<?> scheduledFuture;
public ResourcePublisher(ServletContainerBridge servletContainerBridge, long publishDelay) {
this(createExecutor(), servletContainerBridge, publishDelay);
}
ResourcePublisher(ScheduledExecutorService executor, ServletContainerBridge servletContainerBridge,
long publishDelay) {
this.servletContainerBridge = servletContainerBridge;
this.publishDelay = publishDelay;
this.executor = executor;
}
private static ScheduledExecutorService createExecutor() {
return Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "ResourcePublisher");
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable exception) {
throw new IllegalStateException(exception);
}
});
return thread;
}
});
}
public void setPublishDelay(long publishDelay) {
this.publishDelay = publishDelay;
}
public void schedulePublishing() {
if (scheduledFuture != null) {
scheduledFuture.cancel(false);
}
scheduledFuture = executor.schedule(servletContainerBridge, publishDelay, TimeUnit.MILLISECONDS);
}
public void shutdown() {
executor.shutdown();
}
public void cancelPublishing() {
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
}
}

View File

@ -1,104 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* Dragos Dascalita - added properties
* Ivan Iliev - Performance Optimizations
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RootApplication extends Application {
private final Map<String, Object> properties;
private final List<Object> resources;
private final Object lock = new Object();
private volatile boolean dirty;
public RootApplication() {
resources = new LinkedList<>();
properties = new HashMap<>();
}
void addResource(Object resource) {
synchronized (lock) {
resources.add(resource);
dirty = true;
}
}
void removeResource(Object resource) {
synchronized (lock) {
resources.remove(resource);
dirty = true;
}
}
boolean hasResources() {
return !resources.isEmpty();
}
@Override
public Set<Object> getSingletons() {
synchronized (lock) {
Set<Object> currentResources = getResources();
// when this method is called jersey has obtained our resources as they are now, we mark the
// application as not dirty, next time a resource is added it will mark it as dirty again.
dirty = false;
return currentResources;
}
}
public Set<Object> getResources() {
Set<Object> singletons = new HashSet<>(super.getSingletons());
singletons.addAll(resources);
return singletons;
}
@Override
public Map<String, Object> getProperties() {
return properties;
}
public void addProperty(String key, Object value) {
Object oldValue = properties.get(key);
properties.put(key, value);
// if application is not dirty but the current property is changed - mark it
synchronized (lock) {
if (!dirty && (value != oldValue && (value == null || !value.equals(oldValue)))) {
dirty = true;
}
}
}
public void addProperties(Map<String, Object> properties) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
addProperty(entry.getKey(), entry.getValue());
}
}
public boolean isDirty() {
synchronized (lock) {
return dirty;
}
}
public void setDirty(boolean isDirty) {
synchronized (lock) {
dirty = isDirty;
}
}
}

View File

@ -1,119 +0,0 @@
/*******************************************************************************
* Copyright (c) 2011,2012 Frank Appel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Frank Appel - initial API and implementation
* Holger Staudacher - ongoing development
* ProSyst Software GmbH. - compatibility with OSGi specification 4.2 APIs
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class ServiceContainer {
private final Set<ServiceHolder> services;
private final BundleContext bundleContext;
ServiceContainer(BundleContext bundleContext) {
this.bundleContext = bundleContext;
this.services = new HashSet<>();
}
ServiceHolder add(ServiceReference reference) {
return add(bundleContext.getService(reference), reference);
}
void remove(Object service) {
services.remove(find(service));
}
ServiceHolder[] getServices() {
Set<ServiceHolder> result = new HashSet<>();
Iterator<ServiceHolder> iterator = services.iterator();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return result.toArray(new ServiceHolder[result.size()]);
}
ServiceHolder find(Object service) {
Finder finder = new Finder();
return finder.findServiceHolder(service, services);
}
void clear() {
services.clear();
}
int size() {
return services.size();
}
private ServiceHolder add(Object service, ServiceReference reference) {
ServiceHolder result = find(service);
if (notFound(result)) {
result = new ServiceHolder(service, reference);
services.add(result);
} else if (referenceIsMissing(reference, result)) {
result.setServiceReference(reference);
}
return result;
}
private boolean notFound(ServiceHolder result) {
return result == null;
}
private boolean referenceIsMissing(ServiceReference reference, ServiceHolder result) {
return reference != null && result.getReference() == null;
}
static class ServiceHolder {
private ServiceReference serviceReference;
private final Object service;
ServiceHolder(Object service, ServiceReference serviceReference) {
this.service = service;
this.serviceReference = serviceReference;
}
Object getService() {
return service;
}
ServiceReference getReference() {
return serviceReference;
}
void setServiceReference(ServiceReference serviceReference) {
this.serviceReference = serviceReference;
}
}
static class Finder {
ServiceHolder findServiceHolder(Object service, Set<ServiceHolder> collection) {
Iterator<ServiceHolder> iterator = collection.iterator();
ServiceHolder result = null;
while (iterator.hasNext()) {
ServiceHolder serviceHolder = iterator.next();
Object found = serviceHolder.getService();
if (service.equals(found)) {
result = serviceHolder;
}
}
return result;
}
}
}

View File

@ -1,44 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Ivan Iliev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ivan Iliev - initial API and implementation
* Holger Staudacher - ongoing development
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.ServletConfiguration;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
/**
* <p>
* Tracker for OSGi Services implementing the {@link ServletConfiguration} interface.
* </p>
*/
public class ServletConfigurationTracker extends ServiceTracker {
private final JAXRSConnector connector;
ServletConfigurationTracker(BundleContext context, JAXRSConnector connector) {
super(context, ServletConfiguration.class.getName(), null);
this.connector = connector;
}
@Override
public Object addingService(ServiceReference reference) {
return connector.setServletConfiguration(reference);
}
@Override
public void removedService(ServiceReference reference, Object service) {
if (service instanceof ServletConfiguration) {
connector.unsetServletConfiguration(reference, (ServletConfiguration) service);
}
}
}

View File

@ -1,103 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014,2015 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Holger Staudacher - initial API and implementation
* Ivan Iliev - Performance Optimizations
******************************************************************************/
package org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Request;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
public class ServletContainerBridge extends HttpServlet implements Runnable {
private final RootApplication application;
private ServletContainer servletContainer;
private ServletConfig servletConfig;
private volatile boolean isJerseyReady;
public ServletContainerBridge(RootApplication application) {
this.servletContainer = new ServletContainer(ResourceConfig.forApplication(application));
this.application = application;
this.isJerseyReady = false;
}
@Override
public void run() {
if (application.isDirty()) {
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(Request.class.getClassLoader());
synchronized (this) {
if (!isJerseyReady()) {
// if jersey has not been initialized - use the init method
getServletContainer().init(servletConfig);
} else {
// otherwise reload
isJerseyReady = false;
getServletContainer().reload(ResourceConfig.forApplication(application));
}
isJerseyReady = true;
}
} catch (ServletException e) {
throw new RuntimeException(e);
} finally {
Thread.currentThread().setContextClassLoader(original);
}
}
}
@Override
public void init(ServletConfig config) throws ServletException {
application.setDirty(true);
this.servletConfig = config;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// if jersey has not yet been initialized return service unavailable
if (isJerseyReady()) {
getServletContainer().service(req, res);
} else {
((HttpServletResponse) res).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
"Jersey is not ready yet!");
}
}
@Override
public void destroy() {
synchronized (this) {
if (isJerseyReady()) {
getServletContainer().destroy();
this.isJerseyReady = false;
// create a new ServletContainer when the old one is destroyed.
this.servletContainer = new ServletContainer(ResourceConfig.forApplication(application));
}
}
}
// for testing purposes
ServletContainer getServletContainer() {
return servletContainer;
}
// for testing purposes
boolean isJerseyReady() {
return isJerseyReady;
}
}

View File

@ -1,33 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.io.rest.publisher.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal.JAXRSConnector;
/**
* A provider of an JAX RS connector.
*
* @author Markus Rathgeb - Initial contribution
*/
@NonNullByDefault
public interface JAXRSConnectorProvider {
/**
* Gets a JAX RS connector.
*
* @return JAX RS connector
*/
JAXRSConnector getJAXRSConnector();
}

View File

@ -1,111 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.io.rest.publisher.internal;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.io.rest.OhJAXRSResource;
import org.eclipse.smarthome.io.rest.RESTResource;
import org.eclipse.smarthome.io.rest.sse.SseResource;
import org.glassfish.jersey.media.sse.SseFeature;
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
import org.openhab.core.thirdparty.com.eclipsesource.jaxrs.publisher.internal.JAXRSConnector;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
/**
* A registrator for JAX RS resources.
*
* @author Markus Rathgeb - Initial contribution
*/
@NonNullByDefault
@Component(immediate = true)
public class ResourceRegistrator {
private JAXRSConnector jaxRsConnector;
@Activate
public ResourceRegistrator(final @Reference JAXRSConnectorProvider provider) {
jaxRsConnector = provider.getJAXRSConnector();
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addJaxRsMessageBodyReader(final ServiceReference<MessageBodyReader<?>> resource) {
jaxRsConnector.addResource(resource);
}
public void removeJaxRsMessageBodyReader(final ServiceReference<MessageBodyReader<?>> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addJaxRsMessageBodyWriter(final ServiceReference<MessageBodyWriter<?>> resource) {
jaxRsConnector.addResource(resource);
}
public void removeJaxRsMessageBodyWriter(final ServiceReference<MessageBodyWriter<?>> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addOhRESTResource(final ServiceReference<RESTResource> resource) {
jaxRsConnector.addResource(resource);
}
public void removeOhRESTResource(final ServiceReference<RESTResource> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addOhSSEResource(final ServiceReference<SseResource> resource) {
jaxRsConnector.addResource(resource);
}
public void removeOhSSEResource(final ServiceReference<SseResource> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addOhJaxRsResource(final ServiceReference<OhJAXRSResource> resource) {
jaxRsConnector.addResource(resource);
}
public void removeOhJaxRsResource(final ServiceReference<OhJAXRSResource> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addJerseySseFeature(final ServiceReference<SseFeature> resource) {
jaxRsConnector.addResource(resource);
}
public void removeJerseySseFeature(final ServiceReference<SseFeature> resource) {
jaxRsConnector.removeResource(resource);
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addJerseyApplicationEventListener(final ServiceReference<ApplicationEventListener> resource) {
jaxRsConnector.addResource(resource);
}
public void removeJerseyApplicationEventListener(final ServiceReference<ApplicationEventListener> resource) {
jaxRsConnector.removeResource(resource);
}
}

View File

@ -187,7 +187,7 @@ public class JSONResponse {
* @author Joerg Plewe
*/
@Provider
public static class ExceptionMapper implements OhJAXRSResource, javax.ws.rs.ext.ExceptionMapper<Exception> {
public static class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<Exception> {
private final Logger logger = LoggerFactory.getLogger(ExceptionMapper.class);

View File

@ -1,30 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.rest;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Marker interface for an openHAB JAX RS resource that needs to be registered by the publisher.
*
* <p>
* This marker is for providing OSGi services for services that should be registered by the REST publisher.
* You should not use this. It is only for a migration path...
*
* @author Markus Rathgeb - Initial contribution
*/
@NonNullByDefault
@Deprecated
public interface OhJAXRSResource {
}

View File

@ -25,7 +25,6 @@ import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import org.eclipse.smarthome.io.rest.OhJAXRSResource;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,9 +38,8 @@ import org.slf4j.LoggerFactory;
*/
@Provider
@PreMatching
@Component(configurationPid = "org.eclipse.smarthome.io.rest.proxyfilter", immediate = true, service = {
OhJAXRSResource.class })
public class ProxyFilter implements OhJAXRSResource, ContainerRequestFilter {
@Component(configurationPid = "org.eclipse.smarthome.io.rest.proxyfilter", immediate = true, service = ProxyFilter.class)
public class ProxyFilter implements ContainerRequestFilter {
static final String PROTO_PROXY_HEADER = "x-forwarded-proto";

View File

@ -27,7 +27,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.eclipse.smarthome.io.rest.OhJAXRSResource;
import org.eclipse.smarthome.io.rest.RESTConstants;
import org.eclipse.smarthome.io.rest.RESTResource;
import org.eclipse.smarthome.io.rest.internal.Constants;
@ -55,8 +54,8 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Initial contribution and API
*/
@Path("/")
@Component(service = { OhJAXRSResource.class }, configurationPid = "org.eclipse.smarthome.io.rest.root")
public class RootResource implements OhJAXRSResource {
@Component(service = RootResource.class, configurationPid = "org.eclipse.smarthome.io.rest.root")
public class RootResource {
private final transient Logger logger = LoggerFactory.getLogger(RootResource.class);

View File

@ -62,7 +62,7 @@
<module>org.openhab.core.io.rest.core</module>
<module>org.openhab.core.io.rest.log</module>
<module>org.openhab.core.io.rest.mdns</module>
<module>org.openhab.core.io.rest.publisher</module>
<module>org.openhab.core.io.rest.optimize</module>
<module>org.openhab.core.io.rest.sitemap</module>
<module>org.openhab.core.io.rest.sse</module>
<module>org.openhab.core.io.rest.voice</module>

View File

@ -56,7 +56,7 @@
<feature dependency="true">pax-http-whiteboard</feature>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.http/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest.publisher/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest.optimize/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest.core/${project.version}</bundle>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.io.rest.sse/${project.version}</bundle>
</feature>

View File

@ -79,6 +79,7 @@
<capability>openhab.tp;feature=jax-rs-min;version=5.3.1</capability>
<feature dependency="true">http</feature>
<feature dependency="true">openhab.tp-kat.cpy-jersey-min-2.22.2</feature>
<bundle>mvn:com.eclipsesource.jaxrs/publisher/5.3.1</bundle>
<config name="com.eclipsesource.jaxrs.connector">
root=/rest
</config>