001/* 002 * (C) Copyright 2014 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 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.storage.sql.coremodel; 020 021import java.lang.reflect.Field; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.nuxeo.ecm.core.api.repository.Repository; 028import org.nuxeo.ecm.core.api.repository.RepositoryManager; 029import org.nuxeo.ecm.core.repository.RepositoryFactory; 030import org.nuxeo.ecm.core.repository.RepositoryService; 031import org.nuxeo.ecm.core.storage.FulltextConfiguration; 032import org.nuxeo.ecm.core.storage.FulltextParser; 033import org.nuxeo.ecm.core.storage.sql.RepositoryDescriptor; 034import org.nuxeo.ecm.core.storage.sql.RepositoryImpl; 035import org.nuxeo.ecm.core.storage.sql.RepositoryManagement; 036import org.nuxeo.ecm.core.storage.sql.ra.PoolingRepositoryFactory; 037import org.nuxeo.runtime.api.Framework; 038import org.nuxeo.runtime.model.ComponentContext; 039import org.nuxeo.runtime.model.ComponentInstance; 040import org.nuxeo.runtime.model.DefaultComponent; 041import org.nuxeo.runtime.model.SimpleContributionRegistry; 042 043/** 044 * Service holding the configuration for VCS repositories. 045 * 046 * @since 5.9.3 047 */ 048public class SQLRepositoryService extends DefaultComponent { 049 050 private static final String XP_REPOSITORY = "repository"; 051 052 protected static final String CONNECTIONFACTORYIMPL_CLASS = "org.nuxeo.ecm.core.storage.sql.ra.ConnectionFactoryImpl"; 053 054 protected RepositoryDescriptorRegistry registry = new RepositoryDescriptorRegistry(); 055 056 protected static class RepositoryDescriptorRegistry extends SimpleContributionRegistry<RepositoryDescriptor> { 057 058 @Override 059 public String getContributionId(RepositoryDescriptor contrib) { 060 return contrib.name; 061 } 062 063 @Override 064 public RepositoryDescriptor clone(RepositoryDescriptor orig) { 065 return new RepositoryDescriptor(orig); 066 } 067 068 @Override 069 public void merge(RepositoryDescriptor src, RepositoryDescriptor dst) { 070 dst.merge(src); 071 } 072 073 @Override 074 public boolean isSupportingMerge() { 075 return true; 076 } 077 078 public void clear() { 079 currentContribs.clear(); 080 } 081 082 public RepositoryDescriptor getRepositoryDescriptor(String id) { 083 return getCurrentContribution(id); 084 } 085 086 public List<String> getRepositoryIds() { 087 return new ArrayList<>(currentContribs.keySet()); 088 } 089 } 090 091 @Override 092 public void activate(ComponentContext context) { 093 registry.clear(); 094 } 095 096 @Override 097 public void deactivate(ComponentContext context) { 098 registry.clear(); 099 } 100 101 @Override 102 public void registerContribution(Object contrib, String xpoint, ComponentInstance contributor) { 103 if (XP_REPOSITORY.equals(xpoint)) { 104 addContribution((RepositoryDescriptor) contrib); 105 } else { 106 throw new RuntimeException("Unknown extension point: " + xpoint); 107 } 108 } 109 110 @Override 111 public void unregisterContribution(Object contrib, String xpoint, ComponentInstance contributor) { 112 if (XP_REPOSITORY.equals(xpoint)) { 113 removeContribution((RepositoryDescriptor) contrib); 114 } else { 115 throw new RuntimeException("Unknown extension point: " + xpoint); 116 } 117 } 118 119 protected void addContribution(RepositoryDescriptor descriptor) { 120 registry.addContribution(descriptor); 121 updateRegistration(descriptor.name); 122 } 123 124 protected void removeContribution(RepositoryDescriptor descriptor) { 125 registry.removeContribution(descriptor); 126 updateRegistration(descriptor.name); 127 } 128 129 /** 130 * Update repository registration in high-level repository service. 131 */ 132 protected void updateRegistration(String repositoryName) { 133 RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); 134 RepositoryDescriptor descriptor = registry.getRepositoryDescriptor(repositoryName); 135 if (descriptor == null) { 136 // last contribution removed 137 repositoryManager.removeRepository(repositoryName); 138 return; 139 } 140 // extract label, isDefault 141 // and pass it to high-level registry 142 RepositoryFactory repositoryFactory = new PoolingRepositoryFactory(repositoryName); 143 Repository repository = new Repository(repositoryName, descriptor.label, descriptor.isDefault(), 144 repositoryFactory); 145 repositoryManager.addRepository(repository); 146 } 147 148 public RepositoryDescriptor getRepositoryDescriptor(String name) { 149 return registry.getRepositoryDescriptor(name); 150 } 151 152 /** 153 * Gets the list of SQL repository names. 154 * 155 * @return the list of SQL repository names 156 * @since 5.9.5 157 */ 158 public List<String> getRepositoryNames() { 159 return registry.getRepositoryIds(); 160 } 161 162 protected final Map<String, RepositoryImpl> testRepositories = new HashMap<String, RepositoryImpl>(); 163 164 public void registerTestRepository(RepositoryImpl repository) { 165 testRepositories.put(repository.getName(), repository); 166 } 167 168 /** 169 * Gets the low-level SQL Repository of the given name. 170 * 171 * @param repositoryName the repository name 172 * @return the repository 173 * @since 5.9.5 174 */ 175 public RepositoryManagement getRepository(String repositoryName) { 176 RepositoryService repositoryService = Framework.getLocalService(RepositoryService.class); 177 org.nuxeo.ecm.core.model.Repository repository = repositoryService.getRepository(repositoryName); 178 if (repository == null) { 179 RepositoryImpl repo = testRepositories.get(repositoryName); 180 if (repo != null) { 181 return repo; 182 } 183 } 184 if (repository == null) { 185 throw new RuntimeException("Unknown repository: " + repositoryName); 186 } 187 if (repository instanceof org.nuxeo.ecm.core.storage.sql.Repository) { 188 // (JCA) ConnectionFactoryImpl already implements Repository 189 return (org.nuxeo.ecm.core.storage.sql.Repository) repository; 190 } else { 191 throw new RuntimeException("Unknown repository class: " + repository.getClass().getName()); 192 } 193 } 194 195 public RepositoryImpl getRepositoryImpl(String repositoryName) { 196 RepositoryManagement repository = getRepository(repositoryName); 197 if (repository instanceof RepositoryImpl) { 198 return (RepositoryImpl) repository; 199 } 200 if (!CONNECTIONFACTORYIMPL_CLASS.equals(repository.getClass().getName())) { 201 throw new RuntimeException("Unknown repository class: " + repository.getClass()); 202 } 203 try { 204 Field f1 = repository.getClass().getDeclaredField("managedConnectionFactory"); 205 f1.setAccessible(true); 206 Object factory = f1.get(repository); 207 Field f2 = factory.getClass().getDeclaredField("repository"); 208 f2.setAccessible(true); 209 return (RepositoryImpl) f2.get(factory); 210 } catch (SecurityException | NoSuchFieldException | IllegalAccessException e) { 211 throw new RuntimeException(e); 212 } 213 } 214 215 /** 216 * Gets the repositories as a list of {@link RepositoryManagement} objects. 217 * 218 * @since 5.9.5 219 * @return a list of {@link RepositoryManagement} 220 */ 221 public List<RepositoryManagement> getRepositories() { 222 List<RepositoryManagement> repositories = new ArrayList<RepositoryManagement>(); 223 for (String repositoryName : getRepositoryNames()) { 224 repositories.add(getRepository(repositoryName)); 225 } 226 return repositories; 227 } 228 229 public Class<? extends FulltextParser> getFulltextParserClass(String repositoryName) { 230 return getRepositoryImpl(repositoryName).getFulltextParserClass(); 231 } 232 233 public FulltextConfiguration getFulltextConfiguration(String repositoryName) { 234 return getRepositoryImpl(repositoryName).getModel().getFulltextConfiguration(); 235 } 236 237}