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