001/* 002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Bogdan Stefanescu 018 * Florent Guillaume 019 */ 020package org.nuxeo.ecm.core.repository; 021 022import java.util.List; 023import java.util.Map; 024import java.util.concurrent.ConcurrentHashMap; 025 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 029import org.nuxeo.ecm.core.api.repository.RepositoryManager; 030import org.nuxeo.ecm.core.model.Repository; 031import org.nuxeo.runtime.api.Framework; 032import org.nuxeo.runtime.model.ComponentContext; 033import org.nuxeo.runtime.model.ComponentManager; 034import org.nuxeo.runtime.model.ComponentName; 035import org.nuxeo.runtime.model.ComponentStartOrders; 036import org.nuxeo.runtime.model.DefaultComponent; 037import org.nuxeo.runtime.transaction.TransactionHelper; 038 039/** 040 * Component and service managing low-level repository instances. 041 */ 042public class RepositoryService extends DefaultComponent { 043 044 public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.core.repository.RepositoryService"); 045 046 private static final Log log = LogFactory.getLog(RepositoryService.class); 047 048 public static final String XP_REPOSITORY = "repository"; 049 050 private final Map<String, Repository> repositories = new ConcurrentHashMap<>(); 051 052 public void shutdown() { 053 log.info("Shutting down repository manager"); 054 repositories.values().forEach(Repository::shutdown); 055 repositories.clear(); 056 } 057 058 @Override 059 public int getApplicationStartedOrder() { 060 return ComponentStartOrders.REPOSITORY; 061 } 062 063 @Override 064 public void start(ComponentContext context) { 065 TransactionHelper.runInTransaction(this::doCreateRepositories); 066 Framework.getRuntime().getComponentManager().addListener(new ComponentManager.Listener() { 067 @Override 068 public void afterStart(ComponentManager mgr, boolean isResume) { 069 initRepositories(); // call all RepositoryInitializationHandler 070 } 071 072 @Override 073 public void afterStop(ComponentManager mgr, boolean isStandby) { 074 Framework.getRuntime().getComponentManager().removeListener(this); 075 } 076 }); 077 } 078 079 @Override 080 public void stop(ComponentContext context) { 081 TransactionHelper.runInTransaction(this::shutdown); 082 } 083 084 /** 085 * Start a tx and initialize repositories content. This method is publicly exposed since it is needed by tests to 086 * initialize repositories after cleanups (see CoreFeature). 087 * 088 * @since 8.4 089 */ 090 public void initRepositories() { 091 TransactionHelper.runInTransaction(this::doInitRepositories); 092 } 093 094 /** 095 * Creates all the repositories. Requires an active transaction. 096 * 097 * @since 9.3 098 */ 099 protected void doCreateRepositories() { 100 repositories.clear(); 101 for (String repositoryName : getRepositoryNames()) { 102 RepositoryFactory factory = getFactory(repositoryName); 103 if (factory == null) { 104 continue; 105 } 106 Repository repository = (Repository) factory.call(); 107 repositories.put(repositoryName, repository); 108 } 109 } 110 111 /** 112 * Initializes all the repositories. Requires an active transaction. 113 * 114 * @since 9.3 115 */ 116 protected void doInitRepositories() { 117 // give up if no handler configured 118 RepositoryInitializationHandler handler = RepositoryInitializationHandler.getInstance(); 119 if (handler == null) { 120 return; 121 } 122 // invoke handlers 123 for (String name : getRepositoryNames()) { 124 initializeRepository(handler, name); 125 } 126 } 127 128 @Override 129 public <T> T getAdapter(Class<T> adapter) { 130 if (adapter.isAssignableFrom(getClass())) { 131 return adapter.cast(this); 132 } 133 return null; 134 } 135 136 protected void initializeRepository(final RepositoryInitializationHandler handler, String name) { 137 new UnrestrictedSessionRunner(name) { 138 @Override 139 public void run() { 140 handler.initializeRepository(session); 141 } 142 }.runUnrestricted(); 143 } 144 145 /** 146 * Gets a repository given its name. 147 * <p> 148 * Null is returned if no repository with that name was registered. 149 * 150 * @param repositoryName the repository name 151 * @return the repository instance or null if no repository with that name was registered 152 */ 153 public Repository getRepository(String repositoryName) { 154 return repositories.get(repositoryName); 155 } 156 157 protected RepositoryFactory getFactory(String repositoryName) { 158 RepositoryManager repositoryManager = Framework.getService(RepositoryManager.class); 159 if (repositoryManager == null) { 160 // tests with no high-level repository manager 161 return null; 162 } 163 org.nuxeo.ecm.core.api.repository.Repository repo = repositoryManager.getRepository(repositoryName); 164 if (repo == null) { 165 return null; 166 } 167 RepositoryFactory repositoryFactory = (RepositoryFactory) repo.getRepositoryFactory(); 168 if (repositoryFactory == null) { 169 throw new NullPointerException("Missing repositoryFactory for repository: " + repositoryName); 170 } 171 return repositoryFactory; 172 } 173 174 public List<String> getRepositoryNames() { 175 RepositoryManager repositoryManager = Framework.getService(RepositoryManager.class); 176 return repositoryManager.getRepositoryNames(); 177 } 178 179}