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 */
006package org.fcrepo.persistence.ocfl;
007
008
009import org.fcrepo.config.FedoraPropsConfig;
010import org.fcrepo.config.OcflPropsConfig;
011import org.fcrepo.kernel.api.TransactionManager;
012import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
013import org.fcrepo.kernel.api.identifiers.FedoraId;
014import org.fcrepo.kernel.api.operations.RdfSourceOperation;
015import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
016import org.fcrepo.kernel.api.operations.VersionResourceOperationFactory;
017import org.fcrepo.persistence.api.PersistentStorageSession;
018import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
019import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
020import org.fcrepo.persistence.ocfl.api.IndexBuilder;
021import org.fcrepo.persistence.ocfl.impl.OcflPersistentSessionManager;
022import org.slf4j.Logger;
023import org.slf4j.LoggerFactory;
024import org.springframework.context.ConfigurableApplicationContext;
025import org.springframework.context.event.ContextRefreshedEvent;
026import org.springframework.context.event.EventListener;
027import org.springframework.stereotype.Component;
028
029import javax.inject.Inject;
030
031import static org.fcrepo.kernel.api.RdfLexicon.BASIC_CONTAINER;
032
033/**
034 * This class is responsible for initializing the repository on start-up.
035 *
036 * @author dbernstein
037 */
038@Component
039public class RepositoryInitializer {
040
041    private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryInitializer.class);
042
043    @Inject
044    private OcflPersistentSessionManager sessionManager;
045
046    @Inject
047    private RdfSourceOperationFactory operationFactory;
048
049    @Inject
050    private IndexBuilder indexBuilder;
051
052    @Inject
053    private VersionResourceOperationFactory versionResourceOperationFactory;
054
055    @Inject
056    private OcflPropsConfig config;
057
058    @Inject
059    private FedoraPropsConfig fedoraPropsConfig;
060
061    @Inject
062    private TransactionManager txManager;
063
064    // This is used in-place of @PostConstruct so that it is called _after_ the rest of context has been
065    // completely initialized.
066    @EventListener
067    public void onApplicationEvent(final ContextRefreshedEvent event) {
068        try {
069            initialize();
070        } catch (Exception e) {
071            LOGGER.error("Failed to initialize repository", e);
072            ((ConfigurableApplicationContext) event.getApplicationContext()).close();
073        }
074    }
075
076    /**
077     * Initializes the repository
078     */
079    public void initialize() {
080        LOGGER.info("Initializing repository");
081
082        indexBuilder.rebuildIfNecessary();
083
084        final var root = FedoraId.getRepositoryRootId();
085
086        try {
087            //check that the root is initialized
088            final var transaction = txManager.create();
089            transaction.setShortLived(true);
090            final PersistentStorageSession session = this.sessionManager.getSession(transaction);
091
092            try {
093                session.getHeaders(root, null);
094            } catch (final PersistentItemNotFoundException e) {
095                LOGGER.debug("Repository root ({}) not found. Creating...", root);
096                final RdfSourceOperation operation = this.operationFactory.createBuilder(transaction, root,
097                        BASIC_CONTAINER.getURI(), fedoraPropsConfig.getServerManagedPropsMode())
098                        .parentId(root).build();
099
100                session.persist(operation);
101
102                //if auto versioning is not enabled, be sure to create an immutable version
103                if (!config.isAutoVersioningEnabled()) {
104                    final var versionOperation = this.versionResourceOperationFactory
105                            .createBuilder(transaction, root).build();
106                    session.persist(versionOperation);
107                }
108
109                transaction.commit();
110
111                LOGGER.debug("Successfully created repository root ({}).", root);
112            }
113
114        } catch (final PersistentStorageException ex) {
115            throw new RepositoryRuntimeException(ex.getMessage(), ex);
116        }
117    }
118
119}