001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006
007package org.fcrepo.webapp;
008
009import java.util.Optional;
010import java.util.concurrent.ExecutorService;
011import java.util.concurrent.Executors;
012import java.util.concurrent.TimeUnit;
013
014import javax.inject.Inject;
015
016import org.fcrepo.config.FedoraPropsConfig;
017import org.fcrepo.http.api.ExternalContentHandlerFactory;
018import org.fcrepo.http.api.ExternalContentPathValidator;
019import org.fcrepo.kernel.api.auth.ACLHandle;
020import org.fcrepo.kernel.api.rdf.RdfNamespaceRegistry;
021
022import org.apache.http.conn.HttpClientConnectionManager;
023import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026import org.springframework.context.annotation.Bean;
027import org.springframework.context.annotation.Configuration;
028import org.springframework.scheduling.annotation.EnableScheduling;
029import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
030
031import com.github.benmanes.caffeine.cache.Cache;
032import com.github.benmanes.caffeine.cache.Caffeine;
033import com.google.common.eventbus.AsyncEventBus;
034import com.google.common.eventbus.EventBus;
035
036/**
037 * Spring config for the webapp
038 *
039 * @author pwinckles
040 */
041@Configuration
042@EnableScheduling
043public class WebappConfig {
044
045    private static final Logger LOGGER = LoggerFactory.getLogger(WebappConfig.class);
046
047    @Inject
048    private FedoraPropsConfig fedoraPropsConfig;
049
050    /**
051     * Task scheduler used for cleaning up transactions
052     *
053     * @return scheduler
054     */
055    @Bean
056    public ThreadPoolTaskScheduler taskScheduler() {
057        final var scheduler = new ThreadPoolTaskScheduler();
058        scheduler.setPoolSize(1);
059        scheduler.setThreadNamePrefix("ScheduledTask");
060        return scheduler;
061    }
062
063    /**
064     * HTTP connection manager
065     *
066     * @return connection manager
067     */
068    @Bean
069    public HttpClientConnectionManager connectionManager() {
070        return new PoolingHttpClientConnectionManager();
071    }
072
073    /**
074     * Fedora's lightweight internal event bus. Currently memory-resident.
075     *
076     * @param propsConfig config
077     * @return event bus
078     */
079    @Bean
080    public EventBus eventBus(final FedoraPropsConfig propsConfig) {
081        return new AsyncEventBus(eventBusExecutor(propsConfig));
082    }
083
084    /**
085     * @param propsConfig config
086     * @return executor intended to be used by the Guava event bus
087     */
088    @Bean
089    public ExecutorService eventBusExecutor(final FedoraPropsConfig propsConfig) {
090        LOGGER.debug("Event bus threads: {}", propsConfig);
091        return Executors.newFixedThreadPool(propsConfig.getEventBusThreads());
092    }
093
094    /**
095     * Configuration of namespace prefixes
096     *
097     * @param propsConfig config properties
098     * @return rdf namespace registry
099     */
100    @Bean(initMethod = "init", destroyMethod = "shutdown")
101    public RdfNamespaceRegistry rdfNamespaceRegistry(final FedoraPropsConfig propsConfig) {
102        final var registry = new RdfNamespaceRegistry();
103        registry.setConfigPath(propsConfig.getNamespaceRegistry());
104        registry.setMonitorForChanges(true);
105        return registry;
106    }
107
108    /**
109     * External content configuration
110     *
111     * @param propsConfig config properties
112     * @return external content path validator
113     */
114    @Bean(initMethod = "init", destroyMethod = "shutdown")
115    public ExternalContentPathValidator externalContentPathValidator(final FedoraPropsConfig propsConfig) {
116        final var validator = new ExternalContentPathValidator();
117        validator.setConfigPath(propsConfig.getExternalContentAllowed());
118        validator.setMonitorForChanges(true);
119        return validator;
120    }
121
122    @Bean
123    public ExternalContentHandlerFactory externalContentHandlerFactory(final ExternalContentPathValidator validator) {
124        final var factory = new ExternalContentHandlerFactory();
125        factory.setValidator(validator);
126        return factory;
127    }
128
129    /**
130     * Used to cache the effective ACL location and authorizations for a given resource.
131     *
132     * @return the cache
133     */
134    @Bean
135    public Cache<String, Optional<ACLHandle>> authHandleCache() {
136        return Caffeine.newBuilder().weakValues()
137                .expireAfterAccess(fedoraPropsConfig.getWebacCacheTimeout(), TimeUnit.MINUTES)
138                .maximumSize(fedoraPropsConfig.getWebacCacheSize()).build();
139    }
140}