1 17 package org.alfresco.repo.content; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.ByteArrayOutputStream ; 21 import java.io.File ; 22 import java.io.FileInputStream ; 23 import java.io.FileOutputStream ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.nio.ByteBuffer ; 27 import java.nio.channels.FileChannel ; 28 import java.nio.channels.ReadableByteChannel ; 29 import java.util.Date ; 30 import java.util.Set ; 31 32 import javax.transaction.UserTransaction ; 33 34 import junit.framework.TestCase; 35 36 import org.alfresco.repo.transaction.DummyTransactionService; 37 import org.alfresco.service.cmr.repository.ContentIOException; 38 import org.alfresco.service.cmr.repository.ContentReader; 39 import org.alfresco.service.cmr.repository.ContentStreamListener; 40 import org.alfresco.service.cmr.repository.ContentWriter; 41 import org.alfresco.service.transaction.TransactionService; 42 import org.alfresco.util.ApplicationContextHelper; 43 import org.springframework.context.ApplicationContext; 44 45 54 public abstract class AbstractContentReadWriteTest extends TestCase 55 { 56 private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); 57 58 protected TransactionService transactionService; 59 private String contentUrl; 60 private UserTransaction txn; 61 62 public AbstractContentReadWriteTest() 63 { 64 super(); 65 } 66 67 @Override 68 public void setUp() throws Exception 69 { 70 contentUrl = AbstractContentStore.createNewUrl(); 71 transactionService = (TransactionService) ctx.getBean("TransactionService"); 72 txn = transactionService.getUserTransaction(); 73 txn.begin(); 74 } 75 76 public void tearDown() throws Exception 77 { 78 txn.rollback(); 79 } 80 81 90 protected abstract ContentStore getStore(); 91 92 95 protected final ContentWriter getWriter() 96 { 97 return getStore().getWriter(null, contentUrl); 98 } 99 100 103 protected final ContentReader getReader() 104 { 105 return getStore().getReader(contentUrl); 106 } 107 108 public void testSetUp() throws Exception 109 { 110 assertNotNull("setUp() not executed: no content URL present"); 111 112 ContentStore store = getStore(); 114 assertNotNull("No store provided", store); 115 assertTrue("The same instance of the store must be returned for getStore", store == getStore()); 116 } 117 118 public void testContentUrl() throws Exception 119 { 120 ContentReader reader = getReader(); 121 ContentWriter writer = getWriter(); 122 123 String readerContentUrl = reader.getContentUrl(); 126 String writerContentUrl = writer.getContentUrl(); 127 assertNotNull("Reader url is invalid", readerContentUrl); 128 assertNotNull("Writer url is invalid", writerContentUrl); 129 assertEquals("Reader and writer must reference same content", 130 readerContentUrl, 131 writerContentUrl); 132 133 assertTrue("Content URL doesn't start with correct prefix", 135 readerContentUrl.startsWith(ContentStore.STORE_PROTOCOL)); 136 } 137 138 public void testMimetypeAndEncoding() throws Exception 139 { 140 ContentWriter writer = getWriter(); 141 writer.setMimetype("text/plain"); 143 writer.setEncoding("UTF-16"); 144 145 String content = "A little bit o' this and a little bit o' that"; 147 byte[] bytesUtf16 = content.getBytes("UTF-16"); 148 OutputStream os = writer.getContentOutputStream(); 150 os.write(bytesUtf16); 151 os.close(); 152 153 ContentReader reader = writer.getReader(); 155 assertEquals("Writer -> Reader content URL mismatch", writer.getContentUrl(), reader.getContentUrl()); 156 assertEquals("Writer -> Reader mimetype mismatch", writer.getMimetype(), reader.getMimetype()); 157 assertEquals("Writer -> Reader encoding mismatch", writer.getEncoding(), reader.getEncoding()); 158 159 String contentCheck = reader.getContentString(); assertEquals("Encoding and decoding of strings failed", content, contentCheck); 162 } 163 164 public void testExists() throws Exception 165 { 166 ContentStore store = getStore(); 167 168 String contentUrl = AbstractContentStore.createNewUrl(); 170 171 assertFalse("Store exists fails with new URL", store.exists(contentUrl)); 173 174 ContentReader reader = store.getReader(contentUrl); 176 assertNotNull("Reader must be present, even for missing content", reader); 177 assertFalse("Reader exists failure", reader.exists()); 178 179 ContentWriter writer = store.getWriter(null, contentUrl); 181 writer.putContent("ABC"); 182 183 assertTrue("Store exists should show URL to be present", store.exists(contentUrl)); 184 } 185 186 public void testGetReader() throws Exception 187 { 188 ContentWriter writer = getWriter(); 189 190 ContentReader nullReader = writer.getReader(); 192 assertNull("No reader expected", nullReader); 193 194 String content = "ABC"; 195 writer.setMimetype("text/plain"); 198 writer.setEncoding("UTF-8"); 199 writer.putContent(content); 200 202 ContentReader readerFromWriter = writer.getReader(); 204 assertEquals("URL incorrect", writer.getContentUrl(), readerFromWriter.getContentUrl()); 205 assertEquals("Mimetype incorrect", writer.getMimetype(), readerFromWriter.getMimetype()); 206 assertEquals("Encoding incorrect", writer.getEncoding(), readerFromWriter.getEncoding()); 207 208 ContentReader readerFromReader = readerFromWriter.getReader(); 210 assertEquals("URL incorrect", writer.getContentUrl(), readerFromReader.getContentUrl()); 211 assertEquals("Mimetype incorrect", writer.getMimetype(), readerFromReader.getMimetype()); 212 assertEquals("Encoding incorrect", writer.getEncoding(), readerFromReader.getEncoding()); 213 214 String contentCheck = readerFromWriter.getContentString(); 216 assertEquals("Content is incorrect", content, contentCheck); 217 218 int length = content.getBytes(writer.getEncoding()).length; 220 assertEquals("Reader content length is incorrect", length, readerFromWriter.getSize()); 221 222 } 230 231 public void testClosedState() throws Exception 232 { 233 ContentReader reader = getReader(); 234 ContentWriter writer = getWriter(); 235 236 assertFalse("Reader stream should not be closed", reader.isClosed()); 238 assertFalse("Writer stream should not be closed", writer.isClosed()); 239 240 ContentReader writerGivenReader = writer.getReader(); 242 assertNull("No reader should be available before a write has finished", writerGivenReader); 243 244 writer.putContent("ABC"); 246 assertTrue("Writer stream should be closed", writer.isClosed()); 248 249 writerGivenReader = writer.getReader(); 251 assertNotNull("No reader given by closed writer", writerGivenReader); 252 assertFalse("Readers should still be closed", reader.isClosed()); 253 assertFalse("Readers should still be closed", writerGivenReader.isClosed()); 254 255 ContentReader newReaderA = writer.getReader(); 257 ContentReader newReaderB = writer.getReader(); 258 assertFalse("Reader must always be a new instance", newReaderA == newReaderB); 259 260 assertEquals("Readers should refer to same URL", 262 reader.getContentUrl(), writerGivenReader.getContentUrl()); 263 264 String contentCheck = reader.getContentString(); 266 assertEquals("Incorrect content", "ABC", contentCheck); 267 contentCheck = writerGivenReader.getContentString(); 268 assertEquals("Incorrect content", "ABC", contentCheck); 269 270 assertTrue("Reader should be closed", reader.isClosed()); 272 assertTrue("Reader should be closed", writerGivenReader.isClosed()); 273 } 274 275 278 public void testConcurrentWriteDetection() throws Exception 279 { 280 String contentUrl = AbstractContentStore.createNewUrl(); 281 ContentStore store = getStore(); 282 283 ContentWriter firstWriter = store.getWriter(null, contentUrl); 284 try 285 { 286 ContentWriter secondWriter = store.getWriter(null, contentUrl); 287 fail("Store issued two writers for the same URL: " + store); 288 } 289 catch (ContentIOException e) 290 { 291 } 293 } 294 295 298 public void testWriteStreamListener() throws Exception 299 { 300 ContentWriter writer = getWriter(); 301 302 final boolean[] streamClosed = new boolean[] {false}; ContentStreamListener listener = new ContentStreamListener() 304 { 305 public void contentStreamClosed() throws ContentIOException 306 { 307 streamClosed[0] = true; 308 } 309 }; 310 writer.setTransactionService(new DummyTransactionService()); 311 writer.addListener(listener); 312 313 writer.putContent("ABC"); 315 316 assertTrue("Write stream listener was not called for the stream close", streamClosed[0]); 318 } 319 320 325 public void testWriteAndReadString() throws Exception 326 { 327 ContentReader reader = getReader(); 328 ContentWriter writer = getWriter(); 329 330 String content = "ABC"; 331 writer.putContent(content); 332 assertTrue("Stream close not detected", writer.isClosed()); 333 334 String check = reader.getContentString(); 335 assertTrue("Read and write may not share same resource", check.length() > 0); 336 assertEquals("Write and read didn't work", content, check); 337 } 338 339 public void testStringTruncation() throws Exception 340 { 341 String content = "1234567890"; 342 343 ContentWriter writer = getWriter(); 344 writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); 345 writer.setEncoding("UTF-8"); writer.putContent(content); 348 349 ContentReader reader = writer.getReader(); 351 String checkContent = reader.getContentString(5); 352 assertEquals("Truncated strings don't match", "12345", checkContent); 353 } 354 355 public void testReadAndWriteFile() throws Exception 356 { 357 ContentReader reader = getReader(); 358 ContentWriter writer = getWriter(); 359 360 File sourceFile = File.createTempFile(getName(), ".txt"); 361 sourceFile.deleteOnExit(); 362 String content = "ABC"; 364 FileOutputStream os = new FileOutputStream (sourceFile); 365 os.write(content.getBytes()); 366 os.flush(); 367 os.close(); 368 369 writer.putContent(sourceFile); 371 assertTrue("Stream close not detected", writer.isClosed()); 372 373 File sinkFile = File.createTempFile(getName(), ".txt"); 375 sinkFile.deleteOnExit(); 376 377 reader.getContent(sinkFile); 379 380 FileInputStream is = new FileInputStream (sinkFile); 382 byte[] buffer = new byte[100]; 383 int count = is.read(buffer); 384 assertEquals("No content read", 3, count); 385 is.close(); 386 String check = new String (buffer, 0, count); 387 388 assertEquals("Write out of and read into files failed", content, check); 389 } 390 391 public void testReadAndWriteStreamByPull() throws Exception 392 { 393 ContentReader reader = getReader(); 394 ContentWriter writer = getWriter(); 395 396 String content = "ABC"; 397 InputStream is = new ByteArrayInputStream (content.getBytes()); 399 writer.putContent(is); 400 assertTrue("Stream close not detected", writer.isClosed()); 401 402 ByteArrayOutputStream os = new ByteArrayOutputStream (100); 404 reader.getContent(os); 405 byte[] bytes = os.toByteArray(); 406 String check = new String (bytes); 407 408 assertEquals("Write out and read in using streams failed", content, check); 409 } 410 411 public void testReadAndWriteStreamByPush() throws Exception 412 { 413 ContentReader reader = getReader(); 414 ContentWriter writer = getWriter(); 415 416 String content = "ABC"; 417 OutputStream os = writer.getContentOutputStream(); 419 os.write(content.getBytes()); 420 assertFalse("Stream has not been closed", writer.isClosed()); 421 os.close(); 423 assertTrue("Stream close not detected", writer.isClosed()); 424 425 InputStream is = reader.getContentInputStream(); 427 byte[] buffer = new byte[100]; 428 int count = is.read(buffer); 429 assertEquals("No content read", 3, count); 430 is.close(); 431 String check = new String (buffer, 0, count); 432 433 assertEquals("Write out of and read into files failed", content, check); 434 } 435 436 441 public void testDelete() throws Exception 442 { 443 ContentStore store = getStore(); 444 ContentWriter writer = getWriter(); 445 446 String content = "ABC"; 447 String contentUrl = writer.getContentUrl(); 448 449 OutputStream os = writer.getContentOutputStream(); 451 os.write(content.getBytes()); 452 os.flush(); 454 os.close(); 456 457 ContentReader reader = store.getReader(contentUrl); 459 assertNotNull(reader); 460 461 ContentReader readerCheck = writer.getReader(); 462 assertNotNull(readerCheck); 463 assertEquals("Store and write provided readers onto different URLs", 464 writer.getContentUrl(), reader.getContentUrl()); 465 466 InputStream is = reader.getContentInputStream(); 468 469 boolean deleted = store.delete(contentUrl); 471 472 is.close(); 474 475 reader = store.getReader(contentUrl); 477 assertNotNull(reader); 478 479 if (deleted) 481 { 482 assertFalse("Content should not exist", reader.exists()); 483 return; 485 } 486 else 487 { 488 assertTrue("Content should exist", reader.exists()); 489 } 490 491 store.delete(contentUrl); 493 494 try 496 { 497 is = reader.getContentInputStream(); 498 fail("Reader failed to detect underlying content deletion"); 499 } 500 catch (ContentIOException e) 501 { 502 } 504 505 reader = store.getReader(contentUrl); 507 assertNotNull("Reader must be returned even when underlying content is missing", 508 reader); 509 assertFalse("Content should not exist", reader.exists()); 510 try 511 { 512 is = reader.getContentInputStream(); 513 fail("Reader opened stream onto missing content"); 514 } 515 catch (ContentIOException e) 516 { 517 } 519 } 520 521 526 public void testListUrls() throws Exception 527 { 528 ContentStore store = getStore(); 529 530 ContentWriter writer = getWriter(); 531 532 Set <String > contentUrls = store.getUrls(); 533 String contentUrl = writer.getContentUrl(); 534 assertTrue("Writer URL not listed by store", contentUrls.contains(contentUrl)); 535 536 Date yesterday = new Date (System.currentTimeMillis() - 3600L * 1000L * 24L); 537 538 writer.putContent("The quick brown fox..."); 540 541 contentUrls = store.getUrls(); 543 assertTrue("Writer URL not listed by store", contentUrls.contains(contentUrl)); 544 545 contentUrls = store.getUrls(null, yesterday); 547 assertFalse("URL was younger than required, but still shows up", contentUrls.contains(contentUrl)); 548 549 boolean deleted = store.delete(contentUrl); 551 if (deleted) 552 { 553 contentUrls = store.getUrls(); 554 assertFalse("Successfully deleted URL still shown by store", contentUrls.contains(contentUrl)); 555 } 556 } 557 558 563 public void testRandomAccessWrite() throws Exception 564 { 565 ContentWriter writer = getWriter(); 566 567 FileChannel fileChannel = writer.getFileChannel(true); 568 assertNotNull("No channel given", fileChannel); 569 570 try 572 { 573 writer.getWritableChannel(); 574 fail("Second channel access allowed"); 575 } 576 catch (RuntimeException e) 577 { 578 } 580 581 byte[] content = new byte[] {1, 2, 3}; 583 for (int i = content.length - 1; i >= 0; i--) 584 { 585 ByteBuffer buffer = ByteBuffer.wrap(content, i, 1); 586 fileChannel.write(buffer, i); 587 } 588 589 fileChannel.close(); 591 assertTrue("Writer not closed", writer.isClosed()); 592 593 ContentReader reader = writer.getReader(); 595 ReadableByteChannel channelReader = reader.getReadableChannel(); 596 ByteBuffer buffer = ByteBuffer.allocateDirect(3); 597 int count = channelReader.read(buffer); 598 assertEquals("Incorrect number of bytes read", 3, count); 599 for (int i = 0; i < content.length; i++) 600 { 601 assertEquals("Content doesn't match", content[i], buffer.get(i)); 602 } 603 604 ContentWriter writerTruncate = getStore().getWriter(writer.getReader(), AbstractContentStore.createNewUrl()); 606 assertEquals("Content size incorrect", 0, writerTruncate.getSize()); 607 FileChannel fcTruncate = writerTruncate.getFileChannel(true); 609 fcTruncate.close(); 610 assertEquals("Content not truncated", 0, writerTruncate.getSize()); 611 612 ContentWriter writerNoTruncate = getStore().getWriter(writer.getReader(), AbstractContentStore.createNewUrl()); 614 assertEquals("Content size incorrect", 0, writerNoTruncate.getSize()); 615 FileChannel fcNoTruncate = writerNoTruncate.getFileChannel(false); 617 fcNoTruncate.close(); 618 assertEquals("Content was truncated", writer.getSize(), writerNoTruncate.getSize()); 619 } 620 621 626 public void testRandomAccessRead() throws Exception 627 { 628 ContentWriter writer = getWriter(); 629 String content = "ABC"; 631 byte[] bytes = content.getBytes(); 632 writer.putContent(content); 633 ContentReader reader = writer.getReader(); 634 635 FileChannel fileChannel = reader.getFileChannel(); 636 assertNotNull("No channel given", fileChannel); 637 638 try 640 { 641 reader.getReadableChannel(); 642 fail("Second channel access allowed"); 643 } 644 catch (RuntimeException e) 645 { 646 } 648 649 ByteBuffer buffer = ByteBuffer.allocate(bytes.length); 651 int count = fileChannel.read(buffer); 652 assertEquals("Incorrect number of bytes read", bytes.length, count); 653 buffer.rewind(); 655 buffer.get(bytes); 656 String checkContent = new String (bytes); 657 assertEquals("Content read failure", content, checkContent); 658 fileChannel.close(); 659 } 660 } 661 | Popular Tags |