package org.dcache.services.login;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.Principal;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import diskCacheV111.util.CacheException;
import diskCacheV111.util.PermissionDeniedCacheException;
import dmg.cells.nucleus.CellMessage;
import org.dcache.auth.LoginReply;
import org.dcache.auth.LoginStrategy;
import dmg.cells.nucleus.CellMessageReceiver;
public class MessageHandler
implements CellMessageReceiver
{
private static final Logger _log =
LoggerFactory.getLogger(MessageHandler.class);
private LoginStrategy _loginStrategy;
private ScheduledExecutorService _executor;
public void setLoginStrategy(LoginStrategy loginStrategy)
{
_loginStrategy = loginStrategy;
}
public LoginStrategy getLoginStrategy()
{
return _loginStrategy;
}
public void setTimeoutExecutor(ScheduledExecutorService executor)
{
_executor = executor;
}
public ScheduledExecutorService getTimeoutExecutor()
{
return _executor;
}
/**
* Schedules a timeout task for the given request. The task will
* interrupt the calling thread if the timeout is reached before
* the task is cancelled.
*/
private ScheduledFuture<?> scheduleTimeoutTask(CellMessage envelope)
{
Thread self = Thread.currentThread();
return _executor.schedule(self::interrupt,
envelope.getTtl() - envelope.getLocalAge(),
TimeUnit.MILLISECONDS);
}
public LoginMessage messageArrived(CellMessage envelope, LoginMessage message)
throws CacheException
{
ScheduledFuture<?> timeoutTask = scheduleTimeoutTask(envelope);
try {
LoginReply login = _loginStrategy.login(message.getSubject());
message.setSubject(login.getSubject());
message.setLoginAttributes(login.getLoginAttributes());
} catch(RuntimeException e) {
_log.error("Login operation failed", e);
throw new PermissionDeniedCacheException(e.getMessage());
} finally {
timeoutTask.cancel(false);
}
return message;
}
public MapMessage messageArrived(MapMessage message)
throws CacheException
{
Principal principal;
try {
principal = _loginStrategy.map(message.getPrincipal());
} catch(RuntimeException e) {
_log.error("Map operation failed", e);
principal = null;
}
message.setMappedPrincipal(principal);
return message;
}
public ReverseMapMessage messageArrived(ReverseMapMessage message)
throws CacheException
{
Set<Principal> principals;
try {
principals = _loginStrategy.reverseMap(message.getPrincipal());
} catch(RuntimeException e) {
_log.error("ReverseMap operation failed", e);
principals = Collections.emptySet();
}
message.setMappedPrincipals(principals);
return message;
}
}