001package jmri.server.json.power; 002 003import static jmri.server.json.JSON.GET; 004import static jmri.server.json.JSON.NAME; 005import static jmri.server.json.JSON.PREFIX; 006import static jmri.server.json.power.JsonPowerServiceFactory.POWER; 007 008import com.fasterxml.jackson.databind.JsonNode; 009import java.beans.PropertyChangeEvent; 010import java.beans.PropertyChangeListener; 011import java.io.IOException; 012import java.util.HashSet; 013import java.util.Set; 014import jmri.InstanceManager; 015import jmri.JmriException; 016import jmri.PowerManager; 017import jmri.SystemConnectionMemo; 018import jmri.jmrix.SystemConnectionMemoManager; 019import jmri.server.json.JsonConnection; 020import jmri.server.json.JsonException; 021import jmri.server.json.JsonRequest; 022import jmri.server.json.JsonSocketService; 023 024/** 025 * 026 * @author Randall Wood 027 */ 028public class JsonPowerSocketService extends JsonSocketService<JsonPowerHttpService> implements PropertyChangeListener { 029 030 private final Set<PowerManager> listeningTo = new HashSet<>(); 031 032 public JsonPowerSocketService(JsonConnection connection) { 033 this(connection, new JsonPowerHttpService(connection.getObjectMapper())); 034 } 035 036 protected JsonPowerSocketService(JsonConnection connection, JsonPowerHttpService service) { 037 super(connection, service); 038 } 039 040 @Override 041 public void onMessage(String type, JsonNode data, JsonRequest request) throws IOException, JmriException, JsonException { 042 addListener(resolveManager(data)); 043 connection.sendMessage(service.doPost(type, data.path(NAME).asText(), data, request), request.id); 044 } 045 046 @Override 047 public void onList(String type, JsonNode data, JsonRequest request) throws JsonException, IOException { 048 InstanceManager.getList(PowerManager.class).forEach(this::addListener); 049 connection.sendMessage(service.doGetList(type, data, request), request.id); 050 } 051 052 private void addListener(PowerManager manager) { 053 if (manager != null && listeningTo.add(manager)) { 054 manager.addPropertyChangeListener(this); 055 } 056 } 057 058 /** 059 * Resolves the PowerManager targeted by a client message, using the same 060 * prefix → name → default fallback order as the HTTP service. Returns null 061 * if no PowerManager is configured. 062 */ 063 private PowerManager resolveManager(JsonNode data) { 064 String prefix = data.path(PREFIX).asText(); 065 if (!prefix.isEmpty()) { 066 SystemConnectionMemo memo = SystemConnectionMemoManager.getDefault() 067 .getSystemConnectionMemoForSystemPrefix(prefix); 068 if (memo != null && memo.provides(PowerManager.class)) { 069 return memo.get(PowerManager.class); 070 } 071 return null; 072 } 073 String name = data.path(NAME).asText(); 074 if (!name.isEmpty()) { 075 for (PowerManager pm : InstanceManager.getList(PowerManager.class)) { 076 if (pm.getUserName().equals(name)) { 077 return pm; 078 } 079 } 080 } 081 return InstanceManager.getNullableDefault(PowerManager.class); 082 } 083 084 @Override 085 public void propertyChange(PropertyChangeEvent evt) { 086 try { 087 try { 088 String name = ((PowerManager) evt.getSource()).getUserName(); 089 connection.sendMessage(service.doGet(POWER, name, connection.getObjectMapper().createObjectNode(), new JsonRequest(connection.getLocale(), connection.getVersion(), GET, 0)), 0); 090 } catch (JsonException ex) { 091 connection.sendMessage(ex.getJsonMessage(), 0); 092 } 093 } catch (IOException ex) { 094 // do nothing - we can only silently fail at this point 095 } 096 } 097 098 @Override 099 public void onClose() { 100 listeningTo.forEach(manager -> manager.removePropertyChangeListener(JsonPowerSocketService.this)); 101 } 102 103}