source: src/main/java/geniusweb/partiesserver/websocket/PartiesListSocket.java@ 27

Last change on this file since 27 was 27, checked in by bart, 4 years ago

some minor fixes

File size: 4.6 KB
Line 
1package geniusweb.partiesserver.websocket;
2
3import java.io.IOException;
4import java.lang.management.ManagementFactory;
5import java.net.InetAddress;
6import java.net.URI;
7import java.net.URISyntaxException;
8import java.net.UnknownHostException;
9import java.util.LinkedList;
10import java.util.List;
11import java.util.Set;
12import java.util.logging.Level;
13
14import javax.management.MBeanServer;
15import javax.management.MalformedObjectNameException;
16import javax.management.ObjectName;
17import javax.management.Query;
18import javax.websocket.OnClose;
19import javax.websocket.OnError;
20import javax.websocket.OnOpen;
21import javax.websocket.Session;
22import javax.websocket.server.ServerEndpoint;
23
24import geniusweb.partiesserver.Jackson;
25import geniusweb.partiesserver.repository.AvailablePartiesRepo;
26import geniusweb.partiesserver.repository.AvailableParty;
27import geniusweb.partiesserver.repository.GeneralPartyInfo;
28import tudelft.utilities.listener.Listener;
29import tudelft.utilities.logging.ReportToLogger;
30import tudelft.utilities.logging.Reporter;
31
32/**
33 * Returns a websocket that communicates the list of currently available
34 * (runnable) parties. Every time something changes, a new list of parties is
35 * sent.
36 */
37@ServerEndpoint("/available")
38public class PartiesListSocket {
39
40 private static final String DEFAULT_ADDRESS = "localhost:8080";
41 private final Reporter log;
42 private Listener<String> changeListener; // final, but only initialized in
43 // startSession.
44 private Session session;
45 private AvailablePartiesRepo repo;
46 private SendBuffer outstream;
47 private static transient String hostport = ""; // cache
48
49 public PartiesListSocket() {
50 this(new ReportToLogger("partiesserver"));
51 }
52
53 public PartiesListSocket(Reporter reporter) {
54 this.log = reporter;
55 }
56
57 @OnOpen
58 public void start(Session session) throws IOException {
59 this.session = session;
60 this.outstream = new SendBuffer(session.getBasicRemote(), log);
61
62 repo = getRepo();
63 changeListener = new Listener<String>() {
64 @Override
65 public void notifyChange(String data) {
66 sendUpdatedParties();
67 }
68 };
69 repo.addListener(changeListener);
70
71 sendUpdatedParties();
72 }
73
74 /**
75 * Send the currently available parties to the client.
76 *
77 * @throws IOException
78 */
79 private void sendUpdatedParties() {
80 System.out.println("sending updated parties list1");
81 String ip = DEFAULT_ADDRESS; // default if something fails
82 try {
83 ip = getIpAddressAndPort() + "/" + getServerName();
84 } catch (MalformedObjectNameException | UnknownHostException e1) {
85 log.log(Level.SEVERE,
86 "Can't get proper server name and port, reverting to "
87 + DEFAULT_ADDRESS,
88 e1);
89 }
90 try {
91 List<GeneralPartyInfo> list = new LinkedList<>();
92 for (AvailableParty party : repo.list()) {
93 URI uri = new URI("http://" + ip + "/run/" + party.getName());
94 list.add(new GeneralPartyInfo(uri, party.getCapabilities(),
95 party.getDescription()));
96 }
97 String text = Jackson.instance().writeValueAsString(list);
98 outstream.send(text);
99 } catch (IOException | URISyntaxException e) {
100 log.log(Level.SEVERE, "Bug sending updated parties list", e);
101 }
102 }
103
104 @OnClose
105 public void onClose() throws IOException {
106 repo.removeListener(changeListener);
107 outstream.stop();
108 }
109
110 @OnError
111 public void onError(Throwable t) throws Throwable {
112 if (t instanceof IOException && "Broken pipe".equals(t.getMessage())) {
113 log.log(Level.INFO, "Socket pipe broke:" + session);
114 } else {
115 log.log(Level.SEVERE,
116 "Tomcat reported an error on the connection:" + session, t);
117 }
118 }
119
120 /**
121 * FactoryMethod for testing
122 *
123 * @return RunningPartiesRepo
124 */
125 protected AvailablePartiesRepo getRepo() {
126 return AvailablePartiesRepo.instance();
127 }
128
129 /**
130 *
131 * @return name of our service, eg "profilesserver"
132 */
133 private String getServerName() {
134 // typically something like /profilesserver/websocket/liststream
135 // profilesserver is the name we're looking for
136 return session.getRequestURI().getPath().split("/")[1]; // drop leading
137 // '/'
138 }
139
140 private String getIpAddressAndPort()
141 throws UnknownHostException, MalformedObjectNameException {
142 synchronized (hostport) {
143 if (hostport.isEmpty()) {
144 MBeanServer beanServer = ManagementFactory
145 .getPlatformMBeanServer();
146
147 Set<ObjectName> objectNames = beanServer.queryNames(
148 new ObjectName("*:type=Connector,*"),
149 Query.match(Query.attr("protocol"),
150 Query.value("HTTP/1.1")));
151
152 String host = InetAddress.getLocalHost().getHostAddress();
153 String port = objectNames.iterator().next()
154 .getKeyProperty("port");
155
156 hostport = host + ":" + port;
157 }
158 return hostport;
159 }
160
161 }
162
163}
Note: See TracBrowser for help on using the repository browser.