]> git.basschouten.com Git - openhab-addons.git/commitdiff
[neeo] fix ClassNotFoundException and switch to constructor injection (#9006)
authorJ-N-K <J-N-K@users.noreply.github.com>
Sat, 14 Nov 2020 15:11:06 +0000 (16:11 +0100)
committerGitHub <noreply@github.com>
Sat, 14 Nov 2020 15:11:06 +0000 (16:11 +0100)
Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
12 files changed:
bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/NeeoBrainApi.java
bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoBrainHandler.java
bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoForwardActionsServlet.java
bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoHandlerFactory.java
bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/net/HttpRequest.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/NeeoService.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoApi.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoBrainServlet.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoDeviceKeys.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/MdnsBrainDiscovery.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/net/HttpRequest.java
bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainService.java

index cdc2984f9b3d4224cda6828ab5a59319cf33755c..26ffb6ac9bd5020b3d83c84579d14bfe762eeef6 100644 (file)
@@ -17,6 +17,8 @@ import java.net.URL;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.ws.rs.client.ClientBuilder;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jetty.http.HttpStatus;
 import org.openhab.binding.neeo.internal.models.ExecuteResult;
@@ -44,7 +46,10 @@ public class NeeoBrainApi implements AutoCloseable {
     private final Gson gson = NeeoUtil.getGson();
 
     /** The {@link HttpRequest} used for making requests */
-    private final AtomicReference<HttpRequest> request = new AtomicReference<>(new HttpRequest());
+    private final AtomicReference<HttpRequest> request;
+
+    /** The {@link ClientBuilder} to use */
+    private final ClientBuilder clientBuilder;
 
     /** The IP address of the neeo brain */
     private final NeeoUrlBuilder urlBuilder;
@@ -54,11 +59,14 @@ public class NeeoBrainApi implements AutoCloseable {
      *
      * @param ipAddress the non-empty ip address
      */
-    public NeeoBrainApi(String ipAddress) {
+    public NeeoBrainApi(String ipAddress, ClientBuilder clientBuilder) {
         NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
 
         this.urlBuilder = new NeeoUrlBuilder(
                 NeeoConstants.PROTOCOL + ipAddress + ":" + NeeoConstants.DEFAULT_BRAIN_PORT);
+        this.clientBuilder = clientBuilder;
+
+        request = new AtomicReference<>(new HttpRequest(clientBuilder));
     }
 
     /**
@@ -232,7 +240,7 @@ public class NeeoBrainApi implements AutoCloseable {
 
     @Override
     public void close() throws Exception {
-        NeeoUtil.close(request.getAndSet(new HttpRequest()));
+        NeeoUtil.close(request.getAndSet(new HttpRequest(clientBuilder)));
     }
 
     /**
index 462f9f45b394e5ee7962df0701423caead0f162c..3c797a4ffb64bfadfb0d85f970f8394b2df035c4 100644 (file)
@@ -29,6 +29,7 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.servlet.ServletException;
+import javax.ws.rs.client.ClientBuilder;
 
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -73,6 +74,9 @@ public class NeeoBrainHandler extends BaseBridgeHandler {
     /** The {@link NetworkAddressService} to use */
     private final NetworkAddressService networkAddressService;
 
+    /** The {@link ClientBuilder} to use */
+    private final ClientBuilder clientBuilder;
+
     /** GSON implementation - only used to deserialize {@link NeeoAction} */
     private final Gson gson = new Gson();
 
@@ -112,7 +116,7 @@ public class NeeoBrainHandler extends BaseBridgeHandler {
      * @param networkAddressService the non-null {@link NetworkAddressService}
      */
     NeeoBrainHandler(Bridge bridge, int servicePort, HttpService httpService,
-            NetworkAddressService networkAddressService) {
+            NetworkAddressService networkAddressService, ClientBuilder clientBuilder) {
         super(bridge);
 
         Objects.requireNonNull(bridge, "bridge cannot be null");
@@ -122,6 +126,7 @@ public class NeeoBrainHandler extends BaseBridgeHandler {
         this.servicePort = servicePort;
         this.httpService = httpService;
         this.networkAddressService = networkAddressService;
+        this.clientBuilder = clientBuilder;
     }
 
     /**
@@ -164,7 +169,7 @@ public class NeeoBrainHandler extends BaseBridgeHandler {
                         "Brain IP Address must be specified");
                 return;
             }
-            final NeeoBrainApi api = new NeeoBrainApi(ipAddress);
+            final NeeoBrainApi api = new NeeoBrainApi(ipAddress, clientBuilder);
             final NeeoBrain brain = api.getBrain();
             final String brainId = getNeeoBrainId();
 
@@ -184,22 +189,18 @@ public class NeeoBrainHandler extends BaseBridgeHandler {
             if (config.isEnableForwardActions()) {
                 NeeoUtil.checkInterrupt();
 
-                forwardActionServlet = new NeeoForwardActionsServlet(scheduler,
-                        new NeeoForwardActionsServlet.Callback() {
-                            @Override
-                            public void post(String json) {
-                                triggerChannel(NeeoConstants.CHANNEL_BRAIN_FOWARDACTIONS, json);
-
-                                final NeeoAction action = Objects.requireNonNull(gson.fromJson(json, NeeoAction.class));
-
-                                for (final Thing child : getThing().getThings()) {
-                                    final ThingHandler th = child.getHandler();
-                                    if (th instanceof NeeoRoomHandler) {
-                                        ((NeeoRoomHandler) th).processAction(action);
-                                    }
-                                }
-                            }
-                        }, config.getForwardChain());
+                forwardActionServlet = new NeeoForwardActionsServlet(scheduler, json -> {
+                    triggerChannel(NeeoConstants.CHANNEL_BRAIN_FOWARDACTIONS, json);
+
+                    final NeeoAction action = Objects.requireNonNull(gson.fromJson(json, NeeoAction.class));
+
+                    for (final Thing child : getThing().getThings()) {
+                        final ThingHandler th = child.getHandler();
+                        if (th instanceof NeeoRoomHandler) {
+                            ((NeeoRoomHandler) th).processAction(action);
+                        }
+                    }
+                }, config.getForwardChain(), clientBuilder);
 
                 NeeoUtil.checkInterrupt();
                 try {
index 064cd273f198b6cdab116150b33b997554eb937c..5c2565b5ec1c285a1de646c261bfad949acc4a46 100644 (file)
@@ -16,13 +16,12 @@ import java.io.IOException;
 import java.util.Objects;
 import java.util.concurrent.ScheduledExecutorService;
 
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.ClientBuilder;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.http.HttpStatus;
@@ -52,6 +51,9 @@ public class NeeoForwardActionsServlet extends HttpServlet {
     @Nullable
     private final String forwardChain;
 
+    /** The {@link ClientBuilder} to use */
+    private final ClientBuilder clientBuilder;
+
     /** The scheduler to use to schedule recipe execution */
     private final ScheduledExecutorService scheduler;
 
@@ -62,7 +64,8 @@ public class NeeoForwardActionsServlet extends HttpServlet {
      * @param callback a non-null {@link Callback}
      * @param forwardChain a possibly null, possibly empty forwarding chain
      */
-    NeeoForwardActionsServlet(ScheduledExecutorService scheduler, Callback callback, @Nullable String forwardChain) {
+    NeeoForwardActionsServlet(ScheduledExecutorService scheduler, Callback callback, @Nullable String forwardChain,
+            ClientBuilder clientBuilder) {
         super();
 
         Objects.requireNonNull(scheduler, "scheduler cannot be null");
@@ -71,6 +74,7 @@ public class NeeoForwardActionsServlet extends HttpServlet {
         this.scheduler = scheduler;
         this.callback = callback;
         this.forwardChain = forwardChain;
+        this.clientBuilder = clientBuilder;
     }
 
     /**
@@ -81,10 +85,11 @@ public class NeeoForwardActionsServlet extends HttpServlet {
      * @param resp the non-null response
      */
     @Override
-    protected void doPost(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp)
-            throws ServletException, IOException {
-        Objects.requireNonNull(req, "req cannot be null");
-        Objects.requireNonNull(resp, "resp cannot be null");
+    protected void doPost(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) throws IOException {
+        if (req == null || resp == null) {
+            logger.warn("doPost called with req={}, resp={}, non-null required.", req, resp);
+            return;
+        }
 
         final String json = IOUtils.toString(req.getReader());
         logger.debug("handleForwardActions {}", json);
@@ -92,11 +97,11 @@ public class NeeoForwardActionsServlet extends HttpServlet {
         callback.post(json);
 
         final String fc = forwardChain;
-        if (fc != null && StringUtils.isNotEmpty(fc)) {
+        if (fc != null && !fc.isEmpty()) {
             scheduler.execute(() -> {
-                try (final HttpRequest request = new HttpRequest()) {
+                try (final HttpRequest request = new HttpRequest(clientBuilder)) {
                     for (final String forwardUrl : fc.split(",")) {
-                        if (StringUtils.isNotEmpty(forwardUrl)) {
+                        if (forwardUrl != null && !forwardUrl.isEmpty()) {
                             final HttpResponse httpResponse = request.sendPostJsonCommand(forwardUrl, json);
                             if (httpResponse.getHttpCode() != HttpStatus.OK_200) {
                                 logger.debug("Cannot forward event {} to {}: {}", json, forwardUrl,
index 39a63cc47785fc757bd2a396891eb96758ce9afa..6ef62cebcbdb08fc18b0338c77e96644c4db3109 100644 (file)
@@ -17,6 +17,8 @@ import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.ws.rs.client.ClientBuilder;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.neeo.internal.NeeoConstants;
@@ -33,6 +35,7 @@ import org.openhab.core.thing.binding.BaseThingHandlerFactory;
 import org.openhab.core.thing.binding.ThingHandler;
 import org.openhab.core.thing.binding.ThingHandlerFactory;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.http.HttpService;
@@ -48,54 +51,23 @@ import org.osgi.service.http.HttpService;
 public class NeeoHandlerFactory extends BaseThingHandlerFactory {
 
     /** The {@link HttpService} used to register callbacks */
-    @NonNullByDefault({})
-    private HttpService httpService;
+    private final HttpService httpService;
 
     /** The {@link NetworkAddressService} used for ip lookup */
-    @NonNullByDefault({})
-    private NetworkAddressService networkAddressService;
+    private final NetworkAddressService networkAddressService;
+
+    /** The {@link ClientBuilder} used in HttpRequest */
+    private final ClientBuilder clientBuilder;
 
     /** The discovery services created by this class (one per room and one for each device) */
     private final ConcurrentMap<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new ConcurrentHashMap<>();
 
-    /**
-     * Sets the {@link HttpService}.
-     *
-     * @param httpService the non-null {@link HttpService} to use
-     */
-    @Reference
-    protected void setHttpService(HttpService httpService) {
-        Objects.requireNonNull(httpService, "httpService cannot be null");
+    @Activate
+    public NeeoHandlerFactory(@Reference HttpService httpService,
+            @Reference NetworkAddressService networkAddressService, @Reference ClientBuilder clientBuilder) {
         this.httpService = httpService;
-    }
-
-    /**
-     * Unsets the {@link HttpService}
-     *
-     * @param httpService the {@link HttpService} (not used in this implementation)
-     */
-    protected void unsetHttpService(HttpService httpService) {
-        this.httpService = null;
-    }
-
-    /**
-     * Sets the {@link NetworkAddressService}.
-     *
-     * @param networkAddressService the non-null {@link NetworkAddressService} to use
-     */
-    @Reference
-    protected void setNetworkAddressService(NetworkAddressService networkAddressService) {
-        Objects.requireNonNull(networkAddressService, "networkAddressService cannot be null");
         this.networkAddressService = networkAddressService;
-    }
-
-    /**
-     * Unsets the {@link NetworkAddressService}
-     *
-     * @param networkAddressService the {@link NetworkAddressService} (not used in this implementation)
-     */
-    protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) {
-        this.networkAddressService = null;
+        this.clientBuilder = clientBuilder;
     }
 
     @Override
@@ -112,17 +84,10 @@ public class NeeoHandlerFactory extends BaseThingHandlerFactory {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (thingTypeUID.equals(NeeoConstants.BRIDGE_TYPE_BRAIN)) {
-            final HttpService localHttpService = httpService;
-            final NetworkAddressService localNetworkAddressService = networkAddressService;
-
-            Objects.requireNonNull(localHttpService, "HttpService cannot be null");
-            Objects.requireNonNull(localNetworkAddressService, "networkAddressService cannot be null");
-
             final int port = HttpServiceUtil.getHttpServicePort(this.bundleContext);
-
             final NeeoBrainHandler handler = new NeeoBrainHandler((Bridge) thing,
-                    port < 0 ? NeeoConstants.DEFAULT_BRAIN_HTTP_PORT : port, localHttpService,
-                    localNetworkAddressService);
+                    port < 0 ? NeeoConstants.DEFAULT_BRAIN_HTTP_PORT : port, httpService, networkAddressService,
+                    clientBuilder);
             registerRoomDiscoveryService(handler);
             return handler;
         } else if (thingTypeUID.equals(NeeoConstants.BRIDGE_TYPE_ROOM)) {
index 0e2a5743e8b69bccb1a60c0cd26559816b176f4e..b74f2145b67117bcf37d42fb946b1ef58d4c0c56 100644 (file)
@@ -13,6 +13,8 @@
 package org.openhab.binding.neeo.internal.net;
 
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Objects;
 
 import javax.ws.rs.ProcessingException;
@@ -47,8 +49,8 @@ public class HttpRequest implements AutoCloseable {
     /**
      * Instantiates a new request
      */
-    public HttpRequest() {
-        client = ClientBuilder.newClient();
+    public HttpRequest(ClientBuilder clientBuilder) {
+        client = clientBuilder.build();
 
         if (logger.isDebugEnabled()) {
             client.register(new LoggingFilter(new Slf4LoggingAdapter(logger), true));
@@ -81,16 +83,23 @@ public class HttpRequest implements AutoCloseable {
     /**
      * Send post JSON command using the body
      *
-     * @param uri the non empty uri
+     * @param uriString the non empty uri
      * @param body the non-null, possibly empty body
      * @return the {@link HttpResponse}
      */
-    public HttpResponse sendPostJsonCommand(String uri, String body) {
-        NeeoUtil.requireNotEmpty(uri, "uri cannot be empty");
+    public HttpResponse sendPostJsonCommand(String uriString, String body) {
+        NeeoUtil.requireNotEmpty(uriString, "uri cannot be empty");
         Objects.requireNonNull(body, "body cannot be null");
 
+        logger.trace("sendPostJsonCommand: target={}, body={}", uriString, body);
+
         try {
-            final Builder request = client.target(uri).request(MediaType.APPLICATION_JSON);
+            URI targetUri = new URI(uriString);
+            if (!targetUri.isAbsolute()) {
+                logger.warn("Absolute URI required but provided URI '{}' is non-absolute. ", uriString);
+                return new HttpResponse(HttpStatus.NOT_ACCEPTABLE_406, "Absolute URI required");
+            }
+            final Builder request = client.target(targetUri).request(MediaType.APPLICATION_JSON);
 
             final Response content = request.post(Entity.entity(body, MediaType.APPLICATION_JSON));
 
@@ -103,6 +112,8 @@ public class HttpRequest implements AutoCloseable {
             // as well
         } catch (IOException | IllegalStateException | IllegalArgumentException | ProcessingException e) {
             return new HttpResponse(HttpStatus.SERVICE_UNAVAILABLE_503, e.getMessage());
+        } catch (URISyntaxException e) {
+            return new HttpResponse(HttpStatus.NOT_ACCEPTABLE_406, e.getMessage());
         }
     }
 
index 056756faa937c90da9e367cdb82f5b6af08948b8..594b76bdf8f5de7f26903e2d01ad558880df80aa 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.servlet.ServletException;
+import javax.ws.rs.client.ClientBuilder;
 
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -82,19 +83,20 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
      * This is the context created in the activate method (and nulled in the deactivate method) that will provide the
      * context to all services for all servlets
      */
-    private @Nullable ServiceContext context;
+    private final ServiceContext context;
 
     // The following services are set by openHAB via the getter/setters
-    private @Nullable HttpService httpService;
-    private @Nullable ItemRegistry itemRegistry;
-    private @Nullable BindingInfoRegistry bindingInfoRegistry;
-    private @Nullable ThingRegistry thingRegistry;
-    private @Nullable ThingTypeRegistry thingTypeRegistry;
-    private @Nullable ItemChannelLinkRegistry itemChannelLinkRegistry;
-    private @Nullable ChannelTypeRegistry channelTypeRegistry;
-    private @Nullable MDNSClient mdnsClient;
-    private @Nullable EventPublisher eventPublisher;
-    private @Nullable NetworkAddressService networkAddressService;
+    private final HttpService httpService;
+    private final ItemRegistry itemRegistry;
+    private final BindingInfoRegistry bindingInfoRegistry;
+    private final ThingRegistry thingRegistry;
+    private final ThingTypeRegistry thingTypeRegistry;
+    private final ItemChannelLinkRegistry itemChannelLinkRegistry;
+    private final ChannelTypeRegistry channelTypeRegistry;
+    private final MDNSClient mdnsClient;
+    private final EventPublisher eventPublisher;
+    private final NetworkAddressService networkAddressService;
+    private final ClientBuilder clientBuilder;
 
     /** The main dashboard servlet. Only created in the activate method (and disposed of in the deactivate method) */
     private @Nullable NeeoDashboardServlet dashboardServlet;
@@ -136,238 +138,24 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
         }
     };
 
-    /**
-     * The event filter to apply to this service
-     */
-    private final EventFilter eventFilter = event -> {
-        logger.trace("apply: {}", event);
-
-        for (NeeoBrainServlet ns : servlets) {
-            final List<EventFilter> efs = ns.getEventFilters();
-            if (efs != null) {
-                for (EventFilter ef : efs) {
-                    if (ef.apply(event)) {
-                        logger.trace("apply (true): {}", event);
-                        return true;
-                    }
-                }
-            }
-        }
-
-        logger.trace("apply (false): {}", event);
-        return false;
-    };
-
-    /**
-     * Sets the http service.
-     *
-     * @param httpService the non-null http service
-     */
-    @Reference
-    public void setHttpService(HttpService httpService) {
-        Objects.requireNonNull(httpService, "httpService cannot be null");
+    @Activate
+    public NeeoService(ComponentContext componentContext, @Reference HttpService httpService,
+            @Reference ItemRegistry itemRegistry, @Reference ThingRegistry thingRegistry,
+            @Reference BindingInfoRegistry bindingInfoRegistry, @Reference ChannelTypeRegistry channelTypeRegistry,
+            @Reference ThingTypeRegistry thingTypeRegistry, @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
+            @Reference MDNSClient mdnsClient, @Reference EventPublisher eventPublisher,
+            @Reference NetworkAddressService networkAddressService, @Reference ClientBuilder clientBuilder) {
         this.httpService = httpService;
-    }
-
-    /**
-     * Unset http service.
-     *
-     * @param httpService the http service (ignored)
-     */
-    public void unsetHttpService(HttpService httpService) {
-        this.httpService = null;
-    }
-
-    /**
-     * Sets the item registry.
-     *
-     * @param itemRegistry the non-null item registry
-     */
-    @Reference
-    public void setItemRegistry(ItemRegistry itemRegistry) {
-        Objects.requireNonNull(itemRegistry, "itemRegistry cannot be null");
         this.itemRegistry = itemRegistry;
-    }
-
-    /**
-     * Unset item registry.
-     *
-     * @param itemRegistry the item registry (ignored)
-     */
-    public void unsetItemRegistry(ItemRegistry itemRegistry) {
-        this.itemRegistry = null;
-    }
-
-    /**
-     * Sets the binding info registry.
-     *
-     * @param bindingInfoRegistry the non-null binding info registry
-     */
-    @Reference
-    public void setBindingInfoRegistry(BindingInfoRegistry bindingInfoRegistry) {
-        Objects.requireNonNull(bindingInfoRegistry, "bindingInfoRegistry cannot be null");
         this.bindingInfoRegistry = bindingInfoRegistry;
-    }
-
-    /**
-     * Unset binding info registry.
-     *
-     * @param bindingInfoRegistry the binding info registry (ignored)
-     */
-    public void unsetBindingInfoRegistry(BindingInfoRegistry bindingInfoRegistry) {
-        this.bindingInfoRegistry = null;
-    }
-
-    /**
-     * Sets the thing registry.
-     *
-     * @param thingRegistry the non-null thing registry
-     */
-    @Reference
-    public void setThingRegistry(ThingRegistry thingRegistry) {
-        Objects.requireNonNull(thingRegistry, "thingRegistry cannot be null");
+        this.channelTypeRegistry = channelTypeRegistry;
         this.thingRegistry = thingRegistry;
-    }
-
-    /**
-     * Unset thing registry.
-     *
-     * @param thingRegistry the thing registry (ignored)
-     */
-    public void unsetThingRegistry(ThingRegistry thingRegistry) {
-        this.thingRegistry = null;
-    }
-
-    /**
-     * Sets the thing type registry.
-     *
-     * @param thingTypeRegistry the non-null thing type registry
-     */
-    @Reference
-    public void setThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
-        Objects.requireNonNull(thingTypeRegistry, "thingTypeRegistry cannot be null");
         this.thingTypeRegistry = thingTypeRegistry;
-    }
-
-    /**
-     * Unset thing type registry.
-     *
-     * @param thingTypeRegistry the thing type registry (ignored)
-     */
-    public void unsetThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
-        this.thingTypeRegistry = null;
-    }
-
-    /**
-     * Sets the item channel link registry.
-     *
-     * @param itemChannelLinkRegistry the non-null item channel link registry
-     */
-    @Reference
-    public void setItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
-        Objects.requireNonNull(itemChannelLinkRegistry, "itemChannelLinkRegistry cannot be null");
         this.itemChannelLinkRegistry = itemChannelLinkRegistry;
-    }
-
-    /**
-     * Unset item channel link registry.
-     *
-     * @param itemChannelLinkRegistry the item channel link registry (ignored)
-     */
-    public void unsetItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
-        this.itemChannelLinkRegistry = null;
-    }
-
-    /**
-     * Sets the channel type registry.
-     *
-     * @param channelTypeRegistry the non-null channel type registry
-     */
-    @Reference
-    public void setChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
-        Objects.requireNonNull(channelTypeRegistry, "channelTypeRegistry cannot be null");
-        this.channelTypeRegistry = channelTypeRegistry;
-    }
-
-    /**
-     * Unset channel type registry.
-     *
-     * @param channelTypeRegistry the channel type registry (ignored)
-     */
-    public void unsetChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
-        this.channelTypeRegistry = null;
-    }
-
-    /**
-     * Sets the MDNS client.
-     *
-     * @param mdnsClient the non-null MDNS client
-     */
-    @Reference
-    public void setMDNSClient(MDNSClient mdnsClient) {
-        Objects.requireNonNull(mdnsClient, "mdnsClient cannot be null");
         this.mdnsClient = mdnsClient;
-    }
-
-    /**
-     * Unset MDNS client.
-     *
-     * @param mdnsClient the mdns client (ignored)
-     */
-    public void unsetMDNSClient(MDNSClient mdnsClient) {
-        this.mdnsClient = null;
-    }
-
-    /**
-     * Sets the event publisher.
-     *
-     * @param eventPublisher the new event publisher
-     */
-    @Reference
-    public void setEventPublisher(EventPublisher eventPublisher) {
-        Objects.requireNonNull(eventPublisher, "eventPublisher cannot be null");
         this.eventPublisher = eventPublisher;
-    }
-
-    /**
-     * Unset event publisher.
-     *
-     * @param eventPublisher the event publisher (ignored)
-     */
-    public void unsetEventPublisher(EventPublisher eventPublisher) {
-        this.eventPublisher = null;
-    }
-
-    /**
-     * Sets the network address service
-     *
-     * @param networkAddressService the network address service
-     */
-    @Reference
-    public void setNetworkAddressService(NetworkAddressService networkAddressService) {
-        Objects.requireNonNull(networkAddressService, "networkAddressService cannot be null");
         this.networkAddressService = networkAddressService;
-        networkAddressService.addNetworkAddressChangeListener(this);
-    }
-
-    /**
-     * Unsets network address service
-     *
-     * @param networkAddressService address service
-     */
-    public void unsetNetworkAddressService(NetworkAddressService networkAddressService) {
-        networkAddressService.removeNetworkAddressChangeListener(this);
-        this.networkAddressService = null;
-    }
-
-    /**
-     * Activates this service. The activation will start up the brain discovery service and register the dashboard tile
-     *
-     * @param componentContext the non-null component context
-     */
-    @Activate
-    public void activate(final ComponentContext componentContext) {
-        Objects.requireNonNull(componentContext, "componentContext cannot be null");
+        this.clientBuilder = clientBuilder;
 
         logger.debug("Neeo Service activated");
         final ServiceContext localContext = new ServiceContext(componentContext, validate(httpService, "httpService"),
@@ -378,7 +166,7 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
                 validate(eventPublisher, "eventPublisher"), validate(networkAddressService, "networkAddressService"));
 
         context = localContext;
-        discovery = new MdnsBrainDiscovery(localContext);
+        discovery = new MdnsBrainDiscovery(localContext, clientBuilder);
         discovery.addListener(discoveryListener);
 
         try {
@@ -402,6 +190,28 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
         }
     }
 
+    /**
+     * The event filter to apply to this service
+     */
+    private final EventFilter eventFilter = event -> {
+        logger.trace("apply: {}", event);
+
+        for (NeeoBrainServlet ns : servlets) {
+            final List<EventFilter> efs = ns.getEventFilters();
+            if (efs != null) {
+                for (EventFilter ef : efs) {
+                    if (ef.apply(event)) {
+                        logger.trace("apply (true): {}", event);
+                        return true;
+                    }
+                }
+            }
+        }
+
+        logger.trace("apply (false): {}", event);
+        return false;
+    };
+
     /**
      * Helper method to validate that the specific item wasn't null and convert it's type to a non-nullable type
      *
@@ -441,8 +251,6 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
                 NeeoUtil.close(servlet);
             }
             servlets.clear();
-
-            context = null;
         }
 
         if (dashboardServlet != null) {
@@ -472,7 +280,7 @@ public class NeeoService implements EventSubscriber, NetworkAddressChangeListene
                         servletUrl);
                 try {
                     final NeeoBrainServlet newServlet = NeeoBrainServlet.create(localContext, servletUrl,
-                            sysInfo.getHostname(), ipAddress);
+                            sysInfo.getHostname(), ipAddress, clientBuilder);
                     servlets.add(newServlet);
 
                     localContext.getHttpService().registerServlet(servletUrl, newServlet, new Hashtable<>(),
index a794eadd55c2b259142f1a1695523207fe63cbc4..8899996199248ad57d9ed353dac07b8d4c5c1bc2 100644 (file)
@@ -27,6 +27,8 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.ws.rs.client.ClientBuilder;
+
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -68,6 +70,8 @@ public class NeeoApi implements AutoCloseable {
     /** The brain's IP address */
     private final String brainIpAddress;
 
+    private final ClientBuilder clientBuilder;
+
     /** The URL of the brain */
     private final String brainUrl;
 
@@ -107,8 +111,7 @@ public class NeeoApi implements AutoCloseable {
     private final AtomicReference<@Nullable ScheduledFuture<?>> checkStatus = new AtomicReference<>(null);
 
     /** The {@link HttpRequest} used for making requests */
-    private final AtomicReference<HttpRequest> request = new AtomicReference<>(new HttpRequest());
-
+    private final AtomicReference<HttpRequest> request;
     /** Whether the brain is currently connected */
     private final AtomicBoolean connected = new AtomicBoolean(false);
 
@@ -120,21 +123,25 @@ public class NeeoApi implements AutoCloseable {
      * @param context the non-null {@link ServiceContext}
      * @throws IOException if an exception occurs connecting to the brain
      */
-    public NeeoApi(String ipAddress, String brainId, ServiceContext context) throws IOException {
+    public NeeoApi(String ipAddress, String brainId, ServiceContext context, ClientBuilder clientBuilder)
+            throws IOException {
         NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
         NeeoUtil.requireNotEmpty(brainId, "brainId cannot be empty");
         Objects.requireNonNull(context, "context cannot be null");
 
         this.brainIpAddress = ipAddress;
         this.brainId = brainId;
+        this.clientBuilder = clientBuilder;
         this.brainUrl = NeeoConstants.PROTOCOL + (ipAddress.startsWith("/") ? ipAddress.substring(1) : ipAddress) + ":"
                 + NeeoConstants.DEFAULT_BRAIN_PORT;
-        deviceKeys = new NeeoDeviceKeys(brainUrl);
+        deviceKeys = new NeeoDeviceKeys(brainUrl, clientBuilder);
+
+        request = new AtomicReference<>(new HttpRequest(clientBuilder));
 
-        this.systemInfo = getSystemInfo(ipAddress);
+        this.systemInfo = getSystemInfo(ipAddress, clientBuilder);
 
         String name = brainId;
-        try (HttpRequest request = new HttpRequest()) {
+        try (HttpRequest request = new HttpRequest(clientBuilder)) {
             logger.debug("Getting existing device mappings from {}{}", brainUrl, NeeoConstants.PROJECTS_HOME);
             final HttpResponse resp = request.sendGetCommand(brainUrl + NeeoConstants.PROJECTS_HOME);
             if (resp.getHttpCode() != HttpStatus.OK_200) {
@@ -196,12 +203,12 @@ public class NeeoApi implements AutoCloseable {
      * @return the non-null {@link NeeoSystemInfo} for the address
      * @throws IOException Signals that an I/O exception has occurred or the URL is not a brain
      */
-    public static NeeoSystemInfo getSystemInfo(String ipAddress) throws IOException {
+    public static NeeoSystemInfo getSystemInfo(String ipAddress, ClientBuilder clientBuilder) throws IOException {
         NeeoUtil.requireNotEmpty(ipAddress, "ipAddress cannot be empty");
         final String sysInfo = NeeoConstants.PROTOCOL + (ipAddress.startsWith("/") ? ipAddress.substring(1) : ipAddress)
                 + ":" + NeeoConstants.DEFAULT_BRAIN_PORT + NeeoConstants.SYSTEMINFO;
 
-        try (HttpRequest req = new HttpRequest()) {
+        try (HttpRequest req = new HttpRequest(clientBuilder)) {
             final HttpResponse res = req.sendGetCommand(sysInfo);
             if (res.getHttpCode() == HttpStatus.OK_200) {
                 return Objects.requireNonNull(GSON.fromJson(res.getContent(), NeeoSystemInfo.class));
@@ -387,7 +394,7 @@ public class NeeoApi implements AutoCloseable {
         try {
             setConnected(false);
 
-            NeeoUtil.close(request.getAndSet(new HttpRequest()));
+            NeeoUtil.close(request.getAndSet(new HttpRequest(clientBuilder)));
 
             NeeoUtil.checkInterrupt();
             registerApi();
index 8cefd7acbe3d990e294a2f534a5ca2ff88564262..9a82b4127d7a2f233095c2d5a2ff49342f2a3a71 100644 (file)
@@ -16,6 +16,8 @@ import java.io.IOException;
 import java.net.InetAddress;
 import java.util.Objects;
 
+import javax.ws.rs.client.ClientBuilder;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.io.neeo.internal.models.BrainStatus;
 import org.openhab.io.neeo.internal.servletservices.NeeoBrainSearchService;
@@ -44,8 +46,9 @@ public class NeeoBrainServlet extends AbstractServlet {
      * @param servletUrl the non-null, non-empty servlet URL
      * @param api the non-null API
      */
-    private NeeoBrainServlet(ServiceContext context, String servletUrl, NeeoApi api) {
-        super(context, servletUrl, new NeeoBrainSearchService(context), new NeeoBrainService(api, context));
+    private NeeoBrainServlet(ServiceContext context, String servletUrl, NeeoApi api, ClientBuilder clientBuilder) {
+        super(context, servletUrl, new NeeoBrainSearchService(context),
+                new NeeoBrainService(api, context, clientBuilder));
 
         Objects.requireNonNull(context, "context cannot be null");
         NeeoUtil.requireNotEmpty(servletUrl, "servletUrl cannot be empty");
@@ -65,16 +68,16 @@ public class NeeoBrainServlet extends AbstractServlet {
      * @throws IOException when an exception occurs contacting the brain
      */
     public static NeeoBrainServlet create(ServiceContext context, String servletUrl, String brainId,
-            InetAddress ipAddress) throws IOException {
+            InetAddress ipAddress, ClientBuilder clientBuilder) throws IOException {
         Objects.requireNonNull(context, "context cannot be null");
         NeeoUtil.requireNotEmpty(servletUrl, "servletUrl cannot be empty");
         NeeoUtil.requireNotEmpty(brainId, "brainId cannot be empty");
         Objects.requireNonNull(ipAddress, "ipAddress cannot be null");
 
-        final NeeoApi api = new NeeoApi(ipAddress.getHostAddress(), brainId, context);
+        final NeeoApi api = new NeeoApi(ipAddress.getHostAddress(), brainId, context, clientBuilder);
         api.start();
 
-        return new NeeoBrainServlet(context, servletUrl, api);
+        return new NeeoBrainServlet(context, servletUrl, api, clientBuilder);
     }
 
     /**
index 89b9b12939b45e57494bc5667ed73c3ffe6134e1..b726a9e81ff88cf79b7783f9a64ba15383022a6c 100644 (file)
@@ -21,6 +21,8 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.ws.rs.client.ClientBuilder;
+
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jetty.http.HttpStatus;
@@ -52,15 +54,18 @@ public class NeeoDeviceKeys {
     /** The brain's url */
     private final String brainUrl;
 
+    private final ClientBuilder clientBuilder;
+
     /**
      * Creates the object from the context and brainUrl
      *
      * @param brainUrl the non-empty brain url
      */
-    NeeoDeviceKeys(String brainUrl) {
+    NeeoDeviceKeys(String brainUrl, ClientBuilder clientBuilder) {
         NeeoUtil.requireNotEmpty(brainUrl, "brainUrl cannot be empty");
 
         this.brainUrl = brainUrl;
+        this.clientBuilder = clientBuilder;
     }
 
     /**
@@ -69,7 +74,7 @@ public class NeeoDeviceKeys {
      * @throws IOException Signals that an I/O exception has occurred.
      */
     void refresh() throws IOException {
-        try (HttpRequest request = new HttpRequest()) {
+        try (HttpRequest request = new HttpRequest(clientBuilder)) {
             logger.debug("Getting existing device mappings from {}{}", brainUrl, NeeoConstants.PROJECTS_HOME);
             final HttpResponse resp = request.sendGetCommand(brainUrl + NeeoConstants.PROJECTS_HOME);
             if (resp.getHttpCode() != HttpStatus.OK_200) {
index f67cdb2d84a203d7658c68252ea5cb285eaa72b2..4f052dc4e2ba7075689d87a7720aa0cf6ebb8c4a 100644 (file)
@@ -34,6 +34,7 @@ import java.util.stream.Collectors;
 import javax.jmdns.ServiceEvent;
 import javax.jmdns.ServiceInfo;
 import javax.jmdns.ServiceListener;
+import javax.ws.rs.client.ClientBuilder;
 
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -106,14 +107,17 @@ public class MdnsBrainDiscovery extends AbstractBrainDiscovery {
     /** The file we store definitions in */
     private final File file = new File(NeeoConstants.FILENAME_DISCOVEREDBRAINS);
 
+    private final ClientBuilder clientBuilder;
+
     /**
      * Creates the MDNS brain discovery from the given {@link ServiceContext}
      *
      * @param context the non-null service context
      */
-    public MdnsBrainDiscovery(ServiceContext context) {
+    public MdnsBrainDiscovery(ServiceContext context, ClientBuilder clientBuilder) {
         Objects.requireNonNull(context, "context cannot be null");
         this.context = context;
+        this.clientBuilder = clientBuilder;
     }
 
     /**
@@ -250,7 +254,7 @@ public class MdnsBrainDiscovery extends AbstractBrainDiscovery {
 
         NeeoSystemInfo sysInfo;
         try {
-            sysInfo = NeeoApi.getSystemInfo(brainInfo.getValue().toString());
+            sysInfo = NeeoApi.getSystemInfo(brainInfo.getValue().toString(), clientBuilder);
         } catch (IOException e) {
             // We can get an MDNS notification BEFORE the brain is ready to process.
             // if that happens, we'll get an IOException (usually bad gateway message), schedule another attempt to get
@@ -299,7 +303,7 @@ public class MdnsBrainDiscovery extends AbstractBrainDiscovery {
 
         try {
             final InetAddress addr = InetAddress.getByName(ipAddress);
-            final NeeoSystemInfo sysInfo = NeeoApi.getSystemInfo(ipAddress);
+            final NeeoSystemInfo sysInfo = NeeoApi.getSystemInfo(ipAddress, clientBuilder);
             logger.debug("Manually adding brain ({}) with system information: {}", ipAddress, sysInfo);
 
             systemsLock.lock();
index bac60524fb69b87896c76567f0457829437767c4..fdfa6c5168888cc19df480f9791e262cf088401e 100644 (file)
@@ -47,8 +47,8 @@ public class HttpRequest implements AutoCloseable {
     /**
      * Instantiates a new request
      */
-    public HttpRequest() {
-        client = ClientBuilder.newClient();
+    public HttpRequest(ClientBuilder clientBuilder) {
+        client = clientBuilder.build();
 
         if (logger.isDebugEnabled()) {
             client.register(new LoggingFilter(new Slf4LoggingAdapter(logger), true));
index ef63125bddfae312697bdc47b4ed6eb942caf60e..a4bdb083bd2ec4c0685fefb99e4f38c9fdcd5330 100644 (file)
@@ -21,6 +21,7 @@ import java.util.concurrent.ScheduledExecutorService;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.ClientBuilder;
 
 import org.apache.commons.lang.StringUtils;
 import org.eclipse.jdt.annotation.NonNull;
@@ -90,7 +91,7 @@ public class NeeoBrainService extends DefaultServletService {
     private final ServiceContext context;
 
     /** The HTTP request */
-    private final HttpRequest request = new HttpRequest();
+    private final HttpRequest request;
 
     /** The scheduler to use to schedule recipe execution */
     private final ScheduledExecutorService scheduler = ThreadPoolManager
@@ -114,7 +115,7 @@ public class NeeoBrainService extends DefaultServletService {
      * @param api the non-null api
      * @param context the non-null context
      */
-    public NeeoBrainService(NeeoApi api, ServiceContext context) {
+    public NeeoBrainService(NeeoApi api, ServiceContext context, ClientBuilder clientBuilder) {
         Objects.requireNonNull(api, "api cannot be null");
         Objects.requireNonNull(context, "context cannot be null");
 
@@ -125,6 +126,7 @@ public class NeeoBrainService extends DefaultServletService {
         scheduler.execute(() -> {
             resendState();
         });
+        request = new HttpRequest(clientBuilder);
     }
 
     /**