<commit_before>/*
 * $Id$
 *
 * Copyright 2003-2008 Online Breedband B.V.
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.server.frontend;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.log4j.NDC;
import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.Utils;
import org.xins.common.collections.ChainedMap;
import org.xins.common.collections.InvalidPropertyValueException;
import org.xins.common.collections.MissingRequiredPropertyException;
import org.xins.common.collections.PropertyReader;
import org.xins.common.manageable.BootstrapException;
import org.xins.common.manageable.Manageable;
import org.xins.common.spec.FunctionSpec;
import org.xins.common.text.TextUtils;
import org.xins.server.API;
import org.xins.server.Log;

/**
 * Manager for the sessions and session properties for the XINS front-end framework.
 * This class assumes that the Log4J NDC is unique per request.
 *
 * @version $Revision$ $Date$
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 *
 * @since XINS 1.5.0.
 */
public class SessionManager extends Manageable {

   /**
    * The API, never <code>null</code>.
    */
   private API _api;

   /**
    * The current HTTP sessions, never <code>null</code>.
    */
   private Hashtable _currentSessions = new Hashtable();

   /**
    * The list of pages that doesn't need to be logged in, cannot be <code>null</code>.
    */
   private ArrayList _unrestrictedPages = new ArrayList();

   /**
    * The default page, cannot be <code>null</code>.
    */
   private String _defaultCommand;

   /**
    * Creates the session manager.
    *
    * @param api
    *    the API.
    */
   public SessionManager(API api) {
      _api = api;
   }

   protected void bootstrapImpl(PropertyReader bootstrapProperties)
   throws MissingRequiredPropertyException,
         InvalidPropertyValueException,
         BootstrapException {
      _defaultCommand = bootstrapProperties.get("xinsff.default.command");
      if (_defaultCommand == null) {
         _defaultCommand = "DefaultCommand";
      }
      String loginPage = bootstrapProperties.get("xinsff.login.page");
      if (loginPage != null) {
         _unrestrictedPages.add(loginPage);
         _unrestrictedPages.add("Control");
         _unrestrictedPages.add("Logout");
         String unrestrictedPages = bootstrapProperties.get("xinsff.unrestricted.pages");
         if (unrestrictedPages != null && !unrestrictedPages.equals("")) {
            StringTokenizer stUnrestricted = new StringTokenizer(unrestrictedPages, ",", false);
            while (stUnrestricted.hasMoreTokens()) {
               String nextPage = stUnrestricted.nextToken();
               _unrestrictedPages.add(nextPage);
            }
         }
      } else {
         _unrestrictedPages.add("*");
      }
   }

   /**
    * Method called when the request is received.
    *
    * This method will take care of creating a sessionId if needed and
    * putting the input parameters in the session.
    *
    * @param request
    *    the HTTP request, cannot be <code>null</code>.
    */
   protected void request(HttpServletRequest request) {

      // Find the session ID in the cookies
      String sessionId = null;
      Cookie[] cookies = request.getCookies();
      int cookieCount = (cookies == null) ? 0 : cookies.length;
      for (int i = 0; i < cookieCount && sessionId == null; i++) {
         Cookie cookie = cookies[i];
         String name = cookie.getName();
         if ("SessionID".equals(name)) {
            sessionId = cookie.getValue();
         }
      }

      HttpSession session = request.getSession(true);
      String ndc = NDC.get();
      _currentSessions.put(ndc, session);

      // If the session ID is not found in the cookies, create a new one
      if (sessionId == null || sessionId.equals("") || sessionId.equals("null")) {

         sessionId = session.getId();
         setProperty(sessionId, Boolean.FALSE);
      }

      // Fill the input parameters
      Map inputParameters = new ChainedMap();
      Enumeration params = request.getParameterNames();
      while (params.hasMoreElements()) {
         String name = (String) params.nextElement();
         String value = request.getParameter(name);
         if ("".equals(value) || name.equals(getSessionId())) {
            value = null;
         }
         inputParameters.put(name, value);
      }
      setProperty("_inputs", inputParameters);
      setProperty("_remoteIP", request.getRemoteAddr());
      setProperty("_propertiesSet", new HashSet());
      setProperty("_userAgent", request.getHeader("User-Agent"));
   }

   /**
    * Sets the input parameters in the session is the execution of the function is successful.
    *
    * @param successful
    *    <code>true</code> if the function is successful, <code>false</code> otherwise.
    */
   protected void result(boolean successful) {
      if (successful) {
         Map inputParameters = (Map) getProperty("_inputs");
         Set propertiesSet =  (Set) getProperty("_propertiesSet");
         if (propertiesSet.contains("*")) {
            return;
         }

         // Only valid inputs of an existing function will be added.
         String command = (String) inputParameters.get("command");
         String action = (String) inputParameters.get("action");
         String functionName = command;
         if (action != null && !action.equals("") && !action.equalsIgnoreCase("show")) {
            functionName += TextUtils.firstCharUpper(action);
         }
         try {
            Map specInputParameters = _api.getAPISpecification().getFunction(functionName).getInputParameters();
            Map clonedInputParameters = new ChainedMap();
            clonedInputParameters.putAll(inputParameters);
            Iterator itInputParameters = clonedInputParameters.entrySet().iterator();
            while (itInputParameters.hasNext()) {
               Map.Entry nextInput = (Map.Entry) itInputParameters.next();
               String parameterName = (String) nextInput.getKey();
               parameterName = getRealParameter(parameterName, functionName);
               if (specInputParameters.containsKey(parameterName) && !propertiesSet.contains(parameterName)
                     && !propertiesSet.contains(parameterName.toLowerCase())) {
                  String value = (String) nextInput.getValue();
                  if ("".equals(value) || parameterName.equals(getSessionId())) {
                     value = null;
                  }
                  setProperty(parameterName.toLowerCase(), value);
               }
            }
         } catch (Exception ex) {
            // Ignore
            Utils.logIgnoredException(ex);
         }
      }
   }

   /**
    * Returns <code>true</code> if the user needs to log in to access the page.
    *
    * @return
    *    whether the user should log in.
    **/
   public boolean shouldLogIn() {
      // Check if the page requires a login
      Map inputParameters = (Map) getProperty("_inputs");
      String command = (String) inputParameters.get("command");
      if (command == null || command.equals("")) {
         command = _defaultCommand;
      }
      if (_unrestrictedPages.contains("*") ||
            _unrestrictedPages.contains(command) ||
            (command != null && command.startsWith("_"))) {
         return false;
      }

      // Check if the user is logged in
      boolean shouldLogIn = !getBoolProperty(getSessionId());
      return shouldLogIn;
   }

   /**
    * Gets the session id.
    *<commit_msg>Clear the session when no longer needed.<commit_after>/*
 * $Id$
 *
 * Copyright 2003-2008 Online Breedband B.V.
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.server.frontend;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.log4j.NDC;
import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.Utils;
import org.xins.common.collections.ChainedMap;
import org.xins.common.collections.InvalidPropertyValueException;
import org.xins.common.collections.MissingRequiredPropertyException;
import org.xins.common.collections.PropertyReader;
import org.xins.common.manageable.BootstrapException;
import org.xins.common.manageable.Manageable;
import org.xins.common.spec.FunctionSpec;
import org.xins.common.text.TextUtils;
import org.xins.server.API;
import org.xins.server.Log;

/**
 * Manager for the sessions and session properties for the XINS front-end framework.
 * This class assumes that the Log4J NDC is unique per request.
 *
 * @version $Revision$ $Date$
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 *
 * @since XINS 1.5.0.
 */
public class SessionManager extends Manageable {

   /**
    * The API, never <code>null</code>.
    */
   private API _api;

   /**
    * The current HTTP sessions, never <code>null</code>.
    */
   private Hashtable _currentSessions = new Hashtable();

   /**
    * The list of pages that doesn't need to be logged in, cannot be <code>null</code>.
    */
   private ArrayList _unrestrictedPages = new ArrayList();

   /**
    * The default page, cannot be <code>null</code>.
    */
   private String _defaultCommand;

   /**
    * Creates the session manager.
    *
    * @param api
    *    the API.
    */
   public SessionManager(API api) {
      _api = api;
   }

   protected void bootstrapImpl(PropertyReader bootstrapProperties)
   throws MissingRequiredPropertyException,
         InvalidPropertyValueException,
         BootstrapException {
      _defaultCommand = bootstrapProperties.get("xinsff.default.command");
      if (_defaultCommand == null) {
         _defaultCommand = "DefaultCommand";
      }
      String loginPage = bootstrapProperties.get("xinsff.login.page");
      if (loginPage != null) {
         _unrestrictedPages.add(loginPage);
         _unrestrictedPages.add("Control");
         _unrestrictedPages.add("Logout");
         String unrestrictedPages = bootstrapProperties.get("xinsff.unrestricted.pages");
         if (unrestrictedPages != null && !unrestrictedPages.equals("")) {
            StringTokenizer stUnrestricted = new StringTokenizer(unrestrictedPages, ",", false);
            while (stUnrestricted.hasMoreTokens()) {
               String nextPage = stUnrestricted.nextToken();
               _unrestrictedPages.add(nextPage);
            }
         }
      } else {
         _unrestrictedPages.add("*");
      }
   }

   /**
    * Method called when the request is received.
    *
    * This method will take care of creating a sessionId if needed and
    * putting the input parameters in the session.
    *
    * @param request
    *    the HTTP request, cannot be <code>null</code>.
    */
   protected void request(HttpServletRequest request) {

      // Find the session ID in the cookies
      String sessionId = null;
      Cookie[] cookies = request.getCookies();
      int cookieCount = (cookies == null) ? 0 : cookies.length;
      for (int i = 0; i < cookieCount && sessionId == null; i++) {
         Cookie cookie = cookies[i];
         String name = cookie.getName();
         if ("SessionID".equals(name)) {
            sessionId = cookie.getValue();
         }
      }

      HttpSession session = request.getSession(true);
      String ndc = NDC.get();
      _currentSessions.put(ndc, session);

      // If the session ID is not found in the cookies, create a new one
      if (sessionId == null || sessionId.equals("") || sessionId.equals("null")) {

         sessionId = session.getId();
         setProperty(sessionId, Boolean.FALSE);
      }

      // Fill the input parameters
      Map inputParameters = new ChainedMap();
      Enumeration params = request.getParameterNames();
      while (params.hasMoreElements()) {
         String name = (String) params.nextElement();
         String value = request.getParameter(name);
         if ("".equals(value) || name.equals(getSessionId())) {
            value = null;
         }
         inputParameters.put(name, value);
      }
      setProperty("_inputs", inputParameters);
      setProperty("_remoteIP", request.getRemoteAddr());
      setProperty("_propertiesSet", new HashSet());
      setProperty("_userAgent", request.getHeader("User-Agent"));
   }

   /**
    * Sets the input parameters in the session is the execution of the function is successful.
    *
    * @param successful
    *    <code>true</code> if the function is successful, <code>false</code> otherwise.
    */
   protected void result(boolean successful) {
      if (successful) {
         Map inputParameters = (Map) getProperty("_inputs");
         Set propertiesSet =  (Set) getProperty("_propertiesSet");
         if (propertiesSet.contains("*")) {
            return;
         }

         // Only valid inputs of an existing function will be added.
         String command = (String) inputParameters.get("command");
         String action = (String) inputParameters.get("action");
         String functionName = command;
         if (action != null && !action.equals("") && !action.equalsIgnoreCase("show")) {
            functionName += TextUtils.firstCharUpper(action);
         }
         try {
            Map specInputParameters = _api.getAPISpecification().getFunction(functionName).getInputParameters();
            Map clonedInputParameters = new ChainedMap();
            clonedInputParameters.putAll(inputParameters);
            Iterator itInputParameters = clonedInputParameters.entrySet().iterator();
            while (itInputParameters.hasNext()) {
               Map.Entry nextInput = (Map.Entry) itInputParameters.next();
               String parameterName = (String) nextInput.getKey();
               parameterName = getRealParameter(parameterName, functionName);
               if (specInputParameters.containsKey(parameterName) && !propertiesSet.contains(parameterName)
                     && !propertiesSet.contains(parameterName.toLowerCase())) {
                  String value = (String) nextInput.getValue();
                  if ("".equals(value) || parameterName.equals(getSessionId())) {
                     value = null;
                  }
                  setProperty(parameterName.toLowerCase(), value);
               }
            }
         } catch (Exception ex) {
            // Ignore
            Utils.logIgnoredException(ex);
         }
      }
      _currentSessions.remove(NDC.get());
   }

   /**
    * Returns <code>true</code> if the user needs to log in to access the page.
    *
    * @return
    *    whether the user should log in.
    **/
   public boolean shouldLogIn() {
      // Check if the page requires a login
      Map inputParameters = (Map) getProperty("_inputs");
      String command = (String) inputParameters.get("command");
      if (command == null || command.equals("")) {
         command = _defaultCommand;
      }
      if (_unrestrictedPages.contains("*") ||
            _unrestrictedPages.contains(command) ||
            (command != null && command.startsWith("_"))) {
         return false;
      }

      // Check if the user is logged in
      boolean shouldLogIn = !getBoolProperty(getSessionId());
      return shouldLogIn;
   }

   /**
    * Gets the session id.
    *
{'fraction_non_alphanumeric': 0.11424960505529226, 'fraction_numerical': 0.0018957345971563982, 'mean_word_length': 2.632315813633234, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1089956', 'n_tokens_mistral': 4341, 'n_tokens_neox': 4192, 'n_words': 1077}