2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
8 * Unless otherwise specified, all software contained herein is licensed
9 * under the Apache License, Version 2.0 (the "License");
10 * you may not use this software except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * Unless otherwise specified, all documentation contained herein is licensed
22 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23 * you may not use this documentation except in compliance with the License.
24 * You may obtain a copy of the License at
26 * https://creativecommons.org/licenses/by/4.0/
28 * Unless required by applicable law or agreed to in writing, documentation
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * ============LICENSE_END============================================
38 package org.onap.portalsdk.core.onboarding.listener;
40 import java.util.Calendar;
41 import java.util.Hashtable;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpSession;
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49 import org.onap.portalsdk.core.onboarding.crossapi.SessionCommunicationService;
50 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
51 import org.onap.portalsdk.core.restful.domain.PortalTimeoutVO;
53 import com.fasterxml.jackson.core.JsonProcessingException;
54 import com.fasterxml.jackson.core.type.TypeReference;
55 import com.fasterxml.jackson.databind.ObjectMapper;
58 * Invoked by listeners (UserContextListener and UserSessionListener) to track
61 public class PortalTimeoutHandler {
63 private static final Map<String, HttpSession> sessionMap = new Hashtable<String, HttpSession>();
64 private static final Log logger = LogFactory.getLog(PortalTimeoutHandler.class);
65 private static ObjectMapper mapper = new ObjectMapper();
66 private static PortalTimeoutHandler timeoutHandler;
68 protected static final SessionCommInf sessionComm = new SessionComm();
70 public interface SessionCommInf {
71 public Integer fetchSessionSlotCheckInterval(String... params);
73 public void extendSessionTimeOuts(String... sessionMap);
76 public static class SessionComm implements SessionCommInf {
79 public Integer fetchSessionSlotCheckInterval(String... params) {
80 String ecompRestURL = params[0];
81 String userName = params[1];
82 String pwd = params[2];
83 String uebKey = params[3];
84 String sessionSlot = SessionCommunicationService.getSessionSlotCheckInterval(ecompRestURL, userName, pwd,
86 if (sessionSlot == null)
88 return Integer.parseInt(sessionSlot);
92 public void extendSessionTimeOuts(String... params) {
93 String ecompRestURL = params[0];
94 String userName = params[1];
95 String pwd = params[2];
96 String uebKey = params[3];
97 String sessionTimeoutMap = params[4];
98 SessionCommunicationService.requestPortalSessionTimeoutExtension(ecompRestURL, userName, pwd, uebKey,
103 public static Map<String, HttpSession> getSessionMap() {
107 public static PortalTimeoutHandler getInstance() {
108 if (timeoutHandler == null)
109 timeoutHandler = new PortalTimeoutHandler();
111 return timeoutHandler;
115 * TODO: remove static
117 * @param portalJSessionId
118 * Portal (remote) session ID
124 public static void sessionCreated(String portalJSessionId, String jSessionId, HttpSession session) {
126 storeMaxInactiveTime(session);
128 // this key is a combination of portal jsession id and app session id
129 String jSessionKey = jSessionKey(jSessionId, portalJSessionId);
130 Object jSessionKeySessionVal = session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID);
132 // do not reset the attributes if the same values have already been set
133 // because that will cause PortalTimeoutBindingListener to unbound the
135 if (jSessionKeySessionVal != null && jSessionKeySessionVal.equals(jSessionKey)) {
136 logger.debug(" Session Values already exist in te map for sessionKey " + jSessionKey);
140 session.setAttribute(PortalApiConstants.PORTAL_JSESSION_ID, jSessionKey);
142 // session binding listener will add this value to the static map
143 // and with session replication the listener will fire in all tomcat
145 session.setAttribute(PortalApiConstants.PORTAL_JSESSION_BIND, new PortalTimeoutBindingListener());
149 * TODO: remove static
153 protected static void storeMaxInactiveTime(HttpSession session) {
154 if (session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME) == null)
155 session.setAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME, session.getMaxInactiveInterval());
159 * TODO: remove static
164 public static void sessionDestroyed(HttpSession session) {
166 logger.info(" Session getting destroyed - id: " + session.getId());
167 session.removeAttribute(PortalApiConstants.PORTAL_JSESSION_BIND);
168 } catch (Exception e) {
169 logger.error("sessionDestroyed failed", e);
174 * TODO: remove static
176 * @param portalJSessionId
178 * @return true on success, false if the session cannot be found, etc.
180 public static boolean invalidateSession(String portalJSessionId) {
181 boolean result = false;
182 logger.debug("Session Management: request from Portal to invalidate the session: " + portalJSessionId);
183 for (String jSessionKey : sessionMap.keySet()) {
185 HttpSession session = sessionMap.get(jSessionKey);
186 if (portalJSessionId(jSessionKey).equals(portalJSessionId)) {
187 session.invalidate();
190 } catch (Exception e) {
191 logger.error("invalidateSession failed", e);
198 * TODO: remove static
200 * @return json version of the timeout map: session ID -> timeout object
202 public static String gatherSessionExtensions() {
203 logger.debug("Session Management: gatherSessionExtensions");
205 Map<String, PortalTimeoutVO> sessionTimeoutMap = new Hashtable<>();
208 for (String jSessionKey : sessionMap.keySet()) {
211 // get the expiry time in seconds
212 HttpSession session = sessionMap.get(jSessionKey);
214 Long lastAccessedTimeMilliSec = session.getLastAccessedTime();
215 Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L;
216 Calendar instance = Calendar.getInstance();
217 instance.setTimeInMillis(session.getLastAccessedTime());
218 logger.debug("Session Management: Last Accessed time for " + jSessionKey + ": " + instance.getTime());
220 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
222 sessionTimeoutMap.put(portalJSessionId(jSessionKey),
223 getSingleSessionTimeoutObj(jSessionKey, sessionTimOutMilliSec));
224 logger.debug("Session Management: putting session in map " + jSessionKey + " sessionTimoutSec"
225 + (int) (sessionTimOutMilliSec / 1000));
227 jsonMap = mapper.writeValueAsString(sessionTimeoutMap);
229 } catch (Exception e) {
230 logger.error("gatherSessionExtensions failed", e);
238 * TODO: remove static
240 * @param sessionTimeoutMapStr
241 * Session timeout map as string
242 * @return true on success, false otherwise
244 public static boolean updateSessionExtensions(String sessionTimeoutMapStr) {
245 logger.debug("Session Management: updateSessionExtensions");
246 Map<String, PortalTimeoutVO> sessionTimeoutMap = null;
248 TypeReference<Hashtable<String, PortalTimeoutVO>> typeRef = new TypeReference<Hashtable<String, PortalTimeoutVO>>() {
250 sessionTimeoutMap = mapper.readValue(sessionTimeoutMapStr, typeRef);
251 } catch (Exception e) {
252 logger.error("updateSessionExtensions failed to parse the sessionTimeoutMap from portal", e);
256 boolean result = true;
257 for (String jPortalSessionId : sessionTimeoutMap.keySet()) {
259 PortalTimeoutVO extendedTimeoutVO = mapper.readValue(
260 mapper.writeValueAsString(sessionTimeoutMap.get(jPortalSessionId)), PortalTimeoutVO.class);
261 HttpSession session = sessionMap.get(jSessionKey(extendedTimeoutVO.getjSessionId(), jPortalSessionId));
263 if (session == null) {
267 Long lastAccessedTimeMilliSec = session.getLastAccessedTime();
268 Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L;
269 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
271 Long maxTimeoutTimeMilliSec = extendedTimeoutVO.getSessionTimOutMilliSec();
272 if (maxTimeoutTimeMilliSec > sessionTimOutMilliSec) {
273 session.setMaxInactiveInterval((int) (maxTimeoutTimeMilliSec - lastAccessedTimeMilliSec) / 1000);
274 logger.debug("Session Management: extended session for :" + session.getId() + " to :"
275 + (int) (maxTimeoutTimeMilliSec / 1000));
277 } catch (Exception e) {
278 logger.error("updateSessionExtensions failed to update session timeouts", e);
279 // Signal a problem if any one of them fails
288 * TODO: Remove static
297 * UEB key (application ID)
298 * @param ecompRestURL
300 * @param _sessionComm
301 * Session communication information
303 public static void handleSessionUpdatesNative(HttpServletRequest request, String userName, String pwd,
304 String uebKey, String ecompRestURL, SessionCommInf _sessionComm) {
306 if (_sessionComm == null) {
307 _sessionComm = sessionComm;
310 synchronizeSessionForLastMinuteRequests(request, ecompRestURL, userName, pwd, uebKey, _sessionComm);
311 } catch (Exception e) {
312 logger.error("handleSesionUpdatesNative failed", e);
314 resetSessionMaxIdleTimeOut(request);
318 * TODO: remove Static
322 * @param ecompRestURL
330 * @param _sessionComm
331 * session information
332 * @throws JsonProcessingException
333 * On failure to serialize
335 public static void synchronizeSessionForLastMinuteRequests(HttpServletRequest request, String ecompRestURL,
336 String userName, String pwd, String uebKey, SessionCommInf _sessionComm) throws JsonProcessingException {
338 HttpSession session = request.getSession(false);
342 Object portalSessionSlotCheckObj = session.getServletContext()
343 .getAttribute(PortalApiConstants.PORTAL_SESSION_SLOT_CHECK);
344 Integer portalSessionSlotCheckinMilliSec = 5 * 60 * 1000; // (5 minutes)
345 if (portalSessionSlotCheckObj != null) {
346 portalSessionSlotCheckinMilliSec = Integer.valueOf(portalSessionSlotCheckObj.toString());
348 portalSessionSlotCheckObj = _sessionComm
349 .fetchSessionSlotCheckInterval(new String[] { ecompRestURL, userName, pwd, uebKey });
350 logger.debug("Fetching Portal Session Slot Object: " + portalSessionSlotCheckObj);
351 if (portalSessionSlotCheckObj != null) {
352 portalSessionSlotCheckinMilliSec = Integer.valueOf(portalSessionSlotCheckObj.toString());
353 session.getServletContext().setAttribute(PortalApiConstants.PORTAL_SESSION_SLOT_CHECK,
354 portalSessionSlotCheckinMilliSec);
358 Object previousToLastAccessTimeObj = session.getAttribute(PortalApiConstants.SESSION_PREVIOUS_ACCESS_TIME);
359 final long lastAccessedTimeMilliSec = session.getLastAccessedTime();
360 if (previousToLastAccessTimeObj == null) {
361 previousToLastAccessTimeObj = lastAccessedTimeMilliSec;
362 session.setAttribute(PortalApiConstants.SESSION_PREVIOUS_ACCESS_TIME, previousToLastAccessTimeObj);
364 Long previousToLastAccessTime = (Long) previousToLastAccessTimeObj;
365 final int maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000;
366 if (maxIntervalMilliSec
367 - (lastAccessedTimeMilliSec - previousToLastAccessTime) <= portalSessionSlotCheckinMilliSec) {
369 String jSessionKey = (String) session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID);
370 Map<String, PortalTimeoutVO> sessionTimeoutMap = new Hashtable<>();
371 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
373 sessionTimeoutMap.put(PortalTimeoutHandler.portalJSessionId(jSessionKey),
374 PortalTimeoutHandler.getSingleSessionTimeoutObj(jSessionKey, sessionTimOutMilliSec));
375 String jsonMap = mapper.writeValueAsString(sessionTimeoutMap);
376 logger.debug("Extension requested for all the Apps and Portal; JessionKey: " + jSessionKey
377 + "; SessionMap: " + sessionTimeoutMap);
378 _sessionComm.extendSessionTimeOuts(new String[] { ecompRestURL, userName, pwd, uebKey, jsonMap });
385 * TODO: remove static
390 public static void resetSessionMaxIdleTimeOut(HttpServletRequest request) {
392 HttpSession session = request.getSession(false);
395 final Object maxIdleAttribute = session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME);
396 if (maxIdleAttribute != null) {
397 session.setMaxInactiveInterval(Integer.parseInt(maxIdleAttribute.toString()));
399 } catch (Exception e) {
400 logger.error("resetSessionMaxIdleTimeout failed", e);
408 * @param sessionTimOutMilliSec
411 private static PortalTimeoutVO getSingleSessionTimeoutObj(String jSessionKey, Long sessionTimOutMilliSec) {
412 return new PortalTimeoutVO(jSessionId(jSessionKey), sessionTimOutMilliSec);
418 * @param portalJSessionId
421 private static String jSessionKey(String jSessionId, String portalJSessionId) {
422 return portalJSessionId + "-" + jSessionId;
430 private static String portalJSessionId(String jSessionKey) {
431 return jSessionKey.split("-")[0];
439 private static String jSessionId(String jSessionKey) {
440 return jSessionKey.split("-")[1];