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

Last change on this file since 40 was 40, checked in by bart, 3 years ago

Added python SimpleRunner GUI

File size: 4.7 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 if (reporter == null)
55 throw new IllegalArgumentException("reporter must be not null");
56 this.log = reporter;
57 }
58
59 @OnOpen
60 public void start(Session session) throws IOException {
61 this.session = session;
62 this.outstream = new SendBuffer(session.getBasicRemote(), log);
63
64 repo = getRepo();
65 changeListener = new Listener<String>() {
66 @Override
67 public void notifyChange(String data) {
68 sendUpdatedParties();
69 }
70 };
71 repo.addListener(changeListener);
72
73 sendUpdatedParties();
74 }
75
76 /**
77 * Send the currently available parties to the client.
78 *
79 * @throws IOException
80 */
81 private void sendUpdatedParties() {
82 log.log(Level.INFO, "sending updated parties list1");
83 String ip = DEFAULT_ADDRESS; // default if something fails
84 try {
85 ip = getIpAddressAndPort() + "/" + getServerName();
86 } catch (MalformedObjectNameException | UnknownHostException e1) {
87 log.log(Level.SEVERE,
88 "Can't get proper server name and port, reverting to "
89 + DEFAULT_ADDRESS,
90 e1);
91 }
92 try {
93 List<GeneralPartyInfo> list = new LinkedList<>();
94 for (AvailableParty party : repo.list()) {
95 URI uri = new URI("http://" + ip + "/run/" + party.getName());
96 list.add(new GeneralPartyInfo(uri, party.getCapabilities(),
97 party.getDescription()));
98 }
99 String text = Jackson.instance().writeValueAsString(list);
100 outstream.send(text);
101 } catch (IOException | URISyntaxException e) {
102 log.log(Level.SEVERE, "Bug sending updated parties list", e);
103 }
104 }
105
106 @OnClose
107 public void onClose() throws IOException {
108 repo.removeListener(changeListener);
109 outstream.stop();
110 }
111
112 @OnError
113 public void onError(Throwable t) throws Throwable {
114 if (t instanceof IOException && "Broken pipe".equals(t.getMessage())) {
115 log.log(Level.INFO, "Socket pipe broke:" + session);
116 } else {
117 log.log(Level.SEVERE,
118 "Tomcat reported an error on the connection:" + session, t);
119 }
120 }
121
122 /**
123 * FactoryMethod for testing
124 *
125 * @return RunningPartiesRepo
126 */
127 protected AvailablePartiesRepo getRepo() {
128 return AvailablePartiesRepo.instance();
129 }
130
131 /**
132 *
133 * @return name of our service, eg "profilesserver"
134 */
135 private String getServerName() {
136 // typically something like /profilesserver/websocket/liststream
137 // profilesserver is the name we're looking for
138 return session.getRequestURI().getPath().split("/")[1]; // drop leading
139 // '/'
140 }
141
142 private String getIpAddressAndPort()
143 throws UnknownHostException, MalformedObjectNameException {
144 synchronized (hostport) {
145 if (hostport.isEmpty()) {
146 MBeanServer beanServer = ManagementFactory
147 .getPlatformMBeanServer();
148
149 Set<ObjectName> objectNames = beanServer.queryNames(
150 new ObjectName("*:type=Connector,*"),
151 Query.match(Query.attr("protocol"),
152 Query.value("HTTP/1.1")));
153
154 String host = InetAddress.getLocalHost().getHostAddress();
155 String port = objectNames.iterator().next()
156 .getKeyProperty("port");
157
158 hostport = host + ":" + port;
159 }
160 return hostport;
161 }
162
163 }
164
165}
Note: See TracBrowser for help on using the repository browser.