/* * Licensed to DuraSpace under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * DuraSpace licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fcrepo.kernel.modeshape.spring; import static org.slf4j.LoggerFactory.getLogger; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import org.fcrepo.kernel.api.FedoraRepository; import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; import org.fcrepo.kernel.modeshape.FedoraRepositoryImpl; import org.modeshape.jcr.JcrRepository; import org.modeshape.jcr.ModeShapeEngine; import org.modeshape.jcr.NoSuchRepositoryException; import org.modeshape.jcr.RepositoryConfiguration; import org.slf4j.Logger; import org.springframework.beans.factory.FactoryBean; import org.springframework.core.io.Resource; /** * A Modeshape factory shim to make it play nice with our Spring-based * configuration * * @author Edwin Shin * @since Feb 7, 2013 */ public class ModeShapeRepositoryFactoryBean implements FactoryBean<FedoraRepository> { private static final Logger LOGGER = getLogger(ModeShapeRepositoryFactoryBean.class); private DefaultPropertiesLoader propertiesLoader; @Inject private ModeShapeEngine modeShapeEngine; private Resource repositoryConfiguration; private JcrRepository repository; /** * Generate a JCR repository from the given configuration * */ @PostConstruct public void buildRepository() { try { LOGGER.info("Using repo config (classpath): {}", repositoryConfiguration.getURL()); getPropertiesLoader().loadSystemProperties(); final RepositoryConfiguration config = RepositoryConfiguration.read(repositoryConfiguration.getURL()); repository = modeShapeEngine.deploy(config); // next line ensures that repository starts before the factory is used. final org.modeshape.common.collection.Problems problems = repository.getStartupProblems(); for (final org.modeshape.common.collection.Problem p : problems) { LOGGER.error("ModeShape Start Problem: {}", p.getMessageString()); // TODO determine problems that should be runtime errors } } catch (final Exception e) { throw new RepositoryRuntimeException(e); } } /** * Attempts to undeploy the repository and shutdown the ModeShape engine on * context destroy. * * @throws InterruptedException if interrupted exception occurred */ @PreDestroy public void stopRepository() throws InterruptedException { LOGGER.info("Initiating shutdown of ModeShape"); final String repoName = repository.getName(); try { final Future<Boolean> futureUndeployRepo = modeShapeEngine.undeploy(repoName); if (futureUndeployRepo.get()) { LOGGER.info("ModeShape repository {} has undeployed.", repoName); } else { LOGGER.error("ModeShape repository {} undeploy failed without an exception, still deployed.", repoName); } LOGGER.info("Repository {} undeployed.", repoName); } catch (final NoSuchRepositoryException e) { LOGGER.error("Repository {} unknown, cannot undeploy.", repoName, e); } catch (final ExecutionException e) { LOGGER.error("Repository {} cannot undeploy.", repoName, e.getCause()); } final Future<Boolean> futureShutdownEngine = modeShapeEngine.shutdown(); try { if (futureShutdownEngine.get()) { LOGGER.info("ModeShape Engine has shutdown."); } else { LOGGER.error("ModeShape Engine shutdown failed without an exception, still running."); } } catch (final ExecutionException e) { LOGGER.error("ModeShape Engine shutdown failed.", e.getCause()); } } @Override public FedoraRepository getObject() { return new FedoraRepositoryImpl(repository); } @Override public Class<?> getObjectType() { return FedoraRepository.class; } @Override public boolean isSingleton() { return true; } /** * Set the configuration to use for creating the repository * * @param repositoryConfiguration the repository configuration */ public void setRepositoryConfiguration( final Resource repositoryConfiguration) { this.repositoryConfiguration = repositoryConfiguration; } private DefaultPropertiesLoader getPropertiesLoader() { if (null == propertiesLoader) { propertiesLoader = new DefaultPropertiesLoader(); } return propertiesLoader; } }