/* * Copyright (c) 2011-2013, 2015 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.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); } } 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); 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); } } } 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); } 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; } }