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.impl.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.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 (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 = 096 modeShapeEngine.undeploy(repoName); 097 futureUndeployRepo.get(); 098 LOGGER.info("Repository {} undeployed.", repoName); 099 } catch (final NoSuchRepositoryException e) { 100 LOGGER.error("Repository {} unknown, cannot undeploy.", repoName, e); 101 } catch (final ExecutionException e) { 102 LOGGER.error("Repository {} cannot undeploy.", repoName, e); 103 } 104 final Future<Boolean> futureShutdownEngine = modeShapeEngine.shutdown(); 105 try { 106 if (futureShutdownEngine.get()) { 107 LOGGER.info("ModeShape Engine has shutdown."); 108 } else { 109 LOGGER.error("ModeShape Engine shutdown failed without an exception, still running."); 110 } 111 } catch (final ExecutionException e) { 112 LOGGER.error("ModeShape Engine shutdown failed.", e); 113 } 114 } 115 116 @Override 117 public JcrRepository getObject() { 118 return repository; 119 } 120 121 @Override 122 public Class<?> getObjectType() { 123 return JcrRepository.class; 124 } 125 126 @Override 127 public boolean isSingleton() { 128 return true; 129 } 130 131 /** 132 * Set the configuration to use for creating the repository 133 * 134 * @param repositoryConfiguration the repository configuration 135 */ 136 public void setRepositoryConfiguration( 137 final Resource repositoryConfiguration) { 138 this.repositoryConfiguration = repositoryConfiguration; 139 } 140 141 private DefaultPropertiesLoader getPropertiesLoader() { 142 if (null == propertiesLoader) { 143 propertiesLoader = new DefaultPropertiesLoader(); 144 } 145 return propertiesLoader; 146 } 147}