001    /*
002     * JBoss, Home of Professional Open Source.
003     * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004     * as indicated by the @author tags. See the copyright.txt file in the
005     * distribution for a full listing of individual contributors. 
006     *
007     * This is free software; you can redistribute it and/or modify it
008     * under the terms of the GNU Lesser General Public License as
009     * published by the Free Software Foundation; either version 2.1 of
010     * the License, or (at your option) any later version.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this software; if not, write to the Free
019     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021     */
022    
023    package org.jboss.dna.repository.util;
024    
025    import java.util.Map;
026    import java.util.concurrent.ConcurrentHashMap;
027    import javax.jcr.Credentials;
028    import javax.jcr.Repository;
029    import javax.jcr.Session;
030    import javax.naming.InitialContext;
031    import org.jboss.dna.common.SystemFailureException;
032    import org.jboss.dna.repository.RepositoryI18n;
033    
034    /**
035     * A SessionFactory implementation that creates {@link Session} instances using {@link Repository} instances registered in JNDI.
036     * <p>
037     * This factory using a naming convention where the name supplied to the {@link #createSession(String)} contains both the name of
038     * the repository and the name of the workspace. Typically, this is <i><code>repositoryName/workspaceName</code></i>, where
039     * <code>repositoryName</code> is the JNDI name under which the Repository instance was bound, and <code>workspaceName</code>
040     * is the name of the workspace. Note that this method looks for the last delimiter in the whole name to distinguish between the
041     * repository and workspace names.
042     * </p>
043     * <p>
044     * For example, if "<code>java:comp/env/repository/dataRepository/myWorkspace</code>" is passed to the
045     * {@link #createSession(String)} method, this factory will look for a {@link Repository} instance registered in JDNI with the
046     * name "<code>java:comp/env/repository/dataRepository</code>" and use it to {@link Repository#login(String) create a session}
047     * to the workspace named "<code>myWorkspace</code>".
048     * </p>
049     * <p>
050     * By default, this factory creates an anonymous JCR session. To use sessions with specific {@link Credentials}, simply
051     * {@link #registerCredentials(String, Credentials) register} credentials for the appropriate repository/workspace name. For
052     * security reasons, it is not possible to retrieve the Credentials once registered with this factory.
053     * </p>
054     * 
055     * @author Randall Hauch
056     */
057    public class SimpleSessionFactory extends AbstractSessionFactory {
058    
059        private final Map<String, Repository> repositories = new ConcurrentHashMap<String, Repository>();
060    
061        /**
062         * Create an instance of the factory by creating a new {@link InitialContext}.
063         */
064        public SimpleSessionFactory() {
065            super();
066        }
067    
068        /**
069         * Create an instance of the factory by supplying the characters that may be used to delimit the workspace name from the
070         * repository name.
071         * 
072         * @param workspaceDelimiters the delimiters, or null/empty if the default delimiter of '/' should be used.
073         */
074        public SimpleSessionFactory( char... workspaceDelimiters ) {
075            super(workspaceDelimiters);
076        }
077    
078        /**
079         * {@inheritDoc}
080         */
081        @Override
082        protected void doRegisterRepository( String name,
083                                             Repository repository ) {
084            this.repositories.put(name, repository);
085        }
086    
087        /**
088         * {@inheritDoc}
089         */
090        @Override
091        protected void doUnregisterRepository( String name ) throws SystemFailureException {
092            if (this.repositories.remove(name) == null) {
093                throw new SystemFailureException(RepositoryI18n.unableToRemoveRepository.text(name));
094            }
095        }
096    
097        /**
098         * {@inheritDoc}
099         */
100        @Override
101        protected Repository findRegisteredRepository( String name ) throws SystemFailureException {
102            Repository repository = this.repositories.get(name);
103            if (repository == null) {
104                throw new SystemFailureException(RepositoryI18n.unableToFindRepositoryWithName.text(name));
105            }
106            return repository;
107        }
108    
109    }