package org.apereo.cas.config;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.logout.LogoutManager;
import org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner;
import org.apereo.cas.ticket.registry.NoOpTicketRegistryCleaner;
import org.apereo.cas.ticket.registry.TicketRegistry;
import org.apereo.cas.ticket.registry.TicketRegistryCleaner;
import org.apereo.cas.ticket.registry.support.LockingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* This is {@link CasCoreTicketsSchedulingConfiguration}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
@Configuration("casCoreTicketsSchedulingConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
@EnableScheduling
@EnableAsync
@EnableTransactionManagement(proxyTargetClass = true)
@AutoConfigureAfter(CasCoreTicketsConfiguration.class)
public class CasCoreTicketsSchedulingConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(CasCoreTicketsSchedulingConfiguration.class);
@Autowired
private CasConfigurationProperties casProperties;
@ConditionalOnMissingBean(name = "ticketRegistryCleaner")
@Bean
@Autowired
public TicketRegistryCleaner ticketRegistryCleaner(@Qualifier("lockingStrategy") final LockingStrategy lockingStrategy,
@Qualifier("logoutManager") final LogoutManager logoutManager,
@Qualifier("ticketRegistry") final TicketRegistry ticketRegistry) {
final boolean isCleanerEnabled = casProperties.getTicket().getRegistry().getCleaner().isEnabled();
if (isCleanerEnabled) {
LOGGER.debug("Ticket registry cleaner is enabled");
return new DefaultTicketRegistryCleaner(lockingStrategy, logoutManager, ticketRegistry);
}
LOGGER.debug("Ticket registry cleaner is not enabled. "
+ "Expired tickets are not forcefully collected and cleaned by CAS. It is up to the ticket registry itself to "
+ "clean up tickets based on expiration and eviction policies");
return new NoOpTicketRegistryCleaner();
}
@ConditionalOnMissingBean(name = "ticketRegistryCleanerScheduler")
@ConditionalOnProperty(prefix = "cas.ticket.registry.cleaner", name = "enabled", havingValue = "true", matchIfMissing = true)
@Bean
@Autowired
@RefreshScope
public TicketRegistryCleanerScheduler ticketRegistryCleanerScheduler(@Qualifier("ticketRegistryCleaner")
final TicketRegistryCleaner ticketRegistryCleaner) {
return new TicketRegistryCleanerScheduler(ticketRegistryCleaner);
}
/**
* The Ticket registry cleaner scheduler. Because the cleaner itself is marked
* with {@link org.springframework.transaction.annotation.Transactional},
* we need to create a separate scheduler component that simply invokes it
* so that {@link Scheduled} annotations can be processed and not interfere
* with transaction semantics of the cleaner.
*/
public static class TicketRegistryCleanerScheduler {
private final TicketRegistryCleaner ticketRegistryCleaner;
public TicketRegistryCleanerScheduler(final TicketRegistryCleaner ticketRegistryCleaner) {
this.ticketRegistryCleaner = ticketRegistryCleaner;
}
@Scheduled(initialDelayString = "${cas.ticket.registry.cleaner.startDelay:PT20S}",
fixedDelayString = "${cas.ticket.registry.cleaner.repeatInterval:PT90S}")
public void run() {
this.ticketRegistryCleaner.clean();
}
}
}