Migrate to JAX-RS Whiteboard (#242)
* Update REST Docs feature dependency * Annotate habot for whiteboard * Fix default UI classpath, fix null context ID warning * Annotate cometvisu for whiteboard Signed-off-by: Wouter Born <github@maindrain.net>pull/249/head
parent
e624727564
commit
aa05fab9d2
|
@ -1,53 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>org.openhab.ui.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.ui.reactor.bundles</artifactId>
|
|
||||||
<version>2.5.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>org.openhab.ui.cometvisu.php</artifactId>
|
|
||||||
|
|
||||||
<name>openHAB UI :: Bundles :: CometVisu :: PHP Support</name>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab</groupId>
|
|
||||||
<artifactId>com.caucho.quercus</artifactId>
|
|
||||||
<version>4.0.45</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.ui.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.ui.cometvisu</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.ui.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.ui.dashboard</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.model.sitemap</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.ui</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.ui.icon</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -28,19 +28,16 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
<attribute name="ignore_optional_problems" value="true"/>
|
|
||||||
<attribute name="m2e-apt" value="true"/>
|
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" path="src/gen/java">
|
<classpathentry kind="src" path="src/gen/java">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/classes" path="src-gen">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
Bundle-SymbolicName: ${project.artifactId}
|
|
||||||
Bundle-Activator: org.openhab.ui.cometvisu.internal.CvActivator
|
|
|
@ -68,11 +68,6 @@
|
||||||
<artifactId>jackson-annotations</artifactId>
|
<artifactId>jackson-annotations</artifactId>
|
||||||
<version>2.9.10</version>
|
<version>2.9.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jersey.media</groupId>
|
|
||||||
<artifactId>jersey-media-multipart</artifactId>
|
|
||||||
<version>2.22.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>org.openhab.ui.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.ui.reactor.bundles</artifactId>
|
|
||||||
<version>2.5.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>org.openhab.ui.cometvisu</artifactId>
|
|
||||||
|
|
||||||
<name>openHAB UI :: Bundles :: CometVisu :: Backend</name>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-core</artifactId>
|
|
||||||
<version>2.2.11</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-impl</artifactId>
|
|
||||||
<version>2.2.11</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.activation</groupId>
|
|
||||||
<artifactId>activation</artifactId>
|
|
||||||
<version>1.1.1</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-api</artifactId>
|
|
||||||
<version>2.2.12</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.ui.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.ui.dashboard</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.model.sitemap</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.ui</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
|
||||||
<artifactId>org.openhab.core.ui.icon</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.rrd4j</groupId>
|
|
||||||
<artifactId>rrd4j</artifactId>
|
|
||||||
<version>3.4</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<generatedSourcesDirectory>src/gen/java</generatedSourcesDirectory>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>jaxb2-maven-plugin</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
<configuration>
|
|
||||||
<!-- The package of your generated sources -->
|
|
||||||
<packageName>org.openhab.ui.cometvisu.internal.config.beans</packageName>
|
|
||||||
<sources>
|
|
||||||
<source>src/main/resources/visu_config.xsd</source>
|
|
||||||
</sources>
|
|
||||||
<outputDirectory>src/gen/java</outputDirectory>
|
|
||||||
<locale>en</locale>
|
|
||||||
<clearOutputDir>false</clearOutputDir>
|
|
||||||
<generateEpisode>false</generateEpisode>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,97 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2010-2020 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.ui.cometvisu.internal;
|
|
||||||
|
|
||||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
|
||||||
import org.glassfish.jersey.media.sse.SseFeature;
|
|
||||||
import org.osgi.framework.BundleActivator;
|
|
||||||
import org.osgi.framework.BundleContext;
|
|
||||||
import org.osgi.framework.ServiceRegistration;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bundle activator for CometVisu backend.
|
|
||||||
*
|
|
||||||
* @author Tobias Bräutigam - Initial Contribution and API
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CvActivator implements BundleActivator {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(CvActivator.class);
|
|
||||||
|
|
||||||
private static BundleContext context;
|
|
||||||
|
|
||||||
private ServiceRegistration<?> sseFeatureRegistration;
|
|
||||||
|
|
||||||
private ServiceRegistration<?> blockingAsyncFeatureRegistration;
|
|
||||||
|
|
||||||
private ServiceRegistration<?> multiPartRegistration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called whenever the OSGi framework starts our bundle
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void start(BundleContext bc) throws Exception {
|
|
||||||
context = bc;
|
|
||||||
|
|
||||||
String featureName = SseFeature.class.getName();
|
|
||||||
if (bc.getServiceReference(featureName) == null) {
|
|
||||||
sseFeatureRegistration = bc.registerService(featureName, new SseFeature(), null);
|
|
||||||
|
|
||||||
logger.debug("CometVisu - SseFeature registered.");
|
|
||||||
}
|
|
||||||
featureName = MultiPartFeature.class.getName();
|
|
||||||
if (bc.getServiceReference(featureName) == null) {
|
|
||||||
multiPartRegistration = bc.registerService(featureName, new MultiPartFeature(), null);
|
|
||||||
|
|
||||||
logger.debug("CometVisu - MultiPartFeature registered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("CometVisu has been started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called whenever the OSGi framework stops our bundle
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void stop(BundleContext bc) throws Exception {
|
|
||||||
context = null;
|
|
||||||
|
|
||||||
if (sseFeatureRegistration != null) {
|
|
||||||
sseFeatureRegistration.unregister();
|
|
||||||
logger.debug("CometVisu - SseFeature unregistered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockingAsyncFeatureRegistration != null) {
|
|
||||||
blockingAsyncFeatureRegistration.unregister();
|
|
||||||
logger.debug("CometVisu - BlockingAsyncFeature unregistered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multiPartRegistration != null) {
|
|
||||||
multiPartRegistration.unregister();
|
|
||||||
logger.debug("CometVisu - MultiPartFeature unregistered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("CometVisu has been stopped.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bundle context of this bundle
|
|
||||||
*
|
|
||||||
* @return the bundle context
|
|
||||||
*/
|
|
||||||
public static BundleContext getContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2010-2020 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.ui.cometvisu.internal.async;
|
|
||||||
|
|
||||||
import org.glassfish.hk2.utilities.binding.AbstractBinder;
|
|
||||||
import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
|
|
||||||
import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link AbstractBinder} implementation that registers our custom
|
|
||||||
* {@link BlockingAsyncContextDelegateProvider} class as an implementation of
|
|
||||||
* the {@link AsyncContextDelegateProvider} SPI interface.
|
|
||||||
*
|
|
||||||
* @author Tobias Bräutigam - Initial Contribution and API
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class BlockingAsyncBinder extends AbstractBinder {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
// the qualifiedBy is needed in order for our implementation to be used
|
|
||||||
// if there are multiple implementations of AsyncContextDelegateProvider
|
|
||||||
bind(new BlockingAsyncContextDelegateProvider()).to(AsyncContextDelegateProvider.class)
|
|
||||||
.qualifiedBy(CustomAnnotationLiteral.INSTANCE);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2010-2020 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.ui.cometvisu.internal.async;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.glassfish.jersey.media.sse.SseFeature;
|
|
||||||
import org.glassfish.jersey.servlet.spi.AsyncContextDelegate;
|
|
||||||
import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
|
|
||||||
import org.openhab.ui.cometvisu.internal.util.SseUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link AsyncContextDelegateProvider} implementation that returns a
|
|
||||||
* blocking {@link AsyncContextDelegate}, which blocks while the connection is
|
|
||||||
* alive if the response content-type is {@link SseFeature #SERVER_SENT_EVENTS}
|
|
||||||
* or throws an UnsupportedOperationException otherwise. The blocking continues
|
|
||||||
* until the response can longer be written to.
|
|
||||||
*
|
|
||||||
* @author Tobias Bräutigam - Initial Contribution and API
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class BlockingAsyncContextDelegateProvider implements AsyncContextDelegateProvider {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final AsyncContextDelegate createDelegate(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response) {
|
|
||||||
return new BlockingAsyncContextDelegate(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class BlockingAsyncContextDelegate implements AsyncContextDelegate {
|
|
||||||
private static final int PING_TIMEOUT = 15 * 1000;
|
|
||||||
|
|
||||||
private final HttpServletResponse response;
|
|
||||||
|
|
||||||
private volatile boolean isRunning;
|
|
||||||
|
|
||||||
private BlockingAsyncContextDelegate(final HttpServletRequest request, final HttpServletResponse response) {
|
|
||||||
this.response = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void complete() {
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void suspend() throws IllegalStateException {
|
|
||||||
if (SseUtil.shouldAsyncBlock()) {
|
|
||||||
isRunning = true;
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
while (isRunning) {
|
|
||||||
try {
|
|
||||||
this.wait(PING_TIMEOUT);
|
|
||||||
ServletOutputStream outputStream = response.getOutputStream();
|
|
||||||
|
|
||||||
// write a new line to the OutputStream and flush to
|
|
||||||
// check connectivity. If the other peer closes the
|
|
||||||
// connection, the first flush() should generate a
|
|
||||||
// TCP reset that is detected on the second flush()
|
|
||||||
outputStream.write('\n');
|
|
||||||
response.flushBuffer();
|
|
||||||
|
|
||||||
outputStream.write('\n');
|
|
||||||
response.flushBuffer();
|
|
||||||
} catch (Exception exception) {
|
|
||||||
// If an exception has occurred during write and
|
|
||||||
// flush we consider the connection closed, attempt
|
|
||||||
// to close the output stream and stop blocking.
|
|
||||||
try {
|
|
||||||
response.getOutputStream().close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("ASYNCHRONOUS PROCESSING IS NOT SUPPORTED!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2010-2020 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.ui.cometvisu.internal.async;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.Feature;
|
|
||||||
import javax.ws.rs.core.FeatureContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Feature} implementation that registers our custom
|
|
||||||
* {@link BlockingAsyncBinder}.
|
|
||||||
*
|
|
||||||
* @author Tobias Bräutigam - Initial Contribution and API
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class BlockingAsyncFeature implements Feature {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean configure(FeatureContext context) {
|
|
||||||
if (context.getConfiguration().isEnabled(BlockingAsyncFeature.class)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.register(new BlockingAsyncBinder());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,6 +39,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.core.items.GroupItem;
|
import org.openhab.core.items.GroupItem;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
|
@ -55,6 +56,11 @@ import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.rrd4j.ConsolFun;
|
import org.rrd4j.ConsolFun;
|
||||||
import org.rrd4j.core.FetchData;
|
import org.rrd4j.core.FetchData;
|
||||||
import org.rrd4j.core.FetchRequest;
|
import org.rrd4j.core.FetchRequest;
|
||||||
|
@ -73,9 +79,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* used by the diagram plugin
|
* used by the diagram plugin
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
|
||||||
public class ChartResource implements RESTResource {
|
public class ChartResource implements RESTResource {
|
||||||
|
|
|
@ -21,12 +21,18 @@ import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.rest.CheckResponse;
|
import org.openhab.ui.cometvisu.internal.backend.model.rest.CheckResponse;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.rest.EnvironmentState;
|
import org.openhab.ui.cometvisu.internal.backend.model.rest.EnvironmentState;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
@ -37,9 +43,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* Check filesystem backend for the cometvisu manager.
|
* Check filesystem backend for the cometvisu manager.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
|
||||||
public class CheckResource implements RESTResource {
|
public class CheckResource implements RESTResource {
|
||||||
|
|
|
@ -19,13 +19,20 @@ import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.util.ClientInstaller;
|
import org.openhab.ui.cometvisu.internal.util.ClientInstaller;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import io.swagger.annotations.ApiParam;
|
import io.swagger.annotations.ApiParam;
|
||||||
import io.swagger.annotations.ApiResponse;
|
import io.swagger.annotations.ApiResponse;
|
||||||
|
@ -35,9 +42,15 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* Allows certain actions to configure the CometVisu backend through the REST api.
|
* Allows certain actions to configure the CometVisu backend through the REST api.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
|
||||||
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
|
||||||
public class ConfigResource implements RESTResource {
|
public class ConfigResource implements RESTResource {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ConfigResource.class);
|
private final Logger logger = LoggerFactory.getLogger(ConfigResource.class);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.core.items.GroupItem;
|
import org.openhab.core.items.GroupItem;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
|
@ -43,6 +44,11 @@ import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -55,9 +61,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* DataProvider backend for the cometvisu manager.
|
* DataProvider backend for the cometvisu manager.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/data")
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/data")
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/data")
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/data")
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/data")
|
||||||
public class DataProviderResource implements RESTResource {
|
public class DataProviderResource implements RESTResource {
|
||||||
|
|
|
@ -14,6 +14,8 @@ package org.openhab.ui.cometvisu.internal.backend.rest;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ import org.openhab.core.types.State;
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public interface EventBroadcaster {
|
public interface EventBroadcaster {
|
||||||
/**
|
/**
|
||||||
* Broadcasts an event described by the given parameters to all currently
|
* Broadcasts an event described by the given parameters to all currently
|
||||||
|
@ -65,5 +68,5 @@ public interface EventBroadcaster {
|
||||||
* - the item that is listened to
|
* - the item that is listened to
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Map<String, Class<? extends State>> getClientItems(Item item);
|
public Map<String, @Nullable Class<? extends State>> getClientItems(Item item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,27 +13,29 @@
|
||||||
package org.openhab.ui.cometvisu.internal.backend.rest;
|
package org.openhab.ui.cometvisu.internal.backend.rest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.DefaultValue;
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
||||||
|
@ -42,6 +44,11 @@ import org.openhab.ui.cometvisu.internal.util.FileOperationException;
|
||||||
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
||||||
import org.openhab.ui.cometvisu.internal.util.MountedFile;
|
import org.openhab.ui.cometvisu.internal.util.MountedFile;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -55,9 +62,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* Filesystem backend for the cometvisu manager.
|
* Filesystem backend for the cometvisu manager.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/fs")
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs")
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs")
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs")
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs")
|
||||||
public class FsResource implements RESTResource {
|
public class FsResource implements RESTResource {
|
||||||
|
@ -103,21 +114,22 @@ public class FsResource implements RESTResource {
|
||||||
@ApiOperation(value = "Create a binary file")
|
@ApiOperation(value = "Create a binary file")
|
||||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
|
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
|
||||||
@ApiResponse(code = 406, message = "File already exists") })
|
@ApiResponse(code = 406, message = "File already exists") })
|
||||||
public Response createBinary(
|
public Response createBinary(@Context HttpServletRequest request,
|
||||||
@ApiParam(value = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
|
@ApiParam(value = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
|
||||||
@QueryParam("type") String type,
|
@QueryParam("type") String type,
|
||||||
@ApiParam(value = "CRC32 hash of the file content") @QueryParam("hash") String hash,
|
@ApiParam(value = "CRC32 hash of the file content") @QueryParam("hash") String hash,
|
||||||
@ApiParam(value = "force overriding existing file") @DefaultValue("false") @FormDataParam("force") Boolean force,
|
@ApiParam(value = "force overriding existing file") @DefaultValue("false") @FormParam("force") Boolean force,
|
||||||
@ApiParam(value = "file content") @FormDataParam("file") InputStream fileInputStream,
|
@ApiParam(value = "file content") @FormParam("file") Object fileParam) {
|
||||||
@FormDataParam("file") FormDataContentDisposition fileMetaData) {
|
|
||||||
MountedFile target;
|
MountedFile target;
|
||||||
try {
|
try {
|
||||||
target = new MountedFile(Paths.get(path, fileMetaData.getFileName()).toString());
|
MultipartRequestMap map = new MultipartRequestMap(request);
|
||||||
|
File file = map.getFileParameter("file");
|
||||||
|
target = new MountedFile(Paths.get(path, file.getName()).toString());
|
||||||
File folder = target.toFile().toPath().getParent().toFile();
|
File folder = target.toFile().toPath().getParent().toFile();
|
||||||
if (!target.exists() || force) {
|
if (!target.exists() || force) {
|
||||||
if (!target.isReadonlyMount() && folder.canWrite()) {
|
if (!target.isReadonlyMount() && folder.canWrite()) {
|
||||||
try {
|
try {
|
||||||
FsUtil.getInstance().saveFile(target.toFile(), fileInputStream, hash);
|
FsUtil.getInstance().saveFile(target.toFile(), new FileInputStream(file), hash);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
} catch (FileOperationException e) {
|
} catch (FileOperationException e) {
|
||||||
return FsUtil.createErrorResponse(e);
|
return FsUtil.createErrorResponse(e);
|
||||||
|
|
|
@ -30,6 +30,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
import org.openhab.ui.cometvisu.internal.ManagerSettings;
|
||||||
|
@ -37,6 +38,11 @@ import org.openhab.ui.cometvisu.internal.backend.model.rest.ConfigSection;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.rest.HiddenConfig;
|
import org.openhab.ui.cometvisu.internal.backend.model.rest.HiddenConfig;
|
||||||
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -53,9 +59,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* Hidden configuration backend for the cometvisu manager.
|
* Hidden configuration backend for the cometvisu manager.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/config")
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/config")
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/config")
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/config")
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/config")
|
||||||
public class HiddenConfigResource implements RESTResource {
|
public class HiddenConfigResource implements RESTResource {
|
||||||
|
|
|
@ -22,12 +22,18 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.ConfigBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.ConfigBean;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.LoginBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.LoginBean;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.ResourcesBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.ResourcesBean;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
@ -39,8 +45,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* currently this is just a placeholder and does no real authentification
|
* currently this is just a placeholder and does no real authentification
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
|
||||||
public class LoginResource implements RESTResource {
|
public class LoginResource implements RESTResource {
|
||||||
|
|
|
@ -23,12 +23,18 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.ui.cometvisu.internal.Config;
|
import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.util.FileOperationException;
|
import org.openhab.ui.cometvisu.internal.util.FileOperationException;
|
||||||
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
import org.openhab.ui.cometvisu.internal.util.FsUtil;
|
||||||
import org.openhab.ui.cometvisu.internal.util.MountedFile;
|
import org.openhab.ui.cometvisu.internal.util.MountedFile;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -42,9 +48,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* Move/renames files for the CometVisu manager.
|
* Move/renames files for the CometVisu manager.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
|
||||||
public class MoveResource implements RESTResource {
|
public class MoveResource implements RESTResource {
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.ui.cometvisu.internal.backend.rest;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.Part;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper object for getting files from multi-part {@link HttpServletRequest}s.
|
||||||
|
*
|
||||||
|
* @author Wouter Born - Initial contribution
|
||||||
|
*/
|
||||||
|
public class MultipartRequestMap extends HashMap<String, List<Object>> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||||
|
|
||||||
|
private String encoding;
|
||||||
|
private String tempLocation;
|
||||||
|
|
||||||
|
public MultipartRequestMap(HttpServletRequest request) {
|
||||||
|
this(request, System.getProperty("java.io.tmpdir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultipartRequestMap(HttpServletRequest request, String tempLocation) {
|
||||||
|
super();
|
||||||
|
try {
|
||||||
|
this.tempLocation = tempLocation;
|
||||||
|
|
||||||
|
encoding = request.getCharacterEncoding();
|
||||||
|
if (encoding == null) {
|
||||||
|
try {
|
||||||
|
encoding = DEFAULT_ENCODING;
|
||||||
|
request.setCharacterEncoding(DEFAULT_ENCODING);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new IllegalStateException("Unsupported encoding: " + encoding, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Part part : request.getParts()) {
|
||||||
|
String fileName = part.getSubmittedFileName();
|
||||||
|
if (fileName == null) {
|
||||||
|
putMulti(part.getName(), getValue(part));
|
||||||
|
} else {
|
||||||
|
processFilePart(part, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException | ServletException e) {
|
||||||
|
throw new IllegalStateException("Failed to get request parts", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStringParameter(String name) {
|
||||||
|
List<Object> list = get(name);
|
||||||
|
return (list != null) ? (String) get(name).get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFileParameter(String name) {
|
||||||
|
List<Object> list = get(name);
|
||||||
|
return (list != null) ? (File) get(name).get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFilePart(Part part, String fileName) throws IOException {
|
||||||
|
File tempFile = new File(tempLocation, fileName);
|
||||||
|
tempFile.createNewFile();
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
|
||||||
|
try (BufferedInputStream input = new BufferedInputStream(part.getInputStream(), 8192);
|
||||||
|
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(tempFile), 8192);) {
|
||||||
|
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
for (int length = 0; ((length = input.read(buffer)) > 0);) {
|
||||||
|
output.write(buffer, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part.delete();
|
||||||
|
putMulti(part.getName(), tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getValue(Part part) throws IOException {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), encoding));
|
||||||
|
StringBuilder value = new StringBuilder();
|
||||||
|
char[] buffer = new char[8192];
|
||||||
|
for (int length; (length = reader.read(buffer)) > 0;) {
|
||||||
|
value.append(buffer, 0, length);
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void putMulti(final String key, final T value) {
|
||||||
|
List<Object> values = super.get(key);
|
||||||
|
|
||||||
|
if (values == null) {
|
||||||
|
values = new ArrayList<>();
|
||||||
|
values.add(value);
|
||||||
|
put(key, values);
|
||||||
|
} else {
|
||||||
|
values.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,12 +29,16 @@ import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import javax.ws.rs.sse.Sse;
|
||||||
|
import javax.ws.rs.sse.SseEventSink;
|
||||||
|
|
||||||
import org.glassfish.jersey.media.sse.EventOutput;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.glassfish.jersey.media.sse.SseBroadcaster;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.glassfish.jersey.media.sse.SseFeature;
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
|
import org.openhab.core.io.rest.SseBroadcaster;
|
||||||
import org.openhab.core.items.GenericItem;
|
import org.openhab.core.items.GenericItem;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
import org.openhab.core.items.ItemFactory;
|
import org.openhab.core.items.ItemFactory;
|
||||||
|
@ -45,8 +49,15 @@ import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.StateBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.StateBean;
|
||||||
import org.openhab.ui.cometvisu.internal.listeners.StateEventListener;
|
import org.openhab.ui.cometvisu.internal.listeners.StateEventListener;
|
||||||
import org.openhab.ui.cometvisu.internal.util.SseUtil;
|
import org.openhab.ui.cometvisu.internal.util.SseUtil;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -60,48 +71,56 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* SSE communication
|
* SSE communication
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
|
||||||
|
@NonNullByDefault
|
||||||
public class ReadResource implements EventBroadcaster, RESTResource {
|
public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
private final Logger logger = LoggerFactory.getLogger(ReadResource.class);
|
private final Logger logger = LoggerFactory.getLogger(ReadResource.class);
|
||||||
|
|
||||||
private SseBroadcaster broadcaster = new SseBroadcaster();
|
private SseBroadcaster<SseSinkInfo> broadcaster = new SseBroadcaster<>();
|
||||||
|
|
||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
private ItemRegistry itemRegistry;
|
private final ItemRegistry itemRegistry;
|
||||||
|
|
||||||
private StateEventListener stateEventListener;
|
private final StateEventListener stateEventListener = new StateEventListener(this);
|
||||||
|
|
||||||
private List<String> itemNames = new ArrayList<>();
|
private List<String> itemNames = new ArrayList<>();
|
||||||
private Map<Item, Map<String, Class<? extends State>>> items = new HashMap<>();
|
private Map<Item, Map<String, @Nullable Class<? extends State>>> items = new HashMap<>();
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private UriInfo uriInfo;
|
private @NonNullByDefault({}) UriInfo uriInfo;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private HttpServletResponse response;
|
private @NonNullByDefault({}) HttpServletResponse response;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private HttpServletRequest request;
|
private @NonNullByDefault({}) HttpServletRequest request;
|
||||||
|
|
||||||
|
private @NonNullByDefault({}) Sse sse;
|
||||||
|
|
||||||
private Collection<ItemFactory> itemFactories = new CopyOnWriteArrayList<>();
|
private Collection<ItemFactory> itemFactories = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
public ReadResource() {
|
@Activate
|
||||||
this.executorService = Executors.newSingleThreadExecutor();
|
public ReadResource(@Reference ItemRegistry itemRegistry) {
|
||||||
this.stateEventListener = new StateEventListener();
|
|
||||||
this.stateEventListener.setEventBroadcaster(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Reference
|
|
||||||
protected void setItemRegistry(ItemRegistry itemRegistry) {
|
|
||||||
this.itemRegistry = itemRegistry;
|
this.itemRegistry = itemRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void unsetItemRegistry(ItemRegistry itemRegistry) {
|
@Deactivate
|
||||||
this.itemRegistry = null;
|
public void deactivate() {
|
||||||
|
broadcaster.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Context
|
||||||
|
public void setSse(final Sse sse) {
|
||||||
|
this.sse = sse;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addItemFactory(ItemFactory itemFactory) {
|
protected void addItemFactory(ItemFactory itemFactory) {
|
||||||
|
@ -123,16 +142,15 @@ public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Produces(SseFeature.SERVER_SENT_EVENTS)
|
@Produces(MediaType.SERVER_SENT_EVENTS)
|
||||||
@ApiOperation(value = "Creates the SSE stream for item states, sends all requested states once and then only changes states")
|
@ApiOperation(value = "Creates the SSE stream for item states, sends all requested states once and then only changes states")
|
||||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||||
public Object getStates(@QueryParam("a") List<String> itemNames, @QueryParam("i") long index,
|
public void getStates(@Context final SseEventSink sseEventSink, @QueryParam("a") List<String> itemNames,
|
||||||
@QueryParam("t") long time) throws IOException, InterruptedException {
|
@QueryParam("i") long index, @QueryParam("t") long time) throws IOException, InterruptedException {
|
||||||
final EventOutput eventOutput = new EventOutput();
|
|
||||||
|
|
||||||
this.itemNames = itemNames;
|
this.itemNames = itemNames;
|
||||||
|
|
||||||
broadcaster.add(eventOutput);
|
broadcaster.add(sseEventSink, new SseSinkInfo(itemNames, index, time));
|
||||||
|
|
||||||
// get all requested items and send their states to the client
|
// get all requested items and send their states to the client
|
||||||
items = new HashMap<>();
|
items = new HashMap<>();
|
||||||
|
@ -175,12 +193,10 @@ public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("initially broadcasting {}/{} item states", states.size(), itemNames.size());
|
logger.debug("initially broadcasting {}/{} item states", states.size(), itemNames.size());
|
||||||
broadcaster.broadcast(SseUtil.buildEvent(states));
|
broadcaster.send(SseUtil.buildEvent(sse.newEventBuilder(), states));
|
||||||
}
|
}
|
||||||
// listen to state changes of the requested items
|
// listen to state changes of the requested items
|
||||||
registerItems();
|
registerItems();
|
||||||
|
|
||||||
return eventOutput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,11 +212,9 @@ public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* listens to state changes of the given item, if it is part of the
|
* listens to state changes of the given item, if it is part of the requested items
|
||||||
* requested items
|
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the new item, that should be listened to
|
||||||
* - the new item, that should be listened to
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void registerItem(Item item) {
|
public void registerItem(Item item) {
|
||||||
|
@ -216,8 +230,7 @@ public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
* listens to state changes of the given item, if it is part of the
|
* listens to state changes of the given item, if it is part of the
|
||||||
* requested items
|
* requested items
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the new item, that should be listened to
|
||||||
* - the new item, that should be listened to
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void unregisterItem(Item item) {
|
public void unregisterItem(Item item) {
|
||||||
|
@ -234,20 +247,23 @@ public class ReadResource implements EventBroadcaster, RESTResource {
|
||||||
* Broadcasts an event described by the given parameters to all currently
|
* Broadcasts an event described by the given parameters to all currently
|
||||||
* listening clients.
|
* listening clients.
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the item which has changed
|
||||||
* - the item which has changed
|
* @param eventObject bean that can be converted to a JSON object.
|
||||||
* @param eventObject
|
|
||||||
* - bean that can be converted to a JSON object.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void broadcastEvent(final Object eventObject) {
|
public void broadcastEvent(final Object eventObject) {
|
||||||
|
if (sse == null) {
|
||||||
|
logger.trace("broadcast skipped (no one listened since activation)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
executorService.execute(() -> {
|
executorService.execute(() -> {
|
||||||
broadcaster.broadcast(SseUtil.buildEvent(eventObject));
|
broadcaster.send(SseUtil.buildEvent(sse.newEventBuilder(), eventObject));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Class<? extends State>> getClientItems(Item item) {
|
public Map<String, @Nullable Class<? extends State>> getClientItems(Item item) {
|
||||||
return items.get(item);
|
return items.get(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.ui.cometvisu.internal.backend.rest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specific information we need to hold for a SSE sink.
|
||||||
|
*
|
||||||
|
* @author Wouter Born - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SseSinkInfo {
|
||||||
|
|
||||||
|
public List<String> itemNames;
|
||||||
|
public long index;
|
||||||
|
public long time;
|
||||||
|
|
||||||
|
public SseSinkInfo(List<String> itemNames, long index, long time) {
|
||||||
|
this.itemNames = itemNames;
|
||||||
|
this.index = index;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import javax.ws.rs.core.Response.Status;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
import org.openhab.core.events.EventPublisher;
|
import org.openhab.core.events.EventPublisher;
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
import org.openhab.core.items.ItemNotFoundException;
|
import org.openhab.core.items.ItemNotFoundException;
|
||||||
|
@ -35,6 +36,11 @@ import org.openhab.ui.cometvisu.internal.Config;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.SuccessBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.SuccessBean;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -48,8 +54,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* handles state updates send by the CometVisu client and forwars them to the EventPublisher
|
* handles state updates send by the CometVisu client and forwars them to the EventPublisher
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial contribution
|
* @author Tobias Bräutigam - Initial contribution
|
||||||
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
|
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
|
||||||
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
|
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
|
||||||
public class WriteResource implements RESTResource {
|
public class WriteResource implements RESTResource {
|
||||||
|
|
|
@ -30,6 +30,10 @@ public class StateEventListener implements StateChangeListener {
|
||||||
|
|
||||||
private EventBroadcaster eventBroadcaster;
|
private EventBroadcaster eventBroadcaster;
|
||||||
|
|
||||||
|
public StateEventListener(EventBroadcaster eventBroadcaster) {
|
||||||
|
this.eventBroadcaster = eventBroadcaster;
|
||||||
|
}
|
||||||
|
|
||||||
public void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
|
public void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
|
||||||
this.eventBroadcaster = eventBroadcaster;
|
this.eventBroadcaster = eventBroadcaster;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@ package org.openhab.ui.cometvisu.internal.util;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.sse.OutboundSseEvent;
|
||||||
|
|
||||||
import org.glassfish.jersey.media.sse.OutboundEvent;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.ui.cometvisu.internal.StateBeanMessageBodyWriter;
|
import org.openhab.ui.cometvisu.internal.StateBeanMessageBodyWriter;
|
||||||
import org.openhab.ui.cometvisu.internal.backend.model.StateBean;
|
import org.openhab.ui.cometvisu.internal.backend.model.StateBean;
|
||||||
|
|
||||||
|
@ -24,8 +25,9 @@ import org.openhab.ui.cometvisu.internal.backend.model.StateBean;
|
||||||
* Utility class containing helper methods for the SSE implementation.
|
* Utility class containing helper methods for the SSE implementation.
|
||||||
*
|
*
|
||||||
* @author Tobias Bräutigam - Initial Contribution and API
|
* @author Tobias Bräutigam - Initial Contribution and API
|
||||||
*
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class SseUtil {
|
public class SseUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,29 +35,23 @@ public class SseUtil {
|
||||||
* {@link StateBean} created for the given eventType, objectIdentifier,
|
* {@link StateBean} created for the given eventType, objectIdentifier,
|
||||||
* eventObject.
|
* eventObject.
|
||||||
*
|
*
|
||||||
* @param eventType
|
* @param eventType the event type for the event
|
||||||
* - the event type for the event
|
* @param objectIdentifier the identifier for the main event object
|
||||||
* @param objectIdentifier
|
* @param eventObject the eventObject to be included
|
||||||
* - the identifier for the main event object
|
* @return a new OutboundSseEvent
|
||||||
* @param eventObject
|
|
||||||
* - the eventObject to be included
|
|
||||||
* @return a new OutboundEvent.
|
|
||||||
*/
|
*/
|
||||||
public static OutboundEvent buildEvent(Object eventObject) {
|
public static OutboundSseEvent buildEvent(OutboundSseEvent.Builder eventBuilder, Object eventObject) {
|
||||||
OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
|
|
||||||
StateBeanMessageBodyWriter writer = new StateBeanMessageBodyWriter();
|
StateBeanMessageBodyWriter writer = new StateBeanMessageBodyWriter();
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
OutboundEvent event = eventBuilder.mediaType(MediaType.APPLICATION_JSON_TYPE)
|
return eventBuilder.mediaType(MediaType.APPLICATION_JSON_TYPE).data(writer.serialize(eventObject))
|
||||||
.data(writer.serialize(eventObject)).id(String.valueOf(date.getTime())).build();
|
.id(String.valueOf(date.getTime())).build();
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to mark our current thread(request processing) that SSE blocking
|
* Used to mark our current thread(request processing) that SSE blocking
|
||||||
* should be enabled.
|
* should be enabled.
|
||||||
*/
|
*/
|
||||||
private static ThreadLocal<Boolean> blockingSseEnabled = new ThreadLocal<Boolean>() {
|
private static ThreadLocal<Boolean> blockingSseEnabled = new ThreadLocal<>() {
|
||||||
@Override
|
@Override
|
||||||
protected Boolean initialValue() {
|
protected Boolean initialValue() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,6 +38,7 @@ import javax.ws.rs.core.Response.Status;
|
||||||
import org.eclipse.jdt.annotation.NonNull;
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
import org.openhab.core.auth.Role;
|
import org.openhab.core.auth.Role;
|
||||||
import org.openhab.core.io.rest.LocaleService;
|
import org.openhab.core.io.rest.LocaleService;
|
||||||
|
import org.openhab.core.io.rest.RESTConstants;
|
||||||
import org.openhab.core.io.rest.RESTResource;
|
import org.openhab.core.io.rest.RESTResource;
|
||||||
import org.openhab.core.voice.VoiceManager;
|
import org.openhab.core.voice.VoiceManager;
|
||||||
import org.openhab.core.voice.text.InterpretationException;
|
import org.openhab.core.voice.text.InterpretationException;
|
||||||
|
@ -54,6 +55,11 @@ import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -69,8 +75,13 @@ import io.swagger.annotations.ApiResponses;
|
||||||
* This class describes the /habot resource of the REST API.
|
* This class describes the /habot resource of the REST API.
|
||||||
*
|
*
|
||||||
* @author Yannick Schaus - Initial contribution
|
* @author Yannick Schaus - Initial contribution
|
||||||
|
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsName(HABotResource.PATH_HABOT)
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||||
|
@JSONRequired
|
||||||
@RolesAllowed({ Role.USER, Role.ADMIN })
|
@RolesAllowed({ Role.USER, Role.ADMIN })
|
||||||
@Path(HABotResource.PATH_HABOT)
|
@Path(HABotResource.PATH_HABOT)
|
||||||
@Api(HABotResource.PATH_HABOT)
|
@Api(HABotResource.PATH_HABOT)
|
||||||
|
|
|
@ -6,23 +6,6 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="web">
|
|
||||||
<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="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
@ -33,14 +16,15 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" path="target/generated-sources/annotations">
|
<classpathentry excluding="**" kind="src" output="target/classes" path="web/www">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
<attribute name="test" value="true"/>
|
<attribute name="test" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
|
|
|
@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Yannick Schaus - Initial contribution
|
* @author Yannick Schaus - Initial contribution
|
||||||
*/
|
*/
|
||||||
@Component(immediate = true, name = "org.openhab.ui")
|
@Component(immediate = true, name = "org.openhab.ui", property = { "httpContext.id:String=oh-ui-http-ctx" })
|
||||||
public class UIService implements HttpContext {
|
public class UIService implements HttpContext {
|
||||||
|
|
||||||
private static final String APP_BASE = "app";
|
private static final String APP_BASE = "app";
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
<feature>openhab-core-ui</feature>
|
<feature>openhab-core-ui</feature>
|
||||||
<feature dependency="true">openhab.tp-jaxb</feature>
|
<feature dependency="true">openhab.tp-jaxb</feature>
|
||||||
<feature dependency="true">openhab.tp-jackson</feature>
|
<feature dependency="true">openhab.tp-jackson</feature>
|
||||||
<feature dependency="true">openhab.tp-kat.cpy-jersey-min-2.22.2</feature>
|
|
||||||
<bundle dependency="true">mvn:org.rrd4j/rrd4j/3.4</bundle>
|
<bundle dependency="true">mvn:org.rrd4j/rrd4j/3.4</bundle>
|
||||||
<bundle>mvn:org.openhab.ui.bundles/org.openhab.ui.cometvisu/${project.version}</bundle>
|
<bundle>mvn:org.openhab.ui.bundles/org.openhab.ui.cometvisu/${project.version}</bundle>
|
||||||
<config name="cometvisu">
|
<config name="cometvisu">
|
||||||
|
@ -89,7 +88,7 @@
|
||||||
|
|
||||||
<feature name="openhab-ui-restdocs" description="REST Documentation" version="${project.version}">
|
<feature name="openhab-ui-restdocs" description="REST Documentation" version="${project.version}">
|
||||||
<feature>openhab-core-ui</feature>
|
<feature>openhab-core-ui</feature>
|
||||||
<feature>openhab.tp-swagger-jax-rs-provider</feature>
|
<feature>openhab-core-io-rest-swagger</feature>
|
||||||
<bundle>mvn:org.openhab.ui.bundles/org.openhab.ui.restdocs/${project.version}</bundle>
|
<bundle>mvn:org.openhab.ui.bundles/org.openhab.ui.restdocs/${project.version}</bundle>
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue