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.config;
008
009import java.io.IOException;
010import java.nio.file.Path;
011import java.time.Duration;
012
013import javax.annotation.PostConstruct;
014
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017import org.springframework.beans.factory.annotation.Value;
018import org.springframework.context.annotation.Configuration;
019import org.springframework.core.io.Resource;
020
021/**
022 * General Fedora properties
023 *
024 * @author pwinckles
025 * @since 6.0.0
026 */
027@Configuration
028public class FedoraPropsConfig extends BasePropsConfig {
029
030    private static final Logger LOGGER = LoggerFactory.getLogger(FedoraPropsConfig.class);
031
032    public static final String FCREPO_JMS_HOST = "fcrepo.jms.host";
033    public static final String FCREPO_DYNAMIC_JMS_PORT = "fcrepo.dynamic.jms.port";
034    public static final String FCREPO_DYNAMIC_STOMP_PORT = "fcrepo.dynamic.stomp.port";
035    public static final String FCREPO_ACTIVEMQ_CONFIGURATION = "fcrepo.activemq.configuration";
036    public static final String FCREPO_NAMESPACE_REGISTRY = "fcrepo.namespace.registry";
037    public static final String FCREPO_EXTERNAL_CONTENT_ALLOWED = "fcrepo.external.content.allowed";
038    private static final String FCREPO_ACTIVEMQ_DIRECTORY = "fcrepo.activemq.directory";
039    private static final String FCREPO_SESSION_TIMEOUT = "fcrepo.session.timeout";
040    private static final String FCREPO_VELOCITY_RUNTIME_LOG = "fcrepo.velocity.runtime.log";
041    private static final String FCREPO_REBUILD_VALIDATION = "fcrepo.rebuild.validation";
042    private static final String FCREPO_REBUILD_VALIDATION_FIXITY = "fcrepo.rebuild.validation.fixity";
043    private static final String FCREPO_REBUILD_ON_START = "fcrepo.rebuild.on.start";
044    private static final String FCREPO_JMS_BASEURL = "fcrepo.jms.baseUrl";
045    private static final String FCREPO_SERVER_MANAGED_PROPS_MODE = "fcrepo.properties.management";
046    private static final String FCREPO_JMS_DESTINATION_TYPE = "fcrepo.jms.destination.type";
047    private static final String FCREPO_JMS_DESTINATION_NAME = "fcrepo.jms.destination.name";
048    public static final String FCREPO_JMS_ENABLED = "fcrepo.jms.enabled";
049    private static final String FCREPO_EVENT_THREADS = "fcrepo.event.threads";
050
051    private static final String DATA_DIR_DEFAULT_VALUE = "data";
052    private static final String LOG_DIR_DEFAULT_VALUE = "logs";
053    private static final String ACTIVE_MQ_DIR_DEFAULT_VALUE = "ActiveMQ/kahadb";
054
055    @Value("${" + FCREPO_HOME_PROPERTY + ":" + DEFAULT_FCREPO_HOME_VALUE + "}")
056    protected Path fedoraHome;
057
058    @Value("#{fedoraPropsConfig.fedoraHome.resolve('" + DATA_DIR_DEFAULT_VALUE + "')}")
059    private Path fedoraData;
060
061    @Value("#{fedoraPropsConfig.fedoraHome.resolve('" + LOG_DIR_DEFAULT_VALUE + "')}")
062    private Path fedoraLogs;
063
064    @Value("${" + FCREPO_JMS_HOST + ":localhost}")
065    private String jmsHost;
066
067    @Value("${" + FCREPO_DYNAMIC_JMS_PORT + ":61616}")
068    private String jmsPort;
069
070    @Value("${" + FCREPO_DYNAMIC_STOMP_PORT + ":61613}")
071    private String stompPort;
072
073    @Value("${" + FCREPO_ACTIVEMQ_CONFIGURATION + ":classpath:/config/activemq.xml}")
074    private Resource activeMQConfiguration;
075
076    @Value("${" + FCREPO_ACTIVEMQ_DIRECTORY + ":#{fedoraPropsConfig.fedoraData.resolve('" +
077            ACTIVE_MQ_DIR_DEFAULT_VALUE + "').toAbsolutePath().toString()}}")
078    private String activeMqDirectory;
079
080    @Value("${" + FCREPO_NAMESPACE_REGISTRY + ":classpath:/namespaces.yml}")
081    private String namespaceRegistry;
082
083    @Value("${" + FCREPO_EXTERNAL_CONTENT_ALLOWED + ":#{null}}")
084    private String externalContentAllowed;
085
086    @Value("${" + FCREPO_SESSION_TIMEOUT + ":180000}")
087    private Long sessionTimeoutLong;
088    private Duration sessionTimeout;
089
090    @Value("${" + FCREPO_VELOCITY_RUNTIME_LOG + ":" +
091            "#{fedoraPropsConfig.fedoraLogs.resolve('velocity.log').toString()}}")
092    private Path velocityLog;
093
094    @Value("${" + FCREPO_REBUILD_VALIDATION + ":true}")
095    private boolean rebuildValidation;
096
097    @Value("${" + FCREPO_REBUILD_VALIDATION_FIXITY + ":false}")
098    private boolean rebuildFixityCheck;
099
100    @Value("${" + FCREPO_REBUILD_ON_START + ":false}")
101    private boolean rebuildOnStart;
102
103    @Value("${" + FCREPO_JMS_BASEURL + ":#{null}}")
104    private String jmsBaseUrl;
105
106    @Value("${" + FCREPO_SERVER_MANAGED_PROPS_MODE + ":strict}")
107    private String serverManagedPropsModeStr;
108    private ServerManagedPropsMode serverManagedPropsMode;
109
110    @Value("${" + FCREPO_JMS_DESTINATION_TYPE + ":topic}")
111    private String jmsDestinationTypeStr;
112    private JmsDestination jmsDestinationType;
113
114    @Value("${" + FCREPO_JMS_DESTINATION_NAME + ":fedora}")
115    private String jmsDestinationName;
116
117    @Value("${" + FCREPO_EVENT_THREADS + ":1}")
118    private int eventBusThreads;
119
120    @Value("${fcrepo.cache.db.containment.size.entries:1024}")
121    private long containmentCacheSize;
122
123    @Value("${fcrepo.cache.db.containment.timeout.minutes:10}")
124    private long containmentCacheTimeout;
125
126    @Value("${fcrepo.cache.types.size.entries:1024}")
127    private long userTypesCacheSize;
128
129    @Value("${fcrepo.cache.types.timeout.minutes:10}")
130    private long userTypesCacheTimeout;
131
132    @Value("${fcrepo.cache.webac.acl.size.entries:1024}")
133    private long webacCacheSize;
134
135    @Value("${fcrepo.cache.webac.acl.timeout.minutes:10}")
136    private long webacCacheTimeout;
137
138    @PostConstruct
139    private void postConstruct() throws IOException {
140        LOGGER.info("Fedora home: {}", fedoraHome);
141        LOGGER.debug("Fedora home data: {}", fedoraData);
142        try {
143            createDirectories(fedoraHome);
144        } catch (final IOException e) {
145            throw new IOException(String.format("Failed to create Fedora home directory at %s." +
146                    " Fedora home can be configured by setting the %s property.", fedoraHome, FCREPO_HOME_PROPERTY), e);
147        }
148        createDirectories(fedoraData);
149        serverManagedPropsMode = ServerManagedPropsMode.fromString(serverManagedPropsModeStr);
150        sessionTimeout = Duration.ofMillis(sessionTimeoutLong);
151        jmsDestinationType = JmsDestination.fromString(jmsDestinationTypeStr);
152
153        checkRebuildProps();
154    }
155
156    /**
157     * Check if the rebuild fixity check prop was set without the rebuild validation being enabled
158     */
159    private void checkRebuildProps() {
160        if (rebuildFixityCheck && !rebuildValidation) {
161            throw new IllegalStateException(FCREPO_REBUILD_VALIDATION_FIXITY + " must be false when " +
162                                            FCREPO_REBUILD_VALIDATION + " is false.");
163        }
164    }
165
166    /**
167     * @return Path to Fedora home directory
168     */
169    public Path getFedoraHome() {
170        return fedoraHome;
171    }
172
173    /**
174     * Sets the path to the Fedora home directory -- should only be used for testing purposes.
175     *
176     * @param fedoraHome Path to Fedora home directory
177     */
178    public void setFedoraHome(final Path fedoraHome) {
179        this.fedoraHome = fedoraHome;
180    }
181
182    /**
183     * @return Path to Fedora home data directory
184     */
185    public Path getFedoraData() {
186        return fedoraData;
187    }
188
189    /**
190     * @return Path to Fedora home logs directory
191     */
192    public Path getFedoraLogs() {
193        return fedoraLogs;
194    }
195
196    /**
197     * Sets the path to the Fedora home data directory -- should only be used for testing purposes.
198     *
199     * @param fedoraData Path to Fedora home data directory
200     */
201    public void setFedoraData(final Path fedoraData) {
202        this.fedoraData = fedoraData;
203    }
204
205    /**
206     * @return The JMS host
207     */
208    public String getJmsHost() {
209        return jmsHost;
210    }
211
212    /**
213     * @return The JMS/Open Wire port
214     */
215    public String getJmsPort() {
216        return jmsPort;
217    }
218
219    /**
220     * @return The STOMP protocol port
221     */
222    public String getStompPort() {
223        return stompPort;
224    }
225
226    /**
227     * @return The ActiveMQ data directory
228     */
229    public String getActiveMqDirectory() {
230        return activeMqDirectory;
231    }
232
233    /**
234     * @return The path to the ActiveMQ xml spring configuration.
235     */
236    public Resource getActiveMQConfiguration() {
237        return activeMQConfiguration;
238    }
239
240    /**
241     * @return The path to the allowed external content pattern definitions.
242     */
243    public String getExternalContentAllowed() {
244        return externalContentAllowed;
245    }
246
247    /**
248     * @return The path to the namespace registry file.
249     */
250    public String getNamespaceRegistry() {
251        return namespaceRegistry;
252    }
253
254    /**
255     * @return The timeout in milliseconds of the persistence session
256     */
257    public Duration getSessionTimeout() {
258        return sessionTimeout;
259    }
260
261    /**
262     * @param sessionTimeout the session timeout duration
263     */
264    public void setSessionTimeout(final Duration sessionTimeout) {
265        this.sessionTimeout = sessionTimeout;
266    }
267
268    /**
269     * @return The path to the velocity log.
270     */
271    public Path getVelocityLog() {
272        return velocityLog;
273    }
274
275    /**
276     * @return true if the rebuild object validation should run
277     */
278    public boolean isRebuildValidation() {
279        return rebuildValidation;
280    }
281
282    /**
283     * @return true if the rebuild validation should also check file fixity
284     */
285    public boolean isRebuildFixityCheck() {
286        return rebuildFixityCheck;
287    }
288
289    /**
290     * @return true if the internal indices should be rebuilt when Fedora starts up.
291     */
292    public boolean isRebuildOnStart() {
293        return rebuildOnStart;
294    }
295
296    /**
297     * @param rebuildOnStart A boolean flag indicating whether or not to rebuild on start
298     */
299    public void setRebuildOnStart(final boolean rebuildOnStart) {
300        this.rebuildOnStart = rebuildOnStart;
301    }
302
303    /**
304     * @return the JMS base url, if specified
305     */
306    public String getJmsBaseUrl() {
307        return jmsBaseUrl;
308    }
309
310    /**
311     * @return the server managed properties mode, default strict
312     */
313    public ServerManagedPropsMode getServerManagedPropsMode() {
314        return serverManagedPropsMode;
315    }
316
317    /**
318     * @param serverManagedPropsMode the server managed props mode
319     */
320    public void setServerManagedPropsMode(final ServerManagedPropsMode serverManagedPropsMode) {
321        this.serverManagedPropsMode = serverManagedPropsMode;
322    }
323
324    /**
325     * @return the jms destination type
326     */
327    public JmsDestination getJmsDestinationType() {
328        return jmsDestinationType;
329    }
330
331    /**
332     * @return the jms destination name
333     */
334    public String getJmsDestinationName() {
335        return jmsDestinationName;
336    }
337
338    /**
339     * @return the number of threads to allocate in the event bus thread pool
340     *         if this number is less than 1, 1 is returned
341     */
342    public int getEventBusThreads() {
343        if (eventBusThreads < 1) {
344            return 1;
345        }
346        return eventBusThreads;
347    }
348
349    /**
350     * @return The number of entries in the containment cache.
351     */
352    public long getContainmentCacheSize() {
353        return containmentCacheSize;
354    }
355
356    /**
357     * @return The number of minutes before items in the containment cache expire.
358     */
359    public long getContainmentCacheTimeout() {
360        return containmentCacheTimeout;
361    }
362
363    /**
364     * @return The number of entries in the user types cache.
365     */
366    public long getUserTypesCacheSize() {
367        return userTypesCacheSize;
368    }
369
370    /**
371     * @param userTypesCacheSize user types cache size
372     */
373    public void setUserTypesCacheSize(final long userTypesCacheSize) {
374        this.userTypesCacheSize = userTypesCacheSize;
375    }
376
377    /**
378     * @return The number of minutes before items in the user types cache expire.
379     */
380    public long getUserTypesCacheTimeout() {
381        return userTypesCacheTimeout;
382    }
383
384    /**
385     * @param userTypesCacheTimeout user types cache timeout
386     */
387    public void setUserTypesCacheTimeout(final long userTypesCacheTimeout) {
388        this.userTypesCacheTimeout = userTypesCacheTimeout;
389    }
390
391    /**
392     * @return The number of entries in the WebAC effective ACL cache.
393     */
394    public long getWebacCacheSize() {
395        return webacCacheSize;
396    }
397
398    /**
399     * @return The number of minutes before items in the WebAC ACL cache expire.
400     */
401    public long getWebacCacheTimeout() {
402        return webacCacheTimeout;
403    }
404}