All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.apphosting.runtime.jetty.AppEngineSession Maven / Gradle / Ivy

There is a newer version: 2.0.31
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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 com.google.apphosting.runtime.jetty;

import java.io.NotSerializableException;
import java.io.Serializable;
import org.eclipse.jetty.server.Session;
import org.eclipse.jetty.session.ManagedSession;
import org.eclipse.jetty.session.SessionData;
import org.eclipse.jetty.session.SessionManager;
import org.eclipse.jetty.util.thread.AutoLock;

/**
 * This subclass exists to prevent a call to setMaxInactiveInterval(int) marking the session as
 * dirty and thus requiring it to be written out: in AppEngine the maxInactiveInterval of a session
 * is not persisted. It also keeps the Jetty 9.3 behavior for setAttribute calls which is to throw a
 * RuntimeException for non-serializable values.
 */
class AppEngineSession extends ManagedSession {
  /**
   * To reduce our datastore put time, we only consider a session dirty on access if it is at least
   * 25% of the way to its expiration time. So a session that expires in 1 hr will only be re-stored
   * every 15 minutes, unless a "real" attribute change occurs.
   */
  private static final double UPDATE_TIMESTAMP_RATIO = 0.75;

  /**
   * Create a new session object. Usually after the data has been loaded.
   *
   * @param manager the SessionManager to which the session pertains
   * @param data the info of the session
   */
  AppEngineSession(SessionManager manager, SessionData data) {
    super(manager, data);
  }

  /**
   * @see Session#setMaxInactiveInterval(int)
   */
  @Override
  public void setMaxInactiveInterval(int secs) {
    try (AutoLock lock = _lock.lock()) {
      boolean savedDirty = _sessionData.isDirty();
      super.setMaxInactiveInterval(secs);
      // Ensure it is unchanged by call to setMaxInactiveInterval
      _sessionData.setDirty(savedDirty);
    }
  }

  /**
   * If the session is nearing its expiry time, we mark it as dirty whether any attributes change
   * during this access. The default Jetty implementation does not handle the AppEngine specific
   * dirty state.
   */
  @Override
  public boolean access(long time) {
    try (AutoLock lock = _lock.lock()) {
      if (isValid()) {
        long timeRemaining = _sessionData.getExpiry() - time;
        if (timeRemaining < (_sessionData.getMaxInactiveMs() * UPDATE_TIMESTAMP_RATIO)) {
          _sessionData.setDirty(true);
        }
      }
      return super.access(time);
    }
  }

  @Override
  public Object setAttribute(String name, Object value) {
    // We want to keep the previous Jetty 9 App Engine implementation that emits a
    // NotSerializableException wrapped in a RuntimeException, and do the check as soon as possible.
    if ((value != null) && !(value instanceof Serializable)) {
      throw new RuntimeException(new NotSerializableException(value.getClass().getName()));
    }
    return super.setAttribute(name, value);
  }

  @Override
  public boolean isResident() {
    // Are accesses to non-resident sessions allowed?  This flag preserves GAE on jetty-9.3
    // behaviour. May be set in JavaRuntimeMain. If set will pretend to always be resident
    return super.isResident() || Boolean.getBoolean("gae.allow_non_resident_session_access");
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy