001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.jsp; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsFolder; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsProperty; 034import org.opencms.file.CmsPropertyDefinition; 035import org.opencms.file.CmsRequestContext; 036import org.opencms.file.CmsResource; 037import org.opencms.file.CmsResourceFilter; 038import org.opencms.file.types.CmsResourceTypeXmlContent; 039import org.opencms.file.types.CmsResourceTypeXmlPage; 040import org.opencms.i18n.CmsLocaleGroup; 041import org.opencms.jsp.util.CmsJspCategoryAccessBean; 042import org.opencms.jsp.util.CmsJspContentAccessBean; 043import org.opencms.jsp.util.CmsJspImageBean; 044import org.opencms.jsp.util.CmsJspLinkWrapper; 045import org.opencms.jsp.util.CmsJspValueTransformers.CmsLocalePropertyLoaderTransformer; 046import org.opencms.loader.CmsLoaderException; 047import org.opencms.main.CmsException; 048import org.opencms.main.CmsLog; 049import org.opencms.main.OpenCms; 050import org.opencms.relations.CmsRelation; 051import org.opencms.relations.CmsRelationFilter; 052import org.opencms.security.CmsSecurityException; 053import org.opencms.util.CmsCollectionsGenericWrapper; 054import org.opencms.util.CmsUUID; 055import org.opencms.util.CmsVfsUtil; 056 057import java.util.ArrayList; 058import java.util.Collections; 059import java.util.HashMap; 060import java.util.List; 061import java.util.Locale; 062import java.util.Map; 063import java.util.stream.Collectors; 064 065import org.apache.commons.logging.Log; 066 067import com.google.common.base.Supplier; 068import com.google.common.base.Suppliers; 069 070/** 071 * Wrapper subclass of CmsResource with some convenience methods.<p> 072 */ 073public class CmsJspResourceWrapper extends CmsResource { 074 075 /** Logger instance for this class. */ 076 @SuppressWarnings("unused") 077 private static final Log LOG = CmsLog.getLog(CmsJspResourceWrapper.class); 078 079 /** Serial version id. */ 080 private static final long serialVersionUID = 1L; 081 082 /** Parameter value used to select outgoing relations. */ 083 public static final boolean RELATIONS_OUT = true; 084 085 /** Parameter value used to select incoming relations. */ 086 public static final boolean RELATIONS_IN = false; 087 088 /** All resources that are sources of incoming relations. */ 089 public List<CmsJspResourceWrapper> m_incomingRelations; 090 091 /** All resources that are targets of outgoing relations. */ 092 public List<CmsJspResourceWrapper> m_outgoingRelations; 093 094 /** All parent folder of this resource in the current site as a list. */ 095 public List<CmsJspResourceWrapper> m_parentFolders; 096 097 /** The category access bean for this resource. */ 098 private CmsJspCategoryAccessBean m_categories; 099 100 /** The CMS context. */ 101 private CmsObject m_cms; 102 103 /** The resource / file content as a String. */ 104 private String m_content; 105 106 /** The file object for this resource. */ 107 private CmsFile m_file; 108 109 /** Image bean instance created from this resource. */ 110 private CmsJspImageBean m_imageBean; 111 112 /** Stores if this resource is an XML content or not. */ 113 private Boolean m_isXml; 114 115 /** The set of locale variants. */ 116 private Map<String, CmsJspResourceWrapper> m_localeResources; 117 118 /** The main locale. */ 119 private Locale m_mainLocale; 120 121 /** The navigation builder for this resource. */ 122 private CmsJspNavBuilder m_navBuilder; 123 124 /** The navigation info element for this resource. */ 125 private CmsJspNavElement m_navigation; 126 127 /** The default file of this resource, assumed that this resource is a folder. */ 128 private CmsJspResourceWrapper m_navigationDefaultFile; 129 130 /** The navigation info elements in this resource, assuming that this resource is a folder. */ 131 private List<CmsJspNavElement> m_navigationForFolder; 132 133 /** The parent folder of this resource in the current site. */ 134 private CmsJspResourceWrapper m_parentFolder; 135 136 /** Properties of this resource. */ 137 private Map<String, String> m_properties; 138 139 /** Locale properties of this resource. */ 140 private Map<String, Map<String, String>> m_propertiesLocale; 141 142 /** Locale properties of this resource with search. */ 143 private Map<String, Map<String, String>> m_propertiesLocaleSearch; 144 145 /** Properties of this resource with search. */ 146 private Map<String, String> m_propertiesSearch; 147 148 /** The calculated site path of the resource. */ 149 private String m_sitePath; 150 151 /** The type name of the resource. */ 152 private String m_typeName; 153 154 /** The XML content access bean. */ 155 private CmsJspContentAccessBean m_xml; 156 157 /** Creates/caches link wrapper. */ 158 private Supplier<CmsJspLinkWrapper> m_linkSupplier = Suppliers.memoize( 159 () -> new CmsJspLinkWrapper(m_cms, CmsJspResourceWrapper.this)); 160 161 /** 162 * Creates a new instance.<p> 163 * 164 * @param cms the current CMS context 165 * @param res the resource to wrap 166 */ 167 private CmsJspResourceWrapper(CmsObject cms, CmsResource res) { 168 169 super( 170 res.getStructureId(), 171 res.getResourceId(), 172 res.getRootPath(), 173 res.getTypeId(), 174 res.isFolder(), 175 res.getFlags(), 176 res.getProjectLastModified(), 177 res.getState(), 178 res.getDateCreated(), 179 res.getUserCreated(), 180 res.getDateLastModified(), 181 res.getUserLastModified(), 182 res.getDateReleased(), 183 res.getDateExpired(), 184 res.getSiblingCount(), 185 res.getLength(), 186 res.getDateContent(), 187 res.getVersion()); 188 m_cms = cms; 189 m_file = null; 190 m_content = ""; 191 } 192 193 /** 194 * Factory method to create a new {@link CmsJspResourceWrapper} instance from a {@link CmsResource}.<p> 195 * 196 * In case the parameter resource already is a wrapped resource AND the OpenCms request context is 197 * the same as the provided context, the parameter object is returned.<p> 198 * 199 * @param cms the current CMS context 200 * @param res the resource to wrap 201 * 202 * @return a new instance of a {@link CmsJspResourceWrapper} 203 */ 204 public static CmsJspResourceWrapper wrap(CmsObject cms, CmsResource res) { 205 206 CmsJspResourceWrapper result = null; 207 if ((cms != null) && (res != null)) { 208 if (res instanceof CmsJspResourceWrapper) { 209 CmsJspResourceWrapper wrapper = (CmsJspResourceWrapper)res; 210 if (cms.getRequestContext().getSiteRoot().equals(wrapper.getRequestContext().getSiteRoot())) { 211 result = wrapper; 212 } else { 213 result = new CmsJspResourceWrapper(cms, res); 214 } 215 } else { 216 result = new CmsJspResourceWrapper(cms, res); 217 } 218 } 219 return result; 220 } 221 222 /** 223 * Two resources are considered equal in case their structure id is equal.<p> 224 * 225 * @see CmsResource#equals(java.lang.Object) 226 */ 227 @Override 228 public boolean equals(Object obj) { 229 230 if (obj == null) { 231 return false; 232 } 233 234 if (obj == this) { 235 return true; 236 } 237 if (obj instanceof CmsResource) { 238 return ((CmsResource)obj).getStructureId().equals(getStructureId()); 239 } 240 return false; 241 } 242 243 /** 244 * Returns the categories assigned to this resource.<p> 245 * 246 * @return the categories assigned to this resource 247 */ 248 public CmsJspCategoryAccessBean getCategories() { 249 250 if (m_categories == null) { 251 m_categories = new CmsJspCategoryAccessBean(m_cms, this); 252 } 253 return m_categories; 254 } 255 256 /** 257 * Returns the OpenCms user context this resource was initialized with.<p> 258 * 259 * @return the OpenCms user context this resource was initialized with 260 */ 261 public CmsObject getCmsObject() { 262 263 return m_cms; 264 } 265 266 /** 267 * Returns the content of the file as a String.<p> 268 * 269 * @return the content of the file as a String 270 */ 271 public String getContent() { 272 273 if ((m_content.length() == 0) && (getFile() != null)) { 274 m_content = new String(getFile().getContents()); 275 } 276 return m_content; 277 } 278 279 /** 280 * Returns this resources name extension (if present).<p> 281 * 282 * The extension will always be lower case.<p> 283 * 284 * @return the extension or <code>null</code> if not available 285 * 286 * @see CmsResource#getExtension(String) 287 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getResourceExtension(Object) 288 */ 289 public String getExtension() { 290 291 return getExtension(getRootPath()); 292 } 293 294 /** 295 * Returns the full file object for this resource.<p> 296 * 297 * @return the full file object for this resource 298 */ 299 public CmsFile getFile() { 300 301 if ((m_file == null) && !isFolder()) { 302 try { 303 m_file = m_cms.readFile(this); 304 } catch (CmsException e) { 305 // this should not happen since we are updating from a resource object 306 } 307 } 308 return m_file; 309 } 310 311 /** 312 * Returns the folder of this resource.<p> 313 * 314 * In case this resource already is a {@link CmsFolder}, it is returned without modification. 315 * In case it is a {@link CmsFile}, the parent folder of the file is returned.<p> 316 * 317 * @return the folder of this resource 318 * 319 * @see #getSitePathFolder() 320 */ 321 public CmsJspResourceWrapper getFolder() { 322 323 CmsJspResourceWrapper result; 324 if (isFolder()) { 325 result = this; 326 } else { 327 result = readResource(getSitePathFolder()); 328 } 329 return result; 330 } 331 332 /** 333 * Gets a list of resource wrappers for resources with relations pointing to this resource. 334 * 335 * @return the list of resource wrappers 336 */ 337 public List<CmsJspResourceWrapper> getIncomingRelations() { 338 339 if (m_incomingRelations == null) { 340 m_incomingRelations = getRelatedResources(RELATIONS_IN); 341 } 342 return m_incomingRelations; 343 } 344 345 /** 346 * Gets a list of resource wrappers for resources with relations pointing to this resource, for a specific type. 347 * 348 * @param typeName name of the type to filter 349 * @return the list of resource wrappers 350 */ 351 public List<CmsJspResourceWrapper> getIncomingRelations(String typeName) { 352 353 return getIncomingRelations().stream().filter(res -> res.getTypeName().equals(typeName)).collect( 354 Collectors.toList()); 355 } 356 357 /** 358 * Returns <code>true</code> in case this resource is an image in the VFS.<p> 359 * 360 * @return <code>true</code> in case this resource is an image in the VFS 361 */ 362 public boolean getIsImage() { 363 364 return getToImage().isImage(); 365 } 366 367 /** 368 * Returns <code>true</code> in case this resource is an XML content.<p> 369 * 370 * @return <code>true</code> in case this resource is an XML content 371 */ 372 public boolean getIsXml() { 373 374 if (m_isXml == null) { 375 m_isXml = Boolean.valueOf( 376 CmsResourceTypeXmlPage.isXmlPage(this) || CmsResourceTypeXmlContent.isXmlContent(this)); 377 } 378 return m_isXml.booleanValue(); 379 } 380 381 /** 382 * Returns a substituted link to this resource.<p> 383 * 384 * @return the link 385 */ 386 public String getLink() { 387 388 return getToLink().getLink(); 389 } 390 391 /** 392 * Returns a map of the locale group for the current resource, with locale strings as keys.<p> 393 * 394 * @return a map with locale strings as keys and resource wrappers for the corresponding locale variants 395 */ 396 public Map<String, CmsJspResourceWrapper> getLocaleResource() { 397 398 if (m_localeResources != null) { 399 return m_localeResources; 400 } 401 try { 402 CmsLocaleGroup localeGroup = m_cms.getLocaleGroupService().readLocaleGroup(this); 403 Map<Locale, CmsResource> resourcesByLocale = localeGroup.getResourcesByLocale(); 404 Map<String, CmsJspResourceWrapper> result = new HashMap<>(); 405 for (Map.Entry<Locale, CmsResource> entry : resourcesByLocale.entrySet()) { 406 result.put(entry.getKey().toString(), CmsJspResourceWrapper.wrap(m_cms, entry.getValue())); 407 } 408 m_localeResources = result; 409 return result; 410 } catch (CmsException e) { 411 return new HashMap<String, CmsJspResourceWrapper>(); 412 } 413 } 414 415 /** 416 * Returns the main locale for this resource.<p> 417 * 418 * @return the main locale for this resource 419 */ 420 public Locale getMainLocale() { 421 422 if (m_mainLocale != null) { 423 return m_mainLocale; 424 } 425 try { 426 CmsLocaleGroup localeGroup = m_cms.getLocaleGroupService().readLocaleGroup(this); 427 m_mainLocale = localeGroup.getMainLocale(); 428 return m_mainLocale; 429 } catch (CmsException e) { 430 return null; 431 } 432 } 433 434 /** 435 * Returns the mime type for this resource.<p> 436 * 437 * In case no valid mime type can be determined from the file extension, <code>text/plain</code> is returned.<p> 438 * 439 * @return the mime type for this resource 440 */ 441 public String getMimeType() { 442 443 return OpenCms.getResourceManager().getMimeType(getRootPath(), null, "text/plain"); 444 } 445 446 /** 447 * Returns the navigation builder for this resource.<p> 448 * 449 * This will be initialized with this resource as default URI.<p> 450 * 451 * @return the navigation builder for this resource 452 */ 453 public CmsJspNavBuilder getNavBuilder() { 454 455 if (m_navBuilder == null) { 456 m_navBuilder = new CmsJspNavBuilder(); 457 m_navBuilder.init(m_cms, null, getSitePath()); 458 } 459 return m_navBuilder; 460 } 461 462 /** 463 * Returns the navigation info element for this resource.<p> 464 * 465 * @return the navigation info element for this resource 466 */ 467 public CmsJspNavElement getNavigation() { 468 469 if (m_navigation == null) { 470 m_navigation = getNavBuilder().getNavigationForResource(); 471 } 472 return m_navigation; 473 } 474 475 /** 476 * Returns the default resource for this resource.<p> 477 * 478 * If this resource is a file, then this file is returned.<p> 479 * 480 * Otherwise, in case this resource is a folder:<br> 481 * <ol> 482 * <li>the {@link CmsPropertyDefinition#PROPERTY_DEFAULT_FILE} is checked, and 483 * <li>if still no file could be found, the configured default files in the 484 * <code>opencms-vfs.xml</code> configuration are iterated until a match is 485 * found, and 486 * <li>if still no file could be found, <code>null</code> is returned 487 * </ol> 488 * 489 * @return the default file for the given folder 490 * 491 * @see CmsObject#readDefaultFile(CmsResource, CmsResourceFilter) 492 */ 493 public CmsJspResourceWrapper getNavigationDefaultFile() { 494 495 if (m_navigationDefaultFile == null) { 496 if (isFolder()) { 497 try { 498 m_navigationDefaultFile = wrap(m_cms, m_cms.readDefaultFile(this, CmsResourceFilter.DEFAULT)); 499 } catch (CmsSecurityException e) { 500 if (LOG.isDebugEnabled()) { 501 LOG.debug(e.getMessage(), e); 502 } 503 } 504 } 505 } else { 506 m_navigationDefaultFile = this; 507 } 508 return m_navigationDefaultFile; 509 } 510 511 /** 512 * Returns the navigation info elements in this resource, assuming that this resource is a folder.<p> 513 * 514 * @return the navigation info elements in this resource, assuming that this resource is a folder 515 */ 516 public List<CmsJspNavElement> getNavigationForFolder() { 517 518 if (m_navigationForFolder == null) { 519 m_navigationForFolder = getNavBuilder().getNavigationForFolder(); 520 } 521 return m_navigationForFolder; 522 } 523 524 /** 525 * Returns the substituted online link to this resource.<p> 526 * 527 * @return the link 528 */ 529 public String getOnlineLink() { 530 531 return getToLink().getOnlineLink(); 532 } 533 534 /** 535 * Gets a list of resources with relations pointing to them from this resources, as resource wrappers. 536 * 537 * @return the list of resource wrappers 538 */ 539 public List<CmsJspResourceWrapper> getOutgoingRelations() { 540 541 if (m_outgoingRelations == null) { 542 m_outgoingRelations = getRelatedResources(RELATIONS_OUT); 543 } 544 return m_outgoingRelations; 545 } 546 547 /** 548 * Gets a list of resources with relations pointing to them from this resources, as resource wrappers. 549 * 550 * Only gets resources with the given type. 551 * 552 * @param typeName the name of the type to filter 553 * @return the list of resource wrappers 554 */ 555 556 public List<CmsJspResourceWrapper> getOutgoingRelations(String typeName) { 557 558 return getOutgoingRelations().stream().filter(res -> res.getTypeName().equals(typeName)).collect( 559 Collectors.toList()); 560 } 561 562 /** 563 * Returns the parent folder of this resource in the current site.<p> 564 * 565 * The parent folder of a file is the folder of the file. 566 * The parent folder of a folder is the parent folder of the folder. 567 * The parent folder of the root folder is <code>null</code>.<p> 568 * 569 * @return the parent folder of this resource in the current site 570 * 571 * @see #getSitePathParentFolder() 572 * @see CmsResource#getParentFolder(String) 573 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getParentFolder(Object) 574 */ 575 public CmsJspResourceWrapper getParentFolder() { 576 577 if (m_parentFolder == null) { 578 String parentFolder = getSitePathParentFolder(); 579 if (parentFolder != null) { 580 m_parentFolder = readResource(getSitePathParentFolder()); 581 } 582 } 583 return m_parentFolder; 584 } 585 586 /** 587 * Returns all parent folder of this resource in the current site as a list.<p> 588 * 589 * First resource in the list will be the direct parent folder of this resource, 590 * the last element will be the site root folder.<p> 591 * 592 * @return all parent folder of this resource in the current site as a list 593 */ 594 public List<CmsJspResourceWrapper> getParentFolders() { 595 596 if (m_parentFolders == null) { 597 m_parentFolders = new ArrayList<CmsJspResourceWrapper>(); 598 CmsJspResourceWrapper parentFolder = getParentFolder(); 599 while (parentFolder != null) { 600 m_parentFolders.add(parentFolder); 601 parentFolder = parentFolder.getParentFolder(); 602 } 603 } 604 return m_parentFolders; 605 } 606 607 /** 608 * Returns the direct properties of this resource in a map.<p> 609 * 610 * This is without "search", so it will not include inherited properties from the parent folders.<p> 611 * 612 * @return the direct properties of this resource in a map 613 */ 614 public Map<String, String> getProperty() { 615 616 if (m_properties == null) { 617 try { 618 List<CmsProperty> properties = m_cms.readPropertyObjects(this, false); 619 m_properties = CmsProperty.toMap(properties); 620 } catch (CmsException e) { 621 if (LOG.isDebugEnabled()) { 622 LOG.debug(e.getMessage(), e); 623 } 624 } 625 } 626 return m_properties; 627 } 628 629 /** 630 * Returns the locale specific evaluated "Description" property for the resource. 631 * In case the resource is a default file, also the parent folders "Description" property is read as fallback. 632 * 633 * @return the locale specific description property for the resource. 634 */ 635 public String getPropertyDescription() { 636 637 return CmsVfsUtil.readPropertyValueWithFolderFallbackForDefaultFiles( 638 m_cms, 639 this, 640 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 641 m_cms.getRequestContext().getLocale()); 642 } 643 644 /** 645 * Returns the locale specific evaluated "Keywords" property for the resource. 646 * In case the resource is a default file, also the parent folders "Keywords" property is read as fallback. 647 * 648 * @return the locale specific description property for the resource. 649 */ 650 public String getPropertyKeywords() { 651 652 return CmsVfsUtil.readPropertyValueWithFolderFallbackForDefaultFiles( 653 m_cms, 654 this, 655 CmsPropertyDefinition.PROPERTY_KEYWORDS, 656 m_cms.getRequestContext().getLocale()); 657 } 658 659 /** 660 * Returns the direct properties of this resource in a map for a given locale.<p> 661 * 662 * This is without "search", so it will not include inherited properties from the parent folders.<p> 663 * 664 * @return the direct properties of this resource in a map for a given locale 665 */ 666 public Map<String, Map<String, String>> getPropertyLocale() { 667 668 if (m_propertiesLocale == null) { 669 m_propertiesLocale = CmsCollectionsGenericWrapper.createLazyMap( 670 new CmsLocalePropertyLoaderTransformer(getCmsObject(), this, false)); 671 // result may still be null 672 return (m_propertiesLocale == null) ? Collections.EMPTY_MAP : m_propertiesLocale; 673 } 674 return m_propertiesLocale; 675 } 676 677 /** 678 * Returns the searched properties of this resource in a map for a given locale.<p> 679 * 680 * This is with "search", so it will include inherited properties from the parent folders.<p> 681 * 682 * @return the direct properties of this resource in a map for a given locale 683 */ 684 public Map<String, Map<String, String>> getPropertyLocaleSearch() { 685 686 if (m_propertiesLocaleSearch == null) { 687 m_propertiesLocaleSearch = CmsCollectionsGenericWrapper.createLazyMap( 688 new CmsLocalePropertyLoaderTransformer(getCmsObject(), this, true)); 689 // result may still be null 690 return (m_propertiesLocaleSearch == null) ? Collections.EMPTY_MAP : m_propertiesLocaleSearch; 691 } 692 return m_propertiesLocaleSearch; 693 } 694 695 /** 696 * Returns the searched properties of this resource in a map.<p> 697 * 698 * This is with "search", so it will include inherited properties from the parent folders.<p> 699 * 700 * @return the direct properties of this resource in a map 701 */ 702 public Map<String, String> getPropertySearch() { 703 704 if (m_propertiesSearch == null) { 705 try { 706 List<CmsProperty> properties = m_cms.readPropertyObjects(this, true); 707 m_propertiesSearch = CmsProperty.toMap(properties); 708 } catch (CmsException e) { 709 if (LOG.isDebugEnabled()) { 710 LOG.debug(e.getMessage(), e); 711 } 712 } 713 } 714 return m_propertiesSearch; 715 } 716 717 /** 718 * Returns the OpenCms user request context this resource was initialized with.<p> 719 * 720 * @return the OpenCms user request context this resource was initialized with 721 */ 722 public CmsRequestContext getRequestContext() { 723 724 return m_cms.getRequestContext(); 725 } 726 727 /** 728 * Returns this resources name extension (if present).<p> 729 * 730 * The extension will always be lower case.<p> 731 * 732 * @return the extension or <code>null</code> if not available 733 * 734 * @see CmsResource#getExtension(String) 735 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getResourceExtension(Object) 736 */ 737 public String getResourceExtension() { 738 739 return getExtension(); 740 } 741 742 /** 743 * Returns the name of this resource without the path information.<p> 744 * 745 * The resource name of a file is the name of the file. 746 * The resource name of a folder is the folder name with trailing "/". 747 * The resource name of the root folder is <code>/</code>.<p> 748 * 749 * @return the name of this resource without the path information 750 * 751 * @see CmsResource#getName() 752 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getResourceName(Object) 753 */ 754 public String getResourceName() { 755 756 return getName(); 757 } 758 759 /** 760 * Returns the folder name of this resource from the root site.<p> 761 * 762 * In case this resource already is a {@link CmsFolder}, the folder path is returned without modification. 763 * In case it is a {@link CmsFile}, the parent folder name of the file is returned.<p> 764 * 765 * @return the folder name of this resource from the root site 766 */ 767 public String getRootPathFolder() { 768 769 String result; 770 if (isFile()) { 771 result = getRootPathParentFolder(); 772 } else { 773 result = getRootPath(); 774 } 775 return result; 776 } 777 778 /** 779 * Returns the directory level of a resource from the root site.<p> 780 * 781 * The root folder "/" has level 0, 782 * a folder "/foo/" would have level 1, 783 * a folder "/foo/bar/" level 2 etc.<p> 784 * 785 * @return the directory level of a resource from the root site 786 * 787 * @see CmsResource#getPathLevel(String) 788 */ 789 public int getRootPathLevel() { 790 791 return getPathLevel(getRootPath()); 792 } 793 794 /** 795 * Returns the parent folder of this resource from the root site.<p> 796 * 797 * @return the parent folder of this resource from the root site 798 * 799 * @see CmsResource#getParentFolder(String) 800 */ 801 public String getRootPathParentFolder() { 802 803 return getParentFolder(getRootPath()); 804 } 805 806 /** 807 * Returns the current site path to this resource.<p> 808 * 809 * @return the current site path to this resource 810 * 811 * @see org.opencms.file.CmsRequestContext#getSitePath(CmsResource) 812 */ 813 public String getSitePath() { 814 815 if (m_sitePath == null) { 816 m_sitePath = m_cms.getRequestContext().getSitePath(this); 817 } 818 819 return m_sitePath; 820 } 821 822 /** 823 * Returns the folder name of this resource in the current site.<p> 824 * 825 * In case this resource already is a {@link CmsFolder}, the folder path is returned without modification. 826 * In case it is a {@link CmsFile}, the parent folder name of the file is returned.<p> 827 * 828 * @return the folder name of this resource in the current site 829 */ 830 public String getSitePathFolder() { 831 832 String result; 833 if (isFile()) { 834 result = getSitePathParentFolder(); 835 } else { 836 result = getSitePath(); 837 } 838 return result; 839 } 840 841 /** 842 * Returns the directory level of a resource in the current site.<p> 843 * 844 * The root folder "/" has level 0, 845 * a folder "/foo/" would have level 1, 846 * a folder "/foo/bar/" level 2 etc.<p> 847 * 848 * @return the directory level of a resource in the current site 849 * 850 * @see CmsResource#getPathLevel(String) 851 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getPathLevel(Object) 852 */ 853 public int getSitePathLevel() { 854 855 return getPathLevel(getSitePath()); 856 } 857 858 /** 859 * Returns the parent folder of this resource in the current site.<p> 860 * 861 * The parent folder of a file is the folder of the file. 862 * The parent folder of a folder is the parent folder of the folder. 863 * The parent folder of the root folder is <code>null</code>.<p> 864 * 865 * @return the parent folder of this resource in the current site 866 * 867 * @see CmsResource#getParentFolder(String) 868 * @see org.opencms.jsp.util.CmsJspVfsAccessBean#getParentFolder(Object) 869 */ 870 public String getSitePathParentFolder() { 871 872 return getParentFolder(getSitePath()); 873 } 874 875 /** 876 * Returns a scaled image bean from the wrapped value.<p> 877 * 878 * In case the value does not point to an image resource, <code>null</code> is returned. 879 * 880 * @return the scaled image bean 881 */ 882 public CmsJspImageBean getToImage() { 883 884 if (m_imageBean == null) { 885 m_imageBean = new CmsJspImageBean(getCmsObject(), this, null); 886 } 887 return m_imageBean; 888 } 889 890 /** 891 * Gets a link wrapper corresponding to the the resource's path. 892 * 893 * @return the new link wrapper 894 */ 895 public CmsJspLinkWrapper getToLink() { 896 897 return m_linkSupplier.get(); 898 } 899 900 /** 901 * Returns this resource wrapper.<p> 902 * 903 * This is included because in case {@link org.opencms.jsp.util.CmsJspStandardContextBean#getWrap()} is used, the result may be 904 * either a {@link org.opencms.jsp.util.CmsJspObjectValueWrapper} or a {@link CmsJspResourceWrapper}. 905 * Using {@link #getToResource()} on the result will always return a resource wrapper this way.<p> 906 * 907 * @return this resource wrapper 908 * 909 * @see org.opencms.jsp.util.CmsJspStandardContextBean#getWrap() 910 * @see org.opencms.jsp.util.CmsJspObjectValueWrapper#getToResource() 911 */ 912 public CmsJspResourceWrapper getToResource() { 913 914 return this; 915 } 916 917 /** 918 * Returns an XML content access bean created for this resource.<p> 919 * 920 * In case this resource is not an XML content, <code>null</code> is returned.<p> 921 * 922 * @return an XML content access bean created for this resource 923 * 924 * @see #getIsXml() 925 */ 926 public CmsJspContentAccessBean getToXml() { 927 928 if ((m_xml == null) && getIsXml()) { 929 m_xml = new CmsJspContentAccessBean(m_cms, this); 930 } 931 return m_xml; 932 } 933 934 /** 935 * Returns the resource type name.<p> 936 * 937 * @return the resource type name 938 */ 939 public String getTypeName() { 940 941 if (m_typeName == null) { 942 try { 943 m_typeName = OpenCms.getResourceManager().getResourceType(getTypeId()).getTypeName(); 944 } catch (CmsLoaderException e) { 945 // this should never happen, and anyway it is logged in the resource manage already 946 } 947 } 948 return m_typeName; 949 } 950 951 /** 952 * Returns an XML content access bean created for this resource.<p> 953 * 954 * In case this resource is not an XML content, <code>null</code> is returned.<p> 955 * 956 * @return an XML content access bean created for this resource 957 * 958 * @see #getToXml() 959 * @see #getIsXml() 960 */ 961 public CmsJspContentAccessBean getXml() { 962 963 return getToXml(); 964 } 965 966 /** 967 * @see CmsResource#hashCode() 968 * @see java.lang.Object#hashCode() 969 */ 970 @Override 971 public int hashCode() { 972 973 if (getStructureId() != null) { 974 return getStructureId().hashCode(); 975 } 976 977 return CmsUUID.getNullUUID().hashCode(); 978 } 979 980 /** 981 * Returns <code>true</code> in case this resource is child resource of the provided resource which is assumed to be a folder.<p> 982 * 983 * @param resource the resource to check 984 * 985 * @return <code>true</code> in case this resource is child resource of the provided resource which is assumed to be a folder 986 */ 987 public boolean isChildResourceOf(CmsResource resource) { 988 989 return (resource != null) 990 && resource.isFolder() 991 && !(getStructureId().equals(resource.getStructureId())) 992 && ((getRootPath().indexOf(resource.getRootPath()) == 0)); 993 } 994 995 /** 996 * Returns <code>true</code> in case this resource is child resource of the provided resource path which is assumed to be a folder in the current site.<p> 997 * 998 * No check is performed to see if the provided site path resource actually exists.<p> 999 * 1000 * @param sitePath the resource to check 1001 * 1002 * @return <code>true</code> in case this resource is child resource of the provided resource path which is assumed to be a folder in the current site 1003 */ 1004 public boolean isChildResourceOf(String sitePath) { 1005 1006 return (sitePath != null) 1007 && ((getSitePath().indexOf(sitePath) == 0)) 1008 && (sitePath.length() < getSitePath().length()); 1009 } 1010 1011 public boolean isNavigationDefaultFile() { 1012 1013 return CmsVfsUtil.isDefaultFile(m_cms, this); 1014 } 1015 1016 /** 1017 * Returns <code>true</code> in case this resource is a parent folder of the provided resource.<p> 1018 * 1019 * @param resource the resource to check 1020 * 1021 * @return <code>true</code> in case this resource is a parent folder of the provided resource 1022 */ 1023 public boolean isParentFolderOf(CmsResource resource) { 1024 1025 return (resource != null) 1026 && isFolder() 1027 && !(getStructureId().equals(resource.getStructureId())) 1028 && ((resource.getRootPath().indexOf(getRootPath()) == 0)); 1029 } 1030 1031 /** 1032 * Returns <code>true</code> in case this resource is a parent folder of the provided resource path in the current site.<p> 1033 * 1034 * No check is performed to see if the provided site path resource actually exists.<p> 1035 * 1036 * @param sitePath the path to check 1037 * 1038 * @return <code>true</code> in case this resource is a parent folder of the provided resource path in the current site 1039 */ 1040 public boolean isParentFolderOf(String sitePath) { 1041 1042 return (sitePath != null) 1043 && isFolder() 1044 && ((sitePath.indexOf(getSitePath()) == 0)) 1045 && (sitePath.length() > getSitePath().length()); 1046 } 1047 1048 /** 1049 * Helper method for getting the related resources for this resource, with a given resource filter. 1050 * 1051 * @param out - true for outgoing relations, false for incoming relations 1052 * @return the list of related resources 1053 */ 1054 private List<CmsJspResourceWrapper> getRelatedResources(boolean out) { 1055 1056 CmsObject cms = getCmsObject(); 1057 List<CmsJspResourceWrapper> result = new ArrayList<>(); 1058 try { 1059 CmsRelationFilter filter = out 1060 ? CmsRelationFilter.relationsFromStructureId(getStructureId()) 1061 : CmsRelationFilter.relationsToStructureId(getStructureId()); 1062 List<CmsRelation> relations = cms.readRelations(filter); 1063 for (CmsRelation rel : relations) { 1064 try { 1065 CmsResource other = out 1066 ? rel.getTarget(cms, CmsResourceFilter.DEFAULT) 1067 : rel.getSource(cms, CmsResourceFilter.DEFAULT); 1068 result.add(wrap(cms, other)); 1069 } catch (CmsException e) { 1070 LOG.warn(e.getLocalizedMessage(), e); 1071 } 1072 } 1073 } catch (Exception e) { 1074 LOG.error(e.getLocalizedMessage(), e); 1075 } 1076 return result; 1077 } 1078 1079 /** 1080 * Reads a resource, suppressing possible exceptions.<p> 1081 * 1082 * @param sitePath the site path of the resource to read. 1083 * 1084 * @return the resource of <code>null</code> on case an exception occurred while reading 1085 */ 1086 private CmsJspResourceWrapper readResource(String sitePath) { 1087 1088 CmsJspResourceWrapper result = null; 1089 try { 1090 result = new CmsJspResourceWrapper(m_cms, m_cms.readResource(sitePath)); 1091 } catch (CmsException e) { 1092 if (LOG.isDebugEnabled()) { 1093 LOG.debug(e.getMessage(), e); 1094 } 1095 } 1096 return result; 1097 } 1098}