From a80a379d2f7aac17229be562ffa196a6ca865079 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 28 Jul 2021 18:27:52 +1000 Subject: [PATCH] Issue #6556 Ensure context classloader set when operating on memcache. Signed-off-by: Jan Bartel --- .../session/MemcachedSessionDataMap.java | 47 ++++++++++++++++-- .../session/AbstractSessionDataStore.java | 41 ++-------------- .../jetty/server/session/RunnableResult.java | 49 +++++++++++++++++++ 3 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/RunnableResult.java diff --git a/jetty-memcached/jetty-memcached-sessions/src/main/java/org/eclipse/jetty/memcached/session/MemcachedSessionDataMap.java b/jetty-memcached/jetty-memcached-sessions/src/main/java/org/eclipse/jetty/memcached/session/MemcachedSessionDataMap.java index 531da8eaf1b3..53d967e0ed3b 100644 --- a/jetty-memcached/jetty-memcached-sessions/src/main/java/org/eclipse/jetty/memcached/session/MemcachedSessionDataMap.java +++ b/jetty-memcached/jetty-memcached-sessions/src/main/java/org/eclipse/jetty/memcached/session/MemcachedSessionDataMap.java @@ -21,6 +21,7 @@ import net.rubyeye.xmemcached.MemcachedClient; import net.rubyeye.xmemcached.XMemcachedClientBuilder; import net.rubyeye.xmemcached.transcoders.SerializingTranscoder; +import org.eclipse.jetty.server.session.RunnableResult; import org.eclipse.jetty.server.session.SessionContext; import org.eclipse.jetty.server.session.SessionData; import org.eclipse.jetty.server.session.SessionDataMap; @@ -43,6 +44,7 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio protected int _expirySec = 0; protected boolean _heartbeats = true; protected XMemcachedClientBuilder _builder; + protected SessionContext _context; /** * SessionDataTranscoder @@ -140,9 +142,13 @@ public void setHeartbeats(boolean heartbeats) @Override public void initialize(SessionContext context) { + if (isStarted()) + throw new IllegalStateException("Context set after MemcachedSessionDataMap started"); + try { - _builder.setTranscoder(new SessionDataTranscoder()); + _context = context; + _builder.setTranscoder(new SessionDataTranscoder(_context.getContext().getClassLoader())); _client = _builder.build(); _client.setEnableHeartBeat(isHeartbeats()); } @@ -155,14 +161,47 @@ public void initialize(SessionContext context) @Override public SessionData load(String id) throws Exception { - SessionData data = _client.get(id); - return data; + if (!isStarted()) + throw new IllegalStateException("Not started"); + + final RunnableResult result = new RunnableResult<>(); + + Runnable r = () -> + { + try + { + result.setResult(_client.get(id)); + } + catch (Exception e) + { + result.setException(e); + } + }; + + _context.run(r); + return result.getOrThrow(); } @Override public void store(String id, SessionData data) throws Exception { - _client.set(id, _expirySec, data); + if (!isStarted()) + throw new IllegalStateException("Not started"); + + final RunnableResult result = new RunnableResult<>(); + Runnable r = () -> + { + try + { + _client.set(id, _expirySec, data); + } + catch (Exception e) + { + result.setException(e); + } + }; + _context.run(r); + result.throwIfException(); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java index 49ee9690f160..e24a446820d4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java @@ -40,41 +40,6 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem protected long _lastOrphanSweepTime = 0; //last time in ms that we deleted orphaned sessions protected int _savePeriodSec = DEFAULT_SAVE_PERIOD_SEC; //time in sec between saves - /** - * Small utility class to allow us to - * return a result and an Exception - * from invocation of Runnables. - * - * @param the type of the result. - */ - private class Result - { - private V _result; - private Exception _exception; - - public void setResult(V result) - { - _result = result; - } - - public void setException(Exception exception) - { - _exception = exception; - } - - private void throwIfException() throws Exception - { - if (_exception != null) - throw _exception; - } - - public V getOrThrow() throws Exception - { - throwIfException(); - return _result; - } - } - /** * Check if a session for the given id exists. * @@ -171,7 +136,7 @@ public SessionData load(String id) throws Exception if (!isStarted()) throw new IllegalStateException("Not started"); - final Result result = new Result<>(); + final RunnableResult result = new RunnableResult<>(); Runnable r = () -> { @@ -214,7 +179,7 @@ public void store(String id, SessionData data) throws Exception //set the last saved time to now data.setLastSaved(System.currentTimeMillis()); - final Result result = new Result<>(); + final RunnableResult result = new RunnableResult<>(); Runnable r = () -> { try @@ -238,7 +203,7 @@ public void store(String id, SessionData data) throws Exception @Override public boolean exists(String id) throws Exception { - Result result = new Result<>(); + RunnableResult result = new RunnableResult<>(); Runnable r = () -> { try diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/RunnableResult.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/RunnableResult.java new file mode 100644 index 000000000000..e68419d58289 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/RunnableResult.java @@ -0,0 +1,49 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 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.session; + +/** + * Small utility class to allow us to + * return a result and an Exception + * from invocation of Runnables. + * + * @param the type of the result. + */ +public class RunnableResult +{ + private V _result; + private Exception _exception; + + public void setResult(V result) + { + _result = result; + } + + public void setException(Exception exception) + { + _exception = exception; + } + + public void throwIfException() throws Exception + { + if (_exception != null) + throw _exception; + } + + public V getOrThrow() throws Exception + { + throwIfException(); + return _result; + } +} \ No newline at end of file