2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.homematic.internal.communicator.server;
15 import java.io.IOException;
16 import java.io.PrintWriter;
17 import java.net.InetSocketAddress;
19 import javax.servlet.ServletException;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22 import javax.xml.parsers.ParserConfigurationException;
24 import org.eclipse.jetty.server.Request;
25 import org.eclipse.jetty.server.Server;
26 import org.eclipse.jetty.server.handler.AbstractHandler;
27 import org.openhab.binding.homematic.internal.common.HomematicConfig;
28 import org.openhab.binding.homematic.internal.communicator.message.RpcRequest;
29 import org.openhab.binding.homematic.internal.communicator.message.XmlRpcRequest;
30 import org.openhab.binding.homematic.internal.communicator.message.XmlRpcResponse;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.xml.sax.SAXException;
36 * Reads a XML-RPC message and handles the method call.
38 * @author Gerhard Riegler - Initial contribution
40 public class XmlRpcServer implements RpcServer {
41 private final Logger logger = LoggerFactory.getLogger(XmlRpcServer.class);
43 private static final String XML_EMPTY_STRING = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<methodResponse><params><param><value></value></param></params></methodResponse>";
44 private static final String XML_EMPTY_ARRAY = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<methodResponse><params><param><value><array><data></data></array></value></param></params></methodResponse>";
45 private static final String XML_EMPTY_EVENT_LIST = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<methodResponse><params><param><value><array><data><value>event</value></data></array></value></param></params></methodResponse>";
47 private Server xmlRpcHTTPD;
48 private HomematicConfig config;
49 private RpcResponseHandler<String> rpcResponseHander;
50 private final ResponseHandler jettyResponseHandler = new ResponseHandler();
52 public XmlRpcServer(RpcEventListener listener, HomematicConfig config) {
54 this.rpcResponseHander = new RpcResponseHandler<String>(listener) {
57 protected String getEmptyStringResult() {
58 return XML_EMPTY_STRING;
62 protected String getEmptyEventListResult() {
63 return XML_EMPTY_EVENT_LIST;
67 protected String getEmptyArrayResult() {
68 return XML_EMPTY_ARRAY;
72 protected RpcRequest<String> createRpcRequest() {
73 return new XmlRpcRequest(null, XmlRpcRequest.TYPE.RESPONSE);
79 public void start() throws IOException {
80 logger.debug("Initializing XML-RPC server at port {}", config.getXmlCallbackPort());
82 InetSocketAddress callbackAddress = new InetSocketAddress(config.getXmlCallbackPort());
83 xmlRpcHTTPD = new Server(callbackAddress);
84 xmlRpcHTTPD.setHandler(jettyResponseHandler);
88 if (logger.isTraceEnabled()) {
89 xmlRpcHTTPD.dumpStdErr();
91 } catch (Exception e) {
92 throw new IOException("Jetty start failed", e);
97 public void shutdown() {
98 if (xmlRpcHTTPD != null) {
99 logger.debug("Stopping XML-RPC server");
102 } catch (Exception ex) {
103 logger.error("{}", ex.getMessage(), ex);
109 * Response handler for Jetty implementing a XML-RPC server
111 * @author Martin Herbst
113 private class ResponseHandler extends AbstractHandler {
115 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
116 throws IOException, ServletException {
117 response.setContentType("text/xml;charset=ISO-8859-1");
118 response.setStatus(HttpServletResponse.SC_OK);
119 final PrintWriter respWriter = response.getWriter();
121 XmlRpcResponse xmlResponse = new XmlRpcResponse(request.getInputStream(), config.getEncoding());
122 if (logger.isTraceEnabled()) {
123 logger.trace("Server parsed XmlRpcMessage:\n{}", xmlResponse);
125 final String returnValue = rpcResponseHander.handleMethodCall(xmlResponse.getMethodName(),
126 xmlResponse.getResponseData());
127 if (logger.isTraceEnabled()) {
128 logger.trace("Server XmlRpcResponse:\n{}", returnValue);
130 respWriter.println(returnValue);
131 } catch (SAXException | ParserConfigurationException ex) {
132 logger.error("{}", ex.getMessage(), ex);
133 respWriter.println(XML_EMPTY_STRING);
135 baseRequest.setHandled(true);