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

Last change on this file since 14 was 5, checked in by bart, 5 years ago

Fixed performance issue with some computers

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