1 17 18 19 20 package org.apache.lenya.cms.publication; 21 22 import java.io.File ; 23 import java.util.ArrayList ; 24 import java.util.Arrays ; 25 import java.util.HashMap ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.apache.avalon.framework.configuration.Configuration; 30 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 31 import org.apache.lenya.cms.publishing.PublishingEnvironment; 32 import org.apache.log4j.Category; 33 34 37 public abstract class AbstractPublication implements Publication { 38 private static Category log = Category.getInstance(AbstractPublication.class); 39 40 private static final String [] areas = { AUTHORING_AREA, STAGING_AREA, LIVE_AREA, ADMIN_AREA, 41 ARCHIVE_AREA, TRASH_AREA, INFO_AREA_PREFIX + AUTHORING_AREA, 42 INFO_AREA_PREFIX + STAGING_AREA, INFO_AREA_PREFIX + LIVE_AREA, 43 INFO_AREA_PREFIX + ARCHIVE_AREA, INFO_AREA_PREFIX + TRASH_AREA }; 44 45 private String id; 46 private PublishingEnvironment environment; 47 private File servletContext; 48 private DocumentIdToPathMapper mapper = null; 49 private ArrayList languages = new ArrayList (); 50 private String defaultLanguage = null; 51 private String breadcrumbprefix = null; 52 private String sslprefix = null; 53 private String livemountpoint = null; 54 private HashMap siteTrees = new HashMap (); 55 private String [] rewriteAttributeXPaths = { }; 56 private boolean hasSitetree = true; 57 58 private static final String ELEMENT_PROXY = "proxy"; 59 private static final String ATTRIBUTE_AREA = "area"; 60 private static final String ATTRIBUTE_URL = "url"; 61 private static final String ATTRIBUTE_SSL = "ssl"; 62 private static final String ELEMENT_REWRITE_ATTRIBUTE = "link-attribute"; 63 private static final String ATTRIBUTE_XPATH = "xpath"; 64 65 73 protected AbstractPublication(String id, String servletContextPath) throws PublicationException { 74 assert id != null; 75 this.id = id; 76 77 assert servletContextPath != null; 78 79 File servletContext = new File (servletContextPath); 80 assert servletContext.exists(); 81 this.servletContext = servletContext; 82 83 environment = new PublishingEnvironment(servletContextPath, id); 85 86 File configFile = new File (getDirectory(), CONFIGURATION_FILE); 87 DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); 88 89 Configuration config; 90 91 String pathMapperClassName = null; 92 String documentBuilderClassName = null; 93 94 try { 95 config = builder.buildFromFile(configFile); 96 97 try { 98 pathMapperClassName = config.getChild(ELEMENT_PATH_MAPPER).getValue(); 99 Class pathMapperClass = Class.forName(pathMapperClassName); 100 this.mapper = (DocumentIdToPathMapper) pathMapperClass.newInstance(); 101 } catch (ClassNotFoundException e) { 102 throw new PublicationException("Cannot instantiate documentToPathMapper: [" 103 + pathMapperClassName + "]", e); 104 } 105 106 try { 107 Configuration documentBuilderConfiguration = config.getChild( 108 ELEMENT_DOCUMENT_BUILDER, false); 109 if (documentBuilderConfiguration != null) { 110 documentBuilderClassName = documentBuilderConfiguration.getValue(); 111 Class documentBuilderClass = Class.forName(documentBuilderClassName); 112 this.documentBuilder = (DocumentBuilder) documentBuilderClass.newInstance(); 113 } 114 } catch (ClassNotFoundException e) { 115 throw new PublicationException("Cannot instantiate document builder: [" 116 + pathMapperClassName + "]", e); 117 } 118 119 Configuration[] languages = config.getChild(LANGUAGES).getChildren(); 120 for (int i = 0; i < languages.length; i++) { 121 Configuration languageConfig = languages[i]; 122 String language = languageConfig.getValue(); 123 this.languages.add(language); 124 if (languageConfig.getAttribute(DEFAULT_LANGUAGE_ATTR, null) != null) { 125 defaultLanguage = language; 126 } 127 } 128 129 Configuration siteStructureConfiguration = config.getChild(ELEMENT_SITE_STRUCTURE, 130 false); 131 if (siteStructureConfiguration != null) { 132 String siteStructureType = siteStructureConfiguration.getAttribute(ATTRIBUTE_TYPE); 133 if (!siteStructureType.equals("sitetree")) { 134 hasSitetree = false; 135 } 136 } 137 138 Configuration[] proxyConfigs = config.getChildren(ELEMENT_PROXY); 139 for (int i = 0; i < proxyConfigs.length; i++) { 140 String url = proxyConfigs[i].getAttribute(ATTRIBUTE_URL); 141 String ssl = proxyConfigs[i].getAttribute(ATTRIBUTE_SSL); 142 String area = proxyConfigs[i].getAttribute(ATTRIBUTE_AREA); 143 144 Proxy proxy = new Proxy(); 145 proxy.setUrl(url); 146 147 Object key = getProxyKey(area, Boolean.valueOf(ssl).booleanValue()); 148 this.areaSsl2proxy.put(key, proxy); 149 if (log.isDebugEnabled()) { 150 log.debug("Adding proxy: [" + proxy + "] for area=[" + area + "] SSL=[" + ssl 151 + "]"); 152 } 153 } 154 155 Configuration[] rewriteAttributeConfigs = config.getChildren(ELEMENT_REWRITE_ATTRIBUTE); 156 List xPaths = new ArrayList (); 157 for (int i = 0; i < rewriteAttributeConfigs.length; i++) { 158 String xPath = rewriteAttributeConfigs[i].getAttribute(ATTRIBUTE_XPATH); 159 xPaths.add(xPath); 160 } 161 this.rewriteAttributeXPaths = (String []) xPaths.toArray(new String [xPaths.size()]); 162 163 } catch (PublicationException e) { 164 throw e; 165 } catch (Exception e) { 166 log.error(e); 167 throw new PublicationException("Problem with config file: " 168 + configFile.getAbsolutePath(), e); 169 } 170 171 breadcrumbprefix = config.getChild(BREADCRUMB_PREFIX).getValue(""); 172 173 sslprefix = config.getChild(SSL_PREFIX).getValue(""); 174 175 livemountpoint = config.getChild(LIVE_MOUNT_POINT).getValue(""); 176 177 } 178 179 183 public String getId() { 184 return id; 185 } 186 187 192 public PublishingEnvironment getEnvironment() { 193 return environment; 194 } 195 196 201 public File getServletContext() { 202 return servletContext; 203 } 204 205 209 public File getDirectory() { 210 return new File (getServletContext(), PUBLICATION_PREFIX + File.separator + getId()); 211 } 212 213 220 public File getContentDirectory(String area) { 221 return new File (getDirectory(), CONTENT_PATH + File.separator + area); 222 } 223 224 229 public void setPathMapper(DefaultDocumentIdToPathMapper mapper) { 230 assert mapper != null; 231 this.mapper = mapper; 232 } 233 234 239 public DocumentIdToPathMapper getPathMapper() { 240 return mapper; 241 } 242 243 248 public static boolean isValidArea(String area) { 249 return area != null && Arrays.asList(areas).contains(area); 250 } 251 252 257 public String getDefaultLanguage() { 258 return defaultLanguage; 259 } 260 261 266 public void setDefaultLanguage(String language) { 267 defaultLanguage = language; 268 } 269 270 275 public String [] getLanguages() { 276 return (String []) languages.toArray(new String [languages.size()]); 277 } 278 279 285 public String getBreadcrumbPrefix() { 286 return breadcrumbprefix; 287 } 288 289 296 public String getSSLPrefix() { 297 return sslprefix; 298 } 299 300 309 public String getLiveMountPoint() { 310 return livemountpoint; 311 } 312 313 322 public SiteTree getTree(String area) throws SiteTreeException { 323 324 SiteTree sitetree = null; 325 326 if (hasSitetree) { 327 if (siteTrees.containsKey(area)) { 328 sitetree = (SiteTree) siteTrees.get(area); 329 } else { 330 sitetree = new DefaultSiteTree(getDirectory(), area); 331 siteTrees.put(area, sitetree); 332 } 333 } 334 return sitetree; 335 } 336 337 349 public DefaultSiteTree getSiteTree(String area) throws SiteTreeException { 350 351 DefaultSiteTree sitetree = null; 352 353 if (hasSitetree) { 354 if (siteTrees.containsKey(area)) { 355 sitetree = (DefaultSiteTree) siteTrees.get(area); 356 } else { 357 sitetree = new DefaultSiteTree(getDirectory(), area); 358 siteTrees.put(area, sitetree); 359 } 360 } 361 return sitetree; 362 } 363 364 private DocumentBuilder documentBuilder; 365 366 370 public DocumentBuilder getDocumentBuilder() { 371 372 if (documentBuilder == null) { 373 throw new IllegalStateException ( 374 "The document builder was not defined in publication.xconf!"); 375 } 376 377 return documentBuilder; 378 } 379 380 387 public Document getAreaVersion(Document document, String area) throws PublicationException { 388 DocumentBuilder builder = getDocumentBuilder(); 389 String url = builder 390 .buildCanonicalUrl(this, area, document.getId(), document.getLanguage()); 391 Document destinationDocument = builder.buildDocument(this, url); 392 return destinationDocument; 393 } 394 395 398 public boolean equals(Object object) { 399 boolean equals = false; 400 401 if (getClass().isInstance(object)) { 402 Publication publication = (Publication) object; 403 equals = getId().equals(publication.getId()) 404 && getServletContext().equals(publication.getServletContext()); 405 } 406 407 return equals; 408 } 409 410 413 public int hashCode() { 414 String key = getServletContext() + ":" + getId(); 415 return key.hashCode(); 416 } 417 418 424 public void copyDocument(Document sourceDocument, Document destinationDocument) 425 throws PublicationException { 426 427 copyDocumentSource(sourceDocument, destinationDocument); 428 429 copySiteStructure(sourceDocument, destinationDocument); 430 } 431 432 438 protected void copySiteStructure(Document sourceDocument, Document destinationDocument) 439 throws PublicationException { 440 if (hasSitetree) { 441 try { 442 SiteTree sourceTree = getSiteTree(sourceDocument.getArea()); 443 SiteTree destinationTree = getSiteTree(destinationDocument.getArea()); 444 445 SiteTreeNode sourceNode = sourceTree.getNode(sourceDocument.getId()); 446 if (sourceNode == null) { 447 throw new PublicationException("The node for source document [" 448 + sourceDocument.getId() + "] doesn't exist!"); 449 } 450 SiteTreeNode[] siblings = sourceNode.getNextSiblings(); 451 String parentId = sourceNode.getAbsoluteParentId(); 452 SiteTreeNode sibling = null; 453 String siblingDocId = null; 454 455 if (sourceDocument.getId().equals(destinationDocument.getId())) { 457 for (int i = 0; i < siblings.length; i++) { 458 String docId = parentId + "/" + siblings[i].getId(); 459 sibling = destinationTree.getNode(docId); 460 if (sibling != null) { 461 siblingDocId = docId; 462 break; 463 } 464 } 465 } 466 467 468 Label label = sourceNode.getLabel(sourceDocument.getLanguage()); 469 if (label == null) { 470 throw new PublicationException("The node " + sourceDocument.getId() 473 + " doesn't contain a label for language " 474 + sourceDocument.getLanguage()); 475 } 476 SiteTreeNode destinationNode = destinationTree.getNode(destinationDocument 477 .getId()); 478 if (destinationNode == null) { 479 Label[] labels = { label }; 480 481 if (siblingDocId == null) { 482 destinationTree.addNode(destinationDocument.getId(), labels, 483 sourceNode.visibleInNav(), sourceNode.getHref(), sourceNode.getSuffix(), sourceNode 484 .hasLink()); 485 } else { 486 destinationTree.addNode(destinationDocument.getId(), labels, sourceNode.visibleInNav(), 487 sourceNode.getHref(), sourceNode.getSuffix(), sourceNode 488 .hasLink(), siblingDocId); 489 } 490 491 } else { 492 destinationTree.setLabel(destinationDocument.getId(), label); 496 String visibility ="true"; 498 if (!sourceNode.visibleInNav()) visibility = "false"; 499 destinationNode.setNodeAttribute(SiteTreeNodeImpl.VISIBLEINNAV_ATTRIBUTE_NAME, 500 visibility); 501 502 if (sourceNode.hasLink() != destinationNode.hasLink()) { 504 String link = (sourceNode.hasLink() ? "true" : "false"); 505 destinationNode.setNodeAttribute(SiteTreeNodeImpl.LINK_ATTRIBUTE_NAME, link); 506 } 507 508 } 509 510 destinationTree.save(); 511 } catch (SiteTreeException e) { 512 throw new PublicationException(e); 513 } 514 } 515 } 516 517 523 protected abstract void copyDocumentSource(Document sourceDocument, Document destinationDocument) 524 throws PublicationException; 525 526 529 public void deleteDocument(Document document) throws PublicationException { 530 if (!document.exists()) { 531 throw new PublicationException("Document [" + document + "] does not exist!"); 532 } 533 deleteFromSiteStructure(document); 534 deleteDocumentSource(document); 535 } 536 537 542 protected void deleteFromSiteStructure(Document document) throws PublicationException { 543 if (hasSitetree) { 544 SiteTree tree; 545 try { 546 tree = getSiteTree(document.getArea()); 547 } catch (SiteTreeException e) { 548 throw new PublicationException(e); 549 } 550 551 SiteTreeNode node = tree.getNode(document.getId()); 552 553 if (node == null) { 554 throw new PublicationException("Sitetree node for document [" + document 555 + "] does not exist!"); 556 } 557 558 Label label = node.getLabel(document.getLanguage()); 559 560 if (label == null) { 561 throw new PublicationException("Sitetree label for document [" + document 562 + "] in language [" + document.getLanguage() + "]does not exist!"); 563 } 564 565 if (node.getLabels().length == 1 && node.getChildren().length > 0) { 566 throw new PublicationException("Cannot delete last language version of document [" 567 + document + "] because this node has children."); 568 } 569 570 node.removeLabel(label); 571 572 try { 573 if (node.getLabels().length == 0) { 574 tree.deleteNode(document.getId()); 575 } 576 577 tree.save(); 578 } catch (SiteTreeException e) { 579 throw new PublicationException(e); 580 } 581 } 582 } 583 584 589 protected abstract void deleteDocumentSource(Document document) throws PublicationException; 590 591 595 public void moveDocument(Document sourceDocument, Document destinationDocument) 596 throws PublicationException { 597 copyDocument(sourceDocument, destinationDocument); 598 deleteDocument(sourceDocument); 599 } 600 601 private Map areaSsl2proxy = new HashMap (); 602 603 609 protected Object getProxyKey(String area, boolean isSslProtected) { 610 return area + ":" + isSslProtected; 611 } 612 613 617 public Proxy getProxy(Document document, boolean isSslProtected) { 618 619 Object key = getProxyKey(document.getArea(), isSslProtected); 620 Proxy proxy = (Proxy) this.areaSsl2proxy.get(key); 621 622 if (log.isDebugEnabled()) { 623 log.debug("Resolving proxy for [" + document + "] SSL=[" + isSslProtected + "]"); 624 log.debug("Resolved proxy: [" + proxy + "]"); 625 } 626 627 return proxy; 628 } 629 630 633 public String [] getRewriteAttributeXPaths() { 634 return this.rewriteAttributeXPaths; 635 } 636 } 637 | Popular Tags |