]> git.basschouten.com Git - openhab-addons.git/blob
a5aee9df6f21e5b0239cbcc64c1b3f844bfecb4d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.gpstracker.internal.provider;
14
15 import java.io.BufferedReader;
16 import java.util.Collections;
17 import java.util.List;
18
19 import javax.servlet.http.HttpServlet;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.gpstracker.internal.discovery.TrackerDiscoveryService;
26 import org.openhab.binding.gpstracker.internal.handler.TrackerHandler;
27 import org.openhab.binding.gpstracker.internal.message.MessageUtil;
28 import org.openhab.binding.gpstracker.internal.message.dto.LocationMessage;
29 import org.openhab.binding.gpstracker.internal.message.dto.TransitionMessage;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Abstract callback servlet used by the trackers.
35  *
36  * @author Gabor Bicskei - Initial contribution
37  */
38 @NonNullByDefault
39 public abstract class AbstractCallbackServlet extends HttpServlet {
40
41     private static final long serialVersionUID = -2725161358635927815L;
42
43     /**
44      * Class logger
45      */
46     private final Logger logger = LoggerFactory.getLogger(AbstractCallbackServlet.class);
47
48     /**
49      * Discovery service to handle new trackers
50      */
51     private TrackerDiscoveryService discoveryService;
52
53     /**
54      * Utility to process messages
55      */
56     private MessageUtil messageUtil = new MessageUtil();
57
58     /**
59      * Tracker registry
60      */
61     private TrackerRegistry trackerRegistry;
62
63     /**
64      * Constructor called at binding startup.
65      *
66      * @param discoveryService Discovery service for new trackers.
67      * @param trackerRegistry Tracker handler registry
68      */
69     protected AbstractCallbackServlet(TrackerDiscoveryService discoveryService, TrackerRegistry trackerRegistry) {
70         this.discoveryService = discoveryService;
71         this.trackerRegistry = trackerRegistry;
72     }
73
74     protected abstract String getPath();
75
76     /**
77      * Process the HTTP requests from tracker applications
78      *
79      * @param req HTTP request
80      * @param resp HTTP response
81      */
82     @Override
83     protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
84         try {
85             StringBuilder jb = new StringBuilder();
86             BufferedReader reader = req.getReader();
87
88             String line;
89             while ((line = reader.readLine()) != null) {
90                 jb.append(line);
91             }
92
93             // clear the whitespaces from the message
94             String json = jb.toString().replaceAll("\\p{Z}", "");
95             logger.debug("Post message received from {} tracker: {}", getProvider(), json);
96
97             LocationMessage message = messageUtil.fromJson(json);
98             if (message != null) {
99                 List<? extends LocationMessage> response = processMessage(message);
100                 if (response != null) {
101                     resp.getWriter().append(messageUtil.toJson(response)).flush();
102                 }
103             }
104             resp.setStatus(HttpServletResponse.SC_OK);
105         } catch (Exception e) {
106             logger.error("Error processing location report:", e);
107             resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
108         }
109     }
110
111     /**
112      * Process the message received by the servlet. If the tracker is unknown the discovery service is notified
113      * so that the next search will pop up the new tracker as result.
114      *
115      * @param message The message
116      * @return Response message.
117      */
118     private List<? extends LocationMessage> processMessage(LocationMessage message) {
119         String trackerId = message.getTrackerId();
120         if (!trackerId.isEmpty()) {
121             TrackerHandler recorder = getHandlerById(trackerId);
122             if (recorder != null) {
123                 if (message instanceof TransitionMessage transitionMessage) {
124                     recorder.doTransition(transitionMessage);
125                 } else {
126                     recorder.updateLocation(message);
127                 }
128                 return recorder.getNotifications();
129             } else {
130                 logger.debug("There is no handler for tracker {}. Check the inbox for the new tracker.", trackerId);
131             }
132         } else {
133             logger.debug("Message without tracker id. Dropping message. {}", messageUtil.toJson(message));
134         }
135         return Collections.emptyList();
136     }
137
138     /**
139      * Find handler for tracker. If the handler does not exist it is registered with discovery service.
140      *
141      * @param trackerId Tracker id.
142      * @return Handler for tracker.
143      */
144     private @Nullable TrackerHandler getHandlerById(String trackerId) {
145         TrackerHandler handler = trackerRegistry.getTrackerHandler(trackerId);
146         if (handler == null) {
147             // handler was not found - adding the tracker to discovery service.
148             discoveryService.addTracker(trackerId);
149         } else {
150             return handler;
151         }
152
153         return null;
154     }
155
156     protected abstract String getProvider();
157 }