001package jmri.server.json.util; 002 003import com.fasterxml.jackson.databind.JsonNode; 004import java.beans.PropertyChangeEvent; 005import java.beans.PropertyChangeListener; 006import java.io.IOException; 007import jmri.InstanceManager; 008import jmri.JmriException; 009import jmri.server.json.JSON; 010import jmri.server.json.JsonConnection; 011import jmri.server.json.JsonException; 012import jmri.server.json.JsonRequest; 013import jmri.server.json.JsonSocketService; 014import jmri.web.server.WebServerPreferences; 015import org.slf4j.Logger; 016import org.slf4j.LoggerFactory; 017 018/** 019 * 020 * @author Randall Wood 021 */ 022public class JsonUtilSocketService extends JsonSocketService<JsonUtilHttpService> { 023 024 private PropertyChangeListener rrNameListener; 025 private static final Logger log = LoggerFactory.getLogger(JsonUtilSocketService.class); 026 027 public JsonUtilSocketService(JsonConnection connection) { 028 super(connection, new JsonUtilHttpService(connection.getObjectMapper())); 029 } 030 031 /** 032 * Package protected method for unit testing that allows a test HTTP service 033 * to be used. 034 * 035 * @param connection the connection to use 036 * @param service the supporting HTTP service 037 */ 038 JsonUtilSocketService(JsonConnection connection, JsonUtilHttpService service) { 039 super(connection, service); 040 } 041 042 @Override 043 public void onMessage(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException { 044 String name = data.path(JSON.NAME).asText(); 045 switch (type) { 046 case JSON.LOCALE: 047 // do nothing - we only want to prevent an error at this point 048 break; 049 case JSON.PING: 050 this.connection.sendMessage(this.connection.getObjectMapper().createObjectNode().put(JSON.TYPE, JSON.PONG), request.id); 051 break; 052 case JSON.GOODBYE: 053 this.connection.sendMessage(this.connection.getObjectMapper().createObjectNode().put(JSON.TYPE, JSON.GOODBYE), request.id); 054 break; 055 case JSON.RAILROAD: 056 this.onRailroadNameMessage(type, data, request); 057 break; 058 default: 059 this.connection.sendMessage(this.service.doPost(type, name, data, request), request.id); 060 break; 061 } 062 } 063 064 private void onRailroadNameMessage(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException { 065 String name = data.path(JSON.NAME).asText(); 066 // Follow up handling a POST (change railroad name command) with the same answer as a GET (ask) 067 if (request.method.equals(JSON.POST)) { 068 log.debug("Processing change railroad name to {} from socket service", name); 069 this.connection.sendMessage(this.service.doPost(type, name, data, request), request.id); 070 } 071 this.connection.sendMessage(this.service.doGet(type, name, data, request), request.id); 072 this.rrNameListener = (PropertyChangeEvent evt) -> { 073 try { 074 this.handleRailroadChange(); 075 } catch (IOException ex) { 076 InstanceManager.getDefault(WebServerPreferences.class).removePropertyChangeListener(this.rrNameListener); 077 } 078 }; 079 InstanceManager.getOptionalDefault(WebServerPreferences.class).ifPresent(preferences -> preferences.addPropertyChangeListener(this.rrNameListener)); 080 } 081 082 @Override 083 public void onList(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException { 084 this.connection.sendMessage(this.service.doGetList(type, data, request), request.id); 085 } 086 087 @Override 088 public void onClose() { 089 InstanceManager.getOptionalDefault(WebServerPreferences.class).ifPresent(preferences -> preferences.removePropertyChangeListener(this.rrNameListener)); 090 } 091 092 private void handleRailroadChange() throws IOException { 093 try { 094 connection.sendMessage(service.doGet(JSON.RAILROAD, null, connection.getObjectMapper().createObjectNode(), new JsonRequest(this.connection.getLocale(), JSON.V5, JSON.GET, 0)), 0); 095 } catch (JsonException ex) { 096 this.connection.sendMessage(ex.getJsonMessage(), 0); 097 } 098 } 099}