blob: 07450bc700d52cf6c89ed254661b259dc6fb1143 [file] [log] [blame]
/*
* Copyright (c) 2011-2013, 2015, 2016 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
* Lothar Werzinger - support for configuring user managers
* Christian W. Damus (CEA LIST) - bug 418454
*/
package org.eclipse.emf.cdo.spi.server;
import org.eclipse.emf.cdo.internal.server.SessionManager;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.CDOServerUtil;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IRepositoryFactory;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.server.IStoreFactory;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.container.IManagedContainer.ContainerAware;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.net4j.util.factory.PropertiesFactory;
import org.eclipse.net4j.util.om.OMPlatform;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.security.AuthenticatorFactory;
import org.eclipse.net4j.util.security.IAuthenticator;
import org.eclipse.net4j.util.security.IUserManager;
import org.eclipse.net4j.util.security.UserManagerFactory;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
* @since 4.0
*/
public class RepositoryConfigurator
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REPOSITORY, RepositoryConfigurator.class);
private IManagedContainer container;
private Map<String, IRepositoryFactory> repositoryFactories = new HashMap<String, IRepositoryFactory>();
private Map<String, IStoreFactory> storeFactories = new HashMap<String, IStoreFactory>();
public RepositoryConfigurator()
{
this(null);
}
public RepositoryConfigurator(IManagedContainer container)
{
this.container = container;
}
public IManagedContainer getContainer()
{
return container;
}
public Map<String, IRepositoryFactory> getRepositoryFactories()
{
return repositoryFactories;
}
public Map<String, IStoreFactory> getStoreFactories()
{
return storeFactories;
}
public IRepository[] configure(File configFile) throws ParserConfigurationException, SAXException, IOException, CoreException
{
if (TRACER.isEnabled())
{
TRACER.trace("Configuring CDO server from " + configFile.getAbsolutePath()); //$NON-NLS-1$
}
return configure(getDocument(configFile));
}
/**
* @since 4.3
*/
public IRepository[] configure(Reader configReader) throws ParserConfigurationException, SAXException, IOException, CoreException
{
if (TRACER.isEnabled())
{
TRACER.trace("Configuring CDO server from dynamic configuration"); //$NON-NLS-1$
}
return configure(getDocument(configReader));
}
/**
* @since 4.3
*/
protected IRepository[] configure(Document document) throws ParserConfigurationException, SAXException, IOException, CoreException
{
List<IRepository> repositories = new ArrayList<IRepository>();
NodeList elements = document.getElementsByTagName("repository"); //$NON-NLS-1$
for (int i = 0; i < elements.getLength(); i++)
{
Element repositoryConfig = (Element)elements.item(i);
IRepository repository = getRepository(repositoryConfig);
repositories.add(repository);
if (container != null)
{
CDOServerUtil.addRepository(container, repository);
OM.LOG.info("CDO repository " + repository.getName() + " started");
}
else
{
OM.LOG.info("CDO repository " + repository.getName() + " added");
}
}
return repositories.toArray(new IRepository[repositories.size()]);
}
protected Document getDocument(File configFile) throws ParserConfigurationException, SAXException, IOException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(configFile);
}
/**
* @since 4.3
*/
protected Document getDocument(Reader configReader) throws ParserConfigurationException, SAXException, IOException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new InputSource(configReader));
}
protected IRepositoryFactory getRepositoryFactory(String type) throws CoreException
{
IRepositoryFactory factory = repositoryFactories.get(type);
if (factory == null)
{
factory = createExecutableExtension("repositoryFactories", "repositoryFactory", //$NON-NLS-1$ //$NON-NLS-2$
"repositoryType", type); //$NON-NLS-1$
}
if (factory == null)
{
throw new IllegalStateException("CDORepositoryInfo factory not found: " + type); //$NON-NLS-1$
}
return factory;
}
protected IRepository getRepository(Element repositoryConfig) throws CoreException
{
String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
if (StringUtil.isEmpty(repositoryName))
{
throw new IllegalArgumentException("CDORepositoryInfo name is missing or empty"); //$NON-NLS-1$
}
String repositoryType = repositoryConfig.getAttribute("type"); //$NON-NLS-1$
if (StringUtil.isEmpty(repositoryType))
{
repositoryType = RepositoryFactory.TYPE;
}
if (TRACER.isEnabled())
{
TRACER.format("Configuring repository {0} (type={1})", repositoryName, repositoryType); //$NON-NLS-1$
}
Map<String, String> properties = getProperties(repositoryConfig, 1);
Element storeConfig = getStoreConfig(repositoryConfig);
IStore store = createStore(repositoryName, properties, storeConfig);
InternalRepository repository = (InternalRepository)getRepository(repositoryType);
repository.setName(repositoryName);
repository.setStore((InternalStore)store);
repository.setProperties(properties);
setUserManager(repository, repositoryConfig);
setAuthenticator(repository, repositoryConfig);
setActivityLog(repository, repositoryConfig);
EPackage[] initialPackages = getInitialPackages(repositoryConfig);
if (initialPackages.length != 0)
{
repository.setInitialPackages(initialPackages);
}
return repository;
}
protected IRepository getRepository(String repositoryType) throws CoreException
{
IRepositoryFactory factory = getRepositoryFactory(repositoryType);
return factory.createRepository();
}
protected Element getUserManagerConfig(Element repositoryConfig)
{
NodeList userManagerConfig = repositoryConfig.getElementsByTagName("userManager"); //$NON-NLS-1$
if (userManagerConfig.getLength() > 1)
{
String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
throw new IllegalStateException("At most one user manager must be configured for repository " + repositoryName); //$NON-NLS-1$
}
return (Element)(userManagerConfig.getLength() > 0 ? userManagerConfig.item(0) : null);
}
protected IUserManager getUserManager(Element userManagerConfig) throws CoreException
{
String type = userManagerConfig.getAttribute("type"); //$NON-NLS-1$
String description = userManagerConfig.getAttribute("description"); //$NON-NLS-1$
return getUserManager(type, description);
}
protected IUserManager getUserManager(String type, String description) throws CoreException
{
IUserManager userManager = (IUserManager)container.getElement(UserManagerFactory.PRODUCT_GROUP, type, description);
if (userManager == null)
{
throw new IllegalStateException("UserManager factory not found: " + type); //$NON-NLS-1$
}
return userManager;
}
/**
* @since 4.2
*/
@SuppressWarnings("deprecation")
protected void setUserManager(InternalRepository repository, Element repositoryConfig) throws CoreException
{
Element userManagerConfig = getUserManagerConfig(repositoryConfig);
if (userManagerConfig != null)
{
IUserManager userManager = getUserManager(userManagerConfig);
if (userManager != null)
{
InternalSessionManager sessionManager = repository.getSessionManager();
if (sessionManager == null)
{
sessionManager = new SessionManager();
repository.setSessionManager(sessionManager);
}
sessionManager.setUserManager(userManager);
}
}
}
/**
* @since 4.2
*/
protected Element getAuthenticatorConfig(Element repositoryConfig)
{
NodeList authenticatorConfig = repositoryConfig.getElementsByTagName("authenticator"); //$NON-NLS-1$
if (authenticatorConfig.getLength() > 1)
{
String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
throw new IllegalStateException("At most one authenticator must be configured for repository " + repositoryName); //$NON-NLS-1$
}
return (Element)(authenticatorConfig.getLength() > 0 ? authenticatorConfig.item(0) : null);
}
/**
* @since 4.2
*/
protected IAuthenticator getAuthenticator(Element authenticatorConfig) throws CoreException
{
String type = authenticatorConfig.getAttribute("type"); //$NON-NLS-1$
String description = authenticatorConfig.getAttribute("description"); //$NON-NLS-1$
return getAuthenticator(type, description);
}
/**
* @since 4.2
*/
protected IAuthenticator getAuthenticator(String type, String description) throws CoreException
{
IAuthenticator authenticator = (IAuthenticator)container.getElement(AuthenticatorFactory.PRODUCT_GROUP, type, description);
if (authenticator == null)
{
throw new IllegalStateException("Authenticator factory not found: " + type); //$NON-NLS-1$
}
return authenticator;
}
/**
* @since 4.2
*/
protected void setAuthenticator(InternalRepository repository, Element repositoryConfig) throws CoreException
{
Element authenticatorConfig = getAuthenticatorConfig(repositoryConfig);
if (authenticatorConfig != null)
{
IAuthenticator authenticator = getAuthenticator(authenticatorConfig);
if (authenticator != null)
{
InternalSessionManager sessionManager = repository.getSessionManager();
if (sessionManager == null)
{
sessionManager = new SessionManager();
repository.setSessionManager(sessionManager);
}
sessionManager.setAuthenticator(authenticator);
}
}
}
/**
* @since 4.7
*/
protected void setActivityLog(InternalRepository repository, Element repositoryConfig)
{
NodeList activityLogConfig = repositoryConfig.getElementsByTagName("activityLog"); //$NON-NLS-1$
if (activityLogConfig.getLength() > 1)
{
String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
throw new IllegalStateException("At most one activity log must be configured for repository " + repositoryName); //$NON-NLS-1$
}
if (activityLogConfig.getLength() > 0)
{
Element activityLogElement = (Element)activityLogConfig.item(0);
RepositoryActivityLog activityLog = getContainerElement(activityLogElement, RepositoryActivityLog.Rolling.Factory.TYPE);
activityLog.setRepository(repository);
}
}
protected EPackage[] getInitialPackages(Element repositoryConfig)
{
List<EPackage> result = new ArrayList<EPackage>();
NodeList initialPackagesConfig = repositoryConfig.getElementsByTagName("initialPackage"); //$NON-NLS-1$
for (int i = 0; i < initialPackagesConfig.getLength(); i++)
{
Element initialPackageConfig = (Element)initialPackagesConfig.item(i);
String nsURI = initialPackageConfig.getAttribute("nsURI"); //$NON-NLS-1$
if (nsURI == null)
{
throw new IllegalStateException("nsURI missing for initialPackage element"); //$NON-NLS-1$
}
EPackage initialPackage = EPackage.Registry.INSTANCE.getEPackage(nsURI);
if (initialPackage == null)
{
throw new IllegalStateException("Initial package not found in global package registry: " + nsURI); //$NON-NLS-1$
}
result.add(initialPackage);
}
return result.toArray(new EPackage[result.size()]);
}
protected Element getStoreConfig(Element repositoryConfig)
{
NodeList storeConfigs = repositoryConfig.getElementsByTagName("store"); //$NON-NLS-1$
if (storeConfigs.getLength() == 0)
{
String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
throw new IllegalStateException("A store must be configured for repository " + repositoryName); //$NON-NLS-1$
}
return (Element)storeConfigs.item(0);
}
protected IStoreFactory getStoreFactory(String type) throws CoreException
{
IStoreFactory factory = storeFactories.get(type);
if (factory == null)
{
factory = createExecutableExtension("storeFactories", "storeFactory", "storeType", type); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if (factory == null)
{
throw new IllegalStateException("Store factory not found: " + type); //$NON-NLS-1$
}
return factory;
}
protected IStore createStore(String repositoryName, Map<String, String> repositoryProperties, Element storeConfig) throws CoreException
{
String type = storeConfig.getAttribute("type"); //$NON-NLS-1$
IStoreFactory storeFactory = getStoreFactory(type);
return storeFactory.createStore(repositoryName, repositoryProperties, storeConfig);
}
/**
* @since 4.7
*/
protected <T> T getContainerElement(Element element, String defaultType)
{
String type = element.getAttribute("type"); //$NON-NLS-1$
if (StringUtil.isEmpty(type))
{
type = defaultType;
}
String description = element.getAttribute("description"); //$NON-NLS-1$
if (StringUtil.isEmpty(description))
{
Map<String, String> properties = getProperties(element, 1);
description = PropertiesFactory.createDescription(properties);
}
@SuppressWarnings("unchecked")
T containerElement = (T)container.getElement(RepositoryActivityLog.Factory.PRODUCT_GROUP, type, description);
return containerElement;
}
public static Map<String, String> getProperties(Element element, int levels)
{
Map<String, String> properties = new HashMap<String, String>();
collectProperties(element, "", properties, levels); //$NON-NLS-1$
return properties;
}
private static void collectProperties(Element element, String prefix, Map<String, String> properties, int levels)
{
if ("property".equals(element.getNodeName())) //$NON-NLS-1$
{
String name = element.getAttribute("name"); //$NON-NLS-1$
String value = element.getAttribute("value"); //$NON-NLS-1$
properties.put(prefix + name, value);
prefix += name + "."; //$NON-NLS-1$
}
if (levels > 0)
{
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++)
{
Node childNode = childNodes.item(i);
if (childNode instanceof Element)
{
collectProperties((Element)childNode, prefix, properties, levels - 1);
}
}
}
}
private static <T> T createExecutableExtension(String extPointName, String elementName, String attributeName, String type) throws CoreException
{
if (OMPlatform.INSTANCE.isExtensionRegistryAvailable())
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IConfigurationElement[] elements = registry.getConfigurationElementsFor(OM.BUNDLE_ID, extPointName);
for (IConfigurationElement element : elements)
{
if (ObjectUtil.equals(element.getName(), elementName))
{
String storeType = element.getAttribute(attributeName);
if (ObjectUtil.equals(storeType, type))
{
@SuppressWarnings("unchecked")
T result = (T)element.createExecutableExtension("class"); //$NON-NLS-1$
return result;
}
}
}
}
return null;
}
/**
* @author Eike Stepper
* @since 4.7
*/
public static abstract class Factory extends org.eclipse.net4j.util.factory.Factory implements ContainerAware
{
public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.repositoryConfigurators"; //$NON-NLS-1$
private IManagedContainer container;
public Factory(String type)
{
super(PRODUCT_GROUP, type);
}
public void setManagedContainer(IManagedContainer container)
{
this.container = container;
}
public final RepositoryConfigurator create(String description) throws ProductCreationException
{
return create(container, description);
}
public abstract RepositoryConfigurator create(IManagedContainer container, String description) throws ProductCreationException;
/**
* @author Eike Stepper
*/
public static final class Default extends Factory
{
public static final String TYPE = "default"; //$NON-NLS-1$
public Default()
{
super(TYPE);
}
@Override
public RepositoryConfigurator create(IManagedContainer container, String description) throws ProductCreationException
{
return new RepositoryConfigurator(container);
}
}
}
}