001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.fcrepo.http.commons.session;
020
021import org.fcrepo.kernel.api.Transaction;
022import org.fcrepo.kernel.api.TransactionManager;
023import org.glassfish.jersey.internal.PropertiesDelegate;
024import org.glassfish.jersey.server.ContainerRequest;
025import org.junit.Before;
026import org.junit.Test;
027import org.junit.runner.RunWith;
028import org.mockito.Mock;
029import org.mockito.junit.MockitoJUnitRunner;
030
031import javax.servlet.http.HttpServletRequest;
032import javax.ws.rs.core.SecurityContext;
033import javax.ws.rs.core.UriInfo;
034import java.net.URI;
035
036import static java.net.URI.create;
037import static org.mockito.Mockito.mock;
038import static org.mockito.Mockito.spy;
039import static org.mockito.Mockito.verify;
040import static org.mockito.Mockito.when;
041
042/**
043 * @author pwinckles
044 */
045@RunWith(MockitoJUnitRunner.Silent.class)
046public class TransactionProviderTest {
047
048    @Mock
049    private TransactionManager transactionManager;
050
051    @Mock
052    private HttpServletRequest request;
053
054    @Mock
055    private Transaction transaction;
056
057    @Before
058    public void setup() {
059        when(transactionManager.create()).thenReturn(transaction);
060    }
061
062    private TransactionProvider createProvider(final UriInfo uriInfo, final String jmsBaseUrl) {
063        return new TransactionProvider(transactionManager, request, uriInfo.getBaseUri(), jmsBaseUrl);
064    }
065
066    @Test
067    public void testSetUserAgent() {
068        // Obtain a concrete instance of UriInfo
069        final URI baseUri = create("http://localhost/fcrepo");
070        final URI requestUri = create("http://localhost/fcrepo/foo");
071        final ContainerRequest req = new ContainerRequest(baseUri, requestUri, "GET", mock(SecurityContext.class),
072                mock(PropertiesDelegate.class));
073        final UriInfo info = spy(req.getUriInfo());
074
075        final String expectedBaseUrl = baseUri.toString();
076        final String expectedUserAgent = "fedoraAdmin";
077
078        when(request.getHeader("user-agent")).thenReturn(expectedUserAgent);
079
080        createProvider(info, "").provide();
081
082        verify(transaction).setBaseUri(expectedBaseUrl);
083        verify(transaction).setUserAgent(expectedUserAgent);
084        verify(info).getBaseUri();
085    }
086
087    /**
088     * Demonstrates that when the jmsBaseUrl is not set, the url used for JMS messages is the same as the base url
089     * found in the {@code UriInfo}.
090     * <p>
091     * Implementation note: this test requires a concrete instance of {@link UriInfo}, because it is the interaction of
092     * {@code javax.ws.rs.core.UriBuilder} and {@code TransactionProvider} that is being tested.
093     * </p>
094     */
095    @Test
096    public void testJmsBaseUrlDefault() {
097        // Obtain a concrete instance of UriInfo
098        final URI baseUri = create("http://localhost/fcrepo");
099        final URI requestUri = create("http://localhost/fcrepo/foo");
100        final ContainerRequest req = new ContainerRequest(baseUri, requestUri, "GET", mock(SecurityContext.class),
101                mock(PropertiesDelegate.class));
102        final UriInfo info = spy(req.getUriInfo());
103
104        final String expectedBaseUrl = baseUri.toString();
105
106        createProvider(info, "").provide();
107
108        verify(transaction).setBaseUri(expectedBaseUrl);
109        verify(info).getBaseUri();
110    }
111
112    /**
113     * Demonstrates that the host supplied by the jmsBaseUrl is used as the as the base url for JMS messages, and not
114     * the base url found in {@code UriInfo}.
115     * <p>
116     * Note: the path from the request is preserved, the host from the fcrepo.jms.baseUrl is used
117     * </p>
118     * <p>
119     * Implementation note: this test requires a concrete instance of {@link UriInfo}, because it is the interaction of
120     * {@code javax.ws.rs.core.UriBuilder} and {@code TransactionProvider} that is being tested.
121     * </p>
122     */
123    @Test
124    public void testJmsBaseUrlOverrideHost() {
125        // Obtain a concrete implementation of UriInfo
126        final URI baseUri = create("http://localhost/fcrepo");
127        final URI requestUri = create("http://localhost/fcrepo/foo");
128        final ContainerRequest req = new ContainerRequest(baseUri, requestUri, "GET", mock(SecurityContext.class),
129                mock(PropertiesDelegate.class));
130        final UriInfo info = spy(req.getUriInfo());
131
132        final String baseUrl = "http://example.org";
133        final String expectedBaseUrl = baseUrl + baseUri.getPath();
134
135        createProvider(info, baseUrl).provide();
136
137        verify(transaction).setBaseUri(expectedBaseUrl);
138    }
139
140    /**
141     * Demonstrates that the host and port supplied by the jmsBaseUrl is used as the as the base url for JMS messages,
142     * and not the base url found
143     * in {@code UriInfo}.
144     * <p>
145     * Note: the path from the request is preserved, but the host and port from the request is overridden by the values
146     * from fcrepo.jms.baseUrl
147     * </p>
148     * <p>
149     * Implementation note: this test requires a concrete instance of {@link UriInfo}, because it is the interaction of
150     * {@code javax.ws.rs.core.UriBuilder} and {@code TransactionProvider} that is being tested.
151     * </p>
152     */
153    @Test
154    public void testJmsBaseUrlOverrideHostAndPort() {
155        // Obtain a concrete implementation of UriInfo
156        final URI baseUri = create("http://localhost/fcrepo");
157        final URI requestUri = create("http://localhost/fcrepo/foo");
158        final ContainerRequest req = new ContainerRequest(baseUri, requestUri, "GET", mock(SecurityContext.class),
159                mock(PropertiesDelegate.class));
160        final UriInfo info = spy(req.getUriInfo());
161
162        final String baseUrl = "http://example.org:9090";
163        final String expectedBaseUrl = baseUrl + baseUri.getPath();
164
165        createProvider(info, baseUrl).provide();
166
167        verify(transaction).setBaseUri(expectedBaseUrl);
168    }
169
170    /**
171     * Demonstrates that the url supplied by the jmsBaseUrl is used as the as the base url for JMS messages, and not
172     * the base url found in {@code UriInfo}.
173     * <p>
174     * Note: the host and path from the request is overridden by the values from fcrepo.jms.baseUrl
175     * </p>
176     * <p>
177     * Implementation note: this test requires a concrete instance of {@link UriInfo}, because it is the interaction of
178     * {@code javax.ws.rs.core.UriBuilder} and {@code TransactionProvider} that is being tested.
179     * </p>
180     */
181    @Test
182    public void testJmsBaseUrlOverrideUrl() {
183        // Obtain a concrete implementation of UriInfo
184        final URI baseUri = create("http://localhost/fcrepo");
185        final URI requestUri = create("http://localhost/fcrepo/foo");
186        final ContainerRequest req = new ContainerRequest(baseUri, requestUri, "GET", mock(SecurityContext.class),
187                mock(PropertiesDelegate.class));
188        final UriInfo info = spy(req.getUriInfo());
189
190        final String expectedBaseUrl = "http://example.org/fcrepo/rest";
191
192        createProvider(info, expectedBaseUrl).provide();
193
194        verify(transaction).setBaseUri(expectedBaseUrl);
195    }
196
197    /**
198     * Demonstrates that when the the base url in {@code UriInfo} contains a port number, and the base url does
199     * <em>not</em> contain a port number, that the
200     * base url for JMS messages does not contain a port number.
201     * <p>
202     * Note: the host, port, and path from the request is overridden by values from fcrepo.jms.baseUrl
203     * </p>
204     * <p>
205     * Implementation note: this test requires a concrete instance of {@link UriInfo}, because it is the interaction of
206     * {@code javax.ws.rs.core.UriBuilder} and {@code TransactionProvider} that is being tested.
207     * </p>
208     */
209    @Test
210    public void testJmsBaseUrlOverrideRequestUrlWithPort8080() {
211        // Obtain a concrete implementation of UriInfo
212        final URI baseUri = create("http://localhost:8080/fcrepo/rest");
213        final URI reqUri = create("http://localhost:8080/fcrepo/rest/foo");
214        final ContainerRequest req = new ContainerRequest(baseUri, reqUri, "GET", mock(SecurityContext.class),
215                mock(PropertiesDelegate.class));
216        final UriInfo info = spy(req.getUriInfo());
217
218        final String expectedBaseUrl = "http://example.org/fcrepo/rest/";
219
220        createProvider(info, expectedBaseUrl).provide();
221
222        verify(transaction).setBaseUri(expectedBaseUrl);
223    }
224
225}