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.integration; 019 020import static javax.ws.rs.core.Response.Status.BAD_REQUEST; 021import static javax.ws.rs.core.Response.Status.CONFLICT; 022import static javax.ws.rs.core.Response.Status.CREATED; 023import static javax.ws.rs.core.Response.Status.GONE; 024import static javax.ws.rs.core.Response.Status.NOT_FOUND; 025import static javax.ws.rs.core.Response.Status.NOT_MODIFIED; 026import static javax.ws.rs.core.Response.Status.NO_CONTENT; 027import static javax.ws.rs.core.Response.Status.OK; 028import static javax.ws.rs.core.Response.Status.PARTIAL_CONTENT; 029import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; 030import static javax.ws.rs.core.Response.Status.TEMPORARY_REDIRECT; 031import static org.fcrepo.client.FedoraHeaderConstants.CONTENT_DISPOSITION_FILENAME; 032import static org.fcrepo.client.FedoraHeaderConstants.CONTENT_TYPE; 033import static org.fcrepo.client.FedoraHeaderConstants.DIGEST; 034import static org.fcrepo.client.FedoraHeaderConstants.ETAG; 035import static org.fcrepo.client.FedoraHeaderConstants.LAST_MODIFIED; 036import static org.fcrepo.client.FedoraHeaderConstants.STATE_TOKEN; 037import static org.fcrepo.client.FedoraTypes.LDP_DIRECT_CONTAINER; 038import static org.fcrepo.client.TestUtils.TEXT_TURTLE; 039import static org.fcrepo.client.TestUtils.sparqlUpdate; 040import static org.junit.Assert.assertEquals; 041import static org.junit.Assert.assertNotEquals; 042import static org.junit.Assert.assertNotNull; 043import static org.junit.Assert.assertNull; 044import static org.junit.Assert.assertTrue; 045 046import java.io.ByteArrayInputStream; 047import java.io.InputStream; 048import java.net.URI; 049import java.nio.file.Files; 050import java.nio.file.Path; 051import java.util.Calendar; 052import java.util.Date; 053import java.util.HashMap; 054import java.util.Map; 055 056import javax.ws.rs.core.EntityTag; 057 058import org.apache.commons.io.FileUtils; 059import org.apache.commons.io.IOUtils; 060import org.apache.http.client.utils.DateUtils; 061import org.fcrepo.client.ExternalContentHandling; 062import org.fcrepo.client.FcrepoClient; 063import org.fcrepo.client.FcrepoOperationFailedException; 064import org.fcrepo.client.FcrepoResponse; 065import org.fcrepo.client.HeaderHelpers; 066import org.jgroups.util.UUID; 067import org.junit.Before; 068import org.junit.Ignore; 069import org.junit.Test; 070import org.junit.runner.RunWith; 071import org.springframework.test.context.ContextConfiguration; 072import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 073 074/** 075 * @author bbpennel 076 */ 077@RunWith(SpringJUnit4ClassRunner.class) 078@ContextConfiguration("/spring-test/test-container.xml") 079public class FcrepoClientIT extends AbstractResourceIT { 080 081 protected URI url; 082 083 final private String UNMODIFIED_DATE = "Mon, 1 Jan 2001 00:00:00 GMT"; 084 085 public FcrepoClientIT() throws Exception { 086 super(); 087 088 client = FcrepoClient.client() 089 .credentials("fedoraAdmin", "password") 090 .authScope("localhost") 091 .build(); 092 } 093 094 @Before 095 public void before() { 096 url = URI.create(serverAddress + UUID.randomUUID().toString()); 097 } 098 099 @Test 100 public void testPost() throws Exception { 101 final FcrepoResponse response = client.post(new URI(serverAddress)) 102 .perform(); 103 104 assertEquals(CREATED.getStatusCode(), response.getStatusCode()); 105 } 106 107 @Test 108 public void testPostBinary() throws Exception { 109 final String slug = UUID.randomUUID().toString(); 110 final String filename = "hello.txt"; 111 final String mimetype = "text/plain"; 112 final String bodyContent = "Hello world"; 113 final FcrepoResponse response = client.post(new URI(serverAddress)) 114 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 115 .filename(filename) 116 .slug(slug) 117 .perform(); 118 119 final String content = IOUtils.toString(response.getBody(), "UTF-8"); 120 final int status = response.getStatusCode(); 121 122 assertEquals("Didn't get a CREATED response! Got content:\n" + content, 123 CREATED.getStatusCode(), status); 124 assertEquals("Location did not match slug", serverAddress + slug, response.getLocation().toString()); 125 126 assertNotNull("Didn't find linked description!", response.getLinkHeaders("describedby").get(0)); 127 128 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 129 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 130 assertEquals(filename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 131 132 assertEquals(mimetype, getResponse.getContentType()); 133 134 final String getContent = IOUtils.toString(getResponse.getBody(), "UTF-8"); 135 assertEquals(bodyContent, getContent); 136 } 137 138 @Test 139 public void testPostExternalContent() throws Exception { 140 final String filename = "hello.txt"; 141 final String mimetype = "text/plain"; 142 final String fileContent = "Hello post world"; 143 144 final Path contentPath = Files.createTempFile(null, ".txt"); 145 FileUtils.write(contentPath.toFile(), fileContent, "UTF-8"); 146 147 final FcrepoResponse response = client.post(new URI(serverAddress)) 148 .externalContent(contentPath.toUri(), mimetype, ExternalContentHandling.PROXY) 149 .filename(filename) 150 .perform(); 151 152 final String content = IOUtils.toString(response.getBody(), "UTF-8"); 153 final int status = response.getStatusCode(); 154 155 assertEquals("Didn't get a CREATED response! Got content:\n" + content, 156 CREATED.getStatusCode(), status); 157 158 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 159 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 160 assertEquals(filename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 161 162 assertEquals(mimetype, getResponse.getContentType()); 163 164 final String getContent = IOUtils.toString(getResponse.getBody(), "UTF-8"); 165 assertEquals(fileContent, getContent); 166 } 167 168 @Test 169 public void testPostDigestMismatch() throws Exception { 170 final String bodyContent = "Hello world"; 171 final String invalidDigest = "adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"; 172 173 final FcrepoResponse response = client.post(new URI(serverAddress)) 174 .body(new ByteArrayInputStream(bodyContent.getBytes()), "text/plain") 175 .digestSha1(invalidDigest) 176 .perform(); 177 178 assertEquals("Invalid checksum was not rejected", CONFLICT.getStatusCode(), response.getStatusCode()); 179 } 180 181 @Test 182 public void testPostDigestMultipleChecksums() throws Exception { 183 final String bodyContent = "Hello world"; 184 185 final FcrepoResponse response = client.post(new URI(serverAddress)) 186 .body(new ByteArrayInputStream(bodyContent.getBytes()), "text/plain") 187 .digestMd5("3e25960a79dbc69b674cd4ec67a72c62") 188 .digestSha1("7b502c3a1f48c8609ae212cdfb639dee39673f5e") 189 .digestSha256("64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c") 190 .perform(); 191 192 assertEquals("Checksums rejected", CREATED.getStatusCode(), response.getStatusCode()); 193 } 194 195 @Test 196 public void testPostDigestMultipleChecksumsOneMismatch() throws Exception { 197 final String bodyContent = "Hello world"; 198 199 final FcrepoResponse response = client.post(new URI(serverAddress)) 200 .body(new ByteArrayInputStream(bodyContent.getBytes()), "text/plain") 201 .digestMd5("3e25960a79dbc69b674cd4ec67a72c62") 202 .digestSha1("7b502c3a1f48c8609ae212cdfb639dee39673f5e") 203 // Incorrect sha256 204 .digestSha256("123488ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c") 205 .perform(); 206 207 assertEquals("Invalid checksum was not rejected", CONFLICT.getStatusCode(), response.getStatusCode()); 208 } 209 210 @Test 211 public void testPostBinaryNullFilename() throws Exception { 212 final String bodyContent = "Hello world"; 213 214 final FcrepoResponse response = client.post(new URI(serverAddress)) 215 .body(new ByteArrayInputStream(bodyContent.getBytes()), "text/plain") 216 .filename(null) 217 .perform(); 218 219 assertEquals("Empty filename rejected", CREATED.getStatusCode(), response.getStatusCode()); 220 } 221 222 @Test 223 public void testPostDirectContainer() throws Exception { 224 final FcrepoResponse response = client.post(new URI(serverAddress)) 225 .addInteractionModel(LDP_DIRECT_CONTAINER) 226 .perform(); 227 228 final int status = response.getStatusCode(); 229 230 assertEquals("Didn't get a CREATED response!", CREATED.getStatusCode(), status); 231 232 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 233 assertTrue("Did not have ldp:DirectContainer type", getResponse.hasType(LDP_DIRECT_CONTAINER)); 234 } 235 236 // FCREPO-3698 237 @Test 238 public void testPostBinaryFilenameSpecialCharacters() throws Exception { 239 final String slug = UUID.randomUUID().toString(); 240 final String filename = "hello world\nof_we\0ird:+\tchar/acters\u0001.tx\rt"; 241 final String expectedFilename = "hello world of_we ird:+\tchar/acters .tx t"; 242 final String mimetype = "text/plain"; 243 final String bodyContent = "Hello world"; 244 final FcrepoResponse response = client.post(new URI(serverAddress)) 245 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 246 .filename(filename) 247 .slug(slug) 248 .perform(); 249 250 final String content = IOUtils.toString(response.getBody(), "UTF-8"); 251 final int status = response.getStatusCode(); 252 253 assertEquals("Didn't get a CREATED response! Got content:\n" + content, 254 CREATED.getStatusCode(), status); 255 assertEquals("Location did not match slug", serverAddress + slug, response.getLocation().toString()); 256 257 assertNotNull("Didn't find linked description!", response.getLinkHeaders("describedby").get(0)); 258 259 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 260 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 261 assertEquals(expectedFilename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 262 263 assertEquals(mimetype, getResponse.getContentType()); 264 265 final String getContent = IOUtils.toString(getResponse.getBody(), "UTF-8"); 266 assertEquals(bodyContent, getContent); 267 } 268 269 @Test 270 public void testPutBinaryFilenameSpecialCharacters() throws Exception { 271 final String id = UUID.randomUUID().toString(); 272 final String filename = "hello world\nof_we\0ird:+\tchar/acters\u0001.tx\rt"; 273 final String expectedFilename = "hello world of_we ird:+\tchar/acters .tx t"; 274 final String mimetype = "text/plain"; 275 final String bodyContent = "Hello world"; 276 final FcrepoResponse response = client.put(new URI(serverAddress + id)) 277 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 278 .filename(filename) 279 .perform(); 280 281 final String content = IOUtils.toString(response.getBody(), "UTF-8"); 282 final int status = response.getStatusCode(); 283 284 assertEquals("Didn't get a CREATED response! Got content:\n" + content, 285 CREATED.getStatusCode(), status); 286 assertEquals("Location did not match slug", serverAddress + id, response.getLocation().toString()); 287 288 assertNotNull("Didn't find linked description!", response.getLinkHeaders("describedby").get(0)); 289 290 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 291 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 292 assertEquals(expectedFilename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 293 294 assertEquals(mimetype, getResponse.getContentType()); 295 296 final String getContent = IOUtils.toString(getResponse.getBody(), "UTF-8"); 297 assertEquals(bodyContent, getContent); 298 } 299 300 @Test 301 public void testPut() throws Exception { 302 final FcrepoResponse response = create(); 303 304 assertEquals(CREATED.getStatusCode(), response.getStatusCode()); 305 assertEquals(url, response.getLocation()); 306 } 307 308 @Test 309 public void testPutEtag() throws Exception { 310 // Create object 311 final FcrepoResponse response = create(); 312 313 // Get the etag of the nearly created object 314 final EntityTag etag = EntityTag.valueOf(response.getHeaderValue(ETAG)); 315 316 // Retrieve the body of the resource so we can modify it 317 String body = getTurtle(url); 318 body += "\n<> <http://purl.org/dc/elements/1.1/title> \"some-title\""; 319 320 // Check that etag is making it through and being rejected 321 final FcrepoResponse updateResp = client.put(url) 322 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 323 .ifMatch("\"bad-etag\"") 324 .perform(); 325 326 assertEquals(PRECONDITION_FAILED.getStatusCode(), updateResp.getStatusCode()); 327 328 // Verify that etag is retrieved and resubmitted correctly 329 final FcrepoResponse validResp = client.put(url) 330 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 331 .ifMatch("\"" + etag.getValue() + "\"") 332 .perform(); 333 assertEquals(NO_CONTENT.getStatusCode(), validResp.getStatusCode()); 334 } 335 336 @Test 337 public void testPutUnmodifiedSince() throws Exception { 338 // Create object 339 final FcrepoResponse response = create(); 340 341 // Retrieve the body of the resource so we can modify it 342 String body = getTurtle(url); 343 body += "\n<> <http://purl.org/dc/elements/1.1/title> \"some-title\""; 344 345 // Update the body the first time, which should succeed 346 final String originalModified = response.getHeaderValue(LAST_MODIFIED); 347 final FcrepoResponse matchResponse = client.put(url) 348 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 349 .ifUnmodifiedSince(originalModified) 350 .perform(); 351 352 assertEquals(NO_CONTENT.getStatusCode(), matchResponse.getStatusCode()); 353 354 // Update the triples a second time with old timestamp 355 final FcrepoResponse mismatchResponse = client.put(url) 356 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 357 .ifUnmodifiedSince(UNMODIFIED_DATE) 358 .perform(); 359 360 assertEquals(PRECONDITION_FAILED.getStatusCode(), mismatchResponse.getStatusCode()); 361 } 362 363 @Test 364 public void testPutLenient() throws Exception { 365 // Create object 366 create(); 367 final String body = "<> <http://purl.org/dc/elements/1.1/title> \"some-title\""; 368 369 // try to update without lenient header 370 final FcrepoResponse strictResponse = client.put(url) 371 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 372 .perform(); 373 assertEquals(CONFLICT.getStatusCode(), strictResponse.getStatusCode()); 374 375 // try again with lenient header 376 final FcrepoResponse lenientResponse = client.put(url) 377 .body(new ByteArrayInputStream(body.getBytes()), TEXT_TURTLE) 378 .preferLenient() 379 .perform(); 380 assertEquals(NO_CONTENT.getStatusCode(), lenientResponse.getStatusCode()); 381 } 382 383 @Test 384 public void testPutExternalContent() throws Exception { 385 final String filename = "put.txt"; 386 final String mimetype = "text/plain"; 387 final String fileContent = "Hello put world"; 388 389 final Path contentPath = Files.createTempFile(null, ".txt"); 390 FileUtils.write(contentPath.toFile(), fileContent, "UTF-8"); 391 392 final FcrepoResponse response = client.put(url) 393 .externalContent(contentPath.toUri(), mimetype, ExternalContentHandling.PROXY) 394 .filename(filename) 395 .perform(); 396 397 final String content = IOUtils.toString(response.getBody(), "UTF-8"); 398 final int status = response.getStatusCode(); 399 400 assertEquals("Didn't get a CREATED response! Got content:\n" + content, 401 CREATED.getStatusCode(), status); 402 403 final FcrepoResponse getResponse = client.get(response.getLocation()).perform(); 404 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 405 assertEquals(filename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 406 407 assertEquals(mimetype, getResponse.getContentType()); 408 409 final String getContent = IOUtils.toString(getResponse.getBody(), "UTF-8"); 410 assertEquals(fileContent, getContent); 411 } 412 413 @Test 414 public void testPutBinaryNullFilename() throws Exception { 415 final String bodyContent = "Hello world"; 416 417 final FcrepoResponse response = client.put(url) 418 .body(new ByteArrayInputStream(bodyContent.getBytes()), "text/plain") 419 .filename(null) 420 .perform(); 421 422 assertEquals("Empty filename rejected", CREATED.getStatusCode(), response.getStatusCode()); 423 } 424 425 @Test 426 public void testPatch() throws Exception { 427 // Create object 428 create(); 429 430 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 431 432 // Update triples with sparql update 433 final FcrepoResponse response = client.patch(url) 434 .body(body) 435 .perform(); 436 437 assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode()); 438 } 439 440 @Test 441 public void testPatchEtagUpdated() throws Exception { 442 // Create object 443 final FcrepoResponse createResp = create(); 444 final EntityTag createdEtag = EntityTag.valueOf(createResp.getHeaderValue(ETAG)); 445 446 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 447 448 // Update triples with sparql update 449 final FcrepoResponse response = client.patch(url) 450 .body(body) 451 .ifMatch("\"" + createdEtag.getValue() + "\"") 452 .perform(); 453 454 final EntityTag updateEtag = EntityTag.valueOf(response.getHeaderValue(ETAG)); 455 456 assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode()); 457 assertNotEquals("Etag did not change after patch", createdEtag, updateEtag); 458 } 459 460 @Test 461 public void testPatchNoBody() throws Exception { 462 create(); 463 464 final FcrepoResponse response = client.patch(url) 465 .perform(); 466 467 assertEquals(BAD_REQUEST.getStatusCode(), response.getStatusCode()); 468 } 469 470 @Test 471 public void testDelete() throws Exception { 472 create(); 473 474 final FcrepoResponse response = client.delete(url).perform(); 475 476 assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode()); 477 478 assertEquals(GONE.getStatusCode(), client.get(url).perform().getStatusCode()); 479 } 480 481 @Test 482 public void testGet() throws Exception { 483 create(); 484 final FcrepoResponse response = client.get(url).perform(); 485 486 assertEquals(OK.getStatusCode(), response.getStatusCode()); 487 } 488 489 @Test 490 public void testGetNotFound() throws Exception { 491 final FcrepoResponse response = client.get(url).perform(); 492 493 assertEquals(NOT_FOUND.getStatusCode(), response.getStatusCode()); 494 } 495 496 @Test 497 public void testGetUnmodified() throws Exception { 498 // Check that get returns a 304 if the item hasn't changed according to last-modified 499 final FcrepoResponse response = create(); 500 501 // Get tomorrows date to provide as the modified-since date 502 final String lastModified = response.getHeaderValue(LAST_MODIFIED); 503 final Date modDate = DateUtils.parseDate(lastModified); 504 final Calendar cal = Calendar.getInstance(); 505 cal.setTime(modDate); 506 cal.add(Calendar.DATE, 1); 507 508 final FcrepoResponse modResp = client.get(url) 509 .ifModifiedSince(DateUtils.formatDate(cal.getTime())) 510 .perform(); 511 512 assertEquals(NOT_MODIFIED.getStatusCode(), modResp.getStatusCode()); 513 assertNull("Response body should not be returned when unmodified", modResp.getBody()); 514 } 515 516 @Test 517 public void testGetModified() throws Exception { 518 // Check that get returns a 200 if the item has changed according to last-modified 519 final FcrepoResponse response = create(); 520 521 // Get yesterdays date to provide as the modified-since date 522 final String lastModified = response.getHeaderValue(LAST_MODIFIED); 523 final Date modDate = DateUtils.parseDate(lastModified); 524 final Calendar cal = Calendar.getInstance(); 525 cal.setTime(modDate); 526 cal.add(Calendar.DATE, -1); 527 528 final FcrepoResponse modResp = client.get(url) 529 .ifModifiedSince(DateUtils.formatDate(cal.getTime())) 530 .perform(); 531 532 assertEquals(OK.getStatusCode(), modResp.getStatusCode()); 533 assertNotNull("GET response body should be normal when modified", modResp.getBody()); 534 } 535 536 @Test 537 public void testGetAccept() throws Exception { 538 // Check that get returns a 304 if the item hasn't changed according to last-modified/etag 539 create(); 540 541 final FcrepoResponse response = client.get(url) 542 .accept("application/n-triples") 543 .perform(); 544 545 assertEquals("application/n-triples", response.getHeaderValue(CONTENT_TYPE)); 546 assertEquals(OK.getStatusCode(), response.getStatusCode()); 547 } 548 549 @Test 550 public void testGetPrefer() throws Exception { 551 // Check that get returns a 304 if the item hasn't changed according to last-modified/etag 552 create(); 553 554 final FcrepoResponse response = client.get(url) 555 .preferMinimal() 556 .perform(); 557 558 assertEquals(OK.getStatusCode(), response.getStatusCode()); 559 assertEquals("return=minimal", response.getHeaderValue("Preference-Applied")); 560 } 561 562 @Test 563 public void testGetRange() throws Exception { 564 // Creating a binary for retrieval 565 final String mimetype = "text/plain"; 566 final String bodyContent = "Hello world"; 567 final FcrepoResponse response = client.post(new URI(serverAddress)) 568 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 569 .perform(); 570 571 final URI url = response.getLocation(); 572 573 // Get the content of the object after the first 6 bytes 574 final FcrepoResponse rangeResp = client.get(url) 575 .range(6L, null) 576 .perform(); 577 578 final String content = IOUtils.toString(rangeResp.getBody(), "UTF-8"); 579 assertEquals("Body did not contain correct range of original content", "world", content); 580 assertEquals(PARTIAL_CONTENT.getStatusCode(), rangeResp.getStatusCode()); 581 } 582 583 @Test 584 public void testGetDisableRedirects() throws Exception { 585 final String filename = "example.html"; 586 final String mimetype = "text/plain"; 587 588 final URI externalURI = URI.create("http://example.com/"); 589 590 final FcrepoResponse response = client.post(new URI(serverAddress)) 591 .externalContent(externalURI, mimetype, ExternalContentHandling.REDIRECT) 592 .filename(filename) 593 .perform(); 594 595 final FcrepoResponse getResponse = client.get(response.getLocation()) 596 .disableRedirects() 597 .perform(); 598 assertEquals("Didn't get a REDIRECT response!", 599 TEMPORARY_REDIRECT.getStatusCode(), getResponse.getStatusCode()); 600 assertEquals(mimetype, getResponse.getContentType()); 601 602 final Map<String, String> contentDisp = getResponse.getContentDisposition(); 603 assertEquals(filename, contentDisp.get(CONTENT_DISPOSITION_FILENAME)); 604 605 assertEquals(externalURI, getResponse.getLocation()); 606 } 607 608 @Test 609 public void testGetWantDigest() throws Exception { 610 // Creating a binary for retrieval 611 final String mimetype = "text/plain"; 612 final String bodyContent = "Hello world"; 613 final FcrepoResponse response = client.post(new URI(serverAddress)) 614 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 615 .perform(); 616 617 final URI url = response.getLocation(); 618 619 // Request md5 digest with caching disabled 620 final FcrepoResponse getResp = client.get(url) 621 .wantDigest("md5") 622 .noCache() 623 .perform(); 624 assertEquals(OK.getStatusCode(), getResp.getStatusCode()); 625 626 final String digest = getResp.getHeaderValue(DIGEST); 627 assertTrue("Did not contain md5", digest.contains("md5=3e25960a79dbc69b674cd4ec67a72c62")); 628 } 629 630 @Test 631 public void testHead() throws Exception { 632 final FcrepoResponse response = create(); 633 final FcrepoResponse headResp = client.head(url).perform(); 634 635 assertEquals(OK.getStatusCode(), headResp.getStatusCode()); 636 assertEquals(response.getHeaderValue(ETAG), headResp.getHeaderValue(ETAG)); 637 assertNotNull(headResp.getHeaderValue("Allow")); 638 } 639 640 @Test 641 public void testHeadWantDigest() throws Exception { 642 // Creating a binary for retrieval 643 final String mimetype = "text/plain"; 644 final String bodyContent = "Hello world"; 645 final FcrepoResponse response = client.post(new URI(serverAddress)) 646 .body(new ByteArrayInputStream(bodyContent.getBytes()), mimetype) 647 .perform(); 648 649 final URI url = response.getLocation(); 650 651 final Map<String, Double> qualityMap = new HashMap<>(); 652 qualityMap.put("md5", 1.0); 653 qualityMap.put("sha", 1.0); 654 qualityMap.put("sha-256", 0.4); 655 656 final String wantDigest = HeaderHelpers.formatQualityValues(qualityMap); 657 // Request multiple digests 658 final FcrepoResponse getResp = client.head(url) 659 .wantDigest(wantDigest) 660 .perform(); 661 assertEquals(OK.getStatusCode(), getResp.getStatusCode()); 662 663 final String digest = getResp.getHeaderValue(DIGEST); 664 assertTrue("Did not contain md5", digest.contains("md5=3e25960a79dbc69b674cd4ec67a72c62")); 665 assertTrue("Did not contain sha1", digest.contains("sha=7b502c3a1f48c8609ae212cdfb639dee39673f5e")); 666 assertTrue("Did not contain sha256", digest 667 .contains("sha-256=64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c")); 668 } 669 670 @Test 671 public void testOptions() throws Exception { 672 create(); 673 final FcrepoResponse headResp = client.options(url).perform(); 674 675 assertEquals(OK.getStatusCode(), headResp.getStatusCode()); 676 assertNotNull(headResp.getHeaderValue("Allow")); 677 assertNotNull(headResp.getHeaderValue("Accept-Post")); 678 assertNotNull(headResp.getHeaderValue("Accept-Patch")); 679 } 680 681 @Test 682 public void testMove() throws Exception { 683 create(); 684 685 final URI destUrl = new URI(url.toString() + "_dest"); 686 final FcrepoResponse moveResp = client.move(url, destUrl).perform(); 687 assertEquals(CREATED.getStatusCode(), moveResp.getStatusCode()); 688 689 assertEquals("Object still at original url", 690 GONE.getStatusCode(), client.get(url).perform().getStatusCode()); 691 692 assertEquals("Object not at expected new url", 693 OK.getStatusCode(), client.get(destUrl).perform().getStatusCode()); 694 } 695 696 @Test 697 public void testCopy() throws Exception { 698 create(); 699 700 // Add something identifiable to the record 701 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 702 client.patch(url).body(body).perform(); 703 704 final URI destUrl = new URI(url.toString() + "_dest"); 705 final FcrepoResponse copyResp = client.copy(url, destUrl).perform(); 706 assertEquals(CREATED.getStatusCode(), copyResp.getStatusCode()); 707 708 final FcrepoResponse originalResp = client.get(url).perform(); 709 final String originalContent = IOUtils.toString(originalResp.getBody(), "UTF-8"); 710 assertTrue(originalContent.contains("Foo")); 711 712 final FcrepoResponse destResp = client.get(destUrl).perform(); 713 final String destContent = IOUtils.toString(destResp.getBody(), "UTF-8"); 714 assertTrue(destContent.contains("Foo")); 715 } 716 717 @Ignore("Pending state token implementation in fcrepo") 718 @Test 719 public void testStateTokens() throws Exception { 720 create(); 721 722 final FcrepoResponse getResp = client.get(url).perform(); 723 final String stateToken = getResp.getHeaderValue(STATE_TOKEN); 724 725 // Attempt to update triples with an incorrect state token 726 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 727 final FcrepoResponse badTokenResp = client.patch(url) 728 .body(body) 729 .ifStateToken("bad_state_token") 730 .perform(); 731 assertEquals(PRECONDITION_FAILED.getStatusCode(), badTokenResp.getStatusCode()); 732 733 // Update triples with the correct state token 734 body.reset(); 735 final FcrepoResponse goodTokenResp = client.patch(url) 736 .body(body) 737 .ifStateToken(stateToken) 738 .perform(); 739 assertEquals(NO_CONTENT.getStatusCode(), goodTokenResp.getStatusCode()); 740 } 741 742 private FcrepoResponse create() throws FcrepoOperationFailedException { 743 return client.put(url).perform(); 744 } 745 746 private String getTurtle(final URI url) throws Exception { 747 final FcrepoResponse getResponse = client.get(url) 748 .accept("text/turtle") 749 .perform(); 750 return IOUtils.toString(getResponse.getBody(), "UTF-8"); 751 } 752}