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