/* * Copyright (c) 2010-2015 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.init; import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.common.configuration.api.RuntimeConfiguration; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.api.RepositoryServiceFactory; import com.evolveum.midpoint.repo.api.RepositoryServiceFactoryException; import com.evolveum.midpoint.repo.cache.RepositoryCache; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.apache.commons.configuration.Configuration; import org.apache.cxf.common.util.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class RepositoryFactory implements ApplicationContextAware, RuntimeConfiguration { private static final String REPOSITORY_CONFIGURATION = "midpoint.repository"; private static final String REPOSITORY_FACTORY_CLASS = "repositoryServiceFactoryClass"; private static final String REPOSITORY_FACTORY_CACHE_CLASS = "com.evolveum.midpoint.repo.cache.RepositoryCacheFactory"; private static final Trace LOGGER = TraceManager.getTrace(RepositoryFactory.class); private ApplicationContext applicationContext; @Autowired MidpointConfiguration midpointConfiguration; @Autowired private PrismContext prismContext; //Repository factory private RepositoryServiceFactory factory; private RepositoryServiceFactory cacheFactory; //Repository services private RepositoryService repositoryService; private RepositoryService cacheRepositoryService; public void init() { Configuration config = midpointConfiguration.getConfiguration(REPOSITORY_CONFIGURATION); try { String className = getFactoryClassName(config); LOGGER.info("Repository factory class name from configuration '{}'.", new Object[]{className}); Class<RepositoryServiceFactory> clazz = (Class<RepositoryServiceFactory>) Class.forName(className); factory = getFactoryBean(clazz); factory.init(config); } catch (Exception ex) { LoggingUtils.logException(LOGGER, "RepositoryServiceFactory implementation class {} failed to " + "initialize.", ex, config.getString(REPOSITORY_FACTORY_CLASS)); throw new SystemException("RepositoryServiceFactory implementation class " + config.getString(REPOSITORY_FACTORY_CLASS) + " failed to initialize: " + ex.getMessage(), ex); } } private String getFactoryClassName(Configuration config) { String className = config.getString(REPOSITORY_FACTORY_CLASS); if (StringUtils.isEmpty(className)) { LOGGER.error("RepositoryServiceFactory implementation class name ({}) not found in configuration. " + "Provided configuration:\n{}", new Object[]{REPOSITORY_FACTORY_CLASS, config}); throw new SystemException("RepositoryServiceFactory implementation class name (" + REPOSITORY_FACTORY_CLASS + ") not found in configuration. Provided configuration:\n" + config); } return className; } private RepositoryServiceFactory getFactoryBean(Class<RepositoryServiceFactory> clazz) throws RepositoryServiceFactoryException { LOGGER.info("Getting factory bean '{}'", new Object[]{clazz.getName()}); return applicationContext.getBean(clazz); } public void destroy() { try { if (factory != null) { factory.destroy(); } } catch (RepositoryServiceFactoryException ex) { LoggingUtils.logException(LOGGER, "Failed to destroy RepositoryServiceFactory", ex); throw new SystemException("Failed to destroy RepositoryServiceFactory", ex); } } @Override public String getComponentId() { return REPOSITORY_CONFIGURATION; } @Override public Configuration getCurrentConfiguration() { return midpointConfiguration.getConfiguration(REPOSITORY_CONFIGURATION); } public synchronized RepositoryService getRepositoryService() { if (repositoryService == null) { try { LOGGER.debug("Creating repository service using factory {}", factory); repositoryService = factory.getRepositoryService(); } catch (RepositoryServiceFactoryException | RuntimeException ex) { LoggingUtils.logUnexpectedException(LOGGER, "Failed to get repository service from factory " + factory, ex); throw new SystemException("Failed to get repository service from factory " + factory, ex); } catch (Error ex) { LoggingUtils.logUnexpectedException(LOGGER, "Failed to get repository service from factory " + factory, ex); throw ex; } } return repositoryService; } public RepositoryServiceFactory getFactory() { return factory; } public synchronized RepositoryService getCacheRepositoryService() { if (cacheRepositoryService == null) { try { Class<RepositoryServiceFactory> clazz = (Class<RepositoryServiceFactory>) Class.forName(REPOSITORY_FACTORY_CACHE_CLASS); cacheFactory = getFactoryBean(clazz); //TODO decompose this dependency, remove class casting !!! RepositoryCache repositoryCache = (RepositoryCache) cacheFactory.getRepositoryService(); repositoryCache.setRepository(getRepositoryService(), prismContext); cacheRepositoryService = repositoryCache; } catch (Exception ex) { LoggingUtils.logException(LOGGER, "Failed to get cache repository service. ExceptionClass = {}", ex, ex.getClass().getName()); throw new SystemException("Failed to get cache repository service", ex); } } return cacheRepositoryService; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }