001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.kernel.modeshape.spring; 017 018import static org.slf4j.LoggerFactory.getLogger; 019 020import java.util.concurrent.ExecutionException; 021import java.util.concurrent.Future; 022 023import javax.annotation.PostConstruct; 024import javax.annotation.PreDestroy; 025import javax.inject.Inject; 026 027import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 028import org.modeshape.jcr.JcrRepository; 029import org.modeshape.jcr.ModeShapeEngine; 030import org.modeshape.jcr.NoSuchRepositoryException; 031import org.modeshape.jcr.RepositoryConfiguration; 032import org.slf4j.Logger; 033import org.springframework.beans.factory.FactoryBean; 034import org.springframework.core.io.Resource; 035 036/** 037 * A Modeshape factory shim to make it play nice with our Spring-based 038 * configuration 039 * 040 * @author Edwin Shin 041 * @since Feb 7, 2013 042 */ 043public class ModeShapeRepositoryFactoryBean implements 044 FactoryBean<JcrRepository> { 045 046 private static final Logger LOGGER = 047 getLogger(ModeShapeRepositoryFactoryBean.class); 048 049 private DefaultPropertiesLoader propertiesLoader; 050 051 @Inject 052 private ModeShapeEngine modeShapeEngine; 053 054 private Resource repositoryConfiguration; 055 056 private JcrRepository repository; 057 058 /** 059 * Generate a JCR repository from the given configuration 060 * 061 */ 062 @PostConstruct 063 public void buildRepository() { 064 try { 065 LOGGER.info("Using repo config (classpath): {}", repositoryConfiguration.getURL()); 066 getPropertiesLoader().loadSystemProperties(); 067 068 final RepositoryConfiguration config = 069 RepositoryConfiguration.read(repositoryConfiguration.getURL()); 070 repository = modeShapeEngine.deploy(config); 071 072 // next line ensures that repository starts before the factory is used. 073 final org.modeshape.common.collection.Problems problems = 074 repository.getStartupProblems(); 075 for (final org.modeshape.common.collection.Problem p : problems) { 076 LOGGER.error("ModeShape Start Problem: {}", p.getMessageString()); 077 // TODO determine problems that should be runtime errors 078 } 079 } catch (final Exception e) { 080 throw new RepositoryRuntimeException(e); 081 } 082 } 083 084 /** 085 * Attempts to undeploy the repository and shutdown the ModeShape engine on 086 * context destroy. 087 * 088 * @throws InterruptedException if interrupted exception occurred 089 */ 090 @PreDestroy 091 public void stopRepository() throws InterruptedException { 092 LOGGER.info("Initiating shutdown of ModeShape"); 093 final String repoName = repository.getName(); 094 try { 095 final Future<Boolean> futureUndeployRepo = modeShapeEngine.undeploy(repoName); 096 if (futureUndeployRepo.get()) { 097 LOGGER.info("ModeShape repository {} has undeployed.", repoName); 098 } else { 099 LOGGER.error("ModeShape repository {} undeploy failed without an exception, still deployed.", repoName); 100 } 101 LOGGER.info("Repository {} undeployed.", repoName); 102 } catch (final NoSuchRepositoryException e) { 103 LOGGER.error("Repository {} unknown, cannot undeploy.", repoName, e); 104 } catch (final ExecutionException e) { 105 LOGGER.error("Repository {} cannot undeploy.", repoName, e.getCause()); 106 } 107 final Future<Boolean> futureShutdownEngine = modeShapeEngine.shutdown(); 108 try { 109 if (futureShutdownEngine.get()) { 110 LOGGER.info("ModeShape Engine has shutdown."); 111 } else { 112 LOGGER.error("ModeShape Engine shutdown failed without an exception, still running."); 113 } 114 } catch (final ExecutionException e) { 115 LOGGER.error("ModeShape Engine shutdown failed.", e.getCause()); 116 } 117 } 118 119 @Override 120 public JcrRepository getObject() { 121 return repository; 122 } 123 124 @Override 125 public Class<?> getObjectType() { 126 return JcrRepository.class; 127 } 128 129 @Override 130 public boolean isSingleton() { 131 return true; 132 } 133 134 /** 135 * Set the configuration to use for creating the repository 136 * 137 * @param repositoryConfiguration the repository configuration 138 */ 139 public void setRepositoryConfiguration( 140 final Resource repositoryConfiguration) { 141 this.repositoryConfiguration = repositoryConfiguration; 142 } 143 144 private DefaultPropertiesLoader getPropertiesLoader() { 145 if (null == propertiesLoader) { 146 propertiesLoader = new DefaultPropertiesLoader(); 147 } 148 return propertiesLoader; 149 } 150}