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