* 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.SessionData;
|
||||||
import org.eclipse.jetty.server.session.SessionDataMap;
|
import org.eclipse.jetty.server.session.SessionDataMap;
|
||||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
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.ManagedAttribute;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||||
|
@ -43,6 +44,7 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio
|
||||||
protected int _expirySec = 0;
|
protected int _expirySec = 0;
|
||||||
protected boolean _heartbeats = true;
|
protected boolean _heartbeats = true;
|
||||||
protected XMemcachedClientBuilder _builder;
|
protected XMemcachedClientBuilder _builder;
|
||||||
|
protected SessionContext _context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionDataTranscoder
|
* SessionDataTranscoder
|
||||||
|
@ -140,8 +142,12 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio
|
||||||
@Override
|
@Override
|
||||||
public void initialize(SessionContext context)
|
public void initialize(SessionContext context)
|
||||||
{
|
{
|
||||||
|
if (isStarted())
|
||||||
|
throw new IllegalStateException("Context set after MemcachedSessionDataMap started");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_context = context;
|
||||||
_builder.setTranscoder(new SessionDataTranscoder());
|
_builder.setTranscoder(new SessionDataTranscoder());
|
||||||
_client = _builder.build();
|
_client = _builder.build();
|
||||||
_client.setEnableHeartBeat(isHeartbeats());
|
_client.setEnableHeartBeat(isHeartbeats());
|
||||||
|
@ -155,14 +161,48 @@ public class MemcachedSessionDataMap extends AbstractLifeCycle implements Sessio
|
||||||
@Override
|
@Override
|
||||||
public SessionData load(String id) throws Exception
|
public SessionData load(String id) throws Exception
|
||||||
{
|
{
|
||||||
SessionData data = _client.get(id);
|
if (!isStarted())
|
||||||
return data;
|
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
|
@Override
|
||||||
public void store(String id, SessionData data) throws Exception
|
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
|
@Override
|
||||||
|
|
|
@ -15,8 +15,10 @@ package org.eclipse.jetty.server.session;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.FuturePromise;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
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 long _lastOrphanSweepTime = 0; //last time in ms that we deleted orphaned sessions
|
||||||
protected int _savePeriodSec = DEFAULT_SAVE_PERIOD_SEC; //time in sec between saves
|
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.
|
* Check if a session for the given id exists.
|
||||||
*
|
*
|
||||||
|
@ -171,21 +138,22 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
||||||
if (!isStarted())
|
if (!isStarted())
|
||||||
throw new IllegalStateException("Not started");
|
throw new IllegalStateException("Not started");
|
||||||
|
|
||||||
final Result<SessionData> result = new Result<>();
|
final FuturePromise<SessionData> result = new FuturePromise<>();
|
||||||
|
|
||||||
Runnable r = () ->
|
Runnable r = () ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result.setResult(doLoad(id));
|
result.succeeded(doLoad(id));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
result.setException(e);
|
result.failed(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_context.run(r);
|
_context.run(r);
|
||||||
|
|
||||||
return result.getOrThrow();
|
return result.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +182,7 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
||||||
//set the last saved time to now
|
//set the last saved time to now
|
||||||
data.setLastSaved(System.currentTimeMillis());
|
data.setLastSaved(System.currentTimeMillis());
|
||||||
|
|
||||||
final Result<Object> result = new Result<>();
|
final FuturePromise<Void> result = new FuturePromise<>();
|
||||||
Runnable r = () ->
|
Runnable r = () ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -222,32 +190,33 @@ public abstract class AbstractSessionDataStore extends ContainerLifeCycle implem
|
||||||
//call the specific store method, passing in previous save time
|
//call the specific store method, passing in previous save time
|
||||||
doStore(id, data, lastSave);
|
doStore(id, data, lastSave);
|
||||||
data.clean(); //unset all dirty flags
|
data.clean(); //unset all dirty flags
|
||||||
|
result.succeeded(null);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//reset last save time if save failed
|
//reset last save time if save failed
|
||||||
data.setLastSaved(lastSave);
|
data.setLastSaved(lastSave);
|
||||||
result.setException(e);
|
result.failed(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_context.run(r);
|
_context.run(r);
|
||||||
result.throwIfException();
|
result.getOrThrow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exists(String id) throws Exception
|
public boolean exists(String id) throws Exception
|
||||||
{
|
{
|
||||||
Result<Boolean> result = new Result<>();
|
FuturePromise<Boolean> result = new FuturePromise<>();
|
||||||
Runnable r = () ->
|
Runnable r = () ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result.setResult(doExists(id));
|
result.succeeded(doExists(id));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
result.setException(e);
|
result.failed(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,30 @@ public class FuturePromise<C> implements Future<C>, Promise<C>
|
||||||
throw (CancellationException)new CancellationException().initCause(_cause);
|
throw (CancellationException)new CancellationException().initCause(_cause);
|
||||||
throw new ExecutionException(_cause);
|
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
|
@Override
|
||||||
public C get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
public C get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||||
|
|
Loading…
Reference in New Issue