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 */
018package org.fcrepo.client;
019
020import static java.net.URI.create;
021import static org.fcrepo.client.ExternalContentHandling.PROXY;
022import static org.fcrepo.client.FedoraHeaderConstants.CONTENT_DISPOSITION;
023import static org.fcrepo.client.FedoraHeaderConstants.CONTENT_TYPE;
024import static org.fcrepo.client.FedoraHeaderConstants.DIGEST;
025import static org.fcrepo.client.FedoraHeaderConstants.IF_MATCH;
026import static org.fcrepo.client.FedoraHeaderConstants.IF_STATE_TOKEN;
027import static org.fcrepo.client.FedoraHeaderConstants.IF_UNMODIFIED_SINCE;
028import static org.fcrepo.client.FedoraHeaderConstants.LINK;
029import static org.fcrepo.client.FedoraHeaderConstants.PREFER;
030import static org.fcrepo.client.FedoraTypes.LDP_DIRECT_CONTAINER;
031import static org.fcrepo.client.LinkHeaderConstants.ACL_REL;
032import static org.fcrepo.client.LinkHeaderConstants.EXTERNAL_CONTENT_HANDLING;
033import static org.fcrepo.client.LinkHeaderConstants.EXTERNAL_CONTENT_REL;
034import static org.fcrepo.client.LinkHeaderConstants.TYPE_REL;
035import static org.fcrepo.client.TestUtils.baseUrl;
036import static org.junit.Assert.assertEquals;
037import static org.junit.Assert.assertNull;
038import static org.mockito.ArgumentMatchers.any;
039import static org.mockito.ArgumentMatchers.eq;
040import static org.mockito.Mockito.mock;
041import static org.mockito.Mockito.verify;
042import static org.mockito.Mockito.when;
043
044import java.io.InputStream;
045import java.net.URI;
046
047import org.apache.http.HttpEntity;
048import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
049import org.apache.http.client.methods.HttpRequestBase;
050import org.junit.Before;
051import org.junit.Test;
052import org.junit.runner.RunWith;
053import org.mockito.ArgumentCaptor;
054import org.mockito.Captor;
055import org.mockito.Mock;
056import org.mockito.junit.MockitoJUnitRunner;
057
058/**
059 * @author bbpennel
060 */
061@RunWith(MockitoJUnitRunner.class)
062public class PutBuilderTest {
063
064    @Mock
065    private FcrepoClient client;
066
067    @Mock
068    private FcrepoResponse fcrepoResponse;
069
070    @Captor
071    private ArgumentCaptor<HttpRequestBase> requestCaptor;
072
073    private PutBuilder testBuilder;
074
075    private URI uri;
076
077    @Before
078    public void setUp() throws Exception {
079        when(client.executeRequest(any(URI.class), any(HttpRequestBase.class)))
080                .thenReturn(fcrepoResponse);
081
082        uri = create(baseUrl);
083        testBuilder = new PutBuilder(uri, client);
084    }
085
086    @Test
087    public void testPutNoBody() throws Exception {
088        testBuilder.perform();
089
090        verify(client).executeRequest(eq(uri), requestCaptor.capture());
091
092        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
093        assertNull("Request body should not be set", request.getEntity());
094        assertEquals(0, request.getAllHeaders().length);
095    }
096
097    @Test
098    public void testWithBody() throws Exception {
099        final InputStream bodyStream = mock(InputStream.class);
100
101        testBuilder.body(bodyStream, "plain/text")
102                .digestSha1("checksum")
103                .filename("file.txt")
104                .perform();
105
106        verify(client).executeRequest(eq(uri), requestCaptor.capture());
107
108        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
109        final HttpEntity bodyEntity = request.getEntity();
110        assertEquals(bodyStream, bodyEntity.getContent());
111
112        assertEquals("plain/text", request.getFirstHeader(CONTENT_TYPE).getValue());
113        assertEquals("sha=checksum", request.getFirstHeader(DIGEST).getValue());
114        assertEquals("attachment; filename=\"file.txt\"", request.getFirstHeader(CONTENT_DISPOSITION).getValue());
115    }
116
117    @Test
118    public void testExternalContent() throws Exception {
119        final URI contentURI = URI.create("file:///path/to/file");
120        testBuilder.externalContent(contentURI, "plain/text", PROXY)
121                .perform();
122
123        verify(client).executeRequest(eq(uri), requestCaptor.capture());
124
125        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
126
127        final FcrepoLink extLink = new FcrepoLink(request.getFirstHeader(LINK).getValue());
128        assertEquals(EXTERNAL_CONTENT_REL, extLink.getRel());
129        assertEquals(PROXY, extLink.getParams().get(EXTERNAL_CONTENT_HANDLING));
130        assertEquals("plain/text", extLink.getType());
131    }
132
133    @Test
134    public void testDisposition() throws Exception {
135        final InputStream bodyStream = mock(InputStream.class);
136        testBuilder.body(bodyStream, "plain/text").filename(null).perform();
137
138        verify(client).executeRequest(eq(uri), requestCaptor.capture());
139
140        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
141        final HttpEntity bodyEntity = request.getEntity();
142        assertEquals(bodyStream, bodyEntity.getContent());
143        assertEquals("attachment", request.getFirstHeader(CONTENT_DISPOSITION).getValue());
144    }
145
146    @Test(expected = FcrepoOperationFailedException.class)
147    public void testPostClientError() throws Exception {
148        when(client.executeRequest(any(URI.class), any(HttpRequestBase.class)))
149                .thenThrow(new FcrepoOperationFailedException(uri, 415, "status"));
150
151        testBuilder.perform();
152    }
153
154    @Test
155    public void testWithModificationHeaders() throws Exception {
156        final InputStream bodyStream = mock(InputStream.class);
157
158        final String etag = "123456";
159        final String lastModified = "Mon, 19 May 2014 19:44:59 GMT";
160        testBuilder.body(bodyStream, "plain/text")
161                .ifMatch(etag)
162                .ifUnmodifiedSince(lastModified)
163                .perform();
164
165        verify(client).executeRequest(eq(uri), requestCaptor.capture());
166
167        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
168        final HttpEntity bodyEntity = request.getEntity();
169        assertEquals(bodyStream, bodyEntity.getContent());
170
171        assertEquals("plain/text", request.getFirstHeader(CONTENT_TYPE).getValue());
172        assertEquals(etag, request.getFirstHeader(IF_MATCH).getValue());
173        assertEquals(lastModified, request.getFirstHeader(IF_UNMODIFIED_SINCE).getValue());
174    }
175
176    @Test
177    public void testPreferLenient() throws Exception {
178        testBuilder.preferLenient().perform();
179
180        verify(client).executeRequest(eq(uri), requestCaptor.capture());
181
182        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
183        assertEquals("handling=lenient; received=\"minimal\"", request.getFirstHeader(PREFER).getValue());
184    }
185
186    @Test
187    public void testAddInteractionModel() throws Exception {
188        testBuilder.addInteractionModel(LDP_DIRECT_CONTAINER)
189                .perform();
190
191        verify(client).executeRequest(eq(uri), requestCaptor.capture());
192
193        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
194
195        final FcrepoLink interLink = new FcrepoLink(request.getFirstHeader(LINK).getValue());
196        assertEquals(TYPE_REL, interLink.getRel());
197        assertEquals(LDP_DIRECT_CONTAINER, interLink.getUri().toString());
198    }
199
200    @Test
201    public void testLinkAcl() throws Exception {
202        testBuilder.linkAcl("http://localhost/acl")
203                .perform();
204
205        verify(client).executeRequest(eq(uri), requestCaptor.capture());
206
207        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
208
209        final FcrepoLink aclLink = new FcrepoLink(request.getFirstHeader(LINK).getValue());
210        assertEquals(ACL_REL, aclLink.getRel());
211        assertEquals("http://localhost/acl", aclLink.getUri().toString());
212    }
213
214    @Test
215    public void testStateToken() throws Exception {
216        final InputStream bodyStream = mock(InputStream.class);
217        final String token = "state";
218
219        testBuilder.body(bodyStream)
220                .ifStateToken(token)
221                .perform();
222
223        verify(client).executeRequest(eq(uri), requestCaptor.capture());
224
225        final HttpEntityEnclosingRequestBase request = (HttpEntityEnclosingRequestBase) requestCaptor.getValue();
226        assertEquals(token, request.getFirstHeader(IF_STATE_TOKEN).getValue());
227    }
228
229    @Test
230    public void testAddHeader() throws Exception {
231        testBuilder.addHeader("my-header", "head-val").perform();
232
233        verify(client).executeRequest(eq(uri), requestCaptor.capture());
234        final HttpRequestBase request = requestCaptor.getValue();
235        assertEquals("head-val", request.getFirstHeader("my-header").getValue());
236    }
237
238    @Test
239    public void testAddLinkHeader() throws Exception {
240        final FcrepoLink link = FcrepoLink.fromUri("http://example.com/link").type("foo").build();
241        testBuilder.addLinkHeader(link).perform();
242
243        verify(client).executeRequest(eq(uri), requestCaptor.capture());
244        final HttpRequestBase request = requestCaptor.getValue();
245        assertEquals(link.toString(), request.getFirstHeader(LINK).getValue());
246    }
247}