001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.jdbc;
017
018import java.sql.DriverManager;
019import java.sql.SQLException;
020import javax.jcr.Repository;
021import org.modeshape.jdbc.delegate.HttpRepositoryDelegate;
022
023/**
024 * A JDBC driver implementation that is able to access a JCR repository to query its contents using JCR-SQL2. <h3>Connection URLs</h3>
025 * <p>
026 * The driver accepts several URL formats based on how the repository is configured:
027 * <ol>
028 * <li>configured for <i>local</i> access using JNDI
029 * 
030 * <pre>
031 *     jdbc:jcr:jndi:{jndiName}
032 * </pre>
033 * 
034 * or
035 * 
036 * <pre>
037 *     jdbc:jcr:jndi:{jndiName}?{firstProperty}&amp;{secondProperty}&amp;...
038 * </pre>
039 * 
040 * where
041 * <ul>
042 * <li><strong>{jndiName}</strong> is the JNDI name where the {@link Repository} or {@literal org.modeshape.jcr.api.Repositories}
043 * instance can be found;</li>
044 * <li><strong>{firstProperty}</strong> consists of the first property name followed by '=' followed by the property's value;</li>
045 * <li><strong>{secondProperty}</strong> consists of the second property name followed by '=' followed by the property's value;</li>
046 * </ul>
047 * Note that any use of URL encoding ('%' followed by a two-digit hexadecimal value) will be decoded before being used.
048 * </p>
049 * <p>
050 * Here's an example of a URL that defines a {@link Repository} instance located at "<code>jcr/local</code>" with a repository
051 * name of "repository" and a user, password of "secret", and workspace name of "My Workspace":
052 * 
053 * <pre>
054 *     jdbc:jcr:jndi:jcr/local?repositoryName=repository&user=jsmith&amp;password=secret&amp;workspace=My%20Workspace
055 * </pre>
056 * 
057 * The "repository" property is required only if the object in JNDI is a {@literal org.modeshape.jcr.api.Repositories} object. <br />
058 * <br />
059 * </p>
060 * <li>configured for <i>remote</i> access using REST interface.
061 * 
062 * <pre>
063 *     jdbc:jcr:http://{hostname}:{port}?{firstProperty}&amp;{secondProperty}&amp;...
064 * </pre>
065 * 
066 * where
067 * <ul>
068 * <li><strong>{hostname}</strong> is the host name where the {@link Repository} or {@literal org.modeshape.jcr.api.Repositories}
069 * instance can be found;</li>
070 * <li><strong>{port}</strong> is the port to access the {@link Repository} or {@literal org.modeshape.jcr.api.Repositories} on
071 * the specified <i>hostname</i>;</li>
072 * <li><strong>{firstProperty}</strong> consists of the first property name followed by '=' followed by the property's value;</li>
073 * <li><strong>{secondProperty}</strong> consists of the second property name followed by '=' followed by the property's value;</li>
074 * </ul>
075 * <p>
076 * Note that any use of URL encoding ('%' followed by a two-digit hexadecimal value) will be decoded before being used.
077 * </p>
078 * </ol>
079 */
080
081public class JcrDriver extends LocalJcrDriver {
082
083    /* URL Prefix used for remote access */
084    public static final String HTTP_URL_PREFIX = "jdbc:jcr:http://";
085
086    static {
087        try {
088            DriverManager.registerDriver(new JcrDriver(null));
089        } catch (SQLException e) {
090            logger.error(JdbcI18n.driverErrorRegistering, e.getMessage());
091        }
092    }
093
094    /**
095     * No-arg constructor, required by the {@link DriverManager}.
096     */
097    public JcrDriver() {
098        this(null);
099    }
100
101    /**
102     * Create an instance of this driver using the supplied JNDI naming context factory. This is useful for testing, but is
103     * otherwise not generally recommended.
104     *
105     * @param namingContextFactory the naming context factory; may be null if one should be created automatically
106     */
107    protected JcrDriver( JcrContextFactory namingContextFactory ) {
108        super(HttpRepositoryDelegate.FACTORY, new DriverInfo(JdbcI18n.driverName.text(), JdbcI18n.driverVendor.text(),
109                                                             JdbcI18n.driverVendorUrl.text(), JdbcI18n.driverVersion.text()),
110              namingContextFactory);
111    }
112}