Revert "remove leftovers of REST optimize (#907)"

This reverts commit c86cbea3ba.
pull/930/head
Kai Kreuzer 2019-07-16 18:49:43 +02:00
parent 165df518de
commit b3aabd73ab
7 changed files with 284 additions and 0 deletions

View File

@ -0,0 +1,27 @@
<?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="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

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.io.rest.optimize</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

@ -0,0 +1,14 @@
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

@ -0,0 +1,2 @@
Bundle-SymbolicName: ${project.artifactId}
Bundle-Activator: org.eclipse.smarthome.io.rest.optimize.internal.Activator

View File

@ -0,0 +1,16 @@
<?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.optimize</artifactId>
<name>openHAB Core :: Bundles :: REST JAX-RS Optimizations</name>
</project>

View File

@ -0,0 +1,57 @@
/**
* 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.optimize.internal;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;
import com.eclipsesource.jaxrs.publisher.ResourceFilter;
/**
* Activator
*
* It registers a {@link ResourceFilter} in order to prevent the JAX-RS implementation to
* enforce starting all services once they are registered.
*
* @author Simon Kaufmann - initial contribution and API.
*
*/
public class Activator implements BundleActivator {
private ServiceRegistration<?> resourceFilterRegistration;
@Override
public void start(BundleContext context) throws Exception {
registerResourceFilter(context);
}
@Override
public void stop(BundleContext context) throws Exception {
unregisterResourceFilter();
}
private void registerResourceFilter(BundleContext context) throws InvalidSyntaxException {
resourceFilterRegistration = context.registerService(ResourceFilter.class.getName(), new ResourceFilterImpl(),
null);
}
private void unregisterResourceFilter() {
if (resourceFilterRegistration != null) {
resourceFilterRegistration.unregister();
resourceFilterRegistration = null;
}
}
}

View File

@ -0,0 +1,145 @@
/**
* 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.optimize.internal;
import static com.eclipsesource.jaxrs.publisher.ServiceProperties.PUBLISH;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.eclipsesource.jaxrs.publisher.ResourceFilter;
/**
* Provides a filter for all classes/interfaces which are relevant in the context of JAX-RS.
*
* By default, this filter will allow every service outside of the org.eclipse.smarthome.**-Namespace to be parsed by
* the JAXR-RS implementation. To further optimize this, install a fragment which adds a "/res/whitelist.txt" file,
* containing one service interface or class per line like in the following example:
*
* <pre>
* {@code
* # My Custom Services
* org.example.foo
* org.example.bar
* # Another one
* org.example.test
* }
* </pre>
*
* If this file is present, no other services will be scanned and hence won't be available.
*
* @author Simon Kaufmann - initial contribution and API.
*
*/
public class ResourceFilterImpl implements ResourceFilter {
private final Logger logger = LoggerFactory.getLogger(ResourceFilterImpl.class);
/**
* All classes and interfaces which are considered to be relevant for JAX-RS.
*/
private static final String[] WHITELIST = new String[] {
// JAX-RS
"javax.ws.rs.ext.MessageBodyReader", "javax.ws.rs.ext.MessageBodyWriter",
// openHAB
"org.eclipse.smarthome.io.rest.internal.filter.ProxyFilter",
"org.eclipse.smarthome.io.rest.internal.resources.RootResource",
"org.eclipse.smarthome.io.rest.JSONResponse$ExceptionMapper", "org.eclipse.smarthome.io.rest.RESTResource",
"org.eclipse.smarthome.io.rest.sse.internal.async.BlockingAsyncFeature",
"org.eclipse.smarthome.io.rest.sse.SseResource",
// SSE
"org.glassfish.jersey.media.sse.SseFeature",
"org.glassfish.jersey.server.monitoring.ApplicationEventListener" };
@Override
public Filter getFilter() {
String filterString = createFilter(WHITELIST);
try {
return FrameworkUtil.createFilter(filterString);
} catch (InvalidSyntaxException e) {
logger.error("Error creating RESTResource filter", e);
}
return null;
}
/**
* @param interfaces interface or class names
* @return filter string which matches if the class implements one of the interfaces or the name of the class is
* contained in interfaces
*/
private String createFilter(String[] interfaces) {
StringBuilder builder = new StringBuilder();
builder.append("(&");
builder.append("(|");
List<String> whitelist = loadWhitelistExtension();
if (whitelist == null) {
logger.debug("No /res/whitelist.txt file found - scanning all unknown services");
builder.append("(!(" + Constants.OBJECTCLASS + "=org.eclipse.smarthome.*))");
} else {
logger.debug("Whitelist /res/whitelist.txt file found - restricting scanning of services");
whitelist.forEach(entry -> {
builder.append("(" + Constants.OBJECTCLASS + "=" + entry + ")");
});
}
for (String clazz : interfaces) {
builder.append("(" + Constants.OBJECTCLASS + "=" + clazz + ")");
}
builder.append(")");
builder.append("(!(" + PUBLISH + "=false)))");
return builder.toString();
}
private List<String> loadWhitelistExtension() {
Enumeration<URL> entries = FrameworkUtil.getBundle(this.getClass()).findEntries("res", "whitelist.txt", false);
if (entries != null && entries.hasMoreElements()) {
URL url = entries.nextElement();
try (InputStream is = url.openStream()) {
return readWhitelistEntries(is);
} catch (IOException e) {
logger.warn("Error reading REST extension whitelist from {}", url, e);
return null;
}
} else {
return null;
}
}
private List<String> readWhitelistEntries(InputStream stream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
List<String> ret = new LinkedList<>();
String line = reader.readLine();
while (line != null) {
String trimmed = line.trim();
if (!trimmed.isEmpty() && !trimmed.startsWith("#")) {
ret.add(trimmed);
}
line = reader.readLine();
}
return ret;
}
}