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