001/* 002 * (C) Copyright 2006-2015 Nuxeo SA (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.HashMap; 023import java.util.List; 024import java.util.Map; 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.local.LocalException; 030import org.nuxeo.ecm.core.api.repository.RepositoryManager; 031import org.nuxeo.ecm.core.model.Repository; 032import org.nuxeo.ecm.core.model.Session; 033import org.nuxeo.runtime.RuntimeServiceEvent; 034import org.nuxeo.runtime.RuntimeServiceListener; 035import org.nuxeo.runtime.api.Framework; 036import org.nuxeo.runtime.model.ComponentContext; 037import org.nuxeo.runtime.model.ComponentName; 038import org.nuxeo.runtime.model.DefaultComponent; 039import org.nuxeo.runtime.transaction.TransactionHelper; 040 041/** 042 * Component and service managing low-level repository instances. 043 */ 044public class RepositoryService extends DefaultComponent { 045 046 public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.core.repository.RepositoryService"); 047 048 private static final Log log = LogFactory.getLog(RepositoryService.class); 049 050 public static final String XP_REPOSITORY = "repository"; 051 052 // @GuardedBy("itself") 053 private final Map<String, Repository> repositories = new HashMap<>(); 054 055 public void shutdown() { 056 log.info("Shutting down repository manager"); 057 synchronized (repositories) { 058 for (Repository repository : repositories.values()) { 059 repository.shutdown(); 060 } 061 repositories.clear(); 062 } 063 } 064 065 @Override 066 public int getApplicationStartedOrder() { 067 return 100; 068 } 069 070 @Override 071 public void activate(ComponentContext context) { 072 Framework.addListener(new RuntimeServiceListener() { 073 074 @Override 075 public void handleEvent(RuntimeServiceEvent event) { 076 if (event.id != RuntimeServiceEvent.RUNTIME_ABOUT_TO_STOP) { 077 return; 078 } 079 Framework.removeListener(this); 080 shutdown(); 081 } 082 }); 083 } 084 085 @Override 086 public void applicationStarted(ComponentContext context) { 087 TransactionHelper.runInTransaction(this::initRepositories); 088 } 089 090 /** 091 * Initializes all repositories. Run in a transaction. 092 * 093 * @since 8.4 094 */ 095 protected void initRepositories() { 096 RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); 097 for (String name : repositoryManager.getRepositoryNames()) { 098 openRepository(name); 099 } 100 // give up if no handler configured 101 RepositoryInitializationHandler handler = RepositoryInitializationHandler.getInstance(); 102 if (handler == null) { 103 return; 104 } 105 // invoke handlers 106 for (String name : repositoryManager.getRepositoryNames()) { 107 initializeRepository(handler, name); 108 } 109 } 110 111 @Override 112 public <T> T getAdapter(Class<T> adapter) { 113 if (adapter.isAssignableFrom(getClass())) { 114 return adapter.cast(this); 115 } 116 return null; 117 } 118 119 protected void openRepository(String name) { 120 new UnrestrictedSessionRunner(name) { 121 122 @Override 123 public void run() { 124 ; 125 } 126 127 }.runUnrestricted(); 128 } 129 130 protected void initializeRepository(final RepositoryInitializationHandler handler, String name) { 131 new UnrestrictedSessionRunner(name) { 132 @Override 133 public void run() { 134 handler.initializeRepository(session); 135 } 136 }.runUnrestricted(); 137 } 138 139 /** 140 * Gets a repository given its name. 141 * <p> 142 * Null is returned if no repository with that name was registered. 143 * 144 * @param repositoryName 145 * the repository name 146 * @return the repository instance or null if no repository with that name 147 * was registered 148 */ 149 public Repository getRepository(String repositoryName) { 150 synchronized (repositories) { 151 return doGetRepository(repositoryName); 152 } 153 } 154 155 /** 156 * Calls to that method should be synchronized on repositories 157 * 158 * @since 7.2 159 * @see #getRepository(String) 160 * @see #getSession(String, String) 161 */ 162 protected Repository doGetRepository(String repositoryName) { 163 Repository repository = repositories.get(repositoryName); 164 if (repository == null) { 165 RepositoryFactory factory = getFactory(repositoryName); 166 if (factory == null) { 167 return null; 168 } 169 repository = (Repository) factory.call(); 170 repositories.put(repositoryName, repository); 171 } 172 return repository; 173 } 174 175 protected RepositoryFactory getFactory(String repositoryName) { 176 RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); 177 if (repositoryManager == null) { 178 // tests with no high-level repository manager 179 return null; 180 } 181 org.nuxeo.ecm.core.api.repository.Repository repo = repositoryManager.getRepository(repositoryName); 182 if (repo == null) { 183 return null; 184 } 185 RepositoryFactory repositoryFactory = (RepositoryFactory) repo.getRepositoryFactory(); 186 if (repositoryFactory == null) { 187 throw new NullPointerException("Missing repositoryFactory for repository: " + repositoryName); 188 } 189 return repositoryFactory; 190 } 191 192 public List<String> getRepositoryNames() { 193 RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); 194 return repositoryManager.getRepositoryNames(); 195 } 196 197 /** 198 * Creates a new session with the given session id from the given 199 * repository. 200 * <p/> 201 * Locks repositories before entering the pool. That allows concurrency with 202 * shutdown. 203 * 204 * @since 7.2 205 */ 206 public Session getSession(String repositoryName) { 207 synchronized (repositories) { 208 Repository repository = doGetRepository(repositoryName); 209 if (repository == null) { 210 throw new LocalException("No such repository: " + repositoryName); 211 } 212 return repository.getSession(); 213 } 214 } 215 216}