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.camel;
019
020import static java.net.URI.create;
021import static java.util.Collections.emptyMap;
022import static java.util.Collections.singletonList;
023import static java.util.Collections.singletonMap;
024import static org.apache.camel.Exchange.ACCEPT_CONTENT_TYPE;
025import static org.apache.camel.Exchange.CONTENT_TYPE;
026import static org.apache.camel.Exchange.DISABLE_HTTP_STREAM_CACHE;
027import static org.apache.camel.Exchange.HTTP_METHOD;
028import static org.apache.camel.Exchange.HTTP_RESPONSE_CODE;
029import static org.fcrepo.camel.FcrepoHeaders.FCREPO_IDENTIFIER;
030import static org.fcrepo.camel.FcrepoHeaders.FCREPO_PREFER;
031import static org.fcrepo.camel.FcrepoProducer.PREFER_PROPERTIES;
032import static org.fcrepo.camel.TestUtils.N_TRIPLES;
033import static org.junit.Assert.assertEquals;
034import static org.junit.Assert.assertNotNull;
035import static org.mockito.Matchers.any;
036import static org.mockito.Matchers.eq;
037import static org.mockito.Mockito.mock;
038import static org.mockito.Mockito.when;
039
040import java.io.ByteArrayInputStream;
041import java.io.InputStream;
042import java.io.IOException;
043import java.net.URI;
044import java.util.HashMap;
045import java.util.List;
046import java.util.Map;
047
048import org.apache.camel.Exchange;
049import org.apache.camel.component.http4.HttpMethods;
050import org.apache.camel.converter.stream.InputStreamCache;
051import org.apache.camel.impl.DefaultCamelContext;
052import org.apache.camel.impl.DefaultExchange;
053import org.apache.camel.impl.DefaultUnitOfWork;
054import org.apache.commons.lang3.StringUtils;
055import org.fcrepo.client.DeleteBuilder;
056import org.fcrepo.client.FcrepoClient;
057import org.fcrepo.client.FcrepoOperationFailedException;
058import org.fcrepo.client.FcrepoResponse;
059import org.fcrepo.client.GetBuilder;
060import org.fcrepo.client.HeadBuilder;
061import org.fcrepo.client.PatchBuilder;
062import org.fcrepo.client.PostBuilder;
063import org.fcrepo.client.PutBuilder;
064import org.junit.Before;
065import org.junit.Test;
066import org.junit.runner.RunWith;
067import org.mockito.Mock;
068import org.mockito.runners.MockitoJUnitRunner;
069
070/**
071 * @author acoburn
072 */
073@RunWith(MockitoJUnitRunner.class)
074public class FcrepoProducerTest {
075
076    private static final String REPOSITORY = "http://fedora.info/definitions/v4/repository#";
077
078    private static final String LDP = "http://www.w3.org/ns/ldp#";
079
080    private FcrepoEndpoint testEndpoint;
081
082    private FcrepoProducer testProducer;
083
084    private Exchange testExchange;
085
086    @Mock
087    private FcrepoClient mockClient, mockClient2;
088
089    @Mock
090    private GetBuilder mockGetBuilder, mockGetBuilder2, mockGetBuilder3;
091
092    @Mock
093    private HeadBuilder mockHeadBuilder;
094
095    @Mock
096    private DeleteBuilder mockDeleteBuilder;
097
098    @Mock
099    private PostBuilder mockPostBuilder, mockPostBuilder2, mockPostBuilder3;
100
101    @Mock
102    private PatchBuilder mockPatchBuilder;
103
104    @Mock
105    private PutBuilder mockPutBuilder;
106
107    @Before
108    @SuppressWarnings("unchecked")
109    public void setUp() throws Exception {
110        final FcrepoComponent mockComponent = mock(FcrepoComponent.class);
111
112        final FcrepoConfiguration testConfig = new FcrepoConfiguration();
113        testEndpoint = new FcrepoEndpoint("fcrepo:localhost:8080", "/rest", mockComponent, testConfig);
114        testEndpoint.setBaseUrl("localhost:8080/rest");
115        testExchange = new DefaultExchange(new DefaultCamelContext());
116        testExchange.getIn().setBody(null);
117        when(mockClient.get(any(URI.class))).thenReturn(mockGetBuilder);
118        when(mockClient2.get(any(URI.class))).thenReturn(mockGetBuilder);
119        when(mockClient2.head(any(URI.class))).thenReturn(mockHeadBuilder);
120        when(mockGetBuilder.accept(any(String.class))).thenReturn(mockGetBuilder);
121        when(mockGetBuilder.preferMinimal()).thenReturn(mockGetBuilder);
122        when(mockGetBuilder.preferRepresentation(any(List.class), any(List.class))).thenReturn(mockGetBuilder);
123        when(mockGetBuilder2.accept(any(String.class))).thenReturn(mockGetBuilder2);
124        when(mockGetBuilder3.accept(any(String.class))).thenReturn(mockGetBuilder3);
125        when(mockClient.head(any(URI.class))).thenReturn(mockHeadBuilder);
126        when(mockClient.delete(any(URI.class))).thenReturn(mockDeleteBuilder);
127        when(mockClient.patch(any(URI.class))).thenReturn(mockPatchBuilder);
128        when(mockClient.post(any(URI.class))).thenReturn(mockPostBuilder);
129        when(mockClient.put(any(URI.class))).thenReturn(mockPutBuilder);
130        when(mockPatchBuilder.body(any(InputStream.class))).thenReturn(mockPatchBuilder);
131        when(mockPostBuilder.body(any(InputStream.class), any(String.class))).thenReturn(mockPostBuilder);
132        when(mockPostBuilder2.body(any(InputStream.class), any(String.class))).thenReturn(mockPostBuilder2);
133        when(mockPostBuilder3.body(any(InputStream.class), any(String.class))).thenReturn(mockPostBuilder3);
134        when(mockPutBuilder.body(any(InputStream.class), any(String.class))).thenReturn(mockPutBuilder);
135    }
136
137    public void init() throws IOException {
138        testProducer = new FcrepoProducer(testEndpoint);
139        TestUtils.setField(testProducer, "fcrepoClient", mockClient);
140    }
141
142    @Test
143    public void testGetProducer() throws Exception {
144        final URI uri = create(TestUtils.baseUrl);
145        final int status = 200;
146        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
147        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
148        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
149                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
150
151        init();
152
153        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
154
155        when(mockHeadBuilder.perform()).thenReturn(headResponse);
156        when(mockGetBuilder.perform()).thenReturn(getResponse);
157
158        testProducer.process(testExchange);
159
160        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
161        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
162        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
163    }
164
165    @Test
166    public void testGetAcceptHeaderProducer() throws Exception {
167        final URI uri = create(TestUtils.baseUrl);
168        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
169        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
170        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
171                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
172
173        init();
174
175        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
176        testExchange.getIn().setHeader("Accept", N_TRIPLES);
177
178        when(mockHeadBuilder.perform()).thenReturn(headResponse);
179        when(mockGetBuilder.perform()).thenReturn(getResponse);
180
181        testProducer.process(testExchange);
182
183        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
184        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
185    }
186
187    @Test
188    public void testGetPreferHeaderProducer() throws Exception {
189        final URI uri = create(TestUtils.baseUrl);
190        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
191        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
192        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
193                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)) , body);
194        final String prefer = "return=representation; omit=\"http://www.w3.org/ns/ldp#PreferContainment\";";
195
196        init();
197
198        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
199        testExchange.getIn().setHeader(FCREPO_PREFER, prefer);
200
201        when(mockHeadBuilder.perform()).thenReturn(headResponse);
202        when(mockGetBuilder.perform()).thenReturn(getResponse);
203
204        testProducer.process(testExchange);
205
206        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
207        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
208    }
209
210    @Test
211    public void testGetFixity() throws Exception {
212        final String baseUrl = "http://localhost:8080/rest";
213        final String path = "/binary";
214        final URI uri = create(baseUrl + path);
215        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.fixityTriples.getBytes());
216        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
217        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
218                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
219
220        testEndpoint.setFixity(true);
221
222        init();
223
224        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, path);
225
226        when(mockHeadBuilder.perform()).thenReturn(headResponse);
227        when(mockGetBuilder.perform()).thenReturn(getResponse);
228
229        testProducer.process(testExchange);
230
231        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.fixityTriples);
232        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
233    }
234
235    @Test
236    public void testGetPreferIncludeLongEndpointProducer() throws Exception {
237        final URI uri = create(TestUtils.baseUrl);
238        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
239        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
240        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
241                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
242        final String prefer = "return=representation; " +
243                    "include=\"http://fedora.info/definitions/v4/repository#ServerManaged\";";
244
245        testEndpoint.setPreferInclude("http://fedora.info/definitions/v4/repository#ServerManaged");
246
247        init();
248
249        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
250
251        when(mockHeadBuilder.perform()).thenReturn(headResponse);
252        when(mockGetBuilder.perform()).thenReturn(getResponse);
253
254        testProducer.process(testExchange);
255
256        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
257        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
258    }
259
260    @Test
261    public void testGetPreferIncludeShortEndpointProducer() throws Exception {
262        final URI uri = create(TestUtils.baseUrl);
263        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
264        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
265        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
266                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
267        final String prefer = "return=representation; include=\"http://www.w3.org/ns/ldp#PreferMembership\";";
268
269        testEndpoint.setPreferInclude("PreferMembership");
270
271        init();
272
273        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
274
275        when(mockHeadBuilder.perform()).thenReturn(headResponse);
276        when(mockGetBuilder.perform()).thenReturn(getResponse);
277
278        testProducer.process(testExchange);
279
280        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
281        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
282    }
283
284    @Test
285    public void testGetPreferOmitLongEndpointProducer() throws Exception {
286        final URI uri = create(TestUtils.baseUrl);
287        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
288        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
289        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
290                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
291        final String embed = "http://fedora.info/definitions/v4/repository#EmbedResources";
292
293        testEndpoint.setPreferOmit(embed);
294
295        init();
296
297        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
298
299        when(mockHeadBuilder.perform()).thenReturn(headResponse);
300        when(mockGetBuilder.perform()).thenReturn(getResponse);
301
302        testProducer.process(testExchange);
303
304        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
305        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
306    }
307
308    @Test
309    public void testGetPreferOmitShortEndpointProducer() throws Exception {
310        final URI uri = create(TestUtils.baseUrl);
311        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
312        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
313        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
314                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
315        final String prefer = "return=representation; omit=\"http://www.w3.org/ns/ldp#PreferContainment\";";
316
317        testEndpoint.setPreferOmit("PreferContainment");
318
319        init();
320
321        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
322
323        when(mockHeadBuilder.perform()).thenReturn(headResponse);
324        when(mockGetBuilder.perform()).thenReturn(getResponse);
325
326        testProducer.process(testExchange);
327
328        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
329        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
330    }
331
332    @Test
333    public void testGetAcceptEndpointProducer() throws Exception {
334        final URI uri = create(TestUtils.baseUrl);
335        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
336        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
337        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
338                singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body);
339
340        testEndpoint.setAccept(N_TRIPLES);
341
342        init();
343
344        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
345
346        when(mockHeadBuilder.perform()).thenReturn(headResponse);
347        when(mockGetBuilder.perform()).thenReturn(getResponse);
348
349        testProducer.process(testExchange);
350
351        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfTriples);
352        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
353    }
354
355    @Test
356    public void testGetRootProducer() throws Exception {
357        final URI uri = create("http://localhost:8080/rest");
358        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
359        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
360        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
361                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
362
363        init();
364
365        when(mockHeadBuilder.perform()).thenReturn(headResponse);
366        when(mockGetBuilder.perform()).thenReturn(getResponse);
367
368        testProducer.process(testExchange);
369
370        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
371        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
372    }
373
374    @Test
375    public void testGetBinaryProducer() throws Exception {
376        final URI uri = create(TestUtils.baseUrl);
377        final String content = "Foo";
378        final ByteArrayInputStream body = new ByteArrayInputStream(content.getBytes());
379        final FcrepoResponse getResponse = new FcrepoResponse(uri, 200,
380                singletonMap(CONTENT_TYPE, singletonList(TestUtils.TEXT_PLAIN)), body);
381
382        testEndpoint.setMetadata(false);
383
384        init();
385
386        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
387        testExchange.getIn().setHeader(ACCEPT_CONTENT_TYPE, TestUtils.TEXT_PLAIN);
388        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.GET);
389
390        when(mockGetBuilder.perform()).thenReturn(getResponse);
391
392        testProducer.process(testExchange);
393
394        assertEquals(testExchange.getIn().getBody(String.class), content);
395        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.TEXT_PLAIN);
396    }
397
398    @Test
399    public void testHeadProducer() throws Exception {
400        final URI uri = create(TestUtils.baseUrl);
401        final Map<String, List<String>> headers = new HashMap<>();
402        headers.put(CONTENT_TYPE, singletonList(N_TRIPLES));
403        headers.put("Link", singletonList("<" + TestUtils.baseUrl + "/bar>; rel=\"describedby\""));
404        final int status = 200;
405        final FcrepoResponse headResponse = new FcrepoResponse(uri, status, headers, null);
406
407        init();
408
409        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
410        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.HEAD);
411
412        when(mockHeadBuilder.perform()).thenReturn(headResponse);
413
414        testProducer.process(testExchange);
415
416        assertEquals(testExchange.getIn().getBody(), null);
417        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), N_TRIPLES);
418        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
419    }
420
421    @Test
422    public void testDeleteProducer() throws Exception {
423        final URI uri = create(TestUtils.baseUrl);
424        final int status = 204;
425        final FcrepoResponse deleteResponse = new FcrepoResponse(uri, status, emptyMap(), null);
426
427        init();
428
429        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
430        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.DELETE);
431
432        when(mockDeleteBuilder.perform()).thenReturn(deleteResponse);
433
434        testProducer.process(testExchange);
435
436        assertEquals(testExchange.getIn().getBody(), null);
437        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE), null);
438        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
439    }
440
441    @Test
442    public void testPostProducer() throws Exception {
443        final URI uri = create(TestUtils.baseUrl);
444        final String responseText = TestUtils.baseUrl + "/e8/0b/ab/e80bab60";
445        final int status = 201;
446        final FcrepoResponse postResponse = new FcrepoResponse(uri, status,
447                singletonMap(CONTENT_TYPE, singletonList(TestUtils.TEXT_PLAIN)),
448                new ByteArrayInputStream(responseText.getBytes()));
449
450        init();
451
452        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
453        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.POST);
454
455        when(mockPostBuilder.perform()).thenReturn(postResponse);
456
457        testProducer.process(testExchange);
458
459        assertEquals(testExchange.getIn().getBody(String.class), responseText);
460        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE), TestUtils.TEXT_PLAIN);
461        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
462    }
463
464    @Test
465    public void testPostContentTypeEndpointProducer() throws Exception {
466        final URI uri = create(TestUtils.baseUrl);
467        final int status = 204;
468        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
469        final FcrepoResponse postResponse = new FcrepoResponse(uri, status, emptyMap(), null);
470
471        testEndpoint.setContentType(TestUtils.SPARQL_UPDATE);
472
473        init();
474
475        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
476        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.POST);
477        testExchange.getIn().setBody(new ByteArrayInputStream(TestUtils.sparqlUpdate.getBytes()));
478
479        when(mockHeadBuilder.perform()).thenReturn(headResponse);
480        when(mockPostBuilder.perform()).thenReturn(postResponse);
481
482        testProducer.process(testExchange);
483
484        assertEquals(testExchange.getIn().getBody(), null);
485        assertEquals(testExchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE), status);
486    }
487
488    @Test
489    public void testPatchProducer() throws Exception {
490        final URI uri = create(TestUtils.baseUrl);
491        final String metadata = "<" + TestUtils.baseUrl + "/bar>; rel=\"describedby\"";
492        final int status = 204;
493        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200,
494                singletonMap("Link", singletonList(metadata)), null);
495        final FcrepoResponse patchResponse = new FcrepoResponse(uri, status, emptyMap(), null);
496
497        init();
498
499        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
500        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.PATCH);
501        testExchange.getIn().setBody(new ByteArrayInputStream(TestUtils.sparqlUpdate.getBytes()));
502
503        when(mockHeadBuilder.perform()).thenReturn(headResponse);
504        when(mockPatchBuilder.perform()).thenReturn(patchResponse);
505
506        testProducer.process(testExchange);
507
508        assertEquals(testExchange.getIn().getBody(), null);
509        assertEquals(testExchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE), status);
510    }
511
512    @Test
513    public void testPutProducer() throws Exception {
514        final URI uri = create(TestUtils.baseUrl);
515        final int status = 201;
516        final FcrepoResponse putResponse = new FcrepoResponse(uri, status,
517                singletonMap(CONTENT_TYPE, singletonList(TestUtils.TEXT_PLAIN)),
518                new ByteArrayInputStream(TestUtils.baseUrl.getBytes()));
519
520        init();
521
522        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
523        testExchange.getIn().setHeader(HTTP_METHOD, HttpMethods.PUT);
524        testExchange.getIn().setBody(null);
525
526        when(mockPutBuilder.perform()).thenReturn(putResponse);
527
528        testProducer.process(testExchange);
529
530        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.baseUrl);
531        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
532        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE), TestUtils.TEXT_PLAIN);
533    }
534
535    @Test
536    public void testPreferProperties() throws Exception {
537        testProducer = new FcrepoProducer(testEndpoint);
538
539        assertEquals(6, PREFER_PROPERTIES.size());
540        final String[] fcrepoPrefer = new String[] { "ServerManaged", "EmbedResources", "InboundReferences" };
541        for (final String s : fcrepoPrefer) {
542            assertEquals(REPOSITORY + s, PREFER_PROPERTIES.get(s));
543        }
544
545        final String[] ldpPrefer = new String[] { "PreferContainment", "PreferMembership",
546            "PreferMinimalContainer" };
547        for (final String s : ldpPrefer) {
548            assertEquals(LDP + s, PREFER_PROPERTIES.get(s));
549        }
550    }
551
552    @Test
553    public void testGetProducerWithScheme() throws Exception {
554        final URI uri = create(TestUtils.baseUrl);
555        final int status = 200;
556        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
557        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
558        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
559                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
560
561        // set the baseUrl with an explicit http:// scheme
562        testEndpoint.setBaseUrl("http://localhost:8080/rest");
563        init();
564
565        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
566
567        when(mockHeadBuilder.perform()).thenReturn(headResponse);
568        when(mockGetBuilder.perform()).thenReturn(getResponse);
569
570        testProducer.process(testExchange);
571
572        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
573        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
574        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
575    }
576
577    @Test
578    public void testGetSecureProducer() throws Exception {
579        final URI uri = create(TestUtils.baseUrlSecure);
580        final int status = 200;
581        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
582        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
583        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
584                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
585
586        // set the baseUrl with no scheme but with a secure port
587        testEndpoint.setBaseUrl("localhost:443/rest");
588        init();
589
590        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/secure");
591
592        when(mockHeadBuilder.perform()).thenReturn(headResponse);
593        when(mockGetBuilder.perform()).thenReturn(getResponse);
594
595        testProducer.process(testExchange);
596
597        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
598        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
599        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
600    }
601
602    @Test
603    public void testGetSecureProducerWithScheme() throws Exception {
604        final URI uri = create(TestUtils.baseUrlSecureWithoutPort);
605        final int status = 200;
606        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
607        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
608        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
609                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
610
611        // set the baseUrl with explicit scheme but no port
612        testEndpoint.setBaseUrl("https://localhost/rest");
613        init();
614
615        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/secure");
616
617        when(mockHeadBuilder.perform()).thenReturn(headResponse);
618        when(mockGetBuilder.perform()).thenReturn(getResponse);
619
620        testProducer.process(testExchange);
621
622        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
623        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
624        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
625    }
626
627    @Test
628    public void testTransactedGetProducer() throws Exception {
629        final String baseUrl = "http://localhost:8080/rest";
630        final String path = "/transact";
631        final String path2 = "/transact2";
632        final String tx = "tx:12345";
633        final URI uri = create(baseUrl + "/" + tx + path);
634        final URI uri2 = create(baseUrl + "/" + tx + path2);
635        final URI commitUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.COMMIT);
636        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
637        final int status = 200;
638        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
639        final ByteArrayInputStream body2 = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
640        final DefaultUnitOfWork uow = new DefaultUnitOfWork(testExchange);
641        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
642        txMgr.setBaseUrl(baseUrl);
643
644        testEndpoint.setTransactionManager(txMgr);
645
646        when(mockClient2.post(eq(beginUri))).thenReturn(mockPostBuilder2);
647        when(mockClient2.post(eq(commitUri))).thenReturn(mockPostBuilder2);
648
649        init();
650        TestUtils.setField(txMgr, "fcrepoClient", mockClient2);
651
652        uow.beginTransactedBy((Object)tx);
653
654        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, path);
655        testExchange.setUnitOfWork(uow);
656
657        when(mockPostBuilder2.perform()).thenReturn(
658                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
659        when(mockPostBuilder3.perform()).thenReturn(
660                new FcrepoResponse(commitUri, 201, emptyMap(), null));
661
662        when(mockHeadBuilder.perform()).thenReturn(new FcrepoResponse(uri, 200, emptyMap(), null));
663        when(mockClient.get(eq(uri))).thenReturn(mockGetBuilder2);
664        when(mockClient.get(eq(uri2))).thenReturn(mockGetBuilder3);
665
666        when(mockGetBuilder2.perform()).thenReturn(
667            new FcrepoResponse(uri, status, singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body));
668        when(mockGetBuilder3.perform()).thenReturn(
669            new FcrepoResponse(uri2, status, singletonMap(CONTENT_TYPE, singletonList(N_TRIPLES)), body2));
670
671        testProducer.process(testExchange);
672
673        assertEquals(status, testExchange.getIn().getHeader(HTTP_RESPONSE_CODE));
674        assertEquals(TestUtils.RDF_XML, testExchange.getIn().getHeader(CONTENT_TYPE, String.class));
675        assertEquals(TestUtils.rdfXml, testExchange.getIn().getBody(String.class));
676
677        testExchange.getIn().setHeader(HTTP_METHOD, "GET");
678        testExchange.getIn().setHeader(ACCEPT_CONTENT_TYPE, N_TRIPLES);
679        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, path2);
680        testExchange.setUnitOfWork(uow);
681        testProducer.process(testExchange);
682        assertEquals(status, testExchange.getIn().getHeader(HTTP_RESPONSE_CODE));
683        assertEquals(N_TRIPLES, testExchange.getIn().getHeader(CONTENT_TYPE, String.class));
684        assertEquals(TestUtils.rdfTriples, testExchange.getIn().getBody(String.class));
685    }
686
687    @Test (expected = RuntimeException.class)
688    public void testTransactedProducerWithError() throws Exception {
689        final String baseUrl = "http://localhost:8080/rest";
690        final String path = "/transact";
691        final String path2 = "/transact2";
692        final String tx = "tx:12345";
693        final URI uri = create(baseUrl + "/" + tx + path);
694        final URI uri2 = create(baseUrl + "/" + tx + path2);
695        final URI commitUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.COMMIT);
696        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
697        final int status = 200;
698        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
699        final ByteArrayInputStream body2 = new ByteArrayInputStream(TestUtils.rdfTriples.getBytes());
700        final DefaultUnitOfWork uow = new DefaultUnitOfWork(testExchange);
701        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
702        txMgr.setBaseUrl(baseUrl);
703
704        testEndpoint.setTransactionManager(txMgr);
705
706        init();
707        TestUtils.setField(txMgr, "fcrepoClient", mockClient2);
708
709        uow.beginTransactedBy((Object)tx);
710
711        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, path);
712        testExchange.setUnitOfWork(uow);
713
714        when(mockClient2.post(eq(beginUri))).thenReturn(mockPostBuilder2);
715        when(mockClient2.post(eq(commitUri))).thenReturn(mockPostBuilder3);
716        when(mockPostBuilder2.perform()).thenReturn(
717                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
718        when(mockPostBuilder3.perform()).thenReturn(
719                new FcrepoResponse(commitUri, 201, emptyMap(), null));
720
721        when(mockHeadBuilder.perform()).thenReturn(new FcrepoResponse(uri, 200, emptyMap(), null));
722        when(mockClient.get(eq(uri))).thenReturn(mockGetBuilder2);
723        when(mockClient.get(eq(uri2))).thenReturn(mockGetBuilder3);
724        when(mockGetBuilder2.perform()).thenReturn(
725            new FcrepoResponse(uri, status, singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body));
726        when(mockGetBuilder3.perform()).thenThrow(
727            new FcrepoOperationFailedException(uri2, 400, "Bad Request"));
728
729        testProducer.process(testExchange);
730
731        assertEquals(status, testExchange.getIn().getHeader(HTTP_RESPONSE_CODE));
732        assertEquals(TestUtils.RDF_XML, testExchange.getIn().getHeader(CONTENT_TYPE, String.class));
733        assertEquals(TestUtils.rdfXml, testExchange.getIn().getBody(String.class));
734
735        testExchange.getIn().setHeader(HTTP_METHOD, "GET");
736        testExchange.getIn().setHeader(ACCEPT_CONTENT_TYPE, N_TRIPLES);
737        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, path2);
738        testExchange.setUnitOfWork(uow);
739        testProducer.process(testExchange);
740    }
741
742    @Test
743    public void testNoStreamCaching() throws Exception {
744        final URI uri = create(TestUtils.baseUrl);
745        final int status = 200;
746        final ByteArrayInputStream body = new ByteArrayInputStream(TestUtils.rdfXml.getBytes());
747        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
748        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
749                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
750
751        init();
752
753        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
754        testExchange.setProperty(DISABLE_HTTP_STREAM_CACHE, true);
755
756        when(mockHeadBuilder.perform()).thenReturn(headResponse);
757        when(mockGetBuilder.perform()).thenReturn(getResponse);
758
759        testProducer.process(testExchange);
760
761        assertEquals(testExchange.getIn().getBody(String.class), TestUtils.rdfXml);
762        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
763        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
764    }
765
766    @Test
767    public void testStreamCaching() throws Exception {
768        final URI uri = create(TestUtils.baseUrl);
769        final int status = 200;
770        final String rdfConcat = StringUtils.repeat(TestUtils.rdfXml, 10000);
771        final ByteArrayInputStream body = new ByteArrayInputStream(rdfConcat.getBytes());
772        final FcrepoResponse headResponse = new FcrepoResponse(uri, 200, emptyMap(), null);
773        final FcrepoResponse getResponse = new FcrepoResponse(uri, status,
774                singletonMap(CONTENT_TYPE, singletonList(TestUtils.RDF_XML)), body);
775
776        init();
777
778        testExchange.getIn().setHeader(FCREPO_IDENTIFIER, "/foo");
779        testExchange.setProperty(DISABLE_HTTP_STREAM_CACHE, false);
780
781        testExchange.getContext().getStreamCachingStrategy().setSpoolThreshold(1024);
782        testExchange.getContext().getStreamCachingStrategy().setBufferSize(256);
783        testExchange.getContext().setStreamCaching(true);
784
785        when(mockHeadBuilder.perform()).thenReturn(headResponse);
786        when(mockGetBuilder.perform()).thenReturn(getResponse);
787
788        testProducer.process(testExchange);
789
790        assertEquals(true, testExchange.getContext().isStreamCaching());
791        assertNotNull(testExchange.getIn().getBody(InputStreamCache.class));
792        assertEquals(rdfConcat.length(), testExchange.getIn().getBody(InputStreamCache.class).length());
793        assertEquals(rdfConcat.length(), testExchange.getIn().getBody(InputStreamCache.class).length());
794        assertEquals(testExchange.getIn().getHeader(CONTENT_TYPE, String.class), TestUtils.RDF_XML);
795        assertEquals(testExchange.getIn().getHeader(HTTP_RESPONSE_CODE), status);
796    }
797}