package org.marketcetera.photon.core;
import java.util.List;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import org.marketcetera.photon.commons.Validate;
import org.marketcetera.util.except.ExceptUtils;
import org.marketcetera.util.misc.ClassVersion;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
/* $License$ */
/**
* Base implementation of {@link ILogoutService}. Subclasses can override
* {@link #doLogout()} to perform additional logout actions.
* <p>
* This class is thread safe.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: LogoutService.java 16901 2014-05-11 16:14:11Z colin $
* @since 2.0.0
*/
@ThreadSafe
@ClassVersion("$Id: LogoutService.java 16901 2014-05-11 16:14:11Z colin $")
public class LogoutService implements ILogoutService {
@GuardedBy("mLogoutRunnables")
private final Set<Runnable> mLogoutRunnables = Sets.newHashSet();
@Override
public final void logout() {
final List<Runnable> toRun;
synchronized (mLogoutRunnables) {
try {
doLogout();
} catch (RuntimeException e) {
ExceptUtils.swallow(e, LogoutService.class,
Messages.LOGOUT_SERVICE_UNHANDLED_EXCEPTION);
}
toRun = ImmutableList.copyOf(mLogoutRunnables);
mLogoutRunnables.clear();
}
for (Runnable r : toRun) {
try {
r.run();
} catch (RuntimeException e) {
ExceptUtils.swallow(e, LogoutService.class,
Messages.LOGOUT_SERVICE_UNHANDLED_EXCEPTION);
}
}
}
/**
* Hook for subclasses to perform custom logout actions before runnables are
* notified. This is called while the service is locked, providing
* subclasses implementations exclusive access.
* <p>
* Any {@link RuntimeException} thrown by a subclass implementation will be
* logged and swallowed.
*/
protected void doLogout() {
}
@Override
public final void addLogoutRunnable(Runnable runnable) {
Validate.notNull(runnable, "runnable"); //$NON-NLS-1$
synchronized (mLogoutRunnables) {
mLogoutRunnables.add(runnable);
}
}
@Override
public final void removeLogoutRunnable(Runnable runnable) {
Validate.notNull(runnable, "runnable"); //$NON-NLS-1$
synchronized (mLogoutRunnables) {
mLogoutRunnables.remove(runnable);
}
}
}