source: src/main/java/geniusweb/profilesserver/websocket/ProfilesListSocket.java@ 1

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

Initial Release

File size: 4.5 KB
Line 
1package geniusweb.profilesserver.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.HashMap;
10import java.util.List;
11import java.util.Map;
12import java.util.Set;
13import java.util.logging.Level;
14import java.util.stream.Collectors;
15
16import javax.management.MBeanServer;
17import javax.management.MalformedObjectNameException;
18import javax.management.ObjectName;
19import javax.management.Query;
20import javax.websocket.OnClose;
21import javax.websocket.OnError;
22import javax.websocket.OnOpen;
23import javax.websocket.Session;
24import javax.websocket.server.ServerEndpoint;
25
26import com.fasterxml.jackson.databind.ObjectMapper;
27
28import geniusweb.profilesserver.ProfilesFactory;
29import geniusweb.profilesserver.events.ChangeEvent;
30import tudelft.utilities.listener.Listener;
31import tudelft.utilities.logging.ReportToLogger;
32import tudelft.utilities.logging.Reporter;
33
34/**
35 * Returns a websocket that communicates the list of currently available domains
36 * and profiles. Every time something changes, a new list of domains and
37 * profiles is sent. For each new websocket the server will create one of this
38 * but they all share one {@link ProfilesFactory}.
39 */
40@ServerEndpoint("/websocket/liststream")
41public class ProfilesListSocket {
42
43 private final Reporter log;
44 /** following both final but set in {@link #start(Session)} */
45 private Session session;
46 private Listener<ChangeEvent> changeListener;
47
48 public ProfilesListSocket() {
49 this(new ReportToLogger("profilesserver"));
50 }
51
52 public ProfilesListSocket(ReportToLogger reportToLogger) {
53 this.log = reportToLogger;
54 }
55
56 @OnOpen
57 public void start(Session session) throws IOException {
58 this.session = session;
59 log.log(Level.INFO, "New connection " + session.getRequestURI());
60
61 sendupdatedProfiles();
62 changeListener = new Listener<ChangeEvent>() {
63
64 @Override
65 public void notifyChange(ChangeEvent data) {
66 try {
67 sendupdatedProfiles();
68 } catch (IOException e) {
69 e.printStackTrace();
70 }
71 }
72 };
73 Profiles.factory.addListener(changeListener);
74 }
75
76 /**
77 * Send the latest profiles to the client.
78 *
79 * @throws IOException
80 */
81 private void sendupdatedProfiles() throws IOException {
82 log.log(Level.FINER, "sending updated profiles");
83 session.getBasicRemote().sendText(
84 new ObjectMapper().writeValueAsString(getDomainsProfiles()));
85 }
86
87 /**
88 * @return list of domain and profile URIs, as a hashmap.
89 */
90 private Map<URI, List<URI>> getDomainsProfiles() {
91 Map<URI, List<URI>> allprofiles = new HashMap<>();
92 for (String domain : Profiles.factory.getDomains()) {
93 List<URI> profiles = Profiles.factory.getProfiles(domain).stream()
94 .map(profile -> makeURI(domain, profile.getName()))
95 .collect(Collectors.toList());
96 allprofiles.put(makeURI(domain, null), profiles);
97 }
98 return allprofiles;
99 }
100
101 /**
102 * @param domain the domain name.
103 * @param profile the profile name. If null, a ref to the the domain (no
104 * profile) is needed
105 * @return a URI where to get the given profile/domain.
106 */
107 private URI makeURI(String domain, String profile) {
108 try {
109 return new URI("ws://" + getIpAddressAndPort() + "/"
110 + getServerName() + "/websocket/get/" + domain
111 + (profile != null ? "/" + profile : ""));
112 } catch (MalformedObjectNameException | UnknownHostException
113 | URISyntaxException e) {
114 log.log(Level.SEVERE, "Failed to create profile URI", e);
115 return null;
116 }
117 }
118
119 /**
120 *
121 * @return name of our service, eg "profilesserver"
122 */
123 private String getServerName() {
124 // typically something like /profilesserver/websocket/liststream
125 // profilesserver is the name we're looking for
126 return session.getRequestURI().getPath().split("/")[1]; // drop leading
127 // '/'
128 }
129
130 private String getIpAddressAndPort()
131 throws UnknownHostException, MalformedObjectNameException {
132
133 MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
134
135 Set<ObjectName> objectNames = beanServer.queryNames(
136 new ObjectName("*:type=Connector,*"),
137 Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
138
139 String host = InetAddress.getLocalHost().getHostAddress();
140 String port = objectNames.iterator().next().getKeyProperty("port");
141
142 return host + ":" + port;
143
144 }
145
146 @OnClose
147 public void end() throws IOException {
148 Profiles.factory.removeListener(changeListener);
149 }
150
151 @OnError
152 public void onError(Throwable t) throws Throwable {
153 t.printStackTrace();
154 }
155
156}
Note: See TracBrowser for help on using the repository browser.