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