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.modeshape.jcr.JcrRepository; 028import org.modeshape.jcr.ModeShapeEngine; 029import org.modeshape.jcr.NoSuchRepositoryException; 030import org.modeshape.jcr.RepositoryConfiguration; 031import org.slf4j.Logger; 032import org.springframework.beans.factory.FactoryBean; 033import org.springframework.core.io.Resource; 034 035/** 036 * A Modeshape factory shim to make it play nice with our Spring-based 037 * configuration 038 * 039 * @author Edwin Shin 040 * @since Feb 7, 2013 041 */ 042public class ModeShapeRepositoryFactoryBean implements 043 FactoryBean<JcrRepository> { 044 045 private static final Logger LOGGER = 046 getLogger(ModeShapeRepositoryFactoryBean.class); 047 048 private DefaultPropertiesLoader propertiesLoader; 049 050 @Inject 051 private ModeShapeEngine modeShapeEngine; 052 053 private Resource repositoryConfiguration; 054 055 private JcrRepository repository; 056 057 /** 058 * Generate a JCR repository from the given configuration 059 * 060 * @throws Exception 061 */ 062 @PostConstruct 063 public void buildRepository() throws Exception { 064 LOGGER.info("Using repo config (classpath): {}", repositoryConfiguration.getURL()); 065 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 } 080 081 /** 082 * Attempts to undeploy the repository and shutdown the ModeShape engine on 083 * context destroy. 084 * 085 * @throws InterruptedException 086 */ 087 @PreDestroy 088 public void stopRepository() throws InterruptedException { 089 LOGGER.info("Initiating shutdown of ModeShape"); 090 final String repoName = repository.getName(); 091 try { 092 final Future<Boolean> futureUndeployRepo = 093 modeShapeEngine.undeploy(repoName); 094 futureUndeployRepo.get(); 095 LOGGER.info("Repository {} undeployed.", repoName); 096 } catch (final NoSuchRepositoryException e) { 097 LOGGER.error("Repository {} unknown, cannot undeploy.", repoName, e); 098 } catch (final ExecutionException e) { 099 LOGGER.error("Repository {} cannot undeploy.", repoName, e); 100 } 101 final Future<Boolean> futureShutdownEngine = modeShapeEngine.shutdown(); 102 try { 103 if (futureShutdownEngine.get()) { 104 LOGGER.info("ModeShape Engine has shutdown."); 105 } else { 106 LOGGER.error("ModeShape Engine shutdown failed without an exception, still running."); 107 } 108 } catch (final ExecutionException e) { 109 LOGGER.error("ModeShape Engine shutdown failed.", e); 110 } 111 } 112 113 @Override 114 public JcrRepository getObject() { 115 return repository; 116 } 117 118 @Override 119 public Class<?> getObjectType() { 120 return JcrRepository.class; 121 } 122 123 @Override 124 public boolean isSingleton() { 125 return true; 126 } 127 128 /** 129 * Set the configuration to use for creating the repository 130 * 131 * @param repositoryConfiguration 132 */ 133 public void setRepositoryConfiguration( 134 final Resource repositoryConfiguration) { 135 this.repositoryConfiguration = repositoryConfiguration; 136 } 137 138 private DefaultPropertiesLoader getPropertiesLoader() { 139 if (null == propertiesLoader) { 140 propertiesLoader = new DefaultPropertiesLoader(); 141 } 142 return propertiesLoader; 143 } 144}