55115908f692e58d85e32ba1dde51f61d3e4ff61
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 package org.onap.ccsdk.features.sdnr.wt.websocketmanager;
19
20 import java.time.Instant;
21 import javax.servlet.ServletException;
22 import org.eclipse.jetty.server.Server;
23 import org.eclipse.jetty.server.ServerConnector;
24 import org.eclipse.jetty.servlet.ServletContextHandler;
25 import org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer;
26 import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
27 import org.onap.ccsdk.features.sdnr.wt.common.configuration.ConfigurationFileRepresentation;
28 import org.onap.ccsdk.features.sdnr.wt.websocketmanager.config.WebSocketManagerConfig;
29 import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.WebsocketManagerService;
30 import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.DOMNotificationOutput;
31 import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.NotificationOutput;
32 import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper;
33 import org.opendaylight.mdsal.dom.api.DOMNotification;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
36 import org.opendaylight.yangtools.yang.binding.Notification;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.osgi.service.http.HttpService;
39 import org.osgi.service.http.NamespaceException;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class WebSocketManagerProvider implements WebsocketManagerService, AutoCloseable {
44
45     private static final Logger LOG = LoggerFactory.getLogger(WebSocketManagerProvider.class);
46     private static final String APPLICATION_NAME = WebSocketManagerProvider.class.getName();
47     private static final String CONFIGURATIONFILE = "etc/websocketmanager.properties";
48     private WebSocketManagerConfig wsConfig;
49     private static final String ALIAS = "/websocket";
50     private static final String DEFAULT_IP_ADDR = "0.0.0.0";
51
52     private WebSocketManager wsServlet = null;
53     private Server server = null;
54
55     public WebSocketManagerProvider() {
56         LOG.info("Creating provider for {}", APPLICATION_NAME);
57     }
58
59     public void init() {
60         LOG.info("Init provider for {}", APPLICATION_NAME);
61         ConfigurationFileRepresentation configFileRepresentation =
62                 new ConfigurationFileRepresentation(CONFIGURATIONFILE);
63
64         wsConfig = new WebSocketManagerConfig(configFileRepresentation);
65
66         if (wsConfig.getWebsocketPort().isPresent() && !wsConfig.getWebsocketPort().isEmpty()) {
67             try {
68                 startServer(DEFAULT_IP_ADDR, wsConfig.getWebsocketPort().get().intValue(), ALIAS);
69             } catch (Exception e) {
70                 LOG.error("Failed in Websocker server startup {}", e);
71             }
72         } else {
73             LOG.error("WebSocket Port not configured, hence not starting WebSocket Manager");
74         }
75     }
76
77     public void startServer(String wsHost, int wsPort, String wsPath) throws Exception {
78         server = new Server();
79         ServerConnector connector = new ServerConnector(server);
80         connector.setHost(wsHost);
81         connector.setPort(wsPort);
82         server.addConnector(connector);
83
84         ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
85         context.setContextPath("/");
86         server.setHandler(context);
87
88         NativeWebSocketServletContainerInitializer.configure(context,
89                 (servletContext, nativeWebSocketConfiguration) -> {
90                     // Configure default max size
91                     nativeWebSocketConfiguration.getPolicy().setMaxTextMessageBufferSize(65535);
92
93                     // Add websockets
94                     nativeWebSocketConfiguration.addMapping(wsPath, new WebSocketManagerCreator());
95                 });
96
97         // Add generic filter that will accept WebSocket upgrade.
98         WebSocketUpgradeFilter.configure(context);
99
100         server.start();
101     }
102
103     public void stopServer() throws Exception {
104         if (server != null)
105             server.stop();
106     }
107
108     @Override
109     public void close() throws Exception {
110         LOG.info("Close provider for {}", APPLICATION_NAME);
111         stopServer();
112     }
113
114     public void onUnbindService(HttpService httpService) {
115         httpService.unregister(ALIAS);
116         wsServlet = null;
117     }
118
119     public void setAboutServlet(WebSocketManager wsServlet) {
120         this.wsServlet = wsServlet;
121     }
122
123     public void onBindService(HttpService httpService) throws ServletException, NamespaceException {
124         if (httpService == null) {
125             LOG.warn("Unable to inject HttpService into DluxLoader. dlux modules won't work without httpService");
126         } else {
127             if (wsServlet == null) {
128                 wsServlet = new WebSocketManager();
129                 httpService.registerServlet(ALIAS, wsServlet, null, null);
130                 LOG.info("websocket servlet registered.");
131             } else {
132                 LOG.warn("Servelt ");
133             }
134         }
135
136     }
137
138     public WebSocketManager getWsServlet() {
139         return wsServlet;
140     }
141
142     public void setWsServlet(WebSocketManager wsServlet) {
143         this.wsServlet = wsServlet;
144     }
145
146     public static boolean assertNotificationType(Notification notification, QName eventType) {
147         final String yangTypeName = eventType.getLocalName();
148         final Class<?> cls = notification.getClass();
149         final String clsNameToTest = YangToolsMapperHelper.toCamelCaseClassName(yangTypeName);
150         if (cls.getSimpleName().equals(clsNameToTest)) {
151             return true;
152         }
153         Class<?>[] ifs = cls.getInterfaces();
154         for (Class<?> clsif : ifs) {
155             if (clsif.getSimpleName().equals(clsNameToTest)) {
156                 return true;
157             }
158         }
159         return false;
160     }
161
162     @Override
163     public void sendNotification(Notification notification, NodeId nodeId, QName eventType) {
164         if (!assertNotificationType(notification, eventType)) {
165             return;
166         }
167         this.sendNotification(notification, nodeId, eventType,
168                 YangToolsMapperHelper.getTime(notification, Instant.now()));
169     }
170
171     @Override
172     public void sendNotification(Notification notification, NodeId nodeId, QName eventType, DateAndTime eventTime) {
173         WebSocketManagerSocket.broadCast(new NotificationOutput(notification, nodeId.getValue(), eventType, eventTime));
174
175     }
176
177     @Override
178     public void sendNotification(DOMNotification notification, NodeId nodeId, QName eventType) {
179         WebSocketManagerSocket.broadCast(new DOMNotificationOutput(notification, nodeId.getValue(), eventType,
180                 YangToolsMapperHelper.getTime(notification, Instant.now())));
181     }
182
183     @Override
184     public void sendNotification(DOMNotification notification, NodeId nodeId, QName eventType, DateAndTime eventTime) {
185         WebSocketManagerSocket
186                 .broadCast(new DOMNotificationOutput(notification, nodeId.getValue(), eventType, eventTime));
187     }
188
189 }