/**
   * Gets the {@link SessionContext} without upping its access information and instead checks the
   * current values for timeouts. Can optionally return null or throw an exception.
   *
   * @param uuid
   * @param strict If true, an exception will be raised on timeout; otherwise null returned.
   * @return
   */
  private Data getDataNullOrThrowOnTimeout(String uuid, boolean strict) {
    //
    // All times are in milliseconds
    //

    // Getting quiet so that we have the previous access and hit info
    final Data data = this.sessions.get(uuid);

    if (data == null) {
      // Previously we called internalRemove here, under the
      // assumption that some other thread/event could cause the
      // element to be set to null. That's no longer allowed
      // and will only occur by a call to internalRemove,
      // making that call unneeded.
      if (strict) {
        throw new RemovedSessionException("No context for " + uuid);
      } else {
        return null;
      }
    }

    long lastAccess = data.lastAccessTime;
    long hits = data.hitCount;

    // Get session info
    SessionContext ctx = data.sessionContext;
    long now = System.currentTimeMillis();
    long start = ctx.getSession().getStarted().getTime();
    long timeToIdle = ctx.getSession().getTimeToIdle();
    long timeToLive = ctx.getSession().getTimeToLive();

    // If never accessed, used creation time
    if (lastAccess == 0) {
      lastAccess = start;
    }

    // Calculated
    long alive = now - start;
    long idle = now - lastAccess;

    // Do comparisons if timeTo{} is non-0
    if (0 < timeToLive && timeToLive < alive) {
      String reason =
          reason("timeToLive", lastAccess, hits, start, timeToLive, (alive - timeToLive));
      if (strict) {
        throw new SessionTimeoutException(reason, ctx);
      } else {
        return null;
      }
    } else if (0 < timeToIdle && timeToIdle < idle) {
      String reason =
          reason("timeToIdle", lastAccess, hits, start, timeToIdle, (idle - timeToIdle));
      if (strict) {
        throw new SessionTimeoutException(reason, ctx);
      } else {
        return null;
      }
    }
    return data;
  }
 public void login(Principal principal) {
   // Can't use the method in SessionManager since that leads to a
   // circular reference in Spring.
   final String uuid = principal.getName();
   final SessionContext ctx = cache.getSessionContext(uuid);
   final SessionStats stats = ctx.stats();
   final BasicEventContext c = new BasicEventContext(principal, stats);
   login(c);
 }
 Data(SessionContext sc, long last, long count) {
   this.sessionContext = sc;
   this.lastAccessTime = last;
   this.hitCount = count;
   // clear context
   sc.getSession().getDetails().setContexts(null);
 }