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 040import static org.fcrepo.kernel.api.RdfLexicon.SERVER_MANAGED_PROPERTIES_MODE; 041 042/** 043 * A Modeshape factory shim to make it play nice with our Spring-based 044 * configuration 045 * 046 * @author Edwin Shin 047 * @since Feb 7, 2013 048 */ 049public class ModeShapeRepositoryFactoryBean implements 050 FactoryBean<FedoraRepository> { 051 052 private static final Logger LOGGER = 053 getLogger(ModeShapeRepositoryFactoryBean.class); 054 055 private DefaultPropertiesLoader propertiesLoader; 056 057 @Inject 058 private ModeShapeEngine modeShapeEngine; 059 060 private Resource repositoryConfiguration; 061 062 private JcrRepository repository; 063 064 /** 065 * Generate a JCR repository from the given configuration 066 * 067 */ 068 @PostConstruct 069 public void buildRepository() { 070 try { 071 LOGGER.info("Using repo config (classpath): {}", repositoryConfiguration.getURL()); 072 getPropertiesLoader().loadSystemProperties(); 073 074 final RepositoryConfiguration config = 075 RepositoryConfiguration.read(repositoryConfiguration.getURL()); 076 repository = modeShapeEngine.deploy(config); 077 078 // next line ensures that repository starts before the factory is used. 079 final org.modeshape.common.collection.Problems problems = 080 repository.getStartupProblems(); 081 for (final org.modeshape.common.collection.Problem p : problems) { 082 LOGGER.error("ModeShape Start Problem: {}", p.getMessageString()); 083 // TODO determine problems that should be runtime errors 084 } 085 } catch (final Exception e) { 086 throw new RepositoryRuntimeException(e); 087 } 088 } 089 090 /** 091 * Attempts to undeploy the repository and shutdown the ModeShape engine on 092 * context destroy. 093 * 094 * @throws InterruptedException if interrupted exception occurred 095 */ 096 @PreDestroy 097 public void stopRepository() throws InterruptedException { 098 LOGGER.info("Initiating shutdown of ModeShape"); 099 final String repoName = repository.getName(); 100 try { 101 final Future<Boolean> futureUndeployRepo = modeShapeEngine.undeploy(repoName); 102 if (futureUndeployRepo.get()) { 103 LOGGER.info("ModeShape repository {} has undeployed.", repoName); 104 } else { 105 LOGGER.error("ModeShape repository {} undeploy failed without an exception, still deployed.", repoName); 106 } 107 LOGGER.info("Repository {} undeployed.", repoName); 108 } catch (final NoSuchRepositoryException e) { 109 LOGGER.error("Repository {} unknown, cannot undeploy.", repoName, e); 110 } catch (final ExecutionException e) { 111 LOGGER.error("Repository {} cannot undeploy.", repoName, e.getCause()); 112 } 113 final Future<Boolean> futureShutdownEngine = modeShapeEngine.shutdown(); 114 try { 115 if (futureShutdownEngine.get()) { 116 LOGGER.info("ModeShape Engine has shutdown."); 117 } else { 118 LOGGER.error("ModeShape Engine shutdown failed without an exception, still running."); 119 } 120 } catch (final ExecutionException e) { 121 LOGGER.error("ModeShape Engine shutdown failed.", e.getCause()); 122 } 123 } 124 125 @Override 126 public FedoraRepository getObject() { 127 return new FedoraRepositoryImpl(repository); 128 } 129 130 @Override 131 public Class<?> getObjectType() { 132 return FedoraRepository.class; 133 } 134 135 @Override 136 public boolean isSingleton() { 137 return true; 138 } 139 140 /** 141 * Set the configuration to use for creating the repository 142 * 143 * @param repositoryConfiguration the repository configuration 144 */ 145 public void setRepositoryConfiguration( 146 final Resource repositoryConfiguration) { 147 this.repositoryConfiguration = repositoryConfiguration; 148 } 149 150 private DefaultPropertiesLoader getPropertiesLoader() { 151 if (null == propertiesLoader) { 152 propertiesLoader = new DefaultPropertiesLoader(); 153 } 154 return propertiesLoader; 155 } 156 157 /** 158 * Set the mode for server managed properties. The value "strict" (default) 159 * will result in the classic behavior where certain provenance-related 160 * properties cannot be set, while "relaxed" will allow for them to be 161 * set in some circumstances. 162 * 163 * @param value the value (must be either "strict" or "relaxed") 164 */ 165 public void setServerManagedPropertiesMode(final String value) { 166 if ("strict".equals(value) || "relaxed".equals(value)) { 167 final String propertyValue = System.getProperty(SERVER_MANAGED_PROPERTIES_MODE); 168 if (propertyValue != null) { 169 LOGGER.warn("The system property \"{}\" with the value \"{}\" is being used instead of the" + 170 "serverManagedPropertiesMode of \"{}\" specified in the Spring configuration!", 171 SERVER_MANAGED_PROPERTIES_MODE, propertyValue, value); 172 } else { 173 LOGGER.info("Set sytem property \"{}\" to \"{}\" to correspond to serverManagedPropertiesMode.", 174 SERVER_MANAGED_PROPERTIES_MODE, value); 175 System.setProperty(SERVER_MANAGED_PROPERTIES_MODE, value); 176 } 177 } else { 178 throw new IllegalArgumentException("Invalid value \"" + value 179 + "\" supplied for serverManagedPropertiesMode (expecting \"strict\" or \"relaxed\")!"); 180 } 181 } 182}