parent
165df518de
commit
b3aabd73ab
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Bundle-SymbolicName: ${project.artifactId}
|
||||
Bundle-Activator: org.eclipse.smarthome.io.rest.optimize.internal.Activator
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue