1 16 17 package org.apache.cocoon.components.source.impl; 18 19 import java.io.ByteArrayOutputStream ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.OutputStream ; 23 import java.io.StringReader ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.Date ; 28 import java.util.Enumeration ; 29 import java.util.List ; 30 31 import org.apache.avalon.framework.activity.Initializable; 32 import org.apache.avalon.framework.context.Context; 33 import org.apache.avalon.framework.context.ContextException; 34 import org.apache.avalon.framework.context.Contextualizable; 35 import org.apache.avalon.framework.logger.AbstractLogEnabled; 36 import org.apache.avalon.framework.logger.LogEnabled; 37 import org.apache.avalon.framework.logger.Logger; 38 import org.apache.avalon.framework.service.ServiceManager; 39 import org.apache.avalon.framework.service.Serviceable; 40 import org.apache.cocoon.CascadingIOException; 41 import org.apache.cocoon.Constants; 42 import org.apache.cocoon.components.source.InspectableSource; 43 import org.apache.cocoon.components.source.LockableSource; 44 import org.apache.cocoon.components.source.VersionableSource; 45 import org.apache.cocoon.components.source.helpers.SourceLock; 46 import org.apache.cocoon.components.source.helpers.SourceProperty; 47 import org.apache.excalibur.source.ModifiableTraversableSource; 48 import org.apache.excalibur.source.MoveableSource; 49 import org.apache.excalibur.source.Source; 50 import org.apache.excalibur.source.SourceException; 51 import org.apache.excalibur.source.SourceUtil; 52 import org.apache.excalibur.source.SourceValidity; 53 import org.apache.excalibur.source.impl.validity.TimeStampValidity; 54 import org.apache.excalibur.xml.dom.DOMParser; 55 import org.apache.slide.authenticate.CredentialsToken; 56 import org.apache.slide.common.NamespaceAccessToken; 57 import org.apache.slide.common.SlideException; 58 import org.apache.slide.common.SlideToken; 59 import org.apache.slide.common.SlideTokenImpl; 60 import org.apache.slide.content.Content; 61 import org.apache.slide.content.NodeProperty; 62 import org.apache.slide.content.NodeRevisionContent; 63 import org.apache.slide.content.NodeRevisionDescriptor; 64 import org.apache.slide.content.NodeRevisionDescriptors; 65 import org.apache.slide.content.NodeRevisionNumber; 66 import org.apache.slide.content.RevisionDescriptorNotFoundException; 67 import org.apache.slide.lock.Lock; 68 import org.apache.slide.lock.NodeLock; 69 import org.apache.slide.macro.Macro; 70 import org.apache.slide.security.AccessDeniedException; 71 import org.apache.slide.structure.ObjectNode; 72 import org.apache.slide.structure.ObjectNotFoundException; 73 import org.apache.slide.structure.Structure; 74 import org.apache.slide.structure.SubjectNode; 75 import org.w3c.dom.Document ; 76 import org.xml.sax.InputSource ; 77 78 83 public class SlideSource extends AbstractLogEnabled 84 implements Contextualizable, Serviceable, Initializable, Source, ModifiableTraversableSource, 85 MoveableSource, LockableSource, InspectableSource, 86 VersionableSource { 87 88 89 private Context m_context; 90 private ServiceManager m_manager; 91 92 93 private NamespaceAccessToken m_nat; 94 private SlideToken m_slideToken; 95 96 97 private Structure m_structure; 98 private Content m_content; 99 private Lock m_lock; 100 private Macro m_macro; 101 102 103 private String m_scheme; 104 private String m_path; 105 private String m_scope; 106 private String m_uri; 107 108 private ObjectNode m_node; 109 private NodeRevisionNumber m_version; 110 private NodeRevisionDescriptors m_descriptors; 111 private NodeRevisionDescriptor m_descriptor; 112 113 private String m_principal; 114 private SourceValidity m_validity; 115 116 private SlideSourceOutputStream m_outputStream; 117 118 125 public SlideSource(NamespaceAccessToken nat, 126 String scheme, 127 String scope, 128 String path, 129 String principal, 130 String version) { 131 132 m_nat = nat; 133 m_scheme = scheme; 134 m_scope = scope; 135 m_path = path; 136 if (path.equals("/")) { 137 m_uri = scope; 138 } 139 else if (scope.equals("/")){ 140 m_uri = path; 141 } 142 else { 143 m_uri = scope + path; 144 } 145 m_principal = principal; 146 if (version != null) { 147 m_version = new NodeRevisionNumber(version); 148 } 149 } 150 151 158 public void contextualize(Context context) { 159 this.m_context = context; 160 } 161 162 168 public void service(ServiceManager manager) { 169 m_manager = manager; 170 } 171 172 public void initialize() throws SourceException { 173 174 CredentialsToken credentials = new CredentialsToken(m_principal); 175 m_slideToken = new SlideTokenImpl(credentials); 176 177 m_structure = m_nat.getStructureHelper(); 178 m_content = m_nat.getContentHelper(); 179 m_lock = m_nat.getLockHelper(); 180 m_macro = m_nat.getMacroHelper(); 181 182 try { 183 if (m_node == null) { 184 m_node = m_structure.retrieve(m_slideToken,m_uri); 185 } 186 187 m_descriptors = m_content.retrieve(m_slideToken,m_uri); 188 if (m_version != null) { 189 m_descriptor = m_content.retrieve(m_slideToken,m_descriptors,m_version); 191 } 192 else { 193 m_descriptor = m_content.retrieve(m_slideToken,m_descriptors); 195 m_version = m_descriptor.getRevisionNumber(); 196 } 197 } 198 catch (ObjectNotFoundException e) { 199 if (getLogger().isDebugEnabled()) { 200 getLogger().debug("Not found.",e); 201 } 202 } 204 catch (RevisionDescriptorNotFoundException e) { 205 if (getLogger().isDebugEnabled()) { 206 getLogger().debug("Could not retrieve descriptor.",e); 207 } 208 } 210 catch (AccessDeniedException e) { 211 throw new SourceException("Access denied.",e); 212 } 213 catch (SlideException e) { 214 throw new SourceException("Failure during source initialization.",e); 215 } 216 } 217 218 229 public InputStream getInputStream() throws IOException , SourceException { 230 try { 231 return m_content.retrieve(m_slideToken,m_descriptors,m_descriptor).streamContent(); 232 } catch (SlideException se) { 233 throw new SourceException("Could not get source", se); 234 } 235 } 236 237 242 public String getURI() { 243 return m_scheme + "://" + m_principal + "@" + m_nat.getName() + m_path; 244 } 245 246 251 public String getScheme() { 252 return m_scheme; 253 } 254 255 263 public SourceValidity getValidity() { 264 if (m_validity == null && m_descriptor != null) { 265 final long lastModified = getLastModified(); 266 if (lastModified > 0) { 267 m_validity = new TimeStampValidity(lastModified); 268 } 269 } 270 return m_validity; 271 } 272 273 277 public void refresh() { 278 m_validity = null; 279 } 280 281 288 public String getMimeType() { 289 if (m_descriptor != null) { 290 return m_descriptor.getContentType(); 291 } 292 return null; 293 } 294 295 300 public boolean exists() { 301 return m_node != null; 302 } 303 304 310 public long getContentLength() { 311 if (m_descriptor != null) { 312 return m_descriptor.getContentLength(); 313 } 314 return -1; 315 } 316 317 323 public long getLastModified() { 324 if (m_descriptor != null) { 325 return m_descriptor.getLastModifiedAsDate().getTime(); 326 } 327 return 0; 328 } 329 330 332 342 public OutputStream getOutputStream() 343 throws IOException , SourceException { 344 if (m_outputStream == null) { 345 m_outputStream = new SlideSourceOutputStream(); 346 m_outputStream.enableLogging(getLogger()); 347 } 348 return m_outputStream; 349 } 350 351 358 public boolean canCancel(OutputStream stream) { 359 return m_outputStream.canCancel(); 360 } 361 362 372 public void cancel(OutputStream stream) throws SourceException { 373 if (m_outputStream == stream) { 374 try { 375 m_outputStream.cancel(); 376 } catch (Exception e) { 377 throw new SourceException("Could not cancel output stream",e); 378 } 379 } 380 } 381 382 385 public void delete() { 386 try { 387 m_nat.begin(); 388 m_macro.delete(m_slideToken,m_uri); 389 m_nat.commit(); 390 } catch (Exception se) { 391 getLogger().error("Could not delete source.",se); 392 try { 393 m_nat.rollback(); 394 } catch (Exception rbe) { 395 getLogger().error("Rollback failed for moving source",rbe); 396 } 397 } 398 } 399 400 public void makeCollection() throws SourceException { 401 SubjectNode collection = new SubjectNode(); 402 NodeRevisionDescriptor descriptor = new NodeRevisionDescriptor(0); 403 404 descriptor.setResourceType("<collection/>"); 405 descriptor.setCreationDate(new Date ()); 406 descriptor.setLastModified(new Date ()); 407 descriptor.setContentLength(0); 408 descriptor.setSource(""); 409 descriptor.setOwner(m_slideToken.getCredentialsToken().getPublicCredentials()); 410 411 try { 412 m_nat.begin(); 413 m_structure.create(m_slideToken,collection,m_uri); 414 m_content.create(m_slideToken,m_uri,descriptor,null); 415 m_nat.commit(); 416 } catch (Exception se) { 417 try { 418 m_nat.rollback(); 419 } catch (Exception rbe) { 420 getLogger().error("Rollback failed for creating collection", rbe); 421 } 422 throw new SourceException("Could not create collection.", se); 423 } 424 } 425 426 public Source getChild(String name) throws SourceException { 427 return getChildByPath(m_path+"/"+name); 428 } 429 430 private Source getChildByPath(String path) throws SourceException { 431 SlideSource child = new SlideSource(m_nat,m_scheme,m_scope,path,m_principal,null); 432 child.enableLogging(getLogger()); 433 child.contextualize(m_context); 434 child.service(m_manager); 435 child.initialize(); 436 return child; 437 } 438 439 public Collection getChildren() throws SourceException { 440 if (m_node == null || !m_node.hasChildren()) { 441 return Collections.EMPTY_LIST; 442 } 443 List result = new ArrayList (); 444 final Enumeration children = m_node.enumerateChildren(); 445 while (children.hasMoreElements()) { 446 String child = (String ) children.nextElement(); 447 child = child.substring(m_scope.length()); 448 result.add(getChildByPath(child)); 449 } 450 return result; 451 } 452 453 public String getName() { 454 int index = m_path.lastIndexOf('/'); 455 if (index != -1) { 456 return m_path.substring(index+1); 457 } 458 return m_path; 459 } 460 461 public Source getParent() throws SourceException { 462 if (m_path.length() == 1) { 463 return null; 465 } 466 int index = m_path.lastIndexOf('/'); 467 if (index == -1) { 468 return null; 469 } 470 String parentPath; 471 if (index == 0) { 472 parentPath = "/"; 473 } 474 else if (index == m_path.length()-1) { 475 parentPath = m_path.substring(0,m_path.substring(0, m_path.length()-1).lastIndexOf('/')); 477 } 478 else { 479 parentPath = m_path.substring(0,index); 480 } 481 SlideSource parent = new SlideSource(m_nat,m_scheme,m_scope,parentPath,m_principal,null); 482 parent.enableLogging(getLogger()); 483 parent.contextualize(m_context); 484 parent.service(m_manager); 485 parent.initialize(); 486 return parent; 487 488 } 489 490 public boolean isCollection() { 491 if (m_node == null) { 492 return false; 493 } 494 if (m_descriptor == null) { 495 return true; 497 } 498 NodeProperty property = m_descriptor.getProperty("resourcetype"); 499 if (property != null && ((String ) property.getValue()).startsWith("<collection/>")) { 500 return true; 501 } 502 return false; 503 } 504 505 508 class SlideSourceOutputStream extends ByteArrayOutputStream implements LogEnabled { 509 private boolean isClosed = false; 510 private Logger logger = null; 511 512 517 public void enableLogging(Logger logger) { 518 this.logger = logger; 519 } 520 521 526 public void close() throws IOException { 527 super.close(); 528 529 byte[] bytes = new byte[0]; 531 try { 532 NodeRevisionContent content = new NodeRevisionContent(); 533 bytes = toByteArray(); 534 content.setContent(bytes); 535 536 if (m_descriptor == null) { 537 m_descriptor = new NodeRevisionDescriptor(0); 538 m_descriptor.setName(getName()); 539 } 540 541 m_descriptor.setContentLength(bytes.length); 542 m_descriptor.setLastModified(new Date ()); 543 544 m_nat.begin(); 545 if (m_version == null) { 546 m_content.create(m_slideToken,m_uri,m_descriptor,null); 547 } 548 m_content.store(m_slideToken,m_uri,m_descriptor,content); 549 try { 550 m_nat.commit(); 551 } catch (Exception cme) { 552 throw new CascadingIOException("Could not commit the transaction",cme); 553 } 554 555 } catch (ObjectNotFoundException e) { 556 557 SubjectNode subject = new SubjectNode(); 559 560 try { 561 m_structure.create(m_slideToken,subject,m_uri); 563 } catch (SlideException se) { 564 throw new CascadingIOException(se); 565 } 566 567 NodeRevisionDescriptor descriptor = new NodeRevisionDescriptor(bytes.length); 568 descriptor.setResourceType(""); 569 descriptor.setSource(""); 570 descriptor.setContentLanguage("en"); 571 descriptor.setContentLength(bytes.length); 572 String contentType = null; 573 574 try { 575 contentType = ((org.apache.cocoon.environment.Context) 576 m_context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT)).getMimeType(m_path); 577 } catch (ContextException ce) { 578 this.logger.warn("Could not get context to determine the mime type."); 579 } 580 if (contentType == null) { 581 contentType = "application/octet-stream"; 582 } 583 descriptor.setContentType(contentType); 584 descriptor.setLastModified(new Date ()); 585 descriptor.setOwner(m_slideToken.getCredentialsToken().getPublicCredentials()); 586 NodeRevisionContent content = new NodeRevisionContent(); 587 588 content.setContent(bytes); 589 try { 590 m_content.create(m_slideToken,m_uri,descriptor,content); 591 try { 592 m_nat.commit(); 593 } catch (Exception cme) { 594 throw new CascadingIOException("Could not commit the transaction",cme); 595 596 } 597 } catch (SlideException se) { 598 try { 599 m_nat.rollback(); 600 } catch (Exception rbe) { 601 this.logger.warn("Could not rollback the transaction.",rbe); 602 } 603 throw new CascadingIOException("Could not create source",se); 604 } 605 606 } catch (Exception e) { 607 if (e instanceof IOException ) { 608 throw (IOException ) e; 609 } 610 throw new CascadingIOException("Could not create source", e); 611 } finally { 612 this.isClosed = true; 613 } 614 } 615 616 622 boolean canCancel() { 623 return !this.isClosed; 624 } 625 626 633 void cancel() throws Exception { 634 if (this.isClosed) { 635 throw new IllegalStateException ("Cannot cancel : outputstrem is already closed"); 636 } 637 this.isClosed = true; 638 super.close(); 639 } 640 } 641 642 644 651 public void moveTo(Source source) throws SourceException { 652 if (source instanceof SlideSource) { 653 try { 654 m_nat.begin(); 655 String destination = m_scope+((SlideSource) source).m_path; 656 m_macro.move(m_slideToken,m_uri,destination); 657 m_nat.commit(); 658 } catch (Exception se) { 659 try { 660 m_nat.rollback(); 661 } catch (Exception rbe) { 662 getLogger().error("Rollback failed for moving source", rbe); 663 } 664 throw new SourceException("Could not move source.", se); 665 } 666 } else { 667 SourceUtil.move(this,source); 668 } 669 } 670 671 678 public void copyTo(Source source) throws SourceException { 679 if (source instanceof SlideSource) { 680 try { 681 m_nat.begin(); 682 String destination = m_scope+((SlideSource) source).m_path; 683 m_macro.copy(m_slideToken,m_uri,destination); 684 m_nat.commit(); 685 } catch (Exception se) { 686 try { 687 m_nat.rollback(); 688 } catch (Exception rbe) { 689 690 getLogger().error("Rollback failed for moving source",rbe); 691 } 692 throw new SourceException("Could not move source.",se); 693 } 694 } else { 695 SourceUtil.copy(this,source); 696 } 697 } 698 699 701 711 public SourceProperty getSourceProperty(String namespace, String name) 712 throws SourceException { 713 714 if (m_descriptor == null) { 715 return null; 716 } 717 718 final String quote = "\""; 719 NodeProperty property = m_descriptor.getProperty(name, namespace); 720 721 if (property == null) { 722 return null; 723 } 724 725 String pre = "<"+name+" xmlns="+quote+namespace+quote+" >"; 726 String post = "</"+name+" >"; 727 728 StringReader reader = new StringReader (pre+property.getValue().toString()+post); 729 InputSource src = new InputSource (reader); 730 731 DOMParser parser = null; 732 Document doc = null; 733 734 try { 735 parser = (DOMParser) this.m_manager.lookup(DOMParser.ROLE); 736 doc = parser.parseDocument(src); 737 } catch (Exception e) { 738 throw new SourceException("Could not parse property", e); 739 } finally { 740 this.m_manager.release(parser); 741 } 742 743 return new SourceProperty(doc.getDocumentElement()); 744 } 745 746 753 public void setSourceProperty(SourceProperty property) 754 throws SourceException { 755 try { 756 m_descriptor.setProperty(property.getName(), 757 property.getNamespace(), 758 property.getValueAsString()); 759 m_descriptor.setLastModified(new Date ()); 760 761 m_nat.begin(); 762 m_content.store(m_slideToken,m_uri,m_descriptor,null); 763 m_nat.commit(); 764 } catch (Exception se) { 765 try { 766 m_nat.rollback(); 767 } catch (Exception rbe) { 768 getLogger().error("Rollback failed for setting a source property", rbe); 769 } 770 throw new SourceException("Could not set source property", se); 771 } 772 } 773 774 781 public SourceProperty[] getSourceProperties() throws SourceException { 782 783 if (m_descriptor == null) { 784 return new SourceProperty[0]; 785 } 786 787 List properties = new ArrayList (); 788 DOMParser parser = null; 789 String xml = ""; 790 791 try { 792 parser = (DOMParser) m_manager.lookup(DOMParser.ROLE); 793 final String quote = "\""; 794 Enumeration e = m_descriptor.enumerateProperties(); 795 while (e.hasMoreElements()) { 796 NodeProperty property = (NodeProperty) e.nextElement(); 797 String name = property.getName(); 798 String namespace = property.getNamespace(); 799 String pre = "<"+name+" xmlns="+quote+namespace+quote+" >"; 800 String post = "</"+name+" >"; 801 xml = pre+property.getValue().toString()+post; 802 803 StringReader reader = new StringReader (xml); 804 Document doc = parser.parseDocument(new InputSource (reader)); 805 properties.add(new SourceProperty(doc.getDocumentElement())); 806 } 807 } catch (Exception e) { 808 throw new SourceException("Could not parse property "+xml, e); 809 } finally { 810 m_manager.release(parser); 811 } 812 813 return (SourceProperty[]) properties.toArray(new SourceProperty[properties.size()]); 814 } 815 816 824 public void removeSourceProperty(String namespace, String name) throws SourceException { 825 try { 826 if (m_descriptor != null && !namespace.equals("DAV:")) { 827 m_descriptor.removeProperty(name, namespace); 828 m_descriptor.setLastModified(new Date ()); 829 m_nat.begin(); 830 m_content.store(m_slideToken,m_uri,m_descriptor,null); 831 m_nat.commit(); 832 } 833 } catch (Exception se) { 834 try { 835 m_nat.rollback(); 836 } catch (Exception rbe) { 837 getLogger().error("Rollback failed for removing a source property", rbe); 838 } 839 throw new SourceException("Could not remove property", se); 840 } 841 } 842 843 845 852 public void addSourceLocks(SourceLock sourcelock) throws SourceException { 853 throw new SourceException("Operation not yet supported"); 854 } 855 856 863 public SourceLock[] getSourceLocks() throws SourceException { 864 try { 865 List result = new ArrayList (); 866 867 NodeLock lock; 868 Enumeration locks = m_lock.enumerateLocks(m_slideToken,m_uri, false); 869 while (locks.hasMoreElements()) { 870 lock = (NodeLock) locks.nextElement(); 871 result.add(new SourceLock(lock.getSubjectUri(), 872 lock.getTypeUri(), 873 lock.getExpirationDate(), 874 lock.isInheritable(), 875 lock.isExclusive())); 876 } 877 878 return (SourceLock[]) result.toArray(new SourceLock[result.size()]); 879 } catch (SlideException se) { 880 throw new SourceException("Could not retrieve locks", se); 881 } 882 } 883 884 886 893 public boolean isVersioned() throws SourceException { 894 if (m_descriptors != null) { 895 return m_descriptors.hasRevisions(); 896 } 897 return false; 898 } 899 900 906 public String getSourceRevision() { 907 if (m_version != null) { 908 return m_version.toString(); 909 } 910 return null; 911 } 912 913 920 public void setSourceRevision(String revision) throws SourceException { 921 throw new SourceException("method not implemented"); 924 } 925 926 933 public String getSourceRevisionBranch() throws SourceException { 934 if (m_descriptor != null) { 935 return m_descriptor.getBranchName(); 936 } 937 return null; 938 } 939 940 947 public void setSourceRevisionBranch(String branch) throws SourceException { 948 throw new SourceException("method not implemented"); 951 } 952 953 960 public String getLatestSourceRevision() throws SourceException { 961 if (m_descriptors != null) { 962 return m_descriptors.getLatestRevision().toString(); 963 } 964 return null; 965 } 966 967 } 968 969 | Popular Tags |