1 17 package org.alfresco.repo.content; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.io.OutputStream ; 22 23 import javax.transaction.RollbackException ; 24 import javax.transaction.UserTransaction ; 25 26 import org.alfresco.model.ContentModel; 27 import org.alfresco.repo.content.filestore.FileContentWriter; 28 import org.alfresco.repo.policy.JavaBehaviour; 29 import org.alfresco.repo.policy.PolicyComponent; 30 import org.alfresco.repo.security.authentication.AuthenticationComponent; 31 import org.alfresco.service.ServiceRegistry; 32 import org.alfresco.service.cmr.repository.ChildAssociationRef; 33 import org.alfresco.service.cmr.repository.ContentData; 34 import org.alfresco.service.cmr.repository.ContentIOException; 35 import org.alfresco.service.cmr.repository.ContentReader; 36 import org.alfresco.service.cmr.repository.ContentService; 37 import org.alfresco.service.cmr.repository.ContentWriter; 38 import org.alfresco.service.cmr.repository.NoTransformerException; 39 import org.alfresco.service.cmr.repository.NodeRef; 40 import org.alfresco.service.cmr.repository.NodeService; 41 import org.alfresco.service.cmr.repository.StoreRef; 42 import org.alfresco.service.namespace.NamespaceService; 43 import org.alfresco.service.namespace.QName; 44 import org.alfresco.service.transaction.TransactionService; 45 import org.alfresco.util.BaseSpringTest; 46 import org.alfresco.util.GUID; 47 import org.alfresco.util.PropertyMap; 48 import org.alfresco.util.TempFileProvider; 49 50 55 public class RoutingContentServiceTest extends BaseSpringTest 56 { 57 private static final String SOME_CONTENT = "ABC"; 58 59 private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/RoutingContentServiceTest"; 60 61 private ContentService contentService; 62 private PolicyComponent policyComponent; 63 private NodeService nodeService; 64 private NodeRef rootNodeRef; 65 private NodeRef contentNodeRef; 66 private AuthenticationComponent authenticationComponent; 67 68 public RoutingContentServiceTest() 69 { 70 } 71 72 @Override 73 public void onSetUpInTransaction() throws Exception 74 { 75 super.onSetUpInTransaction(); 76 nodeService = (NodeService) applicationContext.getBean("dbNodeService"); 77 contentService = (ContentService) applicationContext.getBean(ServiceRegistry.CONTENT_SERVICE.getLocalName()); 78 this.policyComponent = (PolicyComponent)this.applicationContext.getBean("policyComponent"); 79 this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent"); 80 81 this.authenticationComponent.setSystemUserAsCurrentUser(); 82 StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, getName()); 84 if (!nodeService.exists(storeRef)) 85 { 86 storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier()); 87 } 88 rootNodeRef = nodeService.getRootNode(storeRef); 89 ContentData contentData = new ContentData(null, "text/plain", 0L, "UTF-16"); 91 92 PropertyMap properties = new PropertyMap(); 93 properties.put(ContentModel.PROP_CONTENT, contentData); 94 95 ChildAssociationRef assocRef = nodeService.createNode( 96 rootNodeRef, 97 ContentModel.ASSOC_CHILDREN, 98 QName.createQName(TEST_NAMESPACE, GUID.generate()), 99 ContentModel.TYPE_CONTENT, 100 properties); 101 contentNodeRef = assocRef.getChildRef(); 102 } 103 104 @Override 105 protected void onTearDownInTransaction() throws Exception 106 { 107 try 108 { 109 authenticationComponent.clearCurrentSecurityContext(); 110 } 111 catch (Throwable e) 112 { 113 } 115 super.onTearDownInTransaction(); 116 } 117 118 private UserTransaction getUserTransaction() 119 { 120 TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionComponent"); 121 return (UserTransaction ) transactionService.getUserTransaction(); 122 } 123 124 public void testSetUp() throws Exception 125 { 126 assertNotNull(contentService); 127 assertNotNull(nodeService); 128 assertNotNull(rootNodeRef); 129 assertNotNull(contentNodeRef); 130 assertNotNull(getUserTransaction()); 131 assertFalse(getUserTransaction() == getUserTransaction()); } 133 134 138 public void testAutoSettingOfProperties() throws Exception 139 { 140 ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 142 assertNotNull("Writer should not be null", writer); 143 assertNotNull("Content URL should not be null", writer.getContentUrl()); 144 assertNotNull("Content mimetype should not be null", writer.getMimetype()); 145 assertNotNull("Content encoding should not be null", writer.getEncoding()); 146 147 writer.putContent(SOME_CONTENT); 149 150 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 152 assertNotNull("Reader should not be null", reader); 153 assertNotNull("Content URL should not be null", reader.getContentUrl()); 154 assertNotNull("Content mimetype should not be null", reader.getMimetype()); 155 assertNotNull("Content encoding should not be null", reader.getEncoding()); 156 157 long length = SOME_CONTENT.getBytes(reader.getEncoding()).length; long checkLength = reader.getSize(); 161 assertEquals("Content length incorrect", length, checkLength); 162 163 String contentCheck = reader.getContentString(); 165 assertEquals("Content incorrect", SOME_CONTENT, contentCheck); 166 } 167 168 public void testWriteToNodeWithoutAnyContentProperties() throws Exception 169 { 170 ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 173 assertNotNull(writer.getMimetype()); 174 assertNotNull(writer.getEncoding()); 175 176 nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, null); 178 179 writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 180 assertNull(writer.getMimetype()); 181 assertEquals("UTF-8", writer.getEncoding()); 182 183 writer.setMimetype("text/plain"); 185 writer.setEncoding("UTF-8"); 186 187 String content = "The quick brown fox ..."; 188 writer.putContent(content); 189 190 ContentData contentData = (ContentData) nodeService.getProperty(contentNodeRef, ContentModel.PROP_CONTENT); 192 assertEquals("metadata didn't get onto node", writer.getContentData(), contentData); 193 194 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 196 assertEquals("Metadata didn't get set on reader", writer.getContentData(), reader.getContentData()); 197 } 198 199 public void testNullReaderForNullUrl() throws Exception 200 { 201 ContentData contentData = new ContentData(null, null, 0L, null); 203 nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, contentData); 204 205 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 207 assertNull("Reader must be null if the content URL is null", reader); 208 } 209 210 213 public void testMissingContent() throws Exception 214 { 215 File tempFile = TempFileProvider.createTempFile(getName(), ".txt"); 216 217 ContentWriter writer = new FileContentWriter(tempFile); 218 writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); 219 writer.setEncoding("UTF-8"); 220 writer.putContent("What about the others? Buckwheats!"); 221 assertTrue("File does not exist", tempFile.exists()); 223 assertTrue("File not written to", tempFile.length() > 0); 224 225 ContentData contentData = writer.getContentData(); 227 nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, contentData); 228 229 tempFile.delete(); 231 assertFalse("File not deleted", tempFile.exists()); 232 233 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 235 assertFalse("Reader should indicate that content is missing", reader.exists()); 236 237 setComplete(); 239 endTransaction(); 240 } 241 242 245 public void testSimpleWrite() throws Exception 246 { 247 ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, false); assertNotNull("Writer should not be null", writer); 250 251 writer.putContent(SOME_CONTENT); 253 254 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 256 assertNull("No reader should yet be available for the node", reader); 257 } 258 259 private boolean policyFired = false; 260 private boolean readPolicyFired = false; 261 private boolean newContent = true; 262 263 266 public void testOnContentUpdatePolicy() 267 { 268 this.policyComponent.bindClassBehaviour( 270 QName.createQName(NamespaceService.ALFRESCO_URI, "onContentUpdate"), 271 ContentModel.ASPECT_VERSIONABLE, 272 new JavaBehaviour(this, "onContentUpdateBehaviourTest")); 273 274 ContentWriter contentWriter = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 276 contentWriter.putContent("content update one"); 277 assertFalse(this.policyFired); 278 279 this.newContent = false; 280 281 this.nodeService.addAspect(this.contentNodeRef, ContentModel.ASPECT_VERSIONABLE, null); 283 ContentWriter contentWriter2 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 284 contentWriter2.putContent("content update two"); 285 assertTrue(this.policyFired); 286 this.policyFired = false; 287 288 ContentWriter contentWriter3 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, false); 290 contentWriter3.putContent("content update three"); 291 assertFalse(this.policyFired); 292 } 293 294 public void onContentUpdateBehaviourTest(NodeRef nodeRef, boolean newContent) 295 { 296 assertEquals(this.contentNodeRef, nodeRef); 297 assertEquals(this.newContent, newContent); 298 assertTrue(this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)); 299 this.policyFired = true; 300 } 301 302 public void testOnContentReadPolicy() 303 { 304 this.policyComponent.bindClassBehaviour( 306 QName.createQName(NamespaceService.ALFRESCO_URI, "onContentRead"), 307 ContentModel.ASPECT_VERSIONABLE, 308 new JavaBehaviour(this, "onContentReadBehaviourTest")); 309 310 this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 312 assertFalse(this.readPolicyFired); 313 314 ContentWriter contentWriter2 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 316 contentWriter2.putContent("content update two"); 317 this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 318 assertFalse(this.readPolicyFired); 319 320 this.nodeService.addAspect(this.contentNodeRef, ContentModel.ASPECT_VERSIONABLE, null); 322 this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 323 assertTrue(this.readPolicyFired); 324 } 325 326 public void onContentReadBehaviourTest(NodeRef nodeRef) 327 { 328 this.readPolicyFired = true; 329 } 330 331 public void testTempWrite() throws Exception 332 { 333 ContentWriter writer1 = contentService.getTempWriter(); 335 ContentWriter writer2 = contentService.getTempWriter(); 337 338 assertNotSame("Temp URLs must be different", 340 writer1.getContentUrl(), writer2.getContentUrl()); 341 } 342 343 346 public void testUpdatingWrite() throws Exception 347 { 348 ContentData contentData = (ContentData) nodeService.getProperty( 350 contentNodeRef, 351 ContentModel.PROP_CONTENT); 352 assertNull("Content URL should be null", contentData.getContentUrl()); 353 354 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 356 assertNull("No reader should be available for new node", reader); 357 358 ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 360 assertNotNull("No writer received", writer); 361 writer.putContent(SOME_CONTENT); 363 364 try 366 { 367 writer.putContent("DEF"); 368 fail("Failed to prevent repeated use of the content writer"); 369 } 370 catch (ContentIOException e) 371 { 372 } 374 375 reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 377 assertNotNull("No reader available for node", reader); 378 String contentCheck = reader.getContentString(); 379 assertEquals("Content fetched doesn't match that written", SOME_CONTENT, contentCheck); 380 381 contentData = (ContentData) nodeService.getProperty( 383 contentNodeRef, 384 ContentModel.PROP_CONTENT); 385 assertNotNull("Content data not set", contentData); 386 assertEquals("Mismatched URL between writer and node", 387 writer.getContentUrl(), contentData.getContentUrl()); 388 389 assertEquals("Reader content length and node content length different", 391 reader.getSize(), contentData.getSize()); 392 393 assertEquals("Mimetype not set on content data", "text/plain", contentData.getMimetype()); 395 assertEquals("Encoding not set", "UTF-16", contentData.getEncoding()); 397 } 398 399 404 public void testConcurrentWritesNoTxn() throws Exception 405 { 406 setComplete(); 408 endTransaction(); 409 410 ContentWriter writer1 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 411 ContentWriter writer2 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 412 ContentWriter writer3 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 413 414 writer1.putContent("writer1 wrote this"); 415 writer2.putContent("writer2 wrote this"); 416 writer3.putContent("writer3 wrote this"); 417 418 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 420 String contentCheck = reader.getContentString(); 421 assertEquals("Content check failed", "writer3 wrote this", contentCheck); 422 } 423 424 public void testConcurrentWritesWithSingleTxn() throws Exception 425 { 426 setComplete(); 428 endTransaction(); 429 430 UserTransaction txn = getUserTransaction(); 431 txn.begin(); 432 txn.setRollbackOnly(); 433 434 ContentWriter writer1 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 435 ContentWriter writer2 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 436 ContentWriter writer3 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 437 438 writer1.putContent("writer1 wrote this"); 439 writer2.putContent("writer2 wrote this"); 440 writer3.putContent("writer3 wrote this"); 441 442 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 444 String contentCheck = reader.getContentString(); 445 assertEquals("Content check failed", "writer3 wrote this", contentCheck); 446 447 try 448 { 449 txn.commit(); 450 fail("Transaction has been marked for rollback"); 451 } 452 catch (RollbackException e) 453 { 454 } 456 457 txn.rollback(); 459 460 txn = getUserTransaction(); 462 txn.begin(); 463 txn.setRollbackOnly(); 464 465 reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 466 assertNull("Transaction was rolled back - no content should be visible", reader); 467 468 txn.rollback(); 469 } 470 471 public synchronized void testConcurrentWritesWithMultipleTxns() throws Exception 472 { 473 setComplete(); 475 endTransaction(); 476 477 UserTransaction txn = getUserTransaction(); 478 txn.begin(); 479 480 ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 482 assertNull("Reader should not be available", reader); 483 484 ContentWriter threadWriter = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 485 String threadContent = "Thread content"; 486 WriteThread thread = new WriteThread(threadWriter, threadContent); 487 thread.start(); 489 while (!thread.isWaiting()) 491 { 492 wait(10); 493 } 494 495 ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); 497 writer.putContent(SOME_CONTENT); 498 499 synchronized(threadWriter) 501 { 502 threadWriter.notifyAll(); 503 } 504 while (!thread.isDone()) 506 { 507 wait(10); 508 } 509 510 reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 512 assertNotNull("Reader should now be available", reader); 513 String checkContent = reader.getContentString(); 514 assertEquals("Content check failed", SOME_CONTENT, checkContent); 515 516 txn.rollback(); 518 519 reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT); 521 assertNotNull("Reader should now be available", reader); 522 checkContent = reader.getContentString(); 523 assertEquals("Content check failed", threadContent, checkContent); 524 } 525 526 public void testTransformation() throws Exception 527 { 528 setComplete(); 530 endTransaction(); 531 532 UserTransaction txn = getUserTransaction(); 533 txn.begin(); 534 txn.setRollbackOnly(); 535 536 ContentWriter writer = contentService.getTempWriter(); 538 writer.setMimetype("text/xml"); 539 String content = "<blah></blah>"; 541 writer.putContent(content); 542 ContentReader reader = writer.getReader(); 544 545 writer = contentService.getTempWriter(); 547 writer.setMimetype("audio/x-wav"); try 549 { 550 contentService.transform(reader, writer); 551 fail("Transformation attempted with invalid mimetype"); 552 } 553 catch (NoTransformerException e) 554 { 555 } 557 558 txn.rollback(); 560 561 txn = getUserTransaction(); 562 txn.begin(); 563 txn.setRollbackOnly(); 564 565 writer.setMimetype("text/plain"); 566 contentService.transform(reader, writer); 567 reader = writer.getReader(); 569 assertEquals("Mimetype of target reader incorrect", 570 writer.getMimetype(), reader.getMimetype()); 571 String contentCheck = reader.getContentString(); 572 assertEquals("Content check failed", content, contentCheck); 573 574 txn.rollback(); 575 } 576 577 585 private class WriteThread extends Thread 586 { 587 private ContentWriter writer; 588 private String content; 589 private boolean isWaiting; 590 private boolean isDone; 591 592 public WriteThread(ContentWriter writer, String content) 593 { 594 this.writer = writer; 595 this.content = content; 596 isWaiting = false; 597 isDone = false; 598 } 599 600 public boolean isWaiting() 601 { 602 return isWaiting; 603 } 604 605 public boolean isDone() 606 { 607 return isDone; 608 } 609 610 public void run() 611 { 612 authenticationComponent.setSystemUserAsCurrentUser(); 613 614 isWaiting = false; 615 isDone = false; 616 UserTransaction txn = getUserTransaction(); 617 OutputStream os = writer.getContentOutputStream(); 618 try 619 { 620 txn.begin(); if (writer.getEncoding() == null) 623 { 624 os.write(content.getBytes()); 625 } 626 else 627 { 628 os.write(content.getBytes(writer.getEncoding())); 629 } 630 synchronized (writer) 631 { 632 isWaiting = true; 633 writer.wait(); } 635 os.close(); 636 os = null; 637 txn.commit(); 638 } 639 catch (Throwable e) 640 { 641 try {txn.rollback(); } catch (Exception ee) {} 642 e.printStackTrace(); 643 throw new RuntimeException ("Failed writing to output stream for writer: " + writer, e); 644 } 645 finally 646 { 647 if (os != null) 648 { 649 try { os.close(); } catch (IOException e) {} 650 } 651 isDone = true; 652 } 653 } 654 } 655 } 656 | Popular Tags |