/* * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Bogdan Stefanescu * Florent Guillaume */ package org.nuxeo.ecm.core.repository; import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; import org.nuxeo.ecm.core.api.local.LocalException; import org.nuxeo.ecm.core.api.repository.RepositoryManager; import org.nuxeo.ecm.core.model.Repository; import org.nuxeo.ecm.core.model.Session; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.model.ComponentContext; import org.nuxeo.runtime.model.ComponentName; import org.nuxeo.runtime.model.DefaultComponent; import org.nuxeo.runtime.transaction.TransactionHelper; /** * Component and service managing low-level repository instances. */ public class RepositoryService extends DefaultComponent { public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.core.repository.RepositoryService"); private static final Log log = LogFactory.getLog(RepositoryService.class); public static final String XP_REPOSITORY = "repository"; // @GuardedBy("itself") private final Map<String, Repository> repositories = new HashMap<>(); public void shutdown() { log.info("Shutting down repository manager"); synchronized (repositories) { for (Repository repository : repositories.values()) { repository.shutdown(); } repositories.clear(); } } @Override public int getApplicationStartedOrder() { return 100; } @Override public void applicationStarted(ComponentContext context) { TransactionHelper.runInTransaction(this::initRepositories); } @Override public void applicationStopped(ComponentContext context, Instant deadline) { TransactionHelper.runInTransaction(this::shutdown); } /** * Initializes all repositories. Run in a transaction. * * @since 8.4 */ protected void initRepositories() { RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); for (String name : repositoryManager.getRepositoryNames()) { openRepository(name); } // give up if no handler configured RepositoryInitializationHandler handler = RepositoryInitializationHandler.getInstance(); if (handler == null) { return; } // invoke handlers for (String name : repositoryManager.getRepositoryNames()) { initializeRepository(handler, name); } } @Override public <T> T getAdapter(Class<T> adapter) { if (adapter.isAssignableFrom(getClass())) { return adapter.cast(this); } return null; } protected void openRepository(String name) { new UnrestrictedSessionRunner(name) { @Override public void run() { ; } }.runUnrestricted(); } protected void initializeRepository(final RepositoryInitializationHandler handler, String name) { new UnrestrictedSessionRunner(name) { @Override public void run() { handler.initializeRepository(session); } }.runUnrestricted(); } /** * Gets a repository given its name. * <p> * Null is returned if no repository with that name was registered. * * @param repositoryName * the repository name * @return the repository instance or null if no repository with that name * was registered */ public Repository getRepository(String repositoryName) { synchronized (repositories) { return doGetRepository(repositoryName); } } /** * Calls to that method should be synchronized on repositories * * @since 7.2 * @see #getRepository(String) * @see #getSession(String, String) */ protected Repository doGetRepository(String repositoryName) { Repository repository = repositories.get(repositoryName); if (repository == null) { RepositoryFactory factory = getFactory(repositoryName); if (factory == null) { return null; } repository = (Repository) factory.call(); repositories.put(repositoryName, repository); } return repository; } protected RepositoryFactory getFactory(String repositoryName) { RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); if (repositoryManager == null) { // tests with no high-level repository manager return null; } org.nuxeo.ecm.core.api.repository.Repository repo = repositoryManager.getRepository(repositoryName); if (repo == null) { return null; } RepositoryFactory repositoryFactory = (RepositoryFactory) repo.getRepositoryFactory(); if (repositoryFactory == null) { throw new NullPointerException("Missing repositoryFactory for repository: " + repositoryName); } return repositoryFactory; } public List<String> getRepositoryNames() { RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); return repositoryManager.getRepositoryNames(); } /** * Creates a new session with the given session id from the given * repository. * <p/> * Locks repositories before entering the pool. That allows concurrency with * shutdown. * * @since 7.2 */ public Session getSession(String repositoryName) { synchronized (repositories) { Repository repository = doGetRepository(repositoryName); if (repository == null) { throw new LocalException("No such repository: " + repositoryName); } return repository.getSession(); } } }