All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modeshape.jcr.JndiJcrRepositoryFactory Maven / Gradle / Ivy

/*
 * ModeShape (http://www.modeshape.org)
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * See the AUTHORS.txt file in the distribution for a full listing of 
 * individual contributors.
 *
 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
 * is licensed to you under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 * 
 * ModeShape is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.modeshape.jcr;

import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.modeshape.jcr.api.Repositories;
import org.modeshape.jcr.api.RepositoryFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Map;
import java.util.ServiceLoader;

/**
 * Service provider for the JCR2 {@code RepositoryFactory} interface. This class provides a single public method,
 * {@link #getRepository(Map)}, that enables finding a JCR repository that is registered in JNDI.
 * 

* The canonical way to get a reference to this class is to use the {@link ServiceLoader}. For example, when the * {@link Repository} instance is registered in JNDI, the following code will find it via the ServiceLoader: * *

 * String jndiUrl = "jndi:jcr/local/myRepository";
 * Map parameters = Collections.singletonMap(JndiJcrRepositoryFactory.URL, configUrl);
 * Repository repository;
 *
 * for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
 *     repository = factory.getRepository(parameters);
 *     if (repository != null) break;
 * }
 * 
* * Or, if the ModeShape engine is registered in JNDI at "jcr/local", the same technique can be used with a slightly modified URL * parameter: * *
 * String jndiUrl = "jndi:jcr/local?repositoryName=myRepository"; // Different URL
 * Map parameters = Collections.singletonMap(JndiJcrRepositoryFactory.URL, configUrl);
 * Repository repository;
 *
 * for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
 *     repository = factory.getRepository(parameters);
 *     if (repository != null) break;
 * }
 * 
* * Alternatively, the repository name can be provided completely separately from the JNDI URL (again, if the ModeShape engine is * registered in JNDI at "jcr/local"): * *
 * String jndiUrl = "jndi:jcr/local";
 * String repoName = "myRepository";
 *
 * Map<String, String> parameters = new HashMap<String, String>();
 * parameters.put(org.modeshape.jcr.JndiJcrRepositoryFactory.URL, jndiUrl);
 * parameters.put(org.modeshape.jcr.JndiJcrRepositoryFactory.REPOSITORY_NAME, repoName);
 *
 * Repository repository = null;
 * for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
 *     repository = factory.getRepository(parameters);
 *     if (repository != null) break;
 * }
 * 
* * @see #getRepository(Map) * @see org.modeshape.jcr.api.RepositoryFactory#getRepository(Map) */ public class JndiJcrRepositoryFactory implements javax.jcr.RepositoryFactory { /** * The name of the key for the ModeShape JCR URL in the parameter map. *

* For example, define a URL that points to the configuration file for your repository: * *

     * String jndiUrl = "jndi:jcr/local/myRepository";
     *
     * Map<String, String> parameters = new HashMap<String, String>();
     * parameters.put(org.modeshape.jcr.JndiJcrRepositoryFactory.URL, configUrl);
     *
     * Repository repository = null;
     * for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
     *     repository = factory.getRepository(parameters);
     *     if (repository != null) break;
     * }
     * 
* *

*/ public static final String URL = RepositoryFactory.URL; /** * The name of the key for the ModeShape JCR repository name in the parameter map. This can be used as with a {@link #URL URL} * that contains the JNDI name of a {@link org.modeshape.jcr.api.Repositories} implementation. *

* For example: * *

     * String jndiUrl = "jndi:jcr/local";
     * String repoName = "myRepository";
     *
     * Map<String, String> parameters = new HashMap<String, String>();
     * parameters.put(org.modeshape.jcr.JndiJcrRepositoryFactory.URL, jndiUrl);
     * parameters.put(org.modeshape.jcr.JndiJcrRepositoryFactory.REPOSITORY_NAME, repoName);
     *
     * Repository repository = null;
     * for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
     *     repository = factory.getRepository(parameters);
     *     if (repository != null) break;
     * }
     * 
* *

*/ public static final String REPOSITORY_NAME = RepositoryFactory.REPOSITORY_NAME; /** * The name of the URL parameter that specifies the repository name. */ public static final String REPOSITORY_NAME_PARAM = "repositoryName"; @SuppressWarnings( { "rawtypes", "unchecked" } ) @Override public Repository getRepository( Map parameters ) throws RepositoryException { URL url = getUrlFrom(parameters); if (url == null) { return null; } if (!"jndi".equals(url.getProtocol())) { // This URL is not a JNDI URL and therefore we don't understand it ... return null; } // Now try to look up the repository in JNDI ... return getRepositoryFromJndi(url, parameters); } private URL getUrlFrom( Map parameters ) { if (parameters == null) { return null; } Object rawUrl = parameters.get(RepositoryFactory.URL); if (rawUrl == null) { return null; } // Convert the raw value to a URL object ... URL url = null; if (rawUrl instanceof URL) { url = (URL)rawUrl; } else { url = urlFor(rawUrl.toString()); } return url; } protected String getRepositoryNameFrom( URL url, Map parameters ) { if (parameters != null) { // First look in the parameters ... Object repoName = parameters.get(REPOSITORY_NAME); if (repoName != null) { return repoName.toString(); } } // Then look for a query parameter in the URL ... String query = url.getQuery(); if (query != null) { for (String keyValuePair : query.split("&")) { String[] splitPair = keyValuePair.split("="); if (splitPair.length == 2 && REPOSITORY_NAME_PARAM.equals(splitPair[0])) { return splitPair[1]; } } } return null; } /** * Convenience method to convert a {@code String} into an {@code URL}. This method never throws a * {@link MalformedURLException}, but may throw a {@link NullPointerException} if {@code jcrUrl} is null. * * @param jcrUrl the string representation of an URL that should be converted into an URL; may not be null * @return the URL version of {@code jcrUrl} if {@code jcrUrl} is a valid URL, otherwise null */ private URL urlFor( String jcrUrl ) { assert jcrUrl != null; assert !jcrUrl.isEmpty(); try { return new URL(jcrUrl); } catch (MalformedURLException mue) { return null; } } /** * Returns a hashtable with the same key/value mappings as the given map * * @param map the set of key/value mappings to convert; may not be null * @return a hashtable with the same key/value mappings as the given map; may be empty, never null */ private Hashtable hashtable( Map map ) { assert map != null; Hashtable hash = new Hashtable(map.size()); for (Map.Entry entry : map.entrySet()) { Object value = entry.getValue(); hash.put(entry.getKey(), value != null ? value.toString() : null); } return hash; } /** * Attempts to look up a {@link Repository} at the given JNDI name. All parameters in the parameters map are passed to the * {@link InitialContext} constructor in a {@link Hashtable}. * * @param url the URL containing the JNDI name of the {@link Repository} or {@link org.modeshape.jcr.api.Repositories} instance; may not be null * @param parameters any additional parameters that should be passed to the {@code InitialContext}'s constructor; may be empty * or null * @return the Repository object from JNDI, if one exists at the given name * @throws RepositoryException if there is a problem obtaining the repository */ private Repository getRepositoryFromJndi( URL url, Map parameters ) throws RepositoryException { String jndiName = url.getPath(); if (jndiName == null) { return null; } // There should be a parameter with the name ... try { InitialContext ic = new InitialContext(hashtable(parameters)); Object ob = ic.lookup(jndiName); if (ob instanceof Repository) { // The object in JNDI is a Repository, so simply return it ... return (Repository)ob; } else if (ob instanceof Repositories) { // The object in JNDI was a Repositories object that allows us to look up the Repository by name Repositories repos = (Repositories)ob; // Get the name from the parameters or the URL ... String repositoryName = getRepositoryNameFrom(url, parameters); // Now look up the repository by name ... return repos.getRepository(repositoryName); } return null; } catch (NamingException ne) { throw new RepositoryException(ne); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy