001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.persistence.ocfl;
019
020
021import org.fcrepo.config.FedoraPropsConfig;
022import org.fcrepo.config.OcflPropsConfig;
023import org.fcrepo.kernel.api.TransactionManager;
024import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
025import org.fcrepo.kernel.api.identifiers.FedoraId;
026import org.fcrepo.kernel.api.operations.RdfSourceOperation;
027import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
028import org.fcrepo.kernel.api.operations.VersionResourceOperationFactory;
029import org.fcrepo.persistence.api.PersistentStorageSession;
030import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
031import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
032import org.fcrepo.persistence.ocfl.api.IndexBuilder;
033import org.fcrepo.persistence.ocfl.impl.OcflPersistentSessionManager;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036import org.springframework.context.ConfigurableApplicationContext;
037import org.springframework.context.event.ContextRefreshedEvent;
038import org.springframework.context.event.EventListener;
039import org.springframework.stereotype.Component;
040
041import javax.inject.Inject;
042
043import static org.fcrepo.kernel.api.RdfLexicon.BASIC_CONTAINER;
044
045/**
046 * This class is responsible for initializing the repository on start-up.
047 *
048 * @author dbernstein
049 */
050@Component
051public class RepositoryInitializer {
052
053    private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryInitializer.class);
054
055    @Inject
056    private OcflPersistentSessionManager sessionManager;
057
058    @Inject
059    private RdfSourceOperationFactory operationFactory;
060
061    @Inject
062    private IndexBuilder indexBuilder;
063
064    @Inject
065    private VersionResourceOperationFactory versionResourceOperationFactory;
066
067    @Inject
068    private OcflPropsConfig config;
069
070    @Inject
071    private FedoraPropsConfig fedoraPropsConfig;
072
073    @Inject
074    private TransactionManager txManager;
075
076    // This is used in-place of @PostConstruct so that it is called _after_ the rest of context has been
077    // completely initialized.
078    @EventListener
079    public void onApplicationEvent(final ContextRefreshedEvent event) {
080        try {
081            initialize();
082        } catch (Exception e) {
083            LOGGER.error("Failed to initialize repository", e);
084            ((ConfigurableApplicationContext) event.getApplicationContext()).close();
085        }
086    }
087
088    /**
089     * Initializes the repository
090     */
091    public void initialize() {
092        LOGGER.info("Initializing repository");
093
094        indexBuilder.rebuildIfNecessary();
095
096        final var root = FedoraId.getRepositoryRootId();
097
098        try {
099            //check that the root is initialized
100            final var transaction = txManager.create();
101            transaction.setShortLived(true);
102            final PersistentStorageSession session = this.sessionManager.getSession(transaction);
103
104            try {
105                session.getHeaders(root, null);
106            } catch (final PersistentItemNotFoundException e) {
107                LOGGER.debug("Repository root ({}) not found. Creating...", root);
108                final RdfSourceOperation operation = this.operationFactory.createBuilder(transaction, root,
109                        BASIC_CONTAINER.getURI(), fedoraPropsConfig.getServerManagedPropsMode())
110                        .parentId(root).build();
111
112                session.persist(operation);
113
114                //if auto versioning is not enabled, be sure to create an immutable version
115                if (!config.isAutoVersioningEnabled()) {
116                    final var versionOperation = this.versionResourceOperationFactory
117                            .createBuilder(transaction, root).build();
118                    session.persist(versionOperation);
119                }
120
121                transaction.commit();
122
123                LOGGER.debug("Successfully created repository root ({}).", root);
124            }
125
126        } catch (final PersistentStorageException ex) {
127            throw new RepositoryRuntimeException(ex.getMessage(), ex);
128        }
129    }
130
131}