Incorporate Liam code review
[policy/engine.git] / PolicyEngineAPI / src / main / java / org / onap / policy / std / AutoClientEnd.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * PolicyEngineAPI
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.std;
22
23 import java.net.URI;
24 import java.util.concurrent.Executors;
25 import java.util.concurrent.ScheduledExecutorService;
26 import java.util.concurrent.TimeUnit;
27 import org.java_websocket.client.WebSocketClient;
28 import org.java_websocket.handshake.ServerHandshake;
29 import org.onap.policy.api.NotificationHandler;
30 import org.onap.policy.api.NotificationScheme;
31 import org.onap.policy.api.NotificationType;
32 import org.onap.policy.api.PDPNotification;
33 import org.onap.policy.common.logging.flexlogger.FlexLogger;
34 import org.onap.policy.common.logging.flexlogger.Logger;
35 import org.onap.policy.xacml.api.XACMLErrorConstants;
36
37 public class AutoClientEnd extends WebSocketClient {
38     private static StdPDPNotification notification = null;
39     private static StdPDPNotification oldNotification = null;
40     private static AutoClientEnd client = null;
41     private static NotificationScheme scheme = null;
42     private static NotificationHandler handler = null;
43     private static String url = null;
44     private static boolean status = false;
45     private static boolean stop = false;
46     private static boolean error = false;
47     private static boolean restartNeeded = false;
48     private static ScheduledExecutorService restartExecutorService = null;
49     private static Logger logger = FlexLogger.getLogger(AutoClientEnd.class.getName());
50
51     private AutoClientEnd(URI serverUri) {
52         super(serverUri);
53     }
54
55     @Override
56     public void onMessage(String msg) {
57         logger.info("Received Auto Notification from : " + getURI() + ", Notification: " + msg);
58         try {
59             AutoClientEnd.notification = NotificationUnMarshal.notificationJSON(msg);
60         } catch (Exception e) {
61             logger.error("PE500 " + e);
62         }
63         try {
64             NotificationStore.recordNotification(notification);
65         } catch (Exception e) {
66             logger.error(e);
67         }
68         if (AutoClientEnd.oldNotification != AutoClientEnd.notification) {
69             AutoClientEnd.oldNotification = AutoClientEnd.notification;
70             callHandler();
71         }
72     }
73
74     @Override
75     public void onClose(int code, String reason, boolean remote) {
76         logger.info("AutoClientEnd disconnected from: " + getURI() + "; Code: " + code + ", reason :  " + reason);
77         AutoClientEnd.restartNeeded = true;
78     }
79
80     @Override
81     public void onError(Exception ex) {
82         logger.error("XACMLErrorConstants.ERROR_PROCESS_FLOW + Error connecting to: " + getURI()
83                 + ", Exception occured ...\n" + ex);
84         AutoClientEnd.restartNeeded = true;
85     }
86
87     @Override
88     public void onOpen(ServerHandshake arg0) {
89         restartNeeded = false;
90         logger.info("Auto Notification Session Started... " + getURI());
91     }
92
93     private static void restart() {
94         try {
95             if (client != null && restartNeeded && !stop) {
96                 logger.info("Auto Notification Session Restarting ... " + getUrl());
97                 client.reconnect();
98             }
99         } catch (Exception e) {
100             logger.info("Auto Notification Session Error Started... " + getUrl());
101         }
102     }
103
104     /**
105      * Sets the auto.
106      *
107      * @param scheme the scheme
108      * @param handler the handler
109      */
110     public static void setAuto(NotificationScheme scheme, NotificationHandler handler) {
111         logger.info("Auto Notification setAuto, scheme: " + scheme);
112         AutoClientEnd.scheme = scheme;
113         AutoClientEnd.handler = handler;
114     }
115
116     public static void setScheme(NotificationScheme scheme) {
117         AutoClientEnd.scheme = scheme;
118     }
119
120     public static boolean getStatus() {
121         return AutoClientEnd.status;
122     }
123
124     public static String getUrl() {
125         return AutoClientEnd.url;
126     }
127
128     /**
129      * Start.
130      *
131      * @param url the url
132      */
133     public static void start(String url) {
134         AutoClientEnd.url = url;
135
136         if (scheme == null || handler == null || !(scheme.equals(NotificationScheme.AUTO_ALL_NOTIFICATIONS)
137                 || scheme.equals(NotificationScheme.AUTO_NOTIFICATIONS)) || AutoClientEnd.client != null) {
138             return;
139         }
140
141         if (url.contains("https")) {
142             url = url.replaceAll("https", "wss");
143         } else {
144             url = url.replaceAll("http", "ws");
145         }
146
147         // Stop and Start needs to be done.
148         try {
149             logger.info("Starting Auto Notification with the PDP server : " + url);
150             client = new AutoClientEnd(new URI(url + "notifications"));
151             client.connect();
152             status = true;
153             restartExecutorService = Executors.newSingleThreadScheduledExecutor();
154             Runnable task = AutoClientEnd::restart;
155             restartExecutorService.scheduleAtFixedRate(task, 60, 60, TimeUnit.SECONDS);
156
157             if (error) {
158                 // will not trigger. leave it in to later add checks
159                 // The URL's will be in Sync according to design Spec.
160                 ManualClientEnd.start(AutoClientEnd.url);
161                 StdPDPNotification notification = NotificationStore.getDeltaNotification(
162                         (StdPDPNotification) ManualClientEnd.result(NotificationScheme.MANUAL_ALL_NOTIFICATIONS));
163                 if (notification.getNotificationType() != null && oldNotification != notification) {
164                     oldNotification = notification;
165                     AutoClientEnd.notification = notification;
166                     callHandler();
167                 }
168                 error = false;
169             }
170         } catch (Exception e) {
171             logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
172             status = false;
173             changeUrl();
174         }
175     }
176
177     private static void changeUrl() {
178         // Change the PDP if it is not Up.
179         stop();
180         StdPolicyEngine.rotatePDPList();
181         start(StdPolicyEngine.getPDPURL());
182     }
183
184     /**
185      * Stop the websocket connection.
186      */
187     public static void stop() {
188         if (client == null) {
189             return;
190         }
191         logger.info("\n Closing Auto Notification WebSocket Connection.. ");
192         stop = true;
193         // first stop the restart service
194         try {
195             restartExecutorService.shutdown();
196         } catch (Exception e1) {
197             logger.info("\n AutoClientEnd: Error stoppping the restart Scheduler ");
198         }
199
200         // close the connection
201         try {
202             client.closeBlocking();
203         } catch (Exception e) {
204             logger.error("\n ERROR Closing Auto Notification WebSocket Connection.. ");
205         }
206
207         logger.info("\n Closed the Auto Notification WebSocket Connection.. ");
208         client = null;
209         status = false;
210         stop = false;
211         restartNeeded = false;
212     }
213
214     private static void callHandler() {
215         if (handler == null || scheme == null) {
216             return;
217         }
218         if (scheme.equals(NotificationScheme.AUTO_ALL_NOTIFICATIONS)) {
219             boolean removed = false;
220             boolean updated = false;
221             if (notification.getRemovedPolicies() != null && !notification.getRemovedPolicies().isEmpty()) {
222                 removed = true;
223                 notification.setNotificationType(NotificationType.REMOVE);
224             }
225             if (notification.getLoadedPolicies() != null && !notification.getLoadedPolicies().isEmpty()) {
226                 updated = true;
227                 notification.setNotificationType(NotificationType.UPDATE);
228             }
229             if (removed && updated) {
230                 notification.setNotificationType(NotificationType.BOTH);
231             }
232             try {
233                 handler.notificationReceived(notification);
234             } catch (Exception e) {
235                 logger.error("Error in Clients Handler Object : ", e);
236             }
237         } else if (scheme.equals(NotificationScheme.AUTO_NOTIFICATIONS)) {
238             PDPNotification newNotification = MatchStore.checkMatch(notification);
239             if (newNotification.getNotificationType() != null) {
240                 try {
241                     handler.notificationReceived(newNotification);
242                 } catch (Exception e) {
243                     logger.error("Error in Clients Handler Object : ", e);
244                 }
245             }
246         }
247     }
248 }