* Issue #6556 Ensure context classloader set when operating on memcache. Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
parent
409a2fc9ff
commit
90a72b0798
|
@ -25,6 +25,7 @@ import org.eclipse.jetty.server.session.SessionContext;
|
|||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataMap;
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
|
@ -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,8 +142,12 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio
|
|||
@Override
|
||||
public void initialize(SessionContext context)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Context set after MemcachedSessionDataMap started");
|
||||
|
||||
try
|
||||
{
|
||||
_context = context;
|
||||
_builder.setTranscoder(new SessionDataTranscoder());
|
||||
_client = _builder.build();
|
||||
_client.setEnableHeartBeat(isHeartbeats());
|
||||
|
@ -155,14 +161,48 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio
|
|||
@Override
|
||||
public SessionData load(String id) throws Exception
|
||||
{
|
||||
SessionData data = _client.get(id);
|
||||
return data;
|
||||
if (!isStarted())
|
||||
throw new IllegalStateException("Not started");
|
||||
|
||||
final FuturePromise<SessionData> result = new FuturePromise<>();
|
||||
|
||||
Runnable r = () ->
|
||||
{
|
||||
try
|
||||
{
|
||||
result.succeeded(_client.get(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.failed(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 FuturePromise<Void> result = new FuturePromise<>();
|
||||
Runnable r = () ->
|
||||
{
|
||||
try
|
||||
{
|
||||
_client.set(id, _expirySec, data);
|
||||
result.succeeded(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.failed(e);
|
||||
}
|
||||
};
|
||||
_context.run(r);
|
||||
result.getOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,8 +15,10 @@ package org.eclipse.jetty.server.session;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
|
@ -40,41 +42,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 <V> the type of the result.
|
||||
*/
|
||||
private class Result<V>
|
||||
{
|
||||
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,21 +138,22 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
|||
if (!isStarted())
|
||||
throw new IllegalStateException("Not started");
|
||||
|
||||
final Result<SessionData> result = new Result<>();
|
||||
final FuturePromise<SessionData> result = new FuturePromise<>();
|
||||
|
||||
Runnable r = () ->
|
||||
{
|
||||
try
|
||||
{
|
||||
result.setResult(doLoad(id));
|
||||
result.succeeded(doLoad(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.setException(e);
|
||||
result.failed(e);
|
||||
}
|
||||
};
|
||||
|
||||
_context.run(r);
|
||||
|
||||
return result.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -214,7 +182,7 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
|||
//set the last saved time to now
|
||||
data.setLastSaved(System.currentTimeMillis());
|
||||
|
||||
final Result<Object> result = new Result<>();
|
||||
final FuturePromise<Void> result = new FuturePromise<>();
|
||||
Runnable r = () ->
|
||||
{
|
||||
try
|
||||
|
@ -222,32 +190,33 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
|||
//call the specific store method, passing in previous save time
|
||||
doStore(id, data, lastSave);
|
||||
data.clean(); //unset all dirty flags
|
||||
result.succeeded(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//reset last save time if save failed
|
||||
data.setLastSaved(lastSave);
|
||||
result.setException(e);
|
||||
result.failed(e);
|
||||
}
|
||||
};
|
||||
_context.run(r);
|
||||
result.throwIfException();
|
||||
result.getOrThrow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String id) throws Exception
|
||||
{
|
||||
Result<Boolean> result = new Result<>();
|
||||
FuturePromise<Boolean> result = new FuturePromise<>();
|
||||
Runnable r = () ->
|
||||
{
|
||||
try
|
||||
{
|
||||
result.setResult(doExists(id));
|
||||
result.succeeded(doExists(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.setException(e);
|
||||
result.failed(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -119,6 +119,30 @@ public class FuturePromise<C> implements Future<C>, Promise<C>
|
|||
throw new ExecutionException(_cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result if completed successfully
|
||||
* or in the case of failure, throw the
|
||||
* Exception/Error, or an ExecutionException wrapping
|
||||
* the cause if it is neither an Exception or Error.
|
||||
*
|
||||
* @return the computed result
|
||||
* @throws Exception if the cause is an Exception or Error,
|
||||
* otherwise an ExecutionException wrapping the cause
|
||||
*/
|
||||
public C getOrThrow() throws Exception
|
||||
{
|
||||
_latch.await();
|
||||
|
||||
if (_cause == COMPLETED)
|
||||
return _result;
|
||||
if (_cause instanceof Exception)
|
||||
throw (Exception)_cause;
|
||||
if (_cause instanceof Error)
|
||||
throw (Error)_cause;
|
||||
|
||||
throw new ExecutionException(_cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public C get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue