diff options
Diffstat (limited to 'ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt')
4 files changed, 790 insertions, 0 deletions
diff --git a/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/CoreTimeoutHandler.java b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/CoreTimeoutHandler.java new file mode 100644 index 00000000..897d9cd9 --- /dev/null +++ b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/CoreTimeoutHandler.java @@ -0,0 +1,166 @@ +/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ================================================================================ + */ +package org.openecomp.portalapp.service.sessionmgt; + +import java.util.Calendar; +import java.util.Hashtable; +import java.util.Map; + +import javax.servlet.http.HttpSession; + +import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog; +import org.openecomp.portalapp.portal.utils.EcompPortalUtils; +import org.openecomp.portalsdk.core.domain.sessionmgt.TimeoutVO; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + + +@Service +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +@EPMetricsLog +public class CoreTimeoutHandler{ + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CoreTimeoutHandler.class); + + public static final Map<String, HttpSession> sessionMap = new Hashtable<String,HttpSession>(); + public static final Integer repeatInterval = 15 * 60; // 15 minutes + ObjectMapper mapper = new ObjectMapper(); + + + public static void sessionCreated(String portalJSessionId, String jSessionId, HttpSession session) { + + storeMaxInactiveTime(session); + + // this key is a combination of portal jsession id and app session id + session.setAttribute(PortalApiConstants.PORTAL_JSESSION_ID,jSessionKey(jSessionId, portalJSessionId)); + sessionMap.put((String)session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID), session); + + } + + protected static void storeMaxInactiveTime(HttpSession session) { + + if(session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME) == null) + session.setAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME,session.getMaxInactiveInterval()); + } + + public static void sessionDestroyed(HttpSession session) { + + try{ + sessionMap.remove((String)session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID)); + }catch(Exception e){ + logger.error(EELFLoggerDelegate.errorLogger, "************************ Session Management: Error while destroying session for " + session.getId() + " Details: " + EcompPortalUtils.getStackTrace(e)); + } + + } + + public String gatherSessionExtenstions() { + + Map<String,TimeoutVO> sessionTimeoutMap = new Hashtable<String,TimeoutVO>(); + String jsonMap = ""; + + + for(String jSessionKey: sessionMap.keySet()) { + + try{ + // get the expirytime in seconds + HttpSession session = sessionMap.get(jSessionKey); + + Long lastAccessedTimeMilliSec = session.getLastAccessedTime(); + Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L; + //Long currentTimeMilliSec = Calendar.getInstance().getTimeInMillis() ; + //(maxIntervalMilliSec - (currentTimeMilliSec - lastAccessedTimeMilliSec) + ; + Calendar instance = Calendar.getInstance(); + instance.setTimeInMillis(session.getLastAccessedTime()); + logger.info(EELFLoggerDelegate.errorLogger, "************************ Session Management: Last Accessed time for "+ jSessionKey + ": " + instance.getTime()); + + Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec; + + sessionTimeoutMap.put( portalJSessionId(jSessionKey), new TimeoutVO(jSessionId(jSessionKey),sessionTimOutMilliSec)); + + + jsonMap = mapper.writeValueAsString(sessionTimeoutMap); + } catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "************************ Session Management: Error during JsonSessionTimout conversion. Details: " + EcompPortalUtils.getStackTrace(e)); + } + } + + return jsonMap; + + } + + + public void updateSessionExtensions(String sessionTimeoutMapStr) throws Exception { + + //Map<String,Object> sessionTimeoutMap = mapper.readValue(sessionTimeoutMapStr, Map.class); + Map<String,TimeoutVO> sessionTimeoutMap; + try{ + TypeReference<Hashtable<String,TimeoutVO>> typeRef + = new TypeReference<Hashtable<String,TimeoutVO>>() {}; + + sessionTimeoutMap = mapper.readValue(sessionTimeoutMapStr, typeRef); + }catch(Exception e){ + logger.error(EELFLoggerDelegate.errorLogger, "************************ Session Management: Error while to parse update session extension in portal", e); + return; + } + for(String jPortalSessionId: sessionTimeoutMap.keySet()) { + try { + + TimeoutVO extendedTimeoutVO = mapper.readValue(mapper.writeValueAsString(sessionTimeoutMap.get(jPortalSessionId)),TimeoutVO.class); + HttpSession session = sessionMap.get(jSessionKey(extendedTimeoutVO.getjSessionId(), jPortalSessionId)); + + if(session == null) { + continue; + } + + Long lastAccessedTimeMilliSec = session.getLastAccessedTime(); + Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L; + Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec; + + Long maxTimeoutTimeMilliSec = extendedTimeoutVO.getSessionTimOutMilliSec(); + if(maxTimeoutTimeMilliSec>sessionTimOutMilliSec) { + logger.debug(EELFLoggerDelegate.debugLogger, "************************ Session Management: " + " updated session max idle time"); + session.setMaxInactiveInterval((int)(maxTimeoutTimeMilliSec-lastAccessedTimeMilliSec)/1000); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "************************ Session Management: " + EcompPortalUtils.getStackTrace(e)); + } + + } + + } + + protected static String jSessionKey(String jSessionId, String portalJSessionId) { + return portalJSessionId + "-" + jSessionId; + } + + protected String portalJSessionId(String jSessionKey) { + return jSessionKey.split("-")[0]; + } + + protected String jSessionId(String jSessionKey) { + return jSessionKey.split("-")[1]; + } + +} diff --git a/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/ManageService.java b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/ManageService.java new file mode 100644 index 00000000..52cc0825 --- /dev/null +++ b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/ManageService.java @@ -0,0 +1,101 @@ +/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ================================================================================ + */ +package org.openecomp.portalapp.service.sessionmgt; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog; +import org.openecomp.portalapp.portal.service.EPAppService; +import org.openecomp.portalapp.portal.transport.OnboardingApp; +import org.openecomp.portalapp.portal.utils.EcompPortalUtils; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.quartz.CronExpression; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +@Service("manageService") +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +@EPMetricsLog +public class ManageService implements PortalTimeoutHandler.SessionCommInf { + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ManageService.class); + + @Autowired + EPAppService appService; + + @Autowired + SessionCommunication sessionCommunication; + + public Integer fetchSessionSlotCheckInterval(String... params) throws Exception { + + String defaultCronExpressionStr = "0 0/5 * * * ? *"; + String cronExpressionStr = SystemProperties.getProperty(SystemProperties.SESSIONTIMEOUT_FEED_CRON); + + if (cronExpressionStr == null) { + cronExpressionStr = defaultCronExpressionStr; + } + + CronExpression cal = new CronExpression(cronExpressionStr); + final Date nowTime = Calendar.getInstance().getTime(); + Date nextTime = cal.getNextValidTimeAfter(nowTime); + Date nextNextTime = cal.getNextValidTimeAfter(nextTime); + + final int timeDiff = (int)(nextNextTime.getTime()-nextTime.getTime()); + logger.debug(EELFLoggerDelegate.debugLogger, "Time interval between subsequent session checks " + timeDiff); + + return timeDiff; + } + + public void extendSessionTimeOuts(String... params) throws Exception { + try { + String sessionMap = params[3]; + + logger.debug(EELFLoggerDelegate.debugLogger, "Extending the App sessions for last minute request: " + sessionMap); + + if (StringUtils.isEmpty(sessionMap)) { + logger.error(EELFLoggerDelegate.errorLogger, "extendSessionTimeOuts: Skipping session updates since the portal session value is empty."); + } else { + List<OnboardingApp> appList = appService.getEnabledNonOpenOnboardingApps(); + for (OnboardingApp onApp : appList) { + sessionCommunication.pingSession(onApp, sessionMap); + } + updateSessionExtensions(sessionMap); + sessionCommunication.clear(false); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred in extendSessionTimeOuts(). Details: " + EcompPortalUtils.getStackTrace(e)); + } + } + + public String gatherSessionExtenstions() { + return PortalTimeoutHandler.gatherSessionExtensions(); + } + + public void updateSessionExtensions(String sessionTimeoutMapStr) throws Exception { + PortalTimeoutHandler.updateSessionExtensions(sessionTimeoutMapStr); + } + +} diff --git a/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/SessionCommunication.java b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/SessionCommunication.java new file mode 100644 index 00000000..11c0890e --- /dev/null +++ b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/SessionCommunication.java @@ -0,0 +1,271 @@ +/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ================================================================================ + */ +package org.openecomp.portalapp.service.sessionmgt; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.UUID; + +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.MDC; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import com.att.eelf.configuration.Configuration; +import org.openecomp.portalsdk.core.exception.UrlAccessRestrictedException; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalapp.portal.logging.aop.EPAuditLog; +import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog; +import org.openecomp.portalapp.portal.logging.format.EPAppMessagesEnum; +import org.openecomp.portalapp.portal.logging.logic.EPLogUtil; +import org.openecomp.portalapp.portal.transport.OnboardingApp; +import org.openecomp.portalapp.portal.utils.EPCommonSystemProperties; +import org.openecomp.portalapp.portal.utils.EcompPortalUtils; + +@Service("sessionCommunication") +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +public class SessionCommunication { + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SessionCommunication.class); + + @EPAuditLog + public String sendGet(OnboardingApp app) throws Exception { + String appResponse = ""; + String appName = "Unknwon"; + int responseCode = 0; + + try { + if (app != null && app.name != null && app.name != "") { + appName = app.name; + } + String url = app.restUrl + "/sessionTimeOuts"; + String encriptedPwdDB = app.appPassword; + String appUserName = app.username; + + setLocalMDCContext(app, "/sessionTimeOuts", url); + + URL obj = new URL(url); + + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("GET"); + con.setConnectTimeout(3000); + con.setReadTimeout(8000); + // add request header + con.setRequestProperty("username", appUserName); + con.setRequestProperty("password", encriptedPwdDB); + + // con.set + responseCode = con.getResponseCode(); + logger.debug(EELFLoggerDelegate.debugLogger, "Response Code : " + responseCode); + + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + + in.close(); + appResponse = response.toString(); + } catch (UrlAccessRestrictedException e) { + responseCode = HttpServletResponse.SC_UNAUTHORIZED; + logger.error(EELFLoggerDelegate.errorLogger, String.format("SessionCommunication.sendGet received an un-authorized exception. AppName: %s", appName)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiAuthenticationError, e); + } catch (Exception e) { + responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + String message = String.format( + "SessionCommunication.sendGet encountered an Exception. AppName: %s, Details: %s", appName, + EcompPortalUtils.getStackTrace(e)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHttpConnectionError, e); + logger.error(EELFLoggerDelegate.errorLogger, message); + } finally { + EcompPortalUtils.setExternalAppResponseCode(responseCode); + } + return appResponse; + } + + @EPAuditLog + public Boolean pingSession(OnboardingApp app, String sessionTimeoutMap) throws Exception { + String appName = "Unknwon"; + int responseCode = 0; + try { + if (app != null && app.name != null && app.name != "") { + appName = app.name; + } + + String url = app.restUrl + "/updateSessionTimeOuts"; + String encriptedPwdDB = app.appPassword; + String appUserName = app.username; + // String decreptedPwd = CipherUtil.decrypt(encriptedPwdDB, + // SystemProperties.getProperty(SystemProperties.Decryption_Key)); + + setLocalMDCContext(app, "/updateSessionTimeOuts", url); + + URL obj = new URL(url); + + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("POST"); + con.setConnectTimeout(3000); + con.setReadTimeout(15000); + + // add request header + con.setRequestProperty("username", appUserName); + con.setRequestProperty("password", encriptedPwdDB); + + con.setRequestProperty("sessionMap", sessionTimeoutMap); + con.setDoInput(true); + con.setDoOutput(true); + con.getOutputStream().write(sessionTimeoutMap.getBytes()); + con.getOutputStream().flush(); + con.getOutputStream().close(); + + responseCode = con.getResponseCode(); + logger.debug(EELFLoggerDelegate.debugLogger, "Response Code : " + responseCode); + } catch (UrlAccessRestrictedException e) { + responseCode = HttpServletResponse.SC_UNAUTHORIZED; + String message = String.format( + "SessionCommunication.pingSession received an un-authorized exception. AppName: %s", appName); + logger.error(EELFLoggerDelegate.errorLogger, message); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiAuthenticationError, e); + } catch (Exception e) { + responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + String message = String.format( + "SessionCommunication.pingSession encountered an Exception. AppName: %s, Details: %s", appName, + EcompPortalUtils.getStackTrace(e)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHttpConnectionError, e); + logger.error(EELFLoggerDelegate.errorLogger, message); + } finally { + EcompPortalUtils.setExternalAppResponseCode(responseCode); + } + + return true; + } + + @EPAuditLog + public Boolean timeoutSession(OnboardingApp app, String portalJSessionId) throws Exception { + String appName = "Unknwon"; + int responseCode = 0; + try { + if (app != null && app.name != null && app.name != "") { + appName = app.name; + } + + String url = app.restUrl + "/timeoutSession" + "?portalJSessionId=" + portalJSessionId; + + String encriptedPwdDB = app.appPassword; + String appUserName = app.username; + // String decreptedPwd = CipherUtil.decrypt(encriptedPwdDB, + // SystemProperties.getProperty(SystemProperties.Decryption_Key)); + + setLocalMDCContext(app, "/timeoutSession", url); + + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("POST"); + con.setConnectTimeout(3000); + con.setReadTimeout(15000); + + // add request header + con.setRequestProperty("username", appUserName); + con.setRequestProperty("password", encriptedPwdDB); + + // con.setRequestProperty("portalJSessionId", portalJSessionId); + con.setDoInput(true); + con.setDoOutput(true); + con.getOutputStream().flush(); + con.getOutputStream().close(); + + responseCode = con.getResponseCode(); + logger.debug(EELFLoggerDelegate.debugLogger, "Response Code : " + responseCode); + } catch (UrlAccessRestrictedException e) { + responseCode = HttpServletResponse.SC_UNAUTHORIZED; + String message = String.format( + "SessionCommunication.timeoutSession received an un-authorized exception. AppName: %s", appName); + logger.error(EELFLoggerDelegate.errorLogger, message); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiAuthenticationError, e); + } catch (Exception e) { + responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + String message = String.format( + "SessionCommunication.timeoutSession encountered an Exception. AppName: %s, Details: %s", appName, + EcompPortalUtils.getStackTrace(e)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHttpConnectionError, e); + logger.error(EELFLoggerDelegate.errorLogger, message); + } finally { + EcompPortalUtils.setExternalAppResponseCode(responseCode); + } + return true; + } + + @EPMetricsLog + private void setLocalMDCContext(OnboardingApp app, String restPath, String url) { + setRequestId(); + MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP); + if (url!=null && url.contains("https")) { + MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS); + } + MDC.put(EPCommonSystemProperties.FULL_URL, url); + MDC.put(EPCommonSystemProperties.TARGET_ENTITY, app.myLoginsAppName); + MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath); + } + + /** + * Generates request id, service name fields and loads them + * into MDC, as these values could be empty as these + * session timeout requests are generated at + * scheduled intervals using quartz scheduler. + */ + @EPMetricsLog + public void setRequestId() { + String requestId = MDC.get(Configuration.MDC_KEY_REQUEST_ID); + if (StringUtils.isEmpty(requestId)) { + MDC.put(Configuration.MDC_KEY_REQUEST_ID, UUID.randomUUID().toString()); + } + + MDC.put(Configuration.MDC_SERVICE_NAME, "/quartz/keepSessionAlive"); + MDC.put(EPCommonSystemProperties.PARTNER_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE); + } + + /** + * Remove the values from MDC as these requests are + * executed at regular intervals based on quartz rather + * incoming REST API requests. + * @param bAll + */ + @EPMetricsLog + public void clear(Boolean bAll) { + MDC.remove(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE); + if (bAll) { + MDC.remove(Configuration.MDC_KEY_REQUEST_ID); + MDC.remove(Configuration.MDC_SERVICE_NAME); + MDC.remove(EPCommonSystemProperties.PARTNER_NAME); + } + } +} diff --git a/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/TimeoutHandler.java b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/TimeoutHandler.java new file mode 100644 index 00000000..53258c06 --- /dev/null +++ b/ecomp-portal-BE-common/src/main/java/org/openecomp/portalapp/service/sessionmgt/TimeoutHandler.java @@ -0,0 +1,252 @@ +/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ================================================================================ + */ +package org.openecomp.portalapp.service.sessionmgt; + +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpSession; + +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.PersistJobDataAfterExecution; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import org.openecomp.portalsdk.core.domain.sessionmgt.TimeoutVO; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants; +import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog; +import org.openecomp.portalapp.portal.logging.format.EPAppMessagesEnum; +import org.openecomp.portalapp.portal.logging.logic.EPLogUtil; +import org.openecomp.portalapp.portal.service.EPAppService; +import org.openecomp.portalapp.portal.transport.OnboardingApp; +import org.openecomp.portalapp.portal.utils.EcompPortalUtils; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Executed periodically by Quartz to discover remote application sessions and + * update timeouts suitably. + */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution +@org.springframework.context.annotation.Configuration +@EnableAspectJAutoProxy +@EPMetricsLog +public class TimeoutHandler extends QuartzJobBean { + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(TimeoutHandler.class); + + ObjectMapper mapper = new ObjectMapper(); + + /** + * Supports static call {@link #timeoutSessions(HttpSession)} + */ + private static List<OnboardingApp> onboardedAppList = null; + + @Autowired + SessionCommunication sessionCommunication; + + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + try { + //Create a request id if there is none available, + //and which will internally be used when making + //session extended timeout calls to the partner applications. + if (getSessionCommunication()!=null) { + getSessionCommunication().setRequestId(); + } + logger.info(EELFLoggerDelegate.debugLogger, "Quartz Cronjob for Session Management begins"); + + ManageService manageService = (ManageService) applicationContext.getBean("manageService"); + EPAppService appService = (EPAppService) applicationContext.getBean("epAppService"); + + List<OnboardingApp> appList = appService.getEnabledNonOpenOnboardingApps(); + onboardedAppList = appList; + TypeReference<Hashtable<String, TimeoutVO>> typeRef = new TypeReference<Hashtable<String, TimeoutVO>>() { + }; + String portalJsonSessionStr; + Map<String, TimeoutVO> portalSessionTimeoutMap = null; + + portalJsonSessionStr = manageService.gatherSessionExtenstions(); + if (portalJsonSessionStr == null || portalJsonSessionStr == "") { + logger.error(EELFLoggerDelegate.errorLogger, "Session Management: Portal session information is empty."); + return; + } + + try { + portalSessionTimeoutMap = mapper.readValue(portalJsonSessionStr, typeRef); + } catch (JsonMappingException | JsonParseException je) { + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, je); + logger.error(EELFLoggerDelegate.errorLogger, "Session Management: JSON Mapping Exception occurred while gathering the Session", je); + return; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Session Management: Error while gather Session from portal", e); + return; + } + + Map<Long, Map<String, TimeoutVO>> appSessionTimeOutMap = new Hashtable<Long, Map<String, TimeoutVO>>(); + // determine the Max TimeOut Time for each of the managed sessions + for (OnboardingApp app : appList) { + if (app.restUrl == null) { + logger.info(EELFLoggerDelegate.debugLogger, "Session Management: null restUrl, not fetching from app " + app.name); + continue; + } + logger.info(EELFLoggerDelegate.debugLogger, "Session Management: Calling App " + app.name + " at URL " + app.restUrl); + String jsonSessionStr = fetchAppSessions(app); + logger.info(EELFLoggerDelegate.debugLogger, "Session Management: App " + app.name + " returned " + jsonSessionStr); + if (jsonSessionStr == null || jsonSessionStr.isEmpty()) + continue; + + try { + Map<String, TimeoutVO> sessionTimeoutMap = mapper.readValue(jsonSessionStr, typeRef); + appSessionTimeOutMap.put(app.id, sessionTimeoutMap); + for (String portalJSessionId : sessionTimeoutMap.keySet()) { + final TimeoutVO maxTimeoutVO = portalSessionTimeoutMap.get(portalJSessionId); + final TimeoutVO compareTimeoutVO = sessionTimeoutMap.get(portalJSessionId); + if (maxTimeoutVO != null && compareTimeoutVO != null) { + if (maxTimeoutVO.compareTo(compareTimeoutVO) < 0) + portalSessionTimeoutMap.get(portalJSessionId) + .setSessionTimOutMilliSec(compareTimeoutVO.getSessionTimOutMilliSec()); + } + } + } catch (JsonParseException | JsonMappingException e) { + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e); + logger.error(EELFLoggerDelegate.errorLogger, + "JSON Mapping/Processing Exception occurred while mapping/parsing the jsonSessionStr", e); + continue; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while mapping/parsing the jsonSessionStr", e); + continue; + } + + } + + // post the updated session timeouts back to the Apps + for (OnboardingApp app : appList) { + if (app.restUrl == null) { + logger.warn(EELFLoggerDelegate.errorLogger, "Session Management: null restUrl, not posting back to app " + app.name); + continue; + } + + Map<String, TimeoutVO> sessionTimeoutMap = appSessionTimeOutMap.get(app.id); + if (sessionTimeoutMap == null || sessionTimeoutMap.isEmpty()) + continue; + + for (String portalJSessionId : sessionTimeoutMap.keySet()) { + try { + final TimeoutVO maxTimeoutVO = portalSessionTimeoutMap.get(portalJSessionId); + final TimeoutVO setTimeoutVO = sessionTimeoutMap.get(portalJSessionId); + if (maxTimeoutVO == null || setTimeoutVO == null) { + String message = String.format( + "Session Management: Failed to update the session timeouts for the app: %s and the sessionId: %s.", + app.name, portalJSessionId); + logger.warn(EELFLoggerDelegate.errorLogger, message); + continue; + } + setTimeoutVO.setSessionTimOutMilliSec(maxTimeoutVO.getSessionTimOutMilliSec()); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Session Management: error while updating the session timeout map", e); + continue; + } + } + logger.info(EELFLoggerDelegate.debugLogger, "Session Management: Updating App " + app.restUrl); + String sessionTimeoutMapStr = ""; + try { + sessionTimeoutMapStr = mapper.writeValueAsString(sessionTimeoutMap); + } catch (JsonProcessingException je) { + logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while processing sessionTimeOutMap object to a String. Details: " + + EcompPortalUtils.getStackTrace(je)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, je); + } + pingAppSessions(app, sessionTimeoutMapStr); + } + String portalSessionTimeoutMapStr = ""; + try { + portalSessionTimeoutMapStr = mapper.writeValueAsString(portalSessionTimeoutMap); + } catch (JsonProcessingException je) { + logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while processing portalSessionTimeOutMap object to a String", je); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, je); + } + manageService.updateSessionExtensions(portalSessionTimeoutMapStr); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "************************ Session Management: error in managing session timeouts", e); + } finally { + getSessionCommunication().clear(true); + } + } + + private String fetchAppSessions(OnboardingApp app) throws Exception { + String jsonSessionValue = getSessionCommunication().sendGet(app); + getSessionCommunication().clear(false); + return jsonSessionValue; + } + + private void pingAppSessions(OnboardingApp app, String sessionTimeoutMapStr) throws Exception { + getSessionCommunication().pingSession(app, sessionTimeoutMapStr); + getSessionCommunication().clear(false); + } + + public void timeoutSessions(HttpSession session) throws Exception { + String portalJSessionId = portalJSessionId(session); + if (onboardedAppList == null) + return; + + for (OnboardingApp app : onboardedAppList) { + getSessionCommunication().timeoutSession(app, portalJSessionId); + getSessionCommunication().clear(false); + } + } + + protected static String portalJSessionId(HttpSession session) { + final Object attribute = session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID); + if (attribute == null) + return ""; + String jSessionKey = (String) attribute; + return jSessionKey.split("-")[0]; + } + + private static ApplicationContext applicationContext; + + public static void setApplicationContext(ApplicationContext _applicationContext) { + applicationContext = _applicationContext; + } + + public SessionCommunication getSessionCommunication() { + if(sessionCommunication == null){ + if (applicationContext != null) + sessionCommunication = (SessionCommunication)applicationContext.getBean("sessionCommunication"); + } + + return sessionCommunication; + } + + public void setSessionCommunication(SessionCommunication sessionCommunication) { + this.sessionCommunication = sessionCommunication; + } + +}
\ No newline at end of file |