/*
* (C) Copyright 2014 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:
* Florent Guillaume
*/
package org.nuxeo.ecm.core.storage.sql.coremodel;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.nuxeo.ecm.core.api.repository.Repository;
import org.nuxeo.ecm.core.api.repository.RepositoryManager;
import org.nuxeo.ecm.core.repository.RepositoryFactory;
import org.nuxeo.ecm.core.repository.RepositoryService;
import org.nuxeo.ecm.core.storage.FulltextConfiguration;
import org.nuxeo.ecm.core.storage.FulltextParser;
import org.nuxeo.ecm.core.storage.sql.RepositoryDescriptor;
import org.nuxeo.ecm.core.storage.sql.RepositoryImpl;
import org.nuxeo.ecm.core.storage.sql.RepositoryManagement;
import org.nuxeo.ecm.core.storage.sql.ra.PoolingRepositoryFactory;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.runtime.model.ComponentContext;
import org.nuxeo.runtime.model.ComponentInstance;
import org.nuxeo.runtime.model.DefaultComponent;
import org.nuxeo.runtime.model.SimpleContributionRegistry;
/**
* Service holding the configuration for VCS repositories.
*
* @since 5.9.3
*/
public class SQLRepositoryService extends DefaultComponent {
private static final String XP_REPOSITORY = "repository";
protected static final String CONNECTIONFACTORYIMPL_CLASS = "org.nuxeo.ecm.core.storage.sql.ra.ConnectionFactoryImpl";
protected RepositoryDescriptorRegistry registry = new RepositoryDescriptorRegistry();
protected static class RepositoryDescriptorRegistry extends SimpleContributionRegistry<RepositoryDescriptor> {
@Override
public String getContributionId(RepositoryDescriptor contrib) {
return contrib.name;
}
@Override
public RepositoryDescriptor clone(RepositoryDescriptor orig) {
return new RepositoryDescriptor(orig);
}
@Override
public void merge(RepositoryDescriptor src, RepositoryDescriptor dst) {
dst.merge(src);
}
@Override
public boolean isSupportingMerge() {
return true;
}
public void clear() {
currentContribs.clear();
}
public RepositoryDescriptor getRepositoryDescriptor(String id) {
return getCurrentContribution(id);
}
public List<String> getRepositoryIds() {
return new ArrayList<>(currentContribs.keySet());
}
}
@Override
public void activate(ComponentContext context) {
registry.clear();
}
@Override
public void deactivate(ComponentContext context) {
registry.clear();
}
@Override
public void registerContribution(Object contrib, String xpoint, ComponentInstance contributor) {
if (XP_REPOSITORY.equals(xpoint)) {
addContribution((RepositoryDescriptor) contrib);
} else {
throw new RuntimeException("Unknown extension point: " + xpoint);
}
}
@Override
public void unregisterContribution(Object contrib, String xpoint, ComponentInstance contributor) {
if (XP_REPOSITORY.equals(xpoint)) {
removeContribution((RepositoryDescriptor) contrib);
} else {
throw new RuntimeException("Unknown extension point: " + xpoint);
}
}
protected void addContribution(RepositoryDescriptor descriptor) {
registry.addContribution(descriptor);
updateRegistration(descriptor.name);
}
protected void removeContribution(RepositoryDescriptor descriptor) {
registry.removeContribution(descriptor);
updateRegistration(descriptor.name);
}
/**
* Update repository registration in high-level repository service.
*/
protected void updateRegistration(String repositoryName) {
RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class);
RepositoryDescriptor descriptor = registry.getRepositoryDescriptor(repositoryName);
if (descriptor == null) {
// last contribution removed
repositoryManager.removeRepository(repositoryName);
return;
}
// extract label, isDefault
// and pass it to high-level registry
RepositoryFactory repositoryFactory = new PoolingRepositoryFactory(repositoryName);
Repository repository = new Repository(repositoryName, descriptor.label, descriptor.isDefault(),
repositoryFactory);
repositoryManager.addRepository(repository);
}
public RepositoryDescriptor getRepositoryDescriptor(String name) {
return registry.getRepositoryDescriptor(name);
}
/**
* Gets the list of SQL repository names.
*
* @return the list of SQL repository names
* @since 5.9.5
*/
public List<String> getRepositoryNames() {
return registry.getRepositoryIds();
}
protected final Map<String, RepositoryImpl> testRepositories = new HashMap<String, RepositoryImpl>();
public void registerTestRepository(RepositoryImpl repository) {
testRepositories.put(repository.getName(), repository);
}
/**
* Gets the low-level SQL Repository of the given name.
*
* @param repositoryName the repository name
* @return the repository
* @since 5.9.5
*/
public RepositoryManagement getRepository(String repositoryName) {
RepositoryService repositoryService = Framework.getLocalService(RepositoryService.class);
org.nuxeo.ecm.core.model.Repository repository = repositoryService.getRepository(repositoryName);
if (repository == null) {
RepositoryImpl repo = testRepositories.get(repositoryName);
if (repo != null) {
return repo;
}
}
if (repository == null) {
throw new RuntimeException("Unknown repository: " + repositoryName);
}
if (repository instanceof org.nuxeo.ecm.core.storage.sql.Repository) {
// (JCA) ConnectionFactoryImpl already implements Repository
return (org.nuxeo.ecm.core.storage.sql.Repository) repository;
} else {
throw new RuntimeException("Unknown repository class: " + repository.getClass().getName());
}
}
public RepositoryImpl getRepositoryImpl(String repositoryName) {
RepositoryManagement repository = getRepository(repositoryName);
if (repository instanceof RepositoryImpl) {
return (RepositoryImpl) repository;
}
if (!CONNECTIONFACTORYIMPL_CLASS.equals(repository.getClass().getName())) {
throw new RuntimeException("Unknown repository class: " + repository.getClass());
}
try {
Field f1 = repository.getClass().getDeclaredField("managedConnectionFactory");
f1.setAccessible(true);
Object factory = f1.get(repository);
Field f2 = factory.getClass().getDeclaredField("repository");
f2.setAccessible(true);
return (RepositoryImpl) f2.get(factory);
} catch (SecurityException | NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
/**
* Gets the repositories as a list of {@link RepositoryManagement} objects.
*
* @since 5.9.5
* @return a list of {@link RepositoryManagement}
*/
public List<RepositoryManagement> getRepositories() {
List<RepositoryManagement> repositories = new ArrayList<RepositoryManagement>();
for (String repositoryName : getRepositoryNames()) {
repositories.add(getRepository(repositoryName));
}
return repositories;
}
public Class<? extends FulltextParser> getFulltextParserClass(String repositoryName) {
return getRepositoryImpl(repositoryName).getFulltextParserClass();
}
public FulltextConfiguration getFulltextConfiguration(String repositoryName) {
return getRepositoryImpl(repositoryName).getModel().getFulltextConfiguration();
}
}