Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetty 12 - Added a core Session abstraction #9223

Merged
merged 8 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,15 @@ default void push(MetaData.Request resource)

void addHttpStreamWrapper(Function<HttpStream, HttpStream> wrapper);

/**
* <p>Get a {@link Session} associated with the request.
* Sessions may not be supported by a given configuration, in which case
* {@code null} will be returned.</p>
* @param create True if the session should be created for the request.
* @return The session associated with the request or {@code null}.
*/
Session getSession(boolean create);

static String getLocalAddr(Request request)
{
if (request == null)
Expand Down Expand Up @@ -643,6 +652,12 @@ public void addHttpStreamWrapper(Function<HttpStream, HttpStream> wrapper)
getWrapped().addHttpStreamWrapper(wrapper);
}

@Override
public Session getSession(boolean create)
{
return getWrapped().getSession(create);
}

@Override
public Request getWrapped()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.server;

import java.util.Set;

/**
* <p>The interface to a generic session associated with a request.
* This interface may be used directly, or it may be wrapped by an API specific
* representation of a session. Such wrappers must implement the {@link API}
* sub interface.</p>
*/
public interface Session
{
static Session getSession(Object session)
{
if (session instanceof API wrapper)
return wrapper.getSession();
return null;
}

/**
* <p>API wrappers of the {@link Session} must implement this interface and return
* the {@link Session} that they wrap.</p>
*/
interface API
lachlan-roberts marked this conversation as resolved.
Show resolved Hide resolved
{
Session getSession();
}

@SuppressWarnings("unchecked")
<T extends API> T getAPISession();

boolean isValid();

String getId();

String getExtendedId();

String getContextPath();

long getLastAccessedTime();

void setMaxInactiveInterval(int secs);

int getMaxInactiveInterval();

Object getAttribute(String name);

int getAttributes();

Set<String> getNames();

void setAttribute(String name, Object value);

void removeAttribute(String name);

void renewId(Request request, Response response);

void invalidate();

boolean isNew() throws IllegalStateException;
lachlan-roberts marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ public static ContextHandler getCurrentContextHandler()
public static ContextHandler getContextHandler(Request request)
{
ContextRequest contextRequest = Request.as(request, ContextRequest.class);
return (contextRequest == null) ? null : contextRequest.getContext().getContextHandler();
if (contextRequest == null)
return null;
return contextRequest.getContext() instanceof ScopedContext scoped ? scoped.getContextHandler() : null;
}

public static String getServerInfo()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import java.util.function.Predicate;

import org.eclipse.jetty.server.Context;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.thread.Invocable;
import org.slf4j.Logger;
Expand Down Expand Up @@ -51,7 +52,7 @@ public boolean addErrorListener(Predicate<Throwable> onError)
}

@Override
public ContextHandler.ScopedContext getContext()
public Context getContext()
{
return _context;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Session;
import org.eclipse.jetty.server.TunnelSupport;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.BufferUtil;
Expand Down Expand Up @@ -955,6 +956,12 @@ public void addHttpStreamWrapper(Function<HttpStream, HttpStream> wrapper)
getHttpChannel().addHttpStreamWrapper(wrapper);
}

@Override
public Session getSession(boolean create)
{
return null;
lachlan-roberts marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public String toString()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

import org.eclipse.jetty.server.Session;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
Expand Down Expand Up @@ -107,7 +108,7 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
* @return a new Session object
*/
@Override
public abstract Session newSession(SessionData data);
public abstract ManagedSession newSession(SessionData data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these all need to use the ManagedSession class and not the Session interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applications use Session.
Implementations of Session use SessionManagers and SessionHandlers and SessionCaches and SessionData to implement a ManagedSession, thus they communicate within themselves with ManagedSession.

If you are just a handler/servlet that wants to use a session, you just see/use Session interface. But if you are implementing/extending our style of concrete session you see/use ManagedSession


/**
* Get the session matching the key from the cache. Does not load
Expand All @@ -116,7 +117,7 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
* @param id session id
* @return the Session object matching the id
*/
protected abstract Session doGet(String id);
protected abstract ManagedSession doGet(String id);

/**
* Put the session into the map if it wasn't already there
Expand All @@ -125,7 +126,7 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
* @param session the session object
* @return null if the session wasn't already in the map, or the existing entry otherwise
*/
protected abstract Session doPutIfAbsent(String id, Session session);
protected abstract Session doPutIfAbsent(String id, ManagedSession session);

/**
* Compute the mappingFunction to create a Session object iff the session
Expand All @@ -137,7 +138,7 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
* @param mappingFunction the function to load the data for the session
* @return an existing Session from the cache
*/
protected abstract Session doComputeIfAbsent(String id, Function<String, Session> mappingFunction);
protected abstract ManagedSession doComputeIfAbsent(String id, Function<String, ManagedSession> mappingFunction);

/**
* Replace the mapping from id to oldValue with newValue
Expand All @@ -147,15 +148,15 @@ public abstract class AbstractSessionCache extends ContainerLifeCycle implements
* @param newValue the new value
* @return true if replacement was done
*/
protected abstract boolean doReplace(String id, Session oldValue, Session newValue);
protected abstract boolean doReplace(String id, ManagedSession oldValue, ManagedSession newValue);

/**
* Remove the session with this identity from the store
*
* @param id the id
* @return Session that was removed or null
*/
public abstract Session doDelete(String id);
public abstract ManagedSession doDelete(String id);

/**
* @param handler the {@link SessionManager} to use
Expand Down Expand Up @@ -296,7 +297,7 @@ public boolean isFlushOnResponseCommit()
*
*/
@Override
public Session get(String id) throws Exception
public ManagedSession get(String id) throws Exception
{
return getAndEnter(id, true);
}
Expand All @@ -312,9 +313,9 @@ public Session get(String id) throws Exception
* @return the session if it exists, null otherwise
* @throws Exception if the session cannot be loaded
*/
protected Session getAndEnter(String id, boolean enter) throws Exception
protected ManagedSession getAndEnter(String id, boolean enter) throws Exception
{
Session session = null;
ManagedSession session = null;
AtomicReference<Exception> exception = new AtomicReference<Exception>();

session = doComputeIfAbsent(id, k ->
Expand All @@ -324,7 +325,7 @@ protected Session getAndEnter(String id, boolean enter) throws Exception

try
{
Session s = loadSession(k);
ManagedSession s = loadSession(k);
if (s != null)
{
try (AutoLock lock = s.lock())
Expand Down Expand Up @@ -376,11 +377,11 @@ else if (enter)
* @param id the id
* @return a Session object filled with data or null if the session doesn't exist
*/
private Session loadSession(String id)
private ManagedSession loadSession(String id)
throws Exception
{
SessionData data = null;
Session session = null;
ManagedSession session = null;

if (_sessionDataStore == null)
return null; //can't load it
Expand Down Expand Up @@ -413,7 +414,7 @@ private Session loadSession(String id)
* @param session the session
*/
@Override
public void add(String id, Session session) throws Exception
public void add(String id, ManagedSession session) throws Exception
{
if (id == null || session == null)
throw new IllegalArgumentException("Add key=" + id + " session=" + (session == null ? "null" : session.getId()));
Expand Down Expand Up @@ -444,7 +445,7 @@ public void add(String id, Session session) throws Exception
* or on other nodes.
*/
@Override
public void commit(Session session) throws Exception
public void commit(ManagedSession session) throws Exception
{
if (session == null)
return;
Expand Down Expand Up @@ -487,7 +488,7 @@ public void commit(Session session) throws Exception
*
*/
@Override
public void release(Session session) throws Exception
public void release(ManagedSession session) throws Exception
{
if (session == null || session.getId() == null)
throw new IllegalArgumentException((session == null ? "Null session" : "Null session id"));
Expand Down Expand Up @@ -578,7 +579,7 @@ public void release(Session session) throws Exception
public boolean exists(String id) throws Exception
{
//try the object store first
Session s = doGet(id);
ManagedSession s = doGet(id);
if (s != null)
{
try (AutoLock lock = s.lock())
Expand Down Expand Up @@ -609,10 +610,10 @@ public boolean contains(String id) throws Exception
*
*/
@Override
public Session delete(String id) throws Exception
public ManagedSession delete(String id) throws Exception
{
//get the session, if its not in memory, this will load it
Session session = getAndEnter(id, false);
ManagedSession session = getAndEnter(id, false);

//Always delete it from the backing data store
if (_sessionDataStore != null)
Expand Down Expand Up @@ -645,7 +646,7 @@ public Set<String> checkExpiration(Set<String> candidates)
{
for (String c : allCandidates)
{
Session s = doGet(c);
ManagedSession s = doGet(c);
if (s != null && s.getRequests() > 0) //if the session is in my cache, check its not in use first
sessionsInUse.add(c);
}
Expand All @@ -671,7 +672,7 @@ public Set<String> checkExpiration(Set<String> candidates)
* @param session session to check
*/
@Override
public void checkInactiveSession(Session session)
public void checkInactiveSession(ManagedSession session)
{
if (session == null)
return;
Expand Down Expand Up @@ -713,15 +714,15 @@ public void checkInactiveSession(Session session)
}

@Override
public Session renewSessionId(String oldId, String newId, String oldExtendedId, String newExtendedId)
public ManagedSession renewSessionId(String oldId, String newId, String oldExtendedId, String newExtendedId)
throws Exception
{
if (StringUtil.isBlank(oldId))
throw new IllegalArgumentException("Old session id is null");
if (StringUtil.isBlank(newId))
throw new IllegalArgumentException("New session id is null");

Session session = getAndEnter(oldId, true);
ManagedSession session = getAndEnter(oldId, true);
renewSessionId(session, newId, newExtendedId);

return session;
Expand All @@ -735,7 +736,7 @@ public Session renewSessionId(String oldId, String newId, String oldExtendedId,
* @param newExtendedId the full id plus node id
* @throws Exception if there was a failure saving the change
*/
protected void renewSessionId(Session session, String newId, String newExtendedId)
protected void renewSessionId(ManagedSession session, String newId, String newExtendedId)
throws Exception
{
if (session == null)
Expand Down Expand Up @@ -796,11 +797,11 @@ public boolean isSaveOnInactiveEviction()
}

@Override
public Session newSession(String id, long time, long maxInactiveMs)
public ManagedSession newSession(String id, long time, long maxInactiveMs)
{
if (LOG.isDebugEnabled())
LOG.debug("Creating new session id={}", id);
Session session = newSession(_sessionDataStore.newSessionData(id, time, time, time, maxInactiveMs));
ManagedSession session = newSession(_sessionDataStore.newSessionData(id, time, time, time, maxInactiveMs));
session.getSessionData().setLastNode(_context.getWorkerName());
try
{
Expand Down
Loading