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 static org.hamcrest.core.Is.is;
019import static org.hamcrest.core.IsInstanceOf.instanceOf;
020import static org.hamcrest.core.IsNull.notNullValue;
021import static org.junit.Assert.assertThat;
022import static org.mockito.Mockito.when;
023import java.sql.Connection;
024import java.sql.DriverManager;
025import java.sql.DriverPropertyInfo;
026import java.sql.SQLException;
027import java.util.Properties;
028import javax.naming.Context;
029import org.junit.After;
030import org.junit.Before;
031import org.junit.Test;
032import org.mockito.Mock;
033import org.mockito.MockitoAnnotations;
034import org.modeshape.jcr.api.Repositories;
035import org.modeshape.jcr.api.Repository;
036import org.modeshape.jdbc.delegate.ConnectionInfo;
037
038/**
039 * 
040 */
041public class JcrDriverTest {
042
043    private JcrDriver driver;
044    private String jndiNameForRepository;
045    private String jndiNameForRepositories;
046    private String validUrl;
047    private Properties validProperties;
048    private String validRepositoryName;
049
050    @Mock
051    private Context jndi;
052    @Mock
053    private Repository repository;
054    @Mock
055    private Repositories repositories;
056
057    @Before
058    public void beforeEach() throws Exception {
059        MockitoAnnotations.initMocks(this);
060        validRepositoryName = "MyRepository";
061        jndiNameForRepository = "java:MyRepository";
062        jndiNameForRepositories = "java:Repositories";
063        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepository + "?workspace=MyWorkspace&user=jsmith&password=secret";
064        validProperties = new Properties();
065
066        when(jndi.lookup(jndiNameForRepository)).thenReturn(repository);
067        when(jndi.lookup(jndiNameForRepositories)).thenReturn(repositories);
068        when(repositories.getRepository(validRepositoryName)).thenReturn(repository);
069
070        driver = new JcrDriver(properties -> jndi);
071    }
072
073    @After
074    public void afterEach() throws Exception {
075        try {
076            DriverManager.deregisterDriver(driver);
077        } finally {
078            jndi = null;
079            repositories = null;
080            driver = null;
081        }
082    }
083
084    @Test
085    public void shouldNotBeJdbcCompliant() {
086        assertThat(driver.jdbcCompliant(), is(false));
087    }
088
089    @Test
090    public void shouldHaveMajorVersion() {
091        assertThat(driver.getMajorVersion(), is(TestUtil.majorVersion(JdbcI18n.driverVersion.text())));
092    }
093
094    @Test
095    public void shouldHaveMinorVersion() {
096        assertThat(driver.getMinorVersion(), is(TestUtil.minorVersion(JdbcI18n.driverVersion.text())));
097    }
098
099    @Test
100    public void shouldHaveVendorUrl() {
101        assertThat(driver.getVendorUrl(), is(JdbcI18n.driverVendorUrl.text()));
102    }
103
104    @Test
105    public void shouldHaveVendorName() {
106        assertThat(driver.getVendorName(), is(JdbcI18n.driverVendor.text()));
107    }
108
109    @Test
110    public void shouldHaveVersion() {
111        assertThat(driver.getVersion(), is(JdbcI18n.driverVersion.text()));
112    }
113
114    @Test
115    public void shouldReturnEmptyPropertyInfosWhenSuppliedValidAndCompleteUrlAndNoProperties() throws SQLException {
116        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
117        assertThat(infos.length, is(0));
118    }
119
120    @Test
121    public void shouldReturnEmptyPropertyInfosWhenSuppliedValidUrlAndAllPropertiesWithRepositoryInJndi() throws SQLException {
122        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepository;
123        validProperties.put(JcrDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
124        validProperties.put(JcrDriver.USERNAME_PROPERTY_NAME, "jsmith");
125        validProperties.put(JcrDriver.PASSWORD_PROPERTY_NAME, "secret");
126        validProperties.put(JcrDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
127        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
128        assertThat(infos.length, is(0));
129    }
130
131    @Test
132    public void shouldReturnEmptyPropertyInfosWhenSuppliedValidUrlAndAllPropertiesWithRepositoriesInJndi() throws SQLException {
133        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepositories;
134        validProperties.put(JcrDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
135        validProperties.put(JcrDriver.USERNAME_PROPERTY_NAME, "jsmith");
136        validProperties.put(JcrDriver.PASSWORD_PROPERTY_NAME, "secret");
137        validProperties.put(JcrDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
138        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
139        assertThat(infos.length, is(0));
140    }
141
142    @Test
143    public void shouldReturnRepositoryPropertyInfoWhenMissingRequiredRepositoryName() throws SQLException {
144        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepositories;
145        validProperties.put(JcrDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
146        validProperties.put(JcrDriver.USERNAME_PROPERTY_NAME, "jsmith");
147        validProperties.put(JcrDriver.PASSWORD_PROPERTY_NAME, "secret");
148        // validProperties.put(JdbcDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
149        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
150        assertThat(infos.length, is(1));
151        assertThat(infos[0].name, is(JdbcLocalI18n.repositoryNamePropertyName.text()));
152        assertThat(infos[0].description, is(JdbcLocalI18n.repositoryNamePropertyDescription.text()));
153        assertThat(infos[0].required, is(true));
154    }
155
156    @Test
157    public void shouldReturnRepositoryPropertyInfoWhenMissingWorkspaceName() throws SQLException {
158        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepositories;
159        // validProperties.put(JdbcDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
160        validProperties.put(JcrDriver.USERNAME_PROPERTY_NAME, "jsmith");
161        validProperties.put(JcrDriver.PASSWORD_PROPERTY_NAME, "secret");
162        validProperties.put(JcrDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
163        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
164        assertThat(infos.length, is(1));
165        assertThat(infos[0].name, is(JdbcLocalI18n.workspaceNamePropertyName.text()));
166        assertThat(infos[0].description, is(JdbcLocalI18n.workspaceNamePropertyDescription.text()));
167        assertThat(infos[0].required, is(false));
168    }
169
170    @Test
171    public void shouldReturnRepositoryPropertyInfoWhenMissingUsername() throws SQLException {
172        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepositories;
173        validProperties.put(JcrDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
174        // validProperties.put(JdbcDriver.USERNAME_PROPERTY_NAME, "jsmith");
175        validProperties.put(JcrDriver.PASSWORD_PROPERTY_NAME, "secret");
176        validProperties.put(JcrDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
177        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
178        assertThat(infos.length, is(1));
179        assertThat(infos[0].name, is(JdbcLocalI18n.usernamePropertyName.text()));
180        assertThat(infos[0].description, is(JdbcLocalI18n.usernamePropertyDescription.text()));
181        assertThat(infos[0].required, is(false));
182    }
183
184    @Test
185    public void shouldReturnRepositoryPropertyInfoWhenMissingPassword() throws SQLException {
186        validUrl = JcrDriver.JNDI_URL_PREFIX + jndiNameForRepositories;
187        validProperties.put(JcrDriver.WORKSPACE_PROPERTY_NAME, "MyWorkspace");
188        validProperties.put(JcrDriver.USERNAME_PROPERTY_NAME, "jsmith");
189        // validProperties.put(JdbcDriver.PASSWORD_PROPERTY_NAME, "secret");
190        validProperties.put(JcrDriver.REPOSITORY_PROPERTY_NAME, validRepositoryName);
191        DriverPropertyInfo[] infos = driver.getPropertyInfo(validUrl, validProperties);
192        assertThat(infos.length, is(1));
193        assertThat(infos[0].name, is(JdbcLocalI18n.passwordPropertyName.text()));
194        assertThat(infos[0].description, is(JdbcLocalI18n.passwordPropertyDescription.text()));
195        assertThat(infos[0].required, is(false));
196    }
197
198    @Test
199    public void shouldAcceptValidUrls() {
200        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX
201                                     + "java:nameInJndi?workspace=MyWorkspace&user=jsmith&password=secret&teiidsupport=true"),
202                   is(true));
203        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX
204                                     + "java:nameInJndi?workspace=MyWorkspace&user=jsmith&password=secret"),
205                   is(true));
206        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "java:nameInJndi?workspace=MyWorkspace&user=jsmith"), is(true));
207        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "java:nameInJndi?workspace=My%20Workspace"), is(true));
208        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "java:nameInJndi"), is(true));
209        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "java:nameInJndi?"), is(true));
210        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "java"), is(true));
211        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "j"), is(true));
212        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + "j "), is(true));
213        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + " j"), is(true));
214    }
215
216    @Test
217    public void shouldNotAcceptInvalidUrls() {
218        assertThat(driver.acceptsURL("jdbc:jcr:jndi"), is(false));
219        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX), is(false));
220        assertThat(driver.acceptsURL(JcrDriver.JNDI_URL_PREFIX + " "), is(false));
221        assertThat(driver.acceptsURL("file://"), is(false));
222        assertThat(driver.acceptsURL("jdbc://"), is(false));
223    }
224
225    @Test
226    public void shouldCreateConnectionInfoForUrlWithEscapedCharacters() throws SQLException {
227        validUrl = JcrDriver.JNDI_URL_PREFIX
228                   + "java:nameInJndi?workspace=My%20Workspace&user=j%20smith&password=secret&repositoryName=My%20Repository&teiidsupport=true";
229        ConnectionInfo info = driver.createConnectionInfo(validUrl, validProperties);
230        assertThat(info.getWorkspaceName(), is("My Workspace"));
231        assertThat(info.getUsername(), is("j smith"));
232        assertThat(info.getPassword(), is("secret".toCharArray()));
233        assertThat(info.getRepositoryName(), is("My Repository"));
234        assertThat(info.isTeiidSupport(), is(true));
235    }
236
237    @Test
238    public void shouldCreateConnectionInfoButIndicateNoTeiidSupport() throws SQLException {
239        validUrl = JcrDriver.JNDI_URL_PREFIX
240                   + "java:nameInJndi?workspace=My%20Workspace&user=j%20smith&password=secret&repositoryName=My%20Repository";
241        ConnectionInfo info = driver.createConnectionInfo(validUrl, validProperties);
242        assertThat(info.isTeiidSupport(), is(false));
243    }
244
245    @Test
246    public void shouldCreateConnectionWithValidUrlAndProperties() throws SQLException {
247        Connection conn = driver.connect(validUrl, validProperties);
248        assertThat(conn, is(notNullValue()));
249        assertThat(conn.isClosed(), is(false));
250        conn.close();
251        assertThat(conn.isClosed(), is(true));
252    }
253
254    @Test
255    public void shouldCreateConnectionWithDriverManagerAfterRegisteringDriver() throws SQLException {
256        DriverManager.registerDriver(driver);
257        Connection connection = DriverManager.getConnection(validUrl, validProperties);
258        assertThat(connection, is(notNullValue()));
259        assertThat(connection, is(instanceOf(JcrConnection.class)));
260        assertThat(connection.isWrapperFor(JcrConnection.class), is(true));
261        assertThat(connection.unwrap(JcrConnection.class), is(instanceOf(JcrConnection.class)));
262    }
263
264}