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