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